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