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 s.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 a.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     m_module->ParseAllDebugSymbols();
1258     if(m_module->GetNumCompileUnits())
1259     {
1260         strm.Indent("Debug info loaded.");
1261     }
1262     else
1263     {
1264         strm.Indent("Debug info does not exist.");
1265     }
1266     strm.EOL();
1267     strm.IndentMore();
1268     strm.Indent();
1269     strm.Printf("Globals: %" PRIu64, static_cast<uint64_t>(m_globals.size()));
1270     strm.EOL();
1271     strm.IndentMore();
1272     for (const auto &global : m_globals)
1273     {
1274         global.Dump(strm);
1275     }
1276     strm.IndentLess();
1277     strm.Indent();
1278     strm.Printf("Kernels: %" PRIu64, static_cast<uint64_t>(m_kernels.size()));
1279     strm.EOL();
1280     strm.IndentMore();
1281     for (const auto &kernel : m_kernels)
1282     {
1283         kernel.Dump(strm);
1284     }
1285     strm.Printf("Pragmas: %"  PRIu64 , static_cast<uint64_t>(m_pragmas.size()));
1286     strm.EOL();
1287     strm.IndentMore();
1288     for (const auto &key_val : m_pragmas)
1289     {
1290         strm.Printf("%s: %s", key_val.first.c_str(), key_val.second.c_str());
1291         strm.EOL();
1292     }
1293     strm.IndentLess(4);
1294 }
1295 
1296 void
1297 RSGlobalDescriptor::Dump(Stream &strm) const
1298 {
1299     strm.Indent(m_name.AsCString());
1300     VariableList var_list;
1301     m_module->m_module->FindGlobalVariables(m_name, nullptr, true, 1U, var_list);
1302     if (var_list.GetSize() == 1)
1303     {
1304         auto var = var_list.GetVariableAtIndex(0);
1305         auto type = var->GetType();
1306         if(type)
1307         {
1308             strm.Printf(" - ");
1309             type->DumpTypeName(&strm);
1310         }
1311         else
1312         {
1313             strm.Printf(" - Unknown Type");
1314         }
1315     }
1316     else
1317     {
1318         strm.Printf(" - variable identified, but not found in binary");
1319         const Symbol* s = m_module->m_module->FindFirstSymbolWithNameAndType(m_name, eSymbolTypeData);
1320         if (s)
1321         {
1322             strm.Printf(" (symbol exists) ");
1323         }
1324     }
1325 
1326     strm.EOL();
1327 }
1328 
1329 void
1330 RSKernelDescriptor::Dump(Stream &strm) const
1331 {
1332     strm.Indent(m_name.AsCString());
1333     strm.EOL();
1334 }
1335 
1336 class CommandObjectRenderScriptRuntimeModuleProbe : public CommandObjectParsed
1337 {
1338   private:
1339   public:
1340     CommandObjectRenderScriptRuntimeModuleProbe(CommandInterpreter &interpreter)
1341         : CommandObjectParsed(interpreter, "renderscript module probe",
1342                               "Initiates a Probe of all loaded modules for kernels and other renderscript objects.",
1343                               "renderscript module probe",
1344                               eCommandRequiresTarget | eCommandRequiresProcess | eCommandProcessMustBeLaunched)
1345     {
1346     }
1347 
1348     ~CommandObjectRenderScriptRuntimeModuleProbe() {}
1349 
1350     bool
1351     DoExecute(Args &command, CommandReturnObject &result)
1352     {
1353         const size_t argc = command.GetArgumentCount();
1354         if (argc == 0)
1355         {
1356             Target *target = m_exe_ctx.GetTargetPtr();
1357             RenderScriptRuntime *runtime =
1358                 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
1359             auto module_list = target->GetImages();
1360             bool new_rs_details = runtime->ProbeModules(module_list);
1361             if (new_rs_details)
1362             {
1363                 result.AppendMessage("New renderscript modules added to runtime model.");
1364             }
1365             result.SetStatus(eReturnStatusSuccessFinishResult);
1366             return true;
1367         }
1368 
1369         result.AppendErrorWithFormat("'%s' takes no arguments", m_cmd_name.c_str());
1370         result.SetStatus(eReturnStatusFailed);
1371         return false;
1372     }
1373 };
1374 
1375 class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed
1376 {
1377   private:
1378   public:
1379     CommandObjectRenderScriptRuntimeModuleDump(CommandInterpreter &interpreter)
1380         : CommandObjectParsed(interpreter, "renderscript module dump",
1381                               "Dumps renderscript specific information for all modules.", "renderscript module dump",
1382                               eCommandRequiresProcess | eCommandProcessMustBeLaunched)
1383     {
1384     }
1385 
1386     ~CommandObjectRenderScriptRuntimeModuleDump() {}
1387 
1388     bool
1389     DoExecute(Args &command, CommandReturnObject &result)
1390     {
1391         RenderScriptRuntime *runtime =
1392             (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
1393         runtime->DumpModules(result.GetOutputStream());
1394         result.SetStatus(eReturnStatusSuccessFinishResult);
1395         return true;
1396     }
1397 };
1398 
1399 class CommandObjectRenderScriptRuntimeModule : public CommandObjectMultiword
1400 {
1401   private:
1402   public:
1403     CommandObjectRenderScriptRuntimeModule(CommandInterpreter &interpreter)
1404         : CommandObjectMultiword(interpreter, "renderscript module", "Commands that deal with renderscript modules.",
1405                                  NULL)
1406     {
1407         LoadSubCommand("probe", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleProbe(interpreter)));
1408         LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleDump(interpreter)));
1409     }
1410 
1411     ~CommandObjectRenderScriptRuntimeModule() {}
1412 };
1413 
1414 class CommandObjectRenderScriptRuntimeKernelList : public CommandObjectParsed
1415 {
1416   private:
1417   public:
1418     CommandObjectRenderScriptRuntimeKernelList(CommandInterpreter &interpreter)
1419         : CommandObjectParsed(interpreter, "renderscript kernel list",
1420                               "Lists renderscript kernel names and associated script resources.", "renderscript kernel list",
1421                               eCommandRequiresProcess | eCommandProcessMustBeLaunched)
1422     {
1423     }
1424 
1425     ~CommandObjectRenderScriptRuntimeKernelList() {}
1426 
1427     bool
1428     DoExecute(Args &command, CommandReturnObject &result)
1429     {
1430         RenderScriptRuntime *runtime =
1431             (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
1432         runtime->DumpKernels(result.GetOutputStream());
1433         result.SetStatus(eReturnStatusSuccessFinishResult);
1434         return true;
1435     }
1436 };
1437 
1438 class CommandObjectRenderScriptRuntimeKernelBreakpointSet : public CommandObjectParsed
1439 {
1440   private:
1441   public:
1442     CommandObjectRenderScriptRuntimeKernelBreakpointSet(CommandInterpreter &interpreter)
1443         : CommandObjectParsed(interpreter, "renderscript kernel breakpoint set",
1444                               "Sets a breakpoint on a renderscript kernel.", "renderscript kernel breakpoint set <kernel_name>",
1445                               eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused)
1446     {
1447     }
1448 
1449     ~CommandObjectRenderScriptRuntimeKernelBreakpointSet() {}
1450 
1451     bool
1452     DoExecute(Args &command, CommandReturnObject &result)
1453     {
1454         const size_t argc = command.GetArgumentCount();
1455         if (argc == 1)
1456         {
1457             RenderScriptRuntime *runtime =
1458                 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
1459 
1460             Error error;
1461             runtime->AttemptBreakpointAtKernelName(result.GetOutputStream(), command.GetArgumentAtIndex(0),
1462                                                    error, m_exe_ctx.GetTargetSP());
1463 
1464             if (error.Success())
1465             {
1466                 result.AppendMessage("Breakpoint(s) created");
1467                 result.SetStatus(eReturnStatusSuccessFinishResult);
1468                 return true;
1469             }
1470             result.SetStatus(eReturnStatusFailed);
1471             result.AppendErrorWithFormat("Error: %s", error.AsCString());
1472             return false;
1473         }
1474 
1475         result.AppendErrorWithFormat("'%s' takes 1 argument of kernel name", m_cmd_name.c_str());
1476         result.SetStatus(eReturnStatusFailed);
1477         return false;
1478     }
1479 };
1480 
1481 class CommandObjectRenderScriptRuntimeKernelBreakpointAll : public CommandObjectParsed
1482 {
1483   private:
1484   public:
1485     CommandObjectRenderScriptRuntimeKernelBreakpointAll(CommandInterpreter &interpreter)
1486         : CommandObjectParsed(interpreter, "renderscript kernel breakpoint all",
1487                               "Automatically sets a breakpoint on all renderscript kernels that are or will be loaded.\n"
1488                               "Disabling option means breakpoints will no longer be set on any kernels loaded in the future, "
1489                               "but does not remove currently set breakpoints.",
1490                               "renderscript kernel breakpoint all <enable/disable>",
1491                               eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused)
1492     {
1493     }
1494 
1495     ~CommandObjectRenderScriptRuntimeKernelBreakpointAll() {}
1496 
1497     bool
1498     DoExecute(Args &command, CommandReturnObject &result)
1499     {
1500         const size_t argc = command.GetArgumentCount();
1501         if (argc != 1)
1502         {
1503             result.AppendErrorWithFormat("'%s' takes 1 argument of 'enable' or 'disable'", m_cmd_name.c_str());
1504             result.SetStatus(eReturnStatusFailed);
1505             return false;
1506         }
1507 
1508         RenderScriptRuntime *runtime =
1509           static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
1510 
1511         bool do_break = false;
1512         const char* argument = command.GetArgumentAtIndex(0);
1513         if (strcmp(argument, "enable") == 0)
1514         {
1515             do_break = true;
1516             result.AppendMessage("Breakpoints will be set on all kernels.");
1517         }
1518         else if (strcmp(argument, "disable") == 0)
1519         {
1520             do_break = false;
1521             result.AppendMessage("Breakpoints will not be set on any new kernels.");
1522         }
1523         else
1524         {
1525             result.AppendErrorWithFormat("Argument must be either 'enable' or 'disable'");
1526             result.SetStatus(eReturnStatusFailed);
1527             return false;
1528         }
1529 
1530         runtime->SetBreakAllKernels(do_break, m_exe_ctx.GetTargetSP());
1531 
1532         result.SetStatus(eReturnStatusSuccessFinishResult);
1533         return true;
1534     }
1535 };
1536 
1537 class CommandObjectRenderScriptRuntimeKernelBreakpoint : public CommandObjectMultiword
1538 {
1539   private:
1540   public:
1541     CommandObjectRenderScriptRuntimeKernelBreakpoint(CommandInterpreter &interpreter)
1542         : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that generate breakpoints on renderscript kernels.",
1543                                  nullptr)
1544     {
1545         LoadSubCommand("set", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointSet(interpreter)));
1546         LoadSubCommand("all", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointAll(interpreter)));
1547     }
1548 
1549     ~CommandObjectRenderScriptRuntimeKernelBreakpoint() {}
1550 };
1551 
1552 class CommandObjectRenderScriptRuntimeKernel : public CommandObjectMultiword
1553 {
1554   private:
1555   public:
1556     CommandObjectRenderScriptRuntimeKernel(CommandInterpreter &interpreter)
1557         : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that deal with renderscript kernels.",
1558                                  NULL)
1559     {
1560         LoadSubCommand("list", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelList(interpreter)));
1561         LoadSubCommand("breakpoint", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpoint(interpreter)));
1562     }
1563 
1564     ~CommandObjectRenderScriptRuntimeKernel() {}
1565 };
1566 
1567 class CommandObjectRenderScriptRuntimeContextDump : public CommandObjectParsed
1568 {
1569   private:
1570   public:
1571     CommandObjectRenderScriptRuntimeContextDump(CommandInterpreter &interpreter)
1572         : CommandObjectParsed(interpreter, "renderscript context dump",
1573                               "Dumps renderscript context information.", "renderscript context dump",
1574                               eCommandRequiresProcess | eCommandProcessMustBeLaunched)
1575     {
1576     }
1577 
1578     ~CommandObjectRenderScriptRuntimeContextDump() {}
1579 
1580     bool
1581     DoExecute(Args &command, CommandReturnObject &result)
1582     {
1583         RenderScriptRuntime *runtime =
1584             (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
1585         runtime->DumpContexts(result.GetOutputStream());
1586         result.SetStatus(eReturnStatusSuccessFinishResult);
1587         return true;
1588     }
1589 };
1590 
1591 class CommandObjectRenderScriptRuntimeContext : public CommandObjectMultiword
1592 {
1593   private:
1594   public:
1595     CommandObjectRenderScriptRuntimeContext(CommandInterpreter &interpreter)
1596         : CommandObjectMultiword(interpreter, "renderscript context", "Commands that deal with renderscript contexts.",
1597                                  NULL)
1598     {
1599         LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeContextDump(interpreter)));
1600     }
1601 
1602     ~CommandObjectRenderScriptRuntimeContext() {}
1603 };
1604 
1605 class CommandObjectRenderScriptRuntimeStatus : public CommandObjectParsed
1606 {
1607   private:
1608   public:
1609     CommandObjectRenderScriptRuntimeStatus(CommandInterpreter &interpreter)
1610         : CommandObjectParsed(interpreter, "renderscript status",
1611                               "Displays current renderscript runtime status.", "renderscript status",
1612                               eCommandRequiresProcess | eCommandProcessMustBeLaunched)
1613     {
1614     }
1615 
1616     ~CommandObjectRenderScriptRuntimeStatus() {}
1617 
1618     bool
1619     DoExecute(Args &command, CommandReturnObject &result)
1620     {
1621         RenderScriptRuntime *runtime =
1622             (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
1623         runtime->Status(result.GetOutputStream());
1624         result.SetStatus(eReturnStatusSuccessFinishResult);
1625         return true;
1626     }
1627 };
1628 
1629 class CommandObjectRenderScriptRuntime : public CommandObjectMultiword
1630 {
1631   public:
1632     CommandObjectRenderScriptRuntime(CommandInterpreter &interpreter)
1633         : CommandObjectMultiword(interpreter, "renderscript", "A set of commands for operating on renderscript.",
1634                                  "renderscript <subcommand> [<subcommand-options>]")
1635     {
1636         LoadSubCommand("module", CommandObjectSP(new CommandObjectRenderScriptRuntimeModule(interpreter)));
1637         LoadSubCommand("status", CommandObjectSP(new CommandObjectRenderScriptRuntimeStatus(interpreter)));
1638         LoadSubCommand("kernel", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernel(interpreter)));
1639         LoadSubCommand("context", CommandObjectSP(new CommandObjectRenderScriptRuntimeContext(interpreter)));
1640     }
1641 
1642     ~CommandObjectRenderScriptRuntime() {}
1643 };
1644 
1645 void
1646 RenderScriptRuntime::Initiate()
1647 {
1648     assert(!m_initiated);
1649 }
1650 
1651 RenderScriptRuntime::RenderScriptRuntime(Process *process)
1652     : lldb_private::CPPLanguageRuntime(process), m_initiated(false), m_debuggerPresentFlagged(false),
1653       m_breakAllKernels(false)
1654 {
1655     ModulesDidLoad(process->GetTarget().GetImages());
1656 }
1657 
1658 lldb::CommandObjectSP
1659 RenderScriptRuntime::GetCommandObject(lldb_private::CommandInterpreter& interpreter)
1660 {
1661     static CommandObjectSP command_object;
1662     if(!command_object)
1663     {
1664         command_object.reset(new CommandObjectRenderScriptRuntime(interpreter));
1665     }
1666     return command_object;
1667 }
1668 
1669 RenderScriptRuntime::~RenderScriptRuntime() = default;
1670