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::mipsel:
669         {
670 
671             // read from the registers
672             if (arg < 4){
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() - Mips - Error while reading the argument #%d", arg);
684                 }
685 
686             }
687 
688             // read from the stack
689             else
690             {
691                 uint64_t sp = reg_ctx->GetSP();
692                 uint32_t offset = arg * sizeof(uint32_t);
693                 process->ReadMemory(sp + offset, &data, sizeof(uint32_t), error);
694                 if (error.Fail())
695                 {
696                     if (log)
697                         log->Printf ("RenderScriptRuntime::GetArgSimple - error reading Mips stack: %s.", error.AsCString());
698                 }
699                 else
700                 {
701                     success = true;
702                 }
703             }
704 
705             break;
706         }
707         case llvm::Triple::ArchType::mips64el:
708         {
709             // read from the registers
710             if (arg < 8)
711             {
712                 const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg + 4);
713                 RegisterValue rVal;
714                 success = reg_ctx->ReadRegister(rArg, rVal);
715                 if (success)
716                 {
717                     (*data) = rVal.GetAsUInt64();
718                 }
719                 else
720                 {
721                     if (log)
722                         log->Printf("RenderScriptRuntime::GetArgSimple - Mips64 - Error reading the argument #%d", arg);
723                 }
724             }
725 
726             // read from the stack
727             else
728             {
729                 uint64_t sp = reg_ctx->GetSP();
730                 uint32_t offset = (arg - 8) * sizeof(uint64_t);
731                 process->ReadMemory(sp + offset, &data, sizeof(uint64_t), error);
732                 if (error.Fail())
733                 {
734                     if (log)
735                         log->Printf ("RenderScriptRuntime::GetArgSimple - Mips64 - Error reading Mips64 stack: %s.", error.AsCString());
736                 }
737                 else
738                 {
739                     success = true;
740                 }
741             }
742 
743             break;
744         }
745         default:
746         {
747             // invalid architecture
748             if (log)
749                 log->Printf("RenderScriptRuntime::GetArgSimple - Architecture not supported");
750 
751         }
752     }
753 
754     return success;
755 }
756 
757 void
758 RenderScriptRuntime::CaptureSetGlobalVar1(RuntimeHook* hook_info, ExecutionContext& context)
759 {
760     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
761 
762     //Context, Script, int, data, length
763 
764     uint64_t rs_context_u64 = 0U;
765     uint64_t rs_script_u64 = 0U;
766     uint64_t rs_id_u64 = 0U;
767     uint64_t rs_data_u64 = 0U;
768     uint64_t rs_length_u64 = 0U;
769 
770     bool success =
771         GetArgSimple(context, 0, &rs_context_u64) &&
772         GetArgSimple(context, 1, &rs_script_u64) &&
773         GetArgSimple(context, 2, &rs_id_u64) &&
774         GetArgSimple(context, 3, &rs_data_u64) &&
775         GetArgSimple(context, 4, &rs_length_u64);
776 
777     if (!success)
778     {
779         if (log)
780             log->Printf("RenderScriptRuntime::CaptureSetGlobalVar1 - Error while reading the function parameters");
781         return;
782     }
783 
784     if (log)
785     {
786         log->Printf ("RenderScriptRuntime::CaptureSetGlobalVar1 - 0x%" PRIx64 ",0x%" PRIx64 " slot %" PRIu64 " = 0x%" PRIx64 ":%" PRIu64 "bytes.",
787                         rs_context_u64, rs_script_u64, rs_id_u64, rs_data_u64, rs_length_u64);
788 
789         addr_t script_addr =  (addr_t)rs_script_u64;
790         if (m_scriptMappings.find( script_addr ) != m_scriptMappings.end())
791         {
792             auto rsm = m_scriptMappings[script_addr];
793             if (rs_id_u64 < rsm->m_globals.size())
794             {
795                 auto rsg = rsm->m_globals[rs_id_u64];
796                 log->Printf ("RenderScriptRuntime::CaptureSetGlobalVar1 - Setting of '%s' within '%s' inferred", rsg.m_name.AsCString(),
797                                 rsm->m_module->GetFileSpec().GetFilename().AsCString());
798             }
799         }
800     }
801 }
802 
803 void
804 RenderScriptRuntime::CaptureAllocationInit1(RuntimeHook* hook_info, ExecutionContext& context)
805 {
806     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
807 
808     //Context, Alloc, bool
809 
810     uint64_t rs_context_u64 = 0U;
811     uint64_t rs_alloc_u64 = 0U;
812     uint64_t rs_forceZero_u64 = 0U;
813 
814     bool success =
815         GetArgSimple(context, 0, &rs_context_u64) &&
816         GetArgSimple(context, 1, &rs_alloc_u64) &&
817         GetArgSimple(context, 2, &rs_forceZero_u64);
818     if (!success) // error case
819     {
820         if (log)
821             log->Printf("RenderScriptRuntime::CaptureAllocationInit1 - Error while reading the function parameters");
822         return; // abort
823     }
824 
825     if (log)
826         log->Printf ("RenderScriptRuntime::CaptureAllocationInit1 - 0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 " .",
827                         rs_context_u64, rs_alloc_u64, rs_forceZero_u64);
828 
829     AllocationDetails* alloc = LookUpAllocation(rs_alloc_u64, true);
830     if (alloc)
831         alloc->context = rs_context_u64;
832 }
833 
834 void
835 RenderScriptRuntime::CaptureScriptInit1(RuntimeHook* hook_info, ExecutionContext& context)
836 {
837     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
838 
839     //Context, Script, resname Str, cachedir Str
840     Error error;
841     Process* process = context.GetProcessPtr();
842 
843     uint64_t rs_context_u64 = 0U;
844     uint64_t rs_script_u64 = 0U;
845     uint64_t rs_resnameptr_u64 = 0U;
846     uint64_t rs_cachedirptr_u64 = 0U;
847 
848     std::string resname;
849     std::string cachedir;
850 
851     // read the function parameters
852     bool success =
853         GetArgSimple(context, 0, &rs_context_u64) &&
854         GetArgSimple(context, 1, &rs_script_u64) &&
855         GetArgSimple(context, 2, &rs_resnameptr_u64) &&
856         GetArgSimple(context, 3, &rs_cachedirptr_u64);
857 
858     if (!success)
859     {
860         if (log)
861             log->Printf("RenderScriptRuntime::CaptureScriptInit1 - Error while reading the function parameters");
862         return;
863     }
864 
865     process->ReadCStringFromMemory((lldb::addr_t)rs_resnameptr_u64, resname, error);
866     if (error.Fail())
867     {
868         if (log)
869             log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - error reading resname: %s.", error.AsCString());
870 
871     }
872 
873     process->ReadCStringFromMemory((lldb::addr_t)rs_cachedirptr_u64, cachedir, error);
874     if (error.Fail())
875     {
876         if (log)
877             log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - error reading cachedir: %s.", error.AsCString());
878     }
879 
880     if (log)
881         log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - 0x%" PRIx64 ",0x%" PRIx64 " => '%s' at '%s' .",
882                      rs_context_u64, rs_script_u64, resname.c_str(), cachedir.c_str());
883 
884     if (resname.size() > 0)
885     {
886         StreamString strm;
887         strm.Printf("librs.%s.so", resname.c_str());
888 
889         ScriptDetails* script = LookUpScript(rs_script_u64, true);
890         if (script)
891         {
892             script->type = ScriptDetails::eScriptC;
893             script->cacheDir = cachedir;
894             script->resName = resname;
895             script->scriptDyLib = strm.GetData();
896             script->context = addr_t(rs_context_u64);
897         }
898 
899         if (log)
900             log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - '%s' tagged with context 0x%" PRIx64 " and script 0x%" PRIx64 ".",
901                          strm.GetData(), rs_context_u64, rs_script_u64);
902     }
903     else if (log)
904     {
905         log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - resource name invalid, Script not tagged");
906     }
907 }
908 
909 void
910 RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind)
911 {
912     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
913 
914     if (!module)
915     {
916         return;
917     }
918 
919     Target &target = GetProcess()->GetTarget();
920     llvm::Triple::ArchType targetArchType = target.GetArchitecture().GetMachine();
921 
922     if (targetArchType != llvm::Triple::ArchType::x86
923         && targetArchType != llvm::Triple::ArchType::arm
924         && targetArchType != llvm::Triple::ArchType::aarch64
925         && targetArchType != llvm::Triple::ArchType::mipsel
926         && targetArchType != llvm::Triple::ArchType::mips64el
927     )
928     {
929         if (log)
930             log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Unable to hook runtime. Only X86, ARM, Mips supported currently.");
931 
932         return;
933     }
934 
935     uint32_t archByteSize = target.GetArchitecture().GetAddressByteSize();
936 
937     for (size_t idx = 0; idx < s_runtimeHookCount; idx++)
938     {
939         const HookDefn* hook_defn = &s_runtimeHookDefns[idx];
940         if (hook_defn->kind != kind) {
941             continue;
942         }
943 
944         const char* symbol_name = (archByteSize == 4) ? hook_defn->symbol_name_m32 : hook_defn->symbol_name_m64;
945 
946         const Symbol *sym = module->FindFirstSymbolWithNameAndType(ConstString(symbol_name), eSymbolTypeCode);
947         if (!sym){
948             if (log){
949                 log->Printf("RenderScriptRuntime::LoadRuntimeHooks - ERROR: Symbol '%s' related to the function %s not found", symbol_name, hook_defn->name);
950             }
951             continue;
952         }
953 
954         addr_t addr = sym->GetLoadAddress(&target);
955         if (addr == LLDB_INVALID_ADDRESS)
956         {
957             if (log)
958                 log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Unable to resolve the address of hook function '%s' with symbol '%s'.",
959                              hook_defn->name, symbol_name);
960             continue;
961         }
962         else
963         {
964             if (log)
965                 log->Printf("RenderScriptRuntime::LoadRuntimeHooks - Function %s, address resolved at 0x%" PRIx64, hook_defn->name, addr);
966         }
967 
968         RuntimeHookSP hook(new RuntimeHook());
969         hook->address = addr;
970         hook->defn = hook_defn;
971         hook->bp_sp = target.CreateBreakpoint(addr, true, false);
972         hook->bp_sp->SetCallback(HookCallback, hook.get(), true);
973         m_runtimeHooks[addr] = hook;
974         if (log)
975         {
976             log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Successfully hooked '%s' in '%s' version %" PRIu64 " at 0x%" PRIx64 ".",
977                 hook_defn->name, module->GetFileSpec().GetFilename().AsCString(), (uint64_t)hook_defn->version, (uint64_t)addr);
978         }
979     }
980 }
981 
982 void
983 RenderScriptRuntime::FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp)
984 {
985     if (!rsmodule_sp)
986         return;
987 
988     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
989 
990     const ModuleSP module = rsmodule_sp->m_module;
991     const FileSpec& file = module->GetPlatformFileSpec();
992 
993     // Iterate over all of the scripts that we currently know of.
994     // Note: We cant push or pop to m_scripts here or it may invalidate rs_script.
995     for (const auto & rs_script : m_scripts)
996     {
997         // Extract the expected .so file path for this script.
998         std::string dylib;
999         if (!rs_script->scriptDyLib.get(dylib))
1000             continue;
1001 
1002         // Only proceed if the module that has loaded corresponds to this script.
1003         if (file.GetFilename() != ConstString(dylib.c_str()))
1004             continue;
1005 
1006         // Obtain the script address which we use as a key.
1007         lldb::addr_t script;
1008         if (!rs_script->script.get(script))
1009             continue;
1010 
1011         // If we have a script mapping for the current script.
1012         if (m_scriptMappings.find(script) != m_scriptMappings.end())
1013         {
1014             // if the module we have stored is different to the one we just received.
1015             if (m_scriptMappings[script] != rsmodule_sp)
1016             {
1017                 if (log)
1018                     log->Printf ("RenderScriptRuntime::FixupScriptDetails - Error: script %" PRIx64 " wants reassigned to new rsmodule '%s'.",
1019                                     (uint64_t)script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
1020             }
1021         }
1022         // We don't have a script mapping for the current script.
1023         else
1024         {
1025             // Obtain the script resource name.
1026             std::string resName;
1027             if (rs_script->resName.get(resName))
1028                 // Set the modules resource name.
1029                 rsmodule_sp->m_resname = resName;
1030             // Add Script/Module pair to map.
1031             m_scriptMappings[script] = rsmodule_sp;
1032             if (log)
1033                 log->Printf ("RenderScriptRuntime::FixupScriptDetails - script %" PRIx64 " associated with rsmodule '%s'.",
1034                                 (uint64_t)script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
1035         }
1036     }
1037 }
1038 
1039 // Uses the Target API to evaluate the expression passed as a parameter to the function
1040 // The result of that expression is returned an unsigned 64 bit int, via the result* paramter.
1041 // Function returns true on success, and false on failure
1042 bool
1043 RenderScriptRuntime::EvalRSExpression(const char* expression, StackFrame* frame_ptr, uint64_t* result)
1044 {
1045     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1046     if (log)
1047         log->Printf("RenderScriptRuntime::EvalRSExpression(%s)", expression);
1048 
1049     ValueObjectSP expr_result;
1050     // Perform the actual expression evaluation
1051     GetProcess()->GetTarget().EvaluateExpression(expression, frame_ptr, expr_result);
1052 
1053     if (!expr_result)
1054     {
1055        if (log)
1056            log->Printf("RenderScriptRuntime::EvalRSExpression -  Error: Couldn't evaluate expression");
1057        return false;
1058     }
1059 
1060     // The result of the expression is invalid
1061     if (!expr_result->GetError().Success())
1062     {
1063         Error err = expr_result->GetError();
1064         if (err.GetError() == UserExpression::kNoResult) // Expression returned void, so this is actually a success
1065         {
1066             if (log)
1067                 log->Printf("RenderScriptRuntime::EvalRSExpression - Expression returned void");
1068 
1069             result = nullptr;
1070             return true;
1071         }
1072 
1073         if (log)
1074             log->Printf("RenderScriptRuntime::EvalRSExpression - Error evaluating expression result: %s", err.AsCString());
1075         return false;
1076     }
1077 
1078     bool success = false;
1079     *result = expr_result->GetValueAsUnsigned(0, &success); // We only read the result as an unsigned int.
1080 
1081     if (!success)
1082     {
1083        if (log)
1084            log->Printf("RenderScriptRuntime::EvalRSExpression -  Error: Couldn't convert expression result to unsigned int");
1085        return false;
1086     }
1087 
1088     return true;
1089 }
1090 
1091 // Used to index expression format strings
1092 enum ExpressionStrings
1093 {
1094    eExprGetOffsetPtr = 0,
1095    eExprAllocGetType,
1096    eExprTypeDimX,
1097    eExprTypeDimY,
1098    eExprTypeDimZ,
1099    eExprTypeElemPtr,
1100    eExprElementType,
1101    eExprElementKind,
1102    eExprElementVec
1103 };
1104 
1105 // Format strings containing the expressions we may need to evaluate.
1106 const char runtimeExpressions[][256] =
1107 {
1108  // Mangled GetOffsetPointer(Allocation*, xoff, yoff, zoff, lod, cubemap)
1109  "(int*)_Z12GetOffsetPtrPKN7android12renderscript10AllocationEjjjj23RsAllocationCubemapFace(0x%lx, %u, %u, %u, 0, 0)",
1110 
1111  // Type* rsaAllocationGetType(Context*, Allocation*)
1112  "(void*)rsaAllocationGetType(0x%lx, 0x%lx)",
1113 
1114  // rsaTypeGetNativeData(Context*, Type*, void* typeData, size)
1115  // Pack the data in the following way mHal.state.dimX; mHal.state.dimY; mHal.state.dimZ;
1116  // mHal.state.lodCount; mHal.state.faces; mElement; into typeData
1117  // Need to specify 32 or 64 bit for uint_t since this differs between devices
1118  "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[0]", // X dim
1119  "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[1]", // Y dim
1120  "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[2]", // Z dim
1121  "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[5]", // Element ptr
1122 
1123  // rsaElementGetNativeData(Context*, Element*, uint32_t* elemData,size)
1124  // Pack mType; mKind; mNormalized; mVectorSize; NumSubElements into elemData
1125  "uint32_t data[6]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[0]", // Type
1126  "uint32_t data[6]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[1]", // Kind
1127  "uint32_t data[6]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[3]"  // Vector Size
1128 };
1129 
1130 // JITs the RS runtime for the internal data pointer of an allocation.
1131 // Is passed x,y,z coordinates for the pointer to a specific element.
1132 // Then sets the data_ptr member in Allocation with the result.
1133 // Returns true on success, false otherwise
1134 bool
1135 RenderScriptRuntime::JITDataPointer(AllocationDetails* allocation, StackFrame* frame_ptr,
1136                                     unsigned int x, unsigned int y, unsigned int z)
1137 {
1138     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1139 
1140     if (!allocation->address.isValid())
1141     {
1142         if (log)
1143             log->Printf("RenderScriptRuntime::JITDataPointer - Failed to find allocation details");
1144         return false;
1145     }
1146 
1147     const char* expr_cstr = runtimeExpressions[eExprGetOffsetPtr];
1148     const int max_expr_size = 512; // Max expression size
1149     char buffer[max_expr_size];
1150 
1151     int chars_written = snprintf(buffer, max_expr_size, expr_cstr, *allocation->address.get(), x, y, z);
1152     if (chars_written < 0)
1153     {
1154         if (log)
1155             log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()");
1156         return false;
1157     }
1158     else if (chars_written >= max_expr_size)
1159     {
1160         if (log)
1161             log->Printf("RenderScriptRuntime::JITDataPointer - Expression too long");
1162         return false;
1163     }
1164 
1165     uint64_t result = 0;
1166     if (!EvalRSExpression(buffer, frame_ptr, &result))
1167         return false;
1168 
1169     addr_t mem_ptr = static_cast<lldb::addr_t>(result);
1170     allocation->data_ptr = mem_ptr;
1171 
1172     return true;
1173 }
1174 
1175 // JITs the RS runtime for the internal pointer to the RS Type of an allocation
1176 // Then sets the type_ptr member in Allocation with the result.
1177 // Returns true on success, false otherwise
1178 bool
1179 RenderScriptRuntime::JITTypePointer(AllocationDetails* allocation, StackFrame* frame_ptr)
1180 {
1181     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1182 
1183     if (!allocation->address.isValid() || !allocation->context.isValid())
1184     {
1185         if (log)
1186             log->Printf("RenderScriptRuntime::JITTypePointer - Failed to find allocation details");
1187         return false;
1188     }
1189 
1190     const char* expr_cstr = runtimeExpressions[eExprAllocGetType];
1191     const int max_expr_size = 512; // Max expression size
1192     char buffer[max_expr_size];
1193 
1194     int chars_written = snprintf(buffer, max_expr_size, expr_cstr, *allocation->context.get(), *allocation->address.get());
1195     if (chars_written < 0)
1196     {
1197         if (log)
1198             log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()");
1199         return false;
1200     }
1201     else if (chars_written >= max_expr_size)
1202     {
1203         if (log)
1204             log->Printf("RenderScriptRuntime::JITTypePointer - Expression too long");
1205         return false;
1206     }
1207 
1208     uint64_t result = 0;
1209     if (!EvalRSExpression(buffer, frame_ptr, &result))
1210         return false;
1211 
1212     addr_t type_ptr = static_cast<lldb::addr_t>(result);
1213     allocation->type_ptr = type_ptr;
1214 
1215     return true;
1216 }
1217 
1218 // JITs the RS runtime for information about the dimensions and type of an allocation
1219 // Then sets dimension and element_ptr members in Allocation with the result.
1220 // Returns true on success, false otherwise
1221 bool
1222 RenderScriptRuntime::JITTypePacked(AllocationDetails* allocation, StackFrame* frame_ptr)
1223 {
1224     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1225 
1226     if (!allocation->type_ptr.isValid() || !allocation->context.isValid())
1227     {
1228         if (log)
1229             log->Printf("RenderScriptRuntime::JITTypePacked - Failed to find allocation details");
1230         return false;
1231     }
1232 
1233     // Expression is different depending on if device is 32 or 64 bit
1234     uint32_t archByteSize = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
1235     const unsigned int bits = archByteSize == 4 ? 32 : 64;
1236 
1237     // We want 4 elements from packed data
1238     const unsigned int num_exprs = 4;
1239     assert(num_exprs == (eExprTypeElemPtr - eExprTypeDimX + 1) && "Invalid number of expressions");
1240 
1241     const int max_expr_size = 512; // Max expression size
1242     char buffer[num_exprs][max_expr_size];
1243     uint64_t results[num_exprs];
1244 
1245     for (unsigned int i = 0; i < num_exprs; ++i)
1246     {
1247         int chars_written = snprintf(buffer[i], max_expr_size, runtimeExpressions[eExprTypeDimX + i], bits,
1248                                      *allocation->context.get(), *allocation->type_ptr.get());
1249         if (chars_written < 0)
1250         {
1251             if (log)
1252                 log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()");
1253             return false;
1254         }
1255         else if (chars_written >= max_expr_size)
1256         {
1257             if (log)
1258                 log->Printf("RenderScriptRuntime::JITTypePacked - Expression too long");
1259             return false;
1260         }
1261 
1262         // Perform expression evaluation
1263         if (!EvalRSExpression(buffer[i], frame_ptr, &results[i]))
1264             return false;
1265     }
1266 
1267     // Assign results to allocation members
1268     AllocationDetails::Dimension dims;
1269     dims.dim_1 = static_cast<uint32_t>(results[0]);
1270     dims.dim_2 = static_cast<uint32_t>(results[1]);
1271     dims.dim_3 = static_cast<uint32_t>(results[2]);
1272     allocation->dimension = dims;
1273 
1274     addr_t elem_ptr = static_cast<lldb::addr_t>(results[3]);
1275     allocation->element_ptr = elem_ptr;
1276 
1277     if (log)
1278         log->Printf("RenderScriptRuntime::JITTypePacked - dims (%u, %u, %u) Element*: 0x%" PRIx64,
1279                     dims.dim_1, dims.dim_2, dims.dim_3, elem_ptr);
1280 
1281     return true;
1282 }
1283 
1284 // JITs the RS runtime for information about the Element of an allocation
1285 // Then sets type, type_vec_size, and type_kind members in Allocation with the result.
1286 // Returns true on success, false otherwise
1287 bool
1288 RenderScriptRuntime::JITElementPacked(AllocationDetails* allocation, StackFrame* frame_ptr)
1289 {
1290     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1291 
1292     if (!allocation->element_ptr.isValid() || !allocation->context.isValid())
1293     {
1294         if (log)
1295             log->Printf("RenderScriptRuntime::JITElementPacked - Failed to find allocation details");
1296         return false;
1297     }
1298 
1299     // We want 3 elements from packed data
1300     const unsigned int num_exprs = 3;
1301     assert(num_exprs == (eExprElementVec - eExprElementType + 1) && "Invalid number of expressions");
1302 
1303     const int max_expr_size = 512; // Max expression size
1304     char buffer[num_exprs][max_expr_size];
1305     uint64_t results[num_exprs];
1306 
1307     for (unsigned int i = 0; i < num_exprs; i++)
1308     {
1309         int chars_written = snprintf(buffer[i], max_expr_size, runtimeExpressions[eExprElementType + i], *allocation->context.get(), *allocation->element_ptr.get());
1310         if (chars_written < 0)
1311         {
1312             if (log)
1313                 log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()");
1314             return false;
1315         }
1316         else if (chars_written >= max_expr_size)
1317         {
1318             if (log)
1319                 log->Printf("RenderScriptRuntime::JITElementPacked - Expression too long");
1320             return false;
1321         }
1322 
1323         // Perform expression evaluation
1324         if (!EvalRSExpression(buffer[i], frame_ptr, &results[i]))
1325             return false;
1326     }
1327 
1328     // Assign results to allocation members
1329     allocation->type = static_cast<RenderScriptRuntime::AllocationDetails::DataType>(results[0]);
1330     allocation->type_kind = static_cast<RenderScriptRuntime::AllocationDetails::DataKind>(results[1]);
1331     allocation->type_vec_size = static_cast<uint32_t>(results[2]);
1332 
1333     if (log)
1334         log->Printf("RenderScriptRuntime::JITElementPacked - data type %u, pixel type %u, vector size %u",
1335                     *allocation->type.get(), *allocation->type_kind.get(), *allocation->type_vec_size.get());
1336 
1337     return true;
1338 }
1339 
1340 // JITs the RS runtime for the address of the last element in the allocation.
1341 // The `elem_size` paramter represents the size of a single element, including padding.
1342 // Which is needed as an offset from the last element pointer.
1343 // Using this offset minus the starting address we can calculate the size of the allocation.
1344 // Returns true on success, false otherwise
1345 bool
1346 RenderScriptRuntime::JITAllocationSize(AllocationDetails* allocation, StackFrame* frame_ptr,
1347                                        const uint32_t elem_size)
1348 {
1349     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1350 
1351     if (!allocation->address.isValid() || !allocation->dimension.isValid()
1352         || !allocation->data_ptr.isValid())
1353     {
1354         if (log)
1355             log->Printf("RenderScriptRuntime::JITAllocationSize - Failed to find allocation details");
1356         return false;
1357     }
1358 
1359     const char* expr_cstr = runtimeExpressions[eExprGetOffsetPtr];
1360     const int max_expr_size = 512; // Max expression size
1361     char buffer[max_expr_size];
1362 
1363     // Find dimensions
1364     unsigned int dim_x = allocation->dimension.get()->dim_1;
1365     unsigned int dim_y = allocation->dimension.get()->dim_2;
1366     unsigned int dim_z = allocation->dimension.get()->dim_3;
1367 
1368     // Calculate last element
1369     dim_x = dim_x == 0 ? 0 : dim_x - 1;
1370     dim_y = dim_y == 0 ? 0 : dim_y - 1;
1371     dim_z = dim_z == 0 ? 0 : dim_z - 1;
1372 
1373     int chars_written = snprintf(buffer, max_expr_size, expr_cstr, *allocation->address.get(),
1374                                  dim_x, dim_y, dim_z);
1375     if (chars_written < 0)
1376     {
1377         if (log)
1378             log->Printf("RenderScriptRuntime::JITAllocationSize - Encoding error in snprintf()");
1379         return false;
1380     }
1381     else if (chars_written >= max_expr_size)
1382     {
1383         if (log)
1384             log->Printf("RenderScriptRuntime::JITAllocationSize - Expression too long");
1385         return false;
1386     }
1387 
1388     uint64_t result = 0;
1389     if (!EvalRSExpression(buffer, frame_ptr, &result))
1390         return false;
1391 
1392     addr_t mem_ptr = static_cast<lldb::addr_t>(result);
1393     // Find pointer to last element and add on size of an element
1394     allocation->size = static_cast<uint32_t>(mem_ptr - *allocation->data_ptr.get()) + elem_size;
1395 
1396     return true;
1397 }
1398 
1399 // JITs the RS runtime for information about the stride between rows in the allocation.
1400 // This is done to detect padding, since allocated memory is 16-byte aligned.
1401 // Returns true on success, false otherwise
1402 bool
1403 RenderScriptRuntime::JITAllocationStride(AllocationDetails* allocation, StackFrame* frame_ptr)
1404 {
1405     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1406 
1407     if (!allocation->address.isValid() || !allocation->data_ptr.isValid())
1408     {
1409         if (log)
1410             log->Printf("RenderScriptRuntime::JITAllocationStride - Failed to find allocation details");
1411         return false;
1412     }
1413 
1414     const char* expr_cstr = runtimeExpressions[eExprGetOffsetPtr];
1415     const int max_expr_size = 512; // Max expression size
1416     char buffer[max_expr_size];
1417 
1418     int chars_written = snprintf(buffer, max_expr_size, expr_cstr, *allocation->address.get(),
1419                                  0, 1, 0);
1420     if (chars_written < 0)
1421     {
1422         if (log)
1423             log->Printf("RenderScriptRuntime::JITAllocationStride - Encoding error in snprintf()");
1424         return false;
1425     }
1426     else if (chars_written >= max_expr_size)
1427     {
1428         if (log)
1429             log->Printf("RenderScriptRuntime::JITAllocationStride - Expression too long");
1430         return false;
1431     }
1432 
1433     uint64_t result = 0;
1434     if (!EvalRSExpression(buffer, frame_ptr, &result))
1435         return false;
1436 
1437     addr_t mem_ptr = static_cast<lldb::addr_t>(result);
1438     allocation->stride = static_cast<uint32_t>(mem_ptr - *allocation->data_ptr.get());
1439 
1440     return true;
1441 }
1442 
1443 // JIT all the current runtime info regarding an allocation
1444 bool
1445 RenderScriptRuntime::RefreshAllocation(AllocationDetails* allocation, StackFrame* frame_ptr)
1446 {
1447     // GetOffsetPointer()
1448     if (!JITDataPointer(allocation, frame_ptr))
1449         return false;
1450 
1451     // rsaAllocationGetType()
1452     if (!JITTypePointer(allocation, frame_ptr))
1453         return false;
1454 
1455     // rsaTypeGetNativeData()
1456     if (!JITTypePacked(allocation, frame_ptr))
1457         return false;
1458 
1459     // rsaElementGetNativeData()
1460     if (!JITElementPacked(allocation, frame_ptr))
1461         return false;
1462 
1463     // Use GetOffsetPointer() to infer size of the allocation
1464     const unsigned int element_size = GetElementSize(allocation);
1465     if (!JITAllocationSize(allocation, frame_ptr, element_size))
1466         return false;
1467 
1468     return true;
1469 }
1470 
1471 // Returns the size of a single allocation element including padding.
1472 // Assumes the relevant allocation information has already been jitted.
1473 unsigned int
1474 RenderScriptRuntime::GetElementSize(const AllocationDetails* allocation)
1475 {
1476     const AllocationDetails::DataType type = *allocation->type.get();
1477     assert(type >= AllocationDetails::RS_TYPE_NONE && type <= AllocationDetails::RS_TYPE_BOOLEAN
1478                                                    && "Invalid allocation type");
1479 
1480     const unsigned int vec_size = *allocation->type_vec_size.get();
1481     const unsigned int data_size = vec_size * AllocationDetails::RSTypeToFormat[type][eElementSize];
1482     const unsigned int padding = vec_size == 3 ? AllocationDetails::RSTypeToFormat[type][eElementSize] : 0;
1483 
1484     return data_size + padding;
1485 }
1486 
1487 // Given an allocation, this function copies the allocation contents from device into a buffer on the heap.
1488 // Returning a shared pointer to the buffer containing the data.
1489 std::shared_ptr<uint8_t>
1490 RenderScriptRuntime::GetAllocationData(AllocationDetails* allocation, StackFrame* frame_ptr)
1491 {
1492     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1493 
1494     // JIT all the allocation details
1495     if (!allocation->data_ptr.isValid() || !allocation->type.isValid() || !allocation->type_vec_size.isValid()
1496         || !allocation->size.isValid())
1497     {
1498         if (log)
1499             log->Printf("RenderScriptRuntime::GetAllocationData - Allocation details not calculated yet, jitting info");
1500 
1501         if (!RefreshAllocation(allocation, frame_ptr))
1502         {
1503             if (log)
1504                 log->Printf("RenderScriptRuntime::GetAllocationData - Couldn't JIT allocation details");
1505             return nullptr;
1506         }
1507     }
1508 
1509     assert(allocation->data_ptr.isValid() && allocation->type.isValid() && allocation->type_vec_size.isValid()
1510            && allocation->size.isValid() && "Allocation information not available");
1511 
1512     // Allocate a buffer to copy data into
1513     const unsigned int size = *allocation->size.get();
1514     std::shared_ptr<uint8_t> buffer(new uint8_t[size]);
1515     if (!buffer)
1516     {
1517         if (log)
1518             log->Printf("RenderScriptRuntime::GetAllocationData - Couldn't allocate a %u byte buffer", size);
1519         return nullptr;
1520     }
1521 
1522     // Read the inferior memory
1523     Error error;
1524     lldb::addr_t data_ptr = *allocation->data_ptr.get();
1525     GetProcess()->ReadMemory(data_ptr, buffer.get(), size, error);
1526     if (error.Fail())
1527     {
1528         if (log)
1529             log->Printf("RenderScriptRuntime::GetAllocationData - '%s' Couldn't read %u bytes of allocation data from 0x%" PRIx64,
1530                         error.AsCString(), size, data_ptr);
1531         return nullptr;
1532     }
1533 
1534     return buffer;
1535 }
1536 
1537 // Function copies data from a binary file into an allocation.
1538 // There is a header at the start of the file, FileHeader, before the data content itself.
1539 // Information from this header is used to display warnings to the user about incompatabilities
1540 bool
1541 RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id, const char* filename, StackFrame* frame_ptr)
1542 {
1543     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1544 
1545     // Find allocation with the given id
1546     AllocationDetails* alloc = FindAllocByID(strm, alloc_id);
1547     if (!alloc)
1548         return false;
1549 
1550     if (log)
1551         log->Printf("RenderScriptRuntime::LoadAllocation - Found allocation 0x%" PRIx64, *alloc->address.get());
1552 
1553     // JIT all the allocation details
1554     if (!alloc->data_ptr.isValid() || !alloc->type.isValid() || !alloc->type_vec_size.isValid() || !alloc->size.isValid())
1555     {
1556         if (log)
1557             log->Printf("RenderScriptRuntime::LoadAllocation - Allocation details not calculated yet, jitting info");
1558 
1559         if (!RefreshAllocation(alloc, frame_ptr))
1560         {
1561             if (log)
1562                 log->Printf("RenderScriptRuntime::LoadAllocation - Couldn't JIT allocation details");
1563             return false;
1564         }
1565     }
1566 
1567     assert(alloc->data_ptr.isValid() && alloc->type.isValid() && alloc->type_vec_size.isValid() && alloc->size.isValid()
1568            && "Allocation information not available");
1569 
1570     // Check we can read from file
1571     FileSpec file(filename, true);
1572     if (!file.Exists())
1573     {
1574         strm.Printf("Error: File %s does not exist", filename);
1575         strm.EOL();
1576         return false;
1577     }
1578 
1579     if (!file.Readable())
1580     {
1581         strm.Printf("Error: File %s does not have readable permissions", filename);
1582         strm.EOL();
1583         return false;
1584     }
1585 
1586     // Read file into data buffer
1587     DataBufferSP data_sp(file.ReadFileContents());
1588 
1589     // Cast start of buffer to FileHeader and use pointer to read metadata
1590     void* file_buffer = data_sp->GetBytes();
1591     const AllocationDetails::FileHeader* head = static_cast<AllocationDetails::FileHeader*>(file_buffer);
1592 
1593     // Advance buffer past header
1594     file_buffer = static_cast<uint8_t*>(file_buffer) + head->hdr_size;
1595 
1596     if (log)
1597         log->Printf("RenderScriptRuntime::LoadAllocation - header type %u, element size %u",
1598                     head->type, head->element_size);
1599 
1600     // Check if the target allocation and file both have the same number of bytes for an Element
1601     const unsigned int elem_size = GetElementSize(alloc);
1602     if (elem_size != head->element_size)
1603     {
1604         strm.Printf("Warning: Mismatched Element sizes - file %u bytes, allocation %u bytes",
1605                     head->element_size, elem_size);
1606         strm.EOL();
1607     }
1608 
1609     // Check if the target allocation and file both have the same integral type
1610     const unsigned int type = static_cast<unsigned int>(*alloc->type.get());
1611     if (type != head->type)
1612     {
1613         const char* file_type_cstr = AllocationDetails::RsDataTypeToString[head->type][0];
1614         const char* alloc_type_cstr = AllocationDetails::RsDataTypeToString[type][0];
1615 
1616         strm.Printf("Warning: Mismatched Types - file '%s' type, allocation '%s' type",
1617                     file_type_cstr, alloc_type_cstr);
1618         strm.EOL();
1619     }
1620 
1621     // Calculate size of allocation data in file
1622     size_t length = data_sp->GetByteSize() - head->hdr_size;
1623 
1624     // Check if the target allocation and file both have the same total data size.
1625     const unsigned int alloc_size = *alloc->size.get();
1626     if (alloc_size != length)
1627     {
1628         strm.Printf("Warning: Mismatched allocation sizes - file 0x%" PRIx64 " bytes, allocation 0x%x bytes",
1629                     (uint64_t) length, alloc_size);
1630         strm.EOL();
1631         length = alloc_size < length ? alloc_size : length; // Set length to copy to minimum
1632     }
1633 
1634     // Copy file data from our buffer into the target allocation.
1635     lldb::addr_t alloc_data = *alloc->data_ptr.get();
1636     Error error;
1637     size_t bytes_written = GetProcess()->WriteMemory(alloc_data, file_buffer, length, error);
1638     if (!error.Success() || bytes_written != length)
1639     {
1640         strm.Printf("Error: Couldn't write data to allocation %s", error.AsCString());
1641         strm.EOL();
1642         return false;
1643     }
1644 
1645     strm.Printf("Contents of file '%s' read into allocation %u", filename, alloc->id);
1646     strm.EOL();
1647 
1648     return true;
1649 }
1650 
1651 // Function copies allocation contents into a binary file.
1652 // This file can then be loaded later into a different allocation.
1653 // There is a header, FileHeader, before the allocation data containing meta-data.
1654 bool
1655 RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id, const char* filename, StackFrame* frame_ptr)
1656 {
1657     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1658 
1659     // Find allocation with the given id
1660     AllocationDetails* alloc = FindAllocByID(strm, alloc_id);
1661     if (!alloc)
1662         return false;
1663 
1664     if (log)
1665         log->Printf("RenderScriptRuntime::SaveAllocation - Found allocation 0x%" PRIx64, *alloc->address.get());
1666 
1667      // JIT all the allocation details
1668     if (!alloc->data_ptr.isValid() || !alloc->type.isValid() || !alloc->type_vec_size.isValid()
1669         || !alloc->type_kind.isValid() || !alloc->dimension.isValid())
1670     {
1671         if (log)
1672             log->Printf("RenderScriptRuntime::SaveAllocation - Allocation details not calculated yet, jitting info");
1673 
1674         if (!RefreshAllocation(alloc, frame_ptr))
1675         {
1676             if (log)
1677                 log->Printf("RenderScriptRuntime::SaveAllocation - Couldn't JIT allocation details");
1678             return false;
1679         }
1680     }
1681 
1682     assert(alloc->data_ptr.isValid() && alloc->type.isValid() && alloc->type_vec_size.isValid() && alloc->type_kind.isValid()
1683            && alloc->dimension.isValid() && "Allocation information not available");
1684 
1685     // Check we can create writable file
1686     FileSpec file_spec(filename, true);
1687     File file(file_spec, File::eOpenOptionWrite | File::eOpenOptionCanCreate | File::eOpenOptionTruncate);
1688     if (!file)
1689     {
1690         strm.Printf("Error: Failed to open '%s' for writing", filename);
1691         strm.EOL();
1692         return false;
1693     }
1694 
1695     // Read allocation into buffer of heap memory
1696     const std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr);
1697     if (!buffer)
1698     {
1699         strm.Printf("Error: Couldn't read allocation data into buffer");
1700         strm.EOL();
1701         return false;
1702     }
1703 
1704     // Create the file header
1705     AllocationDetails::FileHeader head;
1706     head.ident[0] = 'R'; head.ident[1] = 'S'; head.ident[2] = 'A'; head.ident[3] = 'D';
1707     head.hdr_size = static_cast<uint16_t>(sizeof(AllocationDetails::FileHeader));
1708     head.type = static_cast<uint16_t>(*alloc->type.get());
1709     head.kind = static_cast<uint32_t>(*alloc->type_kind.get());
1710     head.dims[0] = static_cast<uint32_t>(alloc->dimension.get()->dim_1);
1711     head.dims[1] = static_cast<uint32_t>(alloc->dimension.get()->dim_2);
1712     head.dims[2] = static_cast<uint32_t>(alloc->dimension.get()->dim_3);
1713     head.element_size = static_cast<uint32_t>(GetElementSize(alloc));
1714 
1715     // Write the file header
1716     size_t num_bytes = sizeof(AllocationDetails::FileHeader);
1717     Error err = file.Write(static_cast<const void*>(&head), num_bytes);
1718     if (!err.Success())
1719     {
1720         strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), filename);
1721         strm.EOL();
1722         return false;
1723     }
1724 
1725     // Write allocation data to file
1726     num_bytes = static_cast<size_t>(*alloc->size.get());
1727     if (log)
1728         log->Printf("RenderScriptRuntime::SaveAllocation - Writing 0x%" PRIx64 " bytes from %p", (uint64_t) num_bytes, buffer.get());
1729 
1730     err = file.Write(buffer.get(), num_bytes);
1731     if (!err.Success())
1732     {
1733         strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), filename);
1734         strm.EOL();
1735         return false;
1736     }
1737 
1738     strm.Printf("Allocation written to file '%s'", filename);
1739     strm.EOL();
1740     return true;
1741 }
1742 
1743 bool
1744 RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp)
1745 {
1746     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1747 
1748     if (module_sp)
1749     {
1750         for (const auto &rs_module : m_rsmodules)
1751         {
1752             if (rs_module->m_module == module_sp)
1753             {
1754                 // Check if the user has enabled automatically breaking on
1755                 // all RS kernels.
1756                 if (m_breakAllKernels)
1757                     BreakOnModuleKernels(rs_module);
1758 
1759                 return false;
1760             }
1761         }
1762         bool module_loaded = false;
1763         switch (GetModuleKind(module_sp))
1764         {
1765             case eModuleKindKernelObj:
1766             {
1767                 RSModuleDescriptorSP module_desc;
1768                 module_desc.reset(new RSModuleDescriptor(module_sp));
1769                 if (module_desc->ParseRSInfo())
1770                 {
1771                     m_rsmodules.push_back(module_desc);
1772                     module_loaded = true;
1773                 }
1774                 if (module_loaded)
1775                 {
1776                     FixupScriptDetails(module_desc);
1777                 }
1778                 break;
1779             }
1780             case eModuleKindDriver:
1781             {
1782                 if (!m_libRSDriver)
1783                 {
1784                     m_libRSDriver = module_sp;
1785                     LoadRuntimeHooks(m_libRSDriver, RenderScriptRuntime::eModuleKindDriver);
1786                 }
1787                 break;
1788             }
1789             case eModuleKindImpl:
1790             {
1791                 m_libRSCpuRef = module_sp;
1792                 break;
1793             }
1794             case eModuleKindLibRS:
1795             {
1796                 if (!m_libRS)
1797                 {
1798                     m_libRS = module_sp;
1799                     static ConstString gDbgPresentStr("gDebuggerPresent");
1800                     const Symbol* debug_present = m_libRS->FindFirstSymbolWithNameAndType(gDbgPresentStr, eSymbolTypeData);
1801                     if (debug_present)
1802                     {
1803                         Error error;
1804                         uint32_t flag = 0x00000001U;
1805                         Target &target = GetProcess()->GetTarget();
1806                         addr_t addr = debug_present->GetLoadAddress(&target);
1807                         GetProcess()->WriteMemory(addr, &flag, sizeof(flag), error);
1808                         if(error.Success())
1809                         {
1810                             if (log)
1811                                 log->Printf ("RenderScriptRuntime::LoadModule - Debugger present flag set on debugee");
1812 
1813                             m_debuggerPresentFlagged = true;
1814                         }
1815                         else if (log)
1816                         {
1817                             log->Printf ("RenderScriptRuntime::LoadModule - Error writing debugger present flags '%s' ", error.AsCString());
1818                         }
1819                     }
1820                     else if (log)
1821                     {
1822                         log->Printf ("RenderScriptRuntime::LoadModule - Error writing debugger present flags - symbol not found");
1823                     }
1824                 }
1825                 break;
1826             }
1827             default:
1828                 break;
1829         }
1830         if (module_loaded)
1831             Update();
1832         return module_loaded;
1833     }
1834     return false;
1835 }
1836 
1837 void
1838 RenderScriptRuntime::Update()
1839 {
1840     if (m_rsmodules.size() > 0)
1841     {
1842         if (!m_initiated)
1843         {
1844             Initiate();
1845         }
1846     }
1847 }
1848 
1849 // The maximum line length of an .rs.info packet
1850 #define MAXLINE 500
1851 
1852 // The .rs.info symbol in renderscript modules contains a string which needs to be parsed.
1853 // The string is basic and is parsed on a line by line basis.
1854 bool
1855 RSModuleDescriptor::ParseRSInfo()
1856 {
1857     const Symbol *info_sym = m_module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData);
1858     if (info_sym)
1859     {
1860         const addr_t addr = info_sym->GetAddressRef().GetFileAddress();
1861         const addr_t size = info_sym->GetByteSize();
1862         const FileSpec fs = m_module->GetFileSpec();
1863 
1864         DataBufferSP buffer = fs.ReadFileContents(addr, size);
1865 
1866         if (!buffer)
1867             return false;
1868 
1869         std::string info((const char *)buffer->GetBytes());
1870 
1871         std::vector<std::string> info_lines;
1872         size_t lpos = info.find('\n');
1873         while (lpos != std::string::npos)
1874         {
1875             info_lines.push_back(info.substr(0, lpos));
1876             info = info.substr(lpos + 1);
1877             lpos = info.find('\n');
1878         }
1879         size_t offset = 0;
1880         while (offset < info_lines.size())
1881         {
1882             std::string line = info_lines[offset];
1883             // Parse directives
1884             uint32_t numDefns = 0;
1885             if (sscanf(line.c_str(), "exportVarCount: %u", &numDefns) == 1)
1886             {
1887                 while (numDefns--)
1888                     m_globals.push_back(RSGlobalDescriptor(this, info_lines[++offset].c_str()));
1889             }
1890             else if (sscanf(line.c_str(), "exportFuncCount: %u", &numDefns) == 1)
1891             {
1892             }
1893             else if (sscanf(line.c_str(), "exportForEachCount: %u", &numDefns) == 1)
1894             {
1895                 char name[MAXLINE];
1896                 while (numDefns--)
1897                 {
1898                     uint32_t slot = 0;
1899                     name[0] = '\0';
1900                     if (sscanf(info_lines[++offset].c_str(), "%u - %s", &slot, &name[0]) == 2)
1901                     {
1902                         m_kernels.push_back(RSKernelDescriptor(this, name, slot));
1903                     }
1904                 }
1905             }
1906             else if (sscanf(line.c_str(), "pragmaCount: %u", &numDefns) == 1)
1907             {
1908                 char name[MAXLINE];
1909                 char value[MAXLINE];
1910                 while (numDefns--)
1911                 {
1912                     name[0] = '\0';
1913                     value[0] = '\0';
1914                     if (sscanf(info_lines[++offset].c_str(), "%s - %s", &name[0], &value[0]) != 0
1915                         && (name[0] != '\0'))
1916                     {
1917                         m_pragmas[std::string(name)] = value;
1918                     }
1919                 }
1920             }
1921             else if (sscanf(line.c_str(), "objectSlotCount: %u", &numDefns) == 1)
1922             {
1923             }
1924 
1925             offset++;
1926         }
1927         return m_kernels.size() > 0;
1928     }
1929     return false;
1930 }
1931 
1932 bool
1933 RenderScriptRuntime::ProbeModules(const ModuleList module_list)
1934 {
1935     bool rs_found = false;
1936     size_t num_modules = module_list.GetSize();
1937     for (size_t i = 0; i < num_modules; i++)
1938     {
1939         auto module = module_list.GetModuleAtIndex(i);
1940         rs_found |= LoadModule(module);
1941     }
1942     return rs_found;
1943 }
1944 
1945 void
1946 RenderScriptRuntime::Status(Stream &strm) const
1947 {
1948     if (m_libRS)
1949     {
1950         strm.Printf("Runtime Library discovered.");
1951         strm.EOL();
1952     }
1953     if (m_libRSDriver)
1954     {
1955         strm.Printf("Runtime Driver discovered.");
1956         strm.EOL();
1957     }
1958     if (m_libRSCpuRef)
1959     {
1960         strm.Printf("CPU Reference Implementation discovered.");
1961         strm.EOL();
1962     }
1963 
1964     if (m_runtimeHooks.size())
1965     {
1966         strm.Printf("Runtime functions hooked:");
1967         strm.EOL();
1968         for (auto b : m_runtimeHooks)
1969         {
1970             strm.Indent(b.second->defn->name);
1971             strm.EOL();
1972         }
1973         strm.EOL();
1974     }
1975     else
1976     {
1977         strm.Printf("Runtime is not hooked.");
1978         strm.EOL();
1979     }
1980 }
1981 
1982 void
1983 RenderScriptRuntime::DumpContexts(Stream &strm) const
1984 {
1985     strm.Printf("Inferred RenderScript Contexts:");
1986     strm.EOL();
1987     strm.IndentMore();
1988 
1989     std::map<addr_t, uint64_t> contextReferences;
1990 
1991     // Iterate over all of the currently discovered scripts.
1992     // Note: We cant push or pop from m_scripts inside this loop or it may invalidate script.
1993     for (const auto & script : m_scripts)
1994     {
1995         if (!script->context.isValid())
1996             continue;
1997         lldb::addr_t context = *script->context;
1998 
1999         if (contextReferences.find(context) != contextReferences.end())
2000         {
2001             contextReferences[context]++;
2002         }
2003         else
2004         {
2005             contextReferences[context] = 1;
2006         }
2007     }
2008 
2009     for (const auto& cRef : contextReferences)
2010     {
2011         strm.Printf("Context 0x%" PRIx64 ": %" PRIu64 " script instances", cRef.first, cRef.second);
2012         strm.EOL();
2013     }
2014     strm.IndentLess();
2015 }
2016 
2017 void
2018 RenderScriptRuntime::DumpKernels(Stream &strm) const
2019 {
2020     strm.Printf("RenderScript Kernels:");
2021     strm.EOL();
2022     strm.IndentMore();
2023     for (const auto &module : m_rsmodules)
2024     {
2025         strm.Printf("Resource '%s':",module->m_resname.c_str());
2026         strm.EOL();
2027         for (const auto &kernel : module->m_kernels)
2028         {
2029             strm.Indent(kernel.m_name.AsCString());
2030             strm.EOL();
2031         }
2032     }
2033     strm.IndentLess();
2034 }
2035 
2036 RenderScriptRuntime::AllocationDetails*
2037 RenderScriptRuntime::FindAllocByID(Stream &strm, const uint32_t alloc_id)
2038 {
2039     AllocationDetails* alloc = nullptr;
2040 
2041     // See if we can find allocation using id as an index;
2042     if (alloc_id <= m_allocations.size() && alloc_id != 0
2043         && m_allocations[alloc_id-1]->id == alloc_id)
2044     {
2045         alloc = m_allocations[alloc_id-1].get();
2046         return alloc;
2047     }
2048 
2049     // Fallback to searching
2050     for (const auto & a : m_allocations)
2051     {
2052        if (a->id == alloc_id)
2053        {
2054            alloc = a.get();
2055            break;
2056        }
2057     }
2058 
2059     if (alloc == nullptr)
2060     {
2061         strm.Printf("Error: Couldn't find allocation with id matching %u", alloc_id);
2062         strm.EOL();
2063     }
2064 
2065     return alloc;
2066 }
2067 
2068 // Prints the contents of an allocation to the output stream, which may be a file
2069 bool
2070 RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame* frame_ptr, const uint32_t id)
2071 {
2072     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
2073 
2074     // Check we can find the desired allocation
2075     AllocationDetails* alloc = FindAllocByID(strm, id);
2076     if (!alloc)
2077         return false; // FindAllocByID() will print error message for us here
2078 
2079     if (log)
2080         log->Printf("RenderScriptRuntime::DumpAllocation - Found allocation 0x%" PRIx64, *alloc->address.get());
2081 
2082     // Check we have information about the allocation, if not calculate it
2083     if (!alloc->data_ptr.isValid() || !alloc->type.isValid() ||
2084         !alloc->type_vec_size.isValid() || !alloc->dimension.isValid())
2085     {
2086         if (log)
2087             log->Printf("RenderScriptRuntime::DumpAllocation - Allocation details not calculated yet, jitting info");
2088 
2089         // JIT all the allocation information
2090         if (!RefreshAllocation(alloc, frame_ptr))
2091         {
2092             strm.Printf("Error: Couldn't JIT allocation details");
2093             strm.EOL();
2094             return false;
2095         }
2096     }
2097 
2098     // Establish format and size of each data element
2099     const unsigned int vec_size = *alloc->type_vec_size.get();
2100     const AllocationDetails::DataType type = *alloc->type.get();
2101 
2102     assert(type >= AllocationDetails::RS_TYPE_NONE && type <= AllocationDetails::RS_TYPE_BOOLEAN
2103                                                    && "Invalid allocation type");
2104 
2105     lldb::Format format = vec_size == 1 ? static_cast<lldb::Format>(AllocationDetails::RSTypeToFormat[type][eFormatSingle])
2106                                         : static_cast<lldb::Format>(AllocationDetails::RSTypeToFormat[type][eFormatVector]);
2107 
2108     const unsigned int data_size = vec_size * AllocationDetails::RSTypeToFormat[type][eElementSize];
2109     // Renderscript pads vector 3 elements to vector 4
2110     const unsigned int elem_padding = vec_size == 3 ? AllocationDetails::RSTypeToFormat[type][eElementSize] : 0;
2111 
2112     if (log)
2113         log->Printf("RenderScriptRuntime::DumpAllocation - Element size %u bytes, element padding %u bytes",
2114                     data_size, elem_padding);
2115 
2116     // Allocate a buffer to copy data into
2117     std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr);
2118     if (!buffer)
2119     {
2120         strm.Printf("Error: Couldn't allocate a read allocation data into memory");
2121         strm.EOL();
2122         return false;
2123     }
2124 
2125     // Calculate stride between rows as there may be padding at end of rows since
2126     // allocated memory is 16-byte aligned
2127     if (!alloc->stride.isValid())
2128     {
2129         if (alloc->dimension.get()->dim_2 == 0) // We only have one dimension
2130             alloc->stride = 0;
2131         else if (!JITAllocationStride(alloc, frame_ptr))
2132         {
2133             strm.Printf("Error: Couldn't calculate allocation row stride");
2134             strm.EOL();
2135             return false;
2136         }
2137     }
2138     const unsigned int stride = *alloc->stride.get();
2139     const unsigned int size = *alloc->size.get(); //size of last element
2140 
2141     if (log)
2142         log->Printf("RenderScriptRuntime::DumpAllocation - stride %u bytes, size %u bytes", stride, size);
2143 
2144     // Find dimensions used to index loops, so need to be non-zero
2145     unsigned int dim_x = alloc->dimension.get()->dim_1;
2146     dim_x = dim_x == 0 ? 1 : dim_x;
2147 
2148     unsigned int dim_y = alloc->dimension.get()->dim_2;
2149     dim_y = dim_y == 0 ? 1 : dim_y;
2150 
2151     unsigned int dim_z = alloc->dimension.get()->dim_3;
2152     dim_z = dim_z == 0 ? 1 : dim_z;
2153 
2154     // Use data extractor to format output
2155     const uint32_t archByteSize = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
2156     DataExtractor alloc_data(buffer.get(), size, GetProcess()->GetByteOrder(), archByteSize);
2157 
2158     unsigned int offset = 0;   // Offset in buffer to next element to be printed
2159     unsigned int prev_row = 0; // Offset to the start of the previous row
2160 
2161     // Iterate over allocation dimensions, printing results to user
2162     strm.Printf("Data (X, Y, Z):");
2163     for (unsigned int z = 0; z < dim_z; ++z)
2164     {
2165         for (unsigned int y = 0; y < dim_y; ++y)
2166         {
2167             // Use stride to index start of next row.
2168             if (!(y==0 && z==0))
2169                 offset = prev_row + stride;
2170             prev_row = offset;
2171 
2172             // Print each element in the row individually
2173             for (unsigned int x = 0; x < dim_x; ++x)
2174             {
2175                 strm.Printf("\n(%u, %u, %u) = ", x, y, z);
2176                 alloc_data.Dump(&strm, offset, format, data_size, 1, 1, LLDB_INVALID_ADDRESS, 0, 0);
2177                 offset += data_size + elem_padding;
2178             }
2179         }
2180     }
2181     strm.EOL();
2182 
2183     return true;
2184 }
2185 
2186 // Prints infomation regarding all the currently loaded allocations.
2187 // These details are gathered by jitting the runtime, which has as latency.
2188 void
2189 RenderScriptRuntime::ListAllocations(Stream &strm, StackFrame* frame_ptr, bool recompute)
2190 {
2191     strm.Printf("RenderScript Allocations:");
2192     strm.EOL();
2193     strm.IndentMore();
2194 
2195     for (auto &alloc : m_allocations)
2196     {
2197         // JIT the allocation info if we haven't done it, or the user forces us to.
2198         bool do_refresh = !alloc->data_ptr.isValid() || recompute;
2199 
2200         // JIT current allocation information
2201         if (do_refresh && !RefreshAllocation(alloc.get(), frame_ptr))
2202         {
2203             strm.Printf("Error: Couldn't evaluate details for allocation %u\n", alloc->id);
2204             continue;
2205         }
2206 
2207         strm.Printf("%u:\n",alloc->id);
2208         strm.IndentMore();
2209 
2210         strm.Indent("Context: ");
2211         if (!alloc->context.isValid())
2212             strm.Printf("unknown\n");
2213         else
2214             strm.Printf("0x%" PRIx64 "\n", *alloc->context.get());
2215 
2216         strm.Indent("Address: ");
2217         if (!alloc->address.isValid())
2218             strm.Printf("unknown\n");
2219         else
2220             strm.Printf("0x%" PRIx64 "\n", *alloc->address.get());
2221 
2222         strm.Indent("Data pointer: ");
2223         if (!alloc->data_ptr.isValid())
2224             strm.Printf("unknown\n");
2225         else
2226             strm.Printf("0x%" PRIx64 "\n", *alloc->data_ptr.get());
2227 
2228         strm.Indent("Dimensions: ");
2229         if (!alloc->dimension.isValid())
2230             strm.Printf("unknown\n");
2231         else
2232             strm.Printf("(%d, %d, %d)\n", alloc->dimension.get()->dim_1,
2233                                           alloc->dimension.get()->dim_2,
2234                                           alloc->dimension.get()->dim_3);
2235 
2236         strm.Indent("Data Type: ");
2237         if (!alloc->type.isValid() || !alloc->type_vec_size.isValid())
2238             strm.Printf("unknown\n");
2239         else
2240         {
2241             const int vector_size = *alloc->type_vec_size.get();
2242             const AllocationDetails::DataType type = *alloc->type.get();
2243 
2244             if (vector_size > 4 || vector_size < 1 ||
2245                 type < AllocationDetails::RS_TYPE_NONE || type > AllocationDetails::RS_TYPE_BOOLEAN)
2246                 strm.Printf("invalid type\n");
2247             else
2248                 strm.Printf("%s\n", AllocationDetails::RsDataTypeToString[static_cast<unsigned int>(type)][vector_size-1]);
2249         }
2250 
2251         strm.Indent("Data Kind: ");
2252         if (!alloc->type_kind.isValid())
2253             strm.Printf("unknown\n");
2254         else
2255         {
2256             const AllocationDetails::DataKind kind = *alloc->type_kind.get();
2257             if (kind < AllocationDetails::RS_KIND_USER || kind > AllocationDetails::RS_KIND_PIXEL_YUV)
2258                 strm.Printf("invalid kind\n");
2259             else
2260                 strm.Printf("%s\n", AllocationDetails::RsDataKindToString[static_cast<unsigned int>(kind)]);
2261         }
2262 
2263         strm.EOL();
2264         strm.IndentLess();
2265     }
2266     strm.IndentLess();
2267 }
2268 
2269 // Set breakpoints on every kernel found in RS module
2270 void
2271 RenderScriptRuntime::BreakOnModuleKernels(const RSModuleDescriptorSP rsmodule_sp)
2272 {
2273     for (const auto &kernel : rsmodule_sp->m_kernels)
2274     {
2275         // Don't set breakpoint on 'root' kernel
2276         if (strcmp(kernel.m_name.AsCString(), "root") == 0)
2277             continue;
2278 
2279         CreateKernelBreakpoint(kernel.m_name);
2280     }
2281 }
2282 
2283 // Method is internally called by the 'kernel breakpoint all' command to
2284 // enable or disable breaking on all kernels.
2285 //
2286 // When do_break is true we want to enable this functionality.
2287 // When do_break is false we want to disable it.
2288 void
2289 RenderScriptRuntime::SetBreakAllKernels(bool do_break, TargetSP target)
2290 {
2291     Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
2292 
2293     InitSearchFilter(target);
2294 
2295     // Set breakpoints on all the kernels
2296     if (do_break && !m_breakAllKernels)
2297     {
2298         m_breakAllKernels = true;
2299 
2300         for (const auto &module : m_rsmodules)
2301             BreakOnModuleKernels(module);
2302 
2303         if (log)
2304             log->Printf("RenderScriptRuntime::SetBreakAllKernels(True)"
2305                         "- breakpoints set on all currently loaded kernels");
2306     }
2307     else if (!do_break && m_breakAllKernels) // Breakpoints won't be set on any new kernels.
2308     {
2309         m_breakAllKernels = false;
2310 
2311         if (log)
2312             log->Printf("RenderScriptRuntime::SetBreakAllKernels(False) - breakpoints no longer automatically set");
2313     }
2314 }
2315 
2316 // Given the name of a kernel this function creates a breakpoint using our
2317 // own breakpoint resolver, and returns the Breakpoint shared pointer.
2318 BreakpointSP
2319 RenderScriptRuntime::CreateKernelBreakpoint(const ConstString& name)
2320 {
2321     Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
2322 
2323     if (!m_filtersp)
2324     {
2325         if (log)
2326             log->Printf("RenderScriptRuntime::CreateKernelBreakpoint - Error: No breakpoint search filter set");
2327         return nullptr;
2328     }
2329 
2330     BreakpointResolverSP resolver_sp(new RSBreakpointResolver(nullptr, name));
2331     BreakpointSP bp = GetProcess()->GetTarget().CreateBreakpoint(m_filtersp, resolver_sp, false, false, false);
2332 
2333     // Give RS breakpoints a specific name, so the user can manipulate them as a group.
2334     Error err;
2335     if (!bp->AddName("RenderScriptKernel", err) && log)
2336         log->Printf("RenderScriptRuntime::CreateKernelBreakpoint: Error setting break name, %s", err.AsCString());
2337 
2338     return bp;
2339 }
2340 
2341 // Given an expression for a variable this function tries to calculate the variable's value.
2342 // If this is possible it returns true and sets the uint64_t parameter to the variables unsigned value.
2343 // Otherwise function returns false.
2344 bool
2345 RenderScriptRuntime::GetFrameVarAsUnsigned(const StackFrameSP frame_sp, const char* var_name, uint64_t& val)
2346 {
2347     Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE));
2348     Error error;
2349     VariableSP var_sp;
2350 
2351     // Find variable in stack frame
2352     ValueObjectSP value_sp(frame_sp->GetValueForVariableExpressionPath(var_name,
2353                                                                        eNoDynamicValues,
2354                                                                        StackFrame::eExpressionPathOptionCheckPtrVsMember |
2355                                                                        StackFrame::eExpressionPathOptionsAllowDirectIVarAccess,
2356                                                                        var_sp,
2357                                                                        error));
2358     if (!error.Success())
2359     {
2360         if (log)
2361             log->Printf("RenderScriptRuntime::GetFrameVarAsUnsigned - Error, couldn't find '%s' in frame", var_name);
2362 
2363         return false;
2364     }
2365 
2366     // Find the unsigned int value for the variable
2367     bool success = false;
2368     val = value_sp->GetValueAsUnsigned(0, &success);
2369     if (!success)
2370     {
2371         if (log)
2372             log->Printf("RenderScriptRuntime::GetFrameVarAsUnsigned - Error, couldn't parse '%s' as an unsigned int", var_name);
2373 
2374         return false;
2375     }
2376 
2377     return true;
2378 }
2379 
2380 // Callback when a kernel breakpoint hits and we're looking for a specific coordinate.
2381 // Baton parameter contains a pointer to the target coordinate we want to break on.
2382 // Function then checks the .expand frame for the current coordinate and breaks to user if it matches.
2383 // Parameter 'break_id' is the id of the Breakpoint which made the callback.
2384 // Parameter 'break_loc_id' is the id for the BreakpointLocation which was hit,
2385 // a single logical breakpoint can have multiple addresses.
2386 bool
2387 RenderScriptRuntime::KernelBreakpointHit(void *baton, StoppointCallbackContext *ctx,
2388                                          user_id_t break_id, user_id_t break_loc_id)
2389 {
2390     Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
2391 
2392     assert(baton && "Error: null baton in conditional kernel breakpoint callback");
2393 
2394     // Coordinate we want to stop on
2395     const int* target_coord = static_cast<const int*>(baton);
2396 
2397     if (log)
2398         log->Printf("RenderScriptRuntime::KernelBreakpointHit - Break ID %" PRIu64 ", target coord (%d, %d, %d)",
2399                     break_id, target_coord[0], target_coord[1], target_coord[2]);
2400 
2401     // Go up one stack frame to .expand kernel
2402     ExecutionContext context(ctx->exe_ctx_ref);
2403     ThreadSP thread_sp = context.GetThreadSP();
2404     if (!thread_sp->SetSelectedFrameByIndex(1))
2405     {
2406         if (log)
2407             log->Printf("RenderScriptRuntime::KernelBreakpointHit - Error, couldn't go up stack frame");
2408 
2409        return false;
2410     }
2411 
2412     StackFrameSP frame_sp = thread_sp->GetSelectedFrame();
2413     if (!frame_sp)
2414     {
2415         if (log)
2416             log->Printf("RenderScriptRuntime::KernelBreakpointHit - Error, couldn't select .expand stack frame");
2417 
2418         return false;
2419     }
2420 
2421     // Get values for variables in .expand frame that tell us the current kernel invocation
2422     const char* coord_expressions[] = {"rsIndex", "p->current.y", "p->current.z"};
2423     uint64_t current_coord[3] = {0, 0, 0};
2424 
2425     for(int i = 0; i < 3; ++i)
2426     {
2427         if (!GetFrameVarAsUnsigned(frame_sp, coord_expressions[i], current_coord[i]))
2428             return false;
2429 
2430         if (log)
2431             log->Printf("RenderScriptRuntime::KernelBreakpointHit, %s = %" PRIu64, coord_expressions[i], current_coord[i]);
2432     }
2433 
2434     // Check if the current kernel invocation coordinate matches our target coordinate
2435     if (current_coord[0] == static_cast<uint64_t>(target_coord[0]) &&
2436         current_coord[1] == static_cast<uint64_t>(target_coord[1]) &&
2437         current_coord[2] == static_cast<uint64_t>(target_coord[2]))
2438     {
2439         if (log)
2440              log->Printf("RenderScriptRuntime::KernelBreakpointHit, BREAKING %" PRIu64 ", %" PRIu64 ", %" PRIu64,
2441                          current_coord[0], current_coord[1], current_coord[2]);
2442 
2443         BreakpointSP breakpoint_sp = context.GetTargetPtr()->GetBreakpointByID(break_id);
2444         assert(breakpoint_sp != nullptr && "Error: Couldn't find breakpoint matching break id for callback");
2445         breakpoint_sp->SetEnabled(false); // Optimise since conditional breakpoint should only be hit once.
2446         return true;
2447     }
2448 
2449     // No match on coordinate
2450     return false;
2451 }
2452 
2453 // Tries to set a breakpoint on the start of a kernel, resolved using the kernel name.
2454 // Argument 'coords', represents a three dimensional coordinate which can be used to specify
2455 // a single kernel instance to break on. If this is set then we add a callback to the breakpoint.
2456 void
2457 RenderScriptRuntime::PlaceBreakpointOnKernel(Stream &strm, const char* name, const std::array<int,3> coords,
2458                                              Error& error, TargetSP target)
2459 {
2460     if (!name)
2461     {
2462         error.SetErrorString("invalid kernel name");
2463         return;
2464     }
2465 
2466     InitSearchFilter(target);
2467 
2468     ConstString kernel_name(name);
2469     BreakpointSP bp = CreateKernelBreakpoint(kernel_name);
2470 
2471     // We have a conditional breakpoint on a specific coordinate
2472     if (coords[0] != -1)
2473     {
2474         strm.Printf("Conditional kernel breakpoint on coordinate %d, %d, %d", coords[0], coords[1], coords[2]);
2475         strm.EOL();
2476 
2477         // Allocate memory for the baton, and copy over coordinate
2478         int* baton = new int[3];
2479         baton[0] = coords[0]; baton[1] = coords[1]; baton[2] = coords[2];
2480 
2481         // Create a callback that will be invoked everytime the breakpoint is hit.
2482         // The baton object passed to the handler is the target coordinate we want to break on.
2483         bp->SetCallback(KernelBreakpointHit, baton, true);
2484 
2485         // Store a shared pointer to the baton, so the memory will eventually be cleaned up after destruction
2486         m_conditional_breaks[bp->GetID()] = std::shared_ptr<int>(baton);
2487     }
2488 
2489     if (bp)
2490         bp->GetDescription(&strm, lldb::eDescriptionLevelInitial, false);
2491 }
2492 
2493 void
2494 RenderScriptRuntime::DumpModules(Stream &strm) const
2495 {
2496     strm.Printf("RenderScript Modules:");
2497     strm.EOL();
2498     strm.IndentMore();
2499     for (const auto &module : m_rsmodules)
2500     {
2501         module->Dump(strm);
2502     }
2503     strm.IndentLess();
2504 }
2505 
2506 RenderScriptRuntime::ScriptDetails*
2507 RenderScriptRuntime::LookUpScript(addr_t address, bool create)
2508 {
2509     for (const auto & s : m_scripts)
2510     {
2511         if (s->script.isValid())
2512             if (*s->script == address)
2513                 return s.get();
2514     }
2515     if (create)
2516     {
2517         std::unique_ptr<ScriptDetails> s(new ScriptDetails);
2518         s->script = address;
2519         m_scripts.push_back(std::move(s));
2520         return m_scripts.back().get();
2521     }
2522     return nullptr;
2523 }
2524 
2525 RenderScriptRuntime::AllocationDetails*
2526 RenderScriptRuntime::LookUpAllocation(addr_t address, bool create)
2527 {
2528     for (const auto & a : m_allocations)
2529     {
2530         if (a->address.isValid())
2531             if (*a->address == address)
2532                 return a.get();
2533     }
2534     if (create)
2535     {
2536         std::unique_ptr<AllocationDetails> a(new AllocationDetails);
2537         a->address = address;
2538         m_allocations.push_back(std::move(a));
2539         return m_allocations.back().get();
2540     }
2541     return nullptr;
2542 }
2543 
2544 void
2545 RSModuleDescriptor::Dump(Stream &strm) const
2546 {
2547     strm.Indent();
2548     m_module->GetFileSpec().Dump(&strm);
2549     if(m_module->GetNumCompileUnits())
2550     {
2551         strm.Indent("Debug info loaded.");
2552     }
2553     else
2554     {
2555         strm.Indent("Debug info does not exist.");
2556     }
2557     strm.EOL();
2558     strm.IndentMore();
2559     strm.Indent();
2560     strm.Printf("Globals: %" PRIu64, static_cast<uint64_t>(m_globals.size()));
2561     strm.EOL();
2562     strm.IndentMore();
2563     for (const auto &global : m_globals)
2564     {
2565         global.Dump(strm);
2566     }
2567     strm.IndentLess();
2568     strm.Indent();
2569     strm.Printf("Kernels: %" PRIu64, static_cast<uint64_t>(m_kernels.size()));
2570     strm.EOL();
2571     strm.IndentMore();
2572     for (const auto &kernel : m_kernels)
2573     {
2574         kernel.Dump(strm);
2575     }
2576     strm.Printf("Pragmas: %"  PRIu64 , static_cast<uint64_t>(m_pragmas.size()));
2577     strm.EOL();
2578     strm.IndentMore();
2579     for (const auto &key_val : m_pragmas)
2580     {
2581         strm.Printf("%s: %s", key_val.first.c_str(), key_val.second.c_str());
2582         strm.EOL();
2583     }
2584     strm.IndentLess(4);
2585 }
2586 
2587 void
2588 RSGlobalDescriptor::Dump(Stream &strm) const
2589 {
2590     strm.Indent(m_name.AsCString());
2591     VariableList var_list;
2592     m_module->m_module->FindGlobalVariables(m_name, nullptr, true, 1U, var_list);
2593     if (var_list.GetSize() == 1)
2594     {
2595         auto var = var_list.GetVariableAtIndex(0);
2596         auto type = var->GetType();
2597         if(type)
2598         {
2599             strm.Printf(" - ");
2600             type->DumpTypeName(&strm);
2601         }
2602         else
2603         {
2604             strm.Printf(" - Unknown Type");
2605         }
2606     }
2607     else
2608     {
2609         strm.Printf(" - variable identified, but not found in binary");
2610         const Symbol* s = m_module->m_module->FindFirstSymbolWithNameAndType(m_name, eSymbolTypeData);
2611         if (s)
2612         {
2613             strm.Printf(" (symbol exists) ");
2614         }
2615     }
2616 
2617     strm.EOL();
2618 }
2619 
2620 void
2621 RSKernelDescriptor::Dump(Stream &strm) const
2622 {
2623     strm.Indent(m_name.AsCString());
2624     strm.EOL();
2625 }
2626 
2627 class CommandObjectRenderScriptRuntimeModuleProbe : public CommandObjectParsed
2628 {
2629 public:
2630     CommandObjectRenderScriptRuntimeModuleProbe(CommandInterpreter &interpreter)
2631         : CommandObjectParsed(interpreter, "renderscript module probe",
2632                               "Initiates a Probe of all loaded modules for kernels and other renderscript objects.",
2633                               "renderscript module probe",
2634                               eCommandRequiresTarget | eCommandRequiresProcess | eCommandProcessMustBeLaunched)
2635     {
2636     }
2637 
2638     ~CommandObjectRenderScriptRuntimeModuleProbe() override = default;
2639 
2640     bool
2641     DoExecute(Args &command, CommandReturnObject &result) override
2642     {
2643         const size_t argc = command.GetArgumentCount();
2644         if (argc == 0)
2645         {
2646             Target *target = m_exe_ctx.GetTargetPtr();
2647             RenderScriptRuntime *runtime =
2648                 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
2649             auto module_list = target->GetImages();
2650             bool new_rs_details = runtime->ProbeModules(module_list);
2651             if (new_rs_details)
2652             {
2653                 result.AppendMessage("New renderscript modules added to runtime model.");
2654             }
2655             result.SetStatus(eReturnStatusSuccessFinishResult);
2656             return true;
2657         }
2658 
2659         result.AppendErrorWithFormat("'%s' takes no arguments", m_cmd_name.c_str());
2660         result.SetStatus(eReturnStatusFailed);
2661         return false;
2662     }
2663 };
2664 
2665 class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed
2666 {
2667 public:
2668     CommandObjectRenderScriptRuntimeModuleDump(CommandInterpreter &interpreter)
2669         : CommandObjectParsed(interpreter, "renderscript module dump",
2670                               "Dumps renderscript specific information for all modules.", "renderscript module dump",
2671                               eCommandRequiresProcess | eCommandProcessMustBeLaunched)
2672     {
2673     }
2674 
2675     ~CommandObjectRenderScriptRuntimeModuleDump() override = default;
2676 
2677     bool
2678     DoExecute(Args &command, CommandReturnObject &result) override
2679     {
2680         RenderScriptRuntime *runtime =
2681             (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
2682         runtime->DumpModules(result.GetOutputStream());
2683         result.SetStatus(eReturnStatusSuccessFinishResult);
2684         return true;
2685     }
2686 };
2687 
2688 class CommandObjectRenderScriptRuntimeModule : public CommandObjectMultiword
2689 {
2690 public:
2691     CommandObjectRenderScriptRuntimeModule(CommandInterpreter &interpreter)
2692         : CommandObjectMultiword(interpreter, "renderscript module", "Commands that deal with renderscript modules.",
2693                                  NULL)
2694     {
2695         LoadSubCommand("probe", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleProbe(interpreter)));
2696         LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleDump(interpreter)));
2697     }
2698 
2699     ~CommandObjectRenderScriptRuntimeModule() override = default;
2700 };
2701 
2702 class CommandObjectRenderScriptRuntimeKernelList : public CommandObjectParsed
2703 {
2704 public:
2705     CommandObjectRenderScriptRuntimeKernelList(CommandInterpreter &interpreter)
2706         : CommandObjectParsed(interpreter, "renderscript kernel list",
2707                               "Lists renderscript kernel names and associated script resources.", "renderscript kernel list",
2708                               eCommandRequiresProcess | eCommandProcessMustBeLaunched)
2709     {
2710     }
2711 
2712     ~CommandObjectRenderScriptRuntimeKernelList() override = default;
2713 
2714     bool
2715     DoExecute(Args &command, CommandReturnObject &result) override
2716     {
2717         RenderScriptRuntime *runtime =
2718             (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
2719         runtime->DumpKernels(result.GetOutputStream());
2720         result.SetStatus(eReturnStatusSuccessFinishResult);
2721         return true;
2722     }
2723 };
2724 
2725 class CommandObjectRenderScriptRuntimeKernelBreakpointSet : public CommandObjectParsed
2726 {
2727 public:
2728     CommandObjectRenderScriptRuntimeKernelBreakpointSet(CommandInterpreter &interpreter)
2729         : CommandObjectParsed(interpreter, "renderscript kernel breakpoint set",
2730                               "Sets a breakpoint on a renderscript kernel.", "renderscript kernel breakpoint set <kernel_name> [-c x,y,z]",
2731                               eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), m_options(interpreter)
2732     {
2733     }
2734 
2735     ~CommandObjectRenderScriptRuntimeKernelBreakpointSet() override = default;
2736 
2737     Options*
2738     GetOptions() override
2739     {
2740         return &m_options;
2741     }
2742 
2743     class CommandOptions : public Options
2744     {
2745     public:
2746         CommandOptions(CommandInterpreter &interpreter) : Options(interpreter)
2747         {
2748         }
2749 
2750         ~CommandOptions() override = default;
2751 
2752         Error
2753         SetOptionValue(uint32_t option_idx, const char *option_arg) override
2754         {
2755             Error error;
2756             const int short_option = m_getopt_table[option_idx].val;
2757 
2758             switch (short_option)
2759             {
2760                 case 'c':
2761                     if (!ParseCoordinate(option_arg))
2762                         error.SetErrorStringWithFormat("Couldn't parse coordinate '%s', should be in format 'x,y,z'.", option_arg);
2763                     break;
2764                 default:
2765                     error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
2766                     break;
2767             }
2768             return error;
2769         }
2770 
2771         // -c takes an argument of the form 'num[,num][,num]'.
2772         // Where 'id_cstr' is this argument with the whitespace trimmed.
2773         // Missing coordinates are defaulted to zero.
2774         bool
2775         ParseCoordinate(const char* id_cstr)
2776         {
2777             RegularExpression regex;
2778             RegularExpression::Match regex_match(3);
2779 
2780             bool matched = false;
2781             if(regex.Compile("^([0-9]+),([0-9]+),([0-9]+)$") && regex.Execute(id_cstr, &regex_match))
2782                 matched = true;
2783             else if(regex.Compile("^([0-9]+),([0-9]+)$") && regex.Execute(id_cstr, &regex_match))
2784                 matched = true;
2785             else if(regex.Compile("^([0-9]+)$") && regex.Execute(id_cstr, &regex_match))
2786                 matched = true;
2787             for(uint32_t i = 0; i < 3; i++)
2788             {
2789                 std::string group;
2790                 if(regex_match.GetMatchAtIndex(id_cstr, i + 1, group))
2791                     m_coord[i] = (uint32_t)strtoul(group.c_str(), NULL, 0);
2792                 else
2793                     m_coord[i] = 0;
2794             }
2795             return matched;
2796         }
2797 
2798         void
2799         OptionParsingStarting() override
2800         {
2801             // -1 means the -c option hasn't been set
2802             m_coord[0] = -1;
2803             m_coord[1] = -1;
2804             m_coord[2] = -1;
2805         }
2806 
2807         const OptionDefinition*
2808         GetDefinitions() override
2809         {
2810             return g_option_table;
2811         }
2812 
2813         static OptionDefinition g_option_table[];
2814         std::array<int,3> m_coord;
2815     };
2816 
2817     bool
2818     DoExecute(Args &command, CommandReturnObject &result) override
2819     {
2820         const size_t argc = command.GetArgumentCount();
2821         if (argc < 1)
2822         {
2823             result.AppendErrorWithFormat("'%s' takes 1 argument of kernel name, and an optional coordinate.", m_cmd_name.c_str());
2824             result.SetStatus(eReturnStatusFailed);
2825             return false;
2826         }
2827 
2828         RenderScriptRuntime *runtime =
2829                 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
2830 
2831         Error error;
2832         runtime->PlaceBreakpointOnKernel(result.GetOutputStream(), command.GetArgumentAtIndex(0), m_options.m_coord,
2833                                          error, m_exe_ctx.GetTargetSP());
2834 
2835         if (error.Success())
2836         {
2837             result.AppendMessage("Breakpoint(s) created");
2838             result.SetStatus(eReturnStatusSuccessFinishResult);
2839             return true;
2840         }
2841         result.SetStatus(eReturnStatusFailed);
2842         result.AppendErrorWithFormat("Error: %s", error.AsCString());
2843         return false;
2844     }
2845 
2846 private:
2847     CommandOptions m_options;
2848 };
2849 
2850 OptionDefinition
2851 CommandObjectRenderScriptRuntimeKernelBreakpointSet::CommandOptions::g_option_table[] =
2852 {
2853     { LLDB_OPT_SET_1, false, "coordinate", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeValue,
2854       "Set a breakpoint on a single invocation of the kernel with specified coordinate.\n"
2855       "Coordinate takes the form 'x[,y][,z] where x,y,z are positive integers representing kernel dimensions. "
2856       "Any unset dimensions will be defaulted to zero."},
2857     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
2858 };
2859 
2860 class CommandObjectRenderScriptRuntimeKernelBreakpointAll : public CommandObjectParsed
2861 {
2862 public:
2863     CommandObjectRenderScriptRuntimeKernelBreakpointAll(CommandInterpreter &interpreter)
2864         : CommandObjectParsed(interpreter, "renderscript kernel breakpoint all",
2865                               "Automatically sets a breakpoint on all renderscript kernels that are or will be loaded.\n"
2866                               "Disabling option means breakpoints will no longer be set on any kernels loaded in the future, "
2867                               "but does not remove currently set breakpoints.",
2868                               "renderscript kernel breakpoint all <enable/disable>",
2869                               eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused)
2870     {
2871     }
2872 
2873     ~CommandObjectRenderScriptRuntimeKernelBreakpointAll() override = default;
2874 
2875     bool
2876     DoExecute(Args &command, CommandReturnObject &result) override
2877     {
2878         const size_t argc = command.GetArgumentCount();
2879         if (argc != 1)
2880         {
2881             result.AppendErrorWithFormat("'%s' takes 1 argument of 'enable' or 'disable'", m_cmd_name.c_str());
2882             result.SetStatus(eReturnStatusFailed);
2883             return false;
2884         }
2885 
2886         RenderScriptRuntime *runtime =
2887           static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
2888 
2889         bool do_break = false;
2890         const char* argument = command.GetArgumentAtIndex(0);
2891         if (strcmp(argument, "enable") == 0)
2892         {
2893             do_break = true;
2894             result.AppendMessage("Breakpoints will be set on all kernels.");
2895         }
2896         else if (strcmp(argument, "disable") == 0)
2897         {
2898             do_break = false;
2899             result.AppendMessage("Breakpoints will not be set on any new kernels.");
2900         }
2901         else
2902         {
2903             result.AppendErrorWithFormat("Argument must be either 'enable' or 'disable'");
2904             result.SetStatus(eReturnStatusFailed);
2905             return false;
2906         }
2907 
2908         runtime->SetBreakAllKernels(do_break, m_exe_ctx.GetTargetSP());
2909 
2910         result.SetStatus(eReturnStatusSuccessFinishResult);
2911         return true;
2912     }
2913 };
2914 
2915 class CommandObjectRenderScriptRuntimeKernelBreakpoint : public CommandObjectMultiword
2916 {
2917 public:
2918     CommandObjectRenderScriptRuntimeKernelBreakpoint(CommandInterpreter &interpreter)
2919         : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that generate breakpoints on renderscript kernels.",
2920                                  nullptr)
2921     {
2922         LoadSubCommand("set", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointSet(interpreter)));
2923         LoadSubCommand("all", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointAll(interpreter)));
2924     }
2925 
2926     ~CommandObjectRenderScriptRuntimeKernelBreakpoint() override = default;
2927 };
2928 
2929 class CommandObjectRenderScriptRuntimeKernel : public CommandObjectMultiword
2930 {
2931 public:
2932     CommandObjectRenderScriptRuntimeKernel(CommandInterpreter &interpreter)
2933         : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that deal with renderscript kernels.",
2934                                  NULL)
2935     {
2936         LoadSubCommand("list", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelList(interpreter)));
2937         LoadSubCommand("breakpoint", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpoint(interpreter)));
2938     }
2939 
2940     ~CommandObjectRenderScriptRuntimeKernel() override = default;
2941 };
2942 
2943 class CommandObjectRenderScriptRuntimeContextDump : public CommandObjectParsed
2944 {
2945 public:
2946     CommandObjectRenderScriptRuntimeContextDump(CommandInterpreter &interpreter)
2947         : CommandObjectParsed(interpreter, "renderscript context dump",
2948                               "Dumps renderscript context information.", "renderscript context dump",
2949                               eCommandRequiresProcess | eCommandProcessMustBeLaunched)
2950     {
2951     }
2952 
2953     ~CommandObjectRenderScriptRuntimeContextDump() override = default;
2954 
2955     bool
2956     DoExecute(Args &command, CommandReturnObject &result) override
2957     {
2958         RenderScriptRuntime *runtime =
2959             (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
2960         runtime->DumpContexts(result.GetOutputStream());
2961         result.SetStatus(eReturnStatusSuccessFinishResult);
2962         return true;
2963     }
2964 };
2965 
2966 class CommandObjectRenderScriptRuntimeContext : public CommandObjectMultiword
2967 {
2968 public:
2969     CommandObjectRenderScriptRuntimeContext(CommandInterpreter &interpreter)
2970         : CommandObjectMultiword(interpreter, "renderscript context", "Commands that deal with renderscript contexts.",
2971                                  NULL)
2972     {
2973         LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeContextDump(interpreter)));
2974     }
2975 
2976     ~CommandObjectRenderScriptRuntimeContext() override = default;
2977 };
2978 
2979 class CommandObjectRenderScriptRuntimeAllocationDump : public CommandObjectParsed
2980 {
2981 public:
2982     CommandObjectRenderScriptRuntimeAllocationDump(CommandInterpreter &interpreter)
2983         : CommandObjectParsed(interpreter, "renderscript allocation dump",
2984                               "Displays the contents of a particular allocation", "renderscript allocation dump <ID>",
2985                               eCommandRequiresProcess | eCommandProcessMustBeLaunched), m_options(interpreter)
2986     {
2987     }
2988 
2989     ~CommandObjectRenderScriptRuntimeAllocationDump() override = default;
2990 
2991     Options*
2992     GetOptions() override
2993     {
2994         return &m_options;
2995     }
2996 
2997     class CommandOptions : public Options
2998     {
2999     public:
3000         CommandOptions(CommandInterpreter &interpreter) : Options(interpreter)
3001         {
3002         }
3003 
3004         ~CommandOptions() override = default;
3005 
3006         Error
3007         SetOptionValue(uint32_t option_idx, const char *option_arg) override
3008         {
3009             Error error;
3010             const int short_option = m_getopt_table[option_idx].val;
3011 
3012             switch (short_option)
3013             {
3014                 case 'f':
3015                     m_outfile.SetFile(option_arg, true);
3016                     if (m_outfile.Exists())
3017                     {
3018                         m_outfile.Clear();
3019                         error.SetErrorStringWithFormat("file already exists: '%s'", option_arg);
3020                     }
3021                     break;
3022                 default:
3023                     error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
3024                     break;
3025             }
3026             return error;
3027         }
3028 
3029         void
3030         OptionParsingStarting() override
3031         {
3032             m_outfile.Clear();
3033         }
3034 
3035         const OptionDefinition*
3036         GetDefinitions() override
3037         {
3038             return g_option_table;
3039         }
3040 
3041         static OptionDefinition g_option_table[];
3042         FileSpec m_outfile;
3043     };
3044 
3045     bool
3046     DoExecute(Args &command, CommandReturnObject &result) override
3047     {
3048         const size_t argc = command.GetArgumentCount();
3049         if (argc < 1)
3050         {
3051             result.AppendErrorWithFormat("'%s' takes 1 argument, an allocation ID. As well as an optional -f argument",
3052                                          m_cmd_name.c_str());
3053             result.SetStatus(eReturnStatusFailed);
3054             return false;
3055         }
3056 
3057         RenderScriptRuntime *runtime =
3058           static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
3059 
3060         const char* id_cstr = command.GetArgumentAtIndex(0);
3061         bool convert_complete = false;
3062         const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete);
3063         if (!convert_complete)
3064         {
3065             result.AppendErrorWithFormat("invalid allocation id argument '%s'", id_cstr);
3066             result.SetStatus(eReturnStatusFailed);
3067             return false;
3068         }
3069 
3070         Stream* output_strm = nullptr;
3071         StreamFile outfile_stream;
3072         const FileSpec &outfile_spec = m_options.m_outfile; // Dump allocation to file instead
3073         if (outfile_spec)
3074         {
3075             // Open output file
3076             char path[256];
3077             outfile_spec.GetPath(path, sizeof(path));
3078             if (outfile_stream.GetFile().Open(path, File::eOpenOptionWrite | File::eOpenOptionCanCreate).Success())
3079             {
3080                 output_strm = &outfile_stream;
3081                 result.GetOutputStream().Printf("Results written to '%s'", path);
3082                 result.GetOutputStream().EOL();
3083             }
3084             else
3085             {
3086                 result.AppendErrorWithFormat("Couldn't open file '%s'", path);
3087                 result.SetStatus(eReturnStatusFailed);
3088                 return false;
3089             }
3090         }
3091         else
3092             output_strm = &result.GetOutputStream();
3093 
3094         assert(output_strm != nullptr);
3095         bool success = runtime->DumpAllocation(*output_strm, m_exe_ctx.GetFramePtr(), id);
3096 
3097         if (success)
3098             result.SetStatus(eReturnStatusSuccessFinishResult);
3099         else
3100             result.SetStatus(eReturnStatusFailed);
3101 
3102         return true;
3103     }
3104 
3105 private:
3106     CommandOptions m_options;
3107 };
3108 
3109 OptionDefinition
3110 CommandObjectRenderScriptRuntimeAllocationDump::CommandOptions::g_option_table[] =
3111 {
3112     { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFilename,
3113       "Print results to specified file instead of command line."},
3114     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
3115 };
3116 
3117 class CommandObjectRenderScriptRuntimeAllocationList : public CommandObjectParsed
3118 {
3119 public:
3120     CommandObjectRenderScriptRuntimeAllocationList(CommandInterpreter &interpreter)
3121         : CommandObjectParsed(interpreter, "renderscript allocation list",
3122                               "List renderscript allocations and their information.", "renderscript allocation list",
3123                               eCommandRequiresProcess | eCommandProcessMustBeLaunched), m_options(interpreter)
3124     {
3125     }
3126 
3127     ~CommandObjectRenderScriptRuntimeAllocationList() override = default;
3128 
3129     Options*
3130     GetOptions() override
3131     {
3132         return &m_options;
3133     }
3134 
3135     class CommandOptions : public Options
3136     {
3137     public:
3138         CommandOptions(CommandInterpreter &interpreter) : Options(interpreter), m_refresh(false)
3139         {
3140         }
3141 
3142         ~CommandOptions() override = default;
3143 
3144         Error
3145         SetOptionValue(uint32_t option_idx, const char *option_arg) override
3146         {
3147             Error error;
3148             const int short_option = m_getopt_table[option_idx].val;
3149 
3150             switch (short_option)
3151             {
3152                 case 'r':
3153                     m_refresh = true;
3154                     break;
3155                 default:
3156                     error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
3157                     break;
3158             }
3159             return error;
3160         }
3161 
3162         void
3163         OptionParsingStarting() override
3164         {
3165             m_refresh = false;
3166         }
3167 
3168         const OptionDefinition*
3169         GetDefinitions() override
3170         {
3171             return g_option_table;
3172         }
3173 
3174         static OptionDefinition g_option_table[];
3175         bool m_refresh;
3176     };
3177 
3178     bool
3179     DoExecute(Args &command, CommandReturnObject &result) override
3180     {
3181         RenderScriptRuntime *runtime =
3182           static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
3183         runtime->ListAllocations(result.GetOutputStream(), m_exe_ctx.GetFramePtr(), m_options.m_refresh);
3184         result.SetStatus(eReturnStatusSuccessFinishResult);
3185         return true;
3186     }
3187 
3188 private:
3189     CommandOptions m_options;
3190 };
3191 
3192 OptionDefinition
3193 CommandObjectRenderScriptRuntimeAllocationList::CommandOptions::g_option_table[] =
3194 {
3195     { LLDB_OPT_SET_1, false, "refresh", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
3196       "Recompute allocation details."},
3197     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
3198 };
3199 
3200 class CommandObjectRenderScriptRuntimeAllocationLoad : public CommandObjectParsed
3201 {
3202 public:
3203     CommandObjectRenderScriptRuntimeAllocationLoad(CommandInterpreter &interpreter)
3204         : CommandObjectParsed(interpreter, "renderscript allocation load",
3205                               "Loads renderscript allocation contents from a file.", "renderscript allocation load <ID> <filename>",
3206                               eCommandRequiresProcess | eCommandProcessMustBeLaunched)
3207     {
3208     }
3209 
3210     ~CommandObjectRenderScriptRuntimeAllocationLoad() override = default;
3211 
3212     bool
3213     DoExecute(Args &command, CommandReturnObject &result) override
3214     {
3215         const size_t argc = command.GetArgumentCount();
3216         if (argc != 2)
3217         {
3218             result.AppendErrorWithFormat("'%s' takes 2 arguments, an allocation ID and filename to read from.", m_cmd_name.c_str());
3219             result.SetStatus(eReturnStatusFailed);
3220             return false;
3221         }
3222 
3223         RenderScriptRuntime *runtime =
3224           static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
3225 
3226         const char* id_cstr = command.GetArgumentAtIndex(0);
3227         bool convert_complete = false;
3228         const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete);
3229         if (!convert_complete)
3230         {
3231             result.AppendErrorWithFormat ("invalid allocation id argument '%s'", id_cstr);
3232             result.SetStatus (eReturnStatusFailed);
3233             return false;
3234         }
3235 
3236         const char* filename = command.GetArgumentAtIndex(1);
3237         bool success = runtime->LoadAllocation(result.GetOutputStream(), id, filename, m_exe_ctx.GetFramePtr());
3238 
3239         if (success)
3240             result.SetStatus(eReturnStatusSuccessFinishResult);
3241         else
3242             result.SetStatus(eReturnStatusFailed);
3243 
3244         return true;
3245     }
3246 };
3247 
3248 class CommandObjectRenderScriptRuntimeAllocationSave : public CommandObjectParsed
3249 {
3250 public:
3251     CommandObjectRenderScriptRuntimeAllocationSave(CommandInterpreter &interpreter)
3252         : CommandObjectParsed(interpreter, "renderscript allocation save",
3253                               "Write renderscript allocation contents to a file.", "renderscript allocation save <ID> <filename>",
3254                               eCommandRequiresProcess | eCommandProcessMustBeLaunched)
3255     {
3256     }
3257 
3258     ~CommandObjectRenderScriptRuntimeAllocationSave() override = default;
3259 
3260     bool
3261     DoExecute(Args &command, CommandReturnObject &result) override
3262     {
3263         const size_t argc = command.GetArgumentCount();
3264         if (argc != 2)
3265         {
3266             result.AppendErrorWithFormat("'%s' takes 2 arguments, an allocation ID and filename to read from.", m_cmd_name.c_str());
3267             result.SetStatus(eReturnStatusFailed);
3268             return false;
3269         }
3270 
3271         RenderScriptRuntime *runtime =
3272           static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
3273 
3274         const char* id_cstr = command.GetArgumentAtIndex(0);
3275         bool convert_complete = false;
3276         const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete);
3277         if (!convert_complete)
3278         {
3279             result.AppendErrorWithFormat ("invalid allocation id argument '%s'", id_cstr);
3280             result.SetStatus (eReturnStatusFailed);
3281             return false;
3282         }
3283 
3284         const char* filename = command.GetArgumentAtIndex(1);
3285         bool success = runtime->SaveAllocation(result.GetOutputStream(), id, filename, m_exe_ctx.GetFramePtr());
3286 
3287         if (success)
3288             result.SetStatus(eReturnStatusSuccessFinishResult);
3289         else
3290             result.SetStatus(eReturnStatusFailed);
3291 
3292         return true;
3293     }
3294 };
3295 
3296 class CommandObjectRenderScriptRuntimeAllocation : public CommandObjectMultiword
3297 {
3298 public:
3299     CommandObjectRenderScriptRuntimeAllocation(CommandInterpreter &interpreter)
3300         : CommandObjectMultiword(interpreter, "renderscript allocation", "Commands that deal with renderscript allocations.",
3301                                  NULL)
3302     {
3303         LoadSubCommand("list", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationList(interpreter)));
3304         LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationDump(interpreter)));
3305         LoadSubCommand("save", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationSave(interpreter)));
3306         LoadSubCommand("load", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationLoad(interpreter)));
3307     }
3308 
3309     ~CommandObjectRenderScriptRuntimeAllocation() override = default;
3310 };
3311 
3312 class CommandObjectRenderScriptRuntimeStatus : public CommandObjectParsed
3313 {
3314 public:
3315     CommandObjectRenderScriptRuntimeStatus(CommandInterpreter &interpreter)
3316         : CommandObjectParsed(interpreter, "renderscript status",
3317                               "Displays current renderscript runtime status.", "renderscript status",
3318                               eCommandRequiresProcess | eCommandProcessMustBeLaunched)
3319     {
3320     }
3321 
3322     ~CommandObjectRenderScriptRuntimeStatus() override = default;
3323 
3324     bool
3325     DoExecute(Args &command, CommandReturnObject &result) override
3326     {
3327         RenderScriptRuntime *runtime =
3328             (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
3329         runtime->Status(result.GetOutputStream());
3330         result.SetStatus(eReturnStatusSuccessFinishResult);
3331         return true;
3332     }
3333 };
3334 
3335 class CommandObjectRenderScriptRuntime : public CommandObjectMultiword
3336 {
3337 public:
3338     CommandObjectRenderScriptRuntime(CommandInterpreter &interpreter)
3339         : CommandObjectMultiword(interpreter, "renderscript", "A set of commands for operating on renderscript.",
3340                                  "renderscript <subcommand> [<subcommand-options>]")
3341     {
3342         LoadSubCommand("module", CommandObjectSP(new CommandObjectRenderScriptRuntimeModule(interpreter)));
3343         LoadSubCommand("status", CommandObjectSP(new CommandObjectRenderScriptRuntimeStatus(interpreter)));
3344         LoadSubCommand("kernel", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernel(interpreter)));
3345         LoadSubCommand("context", CommandObjectSP(new CommandObjectRenderScriptRuntimeContext(interpreter)));
3346         LoadSubCommand("allocation", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocation(interpreter)));
3347     }
3348 
3349     ~CommandObjectRenderScriptRuntime() override = default;
3350 };
3351 
3352 void
3353 RenderScriptRuntime::Initiate()
3354 {
3355     assert(!m_initiated);
3356 }
3357 
3358 RenderScriptRuntime::RenderScriptRuntime(Process *process)
3359     : lldb_private::CPPLanguageRuntime(process), m_initiated(false), m_debuggerPresentFlagged(false),
3360       m_breakAllKernels(false)
3361 {
3362     ModulesDidLoad(process->GetTarget().GetImages());
3363 }
3364 
3365 lldb::CommandObjectSP
3366 RenderScriptRuntime::GetCommandObject(lldb_private::CommandInterpreter& interpreter)
3367 {
3368     static CommandObjectSP command_object;
3369     if(!command_object)
3370     {
3371         command_object.reset(new CommandObjectRenderScriptRuntime(interpreter));
3372     }
3373     return command_object;
3374 }
3375 
3376 RenderScriptRuntime::~RenderScriptRuntime() = default;
3377