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