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