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