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: %u", 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: %u", 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