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