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