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 infomation regarding all the currently loaded allocations.
2874 // These details are gathered by jitting the runtime, which has as latency.
2875 void
2876 RenderScriptRuntime::ListAllocations(Stream &strm, StackFrame* frame_ptr, bool recompute)
2877 {
2878     strm.Printf("RenderScript Allocations:");
2879     strm.EOL();
2880     strm.IndentMore();
2881 
2882     for (auto &alloc : m_allocations)
2883     {
2884         // JIT the allocation info if we haven't done it, or the user forces us to.
2885         bool do_refresh = alloc->shouldRefresh() || recompute;
2886 
2887         // JIT current allocation information
2888         if (do_refresh && !RefreshAllocation(alloc.get(), frame_ptr))
2889         {
2890             strm.Printf("Error: Couldn't evaluate details for allocation %u\n", alloc->id);
2891             continue;
2892         }
2893 
2894         strm.Printf("%u:\n",alloc->id);
2895         strm.IndentMore();
2896 
2897         strm.Indent("Context: ");
2898         if (!alloc->context.isValid())
2899             strm.Printf("unknown\n");
2900         else
2901             strm.Printf("0x%" PRIx64 "\n", *alloc->context.get());
2902 
2903         strm.Indent("Address: ");
2904         if (!alloc->address.isValid())
2905             strm.Printf("unknown\n");
2906         else
2907             strm.Printf("0x%" PRIx64 "\n", *alloc->address.get());
2908 
2909         strm.Indent("Data pointer: ");
2910         if (!alloc->data_ptr.isValid())
2911             strm.Printf("unknown\n");
2912         else
2913             strm.Printf("0x%" PRIx64 "\n", *alloc->data_ptr.get());
2914 
2915         strm.Indent("Dimensions: ");
2916         if (!alloc->dimension.isValid())
2917             strm.Printf("unknown\n");
2918         else
2919             strm.Printf("(%d, %d, %d)\n", alloc->dimension.get()->dim_1,
2920                                           alloc->dimension.get()->dim_2,
2921                                           alloc->dimension.get()->dim_3);
2922 
2923         strm.Indent("Data Type: ");
2924         if (!alloc->element.type.isValid() || !alloc->element.type_vec_size.isValid())
2925             strm.Printf("unknown\n");
2926         else
2927         {
2928             const int vector_size = *alloc->element.type_vec_size.get();
2929             Element::DataType type = *alloc->element.type.get();
2930 
2931             if (!alloc->element.type_name.IsEmpty())
2932                 strm.Printf("%s\n", alloc->element.type_name.AsCString());
2933             else
2934             {
2935                 // Enum value isn't monotonous, so doesn't always index RsDataTypeToString array
2936                 if (type >= Element::RS_TYPE_ELEMENT && type <= Element::RS_TYPE_FONT)
2937                     type = static_cast<Element::DataType>((type - Element::RS_TYPE_ELEMENT) +  Element::RS_TYPE_MATRIX_2X2 + 1);
2938 
2939                 if (type >= (sizeof(AllocationDetails::RsDataTypeToString) / sizeof(AllocationDetails::RsDataTypeToString[0]))
2940                     || vector_size > 4 || vector_size < 1)
2941                     strm.Printf("invalid type\n");
2942                 else
2943                     strm.Printf("%s\n", AllocationDetails::RsDataTypeToString[static_cast<unsigned int>(type)][vector_size-1]);
2944             }
2945         }
2946 
2947         strm.Indent("Data Kind: ");
2948         if (!alloc->element.type_kind.isValid())
2949             strm.Printf("unknown\n");
2950         else
2951         {
2952             const Element::DataKind kind = *alloc->element.type_kind.get();
2953             if (kind < Element::RS_KIND_USER || kind > Element::RS_KIND_PIXEL_YUV)
2954                 strm.Printf("invalid kind\n");
2955             else
2956                 strm.Printf("%s\n", AllocationDetails::RsDataKindToString[static_cast<unsigned int>(kind)]);
2957         }
2958 
2959         strm.EOL();
2960         strm.IndentLess();
2961     }
2962     strm.IndentLess();
2963 }
2964 
2965 // Set breakpoints on every kernel found in RS module
2966 void
2967 RenderScriptRuntime::BreakOnModuleKernels(const RSModuleDescriptorSP rsmodule_sp)
2968 {
2969     for (const auto &kernel : rsmodule_sp->m_kernels)
2970     {
2971         // Don't set breakpoint on 'root' kernel
2972         if (strcmp(kernel.m_name.AsCString(), "root") == 0)
2973             continue;
2974 
2975         CreateKernelBreakpoint(kernel.m_name);
2976     }
2977 }
2978 
2979 // Method is internally called by the 'kernel breakpoint all' command to
2980 // enable or disable breaking on all kernels.
2981 //
2982 // When do_break is true we want to enable this functionality.
2983 // When do_break is false we want to disable it.
2984 void
2985 RenderScriptRuntime::SetBreakAllKernels(bool do_break, TargetSP target)
2986 {
2987     Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
2988 
2989     InitSearchFilter(target);
2990 
2991     // Set breakpoints on all the kernels
2992     if (do_break && !m_breakAllKernels)
2993     {
2994         m_breakAllKernels = true;
2995 
2996         for (const auto &module : m_rsmodules)
2997             BreakOnModuleKernels(module);
2998 
2999         if (log)
3000             log->Printf("RenderScriptRuntime::SetBreakAllKernels(True)"
3001                         "- breakpoints set on all currently loaded kernels");
3002     }
3003     else if (!do_break && m_breakAllKernels) // Breakpoints won't be set on any new kernels.
3004     {
3005         m_breakAllKernels = false;
3006 
3007         if (log)
3008             log->Printf("RenderScriptRuntime::SetBreakAllKernels(False) - breakpoints no longer automatically set");
3009     }
3010 }
3011 
3012 // Given the name of a kernel this function creates a breakpoint using our
3013 // own breakpoint resolver, and returns the Breakpoint shared pointer.
3014 BreakpointSP
3015 RenderScriptRuntime::CreateKernelBreakpoint(const ConstString& name)
3016 {
3017     Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
3018 
3019     if (!m_filtersp)
3020     {
3021         if (log)
3022             log->Printf("RenderScriptRuntime::CreateKernelBreakpoint - Error: No breakpoint search filter set");
3023         return nullptr;
3024     }
3025 
3026     BreakpointResolverSP resolver_sp(new RSBreakpointResolver(nullptr, name));
3027     BreakpointSP bp = GetProcess()->GetTarget().CreateBreakpoint(m_filtersp, resolver_sp, false, false, false);
3028 
3029     // Give RS breakpoints a specific name, so the user can manipulate them as a group.
3030     Error err;
3031     if (!bp->AddName("RenderScriptKernel", err) && log)
3032         log->Printf("RenderScriptRuntime::CreateKernelBreakpoint: Error setting break name, %s", err.AsCString());
3033 
3034     return bp;
3035 }
3036 
3037 // Given an expression for a variable this function tries to calculate the variable's value.
3038 // If this is possible it returns true and sets the uint64_t parameter to the variables unsigned value.
3039 // Otherwise function returns false.
3040 bool
3041 RenderScriptRuntime::GetFrameVarAsUnsigned(const StackFrameSP frame_sp, const char* var_name, uint64_t& val)
3042 {
3043     Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE));
3044     Error error;
3045     VariableSP var_sp;
3046 
3047     // Find variable in stack frame
3048     ValueObjectSP value_sp(frame_sp->GetValueForVariableExpressionPath(var_name,
3049                                                                        eNoDynamicValues,
3050                                                                        StackFrame::eExpressionPathOptionCheckPtrVsMember |
3051                                                                        StackFrame::eExpressionPathOptionsAllowDirectIVarAccess,
3052                                                                        var_sp,
3053                                                                        error));
3054     if (!error.Success())
3055     {
3056         if (log)
3057             log->Printf("RenderScriptRuntime::GetFrameVarAsUnsigned - Error, couldn't find '%s' in frame", var_name);
3058 
3059         return false;
3060     }
3061 
3062     // Find the unsigned int value for the variable
3063     bool success = false;
3064     val = value_sp->GetValueAsUnsigned(0, &success);
3065     if (!success)
3066     {
3067         if (log)
3068             log->Printf("RenderScriptRuntime::GetFrameVarAsUnsigned - Error, couldn't parse '%s' as an unsigned int", var_name);
3069 
3070         return false;
3071     }
3072 
3073     return true;
3074 }
3075 
3076 // Function attempts to find the current coordinate of a kernel invocation by investigating the
3077 // values of frame variables in the .expand function. These coordinates are returned via the coord
3078 // array reference parameter. Returns true if the coordinates could be found, and false otherwise.
3079 bool
3080 RenderScriptRuntime::GetKernelCoordinate(RSCoordinate &coord, Thread *thread_ptr)
3081 {
3082     Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE));
3083 
3084     if (!thread_ptr)
3085     {
3086         if (log)
3087             log->Printf("%s - Error, No thread pointer", __FUNCTION__);
3088 
3089         return false;
3090     }
3091 
3092     // Walk the call stack looking for a function whose name has the suffix '.expand'
3093     // and contains the variables we're looking for.
3094     for (uint32_t i = 0; i < thread_ptr->GetStackFrameCount(); ++i)
3095     {
3096         if (!thread_ptr->SetSelectedFrameByIndex(i))
3097             continue;
3098 
3099         StackFrameSP frame_sp = thread_ptr->GetSelectedFrame();
3100         if (!frame_sp)
3101             continue;
3102 
3103         // Find the function name
3104         const SymbolContext sym_ctx = frame_sp->GetSymbolContext(false);
3105         const char *func_name_cstr = sym_ctx.GetFunctionName().AsCString();
3106         if (!func_name_cstr)
3107             continue;
3108 
3109         if (log)
3110             log->Printf("%s - Inspecting function '%s'", __FUNCTION__, func_name_cstr);
3111 
3112         // Check if function name has .expand suffix
3113         std::string func_name(func_name_cstr);
3114         const int length_difference = func_name.length() - RenderScriptRuntime::s_runtimeExpandSuffix.length();
3115         if (length_difference <= 0)
3116             continue;
3117 
3118         const int32_t has_expand_suffix = func_name.compare(length_difference,
3119                                                             RenderScriptRuntime::s_runtimeExpandSuffix.length(),
3120                                                             RenderScriptRuntime::s_runtimeExpandSuffix);
3121 
3122         if (has_expand_suffix != 0)
3123             continue;
3124 
3125         if (log)
3126             log->Printf("%s - Found .expand function '%s'", __FUNCTION__, func_name_cstr);
3127 
3128         // Get values for variables in .expand frame that tell us the current kernel invocation
3129         bool found_coord_variables = true;
3130         assert(RenderScriptRuntime::s_runtimeCoordVars.size() == coord.size());
3131 
3132         for (uint32_t i = 0; i < coord.size(); ++i)
3133         {
3134             uint64_t value = 0;
3135             if (!GetFrameVarAsUnsigned(frame_sp, RenderScriptRuntime::s_runtimeCoordVars[i], value))
3136             {
3137                 found_coord_variables = false;
3138                 break;
3139             }
3140             coord[i] = value;
3141         }
3142 
3143         if (found_coord_variables)
3144             return true;
3145     }
3146     return false;
3147 }
3148 
3149 // Callback when a kernel breakpoint hits and we're looking for a specific coordinate.
3150 // Baton parameter contains a pointer to the target coordinate we want to break on.
3151 // Function then checks the .expand frame for the current coordinate and breaks to user if it matches.
3152 // Parameter 'break_id' is the id of the Breakpoint which made the callback.
3153 // Parameter 'break_loc_id' is the id for the BreakpointLocation which was hit,
3154 // a single logical breakpoint can have multiple addresses.
3155 bool
3156 RenderScriptRuntime::KernelBreakpointHit(void *baton, StoppointCallbackContext *ctx,
3157                                          user_id_t break_id, user_id_t break_loc_id)
3158 {
3159     Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
3160 
3161     assert(baton && "Error: null baton in conditional kernel breakpoint callback");
3162 
3163     // Coordinate we want to stop on
3164     const uint32_t *target_coord = static_cast<const uint32_t *>(baton);
3165 
3166     if (log)
3167         log->Printf("%s - Break ID %" PRIu64 ", (%" PRIu32 ", %" PRIu32 ", %" PRIu32 ")", __FUNCTION__, break_id,
3168                     target_coord[0], target_coord[1], target_coord[2]);
3169 
3170     // Select current thread
3171     ExecutionContext context(ctx->exe_ctx_ref);
3172     Thread *thread_ptr = context.GetThreadPtr();
3173     assert(thread_ptr && "Null thread pointer");
3174 
3175     // Find current kernel invocation from .expand frame variables
3176     RSCoordinate current_coord{}; // Zero initialise array
3177     if (!GetKernelCoordinate(current_coord, thread_ptr))
3178     {
3179         if (log)
3180             log->Printf("%s - Error, couldn't select .expand stack frame", __FUNCTION__);
3181 
3182         return false;
3183     }
3184 
3185     if (log)
3186         log->Printf("%s - (%" PRIu32 ",%" PRIu32 ",%" PRIu32 ")", __FUNCTION__, current_coord[0], current_coord[1],
3187                     current_coord[2]);
3188 
3189     // Check if the current kernel invocation coordinate matches our target coordinate
3190     if (current_coord[0] == target_coord[0] && current_coord[1] == target_coord[1] &&
3191         current_coord[2] == target_coord[2])
3192     {
3193         if (log)
3194             log->Printf("%s, BREAKING (%" PRIu32 ",%" PRIu32 ",%" PRIu32 ")", __FUNCTION__, current_coord[0],
3195                         current_coord[1], current_coord[2]);
3196 
3197         BreakpointSP breakpoint_sp = context.GetTargetPtr()->GetBreakpointByID(break_id);
3198         assert(breakpoint_sp != nullptr && "Error: Couldn't find breakpoint matching break id for callback");
3199         breakpoint_sp->SetEnabled(false); // Optimise since conditional breakpoint should only be hit once.
3200         return true;
3201     }
3202 
3203     // No match on coordinate
3204     return false;
3205 }
3206 
3207 // Tries to set a breakpoint on the start of a kernel, resolved using the kernel name.
3208 // Argument 'coords', represents a three dimensional coordinate which can be used to specify
3209 // a single kernel instance to break on. If this is set then we add a callback to the breakpoint.
3210 void
3211 RenderScriptRuntime::PlaceBreakpointOnKernel(Stream &strm, const char* name, const std::array<int,3> coords,
3212                                              Error& error, TargetSP target)
3213 {
3214     if (!name)
3215     {
3216         error.SetErrorString("invalid kernel name");
3217         return;
3218     }
3219 
3220     InitSearchFilter(target);
3221 
3222     ConstString kernel_name(name);
3223     BreakpointSP bp = CreateKernelBreakpoint(kernel_name);
3224 
3225     // We have a conditional breakpoint on a specific coordinate
3226     if (coords[0] != -1)
3227     {
3228         strm.Printf("Conditional kernel breakpoint on coordinate %d, %d, %d", coords[0], coords[1], coords[2]);
3229         strm.EOL();
3230 
3231         // Allocate memory for the baton, and copy over coordinate
3232         uint32_t *baton = new uint32_t[coords.size()];
3233         baton[0] = coords[0]; baton[1] = coords[1]; baton[2] = coords[2];
3234 
3235         // Create a callback that will be invoked everytime the breakpoint is hit.
3236         // The baton object passed to the handler is the target coordinate we want to break on.
3237         bp->SetCallback(KernelBreakpointHit, baton, true);
3238 
3239         // Store a shared pointer to the baton, so the memory will eventually be cleaned up after destruction
3240         m_conditional_breaks[bp->GetID()] = std::shared_ptr<uint32_t>(baton);
3241     }
3242 
3243     if (bp)
3244         bp->GetDescription(&strm, lldb::eDescriptionLevelInitial, false);
3245 }
3246 
3247 void
3248 RenderScriptRuntime::DumpModules(Stream &strm) const
3249 {
3250     strm.Printf("RenderScript Modules:");
3251     strm.EOL();
3252     strm.IndentMore();
3253     for (const auto &module : m_rsmodules)
3254     {
3255         module->Dump(strm);
3256     }
3257     strm.IndentLess();
3258 }
3259 
3260 RenderScriptRuntime::ScriptDetails*
3261 RenderScriptRuntime::LookUpScript(addr_t address, bool create)
3262 {
3263     for (const auto & s : m_scripts)
3264     {
3265         if (s->script.isValid())
3266             if (*s->script == address)
3267                 return s.get();
3268     }
3269     if (create)
3270     {
3271         std::unique_ptr<ScriptDetails> s(new ScriptDetails);
3272         s->script = address;
3273         m_scripts.push_back(std::move(s));
3274         return m_scripts.back().get();
3275     }
3276     return nullptr;
3277 }
3278 
3279 RenderScriptRuntime::AllocationDetails*
3280 RenderScriptRuntime::LookUpAllocation(addr_t address, bool create)
3281 {
3282     for (const auto & a : m_allocations)
3283     {
3284         if (a->address.isValid())
3285             if (*a->address == address)
3286                 return a.get();
3287     }
3288     if (create)
3289     {
3290         std::unique_ptr<AllocationDetails> a(new AllocationDetails);
3291         a->address = address;
3292         m_allocations.push_back(std::move(a));
3293         return m_allocations.back().get();
3294     }
3295     return nullptr;
3296 }
3297 
3298 void
3299 RSModuleDescriptor::Dump(Stream &strm) const
3300 {
3301     strm.Indent();
3302     m_module->GetFileSpec().Dump(&strm);
3303     if(m_module->GetNumCompileUnits())
3304     {
3305         strm.Indent("Debug info loaded.");
3306     }
3307     else
3308     {
3309         strm.Indent("Debug info does not exist.");
3310     }
3311     strm.EOL();
3312     strm.IndentMore();
3313     strm.Indent();
3314     strm.Printf("Globals: %" PRIu64, static_cast<uint64_t>(m_globals.size()));
3315     strm.EOL();
3316     strm.IndentMore();
3317     for (const auto &global : m_globals)
3318     {
3319         global.Dump(strm);
3320     }
3321     strm.IndentLess();
3322     strm.Indent();
3323     strm.Printf("Kernels: %" PRIu64, static_cast<uint64_t>(m_kernels.size()));
3324     strm.EOL();
3325     strm.IndentMore();
3326     for (const auto &kernel : m_kernels)
3327     {
3328         kernel.Dump(strm);
3329     }
3330     strm.Printf("Pragmas: %"  PRIu64 , static_cast<uint64_t>(m_pragmas.size()));
3331     strm.EOL();
3332     strm.IndentMore();
3333     for (const auto &key_val : m_pragmas)
3334     {
3335         strm.Printf("%s: %s", key_val.first.c_str(), key_val.second.c_str());
3336         strm.EOL();
3337     }
3338     strm.IndentLess(4);
3339 }
3340 
3341 void
3342 RSGlobalDescriptor::Dump(Stream &strm) const
3343 {
3344     strm.Indent(m_name.AsCString());
3345     VariableList var_list;
3346     m_module->m_module->FindGlobalVariables(m_name, nullptr, true, 1U, var_list);
3347     if (var_list.GetSize() == 1)
3348     {
3349         auto var = var_list.GetVariableAtIndex(0);
3350         auto type = var->GetType();
3351         if(type)
3352         {
3353             strm.Printf(" - ");
3354             type->DumpTypeName(&strm);
3355         }
3356         else
3357         {
3358             strm.Printf(" - Unknown Type");
3359         }
3360     }
3361     else
3362     {
3363         strm.Printf(" - variable identified, but not found in binary");
3364         const Symbol* s = m_module->m_module->FindFirstSymbolWithNameAndType(m_name, eSymbolTypeData);
3365         if (s)
3366         {
3367             strm.Printf(" (symbol exists) ");
3368         }
3369     }
3370 
3371     strm.EOL();
3372 }
3373 
3374 void
3375 RSKernelDescriptor::Dump(Stream &strm) const
3376 {
3377     strm.Indent(m_name.AsCString());
3378     strm.EOL();
3379 }
3380 
3381 class CommandObjectRenderScriptRuntimeModuleProbe : public CommandObjectParsed
3382 {
3383 public:
3384     CommandObjectRenderScriptRuntimeModuleProbe(CommandInterpreter &interpreter)
3385         : CommandObjectParsed(interpreter, "renderscript module probe",
3386                               "Initiates a Probe of all loaded modules for kernels and other renderscript objects.",
3387                               "renderscript module probe",
3388                               eCommandRequiresTarget | eCommandRequiresProcess | eCommandProcessMustBeLaunched)
3389     {
3390     }
3391 
3392     ~CommandObjectRenderScriptRuntimeModuleProbe() override = default;
3393 
3394     bool
3395     DoExecute(Args &command, CommandReturnObject &result) override
3396     {
3397         const size_t argc = command.GetArgumentCount();
3398         if (argc == 0)
3399         {
3400             Target *target = m_exe_ctx.GetTargetPtr();
3401             RenderScriptRuntime *runtime =
3402                 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
3403             auto module_list = target->GetImages();
3404             bool new_rs_details = runtime->ProbeModules(module_list);
3405             if (new_rs_details)
3406             {
3407                 result.AppendMessage("New renderscript modules added to runtime model.");
3408             }
3409             result.SetStatus(eReturnStatusSuccessFinishResult);
3410             return true;
3411         }
3412 
3413         result.AppendErrorWithFormat("'%s' takes no arguments", m_cmd_name.c_str());
3414         result.SetStatus(eReturnStatusFailed);
3415         return false;
3416     }
3417 };
3418 
3419 class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed
3420 {
3421 public:
3422     CommandObjectRenderScriptRuntimeModuleDump(CommandInterpreter &interpreter)
3423         : CommandObjectParsed(interpreter, "renderscript module dump",
3424                               "Dumps renderscript specific information for all modules.", "renderscript module dump",
3425                               eCommandRequiresProcess | eCommandProcessMustBeLaunched)
3426     {
3427     }
3428 
3429     ~CommandObjectRenderScriptRuntimeModuleDump() override = default;
3430 
3431     bool
3432     DoExecute(Args &command, CommandReturnObject &result) override
3433     {
3434         RenderScriptRuntime *runtime =
3435             (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
3436         runtime->DumpModules(result.GetOutputStream());
3437         result.SetStatus(eReturnStatusSuccessFinishResult);
3438         return true;
3439     }
3440 };
3441 
3442 class CommandObjectRenderScriptRuntimeModule : public CommandObjectMultiword
3443 {
3444 public:
3445     CommandObjectRenderScriptRuntimeModule(CommandInterpreter &interpreter)
3446         : CommandObjectMultiword(interpreter, "renderscript module", "Commands that deal with renderscript modules.",
3447                                  NULL)
3448     {
3449         LoadSubCommand("probe", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleProbe(interpreter)));
3450         LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleDump(interpreter)));
3451     }
3452 
3453     ~CommandObjectRenderScriptRuntimeModule() override = default;
3454 };
3455 
3456 class CommandObjectRenderScriptRuntimeKernelList : public CommandObjectParsed
3457 {
3458 public:
3459     CommandObjectRenderScriptRuntimeKernelList(CommandInterpreter &interpreter)
3460         : CommandObjectParsed(interpreter, "renderscript kernel list",
3461                               "Lists renderscript kernel names and associated script resources.", "renderscript kernel list",
3462                               eCommandRequiresProcess | eCommandProcessMustBeLaunched)
3463     {
3464     }
3465 
3466     ~CommandObjectRenderScriptRuntimeKernelList() override = default;
3467 
3468     bool
3469     DoExecute(Args &command, CommandReturnObject &result) override
3470     {
3471         RenderScriptRuntime *runtime =
3472             (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
3473         runtime->DumpKernels(result.GetOutputStream());
3474         result.SetStatus(eReturnStatusSuccessFinishResult);
3475         return true;
3476     }
3477 };
3478 
3479 class CommandObjectRenderScriptRuntimeKernelBreakpointSet : public CommandObjectParsed
3480 {
3481 public:
3482     CommandObjectRenderScriptRuntimeKernelBreakpointSet(CommandInterpreter &interpreter)
3483         : CommandObjectParsed(interpreter, "renderscript kernel breakpoint set",
3484                               "Sets a breakpoint on a renderscript kernel.", "renderscript kernel breakpoint set <kernel_name> [-c x,y,z]",
3485                               eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), m_options(interpreter)
3486     {
3487     }
3488 
3489     ~CommandObjectRenderScriptRuntimeKernelBreakpointSet() override = default;
3490 
3491     Options*
3492     GetOptions() override
3493     {
3494         return &m_options;
3495     }
3496 
3497     class CommandOptions : public Options
3498     {
3499     public:
3500         CommandOptions(CommandInterpreter &interpreter) : Options(interpreter)
3501         {
3502         }
3503 
3504         ~CommandOptions() override = default;
3505 
3506         Error
3507         SetOptionValue(uint32_t option_idx, const char *option_arg) override
3508         {
3509             Error error;
3510             const int short_option = m_getopt_table[option_idx].val;
3511 
3512             switch (short_option)
3513             {
3514                 case 'c':
3515                     if (!ParseCoordinate(option_arg))
3516                         error.SetErrorStringWithFormat("Couldn't parse coordinate '%s', should be in format 'x,y,z'.", option_arg);
3517                     break;
3518                 default:
3519                     error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
3520                     break;
3521             }
3522             return error;
3523         }
3524 
3525         // -c takes an argument of the form 'num[,num][,num]'.
3526         // Where 'id_cstr' is this argument with the whitespace trimmed.
3527         // Missing coordinates are defaulted to zero.
3528         bool
3529         ParseCoordinate(const char* id_cstr)
3530         {
3531             RegularExpression regex;
3532             RegularExpression::Match regex_match(3);
3533 
3534             bool matched = false;
3535             if(regex.Compile("^([0-9]+),([0-9]+),([0-9]+)$") && regex.Execute(id_cstr, &regex_match))
3536                 matched = true;
3537             else if(regex.Compile("^([0-9]+),([0-9]+)$") && regex.Execute(id_cstr, &regex_match))
3538                 matched = true;
3539             else if(regex.Compile("^([0-9]+)$") && regex.Execute(id_cstr, &regex_match))
3540                 matched = true;
3541             for(uint32_t i = 0; i < 3; i++)
3542             {
3543                 std::string group;
3544                 if(regex_match.GetMatchAtIndex(id_cstr, i + 1, group))
3545                     m_coord[i] = (uint32_t)strtoul(group.c_str(), NULL, 0);
3546                 else
3547                     m_coord[i] = 0;
3548             }
3549             return matched;
3550         }
3551 
3552         void
3553         OptionParsingStarting() override
3554         {
3555             // -1 means the -c option hasn't been set
3556             m_coord[0] = -1;
3557             m_coord[1] = -1;
3558             m_coord[2] = -1;
3559         }
3560 
3561         const OptionDefinition*
3562         GetDefinitions() override
3563         {
3564             return g_option_table;
3565         }
3566 
3567         static OptionDefinition g_option_table[];
3568         std::array<int,3> m_coord;
3569     };
3570 
3571     bool
3572     DoExecute(Args &command, CommandReturnObject &result) override
3573     {
3574         const size_t argc = command.GetArgumentCount();
3575         if (argc < 1)
3576         {
3577             result.AppendErrorWithFormat("'%s' takes 1 argument of kernel name, and an optional coordinate.", m_cmd_name.c_str());
3578             result.SetStatus(eReturnStatusFailed);
3579             return false;
3580         }
3581 
3582         RenderScriptRuntime *runtime =
3583                 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
3584 
3585         Error error;
3586         runtime->PlaceBreakpointOnKernel(result.GetOutputStream(), command.GetArgumentAtIndex(0), m_options.m_coord,
3587                                          error, m_exe_ctx.GetTargetSP());
3588 
3589         if (error.Success())
3590         {
3591             result.AppendMessage("Breakpoint(s) created");
3592             result.SetStatus(eReturnStatusSuccessFinishResult);
3593             return true;
3594         }
3595         result.SetStatus(eReturnStatusFailed);
3596         result.AppendErrorWithFormat("Error: %s", error.AsCString());
3597         return false;
3598     }
3599 
3600 private:
3601     CommandOptions m_options;
3602 };
3603 
3604 OptionDefinition
3605 CommandObjectRenderScriptRuntimeKernelBreakpointSet::CommandOptions::g_option_table[] =
3606 {
3607     { LLDB_OPT_SET_1, false, "coordinate", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeValue,
3608       "Set a breakpoint on a single invocation of the kernel with specified coordinate.\n"
3609       "Coordinate takes the form 'x[,y][,z] where x,y,z are positive integers representing kernel dimensions. "
3610       "Any unset dimensions will be defaulted to zero."},
3611     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
3612 };
3613 
3614 class CommandObjectRenderScriptRuntimeKernelBreakpointAll : public CommandObjectParsed
3615 {
3616 public:
3617     CommandObjectRenderScriptRuntimeKernelBreakpointAll(CommandInterpreter &interpreter)
3618         : CommandObjectParsed(interpreter, "renderscript kernel breakpoint all",
3619                               "Automatically sets a breakpoint on all renderscript kernels that are or will be loaded.\n"
3620                               "Disabling option means breakpoints will no longer be set on any kernels loaded in the future, "
3621                               "but does not remove currently set breakpoints.",
3622                               "renderscript kernel breakpoint all <enable/disable>",
3623                               eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused)
3624     {
3625     }
3626 
3627     ~CommandObjectRenderScriptRuntimeKernelBreakpointAll() override = default;
3628 
3629     bool
3630     DoExecute(Args &command, CommandReturnObject &result) override
3631     {
3632         const size_t argc = command.GetArgumentCount();
3633         if (argc != 1)
3634         {
3635             result.AppendErrorWithFormat("'%s' takes 1 argument of 'enable' or 'disable'", m_cmd_name.c_str());
3636             result.SetStatus(eReturnStatusFailed);
3637             return false;
3638         }
3639 
3640         RenderScriptRuntime *runtime =
3641           static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
3642 
3643         bool do_break = false;
3644         const char* argument = command.GetArgumentAtIndex(0);
3645         if (strcmp(argument, "enable") == 0)
3646         {
3647             do_break = true;
3648             result.AppendMessage("Breakpoints will be set on all kernels.");
3649         }
3650         else if (strcmp(argument, "disable") == 0)
3651         {
3652             do_break = false;
3653             result.AppendMessage("Breakpoints will not be set on any new kernels.");
3654         }
3655         else
3656         {
3657             result.AppendErrorWithFormat("Argument must be either 'enable' or 'disable'");
3658             result.SetStatus(eReturnStatusFailed);
3659             return false;
3660         }
3661 
3662         runtime->SetBreakAllKernels(do_break, m_exe_ctx.GetTargetSP());
3663 
3664         result.SetStatus(eReturnStatusSuccessFinishResult);
3665         return true;
3666     }
3667 };
3668 
3669 class CommandObjectRenderScriptRuntimeKernelCoordinate : public CommandObjectParsed
3670 {
3671 public:
3672     CommandObjectRenderScriptRuntimeKernelCoordinate(CommandInterpreter &interpreter)
3673         : CommandObjectParsed(interpreter, "renderscript kernel coordinate",
3674                               "Shows the (x,y,z) coordinate of the current kernel invocation.",
3675                               "renderscript kernel coordinate",
3676                               eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused)
3677     {
3678     }
3679 
3680     ~CommandObjectRenderScriptRuntimeKernelCoordinate() override = default;
3681 
3682     bool
3683     DoExecute(Args &command, CommandReturnObject &result) override
3684     {
3685         RSCoordinate coord{}; // Zero initialize array
3686         bool success = RenderScriptRuntime::GetKernelCoordinate(coord, m_exe_ctx.GetThreadPtr());
3687         Stream &stream = result.GetOutputStream();
3688 
3689         if (success)
3690         {
3691             stream.Printf("Coordinate: (%" PRIu32 ", %" PRIu32 ", %" PRIu32 ")", coord[0], coord[1], coord[2]);
3692             stream.EOL();
3693             result.SetStatus(eReturnStatusSuccessFinishResult);
3694         }
3695         else
3696         {
3697             stream.Printf("Error: Coordinate could not be found.");
3698             stream.EOL();
3699             result.SetStatus(eReturnStatusFailed);
3700         }
3701         return true;
3702     }
3703 };
3704 
3705 class CommandObjectRenderScriptRuntimeKernelBreakpoint : public CommandObjectMultiword
3706 {
3707 public:
3708     CommandObjectRenderScriptRuntimeKernelBreakpoint(CommandInterpreter &interpreter)
3709         : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that generate breakpoints on renderscript kernels.",
3710                                  nullptr)
3711     {
3712         LoadSubCommand("set", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointSet(interpreter)));
3713         LoadSubCommand("all", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointAll(interpreter)));
3714     }
3715 
3716     ~CommandObjectRenderScriptRuntimeKernelBreakpoint() override = default;
3717 };
3718 
3719 class CommandObjectRenderScriptRuntimeKernel : public CommandObjectMultiword
3720 {
3721 public:
3722     CommandObjectRenderScriptRuntimeKernel(CommandInterpreter &interpreter)
3723         : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that deal with renderscript kernels.",
3724                                  NULL)
3725     {
3726         LoadSubCommand("list", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelList(interpreter)));
3727         LoadSubCommand("breakpoint", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpoint(interpreter)));
3728         LoadSubCommand("coordinate", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelCoordinate(interpreter)));
3729     }
3730 
3731     ~CommandObjectRenderScriptRuntimeKernel() override = default;
3732 };
3733 
3734 class CommandObjectRenderScriptRuntimeContextDump : public CommandObjectParsed
3735 {
3736 public:
3737     CommandObjectRenderScriptRuntimeContextDump(CommandInterpreter &interpreter)
3738         : CommandObjectParsed(interpreter, "renderscript context dump",
3739                               "Dumps renderscript context information.", "renderscript context dump",
3740                               eCommandRequiresProcess | eCommandProcessMustBeLaunched)
3741     {
3742     }
3743 
3744     ~CommandObjectRenderScriptRuntimeContextDump() override = default;
3745 
3746     bool
3747     DoExecute(Args &command, CommandReturnObject &result) override
3748     {
3749         RenderScriptRuntime *runtime =
3750             (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
3751         runtime->DumpContexts(result.GetOutputStream());
3752         result.SetStatus(eReturnStatusSuccessFinishResult);
3753         return true;
3754     }
3755 };
3756 
3757 class CommandObjectRenderScriptRuntimeContext : public CommandObjectMultiword
3758 {
3759 public:
3760     CommandObjectRenderScriptRuntimeContext(CommandInterpreter &interpreter)
3761         : CommandObjectMultiword(interpreter, "renderscript context", "Commands that deal with renderscript contexts.",
3762                                  NULL)
3763     {
3764         LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeContextDump(interpreter)));
3765     }
3766 
3767     ~CommandObjectRenderScriptRuntimeContext() override = default;
3768 };
3769 
3770 class CommandObjectRenderScriptRuntimeAllocationDump : public CommandObjectParsed
3771 {
3772 public:
3773     CommandObjectRenderScriptRuntimeAllocationDump(CommandInterpreter &interpreter)
3774         : CommandObjectParsed(interpreter, "renderscript allocation dump",
3775                               "Displays the contents of a particular allocation", "renderscript allocation dump <ID>",
3776                               eCommandRequiresProcess | eCommandProcessMustBeLaunched), m_options(interpreter)
3777     {
3778     }
3779 
3780     ~CommandObjectRenderScriptRuntimeAllocationDump() override = default;
3781 
3782     Options*
3783     GetOptions() override
3784     {
3785         return &m_options;
3786     }
3787 
3788     class CommandOptions : public Options
3789     {
3790     public:
3791         CommandOptions(CommandInterpreter &interpreter) : Options(interpreter)
3792         {
3793         }
3794 
3795         ~CommandOptions() override = default;
3796 
3797         Error
3798         SetOptionValue(uint32_t option_idx, const char *option_arg) override
3799         {
3800             Error error;
3801             const int short_option = m_getopt_table[option_idx].val;
3802 
3803             switch (short_option)
3804             {
3805                 case 'f':
3806                     m_outfile.SetFile(option_arg, true);
3807                     if (m_outfile.Exists())
3808                     {
3809                         m_outfile.Clear();
3810                         error.SetErrorStringWithFormat("file already exists: '%s'", option_arg);
3811                     }
3812                     break;
3813                 default:
3814                     error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
3815                     break;
3816             }
3817             return error;
3818         }
3819 
3820         void
3821         OptionParsingStarting() override
3822         {
3823             m_outfile.Clear();
3824         }
3825 
3826         const OptionDefinition*
3827         GetDefinitions() override
3828         {
3829             return g_option_table;
3830         }
3831 
3832         static OptionDefinition g_option_table[];
3833         FileSpec m_outfile;
3834     };
3835 
3836     bool
3837     DoExecute(Args &command, CommandReturnObject &result) override
3838     {
3839         const size_t argc = command.GetArgumentCount();
3840         if (argc < 1)
3841         {
3842             result.AppendErrorWithFormat("'%s' takes 1 argument, an allocation ID. As well as an optional -f argument",
3843                                          m_cmd_name.c_str());
3844             result.SetStatus(eReturnStatusFailed);
3845             return false;
3846         }
3847 
3848         RenderScriptRuntime *runtime =
3849           static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
3850 
3851         const char* id_cstr = command.GetArgumentAtIndex(0);
3852         bool convert_complete = false;
3853         const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete);
3854         if (!convert_complete)
3855         {
3856             result.AppendErrorWithFormat("invalid allocation id argument '%s'", id_cstr);
3857             result.SetStatus(eReturnStatusFailed);
3858             return false;
3859         }
3860 
3861         Stream* output_strm = nullptr;
3862         StreamFile outfile_stream;
3863         const FileSpec &outfile_spec = m_options.m_outfile; // Dump allocation to file instead
3864         if (outfile_spec)
3865         {
3866             // Open output file
3867             char path[256];
3868             outfile_spec.GetPath(path, sizeof(path));
3869             if (outfile_stream.GetFile().Open(path, File::eOpenOptionWrite | File::eOpenOptionCanCreate).Success())
3870             {
3871                 output_strm = &outfile_stream;
3872                 result.GetOutputStream().Printf("Results written to '%s'", path);
3873                 result.GetOutputStream().EOL();
3874             }
3875             else
3876             {
3877                 result.AppendErrorWithFormat("Couldn't open file '%s'", path);
3878                 result.SetStatus(eReturnStatusFailed);
3879                 return false;
3880             }
3881         }
3882         else
3883             output_strm = &result.GetOutputStream();
3884 
3885         assert(output_strm != nullptr);
3886         bool success = runtime->DumpAllocation(*output_strm, m_exe_ctx.GetFramePtr(), id);
3887 
3888         if (success)
3889             result.SetStatus(eReturnStatusSuccessFinishResult);
3890         else
3891             result.SetStatus(eReturnStatusFailed);
3892 
3893         return true;
3894     }
3895 
3896 private:
3897     CommandOptions m_options;
3898 };
3899 
3900 OptionDefinition
3901 CommandObjectRenderScriptRuntimeAllocationDump::CommandOptions::g_option_table[] =
3902 {
3903     { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFilename,
3904       "Print results to specified file instead of command line."},
3905     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
3906 };
3907 
3908 class CommandObjectRenderScriptRuntimeAllocationList : public CommandObjectParsed
3909 {
3910 public:
3911     CommandObjectRenderScriptRuntimeAllocationList(CommandInterpreter &interpreter)
3912         : CommandObjectParsed(interpreter, "renderscript allocation list",
3913                               "List renderscript allocations and their information.", "renderscript allocation list",
3914                               eCommandRequiresProcess | eCommandProcessMustBeLaunched), m_options(interpreter)
3915     {
3916     }
3917 
3918     ~CommandObjectRenderScriptRuntimeAllocationList() override = default;
3919 
3920     Options*
3921     GetOptions() override
3922     {
3923         return &m_options;
3924     }
3925 
3926     class CommandOptions : public Options
3927     {
3928     public:
3929         CommandOptions(CommandInterpreter &interpreter) : Options(interpreter), m_refresh(false)
3930         {
3931         }
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 'r':
3944                     m_refresh = true;
3945                     break;
3946                 default:
3947                     error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
3948                     break;
3949             }
3950             return error;
3951         }
3952 
3953         void
3954         OptionParsingStarting() override
3955         {
3956             m_refresh = false;
3957         }
3958 
3959         const OptionDefinition*
3960         GetDefinitions() override
3961         {
3962             return g_option_table;
3963         }
3964 
3965         static OptionDefinition g_option_table[];
3966         bool m_refresh;
3967     };
3968 
3969     bool
3970     DoExecute(Args &command, CommandReturnObject &result) override
3971     {
3972         RenderScriptRuntime *runtime =
3973           static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
3974         runtime->ListAllocations(result.GetOutputStream(), m_exe_ctx.GetFramePtr(), m_options.m_refresh);
3975         result.SetStatus(eReturnStatusSuccessFinishResult);
3976         return true;
3977     }
3978 
3979 private:
3980     CommandOptions m_options;
3981 };
3982 
3983 OptionDefinition
3984 CommandObjectRenderScriptRuntimeAllocationList::CommandOptions::g_option_table[] =
3985 {
3986     { LLDB_OPT_SET_1, false, "refresh", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
3987       "Recompute allocation details."},
3988     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
3989 };
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