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