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