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