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