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