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/Target/Process.h"
19 #include "lldb/Target/Target.h"
20 #include "lldb/Interpreter/Args.h"
21 #include "lldb/Interpreter/Options.h"
22 #include "lldb/Interpreter/CommandInterpreter.h"
23 #include "lldb/Interpreter/CommandReturnObject.h"
24 #include "lldb/Interpreter/CommandObjectMultiword.h"
25 
26 using namespace lldb;
27 using namespace lldb_private;
28 
29 //------------------------------------------------------------------
30 // Static Functions
31 //------------------------------------------------------------------
32 LanguageRuntime *
33 RenderScriptRuntime::CreateInstance(Process *process, lldb::LanguageType language)
34 {
35 
36     if (language == eLanguageTypeExtRenderScript)
37         return new RenderScriptRuntime(process);
38     else
39         return NULL;
40 }
41 
42 void
43 RenderScriptRuntime::Initialize()
44 {
45     PluginManager::RegisterPlugin(GetPluginNameStatic(), "RenderScript language support", CreateInstance);
46 }
47 
48 void
49 RenderScriptRuntime::Terminate()
50 {
51     PluginManager::UnregisterPlugin(CreateInstance);
52 }
53 
54 lldb_private::ConstString
55 RenderScriptRuntime::GetPluginNameStatic()
56 {
57     static ConstString g_name("renderscript");
58     return g_name;
59 }
60 
61 //------------------------------------------------------------------
62 // PluginInterface protocol
63 //------------------------------------------------------------------
64 lldb_private::ConstString
65 RenderScriptRuntime::GetPluginName()
66 {
67     return GetPluginNameStatic();
68 }
69 
70 uint32_t
71 RenderScriptRuntime::GetPluginVersion()
72 {
73     return 1;
74 }
75 
76 bool
77 RenderScriptRuntime::IsVTableName(const char *name)
78 {
79     return false;
80 }
81 
82 bool
83 RenderScriptRuntime::GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic,
84                                               TypeAndOrName &class_type_or_name, Address &address)
85 {
86     return false;
87 }
88 
89 bool
90 RenderScriptRuntime::CouldHaveDynamicValue(ValueObject &in_value)
91 {
92     return false;
93 }
94 
95 lldb::BreakpointResolverSP
96 RenderScriptRuntime::CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp)
97 {
98     BreakpointResolverSP resolver_sp;
99     return resolver_sp;
100 }
101 
102 bool
103 RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp)
104 {
105     if (module_sp)
106     {
107         for (const auto &rs_module : m_rsmodules)
108         {
109             if (rs_module.m_module == module_sp)
110                 return false;
111         }
112         RSModuleDescriptor module_desc(module_sp);
113         if (module_desc.ParseRSInfo())
114         {
115             m_rsmodules.push_back(module_desc);
116             return true;
117         }
118     }
119     return false;
120 }
121 
122 // The maximum line length of an .rs.info packet
123 #define MAXLINE 500
124 
125 // The .rs.info symbol in renderscript modules contains a string which needs to be parsed.
126 // The string is basic and is parsed on a line by line basis.
127 bool
128 RSModuleDescriptor::ParseRSInfo()
129 {
130     const Symbol *info_sym = m_module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData);
131     if (info_sym)
132     {
133         const addr_t addr = info_sym->GetAddress().GetFileAddress();
134         const addr_t size = info_sym->GetByteSize();
135         const FileSpec fs = m_module->GetFileSpec();
136 
137         DataBufferSP buffer = fs.ReadFileContents(addr, size);
138 
139         if (!buffer)
140             return false;
141 
142         std::string info((const char *)buffer->GetBytes());
143 
144         std::vector<std::string> info_lines;
145         size_t lpos = info.find_first_of("\n");
146         while (lpos != std::string::npos)
147         {
148             info_lines.push_back(info.substr(0, lpos));
149             info = info.substr(lpos + 1);
150             lpos = info.find_first_of("\n");
151         }
152         size_t offset = 0;
153         while (offset < info_lines.size())
154         {
155             std::string line = info_lines[offset];
156             // Parse directives
157             uint32_t numDefns = 0;
158             if (sscanf(line.c_str(), "exportVarCount: %u", &numDefns) == 1)
159             {
160                 while (numDefns--)
161                     m_globals.push_back(RSGlobalDescriptor(*this, info_lines[++offset].c_str()));
162             }
163             else if (sscanf(line.c_str(), "exportFuncCount: %u", &numDefns) == 1)
164             {
165             }
166             else if (sscanf(line.c_str(), "exportForEachCount: %u", &numDefns) == 1)
167             {
168                 char name[MAXLINE];
169                 while (numDefns--)
170                 {
171                     uint32_t slot = 0;
172                     name[0] = '\0';
173                     if (sscanf(info_lines[++offset].c_str(), "%u - %s", &slot, &name[0]) == 2)
174                     {
175                         m_kernels.push_back(RSKernelDescriptor(*this, name, slot));
176                     }
177                 }
178             }
179             else if (sscanf(line.c_str(), "objectSlotCount: %u", &numDefns) == 1)
180             {
181             }
182 
183             offset++;
184         }
185         return m_kernels.size() > 0;
186     }
187     return false;
188 }
189 
190 bool
191 RenderScriptRuntime::ProbeModules(const ModuleList module_list)
192 {
193     bool rs_found = false;
194     size_t num_modules = module_list.GetSize();
195     for (size_t i = 0; i < num_modules; i++)
196     {
197         auto module = module_list.GetModuleAtIndex(i);
198         rs_found |= LoadModule(module);
199     }
200     return rs_found;
201 }
202 
203 void
204 RenderScriptRuntime::DumpModules(Stream &strm) const
205 {
206     strm.Printf("RenderScript Modules:");
207     strm.EOL();
208     strm.IndentMore();
209     for (const auto &module : m_rsmodules)
210     {
211         module.Dump(strm);
212     }
213     strm.IndentLess();
214 }
215 
216 void
217 RSModuleDescriptor::Dump(Stream &strm) const
218 {
219     strm.Indent();
220     m_module->GetFileSpec().Dump(&strm);
221     strm.EOL();
222     strm.IndentMore();
223     strm.Indent();
224     strm.Printf("Globals: %zu", m_globals.size());
225     strm.EOL();
226     strm.IndentMore();
227     for (const auto &global : m_globals)
228     {
229         global.Dump(strm);
230     }
231     strm.IndentLess();
232     strm.Indent();
233     strm.Printf("Kernels: %zu", m_kernels.size());
234     strm.EOL();
235     strm.IndentMore();
236     for (const auto &kernel : m_kernels)
237     {
238         kernel.Dump(strm);
239     }
240     strm.IndentLess(4);
241 }
242 
243 void
244 RSGlobalDescriptor::Dump(Stream &strm) const
245 {
246     strm.Indent(m_name.AsCString());
247     strm.EOL();
248 }
249 
250 void
251 RSKernelDescriptor::Dump(Stream &strm) const
252 {
253     strm.Indent(m_name.AsCString());
254     strm.EOL();
255 }
256 
257 class CommandObjectRenderScriptRuntimeModuleProbe : public CommandObjectParsed
258 {
259   private:
260   public:
261     CommandObjectRenderScriptRuntimeModuleProbe(CommandInterpreter &interpreter)
262         : CommandObjectParsed(interpreter, "renderscript module probe",
263                               "Initiates a Probe of all loaded modules for kernels and other renderscript objects.",
264                               "renderscript module probe",
265                               eFlagRequiresTarget | eFlagRequiresProcess | eFlagProcessMustBeLaunched)
266     {
267     }
268 
269     ~CommandObjectRenderScriptRuntimeModuleProbe() {}
270 
271     bool
272     DoExecute(Args &command, CommandReturnObject &result)
273     {
274         const size_t argc = command.GetArgumentCount();
275         if (argc == 0)
276         {
277             Target *target = m_exe_ctx.GetTargetPtr();
278             RenderScriptRuntime *runtime =
279                 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
280             auto module_list = target->GetImages();
281             bool new_rs_details = runtime->ProbeModules(module_list);
282             if (new_rs_details)
283             {
284                 result.AppendMessage("New renderscript modules added to runtime model.");
285             }
286             result.SetStatus(eReturnStatusSuccessFinishResult);
287             return true;
288         }
289 
290         result.AppendErrorWithFormat("'%s' takes no arguments", m_cmd_name.c_str());
291         result.SetStatus(eReturnStatusFailed);
292         return false;
293     }
294 };
295 
296 class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed
297 {
298   private:
299   public:
300     CommandObjectRenderScriptRuntimeModuleDump(CommandInterpreter &interpreter)
301         : CommandObjectParsed(interpreter, "renderscript module dump",
302                               "Dumps renderscript specific information for all modules.", "renderscript module dump",
303                               eFlagRequiresProcess | eFlagProcessMustBeLaunched)
304     {
305     }
306 
307     ~CommandObjectRenderScriptRuntimeModuleDump() {}
308 
309     bool
310     DoExecute(Args &command, CommandReturnObject &result)
311     {
312         RenderScriptRuntime *runtime =
313             (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
314         runtime->DumpModules(result.GetOutputStream());
315         result.SetStatus(eReturnStatusSuccessFinishResult);
316         return true;
317     }
318 };
319 
320 class CommandObjectRenderScriptRuntimeModule : public CommandObjectMultiword
321 {
322   private:
323   public:
324     CommandObjectRenderScriptRuntimeModule(CommandInterpreter &interpreter)
325         : CommandObjectMultiword(interpreter, "renderscript module", "Commands that deal with renderscript modules.",
326                                  NULL)
327     {
328         LoadSubCommand("probe", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleProbe(interpreter)));
329         LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleDump(interpreter)));
330     }
331 
332     ~CommandObjectRenderScriptRuntimeModule() {}
333 };
334 
335 class CommandObjectRenderScriptRuntime : public CommandObjectMultiword
336 {
337   public:
338     CommandObjectRenderScriptRuntime(CommandInterpreter &interpreter)
339         : CommandObjectMultiword(interpreter, "renderscript", "A set of commands for operating on renderscript.",
340                                  "renderscript <subcommand> [<subcommand-options>]")
341     {
342         LoadSubCommand("module", CommandObjectSP(new CommandObjectRenderScriptRuntimeModule(interpreter)));
343     }
344 
345     ~CommandObjectRenderScriptRuntime() {}
346 };
347 RenderScriptRuntime::RenderScriptRuntime(Process *process)
348     : lldb_private::CPPLanguageRuntime(process)
349 {
350     if (process)
351     {
352         CommandInterpreter &interpreter = process->GetTarget().GetDebugger().GetCommandInterpreter();
353         interpreter.AddCommand("renderscript", CommandObjectSP(new CommandObjectRenderScriptRuntime(interpreter)),
354                                true);
355     }
356 }
357