1//===-- RenderScriptRuntime.cpp ---------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "RenderScriptRuntime.h"
10#include "RenderScriptScriptGroup.h"
11
12#include "lldb/Breakpoint/StoppointCallbackContext.h"
13#include "lldb/Core/Debugger.h"
14#include "lldb/Core/DumpDataExtractor.h"
15#include "lldb/Core/PluginManager.h"
16#include "lldb/Core/ValueObjectVariable.h"
17#include "lldb/DataFormatters/DumpValueObjectOptions.h"
18#include "lldb/Expression/UserExpression.h"
19#include "lldb/Host/OptionParser.h"
20#include "lldb/Host/StringConvert.h"
21#include "lldb/Interpreter/CommandInterpreter.h"
22#include "lldb/Interpreter/CommandObjectMultiword.h"
23#include "lldb/Interpreter/CommandReturnObject.h"
24#include "lldb/Interpreter/Options.h"
25#include "lldb/Symbol/Function.h"
26#include "lldb/Symbol/Symbol.h"
27#include "lldb/Symbol/Type.h"
28#include "lldb/Symbol/VariableList.h"
29#include "lldb/Target/Process.h"
30#include "lldb/Target/RegisterContext.h"
31#include "lldb/Target/SectionLoadList.h"
32#include "lldb/Target/Target.h"
33#include "lldb/Target/Thread.h"
34#include "lldb/Utility/Args.h"
35#include "lldb/Utility/ConstString.h"
36#include "lldb/Utility/Log.h"
37#include "lldb/Utility/RegisterValue.h"
38#include "lldb/Utility/RegularExpression.h"
39#include "lldb/Utility/Status.h"
40
41#include "llvm/ADT/StringSwitch.h"
42
43#include <memory>
44
45using namespace lldb;
46using namespace lldb_private;
47using namespace lldb_renderscript;
48
49#define FMT_COORD "(%" PRIu32 ", %" PRIu32 ", %" PRIu32 ")"
50
51char RenderScriptRuntime::ID = 0;
52
53namespace {
54
55// The empirical_type adds a basic level of validation to arbitrary data
56// allowing us to track if data has been discovered and stored or not. An
57// empirical_type will be marked as valid only if it has been explicitly
58// assigned to.
59template <typename type_t> class empirical_type {
60public:
61  // Ctor. Contents is invalid when constructed.
62  empirical_type() : valid(false) {}
63
64  // Return true and copy contents to out if valid, else return false.
65  bool get(type_t &out) const {
66    if (valid)
67      out = data;
68    return valid;
69  }
70
71  // Return a pointer to the contents or nullptr if it was not valid.
72  const type_t *get() const { return valid ? &data : nullptr; }
73
74  // Assign data explicitly.
75  void set(const type_t in) {
76    data = in;
77    valid = true;
78  }
79
80  // Mark contents as invalid.
81  void invalidate() { valid = false; }
82
83  // Returns true if this type contains valid data.
84  bool isValid() const { return valid; }
85
86  // Assignment operator.
87  empirical_type<type_t> &operator=(const type_t in) {
88    set(in);
89    return *this;
90  }
91
92  // Dereference operator returns contents.
93  // Warning: Will assert if not valid so use only when you know data is valid.
94  const type_t &operator*() const {
95    assert(valid);
96    return data;
97  }
98
99protected:
100  bool valid;
101  type_t data;
102};
103
104// ArgItem is used by the GetArgs() function when reading function arguments
105// from the target.
106struct ArgItem {
107  enum { ePointer, eInt32, eInt64, eLong, eBool } type;
108
109  uint64_t value;
110
111  explicit operator uint64_t() const { return value; }
112};
113
114// Context structure to be passed into GetArgsXXX(), argument reading functions
115// below.
116struct GetArgsCtx {
117  RegisterContext *reg_ctx;
118  Process *process;
119};
120
121bool GetArgsX86(const GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) {
122  Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
123
124  Status err;
125
126  // get the current stack pointer
127  uint64_t sp = ctx.reg_ctx->GetSP();
128
129  for (size_t i = 0; i < num_args; ++i) {
130    ArgItem &arg = arg_list[i];
131    // advance up the stack by one argument
132    sp += sizeof(uint32_t);
133    // get the argument type size
134    size_t arg_size = sizeof(uint32_t);
135    // read the argument from memory
136    arg.value = 0;
137    Status err;
138    size_t read =
139        ctx.process->ReadMemory(sp, &arg.value, sizeof(uint32_t), err);
140    if (read != arg_size || !err.Success()) {
141      LLDB_LOGF(log, "%s - error reading argument: %" PRIu64 " '%s'",
142                __FUNCTION__, uint64_t(i), err.AsCString());
143      return false;
144    }
145  }
146  return true;
147}
148
149bool GetArgsX86_64(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) {
150  Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
151
152  // number of arguments passed in registers
153  static const uint32_t args_in_reg = 6;
154  // register passing order
155  static const std::array<const char *, args_in_reg> reg_names{
156      {"rdi", "rsi", "rdx", "rcx", "r8", "r9"}};
157  // argument type to size mapping
158  static const std::array<size_t, 5> arg_size{{
159      8, // ePointer,
160      4, // eInt32,
161      8, // eInt64,
162      8, // eLong,
163      4, // eBool,
164  }};
165
166  Status err;
167
168  // get the current stack pointer
169  uint64_t sp = ctx.reg_ctx->GetSP();
170  // step over the return address
171  sp += sizeof(uint64_t);
172
173  // check the stack alignment was correct (16 byte aligned)
174  if ((sp & 0xf) != 0x0) {
175    LLDB_LOGF(log, "%s - stack misaligned", __FUNCTION__);
176    return false;
177  }
178
179  // find the start of arguments on the stack
180  uint64_t sp_offset = 0;
181  for (uint32_t i = args_in_reg; i < num_args; ++i) {
182    sp_offset += arg_size[arg_list[i].type];
183  }
184  // round up to multiple of 16
185  sp_offset = (sp_offset + 0xf) & 0xf;
186  sp += sp_offset;
187
188  for (size_t i = 0; i < num_args; ++i) {
189    bool success = false;
190    ArgItem &arg = arg_list[i];
191    // arguments passed in registers
192    if (i < args_in_reg) {
193      const RegisterInfo *reg =
194          ctx.reg_ctx->GetRegisterInfoByName(reg_names[i]);
195      RegisterValue reg_val;
196      if (ctx.reg_ctx->ReadRegister(reg, reg_val))
197        arg.value = reg_val.GetAsUInt64(0, &success);
198    }
199    // arguments passed on the stack
200    else {
201      // get the argument type size
202      const size_t size = arg_size[arg_list[i].type];
203      // read the argument from memory
204      arg.value = 0;
205      // note: due to little endian layout reading 4 or 8 bytes will give the
206      // correct value.
207      size_t read = ctx.process->ReadMemory(sp, &arg.value, size, err);
208      success = (err.Success() && read == size);
209      // advance past this argument
210      sp -= size;
211    }
212    // fail if we couldn't read this argument
213    if (!success) {
214      LLDB_LOGF(log, "%s - error reading argument: %" PRIu64 ", reason: %s",
215                __FUNCTION__, uint64_t(i), err.AsCString("n/a"));
216      return false;
217    }
218  }
219  return true;
220}
221
222bool GetArgsArm(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) {
223  // number of arguments passed in registers
224  static const uint32_t args_in_reg = 4;
225
226  Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
227
228  Status err;
229
230  // get the current stack pointer
231  uint64_t sp = ctx.reg_ctx->GetSP();
232
233  for (size_t i = 0; i < num_args; ++i) {
234    bool success = false;
235    ArgItem &arg = arg_list[i];
236    // arguments passed in registers
237    if (i < args_in_reg) {
238      const RegisterInfo *reg = ctx.reg_ctx->GetRegisterInfoAtIndex(i);
239      RegisterValue reg_val;
240      if (ctx.reg_ctx->ReadRegister(reg, reg_val))
241        arg.value = reg_val.GetAsUInt32(0, &success);
242    }
243    // arguments passed on the stack
244    else {
245      // get the argument type size
246      const size_t arg_size = sizeof(uint32_t);
247      // clear all 64bits
248      arg.value = 0;
249      // read this argument from memory
250      size_t bytes_read =
251          ctx.process->ReadMemory(sp, &arg.value, arg_size, err);
252      success = (err.Success() && bytes_read == arg_size);
253      // advance the stack pointer
254      sp += sizeof(uint32_t);
255    }
256    // fail if we couldn't read this argument
257    if (!success) {
258      LLDB_LOGF(log, "%s - error reading argument: %" PRIu64 ", reason: %s",
259                __FUNCTION__, uint64_t(i), err.AsCString("n/a"));
260      return false;
261    }
262  }
263  return true;
264}
265
266bool GetArgsAarch64(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) {
267  // number of arguments passed in registers
268  static const uint32_t args_in_reg = 8;
269
270  Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
271
272  for (size_t i = 0; i < num_args; ++i) {
273    bool success = false;
274    ArgItem &arg = arg_list[i];
275    // arguments passed in registers
276    if (i < args_in_reg) {
277      const RegisterInfo *reg = ctx.reg_ctx->GetRegisterInfoAtIndex(i);
278      RegisterValue reg_val;
279      if (ctx.reg_ctx->ReadRegister(reg, reg_val))
280        arg.value = reg_val.GetAsUInt64(0, &success);
281    }
282    // arguments passed on the stack
283    else {
284      LLDB_LOGF(log, "%s - reading arguments spilled to stack not implemented",
285                __FUNCTION__);
286    }
287    // fail if we couldn't read this argument
288    if (!success) {
289      LLDB_LOGF(log, "%s - error reading argument: %" PRIu64, __FUNCTION__,
290                uint64_t(i));
291      return false;
292    }
293  }
294  return true;
295}
296
297bool GetArgsMipsel(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) {
298  // number of arguments passed in registers
299  static const uint32_t args_in_reg = 4;
300  // register file offset to first argument
301  static const uint32_t reg_offset = 4;
302
303  Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
304
305  Status err;
306
307  // find offset to arguments on the stack (+16 to skip over a0-a3 shadow
308  // space)
309  uint64_t sp = ctx.reg_ctx->GetSP() + 16;
310
311  for (size_t i = 0; i < num_args; ++i) {
312    bool success = false;
313    ArgItem &arg = arg_list[i];
314    // arguments passed in registers
315    if (i < args_in_reg) {
316      const RegisterInfo *reg =
317          ctx.reg_ctx->GetRegisterInfoAtIndex(i + reg_offset);
318      RegisterValue reg_val;
319      if (ctx.reg_ctx->ReadRegister(reg, reg_val))
320        arg.value = reg_val.GetAsUInt64(0, &success);
321    }
322    // arguments passed on the stack
323    else {
324      const size_t arg_size = sizeof(uint32_t);
325      arg.value = 0;
326      size_t bytes_read =
327          ctx.process->ReadMemory(sp, &arg.value, arg_size, err);
328      success = (err.Success() && bytes_read == arg_size);
329      // advance the stack pointer
330      sp += arg_size;
331    }
332    // fail if we couldn't read this argument
333    if (!success) {
334      LLDB_LOGF(log, "%s - error reading argument: %" PRIu64 ", reason: %s",
335                __FUNCTION__, uint64_t(i), err.AsCString("n/a"));
336      return false;
337    }
338  }
339  return true;
340}
341
342bool GetArgsMips64el(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) {
343  // number of arguments passed in registers
344  static const uint32_t args_in_reg = 8;
345  // register file offset to first argument
346  static const uint32_t reg_offset = 4;
347
348  Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
349
350  Status err;
351
352  // get the current stack pointer
353  uint64_t sp = ctx.reg_ctx->GetSP();
354
355  for (size_t i = 0; i < num_args; ++i) {
356    bool success = false;
357    ArgItem &arg = arg_list[i];
358    // arguments passed in registers
359    if (i < args_in_reg) {
360      const RegisterInfo *reg =
361          ctx.reg_ctx->GetRegisterInfoAtIndex(i + reg_offset);
362      RegisterValue reg_val;
363      if (ctx.reg_ctx->ReadRegister(reg, reg_val))
364        arg.value = reg_val.GetAsUInt64(0, &success);
365    }
366    // arguments passed on the stack
367    else {
368      // get the argument type size
369      const size_t arg_size = sizeof(uint64_t);
370      // clear all 64bits
371      arg.value = 0;
372      // read this argument from memory
373      size_t bytes_read =
374          ctx.process->ReadMemory(sp, &arg.value, arg_size, err);
375      success = (err.Success() && bytes_read == arg_size);
376      // advance the stack pointer
377      sp += arg_size;
378    }
379    // fail if we couldn't read this argument
380    if (!success) {
381      LLDB_LOGF(log, "%s - error reading argument: %" PRIu64 ", reason: %s",
382                __FUNCTION__, uint64_t(i), err.AsCString("n/a"));
383      return false;
384    }
385  }
386  return true;
387}
388
389bool GetArgs(ExecutionContext &exe_ctx, ArgItem *arg_list, size_t num_args) {
390  Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
391
392  // verify that we have a target
393  if (!exe_ctx.GetTargetPtr()) {
394    LLDB_LOGF(log, "%s - invalid target", __FUNCTION__);
395    return false;
396  }
397
398  GetArgsCtx ctx = {exe_ctx.GetRegisterContext(), exe_ctx.GetProcessPtr()};
399  assert(ctx.reg_ctx && ctx.process);
400
401  // dispatch based on architecture
402  switch (exe_ctx.GetTargetPtr()->GetArchitecture().GetMachine()) {
403  case llvm::Triple::ArchType::x86:
404    return GetArgsX86(ctx, arg_list, num_args);
405
406  case llvm::Triple::ArchType::x86_64:
407    return GetArgsX86_64(ctx, arg_list, num_args);
408
409  case llvm::Triple::ArchType::arm:
410    return GetArgsArm(ctx, arg_list, num_args);
411
412  case llvm::Triple::ArchType::aarch64:
413    return GetArgsAarch64(ctx, arg_list, num_args);
414
415  case llvm::Triple::ArchType::mipsel:
416    return GetArgsMipsel(ctx, arg_list, num_args);
417
418  case llvm::Triple::ArchType::mips64el:
419    return GetArgsMips64el(ctx, arg_list, num_args);
420
421  default:
422    // unsupported architecture
423    if (log) {
424      LLDB_LOGF(log, "%s - architecture not supported: '%s'", __FUNCTION__,
425                exe_ctx.GetTargetRef().GetArchitecture().GetArchitectureName());
426    }
427    return false;
428  }
429}
430
431bool IsRenderScriptScriptModule(ModuleSP module) {
432  if (!module)
433    return false;
434  return module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"),
435                                                eSymbolTypeData) != nullptr;
436}
437
438bool ParseCoordinate(llvm::StringRef coord_s, RSCoordinate &coord) {
439  // takes an argument of the form 'num[,num][,num]'. Where 'coord_s' is a
440  // comma separated 1,2 or 3-dimensional coordinate with the whitespace
441  // trimmed. Missing coordinates are defaulted to zero. If parsing of any
442  // elements fails the contents of &coord are undefined and `false` is
443  // returned, `true` otherwise
444
445  llvm::SmallVector<llvm::StringRef, 4> matches;
446
447  if (!RegularExpression("^([0-9]+),([0-9]+),([0-9]+)$")
448           .Execute(coord_s, &matches) &&
449      !RegularExpression("^([0-9]+),([0-9]+)$").Execute(coord_s, &matches) &&
450      !RegularExpression("^([0-9]+)$").Execute(coord_s, &matches))
451    return false;
452
453  auto get_index = [&](size_t idx, uint32_t &i) -> bool {
454    std::string group;
455    errno = 0;
456    if (idx + 1 < matches.size()) {
457      return !llvm::StringRef(matches[idx + 1]).getAsInteger<uint32_t>(10, i);
458    }
459    return true;
460  };
461
462  return get_index(0, coord.x) && get_index(1, coord.y) &&
463         get_index(2, coord.z);
464}
465
466bool SkipPrologue(lldb::ModuleSP &module, Address &addr) {
467  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
468  SymbolContext sc;
469  uint32_t resolved_flags =
470      module->ResolveSymbolContextForAddress(addr, eSymbolContextFunction, sc);
471  if (resolved_flags & eSymbolContextFunction) {
472    if (sc.function) {
473      const uint32_t offset = sc.function->GetPrologueByteSize();
474      ConstString name = sc.GetFunctionName();
475      if (offset)
476        addr.Slide(offset);
477      LLDB_LOGF(log, "%s: Prologue offset for %s is %" PRIu32, __FUNCTION__,
478                name.AsCString(), offset);
479    }
480    return true;
481  } else
482    return false;
483}
484} // anonymous namespace
485
486// The ScriptDetails class collects data associated with a single script
487// instance.
488struct RenderScriptRuntime::ScriptDetails {
489  ~ScriptDetails() = default;
490
491  enum ScriptType { eScript, eScriptC };
492
493  // The derived type of the script.
494  empirical_type<ScriptType> type;
495  // The name of the original source file.
496  empirical_type<std::string> res_name;
497  // Path to script .so file on the device.
498  empirical_type<std::string> shared_lib;
499  // Directory where kernel objects are cached on device.
500  empirical_type<std::string> cache_dir;
501  // Pointer to the context which owns this script.
502  empirical_type<lldb::addr_t> context;
503  // Pointer to the script object itself.
504  empirical_type<lldb::addr_t> script;
505};
506
507// This Element class represents the Element object in RS, defining the type
508// associated with an Allocation.
509struct RenderScriptRuntime::Element {
510  // Taken from rsDefines.h
511  enum DataKind {
512    RS_KIND_USER,
513    RS_KIND_PIXEL_L = 7,
514    RS_KIND_PIXEL_A,
515    RS_KIND_PIXEL_LA,
516    RS_KIND_PIXEL_RGB,
517    RS_KIND_PIXEL_RGBA,
518    RS_KIND_PIXEL_DEPTH,
519    RS_KIND_PIXEL_YUV,
520    RS_KIND_INVALID = 100
521  };
522
523  // Taken from rsDefines.h
524  enum DataType {
525    RS_TYPE_NONE = 0,
526    RS_TYPE_FLOAT_16,
527    RS_TYPE_FLOAT_32,
528    RS_TYPE_FLOAT_64,
529    RS_TYPE_SIGNED_8,
530    RS_TYPE_SIGNED_16,
531    RS_TYPE_SIGNED_32,
532    RS_TYPE_SIGNED_64,
533    RS_TYPE_UNSIGNED_8,
534    RS_TYPE_UNSIGNED_16,
535    RS_TYPE_UNSIGNED_32,
536    RS_TYPE_UNSIGNED_64,
537    RS_TYPE_BOOLEAN,
538
539    RS_TYPE_UNSIGNED_5_6_5,
540    RS_TYPE_UNSIGNED_5_5_5_1,
541    RS_TYPE_UNSIGNED_4_4_4_4,
542
543    RS_TYPE_MATRIX_4X4,
544    RS_TYPE_MATRIX_3X3,
545    RS_TYPE_MATRIX_2X2,
546
547    RS_TYPE_ELEMENT = 1000,
548    RS_TYPE_TYPE,
549    RS_TYPE_ALLOCATION,
550    RS_TYPE_SAMPLER,
551    RS_TYPE_SCRIPT,
552    RS_TYPE_MESH,
553    RS_TYPE_PROGRAM_FRAGMENT,
554    RS_TYPE_PROGRAM_VERTEX,
555    RS_TYPE_PROGRAM_RASTER,
556    RS_TYPE_PROGRAM_STORE,
557    RS_TYPE_FONT,
558
559    RS_TYPE_INVALID = 10000
560  };
561
562  std::vector<Element> children; // Child Element fields for structs
563  empirical_type<lldb::addr_t>
564      element_ptr; // Pointer to the RS Element of the Type
565  empirical_type<DataType>
566      type; // Type of each data pointer stored by the allocation
567  empirical_type<DataKind>
568      type_kind; // Defines pixel type if Allocation is created from an image
569  empirical_type<uint32_t>
570      type_vec_size; // Vector size of each data point, e.g '4' for uchar4
571  empirical_type<uint32_t> field_count; // Number of Subelements
572  empirical_type<uint32_t> datum_size;  // Size of a single Element with padding
573  empirical_type<uint32_t> padding;     // Number of padding bytes
574  empirical_type<uint32_t>
575      array_size;        // Number of items in array, only needed for structs
576  ConstString type_name; // Name of type, only needed for structs
577
578  static ConstString
579  GetFallbackStructName(); // Print this as the type name of a struct Element
580                           // If we can't resolve the actual struct name
581
582  bool ShouldRefresh() const {
583    const bool valid_ptr = element_ptr.isValid() && *element_ptr.get() != 0x0;
584    const bool valid_type =
585        type.isValid() && type_vec_size.isValid() && type_kind.isValid();
586    return !valid_ptr || !valid_type || !datum_size.isValid();
587  }
588};
589
590// This AllocationDetails class collects data associated with a single
591// allocation instance.
592struct RenderScriptRuntime::AllocationDetails {
593  struct Dimension {
594    uint32_t dim_1;
595    uint32_t dim_2;
596    uint32_t dim_3;
597    uint32_t cube_map;
598
599    Dimension() {
600      dim_1 = 0;
601      dim_2 = 0;
602      dim_3 = 0;
603      cube_map = 0;
604    }
605  };
606
607  // The FileHeader struct specifies the header we use for writing allocations
608  // to a binary file. Our format begins with the ASCII characters "RSAD",
609  // identifying the file as an allocation dump. Member variables dims and
610  // hdr_size are then written consecutively, immediately followed by an
611  // instance of the ElementHeader struct. Because Elements can contain
612  // subelements, there may be more than one instance of the ElementHeader
613  // struct. With this first instance being the root element, and the other
614  // instances being the root's descendants. To identify which instances are an
615  // ElementHeader's children, each struct is immediately followed by a
616  // sequence of consecutive offsets to the start of its child structs. These
617  // offsets are
618  // 4 bytes in size, and the 0 offset signifies no more children.
619  struct FileHeader {
620    uint8_t ident[4];  // ASCII 'RSAD' identifying the file
621    uint32_t dims[3];  // Dimensions
622    uint16_t hdr_size; // Header size in bytes, including all element headers
623  };
624
625  struct ElementHeader {
626    uint16_t type;         // DataType enum
627    uint32_t kind;         // DataKind enum
628    uint32_t element_size; // Size of a single element, including padding
629    uint16_t vector_size;  // Vector width
630    uint32_t array_size;   // Number of elements in array
631  };
632
633  // Monotonically increasing from 1
634  static uint32_t ID;
635
636  // Maps Allocation DataType enum and vector size to printable strings using
637  // mapping from RenderScript numerical types summary documentation
638  static const char *RsDataTypeToString[][4];
639
640  // Maps Allocation DataKind enum to printable strings
641  static const char *RsDataKindToString[];
642
643  // Maps allocation types to format sizes for printing.
644  static const uint32_t RSTypeToFormat[][3];
645
646  // Give each allocation an ID as a way
647  // for commands to reference it.
648  const uint32_t id;
649
650  // Allocation Element type
651  RenderScriptRuntime::Element element;
652  // Dimensions of the Allocation
653  empirical_type<Dimension> dimension;
654  // Pointer to address of the RS Allocation
655  empirical_type<lldb::addr_t> address;
656  // Pointer to the data held by the Allocation
657  empirical_type<lldb::addr_t> data_ptr;
658  // Pointer to the RS Type of the Allocation
659  empirical_type<lldb::addr_t> type_ptr;
660  // Pointer to the RS Context of the Allocation
661  empirical_type<lldb::addr_t> context;
662  // Size of the allocation
663  empirical_type<uint32_t> size;
664  // Stride between rows of the allocation
665  empirical_type<uint32_t> stride;
666
667  // Give each allocation an id, so we can reference it in user commands.
668  AllocationDetails() : id(ID++) {}
669
670  bool ShouldRefresh() const {
671    bool valid_ptrs = data_ptr.isValid() && *data_ptr.get() != 0x0;
672    valid_ptrs = valid_ptrs && type_ptr.isValid() && *type_ptr.get() != 0x0;
673    return !valid_ptrs || !dimension.isValid() || !size.isValid() ||
674           element.ShouldRefresh();
675  }
676};
677
678ConstString RenderScriptRuntime::Element::GetFallbackStructName() {
679  static const ConstString FallbackStructName("struct");
680  return FallbackStructName;
681}
682
683uint32_t RenderScriptRuntime::AllocationDetails::ID = 1;
684
685const char *RenderScriptRuntime::AllocationDetails::RsDataKindToString[] = {
686    "User",       "Undefined",   "Undefined", "Undefined",
687    "Undefined",  "Undefined",   "Undefined", // Enum jumps from 0 to 7
688    "L Pixel",    "A Pixel",     "LA Pixel",  "RGB Pixel",
689    "RGBA Pixel", "Pixel Depth", "YUV Pixel"};
690
691const char *RenderScriptRuntime::AllocationDetails::RsDataTypeToString[][4] = {
692    {"None", "None", "None", "None"},
693    {"half", "half2", "half3", "half4"},
694    {"float", "float2", "float3", "float4"},
695    {"double", "double2", "double3", "double4"},
696    {"char", "char2", "char3", "char4"},
697    {"short", "short2", "short3", "short4"},
698    {"int", "int2", "int3", "int4"},
699    {"long", "long2", "long3", "long4"},
700    {"uchar", "uchar2", "uchar3", "uchar4"},
701    {"ushort", "ushort2", "ushort3", "ushort4"},
702    {"uint", "uint2", "uint3", "uint4"},
703    {"ulong", "ulong2", "ulong3", "ulong4"},
704    {"bool", "bool2", "bool3", "bool4"},
705    {"packed_565", "packed_565", "packed_565", "packed_565"},
706    {"packed_5551", "packed_5551", "packed_5551", "packed_5551"},
707    {"packed_4444", "packed_4444", "packed_4444", "packed_4444"},
708    {"rs_matrix4x4", "rs_matrix4x4", "rs_matrix4x4", "rs_matrix4x4"},
709    {"rs_matrix3x3", "rs_matrix3x3", "rs_matrix3x3", "rs_matrix3x3"},
710    {"rs_matrix2x2", "rs_matrix2x2", "rs_matrix2x2", "rs_matrix2x2"},
711
712    // Handlers
713    {"RS Element", "RS Element", "RS Element", "RS Element"},
714    {"RS Type", "RS Type", "RS Type", "RS Type"},
715    {"RS Allocation", "RS Allocation", "RS Allocation", "RS Allocation"},
716    {"RS Sampler", "RS Sampler", "RS Sampler", "RS Sampler"},
717    {"RS Script", "RS Script", "RS Script", "RS Script"},
718
719    // Deprecated
720    {"RS Mesh", "RS Mesh", "RS Mesh", "RS Mesh"},
721    {"RS Program Fragment", "RS Program Fragment", "RS Program Fragment",
722     "RS Program Fragment"},
723    {"RS Program Vertex", "RS Program Vertex", "RS Program Vertex",
724     "RS Program Vertex"},
725    {"RS Program Raster", "RS Program Raster", "RS Program Raster",
726     "RS Program Raster"},
727    {"RS Program Store", "RS Program Store", "RS Program Store",
728     "RS Program Store"},
729    {"RS Font", "RS Font", "RS Font", "RS Font"}};
730
731// Used as an index into the RSTypeToFormat array elements
732enum TypeToFormatIndex { eFormatSingle = 0, eFormatVector, eElementSize };
733
734// { format enum of single element, format enum of element vector, size of
735// element}
736const uint32_t RenderScriptRuntime::AllocationDetails::RSTypeToFormat[][3] = {
737    // RS_TYPE_NONE
738    {eFormatHex, eFormatHex, 1},
739    // RS_TYPE_FLOAT_16
740    {eFormatFloat, eFormatVectorOfFloat16, 2},
741    // RS_TYPE_FLOAT_32
742    {eFormatFloat, eFormatVectorOfFloat32, sizeof(float)},
743    // RS_TYPE_FLOAT_64
744    {eFormatFloat, eFormatVectorOfFloat64, sizeof(double)},
745    // RS_TYPE_SIGNED_8
746    {eFormatDecimal, eFormatVectorOfSInt8, sizeof(int8_t)},
747    // RS_TYPE_SIGNED_16
748    {eFormatDecimal, eFormatVectorOfSInt16, sizeof(int16_t)},
749    // RS_TYPE_SIGNED_32
750    {eFormatDecimal, eFormatVectorOfSInt32, sizeof(int32_t)},
751    // RS_TYPE_SIGNED_64
752    {eFormatDecimal, eFormatVectorOfSInt64, sizeof(int64_t)},
753    // RS_TYPE_UNSIGNED_8
754    {eFormatDecimal, eFormatVectorOfUInt8, sizeof(uint8_t)},
755    // RS_TYPE_UNSIGNED_16
756    {eFormatDecimal, eFormatVectorOfUInt16, sizeof(uint16_t)},
757    // RS_TYPE_UNSIGNED_32
758    {eFormatDecimal, eFormatVectorOfUInt32, sizeof(uint32_t)},
759    // RS_TYPE_UNSIGNED_64
760    {eFormatDecimal, eFormatVectorOfUInt64, sizeof(uint64_t)},
761    // RS_TYPE_BOOL
762    {eFormatBoolean, eFormatBoolean, 1},
763    // RS_TYPE_UNSIGNED_5_6_5
764    {eFormatHex, eFormatHex, sizeof(uint16_t)},
765    // RS_TYPE_UNSIGNED_5_5_5_1
766    {eFormatHex, eFormatHex, sizeof(uint16_t)},
767    // RS_TYPE_UNSIGNED_4_4_4_4
768    {eFormatHex, eFormatHex, sizeof(uint16_t)},
769    // RS_TYPE_MATRIX_4X4
770    {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 16},
771    // RS_TYPE_MATRIX_3X3
772    {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 9},
773    // RS_TYPE_MATRIX_2X2
774    {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 4}};
775
776// Static Functions
777LanguageRuntime *
778RenderScriptRuntime::CreateInstance(Process *process,
779                                    lldb::LanguageType language) {
780
781  if (language == eLanguageTypeExtRenderScript)
782    return new RenderScriptRuntime(process);
783  else
784    return nullptr;
785}
786
787// Callback with a module to search for matching symbols. We first check that
788// the module contains RS kernels. Then look for a symbol which matches our
789// kernel name. The breakpoint address is finally set using the address of this
790// symbol.
791Searcher::CallbackReturn
792RSBreakpointResolver::SearchCallback(SearchFilter &filter,
793                                     SymbolContext &context, Address *) {
794  ModuleSP module = context.module_sp;
795
796  if (!module || !IsRenderScriptScriptModule(module))
797    return Searcher::eCallbackReturnContinue;
798
799  // Attempt to set a breakpoint on the kernel name symbol within the module
800  // library. If it's not found, it's likely debug info is unavailable - try to
801  // set a breakpoint on <name>.expand.
802  const Symbol *kernel_sym =
803      module->FindFirstSymbolWithNameAndType(m_kernel_name, eSymbolTypeCode);
804  if (!kernel_sym) {
805    std::string kernel_name_expanded(m_kernel_name.AsCString());
806    kernel_name_expanded.append(".expand");
807    kernel_sym = module->FindFirstSymbolWithNameAndType(
808        ConstString(kernel_name_expanded.c_str()), eSymbolTypeCode);
809  }
810
811  if (kernel_sym) {
812    Address bp_addr = kernel_sym->GetAddress();
813    if (filter.AddressPasses(bp_addr))
814      m_breakpoint->AddLocation(bp_addr);
815  }
816
817  return Searcher::eCallbackReturnContinue;
818}
819
820Searcher::CallbackReturn
821RSReduceBreakpointResolver::SearchCallback(lldb_private::SearchFilter &filter,
822                                           lldb_private::SymbolContext &context,
823                                           Address *) {
824  // We need to have access to the list of reductions currently parsed, as
825  // reduce names don't actually exist as symbols in a module. They are only
826  // identifiable by parsing the .rs.info packet, or finding the expand symbol.
827  // We therefore need access to the list of parsed rs modules to properly
828  // resolve reduction names.
829  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
830  ModuleSP module = context.module_sp;
831
832  if (!module || !IsRenderScriptScriptModule(module))
833    return Searcher::eCallbackReturnContinue;
834
835  if (!m_rsmodules)
836    return Searcher::eCallbackReturnContinue;
837
838  for (const auto &module_desc : *m_rsmodules) {
839    if (module_desc->m_module != module)
840      continue;
841
842    for (const auto &reduction : module_desc->m_reductions) {
843      if (reduction.m_reduce_name != m_reduce_name)
844        continue;
845
846      std::array<std::pair<ConstString, int>, 5> funcs{
847          {{reduction.m_init_name, eKernelTypeInit},
848           {reduction.m_accum_name, eKernelTypeAccum},
849           {reduction.m_comb_name, eKernelTypeComb},
850           {reduction.m_outc_name, eKernelTypeOutC},
851           {reduction.m_halter_name, eKernelTypeHalter}}};
852
853      for (const auto &kernel : funcs) {
854        // Skip constituent functions that don't match our spec
855        if (!(m_kernel_types & kernel.second))
856          continue;
857
858        const auto kernel_name = kernel.first;
859        const auto symbol = module->FindFirstSymbolWithNameAndType(
860            kernel_name, eSymbolTypeCode);
861        if (!symbol)
862          continue;
863
864        auto address = symbol->GetAddress();
865        if (filter.AddressPasses(address)) {
866          bool new_bp;
867          if (!SkipPrologue(module, address)) {
868            LLDB_LOGF(log, "%s: Error trying to skip prologue", __FUNCTION__);
869          }
870          m_breakpoint->AddLocation(address, &new_bp);
871          LLDB_LOGF(log, "%s: %s reduction breakpoint on %s in %s",
872                    __FUNCTION__, new_bp ? "new" : "existing",
873                    kernel_name.GetCString(),
874                    address.GetModule()->GetFileSpec().GetCString());
875        }
876      }
877    }
878  }
879  return eCallbackReturnContinue;
880}
881
882Searcher::CallbackReturn RSScriptGroupBreakpointResolver::SearchCallback(
883    SearchFilter &filter, SymbolContext &context, Address *addr) {
884
885  if (!m_breakpoint)
886    return eCallbackReturnContinue;
887
888  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
889  ModuleSP &module = context.module_sp;
890
891  if (!module || !IsRenderScriptScriptModule(module))
892    return Searcher::eCallbackReturnContinue;
893
894  std::vector<std::string> names;
895  m_breakpoint->GetNames(names);
896  if (names.empty())
897    return eCallbackReturnContinue;
898
899  for (auto &name : names) {
900    const RSScriptGroupDescriptorSP sg = FindScriptGroup(ConstString(name));
901    if (!sg) {
902      LLDB_LOGF(log, "%s: could not find script group for %s", __FUNCTION__,
903                name.c_str());
904      continue;
905    }
906
907    LLDB_LOGF(log, "%s: Found ScriptGroup for %s", __FUNCTION__, name.c_str());
908
909    for (const RSScriptGroupDescriptor::Kernel &k : sg->m_kernels) {
910      if (log) {
911        LLDB_LOGF(log, "%s: Adding breakpoint for %s", __FUNCTION__,
912                  k.m_name.AsCString());
913        LLDB_LOGF(log, "%s: Kernel address 0x%" PRIx64, __FUNCTION__, k.m_addr);
914      }
915
916      const lldb_private::Symbol *sym =
917          module->FindFirstSymbolWithNameAndType(k.m_name, eSymbolTypeCode);
918      if (!sym) {
919        LLDB_LOGF(log, "%s: Unable to find symbol for %s", __FUNCTION__,
920                  k.m_name.AsCString());
921        continue;
922      }
923
924      if (log) {
925        LLDB_LOGF(log, "%s: Found symbol name is %s", __FUNCTION__,
926                  sym->GetName().AsCString());
927      }
928
929      auto address = sym->GetAddress();
930      if (!SkipPrologue(module, address)) {
931        LLDB_LOGF(log, "%s: Error trying to skip prologue", __FUNCTION__);
932      }
933
934      bool new_bp;
935      m_breakpoint->AddLocation(address, &new_bp);
936
937      LLDB_LOGF(log, "%s: Placed %sbreakpoint on %s", __FUNCTION__,
938                new_bp ? "new " : "", k.m_name.AsCString());
939
940      // exit after placing the first breakpoint if we do not intend to stop on
941      // all kernels making up this script group
942      if (!m_stop_on_all)
943        break;
944    }
945  }
946
947  return eCallbackReturnContinue;
948}
949
950void RenderScriptRuntime::Initialize() {
951  PluginManager::RegisterPlugin(GetPluginNameStatic(),
952                                "RenderScript language support", CreateInstance,
953                                GetCommandObject);
954}
955
956void RenderScriptRuntime::Terminate() {
957  PluginManager::UnregisterPlugin(CreateInstance);
958}
959
960lldb_private::ConstString RenderScriptRuntime::GetPluginNameStatic() {
961  static ConstString plugin_name("renderscript");
962  return plugin_name;
963}
964
965RenderScriptRuntime::ModuleKind
966RenderScriptRuntime::GetModuleKind(const lldb::ModuleSP &module_sp) {
967  if (module_sp) {
968    if (IsRenderScriptScriptModule(module_sp))
969      return eModuleKindKernelObj;
970
971    // Is this the main RS runtime library
972    const ConstString rs_lib("libRS.so");
973    if (module_sp->GetFileSpec().GetFilename() == rs_lib) {
974      return eModuleKindLibRS;
975    }
976
977    const ConstString rs_driverlib("libRSDriver.so");
978    if (module_sp->GetFileSpec().GetFilename() == rs_driverlib) {
979      return eModuleKindDriver;
980    }
981
982    const ConstString rs_cpureflib("libRSCpuRef.so");
983    if (module_sp->GetFileSpec().GetFilename() == rs_cpureflib) {
984      return eModuleKindImpl;
985    }
986  }
987  return eModuleKindIgnored;
988}
989
990bool RenderScriptRuntime::IsRenderScriptModule(
991    const lldb::ModuleSP &module_sp) {
992  return GetModuleKind(module_sp) != eModuleKindIgnored;
993}
994
995void RenderScriptRuntime::ModulesDidLoad(const ModuleList &module_list) {
996  std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex());
997
998  size_t num_modules = module_list.GetSize();
999  for (size_t i = 0; i < num_modules; i++) {
1000    auto mod = module_list.GetModuleAtIndex(i);
1001    if (IsRenderScriptModule(mod)) {
1002      LoadModule(mod);
1003    }
1004  }
1005}
1006
1007// PluginInterface protocol
1008lldb_private::ConstString RenderScriptRuntime::GetPluginName() {
1009  return GetPluginNameStatic();
1010}
1011
1012uint32_t RenderScriptRuntime::GetPluginVersion() { return 1; }
1013
1014bool RenderScriptRuntime::GetDynamicTypeAndAddress(
1015    ValueObject &in_value, lldb::DynamicValueType use_dynamic,
1016    TypeAndOrName &class_type_or_name, Address &address,
1017    Value::ValueType &value_type) {
1018  return false;
1019}
1020
1021TypeAndOrName
1022RenderScriptRuntime::FixUpDynamicType(const TypeAndOrName &type_and_or_name,
1023                                      ValueObject &static_value) {
1024  return type_and_or_name;
1025}
1026
1027bool RenderScriptRuntime::CouldHaveDynamicValue(ValueObject &in_value) {
1028  return false;
1029}
1030
1031lldb::BreakpointResolverSP
1032RenderScriptRuntime::CreateExceptionResolver(Breakpoint *bp, bool catch_bp,
1033                                             bool throw_bp) {
1034  BreakpointResolverSP resolver_sp;
1035  return resolver_sp;
1036}
1037
1038const RenderScriptRuntime::HookDefn RenderScriptRuntime::s_runtimeHookDefns[] =
1039    {
1040        // rsdScript
1041        {"rsdScriptInit", "_Z13rsdScriptInitPKN7android12renderscript7ContextEP"
1042                          "NS0_7ScriptCEPKcS7_PKhjj",
1043         "_Z13rsdScriptInitPKN7android12renderscript7ContextEPNS0_"
1044         "7ScriptCEPKcS7_PKhmj",
1045         0, RenderScriptRuntime::eModuleKindDriver,
1046         &lldb_private::RenderScriptRuntime::CaptureScriptInit},
1047        {"rsdScriptInvokeForEachMulti",
1048         "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0"
1049         "_6ScriptEjPPKNS0_10AllocationEjPS6_PKvjPK12RsScriptCall",
1050         "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0"
1051         "_6ScriptEjPPKNS0_10AllocationEmPS6_PKvmPK12RsScriptCall",
1052         0, RenderScriptRuntime::eModuleKindDriver,
1053         &lldb_private::RenderScriptRuntime::CaptureScriptInvokeForEachMulti},
1054        {"rsdScriptSetGlobalVar", "_Z21rsdScriptSetGlobalVarPKN7android12render"
1055                                  "script7ContextEPKNS0_6ScriptEjPvj",
1056         "_Z21rsdScriptSetGlobalVarPKN7android12renderscript7ContextEPKNS0_"
1057         "6ScriptEjPvm",
1058         0, RenderScriptRuntime::eModuleKindDriver,
1059         &lldb_private::RenderScriptRuntime::CaptureSetGlobalVar},
1060
1061        // rsdAllocation
1062        {"rsdAllocationInit", "_Z17rsdAllocationInitPKN7android12renderscript7C"
1063                              "ontextEPNS0_10AllocationEb",
1064         "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_"
1065         "10AllocationEb",
1066         0, RenderScriptRuntime::eModuleKindDriver,
1067         &lldb_private::RenderScriptRuntime::CaptureAllocationInit},
1068        {"rsdAllocationRead2D",
1069         "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_"
1070         "10AllocationEjjj23RsAllocationCubemapFacejjPvjj",
1071         "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_"
1072         "10AllocationEjjj23RsAllocationCubemapFacejjPvmm",
1073         0, RenderScriptRuntime::eModuleKindDriver, nullptr},
1074        {"rsdAllocationDestroy", "_Z20rsdAllocationDestroyPKN7android12rendersc"
1075                                 "ript7ContextEPNS0_10AllocationE",
1076         "_Z20rsdAllocationDestroyPKN7android12renderscript7ContextEPNS0_"
1077         "10AllocationE",
1078         0, RenderScriptRuntime::eModuleKindDriver,
1079         &lldb_private::RenderScriptRuntime::CaptureAllocationDestroy},
1080
1081        // renderscript script groups
1082        {"rsdDebugHintScriptGroup2", "_ZN7android12renderscript21debugHintScrip"
1083                                     "tGroup2EPKcjPKPFvPK24RsExpandKernelDriver"
1084                                     "InfojjjEj",
1085         "_ZN7android12renderscript21debugHintScriptGroup2EPKcjPKPFvPK24RsExpan"
1086         "dKernelDriverInfojjjEj",
1087         0, RenderScriptRuntime::eModuleKindImpl,
1088         &lldb_private::RenderScriptRuntime::CaptureDebugHintScriptGroup2}};
1089
1090const size_t RenderScriptRuntime::s_runtimeHookCount =
1091    sizeof(s_runtimeHookDefns) / sizeof(s_runtimeHookDefns[0]);
1092
1093bool RenderScriptRuntime::HookCallback(void *baton,
1094                                       StoppointCallbackContext *ctx,
1095                                       lldb::user_id_t break_id,
1096                                       lldb::user_id_t break_loc_id) {
1097  RuntimeHook *hook = (RuntimeHook *)baton;
1098  ExecutionContext exe_ctx(ctx->exe_ctx_ref);
1099
1100  RenderScriptRuntime *lang_rt = llvm::cast<RenderScriptRuntime>(
1101      exe_ctx.GetProcessPtr()->GetLanguageRuntime(
1102          eLanguageTypeExtRenderScript));
1103
1104  lang_rt->HookCallback(hook, exe_ctx);
1105
1106  return false;
1107}
1108
1109void RenderScriptRuntime::HookCallback(RuntimeHook *hook,
1110                                       ExecutionContext &exe_ctx) {
1111  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1112
1113  LLDB_LOGF(log, "%s - '%s'", __FUNCTION__, hook->defn->name);
1114
1115  if (hook->defn->grabber) {
1116    (this->*(hook->defn->grabber))(hook, exe_ctx);
1117  }
1118}
1119
1120void RenderScriptRuntime::CaptureDebugHintScriptGroup2(
1121    RuntimeHook *hook_info, ExecutionContext &context) {
1122  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1123
1124  enum {
1125    eGroupName = 0,
1126    eGroupNameSize,
1127    eKernel,
1128    eKernelCount,
1129  };
1130
1131  std::array<ArgItem, 4> args{{
1132      {ArgItem::ePointer, 0}, // const char         *groupName
1133      {ArgItem::eInt32, 0},   // const uint32_t      groupNameSize
1134      {ArgItem::ePointer, 0}, // const ExpandFuncTy *kernel
1135      {ArgItem::eInt32, 0},   // const uint32_t      kernelCount
1136  }};
1137
1138  if (!GetArgs(context, args.data(), args.size())) {
1139    LLDB_LOGF(log, "%s - Error while reading the function parameters",
1140              __FUNCTION__);
1141    return;
1142  } else if (log) {
1143    LLDB_LOGF(log, "%s - groupName    : 0x%" PRIx64, __FUNCTION__,
1144              addr_t(args[eGroupName]));
1145    LLDB_LOGF(log, "%s - groupNameSize: %" PRIu64, __FUNCTION__,
1146              uint64_t(args[eGroupNameSize]));
1147    LLDB_LOGF(log, "%s - kernel       : 0x%" PRIx64, __FUNCTION__,
1148              addr_t(args[eKernel]));
1149    LLDB_LOGF(log, "%s - kernelCount  : %" PRIu64, __FUNCTION__,
1150              uint64_t(args[eKernelCount]));
1151  }
1152
1153  // parse script group name
1154  ConstString group_name;
1155  {
1156    Status err;
1157    const uint64_t len = uint64_t(args[eGroupNameSize]);
1158    std::unique_ptr<char[]> buffer(new char[uint32_t(len + 1)]);
1159    m_process->ReadMemory(addr_t(args[eGroupName]), buffer.get(), len, err);
1160    buffer.get()[len] = '\0';
1161    if (!err.Success()) {
1162      LLDB_LOGF(log, "Error reading scriptgroup name from target");
1163      return;
1164    } else {
1165      LLDB_LOGF(log, "Extracted scriptgroup name %s", buffer.get());
1166    }
1167    // write back the script group name
1168    group_name.SetCString(buffer.get());
1169  }
1170
1171  // create or access existing script group
1172  RSScriptGroupDescriptorSP group;
1173  {
1174    // search for existing script group
1175    for (auto sg : m_scriptGroups) {
1176      if (sg->m_name == group_name) {
1177        group = sg;
1178        break;
1179      }
1180    }
1181    if (!group) {
1182      group = std::make_shared<RSScriptGroupDescriptor>();
1183      group->m_name = group_name;
1184      m_scriptGroups.push_back(group);
1185    } else {
1186      // already have this script group
1187      LLDB_LOGF(log, "Attempt to add duplicate script group %s",
1188                group_name.AsCString());
1189      return;
1190    }
1191  }
1192  assert(group);
1193
1194  const uint32_t target_ptr_size = m_process->GetAddressByteSize();
1195  std::vector<addr_t> kernels;
1196  // parse kernel addresses in script group
1197  for (uint64_t i = 0; i < uint64_t(args[eKernelCount]); ++i) {
1198    RSScriptGroupDescriptor::Kernel kernel;
1199    // extract script group kernel addresses from the target
1200    const addr_t ptr_addr = addr_t(args[eKernel]) + i * target_ptr_size;
1201    uint64_t kernel_addr = 0;
1202    Status err;
1203    size_t read =
1204        m_process->ReadMemory(ptr_addr, &kernel_addr, target_ptr_size, err);
1205    if (!err.Success() || read != target_ptr_size) {
1206      LLDB_LOGF(log, "Error parsing kernel address %" PRIu64 " in script group",
1207                i);
1208      return;
1209    }
1210    LLDB_LOGF(log, "Extracted scriptgroup kernel address - 0x%" PRIx64,
1211              kernel_addr);
1212    kernel.m_addr = kernel_addr;
1213
1214    // try to resolve the associated kernel name
1215    if (!ResolveKernelName(kernel.m_addr, kernel.m_name)) {
1216      LLDB_LOGF(log, "Parsed scriptgroup kernel %" PRIu64 " - 0x%" PRIx64, i,
1217                kernel_addr);
1218      return;
1219    }
1220
1221    // try to find the non '.expand' function
1222    {
1223      const llvm::StringRef expand(".expand");
1224      const llvm::StringRef name_ref = kernel.m_name.GetStringRef();
1225      if (name_ref.endswith(expand)) {
1226        const ConstString base_kernel(name_ref.drop_back(expand.size()));
1227        // verify this function is a valid kernel
1228        if (IsKnownKernel(base_kernel)) {
1229          kernel.m_name = base_kernel;
1230          LLDB_LOGF(log, "%s - found non expand version '%s'", __FUNCTION__,
1231                    base_kernel.GetCString());
1232        }
1233      }
1234    }
1235    // add to a list of script group kernels we know about
1236    group->m_kernels.push_back(kernel);
1237  }
1238
1239  // Resolve any pending scriptgroup breakpoints
1240  {
1241    Target &target = m_process->GetTarget();
1242    const BreakpointList &list = target.GetBreakpointList();
1243    const size_t num_breakpoints = list.GetSize();
1244    LLDB_LOGF(log, "Resolving %zu breakpoints", num_breakpoints);
1245    for (size_t i = 0; i < num_breakpoints; ++i) {
1246      const BreakpointSP bp = list.GetBreakpointAtIndex(i);
1247      if (bp) {
1248        if (bp->MatchesName(group_name.AsCString())) {
1249          LLDB_LOGF(log, "Found breakpoint with name %s",
1250                    group_name.AsCString());
1251          bp->ResolveBreakpoint();
1252        }
1253      }
1254    }
1255  }
1256}
1257
1258void RenderScriptRuntime::CaptureScriptInvokeForEachMulti(
1259    RuntimeHook *hook, ExecutionContext &exe_ctx) {
1260  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1261
1262  enum {
1263    eRsContext = 0,
1264    eRsScript,
1265    eRsSlot,
1266    eRsAIns,
1267    eRsInLen,
1268    eRsAOut,
1269    eRsUsr,
1270    eRsUsrLen,
1271    eRsSc,
1272  };
1273
1274  std::array<ArgItem, 9> args{{
1275      ArgItem{ArgItem::ePointer, 0}, // const Context       *rsc
1276      ArgItem{ArgItem::ePointer, 0}, // Script              *s
1277      ArgItem{ArgItem::eInt32, 0},   // uint32_t             slot
1278      ArgItem{ArgItem::ePointer, 0}, // const Allocation   **aIns
1279      ArgItem{ArgItem::eInt32, 0},   // size_t               inLen
1280      ArgItem{ArgItem::ePointer, 0}, // Allocation          *aout
1281      ArgItem{ArgItem::ePointer, 0}, // const void          *usr
1282      ArgItem{ArgItem::eInt32, 0},   // size_t               usrLen
1283      ArgItem{ArgItem::ePointer, 0}, // const RsScriptCall  *sc
1284  }};
1285
1286  bool success = GetArgs(exe_ctx, &args[0], args.size());
1287  if (!success) {
1288    LLDB_LOGF(log, "%s - Error while reading the function parameters",
1289              __FUNCTION__);
1290    return;
1291  }
1292
1293  const uint32_t target_ptr_size = m_process->GetAddressByteSize();
1294  Status err;
1295  std::vector<uint64_t> allocs;
1296
1297  // traverse allocation list
1298  for (uint64_t i = 0; i < uint64_t(args[eRsInLen]); ++i) {
1299    // calculate offest to allocation pointer
1300    const addr_t addr = addr_t(args[eRsAIns]) + i * target_ptr_size;
1301
1302    // Note: due to little endian layout, reading 32bits or 64bits into res
1303    // will give the correct results.
1304    uint64_t result = 0;
1305    size_t read = m_process->ReadMemory(addr, &result, target_ptr_size, err);
1306    if (read != target_ptr_size || !err.Success()) {
1307      LLDB_LOGF(log,
1308                "%s - Error while reading allocation list argument %" PRIu64,
1309                __FUNCTION__, i);
1310    } else {
1311      allocs.push_back(result);
1312    }
1313  }
1314
1315  // if there is an output allocation track it
1316  if (uint64_t alloc_out = uint64_t(args[eRsAOut])) {
1317    allocs.push_back(alloc_out);
1318  }
1319
1320  // for all allocations we have found
1321  for (const uint64_t alloc_addr : allocs) {
1322    AllocationDetails *alloc = LookUpAllocation(alloc_addr);
1323    if (!alloc)
1324      alloc = CreateAllocation(alloc_addr);
1325
1326    if (alloc) {
1327      // save the allocation address
1328      if (alloc->address.isValid()) {
1329        // check the allocation address we already have matches
1330        assert(*alloc->address.get() == alloc_addr);
1331      } else {
1332        alloc->address = alloc_addr;
1333      }
1334
1335      // save the context
1336      if (log) {
1337        if (alloc->context.isValid() &&
1338            *alloc->context.get() != addr_t(args[eRsContext]))
1339          LLDB_LOGF(log, "%s - Allocation used by multiple contexts",
1340                    __FUNCTION__);
1341      }
1342      alloc->context = addr_t(args[eRsContext]);
1343    }
1344  }
1345
1346  // make sure we track this script object
1347  if (lldb_private::RenderScriptRuntime::ScriptDetails *script =
1348          LookUpScript(addr_t(args[eRsScript]), true)) {
1349    if (log) {
1350      if (script->context.isValid() &&
1351          *script->context.get() != addr_t(args[eRsContext]))
1352        LLDB_LOGF(log, "%s - Script used by multiple contexts", __FUNCTION__);
1353    }
1354    script->context = addr_t(args[eRsContext]);
1355  }
1356}
1357
1358void RenderScriptRuntime::CaptureSetGlobalVar(RuntimeHook *hook,
1359                                              ExecutionContext &context) {
1360  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1361
1362  enum {
1363    eRsContext,
1364    eRsScript,
1365    eRsId,
1366    eRsData,
1367    eRsLength,
1368  };
1369
1370  std::array<ArgItem, 5> args{{
1371      ArgItem{ArgItem::ePointer, 0}, // eRsContext
1372      ArgItem{ArgItem::ePointer, 0}, // eRsScript
1373      ArgItem{ArgItem::eInt32, 0},   // eRsId
1374      ArgItem{ArgItem::ePointer, 0}, // eRsData
1375      ArgItem{ArgItem::eInt32, 0},   // eRsLength
1376  }};
1377
1378  bool success = GetArgs(context, &args[0], args.size());
1379  if (!success) {
1380    LLDB_LOGF(log, "%s - error reading the function parameters.", __FUNCTION__);
1381    return;
1382  }
1383
1384  if (log) {
1385    LLDB_LOGF(log,
1386              "%s - 0x%" PRIx64 ",0x%" PRIx64 " slot %" PRIu64 " = 0x%" PRIx64
1387              ":%" PRIu64 "bytes.",
1388              __FUNCTION__, uint64_t(args[eRsContext]),
1389              uint64_t(args[eRsScript]), uint64_t(args[eRsId]),
1390              uint64_t(args[eRsData]), uint64_t(args[eRsLength]));
1391
1392    addr_t script_addr = addr_t(args[eRsScript]);
1393    if (m_scriptMappings.find(script_addr) != m_scriptMappings.end()) {
1394      auto rsm = m_scriptMappings[script_addr];
1395      if (uint64_t(args[eRsId]) < rsm->m_globals.size()) {
1396        auto rsg = rsm->m_globals[uint64_t(args[eRsId])];
1397        LLDB_LOGF(log, "%s - Setting of '%s' within '%s' inferred",
1398                  __FUNCTION__, rsg.m_name.AsCString(),
1399                  rsm->m_module->GetFileSpec().GetFilename().AsCString());
1400      }
1401    }
1402  }
1403}
1404
1405void RenderScriptRuntime::CaptureAllocationInit(RuntimeHook *hook,
1406                                                ExecutionContext &exe_ctx) {
1407  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1408
1409  enum { eRsContext, eRsAlloc, eRsForceZero };
1410
1411  std::array<ArgItem, 3> args{{
1412      ArgItem{ArgItem::ePointer, 0}, // eRsContext
1413      ArgItem{ArgItem::ePointer, 0}, // eRsAlloc
1414      ArgItem{ArgItem::eBool, 0},    // eRsForceZero
1415  }};
1416
1417  bool success = GetArgs(exe_ctx, &args[0], args.size());
1418  if (!success) {
1419    LLDB_LOGF(log, "%s - error while reading the function parameters",
1420              __FUNCTION__);
1421    return;
1422  }
1423
1424  LLDB_LOGF(log, "%s - 0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 " .",
1425            __FUNCTION__, uint64_t(args[eRsContext]), uint64_t(args[eRsAlloc]),
1426            uint64_t(args[eRsForceZero]));
1427
1428  AllocationDetails *alloc = CreateAllocation(uint64_t(args[eRsAlloc]));
1429  if (alloc)
1430    alloc->context = uint64_t(args[eRsContext]);
1431}
1432
1433void RenderScriptRuntime::CaptureAllocationDestroy(RuntimeHook *hook,
1434                                                   ExecutionContext &exe_ctx) {
1435  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1436
1437  enum {
1438    eRsContext,
1439    eRsAlloc,
1440  };
1441
1442  std::array<ArgItem, 2> args{{
1443      ArgItem{ArgItem::ePointer, 0}, // eRsContext
1444      ArgItem{ArgItem::ePointer, 0}, // eRsAlloc
1445  }};
1446
1447  bool success = GetArgs(exe_ctx, &args[0], args.size());
1448  if (!success) {
1449    LLDB_LOGF(log, "%s - error while reading the function parameters.",
1450              __FUNCTION__);
1451    return;
1452  }
1453
1454  LLDB_LOGF(log, "%s - 0x%" PRIx64 ", 0x%" PRIx64 ".", __FUNCTION__,
1455            uint64_t(args[eRsContext]), uint64_t(args[eRsAlloc]));
1456
1457  for (auto iter = m_allocations.begin(); iter != m_allocations.end(); ++iter) {
1458    auto &allocation_up = *iter; // get the unique pointer
1459    if (allocation_up->address.isValid() &&
1460        *allocation_up->address.get() == addr_t(args[eRsAlloc])) {
1461      m_allocations.erase(iter);
1462      LLDB_LOGF(log, "%s - deleted allocation entry.", __FUNCTION__);
1463      return;
1464    }
1465  }
1466
1467  LLDB_LOGF(log, "%s - couldn't find destroyed allocation.", __FUNCTION__);
1468}
1469
1470void RenderScriptRuntime::CaptureScriptInit(RuntimeHook *hook,
1471                                            ExecutionContext &exe_ctx) {
1472  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1473
1474  Status err;
1475  Process *process = exe_ctx.GetProcessPtr();
1476
1477  enum { eRsContext, eRsScript, eRsResNamePtr, eRsCachedDirPtr };
1478
1479  std::array<ArgItem, 4> args{
1480      {ArgItem{ArgItem::ePointer, 0}, ArgItem{ArgItem::ePointer, 0},
1481       ArgItem{ArgItem::ePointer, 0}, ArgItem{ArgItem::ePointer, 0}}};
1482  bool success = GetArgs(exe_ctx, &args[0], args.size());
1483  if (!success) {
1484    LLDB_LOGF(log, "%s - error while reading the function parameters.",
1485              __FUNCTION__);
1486    return;
1487  }
1488
1489  std::string res_name;
1490  process->ReadCStringFromMemory(addr_t(args[eRsResNamePtr]), res_name, err);
1491  if (err.Fail()) {
1492    LLDB_LOGF(log, "%s - error reading res_name: %s.", __FUNCTION__,
1493              err.AsCString());
1494  }
1495
1496  std::string cache_dir;
1497  process->ReadCStringFromMemory(addr_t(args[eRsCachedDirPtr]), cache_dir, err);
1498  if (err.Fail()) {
1499    LLDB_LOGF(log, "%s - error reading cache_dir: %s.", __FUNCTION__,
1500              err.AsCString());
1501  }
1502
1503  LLDB_LOGF(log, "%s - 0x%" PRIx64 ",0x%" PRIx64 " => '%s' at '%s' .",
1504            __FUNCTION__, uint64_t(args[eRsContext]), uint64_t(args[eRsScript]),
1505            res_name.c_str(), cache_dir.c_str());
1506
1507  if (res_name.size() > 0) {
1508    StreamString strm;
1509    strm.Printf("librs.%s.so", res_name.c_str());
1510
1511    ScriptDetails *script = LookUpScript(addr_t(args[eRsScript]), true);
1512    if (script) {
1513      script->type = ScriptDetails::eScriptC;
1514      script->cache_dir = cache_dir;
1515      script->res_name = res_name;
1516      script->shared_lib = strm.GetString();
1517      script->context = addr_t(args[eRsContext]);
1518    }
1519
1520    LLDB_LOGF(log,
1521              "%s - '%s' tagged with context 0x%" PRIx64
1522              " and script 0x%" PRIx64 ".",
1523              __FUNCTION__, strm.GetData(), uint64_t(args[eRsContext]),
1524              uint64_t(args[eRsScript]));
1525  } else if (log) {
1526    LLDB_LOGF(log, "%s - resource name invalid, Script not tagged.",
1527              __FUNCTION__);
1528  }
1529}
1530
1531void RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module,
1532                                           ModuleKind kind) {
1533  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1534
1535  if (!module) {
1536    return;
1537  }
1538
1539  Target &target = GetProcess()->GetTarget();
1540  const llvm::Triple::ArchType machine = target.GetArchitecture().GetMachine();
1541
1542  if (machine != llvm::Triple::ArchType::x86 &&
1543      machine != llvm::Triple::ArchType::arm &&
1544      machine != llvm::Triple::ArchType::aarch64 &&
1545      machine != llvm::Triple::ArchType::mipsel &&
1546      machine != llvm::Triple::ArchType::mips64el &&
1547      machine != llvm::Triple::ArchType::x86_64) {
1548    LLDB_LOGF(log, "%s - unable to hook runtime functions.", __FUNCTION__);
1549    return;
1550  }
1551
1552  const uint32_t target_ptr_size =
1553      target.GetArchitecture().GetAddressByteSize();
1554
1555  std::array<bool, s_runtimeHookCount> hook_placed;
1556  hook_placed.fill(false);
1557
1558  for (size_t idx = 0; idx < s_runtimeHookCount; idx++) {
1559    const HookDefn *hook_defn = &s_runtimeHookDefns[idx];
1560    if (hook_defn->kind != kind) {
1561      continue;
1562    }
1563
1564    const char *symbol_name = (target_ptr_size == 4)
1565                                  ? hook_defn->symbol_name_m32
1566                                  : hook_defn->symbol_name_m64;
1567
1568    const Symbol *sym = module->FindFirstSymbolWithNameAndType(
1569        ConstString(symbol_name), eSymbolTypeCode);
1570    if (!sym) {
1571      if (log) {
1572        LLDB_LOGF(log, "%s - symbol '%s' related to the function %s not found",
1573                  __FUNCTION__, symbol_name, hook_defn->name);
1574      }
1575      continue;
1576    }
1577
1578    addr_t addr = sym->GetLoadAddress(&target);
1579    if (addr == LLDB_INVALID_ADDRESS) {
1580      LLDB_LOGF(log,
1581                "%s - unable to resolve the address of hook function '%s' "
1582                "with symbol '%s'.",
1583                __FUNCTION__, hook_defn->name, symbol_name);
1584      continue;
1585    } else {
1586      LLDB_LOGF(log, "%s - function %s, address resolved at 0x%" PRIx64,
1587                __FUNCTION__, hook_defn->name, addr);
1588    }
1589
1590    RuntimeHookSP hook(new RuntimeHook());
1591    hook->address = addr;
1592    hook->defn = hook_defn;
1593    hook->bp_sp = target.CreateBreakpoint(addr, true, false);
1594    hook->bp_sp->SetCallback(HookCallback, hook.get(), true);
1595    m_runtimeHooks[addr] = hook;
1596    if (log) {
1597      LLDB_LOGF(log,
1598                "%s - successfully hooked '%s' in '%s' version %" PRIu64
1599                " at 0x%" PRIx64 ".",
1600                __FUNCTION__, hook_defn->name,
1601                module->GetFileSpec().GetFilename().AsCString(),
1602                (uint64_t)hook_defn->version, (uint64_t)addr);
1603    }
1604    hook_placed[idx] = true;
1605  }
1606
1607  // log any unhooked function
1608  if (log) {
1609    for (size_t i = 0; i < hook_placed.size(); ++i) {
1610      if (hook_placed[i])
1611        continue;
1612      const HookDefn &hook_defn = s_runtimeHookDefns[i];
1613      if (hook_defn.kind != kind)
1614        continue;
1615      LLDB_LOGF(log, "%s - function %s was not hooked", __FUNCTION__,
1616                hook_defn.name);
1617    }
1618  }
1619}
1620
1621void RenderScriptRuntime::FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp) {
1622  if (!rsmodule_sp)
1623    return;
1624
1625  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1626
1627  const ModuleSP module = rsmodule_sp->m_module;
1628  const FileSpec &file = module->GetPlatformFileSpec();
1629
1630  // Iterate over all of the scripts that we currently know of. Note: We cant
1631  // push or pop to m_scripts here or it may invalidate rs_script.
1632  for (const auto &rs_script : m_scripts) {
1633    // Extract the expected .so file path for this script.
1634    std::string shared_lib;
1635    if (!rs_script->shared_lib.get(shared_lib))
1636      continue;
1637
1638    // Only proceed if the module that has loaded corresponds to this script.
1639    if (file.GetFilename() != ConstString(shared_lib.c_str()))
1640      continue;
1641
1642    // Obtain the script address which we use as a key.
1643    lldb::addr_t script;
1644    if (!rs_script->script.get(script))
1645      continue;
1646
1647    // If we have a script mapping for the current script.
1648    if (m_scriptMappings.find(script) != m_scriptMappings.end()) {
1649      // if the module we have stored is different to the one we just received.
1650      if (m_scriptMappings[script] != rsmodule_sp) {
1651        LLDB_LOGF(
1652            log,
1653            "%s - script %" PRIx64 " wants reassigned to new rsmodule '%s'.",
1654            __FUNCTION__, (uint64_t)script,
1655            rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
1656      }
1657    }
1658    // We don't have a script mapping for the current script.
1659    else {
1660      // Obtain the script resource name.
1661      std::string res_name;
1662      if (rs_script->res_name.get(res_name))
1663        // Set the modules resource name.
1664        rsmodule_sp->m_resname = res_name;
1665      // Add Script/Module pair to map.
1666      m_scriptMappings[script] = rsmodule_sp;
1667      LLDB_LOGF(log, "%s - script %" PRIx64 " associated with rsmodule '%s'.",
1668                __FUNCTION__, (uint64_t)script,
1669                rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
1670    }
1671  }
1672}
1673
1674// Uses the Target API to evaluate the expression passed as a parameter to the
1675// function The result of that expression is returned an unsigned 64 bit int,
1676// via the result* parameter. Function returns true on success, and false on
1677// failure
1678bool RenderScriptRuntime::EvalRSExpression(const char *expr,
1679                                           StackFrame *frame_ptr,
1680                                           uint64_t *result) {
1681  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1682  LLDB_LOGF(log, "%s(%s)", __FUNCTION__, expr);
1683
1684  ValueObjectSP expr_result;
1685  EvaluateExpressionOptions options;
1686  options.SetLanguage(lldb::eLanguageTypeC_plus_plus);
1687  // Perform the actual expression evaluation
1688  auto &target = GetProcess()->GetTarget();
1689  target.EvaluateExpression(expr, frame_ptr, expr_result, options);
1690
1691  if (!expr_result) {
1692    LLDB_LOGF(log, "%s: couldn't evaluate expression.", __FUNCTION__);
1693    return false;
1694  }
1695
1696  // The result of the expression is invalid
1697  if (!expr_result->GetError().Success()) {
1698    Status err = expr_result->GetError();
1699    // Expression returned is void, so this is actually a success
1700    if (err.GetError() == UserExpression::kNoResult) {
1701      LLDB_LOGF(log, "%s - expression returned void.", __FUNCTION__);
1702
1703      result = nullptr;
1704      return true;
1705    }
1706
1707    LLDB_LOGF(log, "%s - error evaluating expression result: %s", __FUNCTION__,
1708              err.AsCString());
1709    return false;
1710  }
1711
1712  bool success = false;
1713  // We only read the result as an uint32_t.
1714  *result = expr_result->GetValueAsUnsigned(0, &success);
1715
1716  if (!success) {
1717    LLDB_LOGF(log, "%s - couldn't convert expression result to uint32_t",
1718              __FUNCTION__);
1719    return false;
1720  }
1721
1722  return true;
1723}
1724
1725namespace {
1726// Used to index expression format strings
1727enum ExpressionStrings {
1728  eExprGetOffsetPtr = 0,
1729  eExprAllocGetType,
1730  eExprTypeDimX,
1731  eExprTypeDimY,
1732  eExprTypeDimZ,
1733  eExprTypeElemPtr,
1734  eExprElementType,
1735  eExprElementKind,
1736  eExprElementVec,
1737  eExprElementFieldCount,
1738  eExprSubelementsId,
1739  eExprSubelementsName,
1740  eExprSubelementsArrSize,
1741
1742  _eExprLast // keep at the end, implicit size of the array runtime_expressions
1743};
1744
1745// max length of an expanded expression
1746const int jit_max_expr_size = 512;
1747
1748// Retrieve the string to JIT for the given expression
1749#define JIT_TEMPLATE_CONTEXT "void* ctxt = (void*)rsDebugGetContextWrapper(0x%" PRIx64 "); "
1750const char *JITTemplate(ExpressionStrings e) {
1751  // Format strings containing the expressions we may need to evaluate.
1752  static std::array<const char *, _eExprLast> runtime_expressions = {
1753      {// Mangled GetOffsetPointer(Allocation*, xoff, yoff, zoff, lod, cubemap)
1754       "(int*)_"
1755       "Z12GetOffsetPtrPKN7android12renderscript10AllocationEjjjj23RsAllocation"
1756       "CubemapFace"
1757       "(0x%" PRIx64 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", 0, 0)", // eExprGetOffsetPtr
1758
1759       // Type* rsaAllocationGetType(Context*, Allocation*)
1760       JIT_TEMPLATE_CONTEXT "(void*)rsaAllocationGetType(ctxt, 0x%" PRIx64 ")", // eExprAllocGetType
1761
1762       // rsaTypeGetNativeData(Context*, Type*, void* typeData, size) Pack the
1763       // data in the following way mHal.state.dimX; mHal.state.dimY;
1764       // mHal.state.dimZ; mHal.state.lodCount; mHal.state.faces; mElement;
1765       // into typeData Need to specify 32 or 64 bit for uint_t since this
1766       // differs between devices
1767       JIT_TEMPLATE_CONTEXT
1768       "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(ctxt"
1769       ", 0x%" PRIx64 ", data, 6); data[0]", // eExprTypeDimX
1770       JIT_TEMPLATE_CONTEXT
1771       "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(ctxt"
1772       ", 0x%" PRIx64 ", data, 6); data[1]", // eExprTypeDimY
1773       JIT_TEMPLATE_CONTEXT
1774       "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(ctxt"
1775       ", 0x%" PRIx64 ", data, 6); data[2]", // eExprTypeDimZ
1776       JIT_TEMPLATE_CONTEXT
1777       "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(ctxt"
1778       ", 0x%" PRIx64 ", data, 6); data[5]", // eExprTypeElemPtr
1779
1780       // rsaElementGetNativeData(Context*, Element*, uint32_t* elemData,size)
1781       // Pack mType; mKind; mNormalized; mVectorSize; NumSubElements into
1782       // elemData
1783       JIT_TEMPLATE_CONTEXT
1784       "uint32_t data[5]; (void*)rsaElementGetNativeData(ctxt"
1785       ", 0x%" PRIx64 ", data, 5); data[0]", // eExprElementType
1786       JIT_TEMPLATE_CONTEXT
1787       "uint32_t data[5]; (void*)rsaElementGetNativeData(ctxt"
1788       ", 0x%" PRIx64 ", data, 5); data[1]", // eExprElementKind
1789       JIT_TEMPLATE_CONTEXT
1790       "uint32_t data[5]; (void*)rsaElementGetNativeData(ctxt"
1791       ", 0x%" PRIx64 ", data, 5); data[3]", // eExprElementVec
1792       JIT_TEMPLATE_CONTEXT
1793       "uint32_t data[5]; (void*)rsaElementGetNativeData(ctxt"
1794       ", 0x%" PRIx64 ", data, 5); data[4]", // eExprElementFieldCount
1795
1796       // rsaElementGetSubElements(RsContext con, RsElement elem, uintptr_t
1797       // *ids, const char **names, size_t *arraySizes, uint32_t dataSize)
1798       // Needed for Allocations of structs to gather details about
1799       // fields/Subelements Element* of field
1800       JIT_TEMPLATE_CONTEXT "void* ids[%" PRIu32 "]; const char* names[%" PRIu32
1801       "]; size_t arr_size[%" PRIu32 "];"
1802       "(void*)rsaElementGetSubElements(ctxt, 0x%" PRIx64
1803       ", ids, names, arr_size, %" PRIu32 "); ids[%" PRIu32 "]", // eExprSubelementsId
1804
1805       // Name of field
1806       JIT_TEMPLATE_CONTEXT "void* ids[%" PRIu32 "]; const char* names[%" PRIu32
1807       "]; size_t arr_size[%" PRIu32 "];"
1808       "(void*)rsaElementGetSubElements(ctxt, 0x%" PRIx64
1809       ", ids, names, arr_size, %" PRIu32 "); names[%" PRIu32 "]", // eExprSubelementsName
1810
1811       // Array size of field
1812       JIT_TEMPLATE_CONTEXT "void* ids[%" PRIu32 "]; const char* names[%" PRIu32
1813       "]; size_t arr_size[%" PRIu32 "];"
1814       "(void*)rsaElementGetSubElements(ctxt, 0x%" PRIx64
1815       ", ids, names, arr_size, %" PRIu32 "); arr_size[%" PRIu32 "]"}}; // eExprSubelementsArrSize
1816
1817  return runtime_expressions[e];
1818}
1819} // end of the anonymous namespace
1820
1821// JITs the RS runtime for the internal data pointer of an allocation. Is
1822// passed x,y,z coordinates for the pointer to a specific element. Then sets
1823// the data_ptr member in Allocation with the result. Returns true on success,
1824// false otherwise
1825bool RenderScriptRuntime::JITDataPointer(AllocationDetails *alloc,
1826                                         StackFrame *frame_ptr, uint32_t x,
1827                                         uint32_t y, uint32_t z) {
1828  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1829
1830  if (!alloc->address.isValid()) {
1831    LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__);
1832    return false;
1833  }
1834
1835  const char *fmt_str = JITTemplate(eExprGetOffsetPtr);
1836  char expr_buf[jit_max_expr_size];
1837
1838  int written = snprintf(expr_buf, jit_max_expr_size, fmt_str,
1839                         *alloc->address.get(), x, y, z);
1840  if (written < 0) {
1841    LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__);
1842    return false;
1843  } else if (written >= jit_max_expr_size) {
1844    LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__);
1845    return false;
1846  }
1847
1848  uint64_t result = 0;
1849  if (!EvalRSExpression(expr_buf, frame_ptr, &result))
1850    return false;
1851
1852  addr_t data_ptr = static_cast<lldb::addr_t>(result);
1853  alloc->data_ptr = data_ptr;
1854
1855  return true;
1856}
1857
1858// JITs the RS runtime for the internal pointer to the RS Type of an allocation
1859// Then sets the type_ptr member in Allocation with the result. Returns true on
1860// success, false otherwise
1861bool RenderScriptRuntime::JITTypePointer(AllocationDetails *alloc,
1862                                         StackFrame *frame_ptr) {
1863  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1864
1865  if (!alloc->address.isValid() || !alloc->context.isValid()) {
1866    LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__);
1867    return false;
1868  }
1869
1870  const char *fmt_str = JITTemplate(eExprAllocGetType);
1871  char expr_buf[jit_max_expr_size];
1872
1873  int written = snprintf(expr_buf, jit_max_expr_size, fmt_str,
1874                         *alloc->context.get(), *alloc->address.get());
1875  if (written < 0) {
1876    LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__);
1877    return false;
1878  } else if (written >= jit_max_expr_size) {
1879    LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__);
1880    return false;
1881  }
1882
1883  uint64_t result = 0;
1884  if (!EvalRSExpression(expr_buf, frame_ptr, &result))
1885    return false;
1886
1887  addr_t type_ptr = static_cast<lldb::addr_t>(result);
1888  alloc->type_ptr = type_ptr;
1889
1890  return true;
1891}
1892
1893// JITs the RS runtime for information about the dimensions and type of an
1894// allocation Then sets dimension and element_ptr members in Allocation with
1895// the result. Returns true on success, false otherwise
1896bool RenderScriptRuntime::JITTypePacked(AllocationDetails *alloc,
1897                                        StackFrame *frame_ptr) {
1898  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1899
1900  if (!alloc->type_ptr.isValid() || !alloc->context.isValid()) {
1901    LLDB_LOGF(log, "%s - Failed to find allocation details.", __FUNCTION__);
1902    return false;
1903  }
1904
1905  // Expression is different depending on if device is 32 or 64 bit
1906  uint32_t target_ptr_size =
1907      GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
1908  const uint32_t bits = target_ptr_size == 4 ? 32 : 64;
1909
1910  // We want 4 elements from packed data
1911  const uint32_t num_exprs = 4;
1912  static_assert(num_exprs == (eExprTypeElemPtr - eExprTypeDimX + 1),
1913                "Invalid number of expressions");
1914
1915  char expr_bufs[num_exprs][jit_max_expr_size];
1916  uint64_t results[num_exprs];
1917
1918  for (uint32_t i = 0; i < num_exprs; ++i) {
1919    const char *fmt_str = JITTemplate(ExpressionStrings(eExprTypeDimX + i));
1920    int written = snprintf(expr_bufs[i], jit_max_expr_size, fmt_str,
1921                           *alloc->context.get(), bits, *alloc->type_ptr.get());
1922    if (written < 0) {
1923      LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__);
1924      return false;
1925    } else if (written >= jit_max_expr_size) {
1926      LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__);
1927      return false;
1928    }
1929
1930    // Perform expression evaluation
1931    if (!EvalRSExpression(expr_bufs[i], frame_ptr, &results[i]))
1932      return false;
1933  }
1934
1935  // Assign results to allocation members
1936  AllocationDetails::Dimension dims;
1937  dims.dim_1 = static_cast<uint32_t>(results[0]);
1938  dims.dim_2 = static_cast<uint32_t>(results[1]);
1939  dims.dim_3 = static_cast<uint32_t>(results[2]);
1940  alloc->dimension = dims;
1941
1942  addr_t element_ptr = static_cast<lldb::addr_t>(results[3]);
1943  alloc->element.element_ptr = element_ptr;
1944
1945  LLDB_LOGF(log,
1946            "%s - dims (%" PRIu32 ", %" PRIu32 ", %" PRIu32
1947            ") Element*: 0x%" PRIx64 ".",
1948            __FUNCTION__, dims.dim_1, dims.dim_2, dims.dim_3, element_ptr);
1949
1950  return true;
1951}
1952
1953// JITs the RS runtime for information about the Element of an allocation Then
1954// sets type, type_vec_size, field_count and type_kind members in Element with
1955// the result. Returns true on success, false otherwise
1956bool RenderScriptRuntime::JITElementPacked(Element &elem,
1957                                           const lldb::addr_t context,
1958                                           StackFrame *frame_ptr) {
1959  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1960
1961  if (!elem.element_ptr.isValid()) {
1962    LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__);
1963    return false;
1964  }
1965
1966  // We want 4 elements from packed data
1967  const uint32_t num_exprs = 4;
1968  static_assert(num_exprs == (eExprElementFieldCount - eExprElementType + 1),
1969                "Invalid number of expressions");
1970
1971  char expr_bufs[num_exprs][jit_max_expr_size];
1972  uint64_t results[num_exprs];
1973
1974  for (uint32_t i = 0; i < num_exprs; i++) {
1975    const char *fmt_str = JITTemplate(ExpressionStrings(eExprElementType + i));
1976    int written = snprintf(expr_bufs[i], jit_max_expr_size, fmt_str, context,
1977                           *elem.element_ptr.get());
1978    if (written < 0) {
1979      LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__);
1980      return false;
1981    } else if (written >= jit_max_expr_size) {
1982      LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__);
1983      return false;
1984    }
1985
1986    // Perform expression evaluation
1987    if (!EvalRSExpression(expr_bufs[i], frame_ptr, &results[i]))
1988      return false;
1989  }
1990
1991  // Assign results to allocation members
1992  elem.type = static_cast<RenderScriptRuntime::Element::DataType>(results[0]);
1993  elem.type_kind =
1994      static_cast<RenderScriptRuntime::Element::DataKind>(results[1]);
1995  elem.type_vec_size = static_cast<uint32_t>(results[2]);
1996  elem.field_count = static_cast<uint32_t>(results[3]);
1997
1998  LLDB_LOGF(log,
1999            "%s - data type %" PRIu32 ", pixel type %" PRIu32
2000            ", vector size %" PRIu32 ", field count %" PRIu32,
2001            __FUNCTION__, *elem.type.get(), *elem.type_kind.get(),
2002            *elem.type_vec_size.get(), *elem.field_count.get());
2003
2004  // If this Element has subelements then JIT rsaElementGetSubElements() for
2005  // details about its fields
2006  return !(*elem.field_count.get() > 0 &&
2007           !JITSubelements(elem, context, frame_ptr));
2008}
2009
2010// JITs the RS runtime for information about the subelements/fields of a struct
2011// allocation This is necessary for infering the struct type so we can pretty
2012// print the allocation's contents. Returns true on success, false otherwise
2013bool RenderScriptRuntime::JITSubelements(Element &elem,
2014                                         const lldb::addr_t context,
2015                                         StackFrame *frame_ptr) {
2016  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
2017
2018  if (!elem.element_ptr.isValid() || !elem.field_count.isValid()) {
2019    LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__);
2020    return false;
2021  }
2022
2023  const short num_exprs = 3;
2024  static_assert(num_exprs == (eExprSubelementsArrSize - eExprSubelementsId + 1),
2025                "Invalid number of expressions");
2026
2027  char expr_buffer[jit_max_expr_size];
2028  uint64_t results;
2029
2030  // Iterate over struct fields.
2031  const uint32_t field_count = *elem.field_count.get();
2032  for (uint32_t field_index = 0; field_index < field_count; ++field_index) {
2033    Element child;
2034    for (uint32_t expr_index = 0; expr_index < num_exprs; ++expr_index) {
2035      const char *fmt_str =
2036          JITTemplate(ExpressionStrings(eExprSubelementsId + expr_index));
2037      int written = snprintf(expr_buffer, jit_max_expr_size, fmt_str,
2038                             context, field_count, field_count, field_count,
2039                             *elem.element_ptr.get(), field_count, field_index);
2040      if (written < 0) {
2041        LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__);
2042        return false;
2043      } else if (written >= jit_max_expr_size) {
2044        LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__);
2045        return false;
2046      }
2047
2048      // Perform expression evaluation
2049      if (!EvalRSExpression(expr_buffer, frame_ptr, &results))
2050        return false;
2051
2052      LLDB_LOGF(log, "%s - expr result 0x%" PRIx64 ".", __FUNCTION__, results);
2053
2054      switch (expr_index) {
2055      case 0: // Element* of child
2056        child.element_ptr = static_cast<addr_t>(results);
2057        break;
2058      case 1: // Name of child
2059      {
2060        lldb::addr_t address = static_cast<addr_t>(results);
2061        Status err;
2062        std::string name;
2063        GetProcess()->ReadCStringFromMemory(address, name, err);
2064        if (!err.Fail())
2065          child.type_name = ConstString(name);
2066        else {
2067          LLDB_LOGF(log, "%s - warning: Couldn't read field name.",
2068                    __FUNCTION__);
2069        }
2070        break;
2071      }
2072      case 2: // Array size of child
2073        child.array_size = static_cast<uint32_t>(results);
2074        break;
2075      }
2076    }
2077
2078    // We need to recursively JIT each Element field of the struct since
2079    // structs can be nested inside structs.
2080    if (!JITElementPacked(child, context, frame_ptr))
2081      return false;
2082    elem.children.push_back(child);
2083  }
2084
2085  // Try to infer the name of the struct type so we can pretty print the
2086  // allocation contents.
2087  FindStructTypeName(elem, frame_ptr);
2088
2089  return true;
2090}
2091
2092// JITs the RS runtime for the address of the last element in the allocation.
2093// The `elem_size` parameter represents the size of a single element, including
2094// padding. Which is needed as an offset from the last element pointer. Using
2095// this offset minus the starting address we can calculate the size of the
2096// allocation. Returns true on success, false otherwise
2097bool RenderScriptRuntime::JITAllocationSize(AllocationDetails *alloc,
2098                                            StackFrame *frame_ptr) {
2099  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
2100
2101  if (!alloc->address.isValid() || !alloc->dimension.isValid() ||
2102      !alloc->data_ptr.isValid() || !alloc->element.datum_size.isValid()) {
2103    LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__);
2104    return false;
2105  }
2106
2107  // Find dimensions
2108  uint32_t dim_x = alloc->dimension.get()->dim_1;
2109  uint32_t dim_y = alloc->dimension.get()->dim_2;
2110  uint32_t dim_z = alloc->dimension.get()->dim_3;
2111
2112  // Our plan of jitting the last element address doesn't seem to work for
2113  // struct Allocations` Instead try to infer the size ourselves without any
2114  // inter element padding.
2115  if (alloc->element.children.size() > 0) {
2116    if (dim_x == 0)
2117      dim_x = 1;
2118    if (dim_y == 0)
2119      dim_y = 1;
2120    if (dim_z == 0)
2121      dim_z = 1;
2122
2123    alloc->size = dim_x * dim_y * dim_z * *alloc->element.datum_size.get();
2124
2125    LLDB_LOGF(log, "%s - inferred size of struct allocation %" PRIu32 ".",
2126              __FUNCTION__, *alloc->size.get());
2127    return true;
2128  }
2129
2130  const char *fmt_str = JITTemplate(eExprGetOffsetPtr);
2131  char expr_buf[jit_max_expr_size];
2132
2133  // Calculate last element
2134  dim_x = dim_x == 0 ? 0 : dim_x - 1;
2135  dim_y = dim_y == 0 ? 0 : dim_y - 1;
2136  dim_z = dim_z == 0 ? 0 : dim_z - 1;
2137
2138  int written = snprintf(expr_buf, jit_max_expr_size, fmt_str,
2139                         *alloc->address.get(), dim_x, dim_y, dim_z);
2140  if (written < 0) {
2141    LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__);
2142    return false;
2143  } else if (written >= jit_max_expr_size) {
2144    LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__);
2145    return false;
2146  }
2147
2148  uint64_t result = 0;
2149  if (!EvalRSExpression(expr_buf, frame_ptr, &result))
2150    return false;
2151
2152  addr_t mem_ptr = static_cast<lldb::addr_t>(result);
2153  // Find pointer to last element and add on size of an element
2154  alloc->size = static_cast<uint32_t>(mem_ptr - *alloc->data_ptr.get()) +
2155                *alloc->element.datum_size.get();
2156
2157  return true;
2158}
2159
2160// JITs the RS runtime for information about the stride between rows in the
2161// allocation. This is done to detect padding, since allocated memory is
2162// 16-byte aligned. Returns true on success, false otherwise
2163bool RenderScriptRuntime::JITAllocationStride(AllocationDetails *alloc,
2164                                              StackFrame *frame_ptr) {
2165  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
2166
2167  if (!alloc->address.isValid() || !alloc->data_ptr.isValid()) {
2168    LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__);
2169    return false;
2170  }
2171
2172  const char *fmt_str = JITTemplate(eExprGetOffsetPtr);
2173  char expr_buf[jit_max_expr_size];
2174
2175  int written = snprintf(expr_buf, jit_max_expr_size, fmt_str,
2176                         *alloc->address.get(), 0, 1, 0);
2177  if (written < 0) {
2178    LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__);
2179    return false;
2180  } else if (written >= jit_max_expr_size) {
2181    LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__);
2182    return false;
2183  }
2184
2185  uint64_t result = 0;
2186  if (!EvalRSExpression(expr_buf, frame_ptr, &result))
2187    return false;
2188
2189  addr_t mem_ptr = static_cast<lldb::addr_t>(result);
2190  alloc->stride = static_cast<uint32_t>(mem_ptr - *alloc->data_ptr.get());
2191
2192  return true;
2193}
2194
2195// JIT all the current runtime info regarding an allocation
2196bool RenderScriptRuntime::RefreshAllocation(AllocationDetails *alloc,
2197                                            StackFrame *frame_ptr) {
2198  // GetOffsetPointer()
2199  if (!JITDataPointer(alloc, frame_ptr))
2200    return false;
2201
2202  // rsaAllocationGetType()
2203  if (!JITTypePointer(alloc, frame_ptr))
2204    return false;
2205
2206  // rsaTypeGetNativeData()
2207  if (!JITTypePacked(alloc, frame_ptr))
2208    return false;
2209
2210  // rsaElementGetNativeData()
2211  if (!JITElementPacked(alloc->element, *alloc->context.get(), frame_ptr))
2212    return false;
2213
2214  // Sets the datum_size member in Element
2215  SetElementSize(alloc->element);
2216
2217  // Use GetOffsetPointer() to infer size of the allocation
2218  return JITAllocationSize(alloc, frame_ptr);
2219}
2220
2221// Function attempts to set the type_name member of the paramaterised Element
2222// object. This string should be the name of the struct type the Element
2223// represents. We need this string for pretty printing the Element to users.
2224void RenderScriptRuntime::FindStructTypeName(Element &elem,
2225                                             StackFrame *frame_ptr) {
2226  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
2227
2228  if (!elem.type_name.IsEmpty()) // Name already set
2229    return;
2230  else
2231    elem.type_name = Element::GetFallbackStructName(); // Default type name if
2232                                                       // we don't succeed
2233
2234  // Find all the global variables from the script rs modules
2235  VariableList var_list;
2236  for (auto module_sp : m_rsmodules)
2237    module_sp->m_module->FindGlobalVariables(
2238        RegularExpression(llvm::StringRef(".")), UINT32_MAX, var_list);
2239
2240  // Iterate over all the global variables looking for one with a matching type
2241  // to the Element. We make the assumption a match exists since there needs to
2242  // be a global variable to reflect the struct type back into java host code.
2243  for (const VariableSP &var_sp : var_list) {
2244    if (!var_sp)
2245      continue;
2246
2247    ValueObjectSP valobj_sp = ValueObjectVariable::Create(frame_ptr, var_sp);
2248    if (!valobj_sp)
2249      continue;
2250
2251    // Find the number of variable fields.
2252    // If it has no fields, or more fields than our Element, then it can't be
2253    // the struct we're looking for. Don't check for equality since RS can add
2254    // extra struct members for padding.
2255    size_t num_children = valobj_sp->GetNumChildren();
2256    if (num_children > elem.children.size() || num_children == 0)
2257      continue;
2258
2259    // Iterate over children looking for members with matching field names. If
2260    // all the field names match, this is likely the struct we want.
2261    //   TODO: This could be made more robust by also checking children data
2262    //   sizes, or array size
2263    bool found = true;
2264    for (size_t i = 0; i < num_children; ++i) {
2265      ValueObjectSP child = valobj_sp->GetChildAtIndex(i, true);
2266      if (!child || (child->GetName() != elem.children[i].type_name)) {
2267        found = false;
2268        break;
2269      }
2270    }
2271
2272    // RS can add extra struct members for padding in the format
2273    // '#rs_padding_[0-9]+'
2274    if (found && num_children < elem.children.size()) {
2275      const uint32_t size_diff = elem.children.size() - num_children;
2276      LLDB_LOGF(log, "%s - %" PRIu32 " padding struct entries", __FUNCTION__,
2277                size_diff);
2278
2279      for (uint32_t i = 0; i < size_diff; ++i) {
2280        ConstString name = elem.children[num_children + i].type_name;
2281        if (strcmp(name.AsCString(), "#rs_padding") < 0)
2282          found = false;
2283      }
2284    }
2285
2286    // We've found a global variable with matching type
2287    if (found) {
2288      // Dereference since our Element type isn't a pointer.
2289      if (valobj_sp->IsPointerType()) {
2290        Status err;
2291        ValueObjectSP deref_valobj = valobj_sp->Dereference(err);
2292        if (!err.Fail())
2293          valobj_sp = deref_valobj;
2294      }
2295
2296      // Save name of variable in Element.
2297      elem.type_name = valobj_sp->GetTypeName();
2298      LLDB_LOGF(log, "%s - element name set to %s", __FUNCTION__,
2299                elem.type_name.AsCString());
2300
2301      return;
2302    }
2303  }
2304}
2305
2306// Function sets the datum_size member of Element. Representing the size of a
2307// single instance including padding. Assumes the relevant allocation
2308// information has already been jitted.
2309void RenderScriptRuntime::SetElementSize(Element &elem) {
2310  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
2311  const Element::DataType type = *elem.type.get();
2312  assert(type >= Element::RS_TYPE_NONE && type <= Element::RS_TYPE_FONT &&
2313         "Invalid allocation type");
2314
2315  const uint32_t vec_size = *elem.type_vec_size.get();
2316  uint32_t data_size = 0;
2317  uint32_t padding = 0;
2318
2319  // Element is of a struct type, calculate size recursively.
2320  if ((type == Element::RS_TYPE_NONE) && (elem.children.size() > 0)) {
2321    for (Element &child : elem.children) {
2322      SetElementSize(child);
2323      const uint32_t array_size =
2324          child.array_size.isValid() ? *child.array_size.get() : 1;
2325      data_size += *child.datum_size.get() * array_size;
2326    }
2327  }
2328  // These have been packed already
2329  else if (type == Element::RS_TYPE_UNSIGNED_5_6_5 ||
2330           type == Element::RS_TYPE_UNSIGNED_5_5_5_1 ||
2331           type == Element::RS_TYPE_UNSIGNED_4_4_4_4) {
2332    data_size = AllocationDetails::RSTypeToFormat[type][eElementSize];
2333  } else if (type < Element::RS_TYPE_ELEMENT) {
2334    data_size =
2335        vec_size * AllocationDetails::RSTypeToFormat[type][eElementSize];
2336    if (vec_size == 3)
2337      padding = AllocationDetails::RSTypeToFormat[type][eElementSize];
2338  } else
2339    data_size =
2340        GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
2341
2342  elem.padding = padding;
2343  elem.datum_size = data_size + padding;
2344  LLDB_LOGF(log, "%s - element size set to %" PRIu32, __FUNCTION__,
2345            data_size + padding);
2346}
2347
2348// Given an allocation, this function copies the allocation contents from
2349// device into a buffer on the heap. Returning a shared pointer to the buffer
2350// containing the data.
2351std::shared_ptr<uint8_t>
2352RenderScriptRuntime::GetAllocationData(AllocationDetails *alloc,
2353                                       StackFrame *frame_ptr) {
2354  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
2355
2356  // JIT all the allocation details
2357  if (alloc->ShouldRefresh()) {
2358    LLDB_LOGF(log, "%s - allocation details not calculated yet, jitting info",
2359              __FUNCTION__);
2360
2361    if (!RefreshAllocation(alloc, frame_ptr)) {
2362      LLDB_LOGF(log, "%s - couldn't JIT allocation details", __FUNCTION__);
2363      return nullptr;
2364    }
2365  }
2366
2367  assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() &&
2368         alloc->element.type_vec_size.isValid() && alloc->size.isValid() &&
2369         "Allocation information not available");
2370
2371  // Allocate a buffer to copy data into
2372  const uint32_t size = *alloc->size.get();
2373  std::shared_ptr<uint8_t> buffer(new uint8_t[size]);
2374  if (!buffer) {
2375    LLDB_LOGF(log, "%s - couldn't allocate a %" PRIu32 " byte buffer",
2376              __FUNCTION__, size);
2377    return nullptr;
2378  }
2379
2380  // Read the inferior memory
2381  Status err;
2382  lldb::addr_t data_ptr = *alloc->data_ptr.get();
2383  GetProcess()->ReadMemory(data_ptr, buffer.get(), size, err);
2384  if (err.Fail()) {
2385    LLDB_LOGF(log,
2386              "%s - '%s' Couldn't read %" PRIu32
2387              " bytes of allocation data from 0x%" PRIx64,
2388              __FUNCTION__, err.AsCString(), size, data_ptr);
2389    return nullptr;
2390  }
2391
2392  return buffer;
2393}
2394
2395// Function copies data from a binary file into an allocation. There is a
2396// header at the start of the file, FileHeader, before the data content itself.
2397// Information from this header is used to display warnings to the user about
2398// incompatibilities
2399bool RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id,
2400                                         const char *path,
2401                                         StackFrame *frame_ptr) {
2402  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
2403
2404  // Find allocation with the given id
2405  AllocationDetails *alloc = FindAllocByID(strm, alloc_id);
2406  if (!alloc)
2407    return false;
2408
2409  LLDB_LOGF(log, "%s - found allocation 0x%" PRIx64, __FUNCTION__,
2410            *alloc->address.get());
2411
2412  // JIT all the allocation details
2413  if (alloc->ShouldRefresh()) {
2414    LLDB_LOGF(log, "%s - allocation details not calculated yet, jitting info.",
2415              __FUNCTION__);
2416
2417    if (!RefreshAllocation(alloc, frame_ptr)) {
2418      LLDB_LOGF(log, "%s - couldn't JIT allocation details", __FUNCTION__);
2419      return false;
2420    }
2421  }
2422
2423  assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() &&
2424         alloc->element.type_vec_size.isValid() && alloc->size.isValid() &&
2425         alloc->element.datum_size.isValid() &&
2426         "Allocation information not available");
2427
2428  // Check we can read from file
2429  FileSpec file(path);
2430  FileSystem::Instance().Resolve(file);
2431  if (!FileSystem::Instance().Exists(file)) {
2432    strm.Printf("Error: File %s does not exist", path);
2433    strm.EOL();
2434    return false;
2435  }
2436
2437  if (!FileSystem::Instance().Readable(file)) {
2438    strm.Printf("Error: File %s does not have readable permissions", path);
2439    strm.EOL();
2440    return false;
2441  }
2442
2443  // Read file into data buffer
2444  auto data_sp = FileSystem::Instance().CreateDataBuffer(file.GetPath());
2445
2446  // Cast start of buffer to FileHeader and use pointer to read metadata
2447  void *file_buf = data_sp->GetBytes();
2448  if (file_buf == nullptr ||
2449      data_sp->GetByteSize() < (sizeof(AllocationDetails::FileHeader) +
2450                                sizeof(AllocationDetails::ElementHeader))) {
2451    strm.Printf("Error: File %s does not contain enough data for header", path);
2452    strm.EOL();
2453    return false;
2454  }
2455  const AllocationDetails::FileHeader *file_header =
2456      static_cast<AllocationDetails::FileHeader *>(file_buf);
2457
2458  // Check file starts with ascii characters "RSAD"
2459  if (memcmp(file_header->ident, "RSAD", 4)) {
2460    strm.Printf("Error: File doesn't contain identifier for an RS allocation "
2461                "dump. Are you sure this is the correct file?");
2462    strm.EOL();
2463    return false;
2464  }
2465
2466  // Look at the type of the root element in the header
2467  AllocationDetails::ElementHeader root_el_hdr;
2468  memcpy(&root_el_hdr, static_cast<uint8_t *>(file_buf) +
2469                           sizeof(AllocationDetails::FileHeader),
2470         sizeof(AllocationDetails::ElementHeader));
2471
2472  LLDB_LOGF(log, "%s - header type %" PRIu32 ", element size %" PRIu32,
2473            __FUNCTION__, root_el_hdr.type, root_el_hdr.element_size);
2474
2475  // Check if the target allocation and file both have the same number of bytes
2476  // for an Element
2477  if (*alloc->element.datum_size.get() != root_el_hdr.element_size) {
2478    strm.Printf("Warning: Mismatched Element sizes - file %" PRIu32
2479                " bytes, allocation %" PRIu32 " bytes",
2480                root_el_hdr.element_size, *alloc->element.datum_size.get());
2481    strm.EOL();
2482  }
2483
2484  // Check if the target allocation and file both have the same type
2485  const uint32_t alloc_type = static_cast<uint32_t>(*alloc->element.type.get());
2486  const uint32_t file_type = root_el_hdr.type;
2487
2488  if (file_type > Element::RS_TYPE_FONT) {
2489    strm.Printf("Warning: File has unknown allocation type");
2490    strm.EOL();
2491  } else if (alloc_type != file_type) {
2492    // Enum value isn't monotonous, so doesn't always index RsDataTypeToString
2493    // array
2494    uint32_t target_type_name_idx = alloc_type;
2495    uint32_t head_type_name_idx = file_type;
2496    if (alloc_type >= Element::RS_TYPE_ELEMENT &&
2497        alloc_type <= Element::RS_TYPE_FONT)
2498      target_type_name_idx = static_cast<Element::DataType>(
2499          (alloc_type - Element::RS_TYPE_ELEMENT) +
2500          Element::RS_TYPE_MATRIX_2X2 + 1);
2501
2502    if (file_type >= Element::RS_TYPE_ELEMENT &&
2503        file_type <= Element::RS_TYPE_FONT)
2504      head_type_name_idx = static_cast<Element::DataType>(
2505          (file_type - Element::RS_TYPE_ELEMENT) + Element::RS_TYPE_MATRIX_2X2 +
2506          1);
2507
2508    const char *head_type_name =
2509        AllocationDetails::RsDataTypeToString[head_type_name_idx][0];
2510    const char *target_type_name =
2511        AllocationDetails::RsDataTypeToString[target_type_name_idx][0];
2512
2513    strm.Printf(
2514        "Warning: Mismatched Types - file '%s' type, allocation '%s' type",
2515        head_type_name, target_type_name);
2516    strm.EOL();
2517  }
2518
2519  // Advance buffer past header
2520  file_buf = static_cast<uint8_t *>(file_buf) + file_header->hdr_size;
2521
2522  // Calculate size of allocation data in file
2523  size_t size = data_sp->GetByteSize() - file_header->hdr_size;
2524
2525  // Check if the target allocation and file both have the same total data
2526  // size.
2527  const uint32_t alloc_size = *alloc->size.get();
2528  if (alloc_size != size) {
2529    strm.Printf("Warning: Mismatched allocation sizes - file 0x%" PRIx64
2530                " bytes, allocation 0x%" PRIx32 " bytes",
2531                (uint64_t)size, alloc_size);
2532    strm.EOL();
2533    // Set length to copy to minimum
2534    size = alloc_size < size ? alloc_size : size;
2535  }
2536
2537  // Copy file data from our buffer into the target allocation.
2538  lldb::addr_t alloc_data = *alloc->data_ptr.get();
2539  Status err;
2540  size_t written = GetProcess()->WriteMemory(alloc_data, file_buf, size, err);
2541  if (!err.Success() || written != size) {
2542    strm.Printf("Error: Couldn't write data to allocation %s", err.AsCString());
2543    strm.EOL();
2544    return false;
2545  }
2546
2547  strm.Printf("Contents of file '%s' read into allocation %" PRIu32, path,
2548              alloc->id);
2549  strm.EOL();
2550
2551  return true;
2552}
2553
2554// Function takes as parameters a byte buffer, which will eventually be written
2555// to file as the element header, an offset into that buffer, and an Element
2556// that will be saved into the buffer at the parametrised offset. Return value
2557// is the new offset after writing the element into the buffer. Elements are
2558// saved to the file as the ElementHeader struct followed by offsets to the
2559// structs of all the element's children.
2560size_t RenderScriptRuntime::PopulateElementHeaders(
2561    const std::shared_ptr<uint8_t> header_buffer, size_t offset,
2562    const Element &elem) {
2563  // File struct for an element header with all the relevant details copied
2564  // from elem. We assume members are valid already.
2565  AllocationDetails::ElementHeader elem_header;
2566  elem_header.type = *elem.type.get();
2567  elem_header.kind = *elem.type_kind.get();
2568  elem_header.element_size = *elem.datum_size.get();
2569  elem_header.vector_size = *elem.type_vec_size.get();
2570  elem_header.array_size =
2571      elem.array_size.isValid() ? *elem.array_size.get() : 0;
2572  const size_t elem_header_size = sizeof(AllocationDetails::ElementHeader);
2573
2574  // Copy struct into buffer and advance offset We assume that header_buffer
2575  // has been checked for nullptr before this method is called
2576  memcpy(header_buffer.get() + offset, &elem_header, elem_header_size);
2577  offset += elem_header_size;
2578
2579  // Starting offset of child ElementHeader struct
2580  size_t child_offset =
2581      offset + ((elem.children.size() + 1) * sizeof(uint32_t));
2582  for (const RenderScriptRuntime::Element &child : elem.children) {
2583    // Recursively populate the buffer with the element header structs of
2584    // children. Then save the offsets where they were set after the parent
2585    // element header.
2586    memcpy(header_buffer.get() + offset, &child_offset, sizeof(uint32_t));
2587    offset += sizeof(uint32_t);
2588
2589    child_offset = PopulateElementHeaders(header_buffer, child_offset, child);
2590  }
2591
2592  // Zero indicates no more children
2593  memset(header_buffer.get() + offset, 0, sizeof(uint32_t));
2594
2595  return child_offset;
2596}
2597
2598// Given an Element object this function returns the total size needed in the
2599// file header to store the element's details. Taking into account the size of
2600// the element header struct, plus the offsets to all the element's children.
2601// Function is recursive so that the size of all ancestors is taken into
2602// account.
2603size_t RenderScriptRuntime::CalculateElementHeaderSize(const Element &elem) {
2604  // Offsets to children plus zero terminator
2605  size_t size = (elem.children.size() + 1) * sizeof(uint32_t);
2606  // Size of header struct with type details
2607  size += sizeof(AllocationDetails::ElementHeader);
2608
2609  // Calculate recursively for all descendants
2610  for (const Element &child : elem.children)
2611    size += CalculateElementHeaderSize(child);
2612
2613  return size;
2614}
2615
2616// Function copies allocation contents into a binary file. This file can then
2617// be loaded later into a different allocation. There is a header, FileHeader,
2618// before the allocation data containing meta-data.
2619bool RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id,
2620                                         const char *path,
2621                                         StackFrame *frame_ptr) {
2622  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
2623
2624  // Find allocation with the given id
2625  AllocationDetails *alloc = FindAllocByID(strm, alloc_id);
2626  if (!alloc)
2627    return false;
2628
2629  LLDB_LOGF(log, "%s - found allocation 0x%" PRIx64 ".", __FUNCTION__,
2630            *alloc->address.get());
2631
2632  // JIT all the allocation details
2633  if (alloc->ShouldRefresh()) {
2634    LLDB_LOGF(log, "%s - allocation details not calculated yet, jitting info.",
2635              __FUNCTION__);
2636
2637    if (!RefreshAllocation(alloc, frame_ptr)) {
2638      LLDB_LOGF(log, "%s - couldn't JIT allocation details.", __FUNCTION__);
2639      return false;
2640    }
2641  }
2642
2643  assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() &&
2644         alloc->element.type_vec_size.isValid() &&
2645         alloc->element.datum_size.get() &&
2646         alloc->element.type_kind.isValid() && alloc->dimension.isValid() &&
2647         "Allocation information not available");
2648
2649  // Check we can create writable file
2650  FileSpec file_spec(path);
2651  FileSystem::Instance().Resolve(file_spec);
2652  auto file = FileSystem::Instance().Open(
2653      file_spec, File::eOpenOptionWrite | File::eOpenOptionCanCreate |
2654                     File::eOpenOptionTruncate);
2655
2656  if (!file) {
2657    std::string error = llvm::toString(file.takeError());
2658    strm.Printf("Error: Failed to open '%s' for writing: %s", path,
2659                error.c_str());
2660    strm.EOL();
2661    return false;
2662  }
2663
2664  // Read allocation into buffer of heap memory
2665  const std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr);
2666  if (!buffer) {
2667    strm.Printf("Error: Couldn't read allocation data into buffer");
2668    strm.EOL();
2669    return false;
2670  }
2671
2672  // Create the file header
2673  AllocationDetails::FileHeader head;
2674  memcpy(head.ident, "RSAD", 4);
2675  head.dims[0] = static_cast<uint32_t>(alloc->dimension.get()->dim_1);
2676  head.dims[1] = static_cast<uint32_t>(alloc->dimension.get()->dim_2);
2677  head.dims[2] = static_cast<uint32_t>(alloc->dimension.get()->dim_3);
2678
2679  const size_t element_header_size = CalculateElementHeaderSize(alloc->element);
2680  assert((sizeof(AllocationDetails::FileHeader) + element_header_size) <
2681             UINT16_MAX &&
2682         "Element header too large");
2683  head.hdr_size = static_cast<uint16_t>(sizeof(AllocationDetails::FileHeader) +
2684                                        element_header_size);
2685
2686  // Write the file header
2687  size_t num_bytes = sizeof(AllocationDetails::FileHeader);
2688  LLDB_LOGF(log, "%s - writing File Header, 0x%" PRIx64 " bytes", __FUNCTION__,
2689            (uint64_t)num_bytes);
2690
2691  Status err = file.get()->Write(&head, num_bytes);
2692  if (!err.Success()) {
2693    strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), path);
2694    strm.EOL();
2695    return false;
2696  }
2697
2698  // Create the headers describing the element type of the allocation.
2699  std::shared_ptr<uint8_t> element_header_buffer(
2700      new uint8_t[element_header_size]);
2701  if (element_header_buffer == nullptr) {
2702    strm.Printf("Internal Error: Couldn't allocate %" PRIu64
2703                " bytes on the heap",
2704                (uint64_t)element_header_size);
2705    strm.EOL();
2706    return false;
2707  }
2708
2709  PopulateElementHeaders(element_header_buffer, 0, alloc->element);
2710
2711  // Write headers for allocation element type to file
2712  num_bytes = element_header_size;
2713  LLDB_LOGF(log, "%s - writing element headers, 0x%" PRIx64 " bytes.",
2714            __FUNCTION__, (uint64_t)num_bytes);
2715
2716  err = file.get()->Write(element_header_buffer.get(), num_bytes);
2717  if (!err.Success()) {
2718    strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), path);
2719    strm.EOL();
2720    return false;
2721  }
2722
2723  // Write allocation data to file
2724  num_bytes = static_cast<size_t>(*alloc->size.get());
2725  LLDB_LOGF(log, "%s - writing 0x%" PRIx64 " bytes", __FUNCTION__,
2726            (uint64_t)num_bytes);
2727
2728  err = file.get()->Write(buffer.get(), num_bytes);
2729  if (!err.Success()) {
2730    strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), path);
2731    strm.EOL();
2732    return false;
2733  }
2734
2735  strm.Printf("Allocation written to file '%s'", path);
2736  strm.EOL();
2737  return true;
2738}
2739
2740bool RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp) {
2741  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
2742
2743  if (module_sp) {
2744    for (const auto &rs_module : m_rsmodules) {
2745      if (rs_module->m_module == module_sp) {
2746        // Check if the user has enabled automatically breaking on all RS
2747        // kernels.
2748        if (m_breakAllKernels)
2749          BreakOnModuleKernels(rs_module);
2750
2751        return false;
2752      }
2753    }
2754    bool module_loaded = false;
2755    switch (GetModuleKind(module_sp)) {
2756    case eModuleKindKernelObj: {
2757      RSModuleDescriptorSP module_desc;
2758      module_desc = std::make_shared<RSModuleDescriptor>(module_sp);
2759      if (module_desc->ParseRSInfo()) {
2760        m_rsmodules.push_back(module_desc);
2761        module_desc->WarnIfVersionMismatch(GetProcess()
2762                                               ->GetTarget()
2763                                               .GetDebugger()
2764                                               .GetAsyncOutputStream()
2765                                               .get());
2766        module_loaded = true;
2767      }
2768      if (module_loaded) {
2769        FixupScriptDetails(module_desc);
2770      }
2771      break;
2772    }
2773    case eModuleKindDriver: {
2774      if (!m_libRSDriver) {
2775        m_libRSDriver = module_sp;
2776        LoadRuntimeHooks(m_libRSDriver, RenderScriptRuntime::eModuleKindDriver);
2777      }
2778      break;
2779    }
2780    case eModuleKindImpl: {
2781      if (!m_libRSCpuRef) {
2782        m_libRSCpuRef = module_sp;
2783        LoadRuntimeHooks(m_libRSCpuRef, RenderScriptRuntime::eModuleKindImpl);
2784      }
2785      break;
2786    }
2787    case eModuleKindLibRS: {
2788      if (!m_libRS) {
2789        m_libRS = module_sp;
2790        static ConstString gDbgPresentStr("gDebuggerPresent");
2791        const Symbol *debug_present = m_libRS->FindFirstSymbolWithNameAndType(
2792            gDbgPresentStr, eSymbolTypeData);
2793        if (debug_present) {
2794          Status err;
2795          uint32_t flag = 0x00000001U;
2796          Target &target = GetProcess()->GetTarget();
2797          addr_t addr = debug_present->GetLoadAddress(&target);
2798          GetProcess()->WriteMemory(addr, &flag, sizeof(flag), err);
2799          if (err.Success()) {
2800            LLDB_LOGF(log, "%s - debugger present flag set on debugee.",
2801                      __FUNCTION__);
2802
2803            m_debuggerPresentFlagged = true;
2804          } else if (log) {
2805            LLDB_LOGF(log, "%s - error writing debugger present flags '%s' ",
2806                      __FUNCTION__, err.AsCString());
2807          }
2808        } else if (log) {
2809          LLDB_LOGF(
2810              log,
2811              "%s - error writing debugger present flags - symbol not found",
2812              __FUNCTION__);
2813        }
2814      }
2815      break;
2816    }
2817    default:
2818      break;
2819    }
2820    if (module_loaded)
2821      Update();
2822    return module_loaded;
2823  }
2824  return false;
2825}
2826
2827void RenderScriptRuntime::Update() {
2828  if (m_rsmodules.size() > 0) {
2829    if (!m_initiated) {
2830      Initiate();
2831    }
2832  }
2833}
2834
2835void RSModuleDescriptor::WarnIfVersionMismatch(lldb_private::Stream *s) const {
2836  if (!s)
2837    return;
2838
2839  if (m_slang_version.empty() || m_bcc_version.empty()) {
2840    s->PutCString("WARNING: Unknown bcc or slang (llvm-rs-cc) version; debug "
2841                  "experience may be unreliable");
2842    s->EOL();
2843  } else if (m_slang_version != m_bcc_version) {
2844    s->Printf("WARNING: The debug info emitted by the slang frontend "
2845              "(llvm-rs-cc) used to build this module (%s) does not match the "
2846              "version of bcc used to generate the debug information (%s). "
2847              "This is an unsupported configuration and may result in a poor "
2848              "debugging experience; proceed with caution",
2849              m_slang_version.c_str(), m_bcc_version.c_str());
2850    s->EOL();
2851  }
2852}
2853
2854bool RSModuleDescriptor::ParsePragmaCount(llvm::StringRef *lines,
2855                                          size_t n_lines) {
2856  // Skip the pragma prototype line
2857  ++lines;
2858  for (; n_lines--; ++lines) {
2859    const auto kv_pair = lines->split(" - ");
2860    m_pragmas[kv_pair.first.trim().str()] = kv_pair.second.trim().str();
2861  }
2862  return true;
2863}
2864
2865bool RSModuleDescriptor::ParseExportReduceCount(llvm::StringRef *lines,
2866                                                size_t n_lines) {
2867  // The list of reduction kernels in the `.rs.info` symbol is of the form
2868  // "signature - accumulatordatasize - reduction_name - initializer_name -
2869  // accumulator_name - combiner_name - outconverter_name - halter_name" Where
2870  // a function is not explicitly named by the user, or is not generated by the
2871  // compiler, it is named "." so the dash separated list should always be 8
2872  // items long
2873  Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
2874  // Skip the exportReduceCount line
2875  ++lines;
2876  for (; n_lines--; ++lines) {
2877    llvm::SmallVector<llvm::StringRef, 8> spec;
2878    lines->split(spec, " - ");
2879    if (spec.size() != 8) {
2880      if (spec.size() < 8) {
2881        if (log)
2882          log->Error("Error parsing RenderScript reduction spec. wrong number "
2883                     "of fields");
2884        return false;
2885      } else if (log)
2886        log->Warning("Extraneous members in reduction spec: '%s'",
2887                     lines->str().c_str());
2888    }
2889
2890    const auto sig_s = spec[0];
2891    uint32_t sig;
2892    if (sig_s.getAsInteger(10, sig)) {
2893      if (log)
2894        log->Error("Error parsing Renderscript reduction spec: invalid kernel "
2895                   "signature: '%s'",
2896                   sig_s.str().c_str());
2897      return false;
2898    }
2899
2900    const auto accum_data_size_s = spec[1];
2901    uint32_t accum_data_size;
2902    if (accum_data_size_s.getAsInteger(10, accum_data_size)) {
2903      if (log)
2904        log->Error("Error parsing Renderscript reduction spec: invalid "
2905                   "accumulator data size %s",
2906                   accum_data_size_s.str().c_str());
2907      return false;
2908    }
2909
2910    LLDB_LOGF(log, "Found RenderScript reduction '%s'", spec[2].str().c_str());
2911
2912    m_reductions.push_back(RSReductionDescriptor(this, sig, accum_data_size,
2913                                                 spec[2], spec[3], spec[4],
2914                                                 spec[5], spec[6], spec[7]));
2915  }
2916  return true;
2917}
2918
2919bool RSModuleDescriptor::ParseVersionInfo(llvm::StringRef *lines,
2920                                          size_t n_lines) {
2921  // Skip the versionInfo line
2922  ++lines;
2923  for (; n_lines--; ++lines) {
2924    // We're only interested in bcc and slang versions, and ignore all other
2925    // versionInfo lines
2926    const auto kv_pair = lines->split(" - ");
2927    if (kv_pair.first == "slang")
2928      m_slang_version = kv_pair.second.str();
2929    else if (kv_pair.first == "bcc")
2930      m_bcc_version = kv_pair.second.str();
2931  }
2932  return true;
2933}
2934
2935bool RSModuleDescriptor::ParseExportForeachCount(llvm::StringRef *lines,
2936                                                 size_t n_lines) {
2937  // Skip the exportForeachCount line
2938  ++lines;
2939  for (; n_lines--; ++lines) {
2940    uint32_t slot;
2941    // `forEach` kernels are listed in the `.rs.info` packet as a "slot - name"
2942    // pair per line
2943    const auto kv_pair = lines->split(" - ");
2944    if (kv_pair.first.getAsInteger(10, slot))
2945      return false;
2946    m_kernels.push_back(RSKernelDescriptor(this, kv_pair.second, slot));
2947  }
2948  return true;
2949}
2950
2951bool RSModuleDescriptor::ParseExportVarCount(llvm::StringRef *lines,
2952                                             size_t n_lines) {
2953  // Skip the ExportVarCount line
2954  ++lines;
2955  for (; n_lines--; ++lines)
2956    m_globals.push_back(RSGlobalDescriptor(this, *lines));
2957  return true;
2958}
2959
2960// The .rs.info symbol in renderscript modules contains a string which needs to
2961// be parsed. The string is basic and is parsed on a line by line basis.
2962bool RSModuleDescriptor::ParseRSInfo() {
2963  assert(m_module);
2964  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
2965  const Symbol *info_sym = m_module->FindFirstSymbolWithNameAndType(
2966      ConstString(".rs.info"), eSymbolTypeData);
2967  if (!info_sym)
2968    return false;
2969
2970  const addr_t addr = info_sym->GetAddressRef().GetFileAddress();
2971  if (addr == LLDB_INVALID_ADDRESS)
2972    return false;
2973
2974  const addr_t size = info_sym->GetByteSize();
2975  const FileSpec fs = m_module->GetFileSpec();
2976
2977  auto buffer =
2978      FileSystem::Instance().CreateDataBuffer(fs.GetPath(), size, addr);
2979  if (!buffer)
2980    return false;
2981
2982  // split rs.info. contents into lines
2983  llvm::SmallVector<llvm::StringRef, 128> info_lines;
2984  {
2985    const llvm::StringRef raw_rs_info((const char *)buffer->GetBytes());
2986    raw_rs_info.split(info_lines, '\n');
2987    LLDB_LOGF(log, "'.rs.info symbol for '%s':\n%s",
2988              m_module->GetFileSpec().GetCString(), raw_rs_info.str().c_str());
2989  }
2990
2991  enum {
2992    eExportVar,
2993    eExportForEach,
2994    eExportReduce,
2995    ePragma,
2996    eBuildChecksum,
2997    eObjectSlot,
2998    eVersionInfo,
2999  };
3000
3001  const auto rs_info_handler = [](llvm::StringRef name) -> int {
3002    return llvm::StringSwitch<int>(name)
3003        // The number of visible global variables in the script
3004        .Case("exportVarCount", eExportVar)
3005        // The number of RenderScrip `forEach` kernels __attribute__((kernel))
3006        .Case("exportForEachCount", eExportForEach)
3007        // The number of generalreductions: This marked in the script by
3008        // `#pragma reduce()`
3009        .Case("exportReduceCount", eExportReduce)
3010        // Total count of all RenderScript specific `#pragmas` used in the
3011        // script
3012        .Case("pragmaCount", ePragma)
3013        .Case("objectSlotCount", eObjectSlot)
3014        .Case("versionInfo", eVersionInfo)
3015        .Default(-1);
3016  };
3017
3018  // parse all text lines of .rs.info
3019  for (auto line = info_lines.begin(); line != info_lines.end(); ++line) {
3020    const auto kv_pair = line->split(": ");
3021    const auto key = kv_pair.first;
3022    const auto val = kv_pair.second.trim();
3023
3024    const auto handler = rs_info_handler(key);
3025    if (handler == -1)
3026      continue;
3027    // getAsInteger returns `true` on an error condition - we're only
3028    // interested in numeric fields at the moment
3029    uint64_t n_lines;
3030    if (val.getAsInteger(10, n_lines)) {
3031      LLDB_LOGV(log, "Failed to parse non-numeric '.rs.info' section {0}",
3032                line->str());
3033      continue;
3034    }
3035    if (info_lines.end() - (line + 1) < (ptrdiff_t)n_lines)
3036      return false;
3037
3038    bool success = false;
3039    switch (handler) {
3040    case eExportVar:
3041      success = ParseExportVarCount(line, n_lines);
3042      break;
3043    case eExportForEach:
3044      success = ParseExportForeachCount(line, n_lines);
3045      break;
3046    case eExportReduce:
3047      success = ParseExportReduceCount(line, n_lines);
3048      break;
3049    case ePragma:
3050      success = ParsePragmaCount(line, n_lines);
3051      break;
3052    case eVersionInfo:
3053      success = ParseVersionInfo(line, n_lines);
3054      break;
3055    default: {
3056      LLDB_LOGF(log, "%s - skipping .rs.info field '%s'", __FUNCTION__,
3057                line->str().c_str());
3058      continue;
3059    }
3060    }
3061    if (!success)
3062      return false;
3063    line += n_lines;
3064  }
3065  return info_lines.size() > 0;
3066}
3067
3068void RenderScriptRuntime::DumpStatus(Stream &strm) const {
3069  if (m_libRS) {
3070    strm.Printf("Runtime Library discovered.");
3071    strm.EOL();
3072  }
3073  if (m_libRSDriver) {
3074    strm.Printf("Runtime Driver discovered.");
3075    strm.EOL();
3076  }
3077  if (m_libRSCpuRef) {
3078    strm.Printf("CPU Reference Implementation discovered.");
3079    strm.EOL();
3080  }
3081
3082  if (m_runtimeHooks.size()) {
3083    strm.Printf("Runtime functions hooked:");
3084    strm.EOL();
3085    for (auto b : m_runtimeHooks) {
3086      strm.Indent(b.second->defn->name);
3087      strm.EOL();
3088    }
3089  } else {
3090    strm.Printf("Runtime is not hooked.");
3091    strm.EOL();
3092  }
3093}
3094
3095void RenderScriptRuntime::DumpContexts(Stream &strm) const {
3096  strm.Printf("Inferred RenderScript Contexts:");
3097  strm.EOL();
3098  strm.IndentMore();
3099
3100  std::map<addr_t, uint64_t> contextReferences;
3101
3102  // Iterate over all of the currently discovered scripts. Note: We cant push
3103  // or pop from m_scripts inside this loop or it may invalidate script.
3104  for (const auto &script : m_scripts) {
3105    if (!script->context.isValid())
3106      continue;
3107    lldb::addr_t context = *script->context;
3108
3109    if (contextReferences.find(context) != contextReferences.end()) {
3110      contextReferences[context]++;
3111    } else {
3112      contextReferences[context] = 1;
3113    }
3114  }
3115
3116  for (const auto &cRef : contextReferences) {
3117    strm.Printf("Context 0x%" PRIx64 ": %" PRIu64 " script instances",
3118                cRef.first, cRef.second);
3119    strm.EOL();
3120  }
3121  strm.IndentLess();
3122}
3123
3124void RenderScriptRuntime::DumpKernels(Stream &strm) const {
3125  strm.Printf("RenderScript Kernels:");
3126  strm.EOL();
3127  strm.IndentMore();
3128  for (const auto &module : m_rsmodules) {
3129    strm.Printf("Resource '%s':", module->m_resname.c_str());
3130    strm.EOL();
3131    for (const auto &kernel : module->m_kernels) {
3132      strm.Indent(kernel.m_name.AsCString());
3133      strm.EOL();
3134    }
3135  }
3136  strm.IndentLess();
3137}
3138
3139RenderScriptRuntime::AllocationDetails *
3140RenderScriptRuntime::FindAllocByID(Stream &strm, const uint32_t alloc_id) {
3141  AllocationDetails *alloc = nullptr;
3142
3143  // See if we can find allocation using id as an index;
3144  if (alloc_id <= m_allocations.size() && alloc_id != 0 &&
3145      m_allocations[alloc_id - 1]->id == alloc_id) {
3146    alloc = m_allocations[alloc_id - 1].get();
3147    return alloc;
3148  }
3149
3150  // Fallback to searching
3151  for (const auto &a : m_allocations) {
3152    if (a->id == alloc_id) {
3153      alloc = a.get();
3154      break;
3155    }
3156  }
3157
3158  if (alloc == nullptr) {
3159    strm.Printf("Error: Couldn't find allocation with id matching %" PRIu32,
3160                alloc_id);
3161    strm.EOL();
3162  }
3163
3164  return alloc;
3165}
3166
3167// Prints the contents of an allocation to the output stream, which may be a
3168// file
3169bool RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame *frame_ptr,
3170                                         const uint32_t id) {
3171  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
3172
3173  // Check we can find the desired allocation
3174  AllocationDetails *alloc = FindAllocByID(strm, id);
3175  if (!alloc)
3176    return false; // FindAllocByID() will print error message for us here
3177
3178  LLDB_LOGF(log, "%s - found allocation 0x%" PRIx64, __FUNCTION__,
3179            *alloc->address.get());
3180
3181  // Check we have information about the allocation, if not calculate it
3182  if (alloc->ShouldRefresh()) {
3183    LLDB_LOGF(log, "%s - allocation details not calculated yet, jitting info.",
3184              __FUNCTION__);
3185
3186    // JIT all the allocation information
3187    if (!RefreshAllocation(alloc, frame_ptr)) {
3188      strm.Printf("Error: Couldn't JIT allocation details");
3189      strm.EOL();
3190      return false;
3191    }
3192  }
3193
3194  // Establish format and size of each data element
3195  const uint32_t vec_size = *alloc->element.type_vec_size.get();
3196  const Element::DataType type = *alloc->element.type.get();
3197
3198  assert(type >= Element::RS_TYPE_NONE && type <= Element::RS_TYPE_FONT &&
3199         "Invalid allocation type");
3200
3201  lldb::Format format;
3202  if (type >= Element::RS_TYPE_ELEMENT)
3203    format = eFormatHex;
3204  else
3205    format = vec_size == 1
3206                 ? static_cast<lldb::Format>(
3207                       AllocationDetails::RSTypeToFormat[type][eFormatSingle])
3208                 : static_cast<lldb::Format>(
3209                       AllocationDetails::RSTypeToFormat[type][eFormatVector]);
3210
3211  const uint32_t data_size = *alloc->element.datum_size.get();
3212
3213  LLDB_LOGF(log, "%s - element size %" PRIu32 " bytes, including padding",
3214            __FUNCTION__, data_size);
3215
3216  // Allocate a buffer to copy data into
3217  std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr);
3218  if (!buffer) {
3219    strm.Printf("Error: Couldn't read allocation data");
3220    strm.EOL();
3221    return false;
3222  }
3223
3224  // Calculate stride between rows as there may be padding at end of rows since
3225  // allocated memory is 16-byte aligned
3226  if (!alloc->stride.isValid()) {
3227    if (alloc->dimension.get()->dim_2 == 0) // We only have one dimension
3228      alloc->stride = 0;
3229    else if (!JITAllocationStride(alloc, frame_ptr)) {
3230      strm.Printf("Error: Couldn't calculate allocation row stride");
3231      strm.EOL();
3232      return false;
3233    }
3234  }
3235  const uint32_t stride = *alloc->stride.get();
3236  const uint32_t size = *alloc->size.get(); // Size of whole allocation
3237  const uint32_t padding =
3238      alloc->element.padding.isValid() ? *alloc->element.padding.get() : 0;
3239  LLDB_LOGF(log,
3240            "%s - stride %" PRIu32 " bytes, size %" PRIu32
3241            " bytes, padding %" PRIu32,
3242            __FUNCTION__, stride, size, padding);
3243
3244  // Find dimensions used to index loops, so need to be non-zero
3245  uint32_t dim_x = alloc->dimension.get()->dim_1;
3246  dim_x = dim_x == 0 ? 1 : dim_x;
3247
3248  uint32_t dim_y = alloc->dimension.get()->dim_2;
3249  dim_y = dim_y == 0 ? 1 : dim_y;
3250
3251  uint32_t dim_z = alloc->dimension.get()->dim_3;
3252  dim_z = dim_z == 0 ? 1 : dim_z;
3253
3254  // Use data extractor to format output
3255  const uint32_t target_ptr_size =
3256      GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
3257  DataExtractor alloc_data(buffer.get(), size, GetProcess()->GetByteOrder(),
3258                           target_ptr_size);
3259
3260  uint32_t offset = 0;   // Offset in buffer to next element to be printed
3261  uint32_t prev_row = 0; // Offset to the start of the previous row
3262
3263  // Iterate over allocation dimensions, printing results to user
3264  strm.Printf("Data (X, Y, Z):");
3265  for (uint32_t z = 0; z < dim_z; ++z) {
3266    for (uint32_t y = 0; y < dim_y; ++y) {
3267      // Use stride to index start of next row.
3268      if (!(y == 0 && z == 0))
3269        offset = prev_row + stride;
3270      prev_row = offset;
3271
3272      // Print each element in the row individually
3273      for (uint32_t x = 0; x < dim_x; ++x) {
3274        strm.Printf("\n(%" PRIu32 ", %" PRIu32 ", %" PRIu32 ") = ", x, y, z);
3275        if ((type == Element::RS_TYPE_NONE) &&
3276            (alloc->element.children.size() > 0) &&
3277            (alloc->element.type_name != Element::GetFallbackStructName())) {
3278          // Here we are dumping an Element of struct type. This is done using
3279          // expression evaluation with the name of the struct type and pointer
3280          // to element. Don't print the name of the resulting expression,
3281          // since this will be '$[0-9]+'
3282          DumpValueObjectOptions expr_options;
3283          expr_options.SetHideName(true);
3284
3285          // Setup expression as dereferencing a pointer cast to element
3286          // address.
3287          char expr_char_buffer[jit_max_expr_size];
3288          int written =
3289              snprintf(expr_char_buffer, jit_max_expr_size, "*(%s*) 0x%" PRIx64,
3290                       alloc->element.type_name.AsCString(),
3291                       *alloc->data_ptr.get() + offset);
3292
3293          if (written < 0 || written >= jit_max_expr_size) {
3294            LLDB_LOGF(log, "%s - error in snprintf().", __FUNCTION__);
3295            continue;
3296          }
3297
3298          // Evaluate expression
3299          ValueObjectSP expr_result;
3300          GetProcess()->GetTarget().EvaluateExpression(expr_char_buffer,
3301                                                       frame_ptr, expr_result);
3302
3303          // Print the results to our stream.
3304          expr_result->Dump(strm, expr_options);
3305        } else {
3306          DumpDataExtractor(alloc_data, &strm, offset, format,
3307                            data_size - padding, 1, 1, LLDB_INVALID_ADDRESS, 0,
3308                            0);
3309        }
3310        offset += data_size;
3311      }
3312    }
3313  }
3314  strm.EOL();
3315
3316  return true;
3317}
3318
3319// Function recalculates all our cached information about allocations by
3320// jitting the RS runtime regarding each allocation we know about. Returns true
3321// if all allocations could be recomputed, false otherwise.
3322bool RenderScriptRuntime::RecomputeAllAllocations(Stream &strm,
3323                                                  StackFrame *frame_ptr) {
3324  bool success = true;
3325  for (auto &alloc : m_allocations) {
3326    // JIT current allocation information
3327    if (!RefreshAllocation(alloc.get(), frame_ptr)) {
3328      strm.Printf("Error: Couldn't evaluate details for allocation %" PRIu32
3329                  "\n",
3330                  alloc->id);
3331      success = false;
3332    }
3333  }
3334
3335  if (success)
3336    strm.Printf("All allocations successfully recomputed");
3337  strm.EOL();
3338
3339  return success;
3340}
3341
3342// Prints information regarding currently loaded allocations. These details are
3343// gathered by jitting the runtime, which has as latency. Index parameter
3344// specifies a single allocation ID to print, or a zero value to print them all
3345void RenderScriptRuntime::ListAllocations(Stream &strm, StackFrame *frame_ptr,
3346                                          const uint32_t index) {
3347  strm.Printf("RenderScript Allocations:");
3348  strm.EOL();
3349  strm.IndentMore();
3350
3351  for (auto &alloc : m_allocations) {
3352    // index will only be zero if we want to print all allocations
3353    if (index != 0 && index != alloc->id)
3354      continue;
3355
3356    // JIT current allocation information
3357    if (alloc->ShouldRefresh() && !RefreshAllocation(alloc.get(), frame_ptr)) {
3358      strm.Printf("Error: Couldn't evaluate details for allocation %" PRIu32,
3359                  alloc->id);
3360      strm.EOL();
3361      continue;
3362    }
3363
3364    strm.Printf("%" PRIu32 ":", alloc->id);
3365    strm.EOL();
3366    strm.IndentMore();
3367
3368    strm.Indent("Context: ");
3369    if (!alloc->context.isValid())
3370      strm.Printf("unknown\n");
3371    else
3372      strm.Printf("0x%" PRIx64 "\n", *alloc->context.get());
3373
3374    strm.Indent("Address: ");
3375    if (!alloc->address.isValid())
3376      strm.Printf("unknown\n");
3377    else
3378      strm.Printf("0x%" PRIx64 "\n", *alloc->address.get());
3379
3380    strm.Indent("Data pointer: ");
3381    if (!alloc->data_ptr.isValid())
3382      strm.Printf("unknown\n");
3383    else
3384      strm.Printf("0x%" PRIx64 "\n", *alloc->data_ptr.get());
3385
3386    strm.Indent("Dimensions: ");
3387    if (!alloc->dimension.isValid())
3388      strm.Printf("unknown\n");
3389    else
3390      strm.Printf("(%" PRId32 ", %" PRId32 ", %" PRId32 ")\n",
3391                  alloc->dimension.get()->dim_1, alloc->dimension.get()->dim_2,
3392                  alloc->dimension.get()->dim_3);
3393
3394    strm.Indent("Data Type: ");
3395    if (!alloc->element.type.isValid() ||
3396        !alloc->element.type_vec_size.isValid())
3397      strm.Printf("unknown\n");
3398    else {
3399      const int vector_size = *alloc->element.type_vec_size.get();
3400      Element::DataType type = *alloc->element.type.get();
3401
3402      if (!alloc->element.type_name.IsEmpty())
3403        strm.Printf("%s\n", alloc->element.type_name.AsCString());
3404      else {
3405        // Enum value isn't monotonous, so doesn't always index
3406        // RsDataTypeToString array
3407        if (type >= Element::RS_TYPE_ELEMENT && type <= Element::RS_TYPE_FONT)
3408          type =
3409              static_cast<Element::DataType>((type - Element::RS_TYPE_ELEMENT) +
3410                                             Element::RS_TYPE_MATRIX_2X2 + 1);
3411
3412        if (type >= (sizeof(AllocationDetails::RsDataTypeToString) /
3413                     sizeof(AllocationDetails::RsDataTypeToString[0])) ||
3414            vector_size > 4 || vector_size < 1)
3415          strm.Printf("invalid type\n");
3416        else
3417          strm.Printf(
3418              "%s\n",
3419              AllocationDetails::RsDataTypeToString[static_cast<uint32_t>(type)]
3420                                                   [vector_size - 1]);
3421      }
3422    }
3423
3424    strm.Indent("Data Kind: ");
3425    if (!alloc->element.type_kind.isValid())
3426      strm.Printf("unknown\n");
3427    else {
3428      const Element::DataKind kind = *alloc->element.type_kind.get();
3429      if (kind < Element::RS_KIND_USER || kind > Element::RS_KIND_PIXEL_YUV)
3430        strm.Printf("invalid kind\n");
3431      else
3432        strm.Printf(
3433            "%s\n",
3434            AllocationDetails::RsDataKindToString[static_cast<uint32_t>(kind)]);
3435    }
3436
3437    strm.EOL();
3438    strm.IndentLess();
3439  }
3440  strm.IndentLess();
3441}
3442
3443// Set breakpoints on every kernel found in RS module
3444void RenderScriptRuntime::BreakOnModuleKernels(
3445    const RSModuleDescriptorSP rsmodule_sp) {
3446  for (const auto &kernel : rsmodule_sp->m_kernels) {
3447    // Don't set breakpoint on 'root' kernel
3448    if (strcmp(kernel.m_name.AsCString(), "root") == 0)
3449      continue;
3450
3451    CreateKernelBreakpoint(kernel.m_name);
3452  }
3453}
3454
3455// Method is internally called by the 'kernel breakpoint all' command to enable
3456// or disable breaking on all kernels. When do_break is true we want to enable
3457// this functionality. When do_break is false we want to disable it.
3458void RenderScriptRuntime::SetBreakAllKernels(bool do_break, TargetSP target) {
3459  Log *log(
3460      GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
3461
3462  InitSearchFilter(target);
3463
3464  // Set breakpoints on all the kernels
3465  if (do_break && !m_breakAllKernels) {
3466    m_breakAllKernels = true;
3467
3468    for (const auto &module : m_rsmodules)
3469      BreakOnModuleKernels(module);
3470
3471    LLDB_LOGF(log,
3472              "%s(True) - breakpoints set on all currently loaded kernels.",
3473              __FUNCTION__);
3474  } else if (!do_break &&
3475             m_breakAllKernels) // Breakpoints won't be set on any new kernels.
3476  {
3477    m_breakAllKernels = false;
3478
3479    LLDB_LOGF(log, "%s(False) - breakpoints no longer automatically set.",
3480              __FUNCTION__);
3481  }
3482}
3483
3484// Given the name of a kernel this function creates a breakpoint using our own
3485// breakpoint resolver, and returns the Breakpoint shared pointer.
3486BreakpointSP
3487RenderScriptRuntime::CreateKernelBreakpoint(ConstString name) {
3488  Log *log(
3489      GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
3490
3491  if (!m_filtersp) {
3492    LLDB_LOGF(log, "%s - error, no breakpoint search filter set.",
3493              __FUNCTION__);
3494    return nullptr;
3495  }
3496
3497  BreakpointResolverSP resolver_sp(new RSBreakpointResolver(nullptr, name));
3498  Target &target = GetProcess()->GetTarget();
3499  BreakpointSP bp = target.CreateBreakpoint(
3500      m_filtersp, resolver_sp, false, false, false);
3501
3502  // Give RS breakpoints a specific name, so the user can manipulate them as a
3503  // group.
3504  Status err;
3505  target.AddNameToBreakpoint(bp, "RenderScriptKernel", err);
3506  if (err.Fail() && log)
3507    LLDB_LOGF(log, "%s - error setting break name, '%s'.", __FUNCTION__,
3508              err.AsCString());
3509
3510  return bp;
3511}
3512
3513BreakpointSP
3514RenderScriptRuntime::CreateReductionBreakpoint(ConstString name,
3515                                               int kernel_types) {
3516  Log *log(
3517      GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
3518
3519  if (!m_filtersp) {
3520    LLDB_LOGF(log, "%s - error, no breakpoint search filter set.",
3521              __FUNCTION__);
3522    return nullptr;
3523  }
3524
3525  BreakpointResolverSP resolver_sp(new RSReduceBreakpointResolver(
3526      nullptr, name, &m_rsmodules, kernel_types));
3527  Target &target = GetProcess()->GetTarget();
3528  BreakpointSP bp = target.CreateBreakpoint(
3529      m_filtersp, resolver_sp, false, false, false);
3530
3531  // Give RS breakpoints a specific name, so the user can manipulate them as a
3532  // group.
3533  Status err;
3534  target.AddNameToBreakpoint(bp, "RenderScriptReduction", err);
3535  if (err.Fail() && log)
3536    LLDB_LOGF(log, "%s - error setting break name, '%s'.", __FUNCTION__,
3537              err.AsCString());
3538
3539  return bp;
3540}
3541
3542// Given an expression for a variable this function tries to calculate the
3543// variable's value. If this is possible it returns true and sets the uint64_t
3544// parameter to the variables unsigned value. Otherwise function returns false.
3545bool RenderScriptRuntime::GetFrameVarAsUnsigned(const StackFrameSP frame_sp,
3546                                                const char *var_name,
3547                                                uint64_t &val) {
3548  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE));
3549  Status err;
3550  VariableSP var_sp;
3551
3552  // Find variable in stack frame
3553  ValueObjectSP value_sp(frame_sp->GetValueForVariableExpressionPath(
3554      var_name, eNoDynamicValues,
3555      StackFrame::eExpressionPathOptionCheckPtrVsMember |
3556          StackFrame::eExpressionPathOptionsAllowDirectIVarAccess,
3557      var_sp, err));
3558  if (!err.Success()) {
3559    LLDB_LOGF(log, "%s - error, couldn't find '%s' in frame", __FUNCTION__,
3560              var_name);
3561    return false;
3562  }
3563
3564  // Find the uint32_t value for the variable
3565  bool success = false;
3566  val = value_sp->GetValueAsUnsigned(0, &success);
3567  if (!success) {
3568    LLDB_LOGF(log, "%s - error, couldn't parse '%s' as an uint32_t.",
3569              __FUNCTION__, var_name);
3570    return false;
3571  }
3572
3573  return true;
3574}
3575
3576// Function attempts to find the current coordinate of a kernel invocation by
3577// investigating the values of frame variables in the .expand function. These
3578// coordinates are returned via the coord array reference parameter. Returns
3579// true if the coordinates could be found, and false otherwise.
3580bool RenderScriptRuntime::GetKernelCoordinate(RSCoordinate &coord,
3581                                              Thread *thread_ptr) {
3582  static const char *const x_expr = "rsIndex";
3583  static const char *const y_expr = "p->current.y";
3584  static const char *const z_expr = "p->current.z";
3585
3586  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE));
3587
3588  if (!thread_ptr) {
3589    LLDB_LOGF(log, "%s - Error, No thread pointer", __FUNCTION__);
3590
3591    return false;
3592  }
3593
3594  // Walk the call stack looking for a function whose name has the suffix
3595  // '.expand' and contains the variables we're looking for.
3596  for (uint32_t i = 0; i < thread_ptr->GetStackFrameCount(); ++i) {
3597    if (!thread_ptr->SetSelectedFrameByIndex(i))
3598      continue;
3599
3600    StackFrameSP frame_sp = thread_ptr->GetSelectedFrame();
3601    if (!frame_sp)
3602      continue;
3603
3604    // Find the function name
3605    const SymbolContext sym_ctx =
3606        frame_sp->GetSymbolContext(eSymbolContextFunction);
3607    const ConstString func_name = sym_ctx.GetFunctionName();
3608    if (!func_name)
3609      continue;
3610
3611    LLDB_LOGF(log, "%s - Inspecting function '%s'", __FUNCTION__,
3612              func_name.GetCString());
3613
3614    // Check if function name has .expand suffix
3615    if (!func_name.GetStringRef().endswith(".expand"))
3616      continue;
3617
3618    LLDB_LOGF(log, "%s - Found .expand function '%s'", __FUNCTION__,
3619              func_name.GetCString());
3620
3621    // Get values for variables in .expand frame that tell us the current
3622    // kernel invocation
3623    uint64_t x, y, z;
3624    bool found = GetFrameVarAsUnsigned(frame_sp, x_expr, x) &&
3625                 GetFrameVarAsUnsigned(frame_sp, y_expr, y) &&
3626                 GetFrameVarAsUnsigned(frame_sp, z_expr, z);
3627
3628    if (found) {
3629      // The RenderScript runtime uses uint32_t for these vars. If they're not
3630      // within bounds, our frame parsing is garbage
3631      assert(x <= UINT32_MAX && y <= UINT32_MAX && z <= UINT32_MAX);
3632      coord.x = (uint32_t)x;
3633      coord.y = (uint32_t)y;
3634      coord.z = (uint32_t)z;
3635      return true;
3636    }
3637  }
3638  return false;
3639}
3640
3641// Callback when a kernel breakpoint hits and we're looking for a specific
3642// coordinate. Baton parameter contains a pointer to the target coordinate we
3643// want to break on. Function then checks the .expand frame for the current
3644// coordinate and breaks to user if it matches. Parameter 'break_id' is the id
3645// of the Breakpoint which made the callback. Parameter 'break_loc_id' is the
3646// id for the BreakpointLocation which was hit, a single logical breakpoint can
3647// have multiple addresses.
3648bool RenderScriptRuntime::KernelBreakpointHit(void *baton,
3649                                              StoppointCallbackContext *ctx,
3650                                              user_id_t break_id,
3651                                              user_id_t break_loc_id) {
3652  Log *log(
3653      GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
3654
3655  assert(baton &&
3656         "Error: null baton in conditional kernel breakpoint callback");
3657
3658  // Coordinate we want to stop on
3659  RSCoordinate target_coord = *static_cast<RSCoordinate *>(baton);
3660
3661  LLDB_LOGF(log, "%s - Break ID %" PRIu64 ", " FMT_COORD, __FUNCTION__,
3662            break_id, target_coord.x, target_coord.y, target_coord.z);
3663
3664  // Select current thread
3665  ExecutionContext context(ctx->exe_ctx_ref);
3666  Thread *thread_ptr = context.GetThreadPtr();
3667  assert(thread_ptr && "Null thread pointer");
3668
3669  // Find current kernel invocation from .expand frame variables
3670  RSCoordinate current_coord{};
3671  if (!GetKernelCoordinate(current_coord, thread_ptr)) {
3672    LLDB_LOGF(log, "%s - Error, couldn't select .expand stack frame",
3673              __FUNCTION__);
3674    return false;
3675  }
3676
3677  LLDB_LOGF(log, "%s - " FMT_COORD, __FUNCTION__, current_coord.x,
3678            current_coord.y, current_coord.z);
3679
3680  // Check if the current kernel invocation coordinate matches our target
3681  // coordinate
3682  if (target_coord == current_coord) {
3683    LLDB_LOGF(log, "%s, BREAKING " FMT_COORD, __FUNCTION__, current_coord.x,
3684              current_coord.y, current_coord.z);
3685
3686    BreakpointSP breakpoint_sp =
3687        context.GetTargetPtr()->GetBreakpointByID(break_id);
3688    assert(breakpoint_sp != nullptr &&
3689           "Error: Couldn't find breakpoint matching break id for callback");
3690    breakpoint_sp->SetEnabled(false); // Optimise since conditional breakpoint
3691                                      // should only be hit once.
3692    return true;
3693  }
3694
3695  // No match on coordinate
3696  return false;
3697}
3698
3699void RenderScriptRuntime::SetConditional(BreakpointSP bp, Stream &messages,
3700                                         const RSCoordinate &coord) {
3701  messages.Printf("Conditional kernel breakpoint on coordinate " FMT_COORD,
3702                  coord.x, coord.y, coord.z);
3703  messages.EOL();
3704
3705  // Allocate memory for the baton, and copy over coordinate
3706  RSCoordinate *baton = new RSCoordinate(coord);
3707
3708  // Create a callback that will be invoked every time the breakpoint is hit.
3709  // The baton object passed to the handler is the target coordinate we want to
3710  // break on.
3711  bp->SetCallback(KernelBreakpointHit, baton, true);
3712
3713  // Store a shared pointer to the baton, so the memory will eventually be
3714  // cleaned up after destruction
3715  m_conditional_breaks[bp->GetID()] = std::unique_ptr<RSCoordinate>(baton);
3716}
3717
3718// Tries to set a breakpoint on the start of a kernel, resolved using the
3719// kernel name. Argument 'coords', represents a three dimensional coordinate
3720// which can be used to specify a single kernel instance to break on. If this
3721// is set then we add a callback to the breakpoint.
3722bool RenderScriptRuntime::PlaceBreakpointOnKernel(TargetSP target,
3723                                                  Stream &messages,
3724                                                  const char *name,
3725                                                  const RSCoordinate *coord) {
3726  if (!name)
3727    return false;
3728
3729  InitSearchFilter(target);
3730
3731  ConstString kernel_name(name);
3732  BreakpointSP bp = CreateKernelBreakpoint(kernel_name);
3733  if (!bp)
3734    return false;
3735
3736  // We have a conditional breakpoint on a specific coordinate
3737  if (coord)
3738    SetConditional(bp, messages, *coord);
3739
3740  bp->GetDescription(&messages, lldb::eDescriptionLevelInitial, false);
3741
3742  return true;
3743}
3744
3745BreakpointSP
3746RenderScriptRuntime::CreateScriptGroupBreakpoint(ConstString name,
3747                                                 bool stop_on_all) {
3748  Log *log(
3749      GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
3750
3751  if (!m_filtersp) {
3752    LLDB_LOGF(log, "%s - error, no breakpoint search filter set.",
3753              __FUNCTION__);
3754    return nullptr;
3755  }
3756
3757  BreakpointResolverSP resolver_sp(new RSScriptGroupBreakpointResolver(
3758      nullptr, name, m_scriptGroups, stop_on_all));
3759  Target &target = GetProcess()->GetTarget();
3760  BreakpointSP bp = target.CreateBreakpoint(
3761      m_filtersp, resolver_sp, false, false, false);
3762  // Give RS breakpoints a specific name, so the user can manipulate them as a
3763  // group.
3764  Status err;
3765  target.AddNameToBreakpoint(bp, name.GetCString(), err);
3766  if (err.Fail() && log)
3767    LLDB_LOGF(log, "%s - error setting break name, '%s'.", __FUNCTION__,
3768              err.AsCString());
3769  // ask the breakpoint to resolve itself
3770  bp->ResolveBreakpoint();
3771  return bp;
3772}
3773
3774bool RenderScriptRuntime::PlaceBreakpointOnScriptGroup(TargetSP target,
3775                                                       Stream &strm,
3776                                                       ConstString name,
3777                                                       bool multi) {
3778  InitSearchFilter(target);
3779  BreakpointSP bp = CreateScriptGroupBreakpoint(name, multi);
3780  if (bp)
3781    bp->GetDescription(&strm, lldb::eDescriptionLevelInitial, false);
3782  return bool(bp);
3783}
3784
3785bool RenderScriptRuntime::PlaceBreakpointOnReduction(TargetSP target,
3786                                                     Stream &messages,
3787                                                     const char *reduce_name,
3788                                                     const RSCoordinate *coord,
3789                                                     int kernel_types) {
3790  if (!reduce_name)
3791    return false;
3792
3793  InitSearchFilter(target);
3794  BreakpointSP bp =
3795      CreateReductionBreakpoint(ConstString(reduce_name), kernel_types);
3796  if (!bp)
3797    return false;
3798
3799  if (coord)
3800    SetConditional(bp, messages, *coord);
3801
3802  bp->GetDescription(&messages, lldb::eDescriptionLevelInitial, false);
3803
3804  return true;
3805}
3806
3807void RenderScriptRuntime::DumpModules(Stream &strm) const {
3808  strm.Printf("RenderScript Modules:");
3809  strm.EOL();
3810  strm.IndentMore();
3811  for (const auto &module : m_rsmodules) {
3812    module->Dump(strm);
3813  }
3814  strm.IndentLess();
3815}
3816
3817RenderScriptRuntime::ScriptDetails *
3818RenderScriptRuntime::LookUpScript(addr_t address, bool create) {
3819  for (const auto &s : m_scripts) {
3820    if (s->script.isValid())
3821      if (*s->script == address)
3822        return s.get();
3823  }
3824  if (create) {
3825    std::unique_ptr<ScriptDetails> s(new ScriptDetails);
3826    s->script = address;
3827    m_scripts.push_back(std::move(s));
3828    return m_scripts.back().get();
3829  }
3830  return nullptr;
3831}
3832
3833RenderScriptRuntime::AllocationDetails *
3834RenderScriptRuntime::LookUpAllocation(addr_t address) {
3835  for (const auto &a : m_allocations) {
3836    if (a->address.isValid())
3837      if (*a->address == address)
3838        return a.get();
3839  }
3840  return nullptr;
3841}
3842
3843RenderScriptRuntime::AllocationDetails *
3844RenderScriptRuntime::CreateAllocation(addr_t address) {
3845  Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
3846
3847  // Remove any previous allocation which contains the same address
3848  auto it = m_allocations.begin();
3849  while (it != m_allocations.end()) {
3850    if (*((*it)->address) == address) {
3851      LLDB_LOGF(log, "%s - Removing allocation id: %d, address: 0x%" PRIx64,
3852                __FUNCTION__, (*it)->id, address);
3853
3854      it = m_allocations.erase(it);
3855    } else {
3856      it++;
3857    }
3858  }
3859
3860  std::unique_ptr<AllocationDetails> a(new AllocationDetails);
3861  a->address = address;
3862  m_allocations.push_back(std::move(a));
3863  return m_allocations.back().get();
3864}
3865
3866bool RenderScriptRuntime::ResolveKernelName(lldb::addr_t kernel_addr,
3867                                            ConstString &name) {
3868  Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS);
3869
3870  Target &target = GetProcess()->GetTarget();
3871  Address resolved;
3872  // RenderScript module
3873  if (!target.GetSectionLoadList().ResolveLoadAddress(kernel_addr, resolved)) {
3874    LLDB_LOGF(log, "%s: unable to resolve 0x%" PRIx64 " to a loaded symbol",
3875              __FUNCTION__, kernel_addr);
3876    return false;
3877  }
3878
3879  Symbol *sym = resolved.CalculateSymbolContextSymbol();
3880  if (!sym)
3881    return false;
3882
3883  name = sym->GetName();
3884  assert(IsRenderScriptModule(resolved.CalculateSymbolContextModule()));
3885  LLDB_LOGF(log, "%s: 0x%" PRIx64 " resolved to the symbol '%s'", __FUNCTION__,
3886            kernel_addr, name.GetCString());
3887  return true;
3888}
3889
3890void RSModuleDescriptor::Dump(Stream &strm) const {
3891  int indent = strm.GetIndentLevel();
3892
3893  strm.Indent();
3894  m_module->GetFileSpec().Dump(strm.AsRawOstream());
3895  strm.Indent(m_module->GetNumCompileUnits() ? "Debug info loaded."
3896                                             : "Debug info does not exist.");
3897  strm.EOL();
3898  strm.IndentMore();
3899
3900  strm.Indent();
3901  strm.Printf("Globals: %" PRIu64, static_cast<uint64_t>(m_globals.size()));
3902  strm.EOL();
3903  strm.IndentMore();
3904  for (const auto &global : m_globals) {
3905    global.Dump(strm);
3906  }
3907  strm.IndentLess();
3908
3909  strm.Indent();
3910  strm.Printf("Kernels: %" PRIu64, static_cast<uint64_t>(m_kernels.size()));
3911  strm.EOL();
3912  strm.IndentMore();
3913  for (const auto &kernel : m_kernels) {
3914    kernel.Dump(strm);
3915  }
3916  strm.IndentLess();
3917
3918  strm.Indent();
3919  strm.Printf("Pragmas: %" PRIu64, static_cast<uint64_t>(m_pragmas.size()));
3920  strm.EOL();
3921  strm.IndentMore();
3922  for (const auto &key_val : m_pragmas) {
3923    strm.Indent();
3924    strm.Printf("%s: %s", key_val.first.c_str(), key_val.second.c_str());
3925    strm.EOL();
3926  }
3927  strm.IndentLess();
3928
3929  strm.Indent();
3930  strm.Printf("Reductions: %" PRIu64,
3931              static_cast<uint64_t>(m_reductions.size()));
3932  strm.EOL();
3933  strm.IndentMore();
3934  for (const auto &reduction : m_reductions) {
3935    reduction.Dump(strm);
3936  }
3937
3938  strm.SetIndentLevel(indent);
3939}
3940
3941void RSGlobalDescriptor::Dump(Stream &strm) const {
3942  strm.Indent(m_name.AsCString());
3943  VariableList var_list;
3944  m_module->m_module->FindGlobalVariables(m_name, nullptr, 1U, var_list);
3945  if (var_list.GetSize() == 1) {
3946    auto var = var_list.GetVariableAtIndex(0);
3947    auto type = var->GetType();
3948    if (type) {
3949      strm.Printf(" - ");
3950      type->DumpTypeName(&strm);
3951    } else {
3952      strm.Printf(" - Unknown Type");
3953    }
3954  } else {
3955    strm.Printf(" - variable identified, but not found in binary");
3956    const Symbol *s = m_module->m_module->FindFirstSymbolWithNameAndType(
3957        m_name, eSymbolTypeData);
3958    if (s) {
3959      strm.Printf(" (symbol exists) ");
3960    }
3961  }
3962
3963  strm.EOL();
3964}
3965
3966void RSKernelDescriptor::Dump(Stream &strm) const {
3967  strm.Indent(m_name.AsCString());
3968  strm.EOL();
3969}
3970
3971void RSReductionDescriptor::Dump(lldb_private::Stream &stream) const {
3972  stream.Indent(m_reduce_name.AsCString());
3973  stream.IndentMore();
3974  stream.EOL();
3975  stream.Indent();
3976  stream.Printf("accumulator: %s", m_accum_name.AsCString());
3977  stream.EOL();
3978  stream.Indent();
3979  stream.Printf("initializer: %s", m_init_name.AsCString());
3980  stream.EOL();
3981  stream.Indent();
3982  stream.Printf("combiner: %s", m_comb_name.AsCString());
3983  stream.EOL();
3984  stream.Indent();
3985  stream.Printf("outconverter: %s", m_outc_name.AsCString());
3986  stream.EOL();
3987  // XXX This is currently unspecified by RenderScript, and unused
3988  // stream.Indent();
3989  // stream.Printf("halter: '%s'", m_init_name.AsCString());
3990  // stream.EOL();
3991  stream.IndentLess();
3992}
3993
3994class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed {
3995public:
3996  CommandObjectRenderScriptRuntimeModuleDump(CommandInterpreter &interpreter)
3997      : CommandObjectParsed(
3998            interpreter, "renderscript module dump",
3999            "Dumps renderscript specific information for all modules.",
4000            "renderscript module dump",
4001            eCommandRequiresProcess | eCommandProcessMustBeLaunched) {}
4002
4003  ~CommandObjectRenderScriptRuntimeModuleDump() override = default;
4004
4005  bool DoExecute(Args &command, CommandReturnObject &result) override {
4006    RenderScriptRuntime *runtime = llvm::cast<RenderScriptRuntime>(
4007        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
4008            eLanguageTypeExtRenderScript));
4009    runtime->DumpModules(result.GetOutputStream());
4010    result.SetStatus(eReturnStatusSuccessFinishResult);
4011    return true;
4012  }
4013};
4014
4015class CommandObjectRenderScriptRuntimeModule : public CommandObjectMultiword {
4016public:
4017  CommandObjectRenderScriptRuntimeModule(CommandInterpreter &interpreter)
4018      : CommandObjectMultiword(interpreter, "renderscript module",
4019                               "Commands that deal with RenderScript modules.",
4020                               nullptr) {
4021    LoadSubCommand(
4022        "dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleDump(
4023                    interpreter)));
4024  }
4025
4026  ~CommandObjectRenderScriptRuntimeModule() override = default;
4027};
4028
4029class CommandObjectRenderScriptRuntimeKernelList : public CommandObjectParsed {
4030public:
4031  CommandObjectRenderScriptRuntimeKernelList(CommandInterpreter &interpreter)
4032      : CommandObjectParsed(
4033            interpreter, "renderscript kernel list",
4034            "Lists renderscript kernel names and associated script resources.",
4035            "renderscript kernel list",
4036            eCommandRequiresProcess | eCommandProcessMustBeLaunched) {}
4037
4038  ~CommandObjectRenderScriptRuntimeKernelList() override = default;
4039
4040  bool DoExecute(Args &command, CommandReturnObject &result) override {
4041    RenderScriptRuntime *runtime = llvm::cast<RenderScriptRuntime>(
4042        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
4043            eLanguageTypeExtRenderScript));
4044    runtime->DumpKernels(result.GetOutputStream());
4045    result.SetStatus(eReturnStatusSuccessFinishResult);
4046    return true;
4047  }
4048};
4049
4050static constexpr OptionDefinition g_renderscript_reduction_bp_set_options[] = {
4051    {LLDB_OPT_SET_1, false, "function-role", 't',
4052     OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOneLiner,
4053     "Break on a comma separated set of reduction kernel types "
4054     "(accumulator,outcoverter,combiner,initializer"},
4055    {LLDB_OPT_SET_1, false, "coordinate", 'c', OptionParser::eRequiredArgument,
4056     nullptr, {}, 0, eArgTypeValue,
4057     "Set a breakpoint on a single invocation of the kernel with specified "
4058     "coordinate.\n"
4059     "Coordinate takes the form 'x[,y][,z] where x,y,z are positive "
4060     "integers representing kernel dimensions. "
4061     "Any unset dimensions will be defaulted to zero."}};
4062
4063class CommandObjectRenderScriptRuntimeReductionBreakpointSet
4064    : public CommandObjectParsed {
4065public:
4066  CommandObjectRenderScriptRuntimeReductionBreakpointSet(
4067      CommandInterpreter &interpreter)
4068      : CommandObjectParsed(
4069            interpreter, "renderscript reduction breakpoint set",
4070            "Set a breakpoint on named RenderScript general reductions",
4071            "renderscript reduction breakpoint set  <kernel_name> [-t "
4072            "<reduction_kernel_type,...>]",
4073            eCommandRequiresProcess | eCommandProcessMustBeLaunched |
4074                eCommandProcessMustBePaused),
4075        m_options(){};
4076
4077  class CommandOptions : public Options {
4078  public:
4079    CommandOptions()
4080        : Options(),
4081          m_kernel_types(RSReduceBreakpointResolver::eKernelTypeAll) {}
4082
4083    ~CommandOptions() override = default;
4084
4085    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
4086                          ExecutionContext *exe_ctx) override {
4087      Status err;
4088      StreamString err_str;
4089      const int short_option = m_getopt_table[option_idx].val;
4090      switch (short_option) {
4091      case 't':
4092        if (!ParseReductionTypes(option_arg, err_str))
4093          err.SetErrorStringWithFormat(
4094              "Unable to deduce reduction types for %s: %s",
4095              option_arg.str().c_str(), err_str.GetData());
4096        break;
4097      case 'c': {
4098        auto coord = RSCoordinate{};
4099        if (!ParseCoordinate(option_arg, coord))
4100          err.SetErrorStringWithFormat("unable to parse coordinate for %s",
4101                                       option_arg.str().c_str());
4102        else {
4103          m_have_coord = true;
4104          m_coord = coord;
4105        }
4106        break;
4107      }
4108      default:
4109        err.SetErrorStringWithFormat("Invalid option '-%c'", short_option);
4110      }
4111      return err;
4112    }
4113
4114    void OptionParsingStarting(ExecutionContext *exe_ctx) override {
4115      m_have_coord = false;
4116    }
4117
4118    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
4119      return llvm::makeArrayRef(g_renderscript_reduction_bp_set_options);
4120    }
4121
4122    bool ParseReductionTypes(llvm::StringRef option_val,
4123                             StreamString &err_str) {
4124      m_kernel_types = RSReduceBreakpointResolver::eKernelTypeNone;
4125      const auto reduce_name_to_type = [](llvm::StringRef name) -> int {
4126        return llvm::StringSwitch<int>(name)
4127            .Case("accumulator", RSReduceBreakpointResolver::eKernelTypeAccum)
4128            .Case("initializer", RSReduceBreakpointResolver::eKernelTypeInit)
4129            .Case("outconverter", RSReduceBreakpointResolver::eKernelTypeOutC)
4130            .Case("combiner", RSReduceBreakpointResolver::eKernelTypeComb)
4131            .Case("all", RSReduceBreakpointResolver::eKernelTypeAll)
4132            // Currently not exposed by the runtime
4133            // .Case("halter", RSReduceBreakpointResolver::eKernelTypeHalter)
4134            .Default(0);
4135      };
4136
4137      // Matching a comma separated list of known words is fairly
4138      // straightforward with PCRE, but we're using ERE, so we end up with a
4139      // little ugliness...
4140      RegularExpression match_type_list(
4141          llvm::StringRef("^([[:alpha:]]+)(,[[:alpha:]]+){0,4}$"));
4142
4143      assert(match_type_list.IsValid());
4144
4145      if (!match_type_list.Execute(option_val)) {
4146        err_str.PutCString(
4147            "a comma-separated list of kernel types is required");
4148        return false;
4149      }
4150
4151      // splitting on commas is much easier with llvm::StringRef than regex
4152      llvm::SmallVector<llvm::StringRef, 5> type_names;
4153      llvm::StringRef(option_val).split(type_names, ',');
4154
4155      for (const auto &name : type_names) {
4156        const int type = reduce_name_to_type(name);
4157        if (!type) {
4158          err_str.Printf("unknown kernel type name %s", name.str().c_str());
4159          return false;
4160        }
4161        m_kernel_types |= type;
4162      }
4163
4164      return true;
4165    }
4166
4167    int m_kernel_types;
4168    llvm::StringRef m_reduce_name;
4169    RSCoordinate m_coord;
4170    bool m_have_coord;
4171  };
4172
4173  Options *GetOptions() override { return &m_options; }
4174
4175  bool DoExecute(Args &command, CommandReturnObject &result) override {
4176    const size_t argc = command.GetArgumentCount();
4177    if (argc < 1) {
4178      result.AppendErrorWithFormat("'%s' takes 1 argument of reduction name, "
4179                                   "and an optional kernel type list",
4180                                   m_cmd_name.c_str());
4181      result.SetStatus(eReturnStatusFailed);
4182      return false;
4183    }
4184
4185    RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
4186        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
4187            eLanguageTypeExtRenderScript));
4188
4189    auto &outstream = result.GetOutputStream();
4190    auto name = command.GetArgumentAtIndex(0);
4191    auto &target = m_exe_ctx.GetTargetSP();
4192    auto coord = m_options.m_have_coord ? &m_options.m_coord : nullptr;
4193    if (!runtime->PlaceBreakpointOnReduction(target, outstream, name, coord,
4194                                             m_options.m_kernel_types)) {
4195      result.SetStatus(eReturnStatusFailed);
4196      result.AppendError("Error: unable to place breakpoint on reduction");
4197      return false;
4198    }
4199    result.AppendMessage("Breakpoint(s) created");
4200    result.SetStatus(eReturnStatusSuccessFinishResult);
4201    return true;
4202  }
4203
4204private:
4205  CommandOptions m_options;
4206};
4207
4208static constexpr OptionDefinition g_renderscript_kernel_bp_set_options[] = {
4209    {LLDB_OPT_SET_1, false, "coordinate", 'c', OptionParser::eRequiredArgument,
4210     nullptr, {}, 0, eArgTypeValue,
4211     "Set a breakpoint on a single invocation of the kernel with specified "
4212     "coordinate.\n"
4213     "Coordinate takes the form 'x[,y][,z] where x,y,z are positive "
4214     "integers representing kernel dimensions. "
4215     "Any unset dimensions will be defaulted to zero."}};
4216
4217class CommandObjectRenderScriptRuntimeKernelBreakpointSet
4218    : public CommandObjectParsed {
4219public:
4220  CommandObjectRenderScriptRuntimeKernelBreakpointSet(
4221      CommandInterpreter &interpreter)
4222      : CommandObjectParsed(
4223            interpreter, "renderscript kernel breakpoint set",
4224            "Sets a breakpoint on a renderscript kernel.",
4225            "renderscript kernel breakpoint set <kernel_name> [-c x,y,z]",
4226            eCommandRequiresProcess | eCommandProcessMustBeLaunched |
4227                eCommandProcessMustBePaused),
4228        m_options() {}
4229
4230  ~CommandObjectRenderScriptRuntimeKernelBreakpointSet() override = default;
4231
4232  Options *GetOptions() override { return &m_options; }
4233
4234  class CommandOptions : public Options {
4235  public:
4236    CommandOptions() : Options() {}
4237
4238    ~CommandOptions() override = default;
4239
4240    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
4241                          ExecutionContext *exe_ctx) override {
4242      Status err;
4243      const int short_option = m_getopt_table[option_idx].val;
4244
4245      switch (short_option) {
4246      case 'c': {
4247        auto coord = RSCoordinate{};
4248        if (!ParseCoordinate(option_arg, coord))
4249          err.SetErrorStringWithFormat(
4250              "Couldn't parse coordinate '%s', should be in format 'x,y,z'.",
4251              option_arg.str().c_str());
4252        else {
4253          m_have_coord = true;
4254          m_coord = coord;
4255        }
4256        break;
4257      }
4258      default:
4259        err.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
4260        break;
4261      }
4262      return err;
4263    }
4264
4265    void OptionParsingStarting(ExecutionContext *exe_ctx) override {
4266      m_have_coord = false;
4267    }
4268
4269    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
4270      return llvm::makeArrayRef(g_renderscript_kernel_bp_set_options);
4271    }
4272
4273    RSCoordinate m_coord;
4274    bool m_have_coord;
4275  };
4276
4277  bool DoExecute(Args &command, CommandReturnObject &result) override {
4278    const size_t argc = command.GetArgumentCount();
4279    if (argc < 1) {
4280      result.AppendErrorWithFormat(
4281          "'%s' takes 1 argument of kernel name, and an optional coordinate.",
4282          m_cmd_name.c_str());
4283      result.SetStatus(eReturnStatusFailed);
4284      return false;
4285    }
4286
4287    RenderScriptRuntime *runtime = llvm::cast<RenderScriptRuntime>(
4288        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
4289            eLanguageTypeExtRenderScript));
4290
4291    auto &outstream = result.GetOutputStream();
4292    auto &target = m_exe_ctx.GetTargetSP();
4293    auto name = command.GetArgumentAtIndex(0);
4294    auto coord = m_options.m_have_coord ? &m_options.m_coord : nullptr;
4295    if (!runtime->PlaceBreakpointOnKernel(target, outstream, name, coord)) {
4296      result.SetStatus(eReturnStatusFailed);
4297      result.AppendErrorWithFormat(
4298          "Error: unable to set breakpoint on kernel '%s'", name);
4299      return false;
4300    }
4301
4302    result.AppendMessage("Breakpoint(s) created");
4303    result.SetStatus(eReturnStatusSuccessFinishResult);
4304    return true;
4305  }
4306
4307private:
4308  CommandOptions m_options;
4309};
4310
4311class CommandObjectRenderScriptRuntimeKernelBreakpointAll
4312    : public CommandObjectParsed {
4313public:
4314  CommandObjectRenderScriptRuntimeKernelBreakpointAll(
4315      CommandInterpreter &interpreter)
4316      : CommandObjectParsed(
4317            interpreter, "renderscript kernel breakpoint all",
4318            "Automatically sets a breakpoint on all renderscript kernels that "
4319            "are or will be loaded.\n"
4320            "Disabling option means breakpoints will no longer be set on any "
4321            "kernels loaded in the future, "
4322            "but does not remove currently set breakpoints.",
4323            "renderscript kernel breakpoint all <enable/disable>",
4324            eCommandRequiresProcess | eCommandProcessMustBeLaunched |
4325                eCommandProcessMustBePaused) {}
4326
4327  ~CommandObjectRenderScriptRuntimeKernelBreakpointAll() override = default;
4328
4329  bool DoExecute(Args &command, CommandReturnObject &result) override {
4330    const size_t argc = command.GetArgumentCount();
4331    if (argc != 1) {
4332      result.AppendErrorWithFormat(
4333          "'%s' takes 1 argument of 'enable' or 'disable'", m_cmd_name.c_str());
4334      result.SetStatus(eReturnStatusFailed);
4335      return false;
4336    }
4337
4338    RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
4339        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
4340            eLanguageTypeExtRenderScript));
4341
4342    bool do_break = false;
4343    const char *argument = command.GetArgumentAtIndex(0);
4344    if (strcmp(argument, "enable") == 0) {
4345      do_break = true;
4346      result.AppendMessage("Breakpoints will be set on all kernels.");
4347    } else if (strcmp(argument, "disable") == 0) {
4348      do_break = false;
4349      result.AppendMessage("Breakpoints will not be set on any new kernels.");
4350    } else {
4351      result.AppendErrorWithFormat(
4352          "Argument must be either 'enable' or 'disable'");
4353      result.SetStatus(eReturnStatusFailed);
4354      return false;
4355    }
4356
4357    runtime->SetBreakAllKernels(do_break, m_exe_ctx.GetTargetSP());
4358
4359    result.SetStatus(eReturnStatusSuccessFinishResult);
4360    return true;
4361  }
4362};
4363
4364class CommandObjectRenderScriptRuntimeReductionBreakpoint
4365    : public CommandObjectMultiword {
4366public:
4367  CommandObjectRenderScriptRuntimeReductionBreakpoint(
4368      CommandInterpreter &interpreter)
4369      : CommandObjectMultiword(interpreter, "renderscript reduction breakpoint",
4370                               "Commands that manipulate breakpoints on "
4371                               "renderscript general reductions.",
4372                               nullptr) {
4373    LoadSubCommand(
4374        "set", CommandObjectSP(
4375                   new CommandObjectRenderScriptRuntimeReductionBreakpointSet(
4376                       interpreter)));
4377  }
4378
4379  ~CommandObjectRenderScriptRuntimeReductionBreakpoint() override = default;
4380};
4381
4382class CommandObjectRenderScriptRuntimeKernelCoordinate
4383    : public CommandObjectParsed {
4384public:
4385  CommandObjectRenderScriptRuntimeKernelCoordinate(
4386      CommandInterpreter &interpreter)
4387      : CommandObjectParsed(
4388            interpreter, "renderscript kernel coordinate",
4389            "Shows the (x,y,z) coordinate of the current kernel invocation.",
4390            "renderscript kernel coordinate",
4391            eCommandRequiresProcess | eCommandProcessMustBeLaunched |
4392                eCommandProcessMustBePaused) {}
4393
4394  ~CommandObjectRenderScriptRuntimeKernelCoordinate() override = default;
4395
4396  bool DoExecute(Args &command, CommandReturnObject &result) override {
4397    RSCoordinate coord{};
4398    bool success = RenderScriptRuntime::GetKernelCoordinate(
4399        coord, m_exe_ctx.GetThreadPtr());
4400    Stream &stream = result.GetOutputStream();
4401
4402    if (success) {
4403      stream.Printf("Coordinate: " FMT_COORD, coord.x, coord.y, coord.z);
4404      stream.EOL();
4405      result.SetStatus(eReturnStatusSuccessFinishResult);
4406    } else {
4407      stream.Printf("Error: Coordinate could not be found.");
4408      stream.EOL();
4409      result.SetStatus(eReturnStatusFailed);
4410    }
4411    return true;
4412  }
4413};
4414
4415class CommandObjectRenderScriptRuntimeKernelBreakpoint
4416    : public CommandObjectMultiword {
4417public:
4418  CommandObjectRenderScriptRuntimeKernelBreakpoint(
4419      CommandInterpreter &interpreter)
4420      : CommandObjectMultiword(
4421            interpreter, "renderscript kernel",
4422            "Commands that generate breakpoints on renderscript kernels.",
4423            nullptr) {
4424    LoadSubCommand(
4425        "set",
4426        CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointSet(
4427            interpreter)));
4428    LoadSubCommand(
4429        "all",
4430        CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointAll(
4431            interpreter)));
4432  }
4433
4434  ~CommandObjectRenderScriptRuntimeKernelBreakpoint() override = default;
4435};
4436
4437class CommandObjectRenderScriptRuntimeKernel : public CommandObjectMultiword {
4438public:
4439  CommandObjectRenderScriptRuntimeKernel(CommandInterpreter &interpreter)
4440      : CommandObjectMultiword(interpreter, "renderscript kernel",
4441                               "Commands that deal with RenderScript kernels.",
4442                               nullptr) {
4443    LoadSubCommand(
4444        "list", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelList(
4445                    interpreter)));
4446    LoadSubCommand(
4447        "coordinate",
4448        CommandObjectSP(
4449            new CommandObjectRenderScriptRuntimeKernelCoordinate(interpreter)));
4450    LoadSubCommand(
4451        "breakpoint",
4452        CommandObjectSP(
4453            new CommandObjectRenderScriptRuntimeKernelBreakpoint(interpreter)));
4454  }
4455
4456  ~CommandObjectRenderScriptRuntimeKernel() override = default;
4457};
4458
4459class CommandObjectRenderScriptRuntimeContextDump : public CommandObjectParsed {
4460public:
4461  CommandObjectRenderScriptRuntimeContextDump(CommandInterpreter &interpreter)
4462      : CommandObjectParsed(interpreter, "renderscript context dump",
4463                            "Dumps renderscript context information.",
4464                            "renderscript context dump",
4465                            eCommandRequiresProcess |
4466                                eCommandProcessMustBeLaunched) {}
4467
4468  ~CommandObjectRenderScriptRuntimeContextDump() override = default;
4469
4470  bool DoExecute(Args &command, CommandReturnObject &result) override {
4471    RenderScriptRuntime *runtime = llvm::cast<RenderScriptRuntime>(
4472        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
4473            eLanguageTypeExtRenderScript));
4474    runtime->DumpContexts(result.GetOutputStream());
4475    result.SetStatus(eReturnStatusSuccessFinishResult);
4476    return true;
4477  }
4478};
4479
4480static constexpr OptionDefinition g_renderscript_runtime_alloc_dump_options[] = {
4481    {LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument,
4482     nullptr, {}, 0, eArgTypeFilename,
4483     "Print results to specified file instead of command line."}};
4484
4485class CommandObjectRenderScriptRuntimeContext : public CommandObjectMultiword {
4486public:
4487  CommandObjectRenderScriptRuntimeContext(CommandInterpreter &interpreter)
4488      : CommandObjectMultiword(interpreter, "renderscript context",
4489                               "Commands that deal with RenderScript contexts.",
4490                               nullptr) {
4491    LoadSubCommand(
4492        "dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeContextDump(
4493                    interpreter)));
4494  }
4495
4496  ~CommandObjectRenderScriptRuntimeContext() override = default;
4497};
4498
4499class CommandObjectRenderScriptRuntimeAllocationDump
4500    : public CommandObjectParsed {
4501public:
4502  CommandObjectRenderScriptRuntimeAllocationDump(
4503      CommandInterpreter &interpreter)
4504      : CommandObjectParsed(interpreter, "renderscript allocation dump",
4505                            "Displays the contents of a particular allocation",
4506                            "renderscript allocation dump <ID>",
4507                            eCommandRequiresProcess |
4508                                eCommandProcessMustBeLaunched),
4509        m_options() {}
4510
4511  ~CommandObjectRenderScriptRuntimeAllocationDump() override = default;
4512
4513  Options *GetOptions() override { return &m_options; }
4514
4515  class CommandOptions : public Options {
4516  public:
4517    CommandOptions() : Options() {}
4518
4519    ~CommandOptions() override = default;
4520
4521    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
4522                          ExecutionContext *exe_ctx) override {
4523      Status err;
4524      const int short_option = m_getopt_table[option_idx].val;
4525
4526      switch (short_option) {
4527      case 'f':
4528        m_outfile.SetFile(option_arg, FileSpec::Style::native);
4529        FileSystem::Instance().Resolve(m_outfile);
4530        if (FileSystem::Instance().Exists(m_outfile)) {
4531          m_outfile.Clear();
4532          err.SetErrorStringWithFormat("file already exists: '%s'",
4533                                       option_arg.str().c_str());
4534        }
4535        break;
4536      default:
4537        err.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
4538        break;
4539      }
4540      return err;
4541    }
4542
4543    void OptionParsingStarting(ExecutionContext *exe_ctx) override {
4544      m_outfile.Clear();
4545    }
4546
4547    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
4548      return llvm::makeArrayRef(g_renderscript_runtime_alloc_dump_options);
4549    }
4550
4551    FileSpec m_outfile;
4552  };
4553
4554  bool DoExecute(Args &command, CommandReturnObject &result) override {
4555    const size_t argc = command.GetArgumentCount();
4556    if (argc < 1) {
4557      result.AppendErrorWithFormat("'%s' takes 1 argument, an allocation ID. "
4558                                   "As well as an optional -f argument",
4559                                   m_cmd_name.c_str());
4560      result.SetStatus(eReturnStatusFailed);
4561      return false;
4562    }
4563
4564    RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
4565        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
4566            eLanguageTypeExtRenderScript));
4567
4568    const char *id_cstr = command.GetArgumentAtIndex(0);
4569    bool success = false;
4570    const uint32_t id =
4571        StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &success);
4572    if (!success) {
4573      result.AppendErrorWithFormat("invalid allocation id argument '%s'",
4574                                   id_cstr);
4575      result.SetStatus(eReturnStatusFailed);
4576      return false;
4577    }
4578
4579    Stream *output_stream_p = nullptr;
4580    std::unique_ptr<Stream> output_stream_storage;
4581
4582    const FileSpec &outfile_spec =
4583        m_options.m_outfile; // Dump allocation to file instead
4584    if (outfile_spec) {
4585      // Open output file
4586      std::string path = outfile_spec.GetPath();
4587      auto file = FileSystem::Instance().Open(
4588          outfile_spec, File::eOpenOptionWrite | File::eOpenOptionCanCreate);
4589      if (file) {
4590        output_stream_storage =
4591            std::make_unique<StreamFile>(std::move(file.get()));
4592        output_stream_p = output_stream_storage.get();
4593        result.GetOutputStream().Printf("Results written to '%s'",
4594                                        path.c_str());
4595        result.GetOutputStream().EOL();
4596      } else {
4597        std::string error = llvm::toString(file.takeError());
4598        result.AppendErrorWithFormat("Couldn't open file '%s': %s",
4599                                     path.c_str(), error.c_str());
4600        result.SetStatus(eReturnStatusFailed);
4601        return false;
4602      }
4603    } else
4604      output_stream_p = &result.GetOutputStream();
4605
4606    assert(output_stream_p != nullptr);
4607    bool dumped =
4608        runtime->DumpAllocation(*output_stream_p, m_exe_ctx.GetFramePtr(), id);
4609
4610    if (dumped)
4611      result.SetStatus(eReturnStatusSuccessFinishResult);
4612    else
4613      result.SetStatus(eReturnStatusFailed);
4614
4615    return true;
4616  }
4617
4618private:
4619  CommandOptions m_options;
4620};
4621
4622static constexpr OptionDefinition g_renderscript_runtime_alloc_list_options[] = {
4623    {LLDB_OPT_SET_1, false, "id", 'i', OptionParser::eRequiredArgument, nullptr,
4624     {}, 0, eArgTypeIndex,
4625     "Only show details of a single allocation with specified id."}};
4626
4627class CommandObjectRenderScriptRuntimeAllocationList
4628    : public CommandObjectParsed {
4629public:
4630  CommandObjectRenderScriptRuntimeAllocationList(
4631      CommandInterpreter &interpreter)
4632      : CommandObjectParsed(
4633            interpreter, "renderscript allocation list",
4634            "List renderscript allocations and their information.",
4635            "renderscript allocation list",
4636            eCommandRequiresProcess | eCommandProcessMustBeLaunched),
4637        m_options() {}
4638
4639  ~CommandObjectRenderScriptRuntimeAllocationList() override = default;
4640
4641  Options *GetOptions() override { return &m_options; }
4642
4643  class CommandOptions : public Options {
4644  public:
4645    CommandOptions() : Options(), m_id(0) {}
4646
4647    ~CommandOptions() override = default;
4648
4649    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
4650                          ExecutionContext *exe_ctx) override {
4651      Status err;
4652      const int short_option = m_getopt_table[option_idx].val;
4653
4654      switch (short_option) {
4655      case 'i':
4656        if (option_arg.getAsInteger(0, m_id))
4657          err.SetErrorStringWithFormat("invalid integer value for option '%c'",
4658                                       short_option);
4659        break;
4660      default:
4661        err.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
4662        break;
4663      }
4664      return err;
4665    }
4666
4667    void OptionParsingStarting(ExecutionContext *exe_ctx) override { m_id = 0; }
4668
4669    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
4670      return llvm::makeArrayRef(g_renderscript_runtime_alloc_list_options);
4671    }
4672
4673    uint32_t m_id;
4674  };
4675
4676  bool DoExecute(Args &command, CommandReturnObject &result) override {
4677    RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
4678        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
4679            eLanguageTypeExtRenderScript));
4680    runtime->ListAllocations(result.GetOutputStream(), m_exe_ctx.GetFramePtr(),
4681                             m_options.m_id);
4682    result.SetStatus(eReturnStatusSuccessFinishResult);
4683    return true;
4684  }
4685
4686private:
4687  CommandOptions m_options;
4688};
4689
4690class CommandObjectRenderScriptRuntimeAllocationLoad
4691    : public CommandObjectParsed {
4692public:
4693  CommandObjectRenderScriptRuntimeAllocationLoad(
4694      CommandInterpreter &interpreter)
4695      : CommandObjectParsed(
4696            interpreter, "renderscript allocation load",
4697            "Loads renderscript allocation contents from a file.",
4698            "renderscript allocation load <ID> <filename>",
4699            eCommandRequiresProcess | eCommandProcessMustBeLaunched) {}
4700
4701  ~CommandObjectRenderScriptRuntimeAllocationLoad() override = default;
4702
4703  bool DoExecute(Args &command, CommandReturnObject &result) override {
4704    const size_t argc = command.GetArgumentCount();
4705    if (argc != 2) {
4706      result.AppendErrorWithFormat(
4707          "'%s' takes 2 arguments, an allocation ID and filename to read from.",
4708          m_cmd_name.c_str());
4709      result.SetStatus(eReturnStatusFailed);
4710      return false;
4711    }
4712
4713    RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
4714        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
4715            eLanguageTypeExtRenderScript));
4716
4717    const char *id_cstr = command.GetArgumentAtIndex(0);
4718    bool success = false;
4719    const uint32_t id =
4720        StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &success);
4721    if (!success) {
4722      result.AppendErrorWithFormat("invalid allocation id argument '%s'",
4723                                   id_cstr);
4724      result.SetStatus(eReturnStatusFailed);
4725      return false;
4726    }
4727
4728    const char *path = command.GetArgumentAtIndex(1);
4729    bool loaded = runtime->LoadAllocation(result.GetOutputStream(), id, path,
4730                                          m_exe_ctx.GetFramePtr());
4731
4732    if (loaded)
4733      result.SetStatus(eReturnStatusSuccessFinishResult);
4734    else
4735      result.SetStatus(eReturnStatusFailed);
4736
4737    return true;
4738  }
4739};
4740
4741class CommandObjectRenderScriptRuntimeAllocationSave
4742    : public CommandObjectParsed {
4743public:
4744  CommandObjectRenderScriptRuntimeAllocationSave(
4745      CommandInterpreter &interpreter)
4746      : CommandObjectParsed(interpreter, "renderscript allocation save",
4747                            "Write renderscript allocation contents to a file.",
4748                            "renderscript allocation save <ID> <filename>",
4749                            eCommandRequiresProcess |
4750                                eCommandProcessMustBeLaunched) {}
4751
4752  ~CommandObjectRenderScriptRuntimeAllocationSave() override = default;
4753
4754  bool DoExecute(Args &command, CommandReturnObject &result) override {
4755    const size_t argc = command.GetArgumentCount();
4756    if (argc != 2) {
4757      result.AppendErrorWithFormat(
4758          "'%s' takes 2 arguments, an allocation ID and filename to read from.",
4759          m_cmd_name.c_str());
4760      result.SetStatus(eReturnStatusFailed);
4761      return false;
4762    }
4763
4764    RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
4765        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
4766            eLanguageTypeExtRenderScript));
4767
4768    const char *id_cstr = command.GetArgumentAtIndex(0);
4769    bool success = false;
4770    const uint32_t id =
4771        StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &success);
4772    if (!success) {
4773      result.AppendErrorWithFormat("invalid allocation id argument '%s'",
4774                                   id_cstr);
4775      result.SetStatus(eReturnStatusFailed);
4776      return false;
4777    }
4778
4779    const char *path = command.GetArgumentAtIndex(1);
4780    bool saved = runtime->SaveAllocation(result.GetOutputStream(), id, path,
4781                                         m_exe_ctx.GetFramePtr());
4782
4783    if (saved)
4784      result.SetStatus(eReturnStatusSuccessFinishResult);
4785    else
4786      result.SetStatus(eReturnStatusFailed);
4787
4788    return true;
4789  }
4790};
4791
4792class CommandObjectRenderScriptRuntimeAllocationRefresh
4793    : public CommandObjectParsed {
4794public:
4795  CommandObjectRenderScriptRuntimeAllocationRefresh(
4796      CommandInterpreter &interpreter)
4797      : CommandObjectParsed(interpreter, "renderscript allocation refresh",
4798                            "Recomputes the details of all allocations.",
4799                            "renderscript allocation refresh",
4800                            eCommandRequiresProcess |
4801                                eCommandProcessMustBeLaunched) {}
4802
4803  ~CommandObjectRenderScriptRuntimeAllocationRefresh() override = default;
4804
4805  bool DoExecute(Args &command, CommandReturnObject &result) override {
4806    RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
4807        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
4808            eLanguageTypeExtRenderScript));
4809
4810    bool success = runtime->RecomputeAllAllocations(result.GetOutputStream(),
4811                                                    m_exe_ctx.GetFramePtr());
4812
4813    if (success) {
4814      result.SetStatus(eReturnStatusSuccessFinishResult);
4815      return true;
4816    } else {
4817      result.SetStatus(eReturnStatusFailed);
4818      return false;
4819    }
4820  }
4821};
4822
4823class CommandObjectRenderScriptRuntimeAllocation
4824    : public CommandObjectMultiword {
4825public:
4826  CommandObjectRenderScriptRuntimeAllocation(CommandInterpreter &interpreter)
4827      : CommandObjectMultiword(
4828            interpreter, "renderscript allocation",
4829            "Commands that deal with RenderScript allocations.", nullptr) {
4830    LoadSubCommand(
4831        "list",
4832        CommandObjectSP(
4833            new CommandObjectRenderScriptRuntimeAllocationList(interpreter)));
4834    LoadSubCommand(
4835        "dump",
4836        CommandObjectSP(
4837            new CommandObjectRenderScriptRuntimeAllocationDump(interpreter)));
4838    LoadSubCommand(
4839        "save",
4840        CommandObjectSP(
4841            new CommandObjectRenderScriptRuntimeAllocationSave(interpreter)));
4842    LoadSubCommand(
4843        "load",
4844        CommandObjectSP(
4845            new CommandObjectRenderScriptRuntimeAllocationLoad(interpreter)));
4846    LoadSubCommand(
4847        "refresh",
4848        CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationRefresh(
4849            interpreter)));
4850  }
4851
4852  ~CommandObjectRenderScriptRuntimeAllocation() override = default;
4853};
4854
4855class CommandObjectRenderScriptRuntimeStatus : public CommandObjectParsed {
4856public:
4857  CommandObjectRenderScriptRuntimeStatus(CommandInterpreter &interpreter)
4858      : CommandObjectParsed(interpreter, "renderscript status",
4859                            "Displays current RenderScript runtime status.",
4860                            "renderscript status",
4861                            eCommandRequiresProcess |
4862                                eCommandProcessMustBeLaunched) {}
4863
4864  ~CommandObjectRenderScriptRuntimeStatus() override = default;
4865
4866  bool DoExecute(Args &command, CommandReturnObject &result) override {
4867    RenderScriptRuntime *runtime = llvm::cast<RenderScriptRuntime>(
4868        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
4869            eLanguageTypeExtRenderScript));
4870    runtime->DumpStatus(result.GetOutputStream());
4871    result.SetStatus(eReturnStatusSuccessFinishResult);
4872    return true;
4873  }
4874};
4875
4876class CommandObjectRenderScriptRuntimeReduction
4877    : public CommandObjectMultiword {
4878public:
4879  CommandObjectRenderScriptRuntimeReduction(CommandInterpreter &interpreter)
4880      : CommandObjectMultiword(interpreter, "renderscript reduction",
4881                               "Commands that handle general reduction kernels",
4882                               nullptr) {
4883    LoadSubCommand(
4884        "breakpoint",
4885        CommandObjectSP(new CommandObjectRenderScriptRuntimeReductionBreakpoint(
4886            interpreter)));
4887  }
4888  ~CommandObjectRenderScriptRuntimeReduction() override = default;
4889};
4890
4891class CommandObjectRenderScriptRuntime : public CommandObjectMultiword {
4892public:
4893  CommandObjectRenderScriptRuntime(CommandInterpreter &interpreter)
4894      : CommandObjectMultiword(
4895            interpreter, "renderscript",
4896            "Commands for operating on the RenderScript runtime.",
4897            "renderscript <subcommand> [<subcommand-options>]") {
4898    LoadSubCommand(
4899        "module", CommandObjectSP(
4900                      new CommandObjectRenderScriptRuntimeModule(interpreter)));
4901    LoadSubCommand(
4902        "status", CommandObjectSP(
4903                      new CommandObjectRenderScriptRuntimeStatus(interpreter)));
4904    LoadSubCommand(
4905        "kernel", CommandObjectSP(
4906                      new CommandObjectRenderScriptRuntimeKernel(interpreter)));
4907    LoadSubCommand("context",
4908                   CommandObjectSP(new CommandObjectRenderScriptRuntimeContext(
4909                       interpreter)));
4910    LoadSubCommand(
4911        "allocation",
4912        CommandObjectSP(
4913            new CommandObjectRenderScriptRuntimeAllocation(interpreter)));
4914    LoadSubCommand("scriptgroup",
4915                   NewCommandObjectRenderScriptScriptGroup(interpreter));
4916    LoadSubCommand(
4917        "reduction",
4918        CommandObjectSP(
4919            new CommandObjectRenderScriptRuntimeReduction(interpreter)));
4920  }
4921
4922  ~CommandObjectRenderScriptRuntime() override = default;
4923};
4924
4925void RenderScriptRuntime::Initiate() { assert(!m_initiated); }
4926
4927RenderScriptRuntime::RenderScriptRuntime(Process *process)
4928    : lldb_private::CPPLanguageRuntime(process), m_initiated(false),
4929      m_debuggerPresentFlagged(false), m_breakAllKernels(false),
4930      m_ir_passes(nullptr) {
4931  ModulesDidLoad(process->GetTarget().GetImages());
4932}
4933
4934lldb::CommandObjectSP RenderScriptRuntime::GetCommandObject(
4935    lldb_private::CommandInterpreter &interpreter) {
4936  return CommandObjectSP(new CommandObjectRenderScriptRuntime(interpreter));
4937}
4938
4939RenderScriptRuntime::~RenderScriptRuntime() = default;
4940