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 
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     ~AllocationDetails () {};
134 
135     enum DataType
136     {
137         eInt,
138     };
139 
140     enum Dimension
141     {
142         e1d,
143         e2d,
144         e3d,
145         eCubeMap,
146     };
147 
148     empirical_type<DataType> type;
149     empirical_type<Dimension> dimension;
150     empirical_type<lldb::addr_t> address;
151     empirical_type<lldb::addr_t> dataPtr;
152     empirical_type<lldb::addr_t> context;
153 };
154 
155 //------------------------------------------------------------------
156 // Static Functions
157 //------------------------------------------------------------------
158 LanguageRuntime *
159 RenderScriptRuntime::CreateInstance(Process *process, lldb::LanguageType language)
160 {
161 
162     if (language == eLanguageTypeExtRenderScript)
163         return new RenderScriptRuntime(process);
164     else
165         return NULL;
166 }
167 
168 // Callback with a module to search for matching symbols.
169 // We first check that the module contains RS kernels.
170 // Then look for a symbol which matches our kernel name.
171 // The breakpoint address is finally set using the address of this symbol.
172 Searcher::CallbackReturn
173 RSBreakpointResolver::SearchCallback(SearchFilter &filter,
174                                      SymbolContext &context,
175                                      Address*,
176                                      bool)
177 {
178     ModuleSP module = context.module_sp;
179 
180     if (!module)
181         return Searcher::eCallbackReturnContinue;
182 
183     // Is this a module containing renderscript kernels?
184     if (nullptr == module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData))
185         return Searcher::eCallbackReturnContinue;
186 
187     // Attempt to set a breakpoint on the kernel name symbol within the module library.
188     // If it's not found, it's likely debug info is unavailable - try to set a
189     // breakpoint on <name>.expand.
190 
191     const Symbol* kernel_sym = module->FindFirstSymbolWithNameAndType(m_kernel_name, eSymbolTypeCode);
192     if (!kernel_sym)
193     {
194         std::string kernel_name_expanded(m_kernel_name.AsCString());
195         kernel_name_expanded.append(".expand");
196         kernel_sym = module->FindFirstSymbolWithNameAndType(ConstString(kernel_name_expanded.c_str()), eSymbolTypeCode);
197     }
198 
199     if (kernel_sym)
200     {
201         Address bp_addr = kernel_sym->GetAddress();
202         if (filter.AddressPasses(bp_addr))
203             m_breakpoint->AddLocation(bp_addr);
204     }
205 
206     return Searcher::eCallbackReturnContinue;
207 }
208 
209 void
210 RenderScriptRuntime::Initialize()
211 {
212     PluginManager::RegisterPlugin(GetPluginNameStatic(), "RenderScript language support", CreateInstance, GetCommandObject);
213 }
214 
215 void
216 RenderScriptRuntime::Terminate()
217 {
218     PluginManager::UnregisterPlugin(CreateInstance);
219 }
220 
221 lldb_private::ConstString
222 RenderScriptRuntime::GetPluginNameStatic()
223 {
224     static ConstString g_name("renderscript");
225     return g_name;
226 }
227 
228 RenderScriptRuntime::ModuleKind
229 RenderScriptRuntime::GetModuleKind(const lldb::ModuleSP &module_sp)
230 {
231     if (module_sp)
232     {
233         // Is this a module containing renderscript kernels?
234         const Symbol *info_sym = module_sp->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData);
235         if (info_sym)
236         {
237             return eModuleKindKernelObj;
238         }
239 
240         // Is this the main RS runtime library
241         const ConstString rs_lib("libRS.so");
242         if (module_sp->GetFileSpec().GetFilename() == rs_lib)
243         {
244             return eModuleKindLibRS;
245         }
246 
247         const ConstString rs_driverlib("libRSDriver.so");
248         if (module_sp->GetFileSpec().GetFilename() == rs_driverlib)
249         {
250             return eModuleKindDriver;
251         }
252 
253         const ConstString rs_cpureflib("libRSCPURef.so");
254         if (module_sp->GetFileSpec().GetFilename() == rs_cpureflib)
255         {
256             return eModuleKindImpl;
257         }
258 
259     }
260     return eModuleKindIgnored;
261 }
262 
263 bool
264 RenderScriptRuntime::IsRenderScriptModule(const lldb::ModuleSP &module_sp)
265 {
266     return GetModuleKind(module_sp) != eModuleKindIgnored;
267 }
268 
269 
270 void
271 RenderScriptRuntime::ModulesDidLoad(const ModuleList &module_list )
272 {
273     Mutex::Locker locker (module_list.GetMutex ());
274 
275     size_t num_modules = module_list.GetSize();
276     for (size_t i = 0; i < num_modules; i++)
277     {
278         auto mod = module_list.GetModuleAtIndex (i);
279         if (IsRenderScriptModule (mod))
280         {
281             LoadModule(mod);
282         }
283     }
284 }
285 
286 
287 //------------------------------------------------------------------
288 // PluginInterface protocol
289 //------------------------------------------------------------------
290 lldb_private::ConstString
291 RenderScriptRuntime::GetPluginName()
292 {
293     return GetPluginNameStatic();
294 }
295 
296 uint32_t
297 RenderScriptRuntime::GetPluginVersion()
298 {
299     return 1;
300 }
301 
302 bool
303 RenderScriptRuntime::IsVTableName(const char *name)
304 {
305     return false;
306 }
307 
308 bool
309 RenderScriptRuntime::GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic,
310                                               TypeAndOrName &class_type_or_name, Address &address,
311                                               Value::ValueType &value_type)
312 {
313     return false;
314 }
315 
316 bool
317 RenderScriptRuntime::CouldHaveDynamicValue(ValueObject &in_value)
318 {
319     return false;
320 }
321 
322 lldb::BreakpointResolverSP
323 RenderScriptRuntime::CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp)
324 {
325     BreakpointResolverSP resolver_sp;
326     return resolver_sp;
327 }
328 
329 
330 const RenderScriptRuntime::HookDefn RenderScriptRuntime::s_runtimeHookDefns[] =
331 {
332     //rsdScript
333     {
334         "rsdScriptInit", //name
335         "_Z13rsdScriptInitPKN7android12renderscript7ContextEPNS0_7ScriptCEPKcS7_PKhjj", // symbol name 32 bit
336         "_Z13rsdScriptInitPKN7android12renderscript7ContextEPNS0_7ScriptCEPKcS7_PKhmj", // symbol name 64 bit
337         0, // version
338         RenderScriptRuntime::eModuleKindDriver, // type
339         &lldb_private::RenderScriptRuntime::CaptureScriptInit1 // handler
340     },
341     {
342         "rsdScriptInvokeForEach", // name
343         "_Z22rsdScriptInvokeForEachPKN7android12renderscript7ContextEPNS0_6ScriptEjPKNS0_10AllocationEPS6_PKvjPK12RsScriptCall", // symbol name 32bit
344         "_Z22rsdScriptInvokeForEachPKN7android12renderscript7ContextEPNS0_6ScriptEjPKNS0_10AllocationEPS6_PKvmPK12RsScriptCall", // symbol name 64bit
345         0, // version
346         RenderScriptRuntime::eModuleKindDriver, // type
347         nullptr // handler
348     },
349     {
350         "rsdScriptInvokeForEachMulti", // name
351         "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0_6ScriptEjPPKNS0_10AllocationEjPS6_PKvjPK12RsScriptCall", // symbol name 32bit
352         "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0_6ScriptEjPPKNS0_10AllocationEmPS6_PKvmPK12RsScriptCall", // symbol name 64bit
353         0, // version
354         RenderScriptRuntime::eModuleKindDriver, // type
355         nullptr // handler
356     },
357     {
358         "rsdScriptInvokeFunction", // name
359         "_Z23rsdScriptInvokeFunctionPKN7android12renderscript7ContextEPNS0_6ScriptEjPKvj", // symbol name 32bit
360         "_Z23rsdScriptInvokeFunctionPKN7android12renderscript7ContextEPNS0_6ScriptEjPKvm", // symbol name 64bit
361         0, // version
362         RenderScriptRuntime::eModuleKindDriver, // type
363         nullptr // handler
364     },
365     {
366         "rsdScriptSetGlobalVar", // name
367         "_Z21rsdScriptSetGlobalVarPKN7android12renderscript7ContextEPKNS0_6ScriptEjPvj", // symbol name 32bit
368         "_Z21rsdScriptSetGlobalVarPKN7android12renderscript7ContextEPKNS0_6ScriptEjPvm", // symbol name 64bit
369         0, // version
370         RenderScriptRuntime::eModuleKindDriver, // type
371         &lldb_private::RenderScriptRuntime::CaptureSetGlobalVar1 // handler
372     },
373 
374     //rsdAllocation
375     {
376         "rsdAllocationInit", // name
377         "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_10AllocationEb", // symbol name 32bit
378         "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_10AllocationEb", // symbol name 64bit
379         0, // version
380         RenderScriptRuntime::eModuleKindDriver, // type
381         &lldb_private::RenderScriptRuntime::CaptureAllocationInit1 // handler
382     },
383     {
384         "rsdAllocationRead2D", //name
385         "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_10AllocationEjjj23RsAllocationCubemapFacejjPvjj", // symbol name 32bit
386         "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_10AllocationEjjj23RsAllocationCubemapFacejjPvmm", // symbol name 64bit
387         0, // version
388         RenderScriptRuntime::eModuleKindDriver, // type
389         nullptr // handler
390     },
391 };
392 const size_t RenderScriptRuntime::s_runtimeHookCount = sizeof(s_runtimeHookDefns)/sizeof(s_runtimeHookDefns[0]);
393 
394 
395 bool
396 RenderScriptRuntime::HookCallback(void *baton, StoppointCallbackContext *ctx, lldb::user_id_t break_id, lldb::user_id_t break_loc_id)
397 {
398     RuntimeHook* hook_info = (RuntimeHook*)baton;
399     ExecutionContext context(ctx->exe_ctx_ref);
400 
401     RenderScriptRuntime *lang_rt = (RenderScriptRuntime *)context.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
402 
403     lang_rt->HookCallback(hook_info, context);
404 
405     return false;
406 }
407 
408 
409 void
410 RenderScriptRuntime::HookCallback(RuntimeHook* hook_info, ExecutionContext& context)
411 {
412     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
413 
414     if (log)
415         log->Printf ("RenderScriptRuntime::HookCallback - '%s' .", hook_info->defn->name);
416 
417     if (hook_info->defn->grabber)
418     {
419         (this->*(hook_info->defn->grabber))(hook_info, context);
420     }
421 }
422 
423 
424 bool
425 RenderScriptRuntime::GetArgSimple(ExecutionContext &context, uint32_t arg, uint64_t *data)
426 {
427     if (!data)
428         return false;
429 
430     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
431     Error error;
432     RegisterContext* reg_ctx = context.GetRegisterContext();
433     Process* process = context.GetProcessPtr();
434     bool success = false; // return value
435 
436     if (!context.GetTargetPtr())
437     {
438         if (log)
439             log->Printf("RenderScriptRuntime::GetArgSimple - Invalid target");
440 
441         return false;
442     }
443 
444     switch (context.GetTargetPtr()->GetArchitecture().GetMachine())
445     {
446         case llvm::Triple::ArchType::x86:
447         {
448             uint64_t sp = reg_ctx->GetSP();
449             uint32_t offset = (1 + arg) * sizeof(uint32_t);
450             uint32_t result = 0;
451             process->ReadMemory(sp + offset, &result, sizeof(uint32_t), error);
452             if (error.Fail())
453             {
454                 if (log)
455                     log->Printf ("RenderScriptRuntime:: GetArgSimple - error reading X86 stack: %s.", error.AsCString());
456             }
457             else
458             {
459                 *data = result;
460                 success = true;
461             }
462 
463             break;
464         }
465         case llvm::Triple::ArchType::arm:
466         {
467             // arm 32 bit
468             if (arg < 4)
469             {
470                 const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg);
471                 RegisterValue rVal;
472                 reg_ctx->ReadRegister(rArg, rVal);
473                 (*data) = rVal.GetAsUInt32();
474                 success = true;
475             }
476             else
477             {
478                 uint64_t sp = reg_ctx->GetSP();
479                 {
480                     uint32_t offset = (arg-4) * sizeof(uint32_t);
481                     process->ReadMemory(sp + offset, &data, sizeof(uint32_t), error);
482                     if (error.Fail())
483                     {
484                         if (log)
485                             log->Printf ("RenderScriptRuntime:: GetArgSimple - error reading ARM stack: %s.", error.AsCString());
486                     }
487                     else
488                     {
489                         success = true;
490                     }
491                 }
492             }
493 
494             break;
495         }
496         case llvm::Triple::ArchType::aarch64:
497         {
498             // arm 64 bit
499             // first 8 arguments are in the registers
500             if (arg < 8)
501             {
502                 const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg);
503                 RegisterValue rVal;
504                 success = reg_ctx->ReadRegister(rArg, rVal);
505                 if (success)
506                 {
507                     *data = rVal.GetAsUInt64();
508                 }
509                 else
510                 {
511                     if (log)
512                         log->Printf("RenderScriptRuntime::GetArgSimple() - AARCH64 - Error while reading the argument #%d", arg);
513                 }
514             }
515             else
516             {
517                 // @TODO: need to find the argument in the stack
518                 if (log)
519                     log->Printf("RenderScriptRuntime::GetArgSimple - AARCH64 - FOR #ARG >= 8 NOT IMPLEMENTED YET. Argument number: %d", arg);
520             }
521             break;
522         }
523         default:
524         {
525             // invalid architecture
526             if (log)
527                 log->Printf("RenderScriptRuntime::GetArgSimple - Architecture not supported");
528 
529         }
530     }
531 
532 
533     return success;
534 }
535 
536 void
537 RenderScriptRuntime::CaptureSetGlobalVar1(RuntimeHook* hook_info, ExecutionContext& context)
538 {
539     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
540 
541     //Context, Script, int, data, length
542 
543     uint64_t rs_context_u64 = 0U;
544     uint64_t rs_script_u64 = 0U;
545     uint64_t rs_id_u64 = 0U;
546     uint64_t rs_data_u64 = 0U;
547     uint64_t rs_length_u64 = 0U;
548 
549     bool success =
550         GetArgSimple(context, 0, &rs_context_u64) &&
551         GetArgSimple(context, 1, &rs_script_u64) &&
552         GetArgSimple(context, 2, &rs_id_u64) &&
553         GetArgSimple(context, 3, &rs_data_u64) &&
554         GetArgSimple(context, 4, &rs_length_u64);
555 
556     if (!success)
557     {
558         if (log)
559             log->Printf("RenderScriptRuntime::CaptureSetGlobalVar1 - Error while reading the function parameters");
560         return;
561     }
562 
563     if (log)
564     {
565         log->Printf ("RenderScriptRuntime::CaptureSetGlobalVar1 - 0x%" PRIx64 ",0x%" PRIx64 " slot %" PRIu64 " = 0x%" PRIx64 ":%" PRIu64 "bytes.",
566                         rs_context_u64, rs_script_u64, rs_id_u64, rs_data_u64, rs_length_u64);
567 
568         addr_t script_addr =  (addr_t)rs_script_u64;
569         if (m_scriptMappings.find( script_addr ) != m_scriptMappings.end())
570         {
571             auto rsm = m_scriptMappings[script_addr];
572             if (rs_id_u64 < rsm->m_globals.size())
573             {
574                 auto rsg = rsm->m_globals[rs_id_u64];
575                 log->Printf ("RenderScriptRuntime::CaptureSetGlobalVar1 - Setting of '%s' within '%s' inferred", rsg.m_name.AsCString(),
576                                 rsm->m_module->GetFileSpec().GetFilename().AsCString());
577             }
578         }
579     }
580 }
581 
582 void
583 RenderScriptRuntime::CaptureAllocationInit1(RuntimeHook* hook_info, ExecutionContext& context)
584 {
585     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
586 
587     //Context, Alloc, bool
588 
589     uint64_t rs_context_u64 = 0U;
590     uint64_t rs_alloc_u64 = 0U;
591     uint64_t rs_forceZero_u64 = 0U;
592 
593     bool success =
594         GetArgSimple(context, 0, &rs_context_u64) &&
595         GetArgSimple(context, 1, &rs_alloc_u64) &&
596         GetArgSimple(context, 2, &rs_forceZero_u64);
597     if (!success) // error case
598     {
599         if (log)
600             log->Printf("RenderScriptRuntime::CaptureAllocationInit1 - Error while reading the function parameters");
601         return; // abort
602     }
603 
604     if (log)
605         log->Printf ("RenderScriptRuntime::CaptureAllocationInit1 - 0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 " .",
606                         rs_context_u64, rs_alloc_u64, rs_forceZero_u64);
607 
608     AllocationDetails* alloc = LookUpAllocation(rs_alloc_u64, true);
609     if (alloc)
610         alloc->context = rs_context_u64;
611 }
612 
613 void
614 RenderScriptRuntime::CaptureScriptInit1(RuntimeHook* hook_info, ExecutionContext& context)
615 {
616     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
617 
618     //Context, Script, resname Str, cachedir Str
619     Error error;
620     Process* process = context.GetProcessPtr();
621 
622     uint64_t rs_context_u64 = 0U;
623     uint64_t rs_script_u64 = 0U;
624     uint64_t rs_resnameptr_u64 = 0U;
625     uint64_t rs_cachedirptr_u64 = 0U;
626 
627     std::string resname;
628     std::string cachedir;
629 
630     // read the function parameters
631     bool success =
632         GetArgSimple(context, 0, &rs_context_u64) &&
633         GetArgSimple(context, 1, &rs_script_u64) &&
634         GetArgSimple(context, 2, &rs_resnameptr_u64) &&
635         GetArgSimple(context, 3, &rs_cachedirptr_u64);
636 
637     if (!success)
638     {
639         if (log)
640             log->Printf("RenderScriptRuntime::CaptureScriptInit1 - Error while reading the function parameters");
641         return;
642     }
643 
644     process->ReadCStringFromMemory((lldb::addr_t)rs_resnameptr_u64, resname, error);
645     if (error.Fail())
646     {
647         if (log)
648             log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - error reading resname: %s.", error.AsCString());
649 
650     }
651 
652     process->ReadCStringFromMemory((lldb::addr_t)rs_cachedirptr_u64, cachedir, error);
653     if (error.Fail())
654     {
655         if (log)
656             log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - error reading cachedir: %s.", error.AsCString());
657     }
658 
659     if (log)
660         log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - 0x%" PRIx64 ",0x%" PRIx64 " => '%s' at '%s' .",
661                      rs_context_u64, rs_script_u64, resname.c_str(), cachedir.c_str());
662 
663     if (resname.size() > 0)
664     {
665         StreamString strm;
666         strm.Printf("librs.%s.so", resname.c_str());
667 
668         ScriptDetails* script = LookUpScript(rs_script_u64, true);
669         if (script)
670         {
671             script->type = ScriptDetails::eScriptC;
672             script->cacheDir = cachedir;
673             script->resName = resname;
674             script->scriptDyLib = strm.GetData();
675             script->context = addr_t(rs_context_u64);
676         }
677 
678         if (log)
679             log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - '%s' tagged with context 0x%" PRIx64 " and script 0x%" PRIx64 ".",
680                          strm.GetData(), rs_context_u64, rs_script_u64);
681     }
682     else if (log)
683     {
684         log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - resource name invalid, Script not tagged");
685     }
686 
687 }
688 
689 void
690 RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind)
691 {
692     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
693 
694     if (!module)
695     {
696         return;
697     }
698 
699     Target &target = GetProcess()->GetTarget();
700     llvm::Triple::ArchType targetArchType = target.GetArchitecture().GetMachine();
701 
702     if (targetArchType != llvm::Triple::ArchType::x86
703         && targetArchType != llvm::Triple::ArchType::arm
704         && targetArchType != llvm::Triple::ArchType::aarch64)
705     {
706         if (log)
707             log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Unable to hook runtime. Only X86, ARM supported currently.");
708 
709         return;
710     }
711 
712     uint32_t archByteSize = target.GetArchitecture().GetAddressByteSize();
713 
714     for (size_t idx = 0; idx < s_runtimeHookCount; idx++)
715     {
716         const HookDefn* hook_defn = &s_runtimeHookDefns[idx];
717         if (hook_defn->kind != kind) {
718             continue;
719         }
720 
721         const char* symbol_name = (archByteSize == 4) ? hook_defn->symbol_name_m32 : hook_defn->symbol_name_m64;
722 
723         const Symbol *sym = module->FindFirstSymbolWithNameAndType(ConstString(symbol_name), eSymbolTypeCode);
724         if (!sym){
725             if (log){
726                 log->Printf("RenderScriptRuntime::LoadRuntimeHooks - ERROR: Symbol '%s' related to the function %s not found", symbol_name, hook_defn->name);
727             }
728             continue;
729         }
730 
731         addr_t addr = sym->GetLoadAddress(&target);
732         if (addr == LLDB_INVALID_ADDRESS)
733         {
734             if (log)
735                 log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Unable to resolve the address of hook function '%s' with symbol '%s'.",
736                              hook_defn->name, symbol_name);
737             continue;
738         }
739         else
740         {
741             if (log)
742                 log->Printf("RenderScriptRuntime::LoadRuntimeHooks - Function %s, address resolved at 0x%" PRIx64, hook_defn->name, addr);
743         }
744 
745         RuntimeHookSP hook(new RuntimeHook());
746         hook->address = addr;
747         hook->defn = hook_defn;
748         hook->bp_sp = target.CreateBreakpoint(addr, true, false);
749         hook->bp_sp->SetCallback(HookCallback, hook.get(), true);
750         m_runtimeHooks[addr] = hook;
751         if (log)
752         {
753             log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Successfully hooked '%s' in '%s' version %" PRIu64 " at 0x%" PRIx64 ".",
754                 hook_defn->name, module->GetFileSpec().GetFilename().AsCString(), (uint64_t)hook_defn->version, (uint64_t)addr);
755         }
756     }
757 }
758 
759 void
760 RenderScriptRuntime::FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp)
761 {
762     if (!rsmodule_sp)
763         return;
764 
765     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
766 
767     const ModuleSP module = rsmodule_sp->m_module;
768     const FileSpec& file = module->GetPlatformFileSpec();
769 
770     // Iterate over all of the scripts that we currently know of.
771     // Note: We cant push or pop to m_scripts here or it may invalidate rs_script.
772     for (const auto & rs_script : m_scripts)
773     {
774         // Extract the expected .so file path for this script.
775         std::string dylib;
776         if (!rs_script->scriptDyLib.get(dylib))
777             continue;
778 
779         // Only proceed if the module that has loaded corresponds to this script.
780         if (file.GetFilename() != ConstString(dylib.c_str()))
781             continue;
782 
783         // Obtain the script address which we use as a key.
784         lldb::addr_t script;
785         if (!rs_script->script.get(script))
786             continue;
787 
788         // If we have a script mapping for the current script.
789         if (m_scriptMappings.find(script) != m_scriptMappings.end())
790         {
791             // if the module we have stored is different to the one we just received.
792             if (m_scriptMappings[script] != rsmodule_sp)
793             {
794                 if (log)
795                     log->Printf ("RenderScriptRuntime::FixupScriptDetails - Error: script %" PRIx64 " wants reassigned to new rsmodule '%s'.",
796                                     (uint64_t)script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
797             }
798         }
799         // We don't have a script mapping for the current script.
800         else
801         {
802             // Obtain the script resource name.
803             std::string resName;
804             if (rs_script->resName.get(resName))
805                 // Set the modules resource name.
806                 rsmodule_sp->m_resname = resName;
807             // Add Script/Module pair to map.
808             m_scriptMappings[script] = rsmodule_sp;
809             if (log)
810                 log->Printf ("RenderScriptRuntime::FixupScriptDetails - script %" PRIx64 " associated with rsmodule '%s'.",
811                                 (uint64_t)script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
812         }
813     }
814 }
815 
816 bool
817 RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp)
818 {
819     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
820 
821     if (module_sp)
822     {
823         for (const auto &rs_module : m_rsmodules)
824         {
825             if (rs_module->m_module == module_sp)
826             {
827                 // Check if the user has enabled automatically breaking on
828                 // all RS kernels.
829                 if (m_breakAllKernels)
830                     BreakOnModuleKernels(rs_module);
831 
832                 return false;
833             }
834         }
835         bool module_loaded = false;
836         switch (GetModuleKind(module_sp))
837         {
838             case eModuleKindKernelObj:
839             {
840                 RSModuleDescriptorSP module_desc;
841                 module_desc.reset(new RSModuleDescriptor(module_sp));
842                 if (module_desc->ParseRSInfo())
843                 {
844                     m_rsmodules.push_back(module_desc);
845                     module_loaded = true;
846                 }
847                 if (module_loaded)
848                 {
849                     FixupScriptDetails(module_desc);
850                 }
851                 break;
852             }
853             case eModuleKindDriver:
854             {
855                 if (!m_libRSDriver)
856                 {
857                     m_libRSDriver = module_sp;
858                     LoadRuntimeHooks(m_libRSDriver, RenderScriptRuntime::eModuleKindDriver);
859                 }
860                 break;
861             }
862             case eModuleKindImpl:
863             {
864                 m_libRSCpuRef = module_sp;
865                 break;
866             }
867             case eModuleKindLibRS:
868             {
869                 if (!m_libRS)
870                 {
871                     m_libRS = module_sp;
872                     static ConstString gDbgPresentStr("gDebuggerPresent");
873                     const Symbol* debug_present = m_libRS->FindFirstSymbolWithNameAndType(gDbgPresentStr, eSymbolTypeData);
874                     if (debug_present)
875                     {
876                         Error error;
877                         uint32_t flag = 0x00000001U;
878                         Target &target = GetProcess()->GetTarget();
879                         addr_t addr = debug_present->GetLoadAddress(&target);
880                         GetProcess()->WriteMemory(addr, &flag, sizeof(flag), error);
881                         if(error.Success())
882                         {
883                             if (log)
884                                 log->Printf ("RenderScriptRuntime::LoadModule - Debugger present flag set on debugee");
885 
886                             m_debuggerPresentFlagged = true;
887                         }
888                         else if (log)
889                         {
890                             log->Printf ("RenderScriptRuntime::LoadModule - Error writing debugger present flags '%s' ", error.AsCString());
891                         }
892                     }
893                     else if (log)
894                     {
895                         log->Printf ("RenderScriptRuntime::LoadModule - Error writing debugger present flags - symbol not found");
896                     }
897                 }
898                 break;
899             }
900             default:
901                 break;
902         }
903         if (module_loaded)
904             Update();
905         return module_loaded;
906     }
907     return false;
908 }
909 
910 void
911 RenderScriptRuntime::Update()
912 {
913     if (m_rsmodules.size() > 0)
914     {
915         if (!m_initiated)
916         {
917             Initiate();
918         }
919     }
920 }
921 
922 
923 // The maximum line length of an .rs.info packet
924 #define MAXLINE 500
925 
926 // The .rs.info symbol in renderscript modules contains a string which needs to be parsed.
927 // The string is basic and is parsed on a line by line basis.
928 bool
929 RSModuleDescriptor::ParseRSInfo()
930 {
931     const Symbol *info_sym = m_module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData);
932     if (info_sym)
933     {
934         const addr_t addr = info_sym->GetAddressRef().GetFileAddress();
935         const addr_t size = info_sym->GetByteSize();
936         const FileSpec fs = m_module->GetFileSpec();
937 
938         DataBufferSP buffer = fs.ReadFileContents(addr, size);
939 
940         if (!buffer)
941             return false;
942 
943         std::string info((const char *)buffer->GetBytes());
944 
945         std::vector<std::string> info_lines;
946         size_t lpos = info.find('\n');
947         while (lpos != std::string::npos)
948         {
949             info_lines.push_back(info.substr(0, lpos));
950             info = info.substr(lpos + 1);
951             lpos = info.find('\n');
952         }
953         size_t offset = 0;
954         while (offset < info_lines.size())
955         {
956             std::string line = info_lines[offset];
957             // Parse directives
958             uint32_t numDefns = 0;
959             if (sscanf(line.c_str(), "exportVarCount: %u", &numDefns) == 1)
960             {
961                 while (numDefns--)
962                     m_globals.push_back(RSGlobalDescriptor(this, info_lines[++offset].c_str()));
963             }
964             else if (sscanf(line.c_str(), "exportFuncCount: %u", &numDefns) == 1)
965             {
966             }
967             else if (sscanf(line.c_str(), "exportForEachCount: %u", &numDefns) == 1)
968             {
969                 char name[MAXLINE];
970                 while (numDefns--)
971                 {
972                     uint32_t slot = 0;
973                     name[0] = '\0';
974                     if (sscanf(info_lines[++offset].c_str(), "%u - %s", &slot, &name[0]) == 2)
975                     {
976                         m_kernels.push_back(RSKernelDescriptor(this, name, slot));
977                     }
978                 }
979             }
980             else if (sscanf(line.c_str(), "pragmaCount: %u", &numDefns) == 1)
981             {
982                 char name[MAXLINE];
983                 char value[MAXLINE];
984                 while (numDefns--)
985                 {
986                     name[0] = '\0';
987                     value[0] = '\0';
988                     if (sscanf(info_lines[++offset].c_str(), "%s - %s", &name[0], &value[0]) != 0
989                         && (name[0] != '\0'))
990                     {
991                         m_pragmas[std::string(name)] = value;
992                     }
993                 }
994             }
995             else if (sscanf(line.c_str(), "objectSlotCount: %u", &numDefns) == 1)
996             {
997             }
998 
999             offset++;
1000         }
1001         return m_kernels.size() > 0;
1002     }
1003     return false;
1004 }
1005 
1006 bool
1007 RenderScriptRuntime::ProbeModules(const ModuleList module_list)
1008 {
1009     bool rs_found = false;
1010     size_t num_modules = module_list.GetSize();
1011     for (size_t i = 0; i < num_modules; i++)
1012     {
1013         auto module = module_list.GetModuleAtIndex(i);
1014         rs_found |= LoadModule(module);
1015     }
1016     return rs_found;
1017 }
1018 
1019 void
1020 RenderScriptRuntime::Status(Stream &strm) const
1021 {
1022     if (m_libRS)
1023     {
1024         strm.Printf("Runtime Library discovered.");
1025         strm.EOL();
1026     }
1027     if (m_libRSDriver)
1028     {
1029         strm.Printf("Runtime Driver discovered.");
1030         strm.EOL();
1031     }
1032     if (m_libRSCpuRef)
1033     {
1034         strm.Printf("CPU Reference Implementation discovered.");
1035         strm.EOL();
1036     }
1037 
1038     if (m_runtimeHooks.size())
1039     {
1040         strm.Printf("Runtime functions hooked:");
1041         strm.EOL();
1042         for (auto b : m_runtimeHooks)
1043         {
1044             strm.Indent(b.second->defn->name);
1045             strm.EOL();
1046         }
1047         strm.EOL();
1048     }
1049     else
1050     {
1051         strm.Printf("Runtime is not hooked.");
1052         strm.EOL();
1053     }
1054 }
1055 
1056 void
1057 RenderScriptRuntime::DumpContexts(Stream &strm) const
1058 {
1059     strm.Printf("Inferred RenderScript Contexts:");
1060     strm.EOL();
1061     strm.IndentMore();
1062 
1063     std::map<addr_t, uint64_t> contextReferences;
1064 
1065     // Iterate over all of the currently discovered scripts.
1066     // Note: We cant push or pop from m_scripts inside this loop or it may invalidate script.
1067     for (const auto & script : m_scripts)
1068     {
1069         if (!script->context.isValid())
1070             continue;
1071         lldb::addr_t context = *script->context;
1072 
1073         if (contextReferences.find(context) != contextReferences.end())
1074         {
1075             contextReferences[context]++;
1076         }
1077         else
1078         {
1079             contextReferences[context] = 1;
1080         }
1081     }
1082 
1083     for (const auto& cRef : contextReferences)
1084     {
1085         strm.Printf("Context 0x%" PRIx64 ": %" PRIu64 " script instances", cRef.first, cRef.second);
1086         strm.EOL();
1087     }
1088     strm.IndentLess();
1089 }
1090 
1091 void
1092 RenderScriptRuntime::DumpKernels(Stream &strm) const
1093 {
1094     strm.Printf("RenderScript Kernels:");
1095     strm.EOL();
1096     strm.IndentMore();
1097     for (const auto &module : m_rsmodules)
1098     {
1099         strm.Printf("Resource '%s':",module->m_resname.c_str());
1100         strm.EOL();
1101         for (const auto &kernel : module->m_kernels)
1102         {
1103             strm.Indent(kernel.m_name.AsCString());
1104             strm.EOL();
1105         }
1106     }
1107     strm.IndentLess();
1108 }
1109 
1110 // Set breakpoints on every kernel found in RS module
1111 void
1112 RenderScriptRuntime::BreakOnModuleKernels(const RSModuleDescriptorSP rsmodule_sp)
1113 {
1114     for (const auto &kernel : rsmodule_sp->m_kernels)
1115     {
1116         // Don't set breakpoint on 'root' kernel
1117         if (strcmp(kernel.m_name.AsCString(), "root") == 0)
1118             continue;
1119 
1120         CreateKernelBreakpoint(kernel.m_name);
1121     }
1122 }
1123 
1124 // Method is internally called by the 'kernel breakpoint all' command to
1125 // enable or disable breaking on all kernels.
1126 //
1127 // When do_break is true we want to enable this functionality.
1128 // When do_break is false we want to disable it.
1129 void
1130 RenderScriptRuntime::SetBreakAllKernels(bool do_break, TargetSP target)
1131 {
1132     Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
1133 
1134     InitSearchFilter(target);
1135 
1136     // Set breakpoints on all the kernels
1137     if (do_break && !m_breakAllKernels)
1138     {
1139         m_breakAllKernels = true;
1140 
1141         for (const auto &module : m_rsmodules)
1142             BreakOnModuleKernels(module);
1143 
1144         if (log)
1145             log->Printf("RenderScriptRuntime::SetBreakAllKernels(True)"
1146                         "- breakpoints set on all currently loaded kernels");
1147     }
1148     else if (!do_break && m_breakAllKernels) // Breakpoints won't be set on any new kernels.
1149     {
1150         m_breakAllKernels = false;
1151 
1152         if (log)
1153             log->Printf("RenderScriptRuntime::SetBreakAllKernels(False) - breakpoints no longer automatically set");
1154     }
1155 }
1156 
1157 // Given the name of a kernel this function creates a breakpoint using our
1158 // own breakpoint resolver, and returns the Breakpoint shared pointer.
1159 BreakpointSP
1160 RenderScriptRuntime::CreateKernelBreakpoint(const ConstString& name)
1161 {
1162     Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
1163 
1164     if (!m_filtersp)
1165     {
1166         if (log)
1167             log->Printf("RenderScriptRuntime::CreateKernelBreakpoint - Error: No breakpoint search filter set");
1168         return nullptr;
1169     }
1170 
1171     BreakpointResolverSP resolver_sp(new RSBreakpointResolver(nullptr, name));
1172     BreakpointSP bp = GetProcess()->GetTarget().CreateBreakpoint(m_filtersp, resolver_sp, false, false, false);
1173 
1174     // Give RS breakpoints a specific name, so the user can manipulate them as a group.
1175     Error err;
1176     if (!bp->AddName("RenderScriptKernel", err) && log)
1177         log->Printf("RenderScriptRuntime::CreateKernelBreakpoint: Error setting break name, %s", err.AsCString());
1178 
1179     return bp;
1180 }
1181 
1182 void
1183 RenderScriptRuntime::AttemptBreakpointAtKernelName(Stream &strm, const char* name, Error& error, TargetSP target)
1184 {
1185     if (!name)
1186     {
1187         error.SetErrorString("invalid kernel name");
1188         return;
1189     }
1190 
1191     InitSearchFilter(target);
1192 
1193     ConstString kernel_name(name);
1194     BreakpointSP bp = CreateKernelBreakpoint(kernel_name);
1195     if (bp)
1196         bp->GetDescription(&strm, lldb::eDescriptionLevelInitial, false);
1197 
1198     return;
1199 }
1200 
1201 void
1202 RenderScriptRuntime::DumpModules(Stream &strm) const
1203 {
1204     strm.Printf("RenderScript Modules:");
1205     strm.EOL();
1206     strm.IndentMore();
1207     for (const auto &module : m_rsmodules)
1208     {
1209         module->Dump(strm);
1210     }
1211     strm.IndentLess();
1212 }
1213 
1214 RenderScriptRuntime::ScriptDetails*
1215 RenderScriptRuntime::LookUpScript(addr_t address, bool create)
1216 {
1217     for (const auto & s : m_scripts)
1218     {
1219         if (s->script.isValid())
1220             if (*s->script == address)
1221                 return s.get();
1222     }
1223     if (create)
1224     {
1225         std::unique_ptr<ScriptDetails> s(new ScriptDetails);
1226         s->script = address;
1227         m_scripts.push_back(std::move(s));
1228         return m_scripts.back().get();
1229     }
1230     return nullptr;
1231 }
1232 
1233 RenderScriptRuntime::AllocationDetails*
1234 RenderScriptRuntime::LookUpAllocation(addr_t address, bool create)
1235 {
1236     for (const auto & a : m_allocations)
1237     {
1238         if (a->address.isValid())
1239             if (*a->address == address)
1240                 return a.get();
1241     }
1242     if (create)
1243     {
1244         std::unique_ptr<AllocationDetails> a(new AllocationDetails);
1245         a->address = address;
1246         m_allocations.push_back(std::move(a));
1247         return m_allocations.back().get();
1248     }
1249     return nullptr;
1250 }
1251 
1252 void
1253 RSModuleDescriptor::Dump(Stream &strm) const
1254 {
1255     strm.Indent();
1256     m_module->GetFileSpec().Dump(&strm);
1257     if(m_module->GetNumCompileUnits())
1258     {
1259         strm.Indent("Debug info loaded.");
1260     }
1261     else
1262     {
1263         strm.Indent("Debug info does not exist.");
1264     }
1265     strm.EOL();
1266     strm.IndentMore();
1267     strm.Indent();
1268     strm.Printf("Globals: %" PRIu64, static_cast<uint64_t>(m_globals.size()));
1269     strm.EOL();
1270     strm.IndentMore();
1271     for (const auto &global : m_globals)
1272     {
1273         global.Dump(strm);
1274     }
1275     strm.IndentLess();
1276     strm.Indent();
1277     strm.Printf("Kernels: %" PRIu64, static_cast<uint64_t>(m_kernels.size()));
1278     strm.EOL();
1279     strm.IndentMore();
1280     for (const auto &kernel : m_kernels)
1281     {
1282         kernel.Dump(strm);
1283     }
1284     strm.Printf("Pragmas: %"  PRIu64 , static_cast<uint64_t>(m_pragmas.size()));
1285     strm.EOL();
1286     strm.IndentMore();
1287     for (const auto &key_val : m_pragmas)
1288     {
1289         strm.Printf("%s: %s", key_val.first.c_str(), key_val.second.c_str());
1290         strm.EOL();
1291     }
1292     strm.IndentLess(4);
1293 }
1294 
1295 void
1296 RSGlobalDescriptor::Dump(Stream &strm) const
1297 {
1298     strm.Indent(m_name.AsCString());
1299     VariableList var_list;
1300     m_module->m_module->FindGlobalVariables(m_name, nullptr, true, 1U, var_list);
1301     if (var_list.GetSize() == 1)
1302     {
1303         auto var = var_list.GetVariableAtIndex(0);
1304         auto type = var->GetType();
1305         if(type)
1306         {
1307             strm.Printf(" - ");
1308             type->DumpTypeName(&strm);
1309         }
1310         else
1311         {
1312             strm.Printf(" - Unknown Type");
1313         }
1314     }
1315     else
1316     {
1317         strm.Printf(" - variable identified, but not found in binary");
1318         const Symbol* s = m_module->m_module->FindFirstSymbolWithNameAndType(m_name, eSymbolTypeData);
1319         if (s)
1320         {
1321             strm.Printf(" (symbol exists) ");
1322         }
1323     }
1324 
1325     strm.EOL();
1326 }
1327 
1328 void
1329 RSKernelDescriptor::Dump(Stream &strm) const
1330 {
1331     strm.Indent(m_name.AsCString());
1332     strm.EOL();
1333 }
1334 
1335 class CommandObjectRenderScriptRuntimeModuleProbe : public CommandObjectParsed
1336 {
1337   private:
1338   public:
1339     CommandObjectRenderScriptRuntimeModuleProbe(CommandInterpreter &interpreter)
1340         : CommandObjectParsed(interpreter, "renderscript module probe",
1341                               "Initiates a Probe of all loaded modules for kernels and other renderscript objects.",
1342                               "renderscript module probe",
1343                               eCommandRequiresTarget | eCommandRequiresProcess | eCommandProcessMustBeLaunched)
1344     {
1345     }
1346 
1347     ~CommandObjectRenderScriptRuntimeModuleProbe() {}
1348 
1349     bool
1350     DoExecute(Args &command, CommandReturnObject &result)
1351     {
1352         const size_t argc = command.GetArgumentCount();
1353         if (argc == 0)
1354         {
1355             Target *target = m_exe_ctx.GetTargetPtr();
1356             RenderScriptRuntime *runtime =
1357                 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
1358             auto module_list = target->GetImages();
1359             bool new_rs_details = runtime->ProbeModules(module_list);
1360             if (new_rs_details)
1361             {
1362                 result.AppendMessage("New renderscript modules added to runtime model.");
1363             }
1364             result.SetStatus(eReturnStatusSuccessFinishResult);
1365             return true;
1366         }
1367 
1368         result.AppendErrorWithFormat("'%s' takes no arguments", m_cmd_name.c_str());
1369         result.SetStatus(eReturnStatusFailed);
1370         return false;
1371     }
1372 };
1373 
1374 class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed
1375 {
1376   private:
1377   public:
1378     CommandObjectRenderScriptRuntimeModuleDump(CommandInterpreter &interpreter)
1379         : CommandObjectParsed(interpreter, "renderscript module dump",
1380                               "Dumps renderscript specific information for all modules.", "renderscript module dump",
1381                               eCommandRequiresProcess | eCommandProcessMustBeLaunched)
1382     {
1383     }
1384 
1385     ~CommandObjectRenderScriptRuntimeModuleDump() {}
1386 
1387     bool
1388     DoExecute(Args &command, CommandReturnObject &result)
1389     {
1390         RenderScriptRuntime *runtime =
1391             (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
1392         runtime->DumpModules(result.GetOutputStream());
1393         result.SetStatus(eReturnStatusSuccessFinishResult);
1394         return true;
1395     }
1396 };
1397 
1398 class CommandObjectRenderScriptRuntimeModule : public CommandObjectMultiword
1399 {
1400   private:
1401   public:
1402     CommandObjectRenderScriptRuntimeModule(CommandInterpreter &interpreter)
1403         : CommandObjectMultiword(interpreter, "renderscript module", "Commands that deal with renderscript modules.",
1404                                  NULL)
1405     {
1406         LoadSubCommand("probe", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleProbe(interpreter)));
1407         LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleDump(interpreter)));
1408     }
1409 
1410     ~CommandObjectRenderScriptRuntimeModule() {}
1411 };
1412 
1413 class CommandObjectRenderScriptRuntimeKernelList : public CommandObjectParsed
1414 {
1415   private:
1416   public:
1417     CommandObjectRenderScriptRuntimeKernelList(CommandInterpreter &interpreter)
1418         : CommandObjectParsed(interpreter, "renderscript kernel list",
1419                               "Lists renderscript kernel names and associated script resources.", "renderscript kernel list",
1420                               eCommandRequiresProcess | eCommandProcessMustBeLaunched)
1421     {
1422     }
1423 
1424     ~CommandObjectRenderScriptRuntimeKernelList() {}
1425 
1426     bool
1427     DoExecute(Args &command, CommandReturnObject &result)
1428     {
1429         RenderScriptRuntime *runtime =
1430             (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
1431         runtime->DumpKernels(result.GetOutputStream());
1432         result.SetStatus(eReturnStatusSuccessFinishResult);
1433         return true;
1434     }
1435 };
1436 
1437 class CommandObjectRenderScriptRuntimeKernelBreakpointSet : public CommandObjectParsed
1438 {
1439   private:
1440   public:
1441     CommandObjectRenderScriptRuntimeKernelBreakpointSet(CommandInterpreter &interpreter)
1442         : CommandObjectParsed(interpreter, "renderscript kernel breakpoint set",
1443                               "Sets a breakpoint on a renderscript kernel.", "renderscript kernel breakpoint set <kernel_name>",
1444                               eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused)
1445     {
1446     }
1447 
1448     ~CommandObjectRenderScriptRuntimeKernelBreakpointSet() {}
1449 
1450     bool
1451     DoExecute(Args &command, CommandReturnObject &result)
1452     {
1453         const size_t argc = command.GetArgumentCount();
1454         if (argc == 1)
1455         {
1456             RenderScriptRuntime *runtime =
1457                 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
1458 
1459             Error error;
1460             runtime->AttemptBreakpointAtKernelName(result.GetOutputStream(), command.GetArgumentAtIndex(0),
1461                                                    error, m_exe_ctx.GetTargetSP());
1462 
1463             if (error.Success())
1464             {
1465                 result.AppendMessage("Breakpoint(s) created");
1466                 result.SetStatus(eReturnStatusSuccessFinishResult);
1467                 return true;
1468             }
1469             result.SetStatus(eReturnStatusFailed);
1470             result.AppendErrorWithFormat("Error: %s", error.AsCString());
1471             return false;
1472         }
1473 
1474         result.AppendErrorWithFormat("'%s' takes 1 argument of kernel name", m_cmd_name.c_str());
1475         result.SetStatus(eReturnStatusFailed);
1476         return false;
1477     }
1478 };
1479 
1480 class CommandObjectRenderScriptRuntimeKernelBreakpointAll : public CommandObjectParsed
1481 {
1482   private:
1483   public:
1484     CommandObjectRenderScriptRuntimeKernelBreakpointAll(CommandInterpreter &interpreter)
1485         : CommandObjectParsed(interpreter, "renderscript kernel breakpoint all",
1486                               "Automatically sets a breakpoint on all renderscript kernels that are or will be loaded.\n"
1487                               "Disabling option means breakpoints will no longer be set on any kernels loaded in the future, "
1488                               "but does not remove currently set breakpoints.",
1489                               "renderscript kernel breakpoint all <enable/disable>",
1490                               eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused)
1491     {
1492     }
1493 
1494     ~CommandObjectRenderScriptRuntimeKernelBreakpointAll() {}
1495 
1496     bool
1497     DoExecute(Args &command, CommandReturnObject &result)
1498     {
1499         const size_t argc = command.GetArgumentCount();
1500         if (argc != 1)
1501         {
1502             result.AppendErrorWithFormat("'%s' takes 1 argument of 'enable' or 'disable'", m_cmd_name.c_str());
1503             result.SetStatus(eReturnStatusFailed);
1504             return false;
1505         }
1506 
1507         RenderScriptRuntime *runtime =
1508           static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
1509 
1510         bool do_break = false;
1511         const char* argument = command.GetArgumentAtIndex(0);
1512         if (strcmp(argument, "enable") == 0)
1513         {
1514             do_break = true;
1515             result.AppendMessage("Breakpoints will be set on all kernels.");
1516         }
1517         else if (strcmp(argument, "disable") == 0)
1518         {
1519             do_break = false;
1520             result.AppendMessage("Breakpoints will not be set on any new kernels.");
1521         }
1522         else
1523         {
1524             result.AppendErrorWithFormat("Argument must be either 'enable' or 'disable'");
1525             result.SetStatus(eReturnStatusFailed);
1526             return false;
1527         }
1528 
1529         runtime->SetBreakAllKernels(do_break, m_exe_ctx.GetTargetSP());
1530 
1531         result.SetStatus(eReturnStatusSuccessFinishResult);
1532         return true;
1533     }
1534 };
1535 
1536 class CommandObjectRenderScriptRuntimeKernelBreakpoint : public CommandObjectMultiword
1537 {
1538   private:
1539   public:
1540     CommandObjectRenderScriptRuntimeKernelBreakpoint(CommandInterpreter &interpreter)
1541         : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that generate breakpoints on renderscript kernels.",
1542                                  nullptr)
1543     {
1544         LoadSubCommand("set", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointSet(interpreter)));
1545         LoadSubCommand("all", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointAll(interpreter)));
1546     }
1547 
1548     ~CommandObjectRenderScriptRuntimeKernelBreakpoint() {}
1549 };
1550 
1551 class CommandObjectRenderScriptRuntimeKernel : public CommandObjectMultiword
1552 {
1553   private:
1554   public:
1555     CommandObjectRenderScriptRuntimeKernel(CommandInterpreter &interpreter)
1556         : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that deal with renderscript kernels.",
1557                                  NULL)
1558     {
1559         LoadSubCommand("list", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelList(interpreter)));
1560         LoadSubCommand("breakpoint", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpoint(interpreter)));
1561     }
1562 
1563     ~CommandObjectRenderScriptRuntimeKernel() {}
1564 };
1565 
1566 class CommandObjectRenderScriptRuntimeContextDump : public CommandObjectParsed
1567 {
1568   private:
1569   public:
1570     CommandObjectRenderScriptRuntimeContextDump(CommandInterpreter &interpreter)
1571         : CommandObjectParsed(interpreter, "renderscript context dump",
1572                               "Dumps renderscript context information.", "renderscript context dump",
1573                               eCommandRequiresProcess | eCommandProcessMustBeLaunched)
1574     {
1575     }
1576 
1577     ~CommandObjectRenderScriptRuntimeContextDump() {}
1578 
1579     bool
1580     DoExecute(Args &command, CommandReturnObject &result)
1581     {
1582         RenderScriptRuntime *runtime =
1583             (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
1584         runtime->DumpContexts(result.GetOutputStream());
1585         result.SetStatus(eReturnStatusSuccessFinishResult);
1586         return true;
1587     }
1588 };
1589 
1590 class CommandObjectRenderScriptRuntimeContext : public CommandObjectMultiword
1591 {
1592   private:
1593   public:
1594     CommandObjectRenderScriptRuntimeContext(CommandInterpreter &interpreter)
1595         : CommandObjectMultiword(interpreter, "renderscript context", "Commands that deal with renderscript contexts.",
1596                                  NULL)
1597     {
1598         LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeContextDump(interpreter)));
1599     }
1600 
1601     ~CommandObjectRenderScriptRuntimeContext() {}
1602 };
1603 
1604 class CommandObjectRenderScriptRuntimeStatus : public CommandObjectParsed
1605 {
1606   private:
1607   public:
1608     CommandObjectRenderScriptRuntimeStatus(CommandInterpreter &interpreter)
1609         : CommandObjectParsed(interpreter, "renderscript status",
1610                               "Displays current renderscript runtime status.", "renderscript status",
1611                               eCommandRequiresProcess | eCommandProcessMustBeLaunched)
1612     {
1613     }
1614 
1615     ~CommandObjectRenderScriptRuntimeStatus() {}
1616 
1617     bool
1618     DoExecute(Args &command, CommandReturnObject &result)
1619     {
1620         RenderScriptRuntime *runtime =
1621             (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
1622         runtime->Status(result.GetOutputStream());
1623         result.SetStatus(eReturnStatusSuccessFinishResult);
1624         return true;
1625     }
1626 };
1627 
1628 class CommandObjectRenderScriptRuntime : public CommandObjectMultiword
1629 {
1630   public:
1631     CommandObjectRenderScriptRuntime(CommandInterpreter &interpreter)
1632         : CommandObjectMultiword(interpreter, "renderscript", "A set of commands for operating on renderscript.",
1633                                  "renderscript <subcommand> [<subcommand-options>]")
1634     {
1635         LoadSubCommand("module", CommandObjectSP(new CommandObjectRenderScriptRuntimeModule(interpreter)));
1636         LoadSubCommand("status", CommandObjectSP(new CommandObjectRenderScriptRuntimeStatus(interpreter)));
1637         LoadSubCommand("kernel", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernel(interpreter)));
1638         LoadSubCommand("context", CommandObjectSP(new CommandObjectRenderScriptRuntimeContext(interpreter)));
1639     }
1640 
1641     ~CommandObjectRenderScriptRuntime() {}
1642 };
1643 
1644 void
1645 RenderScriptRuntime::Initiate()
1646 {
1647     assert(!m_initiated);
1648 }
1649 
1650 RenderScriptRuntime::RenderScriptRuntime(Process *process)
1651     : lldb_private::CPPLanguageRuntime(process), m_initiated(false), m_debuggerPresentFlagged(false),
1652       m_breakAllKernels(false)
1653 {
1654     ModulesDidLoad(process->GetTarget().GetImages());
1655 }
1656 
1657 lldb::CommandObjectSP
1658 RenderScriptRuntime::GetCommandObject(lldb_private::CommandInterpreter& interpreter)
1659 {
1660     static CommandObjectSP command_object;
1661     if(!command_object)
1662     {
1663         command_object.reset(new CommandObjectRenderScriptRuntime(interpreter));
1664     }
1665     return command_object;
1666 }
1667 
1668 RenderScriptRuntime::~RenderScriptRuntime() = default;
1669