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/Host/StringConvert.h" 18 #include "lldb/Symbol/Symbol.h" 19 #include "lldb/Symbol/Type.h" 20 #include "lldb/Target/Process.h" 21 #include "lldb/Target/Target.h" 22 #include "lldb/Interpreter/Args.h" 23 #include "lldb/Interpreter/Options.h" 24 #include "lldb/Interpreter/CommandInterpreter.h" 25 #include "lldb/Interpreter/CommandReturnObject.h" 26 #include "lldb/Interpreter/CommandObjectMultiword.h" 27 #include "lldb/Breakpoint/StoppointCallbackContext.h" 28 #include "lldb/Target/RegisterContext.h" 29 #include "lldb/Expression/UserExpression.h" 30 #include "lldb/Symbol/VariableList.h" 31 32 using namespace lldb; 33 using namespace lldb_private; 34 using namespace lldb_renderscript; 35 36 namespace { 37 38 // The empirical_type adds a basic level of validation to arbitrary data 39 // allowing us to track if data has been discovered and stored or not. 40 // An empirical_type will be marked as valid only if it has been explicitly assigned to. 41 template <typename type_t> 42 class empirical_type 43 { 44 public: 45 // Ctor. Contents is invalid when constructed. 46 empirical_type() 47 : valid(false) 48 {} 49 50 // Return true and copy contents to out if valid, else return false. 51 bool get(type_t& out) const 52 { 53 if (valid) 54 out = data; 55 return valid; 56 } 57 58 // Return a pointer to the contents or nullptr if it was not valid. 59 const type_t* get() const 60 { 61 return valid ? &data : nullptr; 62 } 63 64 // Assign data explicitly. 65 void set(const type_t in) 66 { 67 data = in; 68 valid = true; 69 } 70 71 // Mark contents as invalid. 72 void invalidate() 73 { 74 valid = false; 75 } 76 77 // Returns true if this type contains valid data. 78 bool isValid() const 79 { 80 return valid; 81 } 82 83 // Assignment operator. 84 empirical_type<type_t>& operator = (const type_t in) 85 { 86 set(in); 87 return *this; 88 } 89 90 // Dereference operator returns contents. 91 // Warning: Will assert if not valid so use only when you know data is valid. 92 const type_t& operator * () const 93 { 94 assert(valid); 95 return data; 96 } 97 98 protected: 99 bool valid; 100 type_t data; 101 }; 102 103 } // namespace {} 104 105 // The ScriptDetails class collects data associated with a single script instance. 106 struct RenderScriptRuntime::ScriptDetails 107 { 108 ~ScriptDetails() {}; 109 110 enum ScriptType 111 { 112 eScript, 113 eScriptC 114 }; 115 116 // The derived type of the script. 117 empirical_type<ScriptType> type; 118 // The name of the original source file. 119 empirical_type<std::string> resName; 120 // Path to script .so file on the device. 121 empirical_type<std::string> scriptDyLib; 122 // Directory where kernel objects are cached on device. 123 empirical_type<std::string> cacheDir; 124 // Pointer to the context which owns this script. 125 empirical_type<lldb::addr_t> context; 126 // Pointer to the script object itself. 127 empirical_type<lldb::addr_t> script; 128 }; 129 130 // This AllocationDetails class collects data associated with a single 131 // allocation instance. 132 struct RenderScriptRuntime::AllocationDetails 133 { 134 // Taken from rsDefines.h 135 enum DataKind 136 { 137 RS_KIND_USER, 138 RS_KIND_PIXEL_L = 7, 139 RS_KIND_PIXEL_A, 140 RS_KIND_PIXEL_LA, 141 RS_KIND_PIXEL_RGB, 142 RS_KIND_PIXEL_RGBA, 143 RS_KIND_PIXEL_DEPTH, 144 RS_KIND_PIXEL_YUV, 145 RS_KIND_INVALID = 100 146 }; 147 148 // Taken from rsDefines.h 149 enum DataType 150 { 151 RS_TYPE_NONE = 0, 152 RS_TYPE_FLOAT_16, 153 RS_TYPE_FLOAT_32, 154 RS_TYPE_FLOAT_64, 155 RS_TYPE_SIGNED_8, 156 RS_TYPE_SIGNED_16, 157 RS_TYPE_SIGNED_32, 158 RS_TYPE_SIGNED_64, 159 RS_TYPE_UNSIGNED_8, 160 RS_TYPE_UNSIGNED_16, 161 RS_TYPE_UNSIGNED_32, 162 RS_TYPE_UNSIGNED_64, 163 RS_TYPE_BOOLEAN 164 }; 165 166 struct Dimension 167 { 168 uint32_t dim_1; 169 uint32_t dim_2; 170 uint32_t dim_3; 171 uint32_t cubeMap; 172 173 Dimension() 174 { 175 dim_1 = 0; 176 dim_2 = 0; 177 dim_3 = 0; 178 cubeMap = 0; 179 } 180 }; 181 182 // Monotonically increasing from 1 183 static unsigned int ID; 184 185 // Maps Allocation DataType enum and vector size to printable strings 186 // using mapping from RenderScript numerical types summary documentation 187 static const char* RsDataTypeToString[][4]; 188 189 // Maps Allocation DataKind enum to printable strings 190 static const char* RsDataKindToString[]; 191 192 // Maps allocation types to format sizes for printing. 193 static const unsigned int RSTypeToFormat[][3]; 194 195 // Give each allocation an ID as a way 196 // for commands to reference it. 197 const unsigned int id; 198 199 empirical_type<DataType> type; // Type of each data pointer stored by the allocation 200 empirical_type<DataKind> type_kind; // Defines pixel type if Allocation is created from an image 201 empirical_type<uint32_t> type_vec_size; // Vector size of each data point, e.g '4' for uchar4 202 empirical_type<Dimension> dimension; // Dimensions of the Allocation 203 empirical_type<lldb::addr_t> address; // Pointer to address of the RS Allocation 204 empirical_type<lldb::addr_t> data_ptr; // Pointer to the data held by the Allocation 205 empirical_type<lldb::addr_t> type_ptr; // Pointer to the RS Type of the Allocation 206 empirical_type<lldb::addr_t> element_ptr; // Pointer to the RS Element of the Type 207 empirical_type<lldb::addr_t> context; // Pointer to the RS Context of the Allocation 208 empirical_type<uint32_t> size; // Size of the allocation 209 empirical_type<uint32_t> stride; // Stride between rows of the allocation 210 211 // Give each allocation an id, so we can reference it in user commands. 212 AllocationDetails(): id(ID++) 213 { 214 } 215 216 }; 217 218 unsigned int RenderScriptRuntime::AllocationDetails::ID = 1; 219 220 const char* RenderScriptRuntime::AllocationDetails::RsDataKindToString[] = 221 { 222 "User", 223 "Undefined", "Undefined", "Undefined", // Enum jumps from 0 to 7 224 "Undefined", "Undefined", "Undefined", 225 "L Pixel", 226 "A Pixel", 227 "LA Pixel", 228 "RGB Pixel", 229 "RGBA Pixel", 230 "Pixel Depth", 231 "YUV Pixel" 232 }; 233 234 const char* RenderScriptRuntime::AllocationDetails::RsDataTypeToString[][4] = 235 { 236 {"None", "None", "None", "None"}, 237 {"half", "half2", "half3", "half4"}, 238 {"float", "float2", "float3", "float4"}, 239 {"double", "double2", "double3", "double4"}, 240 {"char", "char2", "char3", "char4"}, 241 {"short", "short2", "short3", "short4"}, 242 {"int", "int2", "int3", "int4"}, 243 {"long", "long2", "long3", "long4"}, 244 {"uchar", "uchar2", "uchar3", "uchar4"}, 245 {"ushort", "ushort2", "ushort3", "ushort4"}, 246 {"uint", "uint2", "uint3", "uint4"}, 247 {"ulong", "ulong2", "ulong3", "ulong4"}, 248 {"bool", "bool2", "bool3", "bool4"} 249 }; 250 251 // Used as an index into the RSTypeToFormat array elements 252 enum TypeToFormatIndex { 253 eFormatSingle = 0, 254 eFormatVector, 255 eElementSize 256 }; 257 258 // { format enum of single element, format enum of element vector, size of element} 259 const unsigned int RenderScriptRuntime::AllocationDetails::RSTypeToFormat[][3] = 260 { 261 {eFormatHex, eFormatHex, 1}, // RS_TYPE_NONE 262 {eFormatFloat, eFormatVectorOfFloat16, 2}, // RS_TYPE_FLOAT_16 263 {eFormatFloat, eFormatVectorOfFloat32, sizeof(float)}, // RS_TYPE_FLOAT_32 264 {eFormatFloat, eFormatVectorOfFloat64, sizeof(double)}, // RS_TYPE_FLOAT_64 265 {eFormatDecimal, eFormatVectorOfSInt8, sizeof(int8_t)}, // RS_TYPE_SIGNED_8 266 {eFormatDecimal, eFormatVectorOfSInt16, sizeof(int16_t)}, // RS_TYPE_SIGNED_16 267 {eFormatDecimal, eFormatVectorOfSInt32, sizeof(int32_t)}, // RS_TYPE_SIGNED_32 268 {eFormatDecimal, eFormatVectorOfSInt64, sizeof(int64_t)}, // RS_TYPE_SIGNED_64 269 {eFormatDecimal, eFormatVectorOfUInt8, sizeof(uint8_t)}, // RS_TYPE_UNSIGNED_8 270 {eFormatDecimal, eFormatVectorOfUInt16, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_16 271 {eFormatDecimal, eFormatVectorOfUInt32, sizeof(uint32_t)}, // RS_TYPE_UNSIGNED_32 272 {eFormatDecimal, eFormatVectorOfUInt64, sizeof(uint64_t)}, // RS_TYPE_UNSIGNED_64 273 {eFormatBoolean, eFormatBoolean, sizeof(bool)} // RS_TYPE_BOOL 274 }; 275 276 //------------------------------------------------------------------ 277 // Static Functions 278 //------------------------------------------------------------------ 279 LanguageRuntime * 280 RenderScriptRuntime::CreateInstance(Process *process, lldb::LanguageType language) 281 { 282 283 if (language == eLanguageTypeExtRenderScript) 284 return new RenderScriptRuntime(process); 285 else 286 return NULL; 287 } 288 289 // Callback with a module to search for matching symbols. 290 // We first check that the module contains RS kernels. 291 // Then look for a symbol which matches our kernel name. 292 // The breakpoint address is finally set using the address of this symbol. 293 Searcher::CallbackReturn 294 RSBreakpointResolver::SearchCallback(SearchFilter &filter, 295 SymbolContext &context, 296 Address*, 297 bool) 298 { 299 ModuleSP module = context.module_sp; 300 301 if (!module) 302 return Searcher::eCallbackReturnContinue; 303 304 // Is this a module containing renderscript kernels? 305 if (nullptr == module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData)) 306 return Searcher::eCallbackReturnContinue; 307 308 // Attempt to set a breakpoint on the kernel name symbol within the module library. 309 // If it's not found, it's likely debug info is unavailable - try to set a 310 // breakpoint on <name>.expand. 311 312 const Symbol* kernel_sym = module->FindFirstSymbolWithNameAndType(m_kernel_name, eSymbolTypeCode); 313 if (!kernel_sym) 314 { 315 std::string kernel_name_expanded(m_kernel_name.AsCString()); 316 kernel_name_expanded.append(".expand"); 317 kernel_sym = module->FindFirstSymbolWithNameAndType(ConstString(kernel_name_expanded.c_str()), eSymbolTypeCode); 318 } 319 320 if (kernel_sym) 321 { 322 Address bp_addr = kernel_sym->GetAddress(); 323 if (filter.AddressPasses(bp_addr)) 324 m_breakpoint->AddLocation(bp_addr); 325 } 326 327 return Searcher::eCallbackReturnContinue; 328 } 329 330 void 331 RenderScriptRuntime::Initialize() 332 { 333 PluginManager::RegisterPlugin(GetPluginNameStatic(), "RenderScript language support", CreateInstance, GetCommandObject); 334 } 335 336 void 337 RenderScriptRuntime::Terminate() 338 { 339 PluginManager::UnregisterPlugin(CreateInstance); 340 } 341 342 lldb_private::ConstString 343 RenderScriptRuntime::GetPluginNameStatic() 344 { 345 static ConstString g_name("renderscript"); 346 return g_name; 347 } 348 349 RenderScriptRuntime::ModuleKind 350 RenderScriptRuntime::GetModuleKind(const lldb::ModuleSP &module_sp) 351 { 352 if (module_sp) 353 { 354 // Is this a module containing renderscript kernels? 355 const Symbol *info_sym = module_sp->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData); 356 if (info_sym) 357 { 358 return eModuleKindKernelObj; 359 } 360 361 // Is this the main RS runtime library 362 const ConstString rs_lib("libRS.so"); 363 if (module_sp->GetFileSpec().GetFilename() == rs_lib) 364 { 365 return eModuleKindLibRS; 366 } 367 368 const ConstString rs_driverlib("libRSDriver.so"); 369 if (module_sp->GetFileSpec().GetFilename() == rs_driverlib) 370 { 371 return eModuleKindDriver; 372 } 373 374 const ConstString rs_cpureflib("libRSCpuRef.so"); 375 if (module_sp->GetFileSpec().GetFilename() == rs_cpureflib) 376 { 377 return eModuleKindImpl; 378 } 379 380 } 381 return eModuleKindIgnored; 382 } 383 384 bool 385 RenderScriptRuntime::IsRenderScriptModule(const lldb::ModuleSP &module_sp) 386 { 387 return GetModuleKind(module_sp) != eModuleKindIgnored; 388 } 389 390 391 void 392 RenderScriptRuntime::ModulesDidLoad(const ModuleList &module_list ) 393 { 394 Mutex::Locker locker (module_list.GetMutex ()); 395 396 size_t num_modules = module_list.GetSize(); 397 for (size_t i = 0; i < num_modules; i++) 398 { 399 auto mod = module_list.GetModuleAtIndex (i); 400 if (IsRenderScriptModule (mod)) 401 { 402 LoadModule(mod); 403 } 404 } 405 } 406 407 408 //------------------------------------------------------------------ 409 // PluginInterface protocol 410 //------------------------------------------------------------------ 411 lldb_private::ConstString 412 RenderScriptRuntime::GetPluginName() 413 { 414 return GetPluginNameStatic(); 415 } 416 417 uint32_t 418 RenderScriptRuntime::GetPluginVersion() 419 { 420 return 1; 421 } 422 423 bool 424 RenderScriptRuntime::IsVTableName(const char *name) 425 { 426 return false; 427 } 428 429 bool 430 RenderScriptRuntime::GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic, 431 TypeAndOrName &class_type_or_name, Address &address, 432 Value::ValueType &value_type) 433 { 434 return false; 435 } 436 437 TypeAndOrName 438 RenderScriptRuntime::FixUpDynamicType (const TypeAndOrName& type_and_or_name, 439 ValueObject& static_value) 440 { 441 return type_and_or_name; 442 } 443 444 bool 445 RenderScriptRuntime::CouldHaveDynamicValue(ValueObject &in_value) 446 { 447 return false; 448 } 449 450 lldb::BreakpointResolverSP 451 RenderScriptRuntime::CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp) 452 { 453 BreakpointResolverSP resolver_sp; 454 return resolver_sp; 455 } 456 457 458 const RenderScriptRuntime::HookDefn RenderScriptRuntime::s_runtimeHookDefns[] = 459 { 460 //rsdScript 461 { 462 "rsdScriptInit", //name 463 "_Z13rsdScriptInitPKN7android12renderscript7ContextEPNS0_7ScriptCEPKcS7_PKhjj", // symbol name 32 bit 464 "_Z13rsdScriptInitPKN7android12renderscript7ContextEPNS0_7ScriptCEPKcS7_PKhmj", // symbol name 64 bit 465 0, // version 466 RenderScriptRuntime::eModuleKindDriver, // type 467 &lldb_private::RenderScriptRuntime::CaptureScriptInit1 // handler 468 }, 469 { 470 "rsdScriptInvokeForEach", // name 471 "_Z22rsdScriptInvokeForEachPKN7android12renderscript7ContextEPNS0_6ScriptEjPKNS0_10AllocationEPS6_PKvjPK12RsScriptCall", // symbol name 32bit 472 "_Z22rsdScriptInvokeForEachPKN7android12renderscript7ContextEPNS0_6ScriptEjPKNS0_10AllocationEPS6_PKvmPK12RsScriptCall", // symbol name 64bit 473 0, // version 474 RenderScriptRuntime::eModuleKindDriver, // type 475 nullptr // handler 476 }, 477 { 478 "rsdScriptInvokeForEachMulti", // name 479 "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0_6ScriptEjPPKNS0_10AllocationEjPS6_PKvjPK12RsScriptCall", // symbol name 32bit 480 "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0_6ScriptEjPPKNS0_10AllocationEmPS6_PKvmPK12RsScriptCall", // symbol name 64bit 481 0, // version 482 RenderScriptRuntime::eModuleKindDriver, // type 483 nullptr // handler 484 }, 485 { 486 "rsdScriptInvokeFunction", // name 487 "_Z23rsdScriptInvokeFunctionPKN7android12renderscript7ContextEPNS0_6ScriptEjPKvj", // symbol name 32bit 488 "_Z23rsdScriptInvokeFunctionPKN7android12renderscript7ContextEPNS0_6ScriptEjPKvm", // symbol name 64bit 489 0, // version 490 RenderScriptRuntime::eModuleKindDriver, // type 491 nullptr // handler 492 }, 493 { 494 "rsdScriptSetGlobalVar", // name 495 "_Z21rsdScriptSetGlobalVarPKN7android12renderscript7ContextEPKNS0_6ScriptEjPvj", // symbol name 32bit 496 "_Z21rsdScriptSetGlobalVarPKN7android12renderscript7ContextEPKNS0_6ScriptEjPvm", // symbol name 64bit 497 0, // version 498 RenderScriptRuntime::eModuleKindDriver, // type 499 &lldb_private::RenderScriptRuntime::CaptureSetGlobalVar1 // handler 500 }, 501 502 //rsdAllocation 503 { 504 "rsdAllocationInit", // name 505 "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_10AllocationEb", // symbol name 32bit 506 "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_10AllocationEb", // symbol name 64bit 507 0, // version 508 RenderScriptRuntime::eModuleKindDriver, // type 509 &lldb_private::RenderScriptRuntime::CaptureAllocationInit1 // handler 510 }, 511 { 512 "rsdAllocationRead2D", //name 513 "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_10AllocationEjjj23RsAllocationCubemapFacejjPvjj", // symbol name 32bit 514 "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_10AllocationEjjj23RsAllocationCubemapFacejjPvmm", // symbol name 64bit 515 0, // version 516 RenderScriptRuntime::eModuleKindDriver, // type 517 nullptr // handler 518 }, 519 }; 520 const size_t RenderScriptRuntime::s_runtimeHookCount = sizeof(s_runtimeHookDefns)/sizeof(s_runtimeHookDefns[0]); 521 522 523 bool 524 RenderScriptRuntime::HookCallback(void *baton, StoppointCallbackContext *ctx, lldb::user_id_t break_id, lldb::user_id_t break_loc_id) 525 { 526 RuntimeHook* hook_info = (RuntimeHook*)baton; 527 ExecutionContext context(ctx->exe_ctx_ref); 528 529 RenderScriptRuntime *lang_rt = (RenderScriptRuntime *)context.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); 530 531 lang_rt->HookCallback(hook_info, context); 532 533 return false; 534 } 535 536 537 void 538 RenderScriptRuntime::HookCallback(RuntimeHook* hook_info, ExecutionContext& context) 539 { 540 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 541 542 if (log) 543 log->Printf ("RenderScriptRuntime::HookCallback - '%s' .", hook_info->defn->name); 544 545 if (hook_info->defn->grabber) 546 { 547 (this->*(hook_info->defn->grabber))(hook_info, context); 548 } 549 } 550 551 552 bool 553 RenderScriptRuntime::GetArgSimple(ExecutionContext &context, uint32_t arg, uint64_t *data) 554 { 555 if (!data) 556 return false; 557 558 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 559 Error error; 560 RegisterContext* reg_ctx = context.GetRegisterContext(); 561 Process* process = context.GetProcessPtr(); 562 bool success = false; // return value 563 564 if (!context.GetTargetPtr()) 565 { 566 if (log) 567 log->Printf("RenderScriptRuntime::GetArgSimple - Invalid target"); 568 569 return false; 570 } 571 572 switch (context.GetTargetPtr()->GetArchitecture().GetMachine()) 573 { 574 case llvm::Triple::ArchType::x86: 575 { 576 uint64_t sp = reg_ctx->GetSP(); 577 uint32_t offset = (1 + arg) * sizeof(uint32_t); 578 uint32_t result = 0; 579 process->ReadMemory(sp + offset, &result, sizeof(uint32_t), error); 580 if (error.Fail()) 581 { 582 if (log) 583 log->Printf ("RenderScriptRuntime:: GetArgSimple - error reading X86 stack: %s.", error.AsCString()); 584 } 585 else 586 { 587 *data = result; 588 success = true; 589 } 590 591 break; 592 } 593 case llvm::Triple::ArchType::arm: 594 { 595 // arm 32 bit 596 if (arg < 4) 597 { 598 const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg); 599 RegisterValue rVal; 600 reg_ctx->ReadRegister(rArg, rVal); 601 (*data) = rVal.GetAsUInt32(); 602 success = true; 603 } 604 else 605 { 606 uint64_t sp = reg_ctx->GetSP(); 607 { 608 uint32_t offset = (arg-4) * sizeof(uint32_t); 609 process->ReadMemory(sp + offset, &data, sizeof(uint32_t), error); 610 if (error.Fail()) 611 { 612 if (log) 613 log->Printf ("RenderScriptRuntime:: GetArgSimple - error reading ARM stack: %s.", error.AsCString()); 614 } 615 else 616 { 617 success = true; 618 } 619 } 620 } 621 622 break; 623 } 624 case llvm::Triple::ArchType::aarch64: 625 { 626 // arm 64 bit 627 // first 8 arguments are in the registers 628 if (arg < 8) 629 { 630 const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg); 631 RegisterValue rVal; 632 success = reg_ctx->ReadRegister(rArg, rVal); 633 if (success) 634 { 635 *data = rVal.GetAsUInt64(); 636 } 637 else 638 { 639 if (log) 640 log->Printf("RenderScriptRuntime::GetArgSimple() - AARCH64 - Error while reading the argument #%d", arg); 641 } 642 } 643 else 644 { 645 // @TODO: need to find the argument in the stack 646 if (log) 647 log->Printf("RenderScriptRuntime::GetArgSimple - AARCH64 - FOR #ARG >= 8 NOT IMPLEMENTED YET. Argument number: %d", arg); 648 } 649 break; 650 } 651 default: 652 { 653 // invalid architecture 654 if (log) 655 log->Printf("RenderScriptRuntime::GetArgSimple - Architecture not supported"); 656 657 } 658 } 659 660 661 return success; 662 } 663 664 void 665 RenderScriptRuntime::CaptureSetGlobalVar1(RuntimeHook* hook_info, ExecutionContext& context) 666 { 667 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 668 669 //Context, Script, int, data, length 670 671 uint64_t rs_context_u64 = 0U; 672 uint64_t rs_script_u64 = 0U; 673 uint64_t rs_id_u64 = 0U; 674 uint64_t rs_data_u64 = 0U; 675 uint64_t rs_length_u64 = 0U; 676 677 bool success = 678 GetArgSimple(context, 0, &rs_context_u64) && 679 GetArgSimple(context, 1, &rs_script_u64) && 680 GetArgSimple(context, 2, &rs_id_u64) && 681 GetArgSimple(context, 3, &rs_data_u64) && 682 GetArgSimple(context, 4, &rs_length_u64); 683 684 if (!success) 685 { 686 if (log) 687 log->Printf("RenderScriptRuntime::CaptureSetGlobalVar1 - Error while reading the function parameters"); 688 return; 689 } 690 691 if (log) 692 { 693 log->Printf ("RenderScriptRuntime::CaptureSetGlobalVar1 - 0x%" PRIx64 ",0x%" PRIx64 " slot %" PRIu64 " = 0x%" PRIx64 ":%" PRIu64 "bytes.", 694 rs_context_u64, rs_script_u64, rs_id_u64, rs_data_u64, rs_length_u64); 695 696 addr_t script_addr = (addr_t)rs_script_u64; 697 if (m_scriptMappings.find( script_addr ) != m_scriptMappings.end()) 698 { 699 auto rsm = m_scriptMappings[script_addr]; 700 if (rs_id_u64 < rsm->m_globals.size()) 701 { 702 auto rsg = rsm->m_globals[rs_id_u64]; 703 log->Printf ("RenderScriptRuntime::CaptureSetGlobalVar1 - Setting of '%s' within '%s' inferred", rsg.m_name.AsCString(), 704 rsm->m_module->GetFileSpec().GetFilename().AsCString()); 705 } 706 } 707 } 708 } 709 710 void 711 RenderScriptRuntime::CaptureAllocationInit1(RuntimeHook* hook_info, ExecutionContext& context) 712 { 713 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 714 715 //Context, Alloc, bool 716 717 uint64_t rs_context_u64 = 0U; 718 uint64_t rs_alloc_u64 = 0U; 719 uint64_t rs_forceZero_u64 = 0U; 720 721 bool success = 722 GetArgSimple(context, 0, &rs_context_u64) && 723 GetArgSimple(context, 1, &rs_alloc_u64) && 724 GetArgSimple(context, 2, &rs_forceZero_u64); 725 if (!success) // error case 726 { 727 if (log) 728 log->Printf("RenderScriptRuntime::CaptureAllocationInit1 - Error while reading the function parameters"); 729 return; // abort 730 } 731 732 if (log) 733 log->Printf ("RenderScriptRuntime::CaptureAllocationInit1 - 0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 " .", 734 rs_context_u64, rs_alloc_u64, rs_forceZero_u64); 735 736 AllocationDetails* alloc = LookUpAllocation(rs_alloc_u64, true); 737 if (alloc) 738 alloc->context = rs_context_u64; 739 } 740 741 void 742 RenderScriptRuntime::CaptureScriptInit1(RuntimeHook* hook_info, ExecutionContext& context) 743 { 744 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 745 746 //Context, Script, resname Str, cachedir Str 747 Error error; 748 Process* process = context.GetProcessPtr(); 749 750 uint64_t rs_context_u64 = 0U; 751 uint64_t rs_script_u64 = 0U; 752 uint64_t rs_resnameptr_u64 = 0U; 753 uint64_t rs_cachedirptr_u64 = 0U; 754 755 std::string resname; 756 std::string cachedir; 757 758 // read the function parameters 759 bool success = 760 GetArgSimple(context, 0, &rs_context_u64) && 761 GetArgSimple(context, 1, &rs_script_u64) && 762 GetArgSimple(context, 2, &rs_resnameptr_u64) && 763 GetArgSimple(context, 3, &rs_cachedirptr_u64); 764 765 if (!success) 766 { 767 if (log) 768 log->Printf("RenderScriptRuntime::CaptureScriptInit1 - Error while reading the function parameters"); 769 return; 770 } 771 772 process->ReadCStringFromMemory((lldb::addr_t)rs_resnameptr_u64, resname, error); 773 if (error.Fail()) 774 { 775 if (log) 776 log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - error reading resname: %s.", error.AsCString()); 777 778 } 779 780 process->ReadCStringFromMemory((lldb::addr_t)rs_cachedirptr_u64, cachedir, error); 781 if (error.Fail()) 782 { 783 if (log) 784 log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - error reading cachedir: %s.", error.AsCString()); 785 } 786 787 if (log) 788 log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - 0x%" PRIx64 ",0x%" PRIx64 " => '%s' at '%s' .", 789 rs_context_u64, rs_script_u64, resname.c_str(), cachedir.c_str()); 790 791 if (resname.size() > 0) 792 { 793 StreamString strm; 794 strm.Printf("librs.%s.so", resname.c_str()); 795 796 ScriptDetails* script = LookUpScript(rs_script_u64, true); 797 if (script) 798 { 799 script->type = ScriptDetails::eScriptC; 800 script->cacheDir = cachedir; 801 script->resName = resname; 802 script->scriptDyLib = strm.GetData(); 803 script->context = addr_t(rs_context_u64); 804 } 805 806 if (log) 807 log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - '%s' tagged with context 0x%" PRIx64 " and script 0x%" PRIx64 ".", 808 strm.GetData(), rs_context_u64, rs_script_u64); 809 } 810 else if (log) 811 { 812 log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - resource name invalid, Script not tagged"); 813 } 814 815 } 816 817 void 818 RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind) 819 { 820 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 821 822 if (!module) 823 { 824 return; 825 } 826 827 Target &target = GetProcess()->GetTarget(); 828 llvm::Triple::ArchType targetArchType = target.GetArchitecture().GetMachine(); 829 830 if (targetArchType != llvm::Triple::ArchType::x86 831 && targetArchType != llvm::Triple::ArchType::arm 832 && targetArchType != llvm::Triple::ArchType::aarch64) 833 { 834 if (log) 835 log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Unable to hook runtime. Only X86, ARM supported currently."); 836 837 return; 838 } 839 840 uint32_t archByteSize = target.GetArchitecture().GetAddressByteSize(); 841 842 for (size_t idx = 0; idx < s_runtimeHookCount; idx++) 843 { 844 const HookDefn* hook_defn = &s_runtimeHookDefns[idx]; 845 if (hook_defn->kind != kind) { 846 continue; 847 } 848 849 const char* symbol_name = (archByteSize == 4) ? hook_defn->symbol_name_m32 : hook_defn->symbol_name_m64; 850 851 const Symbol *sym = module->FindFirstSymbolWithNameAndType(ConstString(symbol_name), eSymbolTypeCode); 852 if (!sym){ 853 if (log){ 854 log->Printf("RenderScriptRuntime::LoadRuntimeHooks - ERROR: Symbol '%s' related to the function %s not found", symbol_name, hook_defn->name); 855 } 856 continue; 857 } 858 859 addr_t addr = sym->GetLoadAddress(&target); 860 if (addr == LLDB_INVALID_ADDRESS) 861 { 862 if (log) 863 log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Unable to resolve the address of hook function '%s' with symbol '%s'.", 864 hook_defn->name, symbol_name); 865 continue; 866 } 867 else 868 { 869 if (log) 870 log->Printf("RenderScriptRuntime::LoadRuntimeHooks - Function %s, address resolved at 0x%" PRIx64, hook_defn->name, addr); 871 } 872 873 RuntimeHookSP hook(new RuntimeHook()); 874 hook->address = addr; 875 hook->defn = hook_defn; 876 hook->bp_sp = target.CreateBreakpoint(addr, true, false); 877 hook->bp_sp->SetCallback(HookCallback, hook.get(), true); 878 m_runtimeHooks[addr] = hook; 879 if (log) 880 { 881 log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Successfully hooked '%s' in '%s' version %" PRIu64 " at 0x%" PRIx64 ".", 882 hook_defn->name, module->GetFileSpec().GetFilename().AsCString(), (uint64_t)hook_defn->version, (uint64_t)addr); 883 } 884 } 885 } 886 887 void 888 RenderScriptRuntime::FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp) 889 { 890 if (!rsmodule_sp) 891 return; 892 893 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 894 895 const ModuleSP module = rsmodule_sp->m_module; 896 const FileSpec& file = module->GetPlatformFileSpec(); 897 898 // Iterate over all of the scripts that we currently know of. 899 // Note: We cant push or pop to m_scripts here or it may invalidate rs_script. 900 for (const auto & rs_script : m_scripts) 901 { 902 // Extract the expected .so file path for this script. 903 std::string dylib; 904 if (!rs_script->scriptDyLib.get(dylib)) 905 continue; 906 907 // Only proceed if the module that has loaded corresponds to this script. 908 if (file.GetFilename() != ConstString(dylib.c_str())) 909 continue; 910 911 // Obtain the script address which we use as a key. 912 lldb::addr_t script; 913 if (!rs_script->script.get(script)) 914 continue; 915 916 // If we have a script mapping for the current script. 917 if (m_scriptMappings.find(script) != m_scriptMappings.end()) 918 { 919 // if the module we have stored is different to the one we just received. 920 if (m_scriptMappings[script] != rsmodule_sp) 921 { 922 if (log) 923 log->Printf ("RenderScriptRuntime::FixupScriptDetails - Error: script %" PRIx64 " wants reassigned to new rsmodule '%s'.", 924 (uint64_t)script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString()); 925 } 926 } 927 // We don't have a script mapping for the current script. 928 else 929 { 930 // Obtain the script resource name. 931 std::string resName; 932 if (rs_script->resName.get(resName)) 933 // Set the modules resource name. 934 rsmodule_sp->m_resname = resName; 935 // Add Script/Module pair to map. 936 m_scriptMappings[script] = rsmodule_sp; 937 if (log) 938 log->Printf ("RenderScriptRuntime::FixupScriptDetails - script %" PRIx64 " associated with rsmodule '%s'.", 939 (uint64_t)script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString()); 940 } 941 } 942 } 943 944 // Uses the Target API to evaluate the expression passed as a parameter to the function 945 // The result of that expression is returned an unsigned 64 bit int, via the result* paramter. 946 // Function returns true on success, and false on failure 947 bool 948 RenderScriptRuntime::EvalRSExpression(const char* expression, StackFrame* frame_ptr, uint64_t* result) 949 { 950 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 951 if (log) 952 log->Printf("RenderScriptRuntime::EvalRSExpression(%s)", expression); 953 954 ValueObjectSP expr_result; 955 // Perform the actual expression evaluation 956 GetProcess()->GetTarget().EvaluateExpression(expression, frame_ptr, expr_result); 957 958 if (!expr_result) 959 { 960 if (log) 961 log->Printf("RenderScriptRuntime::EvalRSExpression - Error: Couldn't evaluate expression"); 962 return false; 963 } 964 965 // The result of the expression is invalid 966 if (!expr_result->GetError().Success()) 967 { 968 Error err = expr_result->GetError(); 969 if (err.GetError() == UserExpression::kNoResult) // Expression returned void, so this is actually a success 970 { 971 if (log) 972 log->Printf("RenderScriptRuntime::EvalRSExpression - Expression returned void"); 973 974 result = nullptr; 975 return true; 976 } 977 978 if (log) 979 log->Printf("RenderScriptRuntime::EvalRSExpression - Error evaluating expression result: %s", err.AsCString()); 980 return false; 981 } 982 983 bool success = false; 984 *result = expr_result->GetValueAsUnsigned(0, &success); // We only read the result as an unsigned int. 985 986 if (!success) 987 { 988 if (log) 989 log->Printf("RenderScriptRuntime::EvalRSExpression - Error: Couldn't convert expression result to unsigned int"); 990 return false; 991 } 992 993 return true; 994 } 995 996 // Used to index expression format strings 997 enum ExpressionStrings 998 { 999 eExprGetOffsetPtr = 0, 1000 eExprAllocGetType, 1001 eExprTypeDimX, 1002 eExprTypeDimY, 1003 eExprTypeDimZ, 1004 eExprTypeElemPtr, 1005 eExprElementType, 1006 eExprElementKind, 1007 eExprElementVec 1008 }; 1009 1010 // Format strings containing the expressions we may need to evaluate. 1011 const char runtimeExpressions[][256] = 1012 { 1013 // Mangled GetOffsetPointer(Allocation*, xoff, yoff, zoff, lod, cubemap) 1014 "(int*)_Z12GetOffsetPtrPKN7android12renderscript10AllocationEjjjj23RsAllocationCubemapFace(0x%lx, %u, %u, %u, 0, 0)", 1015 1016 // Type* rsaAllocationGetType(Context*, Allocation*) 1017 "(void*)rsaAllocationGetType(0x%lx, 0x%lx)", 1018 1019 // rsaTypeGetNativeData(Context*, Type*, void* typeData, size) 1020 // Pack the data in the following way mHal.state.dimX; mHal.state.dimY; mHal.state.dimZ; 1021 // mHal.state.lodCount; mHal.state.faces; mElement; into typeData 1022 // Need to specify 32 or 64 bit for uint_t since this differs between devices 1023 "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[0]", // X dim 1024 "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[1]", // Y dim 1025 "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[2]", // Z dim 1026 "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[5]", // Element ptr 1027 1028 // rsaElementGetNativeData(Context*, Element*, uint32_t* elemData,size) 1029 // Pack mType; mKind; mNormalized; mVectorSize; NumSubElements into elemData 1030 "uint32_t data[6]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[0]", // Type 1031 "uint32_t data[6]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[1]", // Kind 1032 "uint32_t data[6]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[3]" // Vector Size 1033 }; 1034 1035 // JITs the RS runtime for the internal data pointer of an allocation. 1036 // Is passed x,y,z coordinates for the pointer to a specific element. 1037 // Then sets the data_ptr member in Allocation with the result. 1038 // Returns true on success, false otherwise 1039 bool 1040 RenderScriptRuntime::JITDataPointer(AllocationDetails* allocation, StackFrame* frame_ptr, 1041 unsigned int x, unsigned int y, unsigned int z) 1042 { 1043 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 1044 1045 if (!allocation->address.isValid()) 1046 { 1047 if (log) 1048 log->Printf("RenderScriptRuntime::JITDataPointer - Failed to find allocation details"); 1049 return false; 1050 } 1051 1052 const char* expr_cstr = runtimeExpressions[eExprGetOffsetPtr]; 1053 const int max_expr_size = 512; // Max expression size 1054 char buffer[max_expr_size]; 1055 1056 int chars_written = snprintf(buffer, max_expr_size, expr_cstr, *allocation->address.get(), x, y, z); 1057 if (chars_written < 0) 1058 { 1059 if (log) 1060 log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()"); 1061 return false; 1062 } 1063 else if (chars_written >= max_expr_size) 1064 { 1065 if (log) 1066 log->Printf("RenderScriptRuntime::JITDataPointer - Expression too long"); 1067 return false; 1068 } 1069 1070 uint64_t result = 0; 1071 if (!EvalRSExpression(buffer, frame_ptr, &result)) 1072 return false; 1073 1074 addr_t mem_ptr = static_cast<lldb::addr_t>(result); 1075 allocation->data_ptr = mem_ptr; 1076 1077 return true; 1078 } 1079 1080 // JITs the RS runtime for the internal pointer to the RS Type of an allocation 1081 // Then sets the type_ptr member in Allocation with the result. 1082 // Returns true on success, false otherwise 1083 bool 1084 RenderScriptRuntime::JITTypePointer(AllocationDetails* allocation, StackFrame* frame_ptr) 1085 { 1086 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 1087 1088 if (!allocation->address.isValid() || !allocation->context.isValid()) 1089 { 1090 if (log) 1091 log->Printf("RenderScriptRuntime::JITTypePointer - Failed to find allocation details"); 1092 return false; 1093 } 1094 1095 const char* expr_cstr = runtimeExpressions[eExprAllocGetType]; 1096 const int max_expr_size = 512; // Max expression size 1097 char buffer[max_expr_size]; 1098 1099 int chars_written = snprintf(buffer, max_expr_size, expr_cstr, *allocation->context.get(), *allocation->address.get()); 1100 if (chars_written < 0) 1101 { 1102 if (log) 1103 log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()"); 1104 return false; 1105 } 1106 else if (chars_written >= max_expr_size) 1107 { 1108 if (log) 1109 log->Printf("RenderScriptRuntime::JITTypePointer - Expression too long"); 1110 return false; 1111 } 1112 1113 uint64_t result = 0; 1114 if (!EvalRSExpression(buffer, frame_ptr, &result)) 1115 return false; 1116 1117 addr_t type_ptr = static_cast<lldb::addr_t>(result); 1118 allocation->type_ptr = type_ptr; 1119 1120 return true; 1121 } 1122 1123 // JITs the RS runtime for information about the dimensions and type of an allocation 1124 // Then sets dimension and element_ptr members in Allocation with the result. 1125 // Returns true on success, false otherwise 1126 bool 1127 RenderScriptRuntime::JITTypePacked(AllocationDetails* allocation, StackFrame* frame_ptr) 1128 { 1129 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 1130 1131 if (!allocation->type_ptr.isValid() || !allocation->context.isValid()) 1132 { 1133 if (log) 1134 log->Printf("RenderScriptRuntime::JITTypePacked - Failed to find allocation details"); 1135 return false; 1136 } 1137 1138 // Expression is different depending on if device is 32 or 64 bit 1139 uint32_t archByteSize = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize(); 1140 const unsigned int bits = archByteSize == 4 ? 32 : 64; 1141 1142 // We want 4 elements from packed data 1143 const unsigned int num_exprs = 4; 1144 assert(num_exprs == (eExprTypeElemPtr - eExprTypeDimX + 1) && "Invalid number of expressions"); 1145 1146 const int max_expr_size = 512; // Max expression size 1147 char buffer[num_exprs][max_expr_size]; 1148 uint64_t results[num_exprs]; 1149 1150 for (unsigned int i = 0; i < num_exprs; ++i) 1151 { 1152 int chars_written = snprintf(buffer[i], max_expr_size, runtimeExpressions[eExprTypeDimX + i], bits, 1153 *allocation->context.get(), *allocation->type_ptr.get()); 1154 if (chars_written < 0) 1155 { 1156 if (log) 1157 log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()"); 1158 return false; 1159 } 1160 else if (chars_written >= max_expr_size) 1161 { 1162 if (log) 1163 log->Printf("RenderScriptRuntime::JITTypePacked - Expression too long"); 1164 return false; 1165 } 1166 1167 // Perform expression evaluation 1168 if (!EvalRSExpression(buffer[i], frame_ptr, &results[i])) 1169 return false; 1170 } 1171 1172 // Assign results to allocation members 1173 AllocationDetails::Dimension dims; 1174 dims.dim_1 = static_cast<uint32_t>(results[0]); 1175 dims.dim_2 = static_cast<uint32_t>(results[1]); 1176 dims.dim_3 = static_cast<uint32_t>(results[2]); 1177 allocation->dimension = dims; 1178 1179 addr_t elem_ptr = static_cast<lldb::addr_t>(results[3]); 1180 allocation->element_ptr = elem_ptr; 1181 1182 if (log) 1183 log->Printf("RenderScriptRuntime::JITTypePacked - dims (%u, %u, %u) Element*: 0x%" PRIx64, 1184 dims.dim_1, dims.dim_2, dims.dim_3, elem_ptr); 1185 1186 return true; 1187 } 1188 1189 // JITs the RS runtime for information about the Element of an allocation 1190 // Then sets type, type_vec_size, and type_kind members in Allocation with the result. 1191 // Returns true on success, false otherwise 1192 bool 1193 RenderScriptRuntime::JITElementPacked(AllocationDetails* allocation, StackFrame* frame_ptr) 1194 { 1195 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 1196 1197 if (!allocation->element_ptr.isValid() || !allocation->context.isValid()) 1198 { 1199 if (log) 1200 log->Printf("RenderScriptRuntime::JITElementPacked - Failed to find allocation details"); 1201 return false; 1202 } 1203 1204 // We want 3 elements from packed data 1205 const unsigned int num_exprs = 3; 1206 assert(num_exprs == (eExprElementVec - eExprElementType + 1) && "Invalid number of expressions"); 1207 1208 const int max_expr_size = 512; // Max expression size 1209 char buffer[num_exprs][max_expr_size]; 1210 uint64_t results[num_exprs]; 1211 1212 for (unsigned int i = 0; i < num_exprs; i++) 1213 { 1214 int chars_written = snprintf(buffer[i], max_expr_size, runtimeExpressions[eExprElementType + i], *allocation->context.get(), *allocation->element_ptr.get()); 1215 if (chars_written < 0) 1216 { 1217 if (log) 1218 log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()"); 1219 return false; 1220 } 1221 else if (chars_written >= max_expr_size) 1222 { 1223 if (log) 1224 log->Printf("RenderScriptRuntime::JITElementPacked - Expression too long"); 1225 return false; 1226 } 1227 1228 // Perform expression evaluation 1229 if (!EvalRSExpression(buffer[i], frame_ptr, &results[i])) 1230 return false; 1231 } 1232 1233 // Assign results to allocation members 1234 allocation->type = static_cast<RenderScriptRuntime::AllocationDetails::DataType>(results[0]); 1235 allocation->type_kind = static_cast<RenderScriptRuntime::AllocationDetails::DataKind>(results[1]); 1236 allocation->type_vec_size = static_cast<uint32_t>(results[2]); 1237 1238 if (log) 1239 log->Printf("RenderScriptRuntime::JITElementPacked - data type %u, pixel type %u, vector size %u", 1240 *allocation->type.get(), *allocation->type_kind.get(), *allocation->type_vec_size.get()); 1241 1242 return true; 1243 } 1244 1245 // JITs the RS runtime for the address of the last element in the allocation. 1246 // The `elem_size` paramter represents the size of a single element, including padding. 1247 // Which is needed as an offset from the last element pointer. 1248 // Using this offset minus the starting address we can calculate the size of the allocation. 1249 // Returns true on success, false otherwise 1250 bool 1251 RenderScriptRuntime::JITAllocationSize(AllocationDetails* allocation, StackFrame* frame_ptr, 1252 const uint32_t elem_size) 1253 { 1254 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 1255 1256 if (!allocation->address.isValid() || !allocation->dimension.isValid() 1257 || !allocation->data_ptr.isValid()) 1258 { 1259 if (log) 1260 log->Printf("RenderScriptRuntime::JITAllocationSize - Failed to find allocation details"); 1261 return false; 1262 } 1263 1264 const char* expr_cstr = runtimeExpressions[eExprGetOffsetPtr]; 1265 const int max_expr_size = 512; // Max expression size 1266 char buffer[max_expr_size]; 1267 1268 // Find dimensions 1269 unsigned int dim_x = allocation->dimension.get()->dim_1; 1270 unsigned int dim_y = allocation->dimension.get()->dim_2; 1271 unsigned int dim_z = allocation->dimension.get()->dim_3; 1272 1273 // Calculate last element 1274 dim_x = dim_x == 0 ? 0 : dim_x - 1; 1275 dim_y = dim_y == 0 ? 0 : dim_y - 1; 1276 dim_z = dim_z == 0 ? 0 : dim_z - 1; 1277 1278 int chars_written = snprintf(buffer, max_expr_size, expr_cstr, *allocation->address.get(), 1279 dim_x, dim_y, dim_z); 1280 if (chars_written < 0) 1281 { 1282 if (log) 1283 log->Printf("RenderScriptRuntime::JITAllocationSize - Encoding error in snprintf()"); 1284 return false; 1285 } 1286 else if (chars_written >= max_expr_size) 1287 { 1288 if (log) 1289 log->Printf("RenderScriptRuntime::JITAllocationSize - Expression too long"); 1290 return false; 1291 } 1292 1293 uint64_t result = 0; 1294 if (!EvalRSExpression(buffer, frame_ptr, &result)) 1295 return false; 1296 1297 addr_t mem_ptr = static_cast<lldb::addr_t>(result); 1298 // Find pointer to last element and add on size of an element 1299 allocation->size = static_cast<uint32_t>(mem_ptr - *allocation->data_ptr.get()) + elem_size; 1300 1301 return true; 1302 } 1303 1304 // JITs the RS runtime for information about the stride between rows in the allocation. 1305 // This is done to detect padding, since allocated memory is 16-byte aligned. 1306 // Returns true on success, false otherwise 1307 bool 1308 RenderScriptRuntime::JITAllocationStride(AllocationDetails* allocation, StackFrame* frame_ptr) 1309 { 1310 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 1311 1312 if (!allocation->address.isValid() || !allocation->data_ptr.isValid()) 1313 { 1314 if (log) 1315 log->Printf("RenderScriptRuntime::JITAllocationStride - Failed to find allocation details"); 1316 return false; 1317 } 1318 1319 const char* expr_cstr = runtimeExpressions[eExprGetOffsetPtr]; 1320 const int max_expr_size = 512; // Max expression size 1321 char buffer[max_expr_size]; 1322 1323 int chars_written = snprintf(buffer, max_expr_size, expr_cstr, *allocation->address.get(), 1324 0, 1, 0); 1325 if (chars_written < 0) 1326 { 1327 if (log) 1328 log->Printf("RenderScriptRuntime::JITAllocationStride - Encoding error in snprintf()"); 1329 return false; 1330 } 1331 else if (chars_written >= max_expr_size) 1332 { 1333 if (log) 1334 log->Printf("RenderScriptRuntime::JITAllocationStride - Expression too long"); 1335 return false; 1336 } 1337 1338 uint64_t result = 0; 1339 if (!EvalRSExpression(buffer, frame_ptr, &result)) 1340 return false; 1341 1342 addr_t mem_ptr = static_cast<lldb::addr_t>(result); 1343 allocation->stride = static_cast<uint32_t>(mem_ptr - *allocation->data_ptr.get()); 1344 1345 return true; 1346 } 1347 1348 // JIT all the current runtime info regarding an allocation 1349 bool 1350 RenderScriptRuntime::RefreshAllocation(AllocationDetails* allocation, StackFrame* frame_ptr) 1351 { 1352 // GetOffsetPointer() 1353 if (!JITDataPointer(allocation, frame_ptr)) 1354 return false; 1355 1356 // rsaAllocationGetType() 1357 if (!JITTypePointer(allocation, frame_ptr)) 1358 return false; 1359 1360 // rsaTypeGetNativeData() 1361 if (!JITTypePacked(allocation, frame_ptr)) 1362 return false; 1363 1364 // rsaElementGetNativeData() 1365 if (!JITElementPacked(allocation, frame_ptr)) 1366 return false; 1367 1368 return true; 1369 } 1370 1371 bool 1372 RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp) 1373 { 1374 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 1375 1376 if (module_sp) 1377 { 1378 for (const auto &rs_module : m_rsmodules) 1379 { 1380 if (rs_module->m_module == module_sp) 1381 { 1382 // Check if the user has enabled automatically breaking on 1383 // all RS kernels. 1384 if (m_breakAllKernels) 1385 BreakOnModuleKernels(rs_module); 1386 1387 return false; 1388 } 1389 } 1390 bool module_loaded = false; 1391 switch (GetModuleKind(module_sp)) 1392 { 1393 case eModuleKindKernelObj: 1394 { 1395 RSModuleDescriptorSP module_desc; 1396 module_desc.reset(new RSModuleDescriptor(module_sp)); 1397 if (module_desc->ParseRSInfo()) 1398 { 1399 m_rsmodules.push_back(module_desc); 1400 module_loaded = true; 1401 } 1402 if (module_loaded) 1403 { 1404 FixupScriptDetails(module_desc); 1405 } 1406 break; 1407 } 1408 case eModuleKindDriver: 1409 { 1410 if (!m_libRSDriver) 1411 { 1412 m_libRSDriver = module_sp; 1413 LoadRuntimeHooks(m_libRSDriver, RenderScriptRuntime::eModuleKindDriver); 1414 } 1415 break; 1416 } 1417 case eModuleKindImpl: 1418 { 1419 m_libRSCpuRef = module_sp; 1420 break; 1421 } 1422 case eModuleKindLibRS: 1423 { 1424 if (!m_libRS) 1425 { 1426 m_libRS = module_sp; 1427 static ConstString gDbgPresentStr("gDebuggerPresent"); 1428 const Symbol* debug_present = m_libRS->FindFirstSymbolWithNameAndType(gDbgPresentStr, eSymbolTypeData); 1429 if (debug_present) 1430 { 1431 Error error; 1432 uint32_t flag = 0x00000001U; 1433 Target &target = GetProcess()->GetTarget(); 1434 addr_t addr = debug_present->GetLoadAddress(&target); 1435 GetProcess()->WriteMemory(addr, &flag, sizeof(flag), error); 1436 if(error.Success()) 1437 { 1438 if (log) 1439 log->Printf ("RenderScriptRuntime::LoadModule - Debugger present flag set on debugee"); 1440 1441 m_debuggerPresentFlagged = true; 1442 } 1443 else if (log) 1444 { 1445 log->Printf ("RenderScriptRuntime::LoadModule - Error writing debugger present flags '%s' ", error.AsCString()); 1446 } 1447 } 1448 else if (log) 1449 { 1450 log->Printf ("RenderScriptRuntime::LoadModule - Error writing debugger present flags - symbol not found"); 1451 } 1452 } 1453 break; 1454 } 1455 default: 1456 break; 1457 } 1458 if (module_loaded) 1459 Update(); 1460 return module_loaded; 1461 } 1462 return false; 1463 } 1464 1465 void 1466 RenderScriptRuntime::Update() 1467 { 1468 if (m_rsmodules.size() > 0) 1469 { 1470 if (!m_initiated) 1471 { 1472 Initiate(); 1473 } 1474 } 1475 } 1476 1477 1478 // The maximum line length of an .rs.info packet 1479 #define MAXLINE 500 1480 1481 // The .rs.info symbol in renderscript modules contains a string which needs to be parsed. 1482 // The string is basic and is parsed on a line by line basis. 1483 bool 1484 RSModuleDescriptor::ParseRSInfo() 1485 { 1486 const Symbol *info_sym = m_module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData); 1487 if (info_sym) 1488 { 1489 const addr_t addr = info_sym->GetAddressRef().GetFileAddress(); 1490 const addr_t size = info_sym->GetByteSize(); 1491 const FileSpec fs = m_module->GetFileSpec(); 1492 1493 DataBufferSP buffer = fs.ReadFileContents(addr, size); 1494 1495 if (!buffer) 1496 return false; 1497 1498 std::string info((const char *)buffer->GetBytes()); 1499 1500 std::vector<std::string> info_lines; 1501 size_t lpos = info.find('\n'); 1502 while (lpos != std::string::npos) 1503 { 1504 info_lines.push_back(info.substr(0, lpos)); 1505 info = info.substr(lpos + 1); 1506 lpos = info.find('\n'); 1507 } 1508 size_t offset = 0; 1509 while (offset < info_lines.size()) 1510 { 1511 std::string line = info_lines[offset]; 1512 // Parse directives 1513 uint32_t numDefns = 0; 1514 if (sscanf(line.c_str(), "exportVarCount: %u", &numDefns) == 1) 1515 { 1516 while (numDefns--) 1517 m_globals.push_back(RSGlobalDescriptor(this, info_lines[++offset].c_str())); 1518 } 1519 else if (sscanf(line.c_str(), "exportFuncCount: %u", &numDefns) == 1) 1520 { 1521 } 1522 else if (sscanf(line.c_str(), "exportForEachCount: %u", &numDefns) == 1) 1523 { 1524 char name[MAXLINE]; 1525 while (numDefns--) 1526 { 1527 uint32_t slot = 0; 1528 name[0] = '\0'; 1529 if (sscanf(info_lines[++offset].c_str(), "%u - %s", &slot, &name[0]) == 2) 1530 { 1531 m_kernels.push_back(RSKernelDescriptor(this, name, slot)); 1532 } 1533 } 1534 } 1535 else if (sscanf(line.c_str(), "pragmaCount: %u", &numDefns) == 1) 1536 { 1537 char name[MAXLINE]; 1538 char value[MAXLINE]; 1539 while (numDefns--) 1540 { 1541 name[0] = '\0'; 1542 value[0] = '\0'; 1543 if (sscanf(info_lines[++offset].c_str(), "%s - %s", &name[0], &value[0]) != 0 1544 && (name[0] != '\0')) 1545 { 1546 m_pragmas[std::string(name)] = value; 1547 } 1548 } 1549 } 1550 else if (sscanf(line.c_str(), "objectSlotCount: %u", &numDefns) == 1) 1551 { 1552 } 1553 1554 offset++; 1555 } 1556 return m_kernels.size() > 0; 1557 } 1558 return false; 1559 } 1560 1561 bool 1562 RenderScriptRuntime::ProbeModules(const ModuleList module_list) 1563 { 1564 bool rs_found = false; 1565 size_t num_modules = module_list.GetSize(); 1566 for (size_t i = 0; i < num_modules; i++) 1567 { 1568 auto module = module_list.GetModuleAtIndex(i); 1569 rs_found |= LoadModule(module); 1570 } 1571 return rs_found; 1572 } 1573 1574 void 1575 RenderScriptRuntime::Status(Stream &strm) const 1576 { 1577 if (m_libRS) 1578 { 1579 strm.Printf("Runtime Library discovered."); 1580 strm.EOL(); 1581 } 1582 if (m_libRSDriver) 1583 { 1584 strm.Printf("Runtime Driver discovered."); 1585 strm.EOL(); 1586 } 1587 if (m_libRSCpuRef) 1588 { 1589 strm.Printf("CPU Reference Implementation discovered."); 1590 strm.EOL(); 1591 } 1592 1593 if (m_runtimeHooks.size()) 1594 { 1595 strm.Printf("Runtime functions hooked:"); 1596 strm.EOL(); 1597 for (auto b : m_runtimeHooks) 1598 { 1599 strm.Indent(b.second->defn->name); 1600 strm.EOL(); 1601 } 1602 strm.EOL(); 1603 } 1604 else 1605 { 1606 strm.Printf("Runtime is not hooked."); 1607 strm.EOL(); 1608 } 1609 } 1610 1611 void 1612 RenderScriptRuntime::DumpContexts(Stream &strm) const 1613 { 1614 strm.Printf("Inferred RenderScript Contexts:"); 1615 strm.EOL(); 1616 strm.IndentMore(); 1617 1618 std::map<addr_t, uint64_t> contextReferences; 1619 1620 // Iterate over all of the currently discovered scripts. 1621 // Note: We cant push or pop from m_scripts inside this loop or it may invalidate script. 1622 for (const auto & script : m_scripts) 1623 { 1624 if (!script->context.isValid()) 1625 continue; 1626 lldb::addr_t context = *script->context; 1627 1628 if (contextReferences.find(context) != contextReferences.end()) 1629 { 1630 contextReferences[context]++; 1631 } 1632 else 1633 { 1634 contextReferences[context] = 1; 1635 } 1636 } 1637 1638 for (const auto& cRef : contextReferences) 1639 { 1640 strm.Printf("Context 0x%" PRIx64 ": %" PRIu64 " script instances", cRef.first, cRef.second); 1641 strm.EOL(); 1642 } 1643 strm.IndentLess(); 1644 } 1645 1646 void 1647 RenderScriptRuntime::DumpKernels(Stream &strm) const 1648 { 1649 strm.Printf("RenderScript Kernels:"); 1650 strm.EOL(); 1651 strm.IndentMore(); 1652 for (const auto &module : m_rsmodules) 1653 { 1654 strm.Printf("Resource '%s':",module->m_resname.c_str()); 1655 strm.EOL(); 1656 for (const auto &kernel : module->m_kernels) 1657 { 1658 strm.Indent(kernel.m_name.AsCString()); 1659 strm.EOL(); 1660 } 1661 } 1662 strm.IndentLess(); 1663 } 1664 1665 RenderScriptRuntime::AllocationDetails* 1666 RenderScriptRuntime::FindAllocByID(Stream &strm, const uint32_t alloc_id) 1667 { 1668 AllocationDetails* alloc = nullptr; 1669 1670 // See if we can find allocation using id as an index; 1671 if (alloc_id <= m_allocations.size() && alloc_id != 0 1672 && m_allocations[alloc_id-1]->id == alloc_id) 1673 { 1674 alloc = m_allocations[alloc_id-1].get(); 1675 return alloc; 1676 } 1677 1678 // Fallback to searching 1679 for (const auto & a : m_allocations) 1680 { 1681 if (a->id == alloc_id) 1682 { 1683 alloc = a.get(); 1684 break; 1685 } 1686 } 1687 1688 if (alloc == nullptr) 1689 { 1690 strm.Printf("Error: Couldn't find allocation with id matching %u", alloc_id); 1691 strm.EOL(); 1692 } 1693 1694 return alloc; 1695 } 1696 1697 // Prints the contents of an allocation to the output stream, which may be a file 1698 bool 1699 RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame* frame_ptr, const uint32_t id) 1700 { 1701 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 1702 1703 // Check we can find the desired allocation 1704 AllocationDetails* alloc = FindAllocByID(strm, id); 1705 if (!alloc) 1706 return false; // FindAllocByID() will print error message for us here 1707 1708 if (log) 1709 log->Printf("RenderScriptRuntime::DumpAllocation - Found allocation 0x%" PRIx64, *alloc->address.get()); 1710 1711 // Check we have information about the allocation, if not calculate it 1712 if (!alloc->data_ptr.isValid() || !alloc->type.isValid() || 1713 !alloc->type_vec_size.isValid() || !alloc->dimension.isValid()) 1714 { 1715 if (log) 1716 log->Printf("RenderScriptRuntime::DumpAllocation - Allocation details not calculated yet, jitting info"); 1717 1718 // JIT all the allocation information 1719 if (!RefreshAllocation(alloc, frame_ptr)) 1720 { 1721 strm.Printf("Error: Couldn't JIT allocation details"); 1722 strm.EOL(); 1723 return false; 1724 } 1725 } 1726 1727 // Establish format and size of each data element 1728 const unsigned int vec_size = *alloc->type_vec_size.get(); 1729 const AllocationDetails::DataType type = *alloc->type.get(); 1730 1731 assert(type >= AllocationDetails::RS_TYPE_NONE && type <= AllocationDetails::RS_TYPE_BOOLEAN 1732 && "Invalid allocation type"); 1733 1734 lldb::Format format = vec_size == 1 ? static_cast<lldb::Format>(AllocationDetails::RSTypeToFormat[type][eFormatSingle]) 1735 : static_cast<lldb::Format>(AllocationDetails::RSTypeToFormat[type][eFormatVector]); 1736 1737 const unsigned int data_size = vec_size * AllocationDetails::RSTypeToFormat[type][eElementSize]; 1738 // Renderscript pads vector 3 elements to vector 4 1739 const unsigned int elem_padding = vec_size == 3 ? AllocationDetails::RSTypeToFormat[type][eElementSize] : 0; 1740 1741 if (log) 1742 log->Printf("RenderScriptRuntime::DumpAllocation - Element size %u bytes, element padding %u bytes", 1743 data_size, elem_padding); 1744 1745 // Calculate stride between rows as there may be padding at end of rows since 1746 // allocated memory is 16-byte aligned 1747 if (!alloc->stride.isValid()) 1748 { 1749 if (alloc->dimension.get()->dim_2 == 0) // We only have one dimension 1750 alloc->stride = 0; 1751 else if (!JITAllocationStride(alloc, frame_ptr)) 1752 { 1753 strm.Printf("Error: Couldn't calculate allocation row stride"); 1754 strm.EOL(); 1755 return false; 1756 } 1757 } 1758 const unsigned int stride = *alloc->stride.get(); 1759 1760 // Calculate data size 1761 if (!alloc->size.isValid() && !JITAllocationSize(alloc, frame_ptr, data_size + elem_padding)) 1762 { 1763 strm.Printf("Error: Couldn't calculate allocation size"); 1764 strm.EOL(); 1765 return false; 1766 } 1767 const unsigned int size = *alloc->size.get(); //size of last element 1768 1769 if (log) 1770 log->Printf("RenderScriptRuntime::DumpAllocation - stride %u bytes, size %u bytes", stride, size); 1771 1772 // Allocate a buffer to copy data into 1773 uint8_t* buffer = new uint8_t[size]; 1774 if (!buffer) 1775 { 1776 strm.Printf("Error: Couldn't allocate a %u byte buffer to read memory into", size); 1777 strm.EOL(); 1778 return false; 1779 } 1780 1781 // Read Memory into buffer 1782 Error error; 1783 Process* process = GetProcess(); 1784 const addr_t data_ptr = *alloc->data_ptr.get(); 1785 const uint32_t archByteSize = process->GetTarget().GetArchitecture().GetAddressByteSize(); 1786 DataExtractor alloc_data(buffer, size, process->GetByteOrder(), archByteSize); 1787 1788 if (log) 1789 log->Printf("RenderScriptRuntime::DumpAllocation - Reading %u bytes of allocation data from 0x%" PRIx64, 1790 size, data_ptr); 1791 1792 // Read the inferior memory 1793 process->ReadMemory(data_ptr, buffer, size, error); 1794 if (error.Fail()) 1795 { 1796 strm.Printf("Error: Couldn't read %u bytes of allocation data from 0x%" PRIx64, size, data_ptr); 1797 strm.EOL(); 1798 delete[] buffer; // remember to free memory 1799 return false; 1800 } 1801 1802 // Find dimensions used to index loops, so need to be non-zero 1803 unsigned int dim_x = alloc->dimension.get()->dim_1; 1804 dim_x = dim_x == 0 ? 1 : dim_x; 1805 1806 unsigned int dim_y = alloc->dimension.get()->dim_2; 1807 dim_y = dim_y == 0 ? 1 : dim_y; 1808 1809 unsigned int dim_z = alloc->dimension.get()->dim_3; 1810 dim_z = dim_z == 0 ? 1 : dim_z; 1811 1812 unsigned int offset = 0; // Offset in buffer to next element to be printed 1813 unsigned int prev_row = 0; // Offset to the start of the previous row 1814 1815 // Iterate over allocation dimensions, printing results to user 1816 strm.Printf("Data (X, Y, Z):"); 1817 for (unsigned int z = 0; z < dim_z; ++z) 1818 { 1819 for (unsigned int y = 0; y < dim_y; ++y) 1820 { 1821 // Use stride to index start of next row. 1822 if (!(y==0 && z==0)) 1823 offset = prev_row + stride; 1824 prev_row = offset; 1825 1826 // Print each element in the row individually 1827 for (unsigned int x = 0; x < dim_x; ++x) 1828 { 1829 strm.Printf("\n(%u, %u, %u) = ", x, y, z); 1830 alloc_data.Dump(&strm, offset, format, data_size, 1, 1, LLDB_INVALID_ADDRESS, 0, 0); 1831 offset += data_size + elem_padding; 1832 } 1833 } 1834 } 1835 strm.EOL(); 1836 1837 delete[] buffer; 1838 return true; 1839 } 1840 1841 // Prints infomation regarding all the currently loaded allocations. 1842 // These details are gathered by jitting the runtime, which has as latency. 1843 void 1844 RenderScriptRuntime::ListAllocations(Stream &strm, StackFrame* frame_ptr, bool recompute) 1845 { 1846 strm.Printf("RenderScript Allocations:"); 1847 strm.EOL(); 1848 strm.IndentMore(); 1849 1850 for (auto &alloc : m_allocations) 1851 { 1852 // JIT the allocation info if we haven't done it, or the user forces us to. 1853 bool do_refresh = !alloc->data_ptr.isValid() || recompute; 1854 1855 // JIT current allocation information 1856 if (do_refresh && !RefreshAllocation(alloc.get(), frame_ptr)) 1857 { 1858 strm.Printf("Error: Couldn't evaluate details for allocation %u\n", alloc->id); 1859 continue; 1860 } 1861 1862 strm.Printf("%u:\n",alloc->id); 1863 strm.IndentMore(); 1864 1865 strm.Indent("Context: "); 1866 if (!alloc->context.isValid()) 1867 strm.Printf("unknown\n"); 1868 else 1869 strm.Printf("0x%" PRIx64 "\n", *alloc->context.get()); 1870 1871 strm.Indent("Address: "); 1872 if (!alloc->address.isValid()) 1873 strm.Printf("unknown\n"); 1874 else 1875 strm.Printf("0x%" PRIx64 "\n", *alloc->address.get()); 1876 1877 strm.Indent("Data pointer: "); 1878 if (!alloc->data_ptr.isValid()) 1879 strm.Printf("unknown\n"); 1880 else 1881 strm.Printf("0x%" PRIx64 "\n", *alloc->data_ptr.get()); 1882 1883 strm.Indent("Dimensions: "); 1884 if (!alloc->dimension.isValid()) 1885 strm.Printf("unknown\n"); 1886 else 1887 strm.Printf("(%d, %d, %d)\n", alloc->dimension.get()->dim_1, 1888 alloc->dimension.get()->dim_2, 1889 alloc->dimension.get()->dim_3); 1890 1891 strm.Indent("Data Type: "); 1892 if (!alloc->type.isValid() || !alloc->type_vec_size.isValid()) 1893 strm.Printf("unknown\n"); 1894 else 1895 { 1896 const int vector_size = *alloc->type_vec_size.get(); 1897 const AllocationDetails::DataType type = *alloc->type.get(); 1898 1899 if (vector_size > 4 || vector_size < 1 || 1900 type < AllocationDetails::RS_TYPE_NONE || type > AllocationDetails::RS_TYPE_BOOLEAN) 1901 strm.Printf("invalid type\n"); 1902 else 1903 strm.Printf("%s\n", AllocationDetails::RsDataTypeToString[static_cast<unsigned int>(type)][vector_size-1]); 1904 } 1905 1906 strm.Indent("Data Kind: "); 1907 if (!alloc->type_kind.isValid()) 1908 strm.Printf("unknown\n"); 1909 else 1910 { 1911 const AllocationDetails::DataKind kind = *alloc->type_kind.get(); 1912 if (kind < AllocationDetails::RS_KIND_USER || kind > AllocationDetails::RS_KIND_PIXEL_YUV) 1913 strm.Printf("invalid kind\n"); 1914 else 1915 strm.Printf("%s\n", AllocationDetails::RsDataKindToString[static_cast<unsigned int>(kind)]); 1916 } 1917 1918 strm.EOL(); 1919 strm.IndentLess(); 1920 } 1921 strm.IndentLess(); 1922 } 1923 1924 // Set breakpoints on every kernel found in RS module 1925 void 1926 RenderScriptRuntime::BreakOnModuleKernels(const RSModuleDescriptorSP rsmodule_sp) 1927 { 1928 for (const auto &kernel : rsmodule_sp->m_kernels) 1929 { 1930 // Don't set breakpoint on 'root' kernel 1931 if (strcmp(kernel.m_name.AsCString(), "root") == 0) 1932 continue; 1933 1934 CreateKernelBreakpoint(kernel.m_name); 1935 } 1936 } 1937 1938 // Method is internally called by the 'kernel breakpoint all' command to 1939 // enable or disable breaking on all kernels. 1940 // 1941 // When do_break is true we want to enable this functionality. 1942 // When do_break is false we want to disable it. 1943 void 1944 RenderScriptRuntime::SetBreakAllKernels(bool do_break, TargetSP target) 1945 { 1946 Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS)); 1947 1948 InitSearchFilter(target); 1949 1950 // Set breakpoints on all the kernels 1951 if (do_break && !m_breakAllKernels) 1952 { 1953 m_breakAllKernels = true; 1954 1955 for (const auto &module : m_rsmodules) 1956 BreakOnModuleKernels(module); 1957 1958 if (log) 1959 log->Printf("RenderScriptRuntime::SetBreakAllKernels(True)" 1960 "- breakpoints set on all currently loaded kernels"); 1961 } 1962 else if (!do_break && m_breakAllKernels) // Breakpoints won't be set on any new kernels. 1963 { 1964 m_breakAllKernels = false; 1965 1966 if (log) 1967 log->Printf("RenderScriptRuntime::SetBreakAllKernels(False) - breakpoints no longer automatically set"); 1968 } 1969 } 1970 1971 // Given the name of a kernel this function creates a breakpoint using our 1972 // own breakpoint resolver, and returns the Breakpoint shared pointer. 1973 BreakpointSP 1974 RenderScriptRuntime::CreateKernelBreakpoint(const ConstString& name) 1975 { 1976 Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS)); 1977 1978 if (!m_filtersp) 1979 { 1980 if (log) 1981 log->Printf("RenderScriptRuntime::CreateKernelBreakpoint - Error: No breakpoint search filter set"); 1982 return nullptr; 1983 } 1984 1985 BreakpointResolverSP resolver_sp(new RSBreakpointResolver(nullptr, name)); 1986 BreakpointSP bp = GetProcess()->GetTarget().CreateBreakpoint(m_filtersp, resolver_sp, false, false, false); 1987 1988 // Give RS breakpoints a specific name, so the user can manipulate them as a group. 1989 Error err; 1990 if (!bp->AddName("RenderScriptKernel", err) && log) 1991 log->Printf("RenderScriptRuntime::CreateKernelBreakpoint: Error setting break name, %s", err.AsCString()); 1992 1993 return bp; 1994 } 1995 1996 void 1997 RenderScriptRuntime::AttemptBreakpointAtKernelName(Stream &strm, const char* name, Error& error, TargetSP target) 1998 { 1999 if (!name) 2000 { 2001 error.SetErrorString("invalid kernel name"); 2002 return; 2003 } 2004 2005 InitSearchFilter(target); 2006 2007 ConstString kernel_name(name); 2008 BreakpointSP bp = CreateKernelBreakpoint(kernel_name); 2009 if (bp) 2010 bp->GetDescription(&strm, lldb::eDescriptionLevelInitial, false); 2011 2012 return; 2013 } 2014 2015 void 2016 RenderScriptRuntime::DumpModules(Stream &strm) const 2017 { 2018 strm.Printf("RenderScript Modules:"); 2019 strm.EOL(); 2020 strm.IndentMore(); 2021 for (const auto &module : m_rsmodules) 2022 { 2023 module->Dump(strm); 2024 } 2025 strm.IndentLess(); 2026 } 2027 2028 RenderScriptRuntime::ScriptDetails* 2029 RenderScriptRuntime::LookUpScript(addr_t address, bool create) 2030 { 2031 for (const auto & s : m_scripts) 2032 { 2033 if (s->script.isValid()) 2034 if (*s->script == address) 2035 return s.get(); 2036 } 2037 if (create) 2038 { 2039 std::unique_ptr<ScriptDetails> s(new ScriptDetails); 2040 s->script = address; 2041 m_scripts.push_back(std::move(s)); 2042 return m_scripts.back().get(); 2043 } 2044 return nullptr; 2045 } 2046 2047 RenderScriptRuntime::AllocationDetails* 2048 RenderScriptRuntime::LookUpAllocation(addr_t address, bool create) 2049 { 2050 for (const auto & a : m_allocations) 2051 { 2052 if (a->address.isValid()) 2053 if (*a->address == address) 2054 return a.get(); 2055 } 2056 if (create) 2057 { 2058 std::unique_ptr<AllocationDetails> a(new AllocationDetails); 2059 a->address = address; 2060 m_allocations.push_back(std::move(a)); 2061 return m_allocations.back().get(); 2062 } 2063 return nullptr; 2064 } 2065 2066 void 2067 RSModuleDescriptor::Dump(Stream &strm) const 2068 { 2069 strm.Indent(); 2070 m_module->GetFileSpec().Dump(&strm); 2071 if(m_module->GetNumCompileUnits()) 2072 { 2073 strm.Indent("Debug info loaded."); 2074 } 2075 else 2076 { 2077 strm.Indent("Debug info does not exist."); 2078 } 2079 strm.EOL(); 2080 strm.IndentMore(); 2081 strm.Indent(); 2082 strm.Printf("Globals: %" PRIu64, static_cast<uint64_t>(m_globals.size())); 2083 strm.EOL(); 2084 strm.IndentMore(); 2085 for (const auto &global : m_globals) 2086 { 2087 global.Dump(strm); 2088 } 2089 strm.IndentLess(); 2090 strm.Indent(); 2091 strm.Printf("Kernels: %" PRIu64, static_cast<uint64_t>(m_kernels.size())); 2092 strm.EOL(); 2093 strm.IndentMore(); 2094 for (const auto &kernel : m_kernels) 2095 { 2096 kernel.Dump(strm); 2097 } 2098 strm.Printf("Pragmas: %" PRIu64 , static_cast<uint64_t>(m_pragmas.size())); 2099 strm.EOL(); 2100 strm.IndentMore(); 2101 for (const auto &key_val : m_pragmas) 2102 { 2103 strm.Printf("%s: %s", key_val.first.c_str(), key_val.second.c_str()); 2104 strm.EOL(); 2105 } 2106 strm.IndentLess(4); 2107 } 2108 2109 void 2110 RSGlobalDescriptor::Dump(Stream &strm) const 2111 { 2112 strm.Indent(m_name.AsCString()); 2113 VariableList var_list; 2114 m_module->m_module->FindGlobalVariables(m_name, nullptr, true, 1U, var_list); 2115 if (var_list.GetSize() == 1) 2116 { 2117 auto var = var_list.GetVariableAtIndex(0); 2118 auto type = var->GetType(); 2119 if(type) 2120 { 2121 strm.Printf(" - "); 2122 type->DumpTypeName(&strm); 2123 } 2124 else 2125 { 2126 strm.Printf(" - Unknown Type"); 2127 } 2128 } 2129 else 2130 { 2131 strm.Printf(" - variable identified, but not found in binary"); 2132 const Symbol* s = m_module->m_module->FindFirstSymbolWithNameAndType(m_name, eSymbolTypeData); 2133 if (s) 2134 { 2135 strm.Printf(" (symbol exists) "); 2136 } 2137 } 2138 2139 strm.EOL(); 2140 } 2141 2142 void 2143 RSKernelDescriptor::Dump(Stream &strm) const 2144 { 2145 strm.Indent(m_name.AsCString()); 2146 strm.EOL(); 2147 } 2148 2149 class CommandObjectRenderScriptRuntimeModuleProbe : public CommandObjectParsed 2150 { 2151 private: 2152 public: 2153 CommandObjectRenderScriptRuntimeModuleProbe(CommandInterpreter &interpreter) 2154 : CommandObjectParsed(interpreter, "renderscript module probe", 2155 "Initiates a Probe of all loaded modules for kernels and other renderscript objects.", 2156 "renderscript module probe", 2157 eCommandRequiresTarget | eCommandRequiresProcess | eCommandProcessMustBeLaunched) 2158 { 2159 } 2160 2161 ~CommandObjectRenderScriptRuntimeModuleProbe() {} 2162 2163 bool 2164 DoExecute(Args &command, CommandReturnObject &result) 2165 { 2166 const size_t argc = command.GetArgumentCount(); 2167 if (argc == 0) 2168 { 2169 Target *target = m_exe_ctx.GetTargetPtr(); 2170 RenderScriptRuntime *runtime = 2171 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); 2172 auto module_list = target->GetImages(); 2173 bool new_rs_details = runtime->ProbeModules(module_list); 2174 if (new_rs_details) 2175 { 2176 result.AppendMessage("New renderscript modules added to runtime model."); 2177 } 2178 result.SetStatus(eReturnStatusSuccessFinishResult); 2179 return true; 2180 } 2181 2182 result.AppendErrorWithFormat("'%s' takes no arguments", m_cmd_name.c_str()); 2183 result.SetStatus(eReturnStatusFailed); 2184 return false; 2185 } 2186 }; 2187 2188 class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed 2189 { 2190 private: 2191 public: 2192 CommandObjectRenderScriptRuntimeModuleDump(CommandInterpreter &interpreter) 2193 : CommandObjectParsed(interpreter, "renderscript module dump", 2194 "Dumps renderscript specific information for all modules.", "renderscript module dump", 2195 eCommandRequiresProcess | eCommandProcessMustBeLaunched) 2196 { 2197 } 2198 2199 ~CommandObjectRenderScriptRuntimeModuleDump() {} 2200 2201 bool 2202 DoExecute(Args &command, CommandReturnObject &result) 2203 { 2204 RenderScriptRuntime *runtime = 2205 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); 2206 runtime->DumpModules(result.GetOutputStream()); 2207 result.SetStatus(eReturnStatusSuccessFinishResult); 2208 return true; 2209 } 2210 }; 2211 2212 class CommandObjectRenderScriptRuntimeModule : public CommandObjectMultiword 2213 { 2214 private: 2215 public: 2216 CommandObjectRenderScriptRuntimeModule(CommandInterpreter &interpreter) 2217 : CommandObjectMultiword(interpreter, "renderscript module", "Commands that deal with renderscript modules.", 2218 NULL) 2219 { 2220 LoadSubCommand("probe", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleProbe(interpreter))); 2221 LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleDump(interpreter))); 2222 } 2223 2224 ~CommandObjectRenderScriptRuntimeModule() {} 2225 }; 2226 2227 class CommandObjectRenderScriptRuntimeKernelList : public CommandObjectParsed 2228 { 2229 private: 2230 public: 2231 CommandObjectRenderScriptRuntimeKernelList(CommandInterpreter &interpreter) 2232 : CommandObjectParsed(interpreter, "renderscript kernel list", 2233 "Lists renderscript kernel names and associated script resources.", "renderscript kernel list", 2234 eCommandRequiresProcess | eCommandProcessMustBeLaunched) 2235 { 2236 } 2237 2238 ~CommandObjectRenderScriptRuntimeKernelList() {} 2239 2240 bool 2241 DoExecute(Args &command, CommandReturnObject &result) 2242 { 2243 RenderScriptRuntime *runtime = 2244 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); 2245 runtime->DumpKernels(result.GetOutputStream()); 2246 result.SetStatus(eReturnStatusSuccessFinishResult); 2247 return true; 2248 } 2249 }; 2250 2251 class CommandObjectRenderScriptRuntimeKernelBreakpointSet : public CommandObjectParsed 2252 { 2253 private: 2254 public: 2255 CommandObjectRenderScriptRuntimeKernelBreakpointSet(CommandInterpreter &interpreter) 2256 : CommandObjectParsed(interpreter, "renderscript kernel breakpoint set", 2257 "Sets a breakpoint on a renderscript kernel.", "renderscript kernel breakpoint set <kernel_name>", 2258 eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) 2259 { 2260 } 2261 2262 ~CommandObjectRenderScriptRuntimeKernelBreakpointSet() {} 2263 2264 bool 2265 DoExecute(Args &command, CommandReturnObject &result) 2266 { 2267 const size_t argc = command.GetArgumentCount(); 2268 if (argc == 1) 2269 { 2270 RenderScriptRuntime *runtime = 2271 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); 2272 2273 Error error; 2274 runtime->AttemptBreakpointAtKernelName(result.GetOutputStream(), command.GetArgumentAtIndex(0), 2275 error, m_exe_ctx.GetTargetSP()); 2276 2277 if (error.Success()) 2278 { 2279 result.AppendMessage("Breakpoint(s) created"); 2280 result.SetStatus(eReturnStatusSuccessFinishResult); 2281 return true; 2282 } 2283 result.SetStatus(eReturnStatusFailed); 2284 result.AppendErrorWithFormat("Error: %s", error.AsCString()); 2285 return false; 2286 } 2287 2288 result.AppendErrorWithFormat("'%s' takes 1 argument of kernel name", m_cmd_name.c_str()); 2289 result.SetStatus(eReturnStatusFailed); 2290 return false; 2291 } 2292 }; 2293 2294 class CommandObjectRenderScriptRuntimeKernelBreakpointAll : public CommandObjectParsed 2295 { 2296 private: 2297 public: 2298 CommandObjectRenderScriptRuntimeKernelBreakpointAll(CommandInterpreter &interpreter) 2299 : CommandObjectParsed(interpreter, "renderscript kernel breakpoint all", 2300 "Automatically sets a breakpoint on all renderscript kernels that are or will be loaded.\n" 2301 "Disabling option means breakpoints will no longer be set on any kernels loaded in the future, " 2302 "but does not remove currently set breakpoints.", 2303 "renderscript kernel breakpoint all <enable/disable>", 2304 eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) 2305 { 2306 } 2307 2308 ~CommandObjectRenderScriptRuntimeKernelBreakpointAll() {} 2309 2310 bool 2311 DoExecute(Args &command, CommandReturnObject &result) 2312 { 2313 const size_t argc = command.GetArgumentCount(); 2314 if (argc != 1) 2315 { 2316 result.AppendErrorWithFormat("'%s' takes 1 argument of 'enable' or 'disable'", m_cmd_name.c_str()); 2317 result.SetStatus(eReturnStatusFailed); 2318 return false; 2319 } 2320 2321 RenderScriptRuntime *runtime = 2322 static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); 2323 2324 bool do_break = false; 2325 const char* argument = command.GetArgumentAtIndex(0); 2326 if (strcmp(argument, "enable") == 0) 2327 { 2328 do_break = true; 2329 result.AppendMessage("Breakpoints will be set on all kernels."); 2330 } 2331 else if (strcmp(argument, "disable") == 0) 2332 { 2333 do_break = false; 2334 result.AppendMessage("Breakpoints will not be set on any new kernels."); 2335 } 2336 else 2337 { 2338 result.AppendErrorWithFormat("Argument must be either 'enable' or 'disable'"); 2339 result.SetStatus(eReturnStatusFailed); 2340 return false; 2341 } 2342 2343 runtime->SetBreakAllKernels(do_break, m_exe_ctx.GetTargetSP()); 2344 2345 result.SetStatus(eReturnStatusSuccessFinishResult); 2346 return true; 2347 } 2348 }; 2349 2350 class CommandObjectRenderScriptRuntimeKernelBreakpoint : public CommandObjectMultiword 2351 { 2352 private: 2353 public: 2354 CommandObjectRenderScriptRuntimeKernelBreakpoint(CommandInterpreter &interpreter) 2355 : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that generate breakpoints on renderscript kernels.", 2356 nullptr) 2357 { 2358 LoadSubCommand("set", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointSet(interpreter))); 2359 LoadSubCommand("all", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointAll(interpreter))); 2360 } 2361 2362 ~CommandObjectRenderScriptRuntimeKernelBreakpoint() {} 2363 }; 2364 2365 class CommandObjectRenderScriptRuntimeKernel : public CommandObjectMultiword 2366 { 2367 private: 2368 public: 2369 CommandObjectRenderScriptRuntimeKernel(CommandInterpreter &interpreter) 2370 : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that deal with renderscript kernels.", 2371 NULL) 2372 { 2373 LoadSubCommand("list", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelList(interpreter))); 2374 LoadSubCommand("breakpoint", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpoint(interpreter))); 2375 } 2376 2377 ~CommandObjectRenderScriptRuntimeKernel() {} 2378 }; 2379 2380 class CommandObjectRenderScriptRuntimeContextDump : public CommandObjectParsed 2381 { 2382 private: 2383 public: 2384 CommandObjectRenderScriptRuntimeContextDump(CommandInterpreter &interpreter) 2385 : CommandObjectParsed(interpreter, "renderscript context dump", 2386 "Dumps renderscript context information.", "renderscript context dump", 2387 eCommandRequiresProcess | eCommandProcessMustBeLaunched) 2388 { 2389 } 2390 2391 ~CommandObjectRenderScriptRuntimeContextDump() {} 2392 2393 bool 2394 DoExecute(Args &command, CommandReturnObject &result) 2395 { 2396 RenderScriptRuntime *runtime = 2397 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); 2398 runtime->DumpContexts(result.GetOutputStream()); 2399 result.SetStatus(eReturnStatusSuccessFinishResult); 2400 return true; 2401 } 2402 }; 2403 2404 class CommandObjectRenderScriptRuntimeContext : public CommandObjectMultiword 2405 { 2406 private: 2407 public: 2408 CommandObjectRenderScriptRuntimeContext(CommandInterpreter &interpreter) 2409 : CommandObjectMultiword(interpreter, "renderscript context", "Commands that deal with renderscript contexts.", 2410 NULL) 2411 { 2412 LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeContextDump(interpreter))); 2413 } 2414 2415 ~CommandObjectRenderScriptRuntimeContext() {} 2416 }; 2417 2418 2419 class CommandObjectRenderScriptRuntimeAllocationDump : public CommandObjectParsed 2420 { 2421 private: 2422 public: 2423 CommandObjectRenderScriptRuntimeAllocationDump(CommandInterpreter &interpreter) 2424 : CommandObjectParsed(interpreter, "renderscript allocation dump", 2425 "Displays the contents of a particular allocation", "renderscript allocation dump <ID>", 2426 eCommandRequiresProcess | eCommandProcessMustBeLaunched), m_options(interpreter) 2427 { 2428 } 2429 2430 virtual Options* 2431 GetOptions() 2432 { 2433 return &m_options; 2434 } 2435 2436 class CommandOptions : public Options 2437 { 2438 public: 2439 CommandOptions(CommandInterpreter &interpreter) : Options(interpreter) 2440 { 2441 } 2442 2443 virtual 2444 ~CommandOptions() 2445 { 2446 } 2447 2448 virtual Error 2449 SetOptionValue(uint32_t option_idx, const char *option_arg) 2450 { 2451 Error error; 2452 const int short_option = m_getopt_table[option_idx].val; 2453 2454 switch (short_option) 2455 { 2456 case 'f': 2457 m_outfile.SetFile(option_arg, true); 2458 if (m_outfile.Exists()) 2459 { 2460 m_outfile.Clear(); 2461 error.SetErrorStringWithFormat("file already exists: '%s'", option_arg); 2462 } 2463 break; 2464 default: 2465 error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); 2466 break; 2467 } 2468 return error; 2469 } 2470 2471 void 2472 OptionParsingStarting() 2473 { 2474 m_outfile.Clear(); 2475 } 2476 2477 const OptionDefinition* 2478 GetDefinitions() 2479 { 2480 return g_option_table; 2481 } 2482 2483 static OptionDefinition g_option_table[]; 2484 FileSpec m_outfile; 2485 }; 2486 2487 ~CommandObjectRenderScriptRuntimeAllocationDump() {} 2488 2489 bool 2490 DoExecute(Args &command, CommandReturnObject &result) 2491 { 2492 const size_t argc = command.GetArgumentCount(); 2493 if (argc < 1) 2494 { 2495 result.AppendErrorWithFormat("'%s' takes 1 argument, an allocation ID. As well as an optional -f argument", 2496 m_cmd_name.c_str()); 2497 result.SetStatus(eReturnStatusFailed); 2498 return false; 2499 } 2500 2501 RenderScriptRuntime *runtime = 2502 static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); 2503 2504 const char* id_cstr = command.GetArgumentAtIndex(0); 2505 bool convert_complete = false; 2506 const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete); 2507 if (!convert_complete) 2508 { 2509 result.AppendErrorWithFormat("invalid allocation id argument '%s'", id_cstr); 2510 result.SetStatus(eReturnStatusFailed); 2511 return false; 2512 } 2513 2514 Stream* output_strm = nullptr; 2515 StreamFile outfile_stream; 2516 const FileSpec &outfile_spec = m_options.m_outfile; // Dump allocation to file instead 2517 if (outfile_spec) 2518 { 2519 // Open output file 2520 char path[256]; 2521 outfile_spec.GetPath(path, sizeof(path)); 2522 if (outfile_stream.GetFile().Open(path, File::eOpenOptionWrite | File::eOpenOptionCanCreate).Success()) 2523 { 2524 output_strm = &outfile_stream; 2525 result.GetOutputStream().Printf("Results written to '%s'", path); 2526 result.GetOutputStream().EOL(); 2527 } 2528 else 2529 { 2530 result.AppendErrorWithFormat("Couldn't open file '%s'", path); 2531 result.SetStatus(eReturnStatusFailed); 2532 return false; 2533 } 2534 } 2535 else 2536 output_strm = &result.GetOutputStream(); 2537 2538 assert(output_strm != nullptr); 2539 bool success = runtime->DumpAllocation(*output_strm, m_exe_ctx.GetFramePtr(), id); 2540 2541 if (success) 2542 result.SetStatus(eReturnStatusSuccessFinishResult); 2543 else 2544 result.SetStatus(eReturnStatusFailed); 2545 2546 return true; 2547 } 2548 2549 private: 2550 CommandOptions m_options; 2551 }; 2552 2553 OptionDefinition 2554 CommandObjectRenderScriptRuntimeAllocationDump::CommandOptions::g_option_table[] = 2555 { 2556 { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFilename, 2557 "Print results to specified file instead of command line."}, 2558 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 2559 }; 2560 2561 2562 class CommandObjectRenderScriptRuntimeAllocationList : public CommandObjectParsed 2563 { 2564 public: 2565 CommandObjectRenderScriptRuntimeAllocationList(CommandInterpreter &interpreter) 2566 : CommandObjectParsed(interpreter, "renderscript allocation list", 2567 "List renderscript allocations and their information.", "renderscript allocation list", 2568 eCommandRequiresProcess | eCommandProcessMustBeLaunched), m_options(interpreter) 2569 { 2570 } 2571 2572 virtual Options* 2573 GetOptions() 2574 { 2575 return &m_options; 2576 } 2577 2578 class CommandOptions : public Options 2579 { 2580 public: 2581 CommandOptions(CommandInterpreter &interpreter) : Options(interpreter), m_refresh(false) 2582 { 2583 } 2584 2585 virtual 2586 ~CommandOptions() 2587 { 2588 } 2589 2590 virtual Error 2591 SetOptionValue(uint32_t option_idx, const char *option_arg) 2592 { 2593 Error error; 2594 const int short_option = m_getopt_table[option_idx].val; 2595 2596 switch (short_option) 2597 { 2598 case 'r': 2599 m_refresh = true; 2600 break; 2601 default: 2602 error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); 2603 break; 2604 } 2605 return error; 2606 } 2607 2608 void 2609 OptionParsingStarting() 2610 { 2611 m_refresh = false; 2612 } 2613 2614 const OptionDefinition* 2615 GetDefinitions() 2616 { 2617 return g_option_table; 2618 } 2619 2620 static OptionDefinition g_option_table[]; 2621 bool m_refresh; 2622 }; 2623 2624 ~CommandObjectRenderScriptRuntimeAllocationList() {} 2625 2626 bool 2627 DoExecute(Args &command, CommandReturnObject &result) 2628 { 2629 RenderScriptRuntime *runtime = 2630 static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); 2631 runtime->ListAllocations(result.GetOutputStream(), m_exe_ctx.GetFramePtr(), m_options.m_refresh); 2632 result.SetStatus(eReturnStatusSuccessFinishResult); 2633 return true; 2634 } 2635 2636 private: 2637 CommandOptions m_options; 2638 }; 2639 2640 OptionDefinition 2641 CommandObjectRenderScriptRuntimeAllocationList::CommandOptions::g_option_table[] = 2642 { 2643 { LLDB_OPT_SET_1, false, "refresh", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, 2644 "Recompute allocation details."}, 2645 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 2646 }; 2647 2648 2649 class CommandObjectRenderScriptRuntimeAllocation : public CommandObjectMultiword 2650 { 2651 private: 2652 public: 2653 CommandObjectRenderScriptRuntimeAllocation(CommandInterpreter &interpreter) 2654 : CommandObjectMultiword(interpreter, "renderscript allocation", "Commands that deal with renderscript allocations.", 2655 NULL) 2656 { 2657 LoadSubCommand("list", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationList(interpreter))); 2658 LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationDump(interpreter))); 2659 } 2660 2661 ~CommandObjectRenderScriptRuntimeAllocation() {} 2662 }; 2663 2664 2665 class CommandObjectRenderScriptRuntimeStatus : public CommandObjectParsed 2666 { 2667 private: 2668 public: 2669 CommandObjectRenderScriptRuntimeStatus(CommandInterpreter &interpreter) 2670 : CommandObjectParsed(interpreter, "renderscript status", 2671 "Displays current renderscript runtime status.", "renderscript status", 2672 eCommandRequiresProcess | eCommandProcessMustBeLaunched) 2673 { 2674 } 2675 2676 ~CommandObjectRenderScriptRuntimeStatus() {} 2677 2678 bool 2679 DoExecute(Args &command, CommandReturnObject &result) 2680 { 2681 RenderScriptRuntime *runtime = 2682 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); 2683 runtime->Status(result.GetOutputStream()); 2684 result.SetStatus(eReturnStatusSuccessFinishResult); 2685 return true; 2686 } 2687 }; 2688 2689 class CommandObjectRenderScriptRuntime : public CommandObjectMultiword 2690 { 2691 public: 2692 CommandObjectRenderScriptRuntime(CommandInterpreter &interpreter) 2693 : CommandObjectMultiword(interpreter, "renderscript", "A set of commands for operating on renderscript.", 2694 "renderscript <subcommand> [<subcommand-options>]") 2695 { 2696 LoadSubCommand("module", CommandObjectSP(new CommandObjectRenderScriptRuntimeModule(interpreter))); 2697 LoadSubCommand("status", CommandObjectSP(new CommandObjectRenderScriptRuntimeStatus(interpreter))); 2698 LoadSubCommand("kernel", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernel(interpreter))); 2699 LoadSubCommand("context", CommandObjectSP(new CommandObjectRenderScriptRuntimeContext(interpreter))); 2700 LoadSubCommand("allocation", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocation(interpreter))); 2701 } 2702 2703 ~CommandObjectRenderScriptRuntime() {} 2704 }; 2705 2706 void 2707 RenderScriptRuntime::Initiate() 2708 { 2709 assert(!m_initiated); 2710 } 2711 2712 RenderScriptRuntime::RenderScriptRuntime(Process *process) 2713 : lldb_private::CPPLanguageRuntime(process), m_initiated(false), m_debuggerPresentFlagged(false), 2714 m_breakAllKernels(false) 2715 { 2716 ModulesDidLoad(process->GetTarget().GetImages()); 2717 } 2718 2719 lldb::CommandObjectSP 2720 RenderScriptRuntime::GetCommandObject(lldb_private::CommandInterpreter& interpreter) 2721 { 2722 static CommandObjectSP command_object; 2723 if(!command_object) 2724 { 2725 command_object.reset(new CommandObjectRenderScriptRuntime(interpreter)); 2726 } 2727 return command_object; 2728 } 2729 2730 RenderScriptRuntime::~RenderScriptRuntime() = default; 2731