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