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