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 #include "RenderScriptRuntime.h"
11 
12 #include "lldb/Core/ConstString.h"
13 #include "lldb/Core/Debugger.h"
14 #include "lldb/Core/Error.h"
15 #include "lldb/Core/Log.h"
16 #include "lldb/Core/PluginManager.h"
17 #include "lldb/Symbol/Symbol.h"
18 #include "lldb/Symbol/Type.h"
19 #include "lldb/Target/Process.h"
20 #include "lldb/Target/Target.h"
21 #include "lldb/Interpreter/Args.h"
22 #include "lldb/Interpreter/Options.h"
23 #include "lldb/Interpreter/CommandInterpreter.h"
24 #include "lldb/Interpreter/CommandReturnObject.h"
25 #include "lldb/Interpreter/CommandObjectMultiword.h"
26 #include "lldb/Breakpoint/StoppointCallbackContext.h"
27 #include "lldb/Target/RegisterContext.h"
28 #include "lldb/Expression/UserExpression.h"
29 #include "lldb/Symbol/VariableList.h"
30 
31 using namespace lldb;
32 using namespace lldb_private;
33 using namespace lldb_renderscript;
34 
35 namespace {
36 
37 // The empirical_type adds a basic level of validation to arbitrary data
38 // allowing us to track if data has been discovered and stored or not.
39 // An empirical_type will be marked as valid only if it has been explicitly assigned to.
40 template <typename type_t>
41 class empirical_type
42 {
43   public:
44     // Ctor. Contents is invalid when constructed.
45     empirical_type()
46         : valid(false)
47     {}
48 
49     // Return true and copy contents to out if valid, else return false.
50     bool get(type_t& out) const
51     {
52         if (valid)
53             out = data;
54         return valid;
55     }
56 
57     // Return a pointer to the contents or nullptr if it was not valid.
58     const type_t* get() const
59     {
60         return valid ? &data : nullptr;
61     }
62 
63     // Assign data explicitly.
64     void set(const type_t in)
65     {
66         data = in;
67         valid = true;
68     }
69 
70     // Mark contents as invalid.
71     void invalidate()
72     {
73         valid = false;
74     }
75 
76     // Returns true if this type contains valid data.
77     bool isValid() const
78     {
79         return valid;
80     }
81 
82     // Assignment operator.
83     empirical_type<type_t>& operator = (const type_t in)
84     {
85         set(in);
86         return *this;
87     }
88 
89     // Dereference operator returns contents.
90     // Warning: Will assert if not valid so use only when you know data is valid.
91     const type_t& operator * () const
92     {
93         assert(valid);
94         return data;
95     }
96 
97   protected:
98     bool valid;
99     type_t data;
100 };
101 
102 } // namespace {}
103 
104 // The ScriptDetails class collects data associated with a single script instance.
105 struct RenderScriptRuntime::ScriptDetails
106 {
107     ~ScriptDetails() {};
108 
109     enum ScriptType
110     {
111         eScript,
112         eScriptC
113     };
114 
115     // The derived type of the script.
116     empirical_type<ScriptType> type;
117     // The name of the original source file.
118     empirical_type<std::string> resName;
119     // Path to script .so file on the device.
120     empirical_type<std::string> scriptDyLib;
121     // Directory where kernel objects are cached on device.
122     empirical_type<std::string> cacheDir;
123     // Pointer to the context which owns this script.
124     empirical_type<lldb::addr_t> context;
125     // Pointer to the script object itself.
126     empirical_type<lldb::addr_t> script;
127 };
128 
129 // This AllocationDetails class collects data associated with a single
130 // allocation instance.
131 struct RenderScriptRuntime::AllocationDetails
132 {
133    // Taken from rsDefines.h
134    enum DataKind
135    {
136        RS_KIND_USER,
137        RS_KIND_PIXEL_L = 7,
138        RS_KIND_PIXEL_A,
139        RS_KIND_PIXEL_LA,
140        RS_KIND_PIXEL_RGB,
141        RS_KIND_PIXEL_RGBA,
142        RS_KIND_PIXEL_DEPTH,
143        RS_KIND_PIXEL_YUV,
144        RS_KIND_INVALID = 100
145    };
146 
147    // Taken from rsDefines.h
148    enum DataType
149    {
150        RS_TYPE_NONE = 0,
151        RS_TYPE_FLOAT_16,
152        RS_TYPE_FLOAT_32,
153        RS_TYPE_FLOAT_64,
154        RS_TYPE_SIGNED_8,
155        RS_TYPE_SIGNED_16,
156        RS_TYPE_SIGNED_32,
157        RS_TYPE_SIGNED_64,
158        RS_TYPE_UNSIGNED_8,
159        RS_TYPE_UNSIGNED_16,
160        RS_TYPE_UNSIGNED_32,
161        RS_TYPE_UNSIGNED_64,
162        RS_TYPE_BOOLEAN
163     };
164 
165     struct Dimension
166     {
167         uint32_t dim_1;
168         uint32_t dim_2;
169         uint32_t dim_3;
170         uint32_t cubeMap;
171 
172         Dimension()
173         {
174              dim_1 = 0;
175              dim_2 = 0;
176              dim_3 = 0;
177              cubeMap = 0;
178         }
179     };
180 
181     // Monotonically increasing from 1
182     static unsigned int ID;
183 
184     // Maps Allocation DataType enum and vector size to printable strings
185     // using mapping from RenderScript numerical types summary documentation
186     static const char* RsDataTypeToString[][4];
187 
188     // Maps Allocation DataKind enum to printable strings
189     static const char* RsDataKindToString[];
190 
191     // Give each allocation an ID as a way
192     // for commands to reference it.
193     const unsigned int id;
194 
195     empirical_type<DataType> type;            // Type of each data pointer stored by the allocation
196     empirical_type<DataKind> type_kind;       // Defines pixel type if Allocation is created from an image
197     empirical_type<uint32_t> type_vec_size;   // Vector size of each data point, e.g '4' for uchar4
198     empirical_type<Dimension> dimension;      // Dimensions of the Allocation
199     empirical_type<lldb::addr_t> address;     // Pointer to address of the RS Allocation
200     empirical_type<lldb::addr_t> data_ptr;    // Pointer to the data held by the Allocation
201     empirical_type<lldb::addr_t> type_ptr;    // Pointer to the RS Type of the Allocation
202     empirical_type<lldb::addr_t> element_ptr; // Pointer to the RS Element of the Type
203     empirical_type<lldb::addr_t> context;     // Pointer to the RS Context of the Allocation
204 
205     // Give each allocation an id, so we can reference it in user commands.
206     AllocationDetails(): id(ID++)
207     {
208     }
209 
210 };
211 
212 unsigned int RenderScriptRuntime::AllocationDetails::ID = 1;
213 
214 const char* RenderScriptRuntime::AllocationDetails::RsDataKindToString[] =
215 {
216    "User",
217    "Undefined", "Undefined", "Undefined", // Enum jumps from 0 to 7
218    "Undefined", "Undefined", "Undefined",
219    "L Pixel",
220    "A Pixel",
221    "LA Pixel",
222    "RGB Pixel",
223    "RGBA Pixel",
224    "Pixel Depth",
225    "YUV Pixel"
226 };
227 
228 const char* RenderScriptRuntime::AllocationDetails::RsDataTypeToString[][4] =
229 {
230     {"None", "None", "None", "None"},
231     {"half", "half2", "half3", "half4"},
232     {"float", "float2", "float3", "float4"},
233     {"double", "double2", "double3", "double4"},
234     {"char", "char2", "char3", "char4"},
235     {"short", "short2", "short3", "short4"},
236     {"int", "int2", "int3", "int4"},
237     {"long", "long2", "long3", "long4"},
238     {"uchar", "uchar2", "uchar3", "uchar4"},
239     {"ushort", "ushort2", "ushort3", "ushort4"},
240     {"uint", "uint2", "uint3", "uint4"},
241     {"ulong", "ulong2", "ulong3", "ulong4"},
242     {"bool", "bool2", "bool3", "bool4"}
243 };
244 
245 //------------------------------------------------------------------
246 // Static Functions
247 //------------------------------------------------------------------
248 LanguageRuntime *
249 RenderScriptRuntime::CreateInstance(Process *process, lldb::LanguageType language)
250 {
251 
252     if (language == eLanguageTypeExtRenderScript)
253         return new RenderScriptRuntime(process);
254     else
255         return NULL;
256 }
257 
258 // Callback with a module to search for matching symbols.
259 // We first check that the module contains RS kernels.
260 // Then look for a symbol which matches our kernel name.
261 // The breakpoint address is finally set using the address of this symbol.
262 Searcher::CallbackReturn
263 RSBreakpointResolver::SearchCallback(SearchFilter &filter,
264                                      SymbolContext &context,
265                                      Address*,
266                                      bool)
267 {
268     ModuleSP module = context.module_sp;
269 
270     if (!module)
271         return Searcher::eCallbackReturnContinue;
272 
273     // Is this a module containing renderscript kernels?
274     if (nullptr == module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData))
275         return Searcher::eCallbackReturnContinue;
276 
277     // Attempt to set a breakpoint on the kernel name symbol within the module library.
278     // If it's not found, it's likely debug info is unavailable - try to set a
279     // breakpoint on <name>.expand.
280 
281     const Symbol* kernel_sym = module->FindFirstSymbolWithNameAndType(m_kernel_name, eSymbolTypeCode);
282     if (!kernel_sym)
283     {
284         std::string kernel_name_expanded(m_kernel_name.AsCString());
285         kernel_name_expanded.append(".expand");
286         kernel_sym = module->FindFirstSymbolWithNameAndType(ConstString(kernel_name_expanded.c_str()), eSymbolTypeCode);
287     }
288 
289     if (kernel_sym)
290     {
291         Address bp_addr = kernel_sym->GetAddress();
292         if (filter.AddressPasses(bp_addr))
293             m_breakpoint->AddLocation(bp_addr);
294     }
295 
296     return Searcher::eCallbackReturnContinue;
297 }
298 
299 void
300 RenderScriptRuntime::Initialize()
301 {
302     PluginManager::RegisterPlugin(GetPluginNameStatic(), "RenderScript language support", CreateInstance, GetCommandObject);
303 }
304 
305 void
306 RenderScriptRuntime::Terminate()
307 {
308     PluginManager::UnregisterPlugin(CreateInstance);
309 }
310 
311 lldb_private::ConstString
312 RenderScriptRuntime::GetPluginNameStatic()
313 {
314     static ConstString g_name("renderscript");
315     return g_name;
316 }
317 
318 RenderScriptRuntime::ModuleKind
319 RenderScriptRuntime::GetModuleKind(const lldb::ModuleSP &module_sp)
320 {
321     if (module_sp)
322     {
323         // Is this a module containing renderscript kernels?
324         const Symbol *info_sym = module_sp->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData);
325         if (info_sym)
326         {
327             return eModuleKindKernelObj;
328         }
329 
330         // Is this the main RS runtime library
331         const ConstString rs_lib("libRS.so");
332         if (module_sp->GetFileSpec().GetFilename() == rs_lib)
333         {
334             return eModuleKindLibRS;
335         }
336 
337         const ConstString rs_driverlib("libRSDriver.so");
338         if (module_sp->GetFileSpec().GetFilename() == rs_driverlib)
339         {
340             return eModuleKindDriver;
341         }
342 
343         const ConstString rs_cpureflib("libRSCpuRef.so");
344         if (module_sp->GetFileSpec().GetFilename() == rs_cpureflib)
345         {
346             return eModuleKindImpl;
347         }
348 
349     }
350     return eModuleKindIgnored;
351 }
352 
353 bool
354 RenderScriptRuntime::IsRenderScriptModule(const lldb::ModuleSP &module_sp)
355 {
356     return GetModuleKind(module_sp) != eModuleKindIgnored;
357 }
358 
359 
360 void
361 RenderScriptRuntime::ModulesDidLoad(const ModuleList &module_list )
362 {
363     Mutex::Locker locker (module_list.GetMutex ());
364 
365     size_t num_modules = module_list.GetSize();
366     for (size_t i = 0; i < num_modules; i++)
367     {
368         auto mod = module_list.GetModuleAtIndex (i);
369         if (IsRenderScriptModule (mod))
370         {
371             LoadModule(mod);
372         }
373     }
374 }
375 
376 
377 //------------------------------------------------------------------
378 // PluginInterface protocol
379 //------------------------------------------------------------------
380 lldb_private::ConstString
381 RenderScriptRuntime::GetPluginName()
382 {
383     return GetPluginNameStatic();
384 }
385 
386 uint32_t
387 RenderScriptRuntime::GetPluginVersion()
388 {
389     return 1;
390 }
391 
392 bool
393 RenderScriptRuntime::IsVTableName(const char *name)
394 {
395     return false;
396 }
397 
398 bool
399 RenderScriptRuntime::GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic,
400                                               TypeAndOrName &class_type_or_name, Address &address,
401                                               Value::ValueType &value_type)
402 {
403     return false;
404 }
405 
406 TypeAndOrName
407 RenderScriptRuntime::FixUpDynamicType (const TypeAndOrName& type_and_or_name,
408                                        ValueObject& static_value)
409 {
410     return type_and_or_name;
411 }
412 
413 bool
414 RenderScriptRuntime::CouldHaveDynamicValue(ValueObject &in_value)
415 {
416     return false;
417 }
418 
419 lldb::BreakpointResolverSP
420 RenderScriptRuntime::CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp)
421 {
422     BreakpointResolverSP resolver_sp;
423     return resolver_sp;
424 }
425 
426 
427 const RenderScriptRuntime::HookDefn RenderScriptRuntime::s_runtimeHookDefns[] =
428 {
429     //rsdScript
430     {
431         "rsdScriptInit", //name
432         "_Z13rsdScriptInitPKN7android12renderscript7ContextEPNS0_7ScriptCEPKcS7_PKhjj", // symbol name 32 bit
433         "_Z13rsdScriptInitPKN7android12renderscript7ContextEPNS0_7ScriptCEPKcS7_PKhmj", // symbol name 64 bit
434         0, // version
435         RenderScriptRuntime::eModuleKindDriver, // type
436         &lldb_private::RenderScriptRuntime::CaptureScriptInit1 // handler
437     },
438     {
439         "rsdScriptInvokeForEach", // name
440         "_Z22rsdScriptInvokeForEachPKN7android12renderscript7ContextEPNS0_6ScriptEjPKNS0_10AllocationEPS6_PKvjPK12RsScriptCall", // symbol name 32bit
441         "_Z22rsdScriptInvokeForEachPKN7android12renderscript7ContextEPNS0_6ScriptEjPKNS0_10AllocationEPS6_PKvmPK12RsScriptCall", // symbol name 64bit
442         0, // version
443         RenderScriptRuntime::eModuleKindDriver, // type
444         nullptr // handler
445     },
446     {
447         "rsdScriptInvokeForEachMulti", // name
448         "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0_6ScriptEjPPKNS0_10AllocationEjPS6_PKvjPK12RsScriptCall", // symbol name 32bit
449         "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0_6ScriptEjPPKNS0_10AllocationEmPS6_PKvmPK12RsScriptCall", // symbol name 64bit
450         0, // version
451         RenderScriptRuntime::eModuleKindDriver, // type
452         nullptr // handler
453     },
454     {
455         "rsdScriptInvokeFunction", // name
456         "_Z23rsdScriptInvokeFunctionPKN7android12renderscript7ContextEPNS0_6ScriptEjPKvj", // symbol name 32bit
457         "_Z23rsdScriptInvokeFunctionPKN7android12renderscript7ContextEPNS0_6ScriptEjPKvm", // symbol name 64bit
458         0, // version
459         RenderScriptRuntime::eModuleKindDriver, // type
460         nullptr // handler
461     },
462     {
463         "rsdScriptSetGlobalVar", // name
464         "_Z21rsdScriptSetGlobalVarPKN7android12renderscript7ContextEPKNS0_6ScriptEjPvj", // symbol name 32bit
465         "_Z21rsdScriptSetGlobalVarPKN7android12renderscript7ContextEPKNS0_6ScriptEjPvm", // symbol name 64bit
466         0, // version
467         RenderScriptRuntime::eModuleKindDriver, // type
468         &lldb_private::RenderScriptRuntime::CaptureSetGlobalVar1 // handler
469     },
470 
471     //rsdAllocation
472     {
473         "rsdAllocationInit", // name
474         "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_10AllocationEb", // symbol name 32bit
475         "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_10AllocationEb", // symbol name 64bit
476         0, // version
477         RenderScriptRuntime::eModuleKindDriver, // type
478         &lldb_private::RenderScriptRuntime::CaptureAllocationInit1 // handler
479     },
480     {
481         "rsdAllocationRead2D", //name
482         "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_10AllocationEjjj23RsAllocationCubemapFacejjPvjj", // symbol name 32bit
483         "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_10AllocationEjjj23RsAllocationCubemapFacejjPvmm", // symbol name 64bit
484         0, // version
485         RenderScriptRuntime::eModuleKindDriver, // type
486         nullptr // handler
487     },
488 };
489 const size_t RenderScriptRuntime::s_runtimeHookCount = sizeof(s_runtimeHookDefns)/sizeof(s_runtimeHookDefns[0]);
490 
491 
492 bool
493 RenderScriptRuntime::HookCallback(void *baton, StoppointCallbackContext *ctx, lldb::user_id_t break_id, lldb::user_id_t break_loc_id)
494 {
495     RuntimeHook* hook_info = (RuntimeHook*)baton;
496     ExecutionContext context(ctx->exe_ctx_ref);
497 
498     RenderScriptRuntime *lang_rt = (RenderScriptRuntime *)context.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
499 
500     lang_rt->HookCallback(hook_info, context);
501 
502     return false;
503 }
504 
505 
506 void
507 RenderScriptRuntime::HookCallback(RuntimeHook* hook_info, ExecutionContext& context)
508 {
509     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
510 
511     if (log)
512         log->Printf ("RenderScriptRuntime::HookCallback - '%s' .", hook_info->defn->name);
513 
514     if (hook_info->defn->grabber)
515     {
516         (this->*(hook_info->defn->grabber))(hook_info, context);
517     }
518 }
519 
520 
521 bool
522 RenderScriptRuntime::GetArgSimple(ExecutionContext &context, uint32_t arg, uint64_t *data)
523 {
524     if (!data)
525         return false;
526 
527     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
528     Error error;
529     RegisterContext* reg_ctx = context.GetRegisterContext();
530     Process* process = context.GetProcessPtr();
531     bool success = false; // return value
532 
533     if (!context.GetTargetPtr())
534     {
535         if (log)
536             log->Printf("RenderScriptRuntime::GetArgSimple - Invalid target");
537 
538         return false;
539     }
540 
541     switch (context.GetTargetPtr()->GetArchitecture().GetMachine())
542     {
543         case llvm::Triple::ArchType::x86:
544         {
545             uint64_t sp = reg_ctx->GetSP();
546             uint32_t offset = (1 + arg) * sizeof(uint32_t);
547             uint32_t result = 0;
548             process->ReadMemory(sp + offset, &result, sizeof(uint32_t), error);
549             if (error.Fail())
550             {
551                 if (log)
552                     log->Printf ("RenderScriptRuntime:: GetArgSimple - error reading X86 stack: %s.", error.AsCString());
553             }
554             else
555             {
556                 *data = result;
557                 success = true;
558             }
559 
560             break;
561         }
562         case llvm::Triple::ArchType::arm:
563         {
564             // arm 32 bit
565             if (arg < 4)
566             {
567                 const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg);
568                 RegisterValue rVal;
569                 reg_ctx->ReadRegister(rArg, rVal);
570                 (*data) = rVal.GetAsUInt32();
571                 success = true;
572             }
573             else
574             {
575                 uint64_t sp = reg_ctx->GetSP();
576                 {
577                     uint32_t offset = (arg-4) * sizeof(uint32_t);
578                     process->ReadMemory(sp + offset, &data, sizeof(uint32_t), error);
579                     if (error.Fail())
580                     {
581                         if (log)
582                             log->Printf ("RenderScriptRuntime:: GetArgSimple - error reading ARM stack: %s.", error.AsCString());
583                     }
584                     else
585                     {
586                         success = true;
587                     }
588                 }
589             }
590 
591             break;
592         }
593         case llvm::Triple::ArchType::aarch64:
594         {
595             // arm 64 bit
596             // first 8 arguments are in the registers
597             if (arg < 8)
598             {
599                 const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg);
600                 RegisterValue rVal;
601                 success = reg_ctx->ReadRegister(rArg, rVal);
602                 if (success)
603                 {
604                     *data = rVal.GetAsUInt64();
605                 }
606                 else
607                 {
608                     if (log)
609                         log->Printf("RenderScriptRuntime::GetArgSimple() - AARCH64 - Error while reading the argument #%d", arg);
610                 }
611             }
612             else
613             {
614                 // @TODO: need to find the argument in the stack
615                 if (log)
616                     log->Printf("RenderScriptRuntime::GetArgSimple - AARCH64 - FOR #ARG >= 8 NOT IMPLEMENTED YET. Argument number: %d", arg);
617             }
618             break;
619         }
620         default:
621         {
622             // invalid architecture
623             if (log)
624                 log->Printf("RenderScriptRuntime::GetArgSimple - Architecture not supported");
625 
626         }
627     }
628 
629 
630     return success;
631 }
632 
633 void
634 RenderScriptRuntime::CaptureSetGlobalVar1(RuntimeHook* hook_info, ExecutionContext& context)
635 {
636     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
637 
638     //Context, Script, int, data, length
639 
640     uint64_t rs_context_u64 = 0U;
641     uint64_t rs_script_u64 = 0U;
642     uint64_t rs_id_u64 = 0U;
643     uint64_t rs_data_u64 = 0U;
644     uint64_t rs_length_u64 = 0U;
645 
646     bool success =
647         GetArgSimple(context, 0, &rs_context_u64) &&
648         GetArgSimple(context, 1, &rs_script_u64) &&
649         GetArgSimple(context, 2, &rs_id_u64) &&
650         GetArgSimple(context, 3, &rs_data_u64) &&
651         GetArgSimple(context, 4, &rs_length_u64);
652 
653     if (!success)
654     {
655         if (log)
656             log->Printf("RenderScriptRuntime::CaptureSetGlobalVar1 - Error while reading the function parameters");
657         return;
658     }
659 
660     if (log)
661     {
662         log->Printf ("RenderScriptRuntime::CaptureSetGlobalVar1 - 0x%" PRIx64 ",0x%" PRIx64 " slot %" PRIu64 " = 0x%" PRIx64 ":%" PRIu64 "bytes.",
663                         rs_context_u64, rs_script_u64, rs_id_u64, rs_data_u64, rs_length_u64);
664 
665         addr_t script_addr =  (addr_t)rs_script_u64;
666         if (m_scriptMappings.find( script_addr ) != m_scriptMappings.end())
667         {
668             auto rsm = m_scriptMappings[script_addr];
669             if (rs_id_u64 < rsm->m_globals.size())
670             {
671                 auto rsg = rsm->m_globals[rs_id_u64];
672                 log->Printf ("RenderScriptRuntime::CaptureSetGlobalVar1 - Setting of '%s' within '%s' inferred", rsg.m_name.AsCString(),
673                                 rsm->m_module->GetFileSpec().GetFilename().AsCString());
674             }
675         }
676     }
677 }
678 
679 void
680 RenderScriptRuntime::CaptureAllocationInit1(RuntimeHook* hook_info, ExecutionContext& context)
681 {
682     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
683 
684     //Context, Alloc, bool
685 
686     uint64_t rs_context_u64 = 0U;
687     uint64_t rs_alloc_u64 = 0U;
688     uint64_t rs_forceZero_u64 = 0U;
689 
690     bool success =
691         GetArgSimple(context, 0, &rs_context_u64) &&
692         GetArgSimple(context, 1, &rs_alloc_u64) &&
693         GetArgSimple(context, 2, &rs_forceZero_u64);
694     if (!success) // error case
695     {
696         if (log)
697             log->Printf("RenderScriptRuntime::CaptureAllocationInit1 - Error while reading the function parameters");
698         return; // abort
699     }
700 
701     if (log)
702         log->Printf ("RenderScriptRuntime::CaptureAllocationInit1 - 0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 " .",
703                         rs_context_u64, rs_alloc_u64, rs_forceZero_u64);
704 
705     AllocationDetails* alloc = LookUpAllocation(rs_alloc_u64, true);
706     if (alloc)
707         alloc->context = rs_context_u64;
708 }
709 
710 void
711 RenderScriptRuntime::CaptureScriptInit1(RuntimeHook* hook_info, ExecutionContext& context)
712 {
713     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
714 
715     //Context, Script, resname Str, cachedir Str
716     Error error;
717     Process* process = context.GetProcessPtr();
718 
719     uint64_t rs_context_u64 = 0U;
720     uint64_t rs_script_u64 = 0U;
721     uint64_t rs_resnameptr_u64 = 0U;
722     uint64_t rs_cachedirptr_u64 = 0U;
723 
724     std::string resname;
725     std::string cachedir;
726 
727     // read the function parameters
728     bool success =
729         GetArgSimple(context, 0, &rs_context_u64) &&
730         GetArgSimple(context, 1, &rs_script_u64) &&
731         GetArgSimple(context, 2, &rs_resnameptr_u64) &&
732         GetArgSimple(context, 3, &rs_cachedirptr_u64);
733 
734     if (!success)
735     {
736         if (log)
737             log->Printf("RenderScriptRuntime::CaptureScriptInit1 - Error while reading the function parameters");
738         return;
739     }
740 
741     process->ReadCStringFromMemory((lldb::addr_t)rs_resnameptr_u64, resname, error);
742     if (error.Fail())
743     {
744         if (log)
745             log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - error reading resname: %s.", error.AsCString());
746 
747     }
748 
749     process->ReadCStringFromMemory((lldb::addr_t)rs_cachedirptr_u64, cachedir, error);
750     if (error.Fail())
751     {
752         if (log)
753             log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - error reading cachedir: %s.", error.AsCString());
754     }
755 
756     if (log)
757         log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - 0x%" PRIx64 ",0x%" PRIx64 " => '%s' at '%s' .",
758                      rs_context_u64, rs_script_u64, resname.c_str(), cachedir.c_str());
759 
760     if (resname.size() > 0)
761     {
762         StreamString strm;
763         strm.Printf("librs.%s.so", resname.c_str());
764 
765         ScriptDetails* script = LookUpScript(rs_script_u64, true);
766         if (script)
767         {
768             script->type = ScriptDetails::eScriptC;
769             script->cacheDir = cachedir;
770             script->resName = resname;
771             script->scriptDyLib = strm.GetData();
772             script->context = addr_t(rs_context_u64);
773         }
774 
775         if (log)
776             log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - '%s' tagged with context 0x%" PRIx64 " and script 0x%" PRIx64 ".",
777                          strm.GetData(), rs_context_u64, rs_script_u64);
778     }
779     else if (log)
780     {
781         log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - resource name invalid, Script not tagged");
782     }
783 
784 }
785 
786 void
787 RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind)
788 {
789     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
790 
791     if (!module)
792     {
793         return;
794     }
795 
796     Target &target = GetProcess()->GetTarget();
797     llvm::Triple::ArchType targetArchType = target.GetArchitecture().GetMachine();
798 
799     if (targetArchType != llvm::Triple::ArchType::x86
800         && targetArchType != llvm::Triple::ArchType::arm
801         && targetArchType != llvm::Triple::ArchType::aarch64)
802     {
803         if (log)
804             log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Unable to hook runtime. Only X86, ARM supported currently.");
805 
806         return;
807     }
808 
809     uint32_t archByteSize = target.GetArchitecture().GetAddressByteSize();
810 
811     for (size_t idx = 0; idx < s_runtimeHookCount; idx++)
812     {
813         const HookDefn* hook_defn = &s_runtimeHookDefns[idx];
814         if (hook_defn->kind != kind) {
815             continue;
816         }
817 
818         const char* symbol_name = (archByteSize == 4) ? hook_defn->symbol_name_m32 : hook_defn->symbol_name_m64;
819 
820         const Symbol *sym = module->FindFirstSymbolWithNameAndType(ConstString(symbol_name), eSymbolTypeCode);
821         if (!sym){
822             if (log){
823                 log->Printf("RenderScriptRuntime::LoadRuntimeHooks - ERROR: Symbol '%s' related to the function %s not found", symbol_name, hook_defn->name);
824             }
825             continue;
826         }
827 
828         addr_t addr = sym->GetLoadAddress(&target);
829         if (addr == LLDB_INVALID_ADDRESS)
830         {
831             if (log)
832                 log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Unable to resolve the address of hook function '%s' with symbol '%s'.",
833                              hook_defn->name, symbol_name);
834             continue;
835         }
836         else
837         {
838             if (log)
839                 log->Printf("RenderScriptRuntime::LoadRuntimeHooks - Function %s, address resolved at 0x%" PRIx64, hook_defn->name, addr);
840         }
841 
842         RuntimeHookSP hook(new RuntimeHook());
843         hook->address = addr;
844         hook->defn = hook_defn;
845         hook->bp_sp = target.CreateBreakpoint(addr, true, false);
846         hook->bp_sp->SetCallback(HookCallback, hook.get(), true);
847         m_runtimeHooks[addr] = hook;
848         if (log)
849         {
850             log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Successfully hooked '%s' in '%s' version %" PRIu64 " at 0x%" PRIx64 ".",
851                 hook_defn->name, module->GetFileSpec().GetFilename().AsCString(), (uint64_t)hook_defn->version, (uint64_t)addr);
852         }
853     }
854 }
855 
856 void
857 RenderScriptRuntime::FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp)
858 {
859     if (!rsmodule_sp)
860         return;
861 
862     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
863 
864     const ModuleSP module = rsmodule_sp->m_module;
865     const FileSpec& file = module->GetPlatformFileSpec();
866 
867     // Iterate over all of the scripts that we currently know of.
868     // Note: We cant push or pop to m_scripts here or it may invalidate rs_script.
869     for (const auto & rs_script : m_scripts)
870     {
871         // Extract the expected .so file path for this script.
872         std::string dylib;
873         if (!rs_script->scriptDyLib.get(dylib))
874             continue;
875 
876         // Only proceed if the module that has loaded corresponds to this script.
877         if (file.GetFilename() != ConstString(dylib.c_str()))
878             continue;
879 
880         // Obtain the script address which we use as a key.
881         lldb::addr_t script;
882         if (!rs_script->script.get(script))
883             continue;
884 
885         // If we have a script mapping for the current script.
886         if (m_scriptMappings.find(script) != m_scriptMappings.end())
887         {
888             // if the module we have stored is different to the one we just received.
889             if (m_scriptMappings[script] != rsmodule_sp)
890             {
891                 if (log)
892                     log->Printf ("RenderScriptRuntime::FixupScriptDetails - Error: script %" PRIx64 " wants reassigned to new rsmodule '%s'.",
893                                     (uint64_t)script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
894             }
895         }
896         // We don't have a script mapping for the current script.
897         else
898         {
899             // Obtain the script resource name.
900             std::string resName;
901             if (rs_script->resName.get(resName))
902                 // Set the modules resource name.
903                 rsmodule_sp->m_resname = resName;
904             // Add Script/Module pair to map.
905             m_scriptMappings[script] = rsmodule_sp;
906             if (log)
907                 log->Printf ("RenderScriptRuntime::FixupScriptDetails - script %" PRIx64 " associated with rsmodule '%s'.",
908                                 (uint64_t)script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
909         }
910     }
911 }
912 
913 // Uses the Target API to evaluate the expression passed as a parameter to the function
914 // The result of that expression is returned an unsigned 64 bit int, via the result* paramter.
915 // Function returns true on success, and false on failure
916 bool
917 RenderScriptRuntime::EvalRSExpression(const char* expression, StackFrame* frame_ptr, uint64_t* result)
918 {
919     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
920     if (log)
921         log->Printf("RenderScriptRuntime::EvalRSExpression(%s)", expression);
922 
923     ValueObjectSP expr_result;
924     // Perform the actual expression evaluation
925     GetProcess()->GetTarget().EvaluateExpression(expression, frame_ptr, expr_result);
926 
927     if (!expr_result)
928     {
929        if (log)
930            log->Printf("RenderScriptRuntime::EvalRSExpression -  Error: Couldn't evaluate expression");
931        return false;
932     }
933 
934     // The result of the expression is invalid
935     if (!expr_result->GetError().Success())
936     {
937         Error err = expr_result->GetError();
938         if (err.GetError() == UserExpression::kNoResult) // Expression returned void, so this is actually a success
939         {
940             if (log)
941                 log->Printf("RenderScriptRuntime::EvalRSExpression - Expression returned void");
942 
943             result = nullptr;
944             return true;
945         }
946 
947         if (log)
948             log->Printf("RenderScriptRuntime::EvalRSExpression - Error evaluating expression result: %s", err.AsCString());
949         return false;
950     }
951 
952     bool success = false;
953     *result = expr_result->GetValueAsUnsigned(0, &success); // We only read the result as an unsigned int.
954 
955     if (!success)
956     {
957        if (log)
958            log->Printf("RenderScriptRuntime::EvalRSExpression -  Error: Couldn't convert expression result to unsigned int");
959        return false;
960     }
961 
962     return true;
963 }
964 
965 // Used to index expression format strings
966 enum ExpressionStrings
967 {
968    eExprGetOffsetPtr = 0,
969    eExprAllocGetType,
970    eExprTypeDimX,
971    eExprTypeDimY,
972    eExprTypeDimZ,
973    eExprTypeElemPtr,
974    eExprElementType,
975    eExprElementKind,
976    eExprElementVec
977 };
978 
979 // Format strings containing the expressions we may need to evaluate.
980 const char runtimeExpressions[][256] =
981 {
982  // Mangled GetOffsetPointer(Allocation*, xoff, yoff, zoff, lod, cubemap)
983  "(int*)_Z12GetOffsetPtrPKN7android12renderscript10AllocationEjjjj23RsAllocationCubemapFace(0x%lx, %u, %u, %u, 0, 0)",
984 
985  // Type* rsaAllocationGetType(Context*, Allocation*)
986  "(void*)rsaAllocationGetType(0x%lx, 0x%lx)",
987 
988  // rsaTypeGetNativeData(Context*, Type*, void* typeData, size)
989  // Pack the data in the following way mHal.state.dimX; mHal.state.dimY; mHal.state.dimZ;
990  // mHal.state.lodCount; mHal.state.faces; mElement; into typeData
991  // Need to specify 32 or 64 bit for uint_t since this differs between devices
992  "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[0]", // X dim
993  "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[1]", // Y dim
994  "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[2]", // Z dim
995  "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[5]", // Element ptr
996 
997  // rsaElementGetNativeData(Context*, Element*, uint32_t* elemData,size)
998  // Pack mType; mKind; mNormalized; mVectorSize; NumSubElements into elemData
999  "uint32_t data[6]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[0]", // Type
1000  "uint32_t data[6]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[1]", // Kind
1001  "uint32_t data[6]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[3]"  // Vector Size
1002 };
1003 
1004 // JITs the RS runtime for the internal data pointer of an allocation.
1005 // Is passed x,y,z coordinates for the pointer to a specific element.
1006 // Then sets the data_ptr member in Allocation with the result.
1007 // Returns true on success, false otherwise
1008 bool
1009 RenderScriptRuntime::JITDataPointer(AllocationDetails* allocation, StackFrame* frame_ptr,
1010                                     unsigned int x, unsigned int y, unsigned int z)
1011 {
1012     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1013 
1014     if (!allocation->address.isValid())
1015     {
1016         if (log)
1017             log->Printf("RenderScriptRuntime::JITDataPointer - Failed to find allocation details");
1018         return false;
1019     }
1020 
1021     const char* expr_cstr = runtimeExpressions[eExprGetOffsetPtr];
1022     const int max_expr_size = 512; // Max expression size
1023     char buffer[max_expr_size];
1024 
1025     int chars_written = snprintf(buffer, max_expr_size, expr_cstr, *allocation->address.get(), x, y, z);
1026     if (chars_written < 0)
1027     {
1028         if (log)
1029             log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()");
1030         return false;
1031     }
1032     else if (chars_written >= max_expr_size)
1033     {
1034         if (log)
1035             log->Printf("RenderScriptRuntime::JITDataPointer - Expression too long");
1036         return false;
1037     }
1038 
1039     uint64_t result = 0;
1040     if (!EvalRSExpression(buffer, frame_ptr, &result))
1041         return false;
1042 
1043     addr_t mem_ptr = static_cast<lldb::addr_t>(result);
1044     allocation->data_ptr = mem_ptr;
1045 
1046     return true;
1047 }
1048 
1049 // JITs the RS runtime for the internal pointer to the RS Type of an allocation
1050 // Then sets the type_ptr member in Allocation with the result.
1051 // Returns true on success, false otherwise
1052 bool
1053 RenderScriptRuntime::JITTypePointer(AllocationDetails* allocation, StackFrame* frame_ptr)
1054 {
1055     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1056 
1057     if (!allocation->address.isValid() || !allocation->context.isValid())
1058     {
1059         if (log)
1060             log->Printf("RenderScriptRuntime::JITTypePointer - Failed to find allocation details");
1061         return false;
1062     }
1063 
1064     const char* expr_cstr = runtimeExpressions[eExprAllocGetType];
1065     const int max_expr_size = 512; // Max expression size
1066     char buffer[max_expr_size];
1067 
1068     int chars_written = snprintf(buffer, max_expr_size, expr_cstr, *allocation->context.get(), *allocation->address.get());
1069     if (chars_written < 0)
1070     {
1071         if (log)
1072             log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()");
1073         return false;
1074     }
1075     else if (chars_written >= max_expr_size)
1076     {
1077         if (log)
1078             log->Printf("RenderScriptRuntime::JITTypePointer - Expression too long");
1079         return false;
1080     }
1081 
1082     uint64_t result = 0;
1083     if (!EvalRSExpression(buffer, frame_ptr, &result))
1084         return false;
1085 
1086     addr_t type_ptr = static_cast<lldb::addr_t>(result);
1087     allocation->type_ptr = type_ptr;
1088 
1089     return true;
1090 }
1091 
1092 // JITs the RS runtime for information about the dimensions and type of an allocation
1093 // Then sets dimension and element_ptr members in Allocation with the result.
1094 // Returns true on success, false otherwise
1095 bool
1096 RenderScriptRuntime::JITTypePacked(AllocationDetails* allocation, StackFrame* frame_ptr)
1097 {
1098     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1099 
1100     if (!allocation->type_ptr.isValid() || !allocation->context.isValid())
1101     {
1102         if (log)
1103             log->Printf("RenderScriptRuntime::JITTypePacked - Failed to find allocation details");
1104         return false;
1105     }
1106 
1107     // Expression is different depending on if device is 32 or 64 bit
1108     uint32_t archByteSize = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
1109     const unsigned int bits = archByteSize == 4 ? 32 : 64;
1110 
1111     // We want 4 elements from packed data
1112     const unsigned int num_exprs = 4;
1113     assert(num_exprs == (eExprTypeElemPtr - eExprTypeDimX + 1) && "Invalid number of expressions");
1114 
1115     const int max_expr_size = 512; // Max expression size
1116     char buffer[num_exprs][max_expr_size];
1117     uint64_t results[num_exprs];
1118 
1119     for (unsigned int i = 0; i < num_exprs; ++i)
1120     {
1121         int chars_written = snprintf(buffer[i], max_expr_size, runtimeExpressions[eExprTypeDimX + i], bits,
1122                                      *allocation->context.get(), *allocation->type_ptr.get());
1123         if (chars_written < 0)
1124         {
1125             if (log)
1126                 log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()");
1127             return false;
1128         }
1129         else if (chars_written >= max_expr_size)
1130         {
1131             if (log)
1132                 log->Printf("RenderScriptRuntime::JITTypePacked - Expression too long");
1133             return false;
1134         }
1135 
1136         // Perform expression evaluation
1137         if (!EvalRSExpression(buffer[i], frame_ptr, &results[i]))
1138             return false;
1139     }
1140 
1141     // Assign results to allocation members
1142     AllocationDetails::Dimension dims;
1143     dims.dim_1 = static_cast<uint32_t>(results[0]);
1144     dims.dim_2 = static_cast<uint32_t>(results[1]);
1145     dims.dim_3 = static_cast<uint32_t>(results[2]);
1146     allocation->dimension = dims;
1147 
1148     addr_t elem_ptr = static_cast<lldb::addr_t>(results[3]);
1149     allocation->element_ptr = elem_ptr;
1150 
1151     if (log)
1152         log->Printf("RenderScriptRuntime::JITTypePacked - dims (%u, %u, %u) Element*: 0x%" PRIx64,
1153                     dims.dim_1, dims.dim_2, dims.dim_3, elem_ptr);
1154 
1155     return true;
1156 }
1157 
1158 // JITs the RS runtime for information about the Element of an allocation
1159 // Then sets type, type_vec_size, and type_kind members in Allocation with the result.
1160 // Returns true on success, false otherwise
1161 bool
1162 RenderScriptRuntime::JITElementPacked(AllocationDetails* allocation, StackFrame* frame_ptr)
1163 {
1164     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1165 
1166     if (!allocation->element_ptr.isValid() || !allocation->context.isValid())
1167     {
1168         if (log)
1169             log->Printf("RenderScriptRuntime::JITElementPacked - Failed to find allocation details");
1170         return false;
1171     }
1172 
1173     // We want 3 elements from packed data
1174     const unsigned int num_exprs = 3;
1175     assert(num_exprs == (eExprElementVec - eExprElementType + 1) && "Invalid number of expressions");
1176 
1177     const int max_expr_size = 512; // Max expression size
1178     char buffer[num_exprs][max_expr_size];
1179     uint64_t results[num_exprs];
1180 
1181     for (unsigned int i = 0; i < num_exprs; i++)
1182     {
1183         int chars_written = snprintf(buffer[i], max_expr_size, runtimeExpressions[eExprElementType + i], *allocation->context.get(), *allocation->element_ptr.get());
1184         if (chars_written < 0)
1185         {
1186             if (log)
1187                 log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()");
1188             return false;
1189         }
1190         else if (chars_written >= max_expr_size)
1191         {
1192             if (log)
1193                 log->Printf("RenderScriptRuntime::JITElementPacked - Expression too long");
1194             return false;
1195         }
1196 
1197         // Perform expression evaluation
1198         if (!EvalRSExpression(buffer[i], frame_ptr, &results[i]))
1199             return false;
1200     }
1201 
1202     // Assign results to allocation members
1203     allocation->type = static_cast<RenderScriptRuntime::AllocationDetails::DataType>(results[0]);
1204     allocation->type_kind = static_cast<RenderScriptRuntime::AllocationDetails::DataKind>(results[1]);
1205     allocation->type_vec_size = static_cast<uint32_t>(results[2]);
1206 
1207     if (log)
1208         log->Printf("RenderScriptRuntime::JITElementPacked - data type %u, pixel type %u, vector size %u",
1209                     *allocation->type.get(), *allocation->type_kind.get(), *allocation->type_vec_size.get());
1210 
1211     return true;
1212 }
1213 
1214 // JIT all the current runtime info regarding an allocation
1215 bool
1216 RenderScriptRuntime::RefreshAllocation(AllocationDetails* allocation, StackFrame* frame_ptr)
1217 {
1218     // GetOffsetPointer()
1219     if (!JITDataPointer(allocation, frame_ptr))
1220         return false;
1221 
1222     // rsaAllocationGetType()
1223     if (!JITTypePointer(allocation, frame_ptr))
1224         return false;
1225 
1226     // rsaTypeGetNativeData()
1227     if (!JITTypePacked(allocation, frame_ptr))
1228         return false;
1229 
1230     // rsaElementGetNativeData()
1231     if (!JITElementPacked(allocation, frame_ptr))
1232         return false;
1233 
1234     return true;
1235 }
1236 
1237 bool
1238 RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp)
1239 {
1240     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1241 
1242     if (module_sp)
1243     {
1244         for (const auto &rs_module : m_rsmodules)
1245         {
1246             if (rs_module->m_module == module_sp)
1247             {
1248                 // Check if the user has enabled automatically breaking on
1249                 // all RS kernels.
1250                 if (m_breakAllKernels)
1251                     BreakOnModuleKernels(rs_module);
1252 
1253                 return false;
1254             }
1255         }
1256         bool module_loaded = false;
1257         switch (GetModuleKind(module_sp))
1258         {
1259             case eModuleKindKernelObj:
1260             {
1261                 RSModuleDescriptorSP module_desc;
1262                 module_desc.reset(new RSModuleDescriptor(module_sp));
1263                 if (module_desc->ParseRSInfo())
1264                 {
1265                     m_rsmodules.push_back(module_desc);
1266                     module_loaded = true;
1267                 }
1268                 if (module_loaded)
1269                 {
1270                     FixupScriptDetails(module_desc);
1271                 }
1272                 break;
1273             }
1274             case eModuleKindDriver:
1275             {
1276                 if (!m_libRSDriver)
1277                 {
1278                     m_libRSDriver = module_sp;
1279                     LoadRuntimeHooks(m_libRSDriver, RenderScriptRuntime::eModuleKindDriver);
1280                 }
1281                 break;
1282             }
1283             case eModuleKindImpl:
1284             {
1285                 m_libRSCpuRef = module_sp;
1286                 break;
1287             }
1288             case eModuleKindLibRS:
1289             {
1290                 if (!m_libRS)
1291                 {
1292                     m_libRS = module_sp;
1293                     static ConstString gDbgPresentStr("gDebuggerPresent");
1294                     const Symbol* debug_present = m_libRS->FindFirstSymbolWithNameAndType(gDbgPresentStr, eSymbolTypeData);
1295                     if (debug_present)
1296                     {
1297                         Error error;
1298                         uint32_t flag = 0x00000001U;
1299                         Target &target = GetProcess()->GetTarget();
1300                         addr_t addr = debug_present->GetLoadAddress(&target);
1301                         GetProcess()->WriteMemory(addr, &flag, sizeof(flag), error);
1302                         if(error.Success())
1303                         {
1304                             if (log)
1305                                 log->Printf ("RenderScriptRuntime::LoadModule - Debugger present flag set on debugee");
1306 
1307                             m_debuggerPresentFlagged = true;
1308                         }
1309                         else if (log)
1310                         {
1311                             log->Printf ("RenderScriptRuntime::LoadModule - Error writing debugger present flags '%s' ", error.AsCString());
1312                         }
1313                     }
1314                     else if (log)
1315                     {
1316                         log->Printf ("RenderScriptRuntime::LoadModule - Error writing debugger present flags - symbol not found");
1317                     }
1318                 }
1319                 break;
1320             }
1321             default:
1322                 break;
1323         }
1324         if (module_loaded)
1325             Update();
1326         return module_loaded;
1327     }
1328     return false;
1329 }
1330 
1331 void
1332 RenderScriptRuntime::Update()
1333 {
1334     if (m_rsmodules.size() > 0)
1335     {
1336         if (!m_initiated)
1337         {
1338             Initiate();
1339         }
1340     }
1341 }
1342 
1343 
1344 // The maximum line length of an .rs.info packet
1345 #define MAXLINE 500
1346 
1347 // The .rs.info symbol in renderscript modules contains a string which needs to be parsed.
1348 // The string is basic and is parsed on a line by line basis.
1349 bool
1350 RSModuleDescriptor::ParseRSInfo()
1351 {
1352     const Symbol *info_sym = m_module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData);
1353     if (info_sym)
1354     {
1355         const addr_t addr = info_sym->GetAddressRef().GetFileAddress();
1356         const addr_t size = info_sym->GetByteSize();
1357         const FileSpec fs = m_module->GetFileSpec();
1358 
1359         DataBufferSP buffer = fs.ReadFileContents(addr, size);
1360 
1361         if (!buffer)
1362             return false;
1363 
1364         std::string info((const char *)buffer->GetBytes());
1365 
1366         std::vector<std::string> info_lines;
1367         size_t lpos = info.find('\n');
1368         while (lpos != std::string::npos)
1369         {
1370             info_lines.push_back(info.substr(0, lpos));
1371             info = info.substr(lpos + 1);
1372             lpos = info.find('\n');
1373         }
1374         size_t offset = 0;
1375         while (offset < info_lines.size())
1376         {
1377             std::string line = info_lines[offset];
1378             // Parse directives
1379             uint32_t numDefns = 0;
1380             if (sscanf(line.c_str(), "exportVarCount: %u", &numDefns) == 1)
1381             {
1382                 while (numDefns--)
1383                     m_globals.push_back(RSGlobalDescriptor(this, info_lines[++offset].c_str()));
1384             }
1385             else if (sscanf(line.c_str(), "exportFuncCount: %u", &numDefns) == 1)
1386             {
1387             }
1388             else if (sscanf(line.c_str(), "exportForEachCount: %u", &numDefns) == 1)
1389             {
1390                 char name[MAXLINE];
1391                 while (numDefns--)
1392                 {
1393                     uint32_t slot = 0;
1394                     name[0] = '\0';
1395                     if (sscanf(info_lines[++offset].c_str(), "%u - %s", &slot, &name[0]) == 2)
1396                     {
1397                         m_kernels.push_back(RSKernelDescriptor(this, name, slot));
1398                     }
1399                 }
1400             }
1401             else if (sscanf(line.c_str(), "pragmaCount: %u", &numDefns) == 1)
1402             {
1403                 char name[MAXLINE];
1404                 char value[MAXLINE];
1405                 while (numDefns--)
1406                 {
1407                     name[0] = '\0';
1408                     value[0] = '\0';
1409                     if (sscanf(info_lines[++offset].c_str(), "%s - %s", &name[0], &value[0]) != 0
1410                         && (name[0] != '\0'))
1411                     {
1412                         m_pragmas[std::string(name)] = value;
1413                     }
1414                 }
1415             }
1416             else if (sscanf(line.c_str(), "objectSlotCount: %u", &numDefns) == 1)
1417             {
1418             }
1419 
1420             offset++;
1421         }
1422         return m_kernels.size() > 0;
1423     }
1424     return false;
1425 }
1426 
1427 bool
1428 RenderScriptRuntime::ProbeModules(const ModuleList module_list)
1429 {
1430     bool rs_found = false;
1431     size_t num_modules = module_list.GetSize();
1432     for (size_t i = 0; i < num_modules; i++)
1433     {
1434         auto module = module_list.GetModuleAtIndex(i);
1435         rs_found |= LoadModule(module);
1436     }
1437     return rs_found;
1438 }
1439 
1440 void
1441 RenderScriptRuntime::Status(Stream &strm) const
1442 {
1443     if (m_libRS)
1444     {
1445         strm.Printf("Runtime Library discovered.");
1446         strm.EOL();
1447     }
1448     if (m_libRSDriver)
1449     {
1450         strm.Printf("Runtime Driver discovered.");
1451         strm.EOL();
1452     }
1453     if (m_libRSCpuRef)
1454     {
1455         strm.Printf("CPU Reference Implementation discovered.");
1456         strm.EOL();
1457     }
1458 
1459     if (m_runtimeHooks.size())
1460     {
1461         strm.Printf("Runtime functions hooked:");
1462         strm.EOL();
1463         for (auto b : m_runtimeHooks)
1464         {
1465             strm.Indent(b.second->defn->name);
1466             strm.EOL();
1467         }
1468         strm.EOL();
1469     }
1470     else
1471     {
1472         strm.Printf("Runtime is not hooked.");
1473         strm.EOL();
1474     }
1475 }
1476 
1477 void
1478 RenderScriptRuntime::DumpContexts(Stream &strm) const
1479 {
1480     strm.Printf("Inferred RenderScript Contexts:");
1481     strm.EOL();
1482     strm.IndentMore();
1483 
1484     std::map<addr_t, uint64_t> contextReferences;
1485 
1486     // Iterate over all of the currently discovered scripts.
1487     // Note: We cant push or pop from m_scripts inside this loop or it may invalidate script.
1488     for (const auto & script : m_scripts)
1489     {
1490         if (!script->context.isValid())
1491             continue;
1492         lldb::addr_t context = *script->context;
1493 
1494         if (contextReferences.find(context) != contextReferences.end())
1495         {
1496             contextReferences[context]++;
1497         }
1498         else
1499         {
1500             contextReferences[context] = 1;
1501         }
1502     }
1503 
1504     for (const auto& cRef : contextReferences)
1505     {
1506         strm.Printf("Context 0x%" PRIx64 ": %" PRIu64 " script instances", cRef.first, cRef.second);
1507         strm.EOL();
1508     }
1509     strm.IndentLess();
1510 }
1511 
1512 void
1513 RenderScriptRuntime::DumpKernels(Stream &strm) const
1514 {
1515     strm.Printf("RenderScript Kernels:");
1516     strm.EOL();
1517     strm.IndentMore();
1518     for (const auto &module : m_rsmodules)
1519     {
1520         strm.Printf("Resource '%s':",module->m_resname.c_str());
1521         strm.EOL();
1522         for (const auto &kernel : module->m_kernels)
1523         {
1524             strm.Indent(kernel.m_name.AsCString());
1525             strm.EOL();
1526         }
1527     }
1528     strm.IndentLess();
1529 }
1530 
1531 // Prints infomation regarding all the currently loaded allocations.
1532 // These details are gathered by jitting the runtime, which has as latency.
1533 void
1534 RenderScriptRuntime::ListAllocations(Stream &strm, StackFrame* frame_ptr, bool recompute)
1535 {
1536     strm.Printf("RenderScript Allocations:");
1537     strm.EOL();
1538     strm.IndentMore();
1539 
1540     for (auto &alloc : m_allocations)
1541     {
1542         // JIT the allocation info if we haven't done it, or the user forces us to.
1543         bool do_refresh = !alloc->data_ptr.isValid() || recompute;
1544 
1545         // JIT current allocation information
1546         if (do_refresh && !RefreshAllocation(alloc.get(), frame_ptr))
1547         {
1548             strm.Printf("Error: Couldn't evaluate details for allocation %u\n", alloc->id);
1549             continue;
1550         }
1551 
1552         strm.Printf("%u:\n",alloc->id);
1553         strm.IndentMore();
1554 
1555         strm.Indent("Context: ");
1556         if (!alloc->context.isValid())
1557             strm.Printf("unknown\n");
1558         else
1559             strm.Printf("0x%" PRIx64 "\n", *alloc->context.get());
1560 
1561         strm.Indent("Address: ");
1562         if (!alloc->address.isValid())
1563             strm.Printf("unknown\n");
1564         else
1565             strm.Printf("0x%" PRIx64 "\n", *alloc->address.get());
1566 
1567         strm.Indent("Data pointer: ");
1568         if (!alloc->data_ptr.isValid())
1569             strm.Printf("unknown\n");
1570         else
1571             strm.Printf("0x%" PRIx64 "\n", *alloc->data_ptr.get());
1572 
1573         strm.Indent("Dimensions: ");
1574         if (!alloc->dimension.isValid())
1575             strm.Printf("unknown\n");
1576         else
1577             strm.Printf("(%d, %d, %d)\n", alloc->dimension.get()->dim_1,
1578                                           alloc->dimension.get()->dim_2,
1579                                           alloc->dimension.get()->dim_3);
1580 
1581         strm.Indent("Data Type: ");
1582         if (!alloc->type.isValid() || !alloc->type_vec_size.isValid())
1583             strm.Printf("unknown\n");
1584         else
1585         {
1586             const int vector_size = *alloc->type_vec_size.get();
1587             const AllocationDetails::DataType type = *alloc->type.get();
1588 
1589             if (vector_size > 4 || vector_size < 1 ||
1590                 type < AllocationDetails::RS_TYPE_NONE || type > AllocationDetails::RS_TYPE_BOOLEAN)
1591                 strm.Printf("invalid type\n");
1592             else
1593                 strm.Printf("%s\n", AllocationDetails::RsDataTypeToString[static_cast<unsigned int>(type)][vector_size-1]);
1594         }
1595 
1596         strm.Indent("Data Kind: ");
1597         if (!alloc->type_kind.isValid())
1598             strm.Printf("unknown\n");
1599         else
1600         {
1601             const AllocationDetails::DataKind kind = *alloc->type_kind.get();
1602             if (kind < AllocationDetails::RS_KIND_USER || kind > AllocationDetails::RS_KIND_PIXEL_YUV)
1603                 strm.Printf("invalid kind\n");
1604             else
1605                 strm.Printf("%s\n", AllocationDetails::RsDataKindToString[static_cast<unsigned int>(kind)]);
1606         }
1607 
1608         strm.EOL();
1609         strm.IndentLess();
1610     }
1611     strm.IndentLess();
1612 }
1613 
1614 // Set breakpoints on every kernel found in RS module
1615 void
1616 RenderScriptRuntime::BreakOnModuleKernels(const RSModuleDescriptorSP rsmodule_sp)
1617 {
1618     for (const auto &kernel : rsmodule_sp->m_kernels)
1619     {
1620         // Don't set breakpoint on 'root' kernel
1621         if (strcmp(kernel.m_name.AsCString(), "root") == 0)
1622             continue;
1623 
1624         CreateKernelBreakpoint(kernel.m_name);
1625     }
1626 }
1627 
1628 // Method is internally called by the 'kernel breakpoint all' command to
1629 // enable or disable breaking on all kernels.
1630 //
1631 // When do_break is true we want to enable this functionality.
1632 // When do_break is false we want to disable it.
1633 void
1634 RenderScriptRuntime::SetBreakAllKernels(bool do_break, TargetSP target)
1635 {
1636     Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
1637 
1638     InitSearchFilter(target);
1639 
1640     // Set breakpoints on all the kernels
1641     if (do_break && !m_breakAllKernels)
1642     {
1643         m_breakAllKernels = true;
1644 
1645         for (const auto &module : m_rsmodules)
1646             BreakOnModuleKernels(module);
1647 
1648         if (log)
1649             log->Printf("RenderScriptRuntime::SetBreakAllKernels(True)"
1650                         "- breakpoints set on all currently loaded kernels");
1651     }
1652     else if (!do_break && m_breakAllKernels) // Breakpoints won't be set on any new kernels.
1653     {
1654         m_breakAllKernels = false;
1655 
1656         if (log)
1657             log->Printf("RenderScriptRuntime::SetBreakAllKernels(False) - breakpoints no longer automatically set");
1658     }
1659 }
1660 
1661 // Given the name of a kernel this function creates a breakpoint using our
1662 // own breakpoint resolver, and returns the Breakpoint shared pointer.
1663 BreakpointSP
1664 RenderScriptRuntime::CreateKernelBreakpoint(const ConstString& name)
1665 {
1666     Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
1667 
1668     if (!m_filtersp)
1669     {
1670         if (log)
1671             log->Printf("RenderScriptRuntime::CreateKernelBreakpoint - Error: No breakpoint search filter set");
1672         return nullptr;
1673     }
1674 
1675     BreakpointResolverSP resolver_sp(new RSBreakpointResolver(nullptr, name));
1676     BreakpointSP bp = GetProcess()->GetTarget().CreateBreakpoint(m_filtersp, resolver_sp, false, false, false);
1677 
1678     // Give RS breakpoints a specific name, so the user can manipulate them as a group.
1679     Error err;
1680     if (!bp->AddName("RenderScriptKernel", err) && log)
1681         log->Printf("RenderScriptRuntime::CreateKernelBreakpoint: Error setting break name, %s", err.AsCString());
1682 
1683     return bp;
1684 }
1685 
1686 void
1687 RenderScriptRuntime::AttemptBreakpointAtKernelName(Stream &strm, const char* name, Error& error, TargetSP target)
1688 {
1689     if (!name)
1690     {
1691         error.SetErrorString("invalid kernel name");
1692         return;
1693     }
1694 
1695     InitSearchFilter(target);
1696 
1697     ConstString kernel_name(name);
1698     BreakpointSP bp = CreateKernelBreakpoint(kernel_name);
1699     if (bp)
1700         bp->GetDescription(&strm, lldb::eDescriptionLevelInitial, false);
1701 
1702     return;
1703 }
1704 
1705 void
1706 RenderScriptRuntime::DumpModules(Stream &strm) const
1707 {
1708     strm.Printf("RenderScript Modules:");
1709     strm.EOL();
1710     strm.IndentMore();
1711     for (const auto &module : m_rsmodules)
1712     {
1713         module->Dump(strm);
1714     }
1715     strm.IndentLess();
1716 }
1717 
1718 RenderScriptRuntime::ScriptDetails*
1719 RenderScriptRuntime::LookUpScript(addr_t address, bool create)
1720 {
1721     for (const auto & s : m_scripts)
1722     {
1723         if (s->script.isValid())
1724             if (*s->script == address)
1725                 return s.get();
1726     }
1727     if (create)
1728     {
1729         std::unique_ptr<ScriptDetails> s(new ScriptDetails);
1730         s->script = address;
1731         m_scripts.push_back(std::move(s));
1732         return m_scripts.back().get();
1733     }
1734     return nullptr;
1735 }
1736 
1737 RenderScriptRuntime::AllocationDetails*
1738 RenderScriptRuntime::LookUpAllocation(addr_t address, bool create)
1739 {
1740     for (const auto & a : m_allocations)
1741     {
1742         if (a->address.isValid())
1743             if (*a->address == address)
1744                 return a.get();
1745     }
1746     if (create)
1747     {
1748         std::unique_ptr<AllocationDetails> a(new AllocationDetails);
1749         a->address = address;
1750         m_allocations.push_back(std::move(a));
1751         return m_allocations.back().get();
1752     }
1753     return nullptr;
1754 }
1755 
1756 void
1757 RSModuleDescriptor::Dump(Stream &strm) const
1758 {
1759     strm.Indent();
1760     m_module->GetFileSpec().Dump(&strm);
1761     if(m_module->GetNumCompileUnits())
1762     {
1763         strm.Indent("Debug info loaded.");
1764     }
1765     else
1766     {
1767         strm.Indent("Debug info does not exist.");
1768     }
1769     strm.EOL();
1770     strm.IndentMore();
1771     strm.Indent();
1772     strm.Printf("Globals: %" PRIu64, static_cast<uint64_t>(m_globals.size()));
1773     strm.EOL();
1774     strm.IndentMore();
1775     for (const auto &global : m_globals)
1776     {
1777         global.Dump(strm);
1778     }
1779     strm.IndentLess();
1780     strm.Indent();
1781     strm.Printf("Kernels: %" PRIu64, static_cast<uint64_t>(m_kernels.size()));
1782     strm.EOL();
1783     strm.IndentMore();
1784     for (const auto &kernel : m_kernels)
1785     {
1786         kernel.Dump(strm);
1787     }
1788     strm.Printf("Pragmas: %"  PRIu64 , static_cast<uint64_t>(m_pragmas.size()));
1789     strm.EOL();
1790     strm.IndentMore();
1791     for (const auto &key_val : m_pragmas)
1792     {
1793         strm.Printf("%s: %s", key_val.first.c_str(), key_val.second.c_str());
1794         strm.EOL();
1795     }
1796     strm.IndentLess(4);
1797 }
1798 
1799 void
1800 RSGlobalDescriptor::Dump(Stream &strm) const
1801 {
1802     strm.Indent(m_name.AsCString());
1803     VariableList var_list;
1804     m_module->m_module->FindGlobalVariables(m_name, nullptr, true, 1U, var_list);
1805     if (var_list.GetSize() == 1)
1806     {
1807         auto var = var_list.GetVariableAtIndex(0);
1808         auto type = var->GetType();
1809         if(type)
1810         {
1811             strm.Printf(" - ");
1812             type->DumpTypeName(&strm);
1813         }
1814         else
1815         {
1816             strm.Printf(" - Unknown Type");
1817         }
1818     }
1819     else
1820     {
1821         strm.Printf(" - variable identified, but not found in binary");
1822         const Symbol* s = m_module->m_module->FindFirstSymbolWithNameAndType(m_name, eSymbolTypeData);
1823         if (s)
1824         {
1825             strm.Printf(" (symbol exists) ");
1826         }
1827     }
1828 
1829     strm.EOL();
1830 }
1831 
1832 void
1833 RSKernelDescriptor::Dump(Stream &strm) const
1834 {
1835     strm.Indent(m_name.AsCString());
1836     strm.EOL();
1837 }
1838 
1839 class CommandObjectRenderScriptRuntimeModuleProbe : public CommandObjectParsed
1840 {
1841   private:
1842   public:
1843     CommandObjectRenderScriptRuntimeModuleProbe(CommandInterpreter &interpreter)
1844         : CommandObjectParsed(interpreter, "renderscript module probe",
1845                               "Initiates a Probe of all loaded modules for kernels and other renderscript objects.",
1846                               "renderscript module probe",
1847                               eCommandRequiresTarget | eCommandRequiresProcess | eCommandProcessMustBeLaunched)
1848     {
1849     }
1850 
1851     ~CommandObjectRenderScriptRuntimeModuleProbe() {}
1852 
1853     bool
1854     DoExecute(Args &command, CommandReturnObject &result)
1855     {
1856         const size_t argc = command.GetArgumentCount();
1857         if (argc == 0)
1858         {
1859             Target *target = m_exe_ctx.GetTargetPtr();
1860             RenderScriptRuntime *runtime =
1861                 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
1862             auto module_list = target->GetImages();
1863             bool new_rs_details = runtime->ProbeModules(module_list);
1864             if (new_rs_details)
1865             {
1866                 result.AppendMessage("New renderscript modules added to runtime model.");
1867             }
1868             result.SetStatus(eReturnStatusSuccessFinishResult);
1869             return true;
1870         }
1871 
1872         result.AppendErrorWithFormat("'%s' takes no arguments", m_cmd_name.c_str());
1873         result.SetStatus(eReturnStatusFailed);
1874         return false;
1875     }
1876 };
1877 
1878 class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed
1879 {
1880   private:
1881   public:
1882     CommandObjectRenderScriptRuntimeModuleDump(CommandInterpreter &interpreter)
1883         : CommandObjectParsed(interpreter, "renderscript module dump",
1884                               "Dumps renderscript specific information for all modules.", "renderscript module dump",
1885                               eCommandRequiresProcess | eCommandProcessMustBeLaunched)
1886     {
1887     }
1888 
1889     ~CommandObjectRenderScriptRuntimeModuleDump() {}
1890 
1891     bool
1892     DoExecute(Args &command, CommandReturnObject &result)
1893     {
1894         RenderScriptRuntime *runtime =
1895             (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
1896         runtime->DumpModules(result.GetOutputStream());
1897         result.SetStatus(eReturnStatusSuccessFinishResult);
1898         return true;
1899     }
1900 };
1901 
1902 class CommandObjectRenderScriptRuntimeModule : public CommandObjectMultiword
1903 {
1904   private:
1905   public:
1906     CommandObjectRenderScriptRuntimeModule(CommandInterpreter &interpreter)
1907         : CommandObjectMultiword(interpreter, "renderscript module", "Commands that deal with renderscript modules.",
1908                                  NULL)
1909     {
1910         LoadSubCommand("probe", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleProbe(interpreter)));
1911         LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleDump(interpreter)));
1912     }
1913 
1914     ~CommandObjectRenderScriptRuntimeModule() {}
1915 };
1916 
1917 class CommandObjectRenderScriptRuntimeKernelList : public CommandObjectParsed
1918 {
1919   private:
1920   public:
1921     CommandObjectRenderScriptRuntimeKernelList(CommandInterpreter &interpreter)
1922         : CommandObjectParsed(interpreter, "renderscript kernel list",
1923                               "Lists renderscript kernel names and associated script resources.", "renderscript kernel list",
1924                               eCommandRequiresProcess | eCommandProcessMustBeLaunched)
1925     {
1926     }
1927 
1928     ~CommandObjectRenderScriptRuntimeKernelList() {}
1929 
1930     bool
1931     DoExecute(Args &command, CommandReturnObject &result)
1932     {
1933         RenderScriptRuntime *runtime =
1934             (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
1935         runtime->DumpKernels(result.GetOutputStream());
1936         result.SetStatus(eReturnStatusSuccessFinishResult);
1937         return true;
1938     }
1939 };
1940 
1941 class CommandObjectRenderScriptRuntimeKernelBreakpointSet : public CommandObjectParsed
1942 {
1943   private:
1944   public:
1945     CommandObjectRenderScriptRuntimeKernelBreakpointSet(CommandInterpreter &interpreter)
1946         : CommandObjectParsed(interpreter, "renderscript kernel breakpoint set",
1947                               "Sets a breakpoint on a renderscript kernel.", "renderscript kernel breakpoint set <kernel_name>",
1948                               eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused)
1949     {
1950     }
1951 
1952     ~CommandObjectRenderScriptRuntimeKernelBreakpointSet() {}
1953 
1954     bool
1955     DoExecute(Args &command, CommandReturnObject &result)
1956     {
1957         const size_t argc = command.GetArgumentCount();
1958         if (argc == 1)
1959         {
1960             RenderScriptRuntime *runtime =
1961                 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
1962 
1963             Error error;
1964             runtime->AttemptBreakpointAtKernelName(result.GetOutputStream(), command.GetArgumentAtIndex(0),
1965                                                    error, m_exe_ctx.GetTargetSP());
1966 
1967             if (error.Success())
1968             {
1969                 result.AppendMessage("Breakpoint(s) created");
1970                 result.SetStatus(eReturnStatusSuccessFinishResult);
1971                 return true;
1972             }
1973             result.SetStatus(eReturnStatusFailed);
1974             result.AppendErrorWithFormat("Error: %s", error.AsCString());
1975             return false;
1976         }
1977 
1978         result.AppendErrorWithFormat("'%s' takes 1 argument of kernel name", m_cmd_name.c_str());
1979         result.SetStatus(eReturnStatusFailed);
1980         return false;
1981     }
1982 };
1983 
1984 class CommandObjectRenderScriptRuntimeKernelBreakpointAll : public CommandObjectParsed
1985 {
1986   private:
1987   public:
1988     CommandObjectRenderScriptRuntimeKernelBreakpointAll(CommandInterpreter &interpreter)
1989         : CommandObjectParsed(interpreter, "renderscript kernel breakpoint all",
1990                               "Automatically sets a breakpoint on all renderscript kernels that are or will be loaded.\n"
1991                               "Disabling option means breakpoints will no longer be set on any kernels loaded in the future, "
1992                               "but does not remove currently set breakpoints.",
1993                               "renderscript kernel breakpoint all <enable/disable>",
1994                               eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused)
1995     {
1996     }
1997 
1998     ~CommandObjectRenderScriptRuntimeKernelBreakpointAll() {}
1999 
2000     bool
2001     DoExecute(Args &command, CommandReturnObject &result)
2002     {
2003         const size_t argc = command.GetArgumentCount();
2004         if (argc != 1)
2005         {
2006             result.AppendErrorWithFormat("'%s' takes 1 argument of 'enable' or 'disable'", m_cmd_name.c_str());
2007             result.SetStatus(eReturnStatusFailed);
2008             return false;
2009         }
2010 
2011         RenderScriptRuntime *runtime =
2012           static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
2013 
2014         bool do_break = false;
2015         const char* argument = command.GetArgumentAtIndex(0);
2016         if (strcmp(argument, "enable") == 0)
2017         {
2018             do_break = true;
2019             result.AppendMessage("Breakpoints will be set on all kernels.");
2020         }
2021         else if (strcmp(argument, "disable") == 0)
2022         {
2023             do_break = false;
2024             result.AppendMessage("Breakpoints will not be set on any new kernels.");
2025         }
2026         else
2027         {
2028             result.AppendErrorWithFormat("Argument must be either 'enable' or 'disable'");
2029             result.SetStatus(eReturnStatusFailed);
2030             return false;
2031         }
2032 
2033         runtime->SetBreakAllKernels(do_break, m_exe_ctx.GetTargetSP());
2034 
2035         result.SetStatus(eReturnStatusSuccessFinishResult);
2036         return true;
2037     }
2038 };
2039 
2040 class CommandObjectRenderScriptRuntimeKernelBreakpoint : public CommandObjectMultiword
2041 {
2042   private:
2043   public:
2044     CommandObjectRenderScriptRuntimeKernelBreakpoint(CommandInterpreter &interpreter)
2045         : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that generate breakpoints on renderscript kernels.",
2046                                  nullptr)
2047     {
2048         LoadSubCommand("set", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointSet(interpreter)));
2049         LoadSubCommand("all", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointAll(interpreter)));
2050     }
2051 
2052     ~CommandObjectRenderScriptRuntimeKernelBreakpoint() {}
2053 };
2054 
2055 class CommandObjectRenderScriptRuntimeKernel : public CommandObjectMultiword
2056 {
2057   private:
2058   public:
2059     CommandObjectRenderScriptRuntimeKernel(CommandInterpreter &interpreter)
2060         : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that deal with renderscript kernels.",
2061                                  NULL)
2062     {
2063         LoadSubCommand("list", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelList(interpreter)));
2064         LoadSubCommand("breakpoint", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpoint(interpreter)));
2065     }
2066 
2067     ~CommandObjectRenderScriptRuntimeKernel() {}
2068 };
2069 
2070 class CommandObjectRenderScriptRuntimeContextDump : public CommandObjectParsed
2071 {
2072   private:
2073   public:
2074     CommandObjectRenderScriptRuntimeContextDump(CommandInterpreter &interpreter)
2075         : CommandObjectParsed(interpreter, "renderscript context dump",
2076                               "Dumps renderscript context information.", "renderscript context dump",
2077                               eCommandRequiresProcess | eCommandProcessMustBeLaunched)
2078     {
2079     }
2080 
2081     ~CommandObjectRenderScriptRuntimeContextDump() {}
2082 
2083     bool
2084     DoExecute(Args &command, CommandReturnObject &result)
2085     {
2086         RenderScriptRuntime *runtime =
2087             (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
2088         runtime->DumpContexts(result.GetOutputStream());
2089         result.SetStatus(eReturnStatusSuccessFinishResult);
2090         return true;
2091     }
2092 };
2093 
2094 class CommandObjectRenderScriptRuntimeContext : public CommandObjectMultiword
2095 {
2096   private:
2097   public:
2098     CommandObjectRenderScriptRuntimeContext(CommandInterpreter &interpreter)
2099         : CommandObjectMultiword(interpreter, "renderscript context", "Commands that deal with renderscript contexts.",
2100                                  NULL)
2101     {
2102         LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeContextDump(interpreter)));
2103     }
2104 
2105     ~CommandObjectRenderScriptRuntimeContext() {}
2106 };
2107 
2108 class CommandObjectRenderScriptRuntimeAllocationList : public CommandObjectParsed
2109 {
2110   public:
2111     CommandObjectRenderScriptRuntimeAllocationList(CommandInterpreter &interpreter)
2112         : CommandObjectParsed(interpreter, "renderscript allocation list",
2113                               "List renderscript allocations and their information.", "renderscript allocation list",
2114                               eCommandRequiresProcess | eCommandProcessMustBeLaunched), m_options(interpreter)
2115     {
2116     }
2117 
2118     virtual Options*
2119     GetOptions()
2120     {
2121         return &m_options;
2122     }
2123 
2124     class CommandOptions : public Options
2125     {
2126       public:
2127         CommandOptions(CommandInterpreter &interpreter) : Options(interpreter), m_refresh(false)
2128         {
2129         }
2130 
2131         virtual
2132         ~CommandOptions()
2133         {
2134         }
2135 
2136         virtual Error
2137         SetOptionValue(uint32_t option_idx, const char *option_arg)
2138         {
2139             Error error;
2140             const int short_option = m_getopt_table[option_idx].val;
2141 
2142             switch (short_option)
2143             {
2144                 case 'r':
2145                     m_refresh = true;
2146                     break;
2147                 default:
2148                     error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
2149                     break;
2150             }
2151             return error;
2152         }
2153 
2154         void
2155         OptionParsingStarting()
2156         {
2157             m_refresh = false;
2158         }
2159 
2160         const OptionDefinition*
2161         GetDefinitions()
2162         {
2163             return g_option_table;
2164         }
2165 
2166         static OptionDefinition g_option_table[];
2167         bool m_refresh;
2168     };
2169 
2170     ~CommandObjectRenderScriptRuntimeAllocationList() {}
2171 
2172     bool
2173     DoExecute(Args &command, CommandReturnObject &result)
2174     {
2175         RenderScriptRuntime *runtime =
2176           static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
2177         runtime->ListAllocations(result.GetOutputStream(), m_exe_ctx.GetFramePtr(), m_options.m_refresh);
2178         result.SetStatus(eReturnStatusSuccessFinishResult);
2179         return true;
2180     }
2181 
2182   private:
2183     CommandOptions m_options;
2184 };
2185 
2186 OptionDefinition
2187 CommandObjectRenderScriptRuntimeAllocationList::CommandOptions::g_option_table[] =
2188 {
2189     { LLDB_OPT_SET_1, false, "refresh", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
2190       "Recompute allocation details."},
2191     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
2192 };
2193 
2194 
2195 class CommandObjectRenderScriptRuntimeAllocation : public CommandObjectMultiword
2196 {
2197   private:
2198   public:
2199     CommandObjectRenderScriptRuntimeAllocation(CommandInterpreter &interpreter)
2200         : CommandObjectMultiword(interpreter, "renderscript allocation", "Commands that deal with renderscript allocations.",
2201                                  NULL)
2202     {
2203         LoadSubCommand("list", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationList(interpreter)));
2204     }
2205 
2206     ~CommandObjectRenderScriptRuntimeAllocation() {}
2207 };
2208 
2209 
2210 class CommandObjectRenderScriptRuntimeStatus : public CommandObjectParsed
2211 {
2212   private:
2213   public:
2214     CommandObjectRenderScriptRuntimeStatus(CommandInterpreter &interpreter)
2215         : CommandObjectParsed(interpreter, "renderscript status",
2216                               "Displays current renderscript runtime status.", "renderscript status",
2217                               eCommandRequiresProcess | eCommandProcessMustBeLaunched)
2218     {
2219     }
2220 
2221     ~CommandObjectRenderScriptRuntimeStatus() {}
2222 
2223     bool
2224     DoExecute(Args &command, CommandReturnObject &result)
2225     {
2226         RenderScriptRuntime *runtime =
2227             (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
2228         runtime->Status(result.GetOutputStream());
2229         result.SetStatus(eReturnStatusSuccessFinishResult);
2230         return true;
2231     }
2232 };
2233 
2234 class CommandObjectRenderScriptRuntime : public CommandObjectMultiword
2235 {
2236   public:
2237     CommandObjectRenderScriptRuntime(CommandInterpreter &interpreter)
2238         : CommandObjectMultiword(interpreter, "renderscript", "A set of commands for operating on renderscript.",
2239                                  "renderscript <subcommand> [<subcommand-options>]")
2240     {
2241         LoadSubCommand("module", CommandObjectSP(new CommandObjectRenderScriptRuntimeModule(interpreter)));
2242         LoadSubCommand("status", CommandObjectSP(new CommandObjectRenderScriptRuntimeStatus(interpreter)));
2243         LoadSubCommand("kernel", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernel(interpreter)));
2244         LoadSubCommand("context", CommandObjectSP(new CommandObjectRenderScriptRuntimeContext(interpreter)));
2245         LoadSubCommand("allocation", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocation(interpreter)));
2246     }
2247 
2248     ~CommandObjectRenderScriptRuntime() {}
2249 };
2250 
2251 void
2252 RenderScriptRuntime::Initiate()
2253 {
2254     assert(!m_initiated);
2255 }
2256 
2257 RenderScriptRuntime::RenderScriptRuntime(Process *process)
2258     : lldb_private::CPPLanguageRuntime(process), m_initiated(false), m_debuggerPresentFlagged(false),
2259       m_breakAllKernels(false)
2260 {
2261     ModulesDidLoad(process->GetTarget().GetImages());
2262 }
2263 
2264 lldb::CommandObjectSP
2265 RenderScriptRuntime::GetCommandObject(lldb_private::CommandInterpreter& interpreter)
2266 {
2267     static CommandObjectSP command_object;
2268     if(!command_object)
2269     {
2270         command_object.reset(new CommandObjectRenderScriptRuntime(interpreter));
2271     }
2272     return command_object;
2273 }
2274 
2275 RenderScriptRuntime::~RenderScriptRuntime() = default;
2276