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