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