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