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 RenderScriptRuntime::ModuleKind 62 RenderScriptRuntime::GetModuleKind(const lldb::ModuleSP &module_sp) 63 { 64 if (module_sp) 65 { 66 // Is this a module containing renderscript kernels? 67 const Symbol *info_sym = module_sp->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData); 68 if (info_sym) 69 { 70 return eModuleKindKernelObj; 71 } 72 } 73 return eModuleKindIgnored; 74 } 75 76 bool 77 RenderScriptRuntime::IsRenderScriptModule(const lldb::ModuleSP &module_sp) 78 { 79 return GetModuleKind(module_sp) != eModuleKindIgnored; 80 } 81 82 83 void 84 RenderScriptRuntime::ModulesDidLoad(const ModuleList &module_list ) 85 { 86 Mutex::Locker locker (module_list.GetMutex ()); 87 88 size_t num_modules = module_list.GetSize(); 89 for (size_t i = 0; i < num_modules; i++) 90 { 91 auto mod = module_list.GetModuleAtIndex (i); 92 if (IsRenderScriptModule (mod)) 93 { 94 LoadModule(mod); 95 } 96 } 97 } 98 99 100 //------------------------------------------------------------------ 101 // PluginInterface protocol 102 //------------------------------------------------------------------ 103 lldb_private::ConstString 104 RenderScriptRuntime::GetPluginName() 105 { 106 return GetPluginNameStatic(); 107 } 108 109 uint32_t 110 RenderScriptRuntime::GetPluginVersion() 111 { 112 return 1; 113 } 114 115 bool 116 RenderScriptRuntime::IsVTableName(const char *name) 117 { 118 return false; 119 } 120 121 bool 122 RenderScriptRuntime::GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic, 123 TypeAndOrName &class_type_or_name, Address &address) 124 { 125 return false; 126 } 127 128 bool 129 RenderScriptRuntime::CouldHaveDynamicValue(ValueObject &in_value) 130 { 131 return false; 132 } 133 134 lldb::BreakpointResolverSP 135 RenderScriptRuntime::CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp) 136 { 137 BreakpointResolverSP resolver_sp; 138 return resolver_sp; 139 } 140 141 bool 142 RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp) 143 { 144 if (module_sp) 145 { 146 for (const auto &rs_module : m_rsmodules) 147 { 148 if (rs_module.m_module == module_sp) 149 return false; 150 } 151 bool module_loaded = false; 152 switch (GetModuleKind(module_sp)) 153 { 154 case eModuleKindKernelObj: 155 { 156 RSModuleDescriptor module_desc(module_sp); 157 if (module_desc.ParseRSInfo()) 158 { 159 m_rsmodules.push_back(module_desc); 160 module_loaded = true; 161 } 162 break; 163 } 164 case eModuleKindDriver: 165 case eModuleKindImpl: 166 case eModuleKindLibRS: 167 default: 168 break; 169 } 170 if (module_loaded) 171 Update(); 172 return module_loaded; 173 } 174 return false; 175 } 176 177 void 178 RenderScriptRuntime::Update() 179 { 180 if (m_rsmodules.size() > 0) 181 { 182 if (!m_initiated) 183 { 184 Initiate(); 185 } 186 } 187 } 188 189 190 // The maximum line length of an .rs.info packet 191 #define MAXLINE 500 192 193 // The .rs.info symbol in renderscript modules contains a string which needs to be parsed. 194 // The string is basic and is parsed on a line by line basis. 195 bool 196 RSModuleDescriptor::ParseRSInfo() 197 { 198 const Symbol *info_sym = m_module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData); 199 if (info_sym) 200 { 201 const addr_t addr = info_sym->GetAddress().GetFileAddress(); 202 const addr_t size = info_sym->GetByteSize(); 203 const FileSpec fs = m_module->GetFileSpec(); 204 205 DataBufferSP buffer = fs.ReadFileContents(addr, size); 206 207 if (!buffer) 208 return false; 209 210 std::string info((const char *)buffer->GetBytes()); 211 212 std::vector<std::string> info_lines; 213 size_t lpos = info.find_first_of("\n"); 214 while (lpos != std::string::npos) 215 { 216 info_lines.push_back(info.substr(0, lpos)); 217 info = info.substr(lpos + 1); 218 lpos = info.find_first_of("\n"); 219 } 220 size_t offset = 0; 221 while (offset < info_lines.size()) 222 { 223 std::string line = info_lines[offset]; 224 // Parse directives 225 uint32_t numDefns = 0; 226 if (sscanf(line.c_str(), "exportVarCount: %u", &numDefns) == 1) 227 { 228 while (numDefns--) 229 m_globals.push_back(RSGlobalDescriptor(*this, info_lines[++offset].c_str())); 230 } 231 else if (sscanf(line.c_str(), "exportFuncCount: %u", &numDefns) == 1) 232 { 233 } 234 else if (sscanf(line.c_str(), "exportForEachCount: %u", &numDefns) == 1) 235 { 236 char name[MAXLINE]; 237 while (numDefns--) 238 { 239 uint32_t slot = 0; 240 name[0] = '\0'; 241 if (sscanf(info_lines[++offset].c_str(), "%u - %s", &slot, &name[0]) == 2) 242 { 243 m_kernels.push_back(RSKernelDescriptor(*this, name, slot)); 244 } 245 } 246 } 247 else if (sscanf(line.c_str(), "objectSlotCount: %u", &numDefns) == 1) 248 { 249 } 250 251 offset++; 252 } 253 return m_kernels.size() > 0; 254 } 255 return false; 256 } 257 258 bool 259 RenderScriptRuntime::ProbeModules(const ModuleList module_list) 260 { 261 bool rs_found = false; 262 size_t num_modules = module_list.GetSize(); 263 for (size_t i = 0; i < num_modules; i++) 264 { 265 auto module = module_list.GetModuleAtIndex(i); 266 rs_found |= LoadModule(module); 267 } 268 return rs_found; 269 } 270 271 void 272 RenderScriptRuntime::DumpModules(Stream &strm) const 273 { 274 strm.Printf("RenderScript Modules:"); 275 strm.EOL(); 276 strm.IndentMore(); 277 for (const auto &module : m_rsmodules) 278 { 279 module.Dump(strm); 280 } 281 strm.IndentLess(); 282 } 283 284 void 285 RSModuleDescriptor::Dump(Stream &strm) const 286 { 287 strm.Indent(); 288 m_module->GetFileSpec().Dump(&strm); 289 strm.EOL(); 290 strm.IndentMore(); 291 strm.Indent(); 292 strm.Printf("Globals: %" PRIu64, static_cast<uint64_t>(m_globals.size())); 293 strm.EOL(); 294 strm.IndentMore(); 295 for (const auto &global : m_globals) 296 { 297 global.Dump(strm); 298 } 299 strm.IndentLess(); 300 strm.Indent(); 301 strm.Printf("Kernels: %" PRIu64, static_cast<uint64_t>(m_kernels.size())); 302 strm.EOL(); 303 strm.IndentMore(); 304 for (const auto &kernel : m_kernels) 305 { 306 kernel.Dump(strm); 307 } 308 strm.IndentLess(4); 309 } 310 311 void 312 RSGlobalDescriptor::Dump(Stream &strm) const 313 { 314 strm.Indent(m_name.AsCString()); 315 strm.EOL(); 316 } 317 318 void 319 RSKernelDescriptor::Dump(Stream &strm) const 320 { 321 strm.Indent(m_name.AsCString()); 322 strm.EOL(); 323 } 324 325 class CommandObjectRenderScriptRuntimeModuleProbe : public CommandObjectParsed 326 { 327 private: 328 public: 329 CommandObjectRenderScriptRuntimeModuleProbe(CommandInterpreter &interpreter) 330 : CommandObjectParsed(interpreter, "renderscript module probe", 331 "Initiates a Probe of all loaded modules for kernels and other renderscript objects.", 332 "renderscript module probe", 333 eFlagRequiresTarget | eFlagRequiresProcess | eFlagProcessMustBeLaunched) 334 { 335 } 336 337 ~CommandObjectRenderScriptRuntimeModuleProbe() {} 338 339 bool 340 DoExecute(Args &command, CommandReturnObject &result) 341 { 342 const size_t argc = command.GetArgumentCount(); 343 if (argc == 0) 344 { 345 Target *target = m_exe_ctx.GetTargetPtr(); 346 RenderScriptRuntime *runtime = 347 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); 348 auto module_list = target->GetImages(); 349 bool new_rs_details = runtime->ProbeModules(module_list); 350 if (new_rs_details) 351 { 352 result.AppendMessage("New renderscript modules added to runtime model."); 353 } 354 result.SetStatus(eReturnStatusSuccessFinishResult); 355 return true; 356 } 357 358 result.AppendErrorWithFormat("'%s' takes no arguments", m_cmd_name.c_str()); 359 result.SetStatus(eReturnStatusFailed); 360 return false; 361 } 362 }; 363 364 class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed 365 { 366 private: 367 public: 368 CommandObjectRenderScriptRuntimeModuleDump(CommandInterpreter &interpreter) 369 : CommandObjectParsed(interpreter, "renderscript module dump", 370 "Dumps renderscript specific information for all modules.", "renderscript module dump", 371 eFlagRequiresProcess | eFlagProcessMustBeLaunched) 372 { 373 } 374 375 ~CommandObjectRenderScriptRuntimeModuleDump() {} 376 377 bool 378 DoExecute(Args &command, CommandReturnObject &result) 379 { 380 RenderScriptRuntime *runtime = 381 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); 382 runtime->DumpModules(result.GetOutputStream()); 383 result.SetStatus(eReturnStatusSuccessFinishResult); 384 return true; 385 } 386 }; 387 388 class CommandObjectRenderScriptRuntimeModule : public CommandObjectMultiword 389 { 390 private: 391 public: 392 CommandObjectRenderScriptRuntimeModule(CommandInterpreter &interpreter) 393 : CommandObjectMultiword(interpreter, "renderscript module", "Commands that deal with renderscript modules.", 394 NULL) 395 { 396 LoadSubCommand("probe", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleProbe(interpreter))); 397 LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleDump(interpreter))); 398 } 399 400 ~CommandObjectRenderScriptRuntimeModule() {} 401 }; 402 403 class CommandObjectRenderScriptRuntime : public CommandObjectMultiword 404 { 405 public: 406 CommandObjectRenderScriptRuntime(CommandInterpreter &interpreter) 407 : CommandObjectMultiword(interpreter, "renderscript", "A set of commands for operating on renderscript.", 408 "renderscript <subcommand> [<subcommand-options>]") 409 { 410 LoadSubCommand("module", CommandObjectSP(new CommandObjectRenderScriptRuntimeModule(interpreter))); 411 } 412 413 ~CommandObjectRenderScriptRuntime() {} 414 }; 415 416 void 417 RenderScriptRuntime::Initiate() 418 { 419 assert(!m_initiated); 420 Process* process = GetProcess(); 421 if (process) 422 { 423 CommandInterpreter &interpreter = process->GetTarget().GetDebugger().GetCommandInterpreter(); 424 m_initiated = interpreter.AddCommand("renderscript", CommandObjectSP( 425 new CommandObjectRenderScriptRuntime(interpreter)), true); 426 } 427 } 428 429 RenderScriptRuntime::RenderScriptRuntime(Process *process) 430 : lldb_private::CPPLanguageRuntime(process), m_initiated(false) 431 { 432 433 } 434