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