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