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