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