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