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 // Used to index expression format strings 1118 enum ExpressionStrings 1119 { 1120 eExprGetOffsetPtr = 0, 1121 eExprAllocGetType, 1122 eExprTypeDimX, 1123 eExprTypeDimY, 1124 eExprTypeDimZ, 1125 eExprTypeElemPtr, 1126 eExprElementType, 1127 eExprElementKind, 1128 eExprElementVec, 1129 eExprElementFieldCount, 1130 eExprSubelementsId, 1131 eExprSubelementsName, 1132 eExprSubelementsArrSize 1133 }; 1134 1135 // Format strings containing the expressions we may need to evaluate. 1136 const char runtimeExpressions[][256] = 1137 { 1138 // Mangled GetOffsetPointer(Allocation*, xoff, yoff, zoff, lod, cubemap) 1139 "(int*)_Z12GetOffsetPtrPKN7android12renderscript10AllocationEjjjj23RsAllocationCubemapFace(0x%lx, %u, %u, %u, 0, 0)", 1140 1141 // Type* rsaAllocationGetType(Context*, Allocation*) 1142 "(void*)rsaAllocationGetType(0x%lx, 0x%lx)", 1143 1144 // rsaTypeGetNativeData(Context*, Type*, void* typeData, size) 1145 // Pack the data in the following way mHal.state.dimX; mHal.state.dimY; mHal.state.dimZ; 1146 // mHal.state.lodCount; mHal.state.faces; mElement; into typeData 1147 // Need to specify 32 or 64 bit for uint_t since this differs between devices 1148 "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[0]", // X dim 1149 "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[1]", // Y dim 1150 "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[2]", // Z dim 1151 "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[5]", // Element ptr 1152 1153 // rsaElementGetNativeData(Context*, Element*, uint32_t* elemData,size) 1154 // Pack mType; mKind; mNormalized; mVectorSize; NumSubElements into elemData 1155 "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[0]", // Type 1156 "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[1]", // Kind 1157 "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[3]", // Vector Size 1158 "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[4]", // Field Count 1159 1160 // rsaElementGetSubElements(RsContext con, RsElement elem, uintptr_t *ids, const char **names, 1161 // size_t *arraySizes, uint32_t dataSize) 1162 // Needed for Allocations of structs to gather details about fields/Subelements 1163 "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];" 1164 "(void*)rsaElementGetSubElements(0x%lx, 0x%lx, ids, names, arr_size, %u); ids[%u]", // Element* of field 1165 1166 "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];" 1167 "(void*)rsaElementGetSubElements(0x%lx, 0x%lx, ids, names, arr_size, %u); names[%u]", // Name of field 1168 1169 "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];" 1170 "(void*)rsaElementGetSubElements(0x%lx, 0x%lx, ids, names, arr_size, %u); arr_size[%u]" // Array size of field 1171 }; 1172 1173 // JITs the RS runtime for the internal data pointer of an allocation. 1174 // Is passed x,y,z coordinates for the pointer to a specific element. 1175 // Then sets the data_ptr member in Allocation with the result. 1176 // Returns true on success, false otherwise 1177 bool 1178 RenderScriptRuntime::JITDataPointer(AllocationDetails* allocation, StackFrame* frame_ptr, 1179 unsigned int x, unsigned int y, unsigned int z) 1180 { 1181 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 1182 1183 if (!allocation->address.isValid()) 1184 { 1185 if (log) 1186 log->Printf("RenderScriptRuntime::JITDataPointer - Failed to find allocation details"); 1187 return false; 1188 } 1189 1190 const char* expr_cstr = runtimeExpressions[eExprGetOffsetPtr]; 1191 const int max_expr_size = 512; // Max expression size 1192 char buffer[max_expr_size]; 1193 1194 int chars_written = snprintf(buffer, max_expr_size, expr_cstr, *allocation->address.get(), x, y, z); 1195 if (chars_written < 0) 1196 { 1197 if (log) 1198 log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()"); 1199 return false; 1200 } 1201 else if (chars_written >= max_expr_size) 1202 { 1203 if (log) 1204 log->Printf("RenderScriptRuntime::JITDataPointer - Expression too long"); 1205 return false; 1206 } 1207 1208 uint64_t result = 0; 1209 if (!EvalRSExpression(buffer, frame_ptr, &result)) 1210 return false; 1211 1212 addr_t mem_ptr = static_cast<lldb::addr_t>(result); 1213 allocation->data_ptr = mem_ptr; 1214 1215 return true; 1216 } 1217 1218 // JITs the RS runtime for the internal pointer to the RS Type of an allocation 1219 // Then sets the type_ptr member in Allocation with the result. 1220 // Returns true on success, false otherwise 1221 bool 1222 RenderScriptRuntime::JITTypePointer(AllocationDetails* allocation, StackFrame* frame_ptr) 1223 { 1224 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 1225 1226 if (!allocation->address.isValid() || !allocation->context.isValid()) 1227 { 1228 if (log) 1229 log->Printf("RenderScriptRuntime::JITTypePointer - Failed to find allocation details"); 1230 return false; 1231 } 1232 1233 const char* expr_cstr = runtimeExpressions[eExprAllocGetType]; 1234 const int max_expr_size = 512; // Max expression size 1235 char buffer[max_expr_size]; 1236 1237 int chars_written = snprintf(buffer, max_expr_size, expr_cstr, *allocation->context.get(), *allocation->address.get()); 1238 if (chars_written < 0) 1239 { 1240 if (log) 1241 log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()"); 1242 return false; 1243 } 1244 else if (chars_written >= max_expr_size) 1245 { 1246 if (log) 1247 log->Printf("RenderScriptRuntime::JITTypePointer - Expression too long"); 1248 return false; 1249 } 1250 1251 uint64_t result = 0; 1252 if (!EvalRSExpression(buffer, frame_ptr, &result)) 1253 return false; 1254 1255 addr_t type_ptr = static_cast<lldb::addr_t>(result); 1256 allocation->type_ptr = type_ptr; 1257 1258 return true; 1259 } 1260 1261 // JITs the RS runtime for information about the dimensions and type of an allocation 1262 // Then sets dimension and element_ptr members in Allocation with the result. 1263 // Returns true on success, false otherwise 1264 bool 1265 RenderScriptRuntime::JITTypePacked(AllocationDetails* allocation, StackFrame* frame_ptr) 1266 { 1267 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 1268 1269 if (!allocation->type_ptr.isValid() || !allocation->context.isValid()) 1270 { 1271 if (log) 1272 log->Printf("RenderScriptRuntime::JITTypePacked - Failed to find allocation details"); 1273 return false; 1274 } 1275 1276 // Expression is different depending on if device is 32 or 64 bit 1277 uint32_t archByteSize = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize(); 1278 const unsigned int bits = archByteSize == 4 ? 32 : 64; 1279 1280 // We want 4 elements from packed data 1281 const unsigned int num_exprs = 4; 1282 assert(num_exprs == (eExprTypeElemPtr - eExprTypeDimX + 1) && "Invalid number of expressions"); 1283 1284 const int max_expr_size = 512; // Max expression size 1285 char buffer[num_exprs][max_expr_size]; 1286 uint64_t results[num_exprs]; 1287 1288 for (unsigned int i = 0; i < num_exprs; ++i) 1289 { 1290 int chars_written = snprintf(buffer[i], max_expr_size, runtimeExpressions[eExprTypeDimX + i], bits, 1291 *allocation->context.get(), *allocation->type_ptr.get()); 1292 if (chars_written < 0) 1293 { 1294 if (log) 1295 log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()"); 1296 return false; 1297 } 1298 else if (chars_written >= max_expr_size) 1299 { 1300 if (log) 1301 log->Printf("RenderScriptRuntime::JITTypePacked - Expression too long"); 1302 return false; 1303 } 1304 1305 // Perform expression evaluation 1306 if (!EvalRSExpression(buffer[i], frame_ptr, &results[i])) 1307 return false; 1308 } 1309 1310 // Assign results to allocation members 1311 AllocationDetails::Dimension dims; 1312 dims.dim_1 = static_cast<uint32_t>(results[0]); 1313 dims.dim_2 = static_cast<uint32_t>(results[1]); 1314 dims.dim_3 = static_cast<uint32_t>(results[2]); 1315 allocation->dimension = dims; 1316 1317 addr_t elem_ptr = static_cast<lldb::addr_t>(results[3]); 1318 allocation->element.element_ptr = elem_ptr; 1319 1320 if (log) 1321 log->Printf("RenderScriptRuntime::JITTypePacked - dims (%u, %u, %u) Element*: 0x%" PRIx64, 1322 dims.dim_1, dims.dim_2, dims.dim_3, elem_ptr); 1323 1324 return true; 1325 } 1326 1327 // JITs the RS runtime for information about the Element of an allocation 1328 // Then sets type, type_vec_size, field_count and type_kind members in Element with the result. 1329 // Returns true on success, false otherwise 1330 bool 1331 RenderScriptRuntime::JITElementPacked(Element& elem, const lldb::addr_t context, StackFrame* frame_ptr) 1332 { 1333 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 1334 1335 if (!elem.element_ptr.isValid()) 1336 { 1337 if (log) 1338 log->Printf("RenderScriptRuntime::JITElementPacked - Failed to find allocation details"); 1339 return false; 1340 } 1341 1342 // We want 4 elements from packed data 1343 const unsigned int num_exprs = 4; 1344 assert(num_exprs == (eExprElementFieldCount - eExprElementType + 1) && "Invalid number of expressions"); 1345 1346 const int max_expr_size = 512; // Max expression size 1347 char buffer[num_exprs][max_expr_size]; 1348 uint64_t results[num_exprs]; 1349 1350 for (unsigned int i = 0; i < num_exprs; i++) 1351 { 1352 int chars_written = snprintf(buffer[i], max_expr_size, runtimeExpressions[eExprElementType + i], context, *elem.element_ptr.get()); 1353 if (chars_written < 0) 1354 { 1355 if (log) 1356 log->Printf("RenderScriptRuntime::JITElementPacked - Encoding error in snprintf()"); 1357 return false; 1358 } 1359 else if (chars_written >= max_expr_size) 1360 { 1361 if (log) 1362 log->Printf("RenderScriptRuntime::JITElementPacked - Expression too long"); 1363 return false; 1364 } 1365 1366 // Perform expression evaluation 1367 if (!EvalRSExpression(buffer[i], frame_ptr, &results[i])) 1368 return false; 1369 } 1370 1371 // Assign results to allocation members 1372 elem.type = static_cast<RenderScriptRuntime::Element::DataType>(results[0]); 1373 elem.type_kind = static_cast<RenderScriptRuntime::Element::DataKind>(results[1]); 1374 elem.type_vec_size = static_cast<uint32_t>(results[2]); 1375 elem.field_count = static_cast<uint32_t>(results[3]); 1376 1377 if (log) 1378 log->Printf("RenderScriptRuntime::JITElementPacked - data type %u, pixel type %u, vector size %u, field count %u", 1379 *elem.type.get(), *elem.type_kind.get(), *elem.type_vec_size.get(), *elem.field_count.get()); 1380 1381 // If this Element has subelements then JIT rsaElementGetSubElements() for details about its fields 1382 if (*elem.field_count.get() > 0 && !JITSubelements(elem, context, frame_ptr)) 1383 return false; 1384 1385 return true; 1386 } 1387 1388 // JITs the RS runtime for information about the subelements/fields of a struct allocation 1389 // This is necessary for infering the struct type so we can pretty print the allocation's contents. 1390 // Returns true on success, false otherwise 1391 bool 1392 RenderScriptRuntime::JITSubelements(Element& elem, const lldb::addr_t context, StackFrame* frame_ptr) 1393 { 1394 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 1395 1396 if (!elem.element_ptr.isValid() || !elem.field_count.isValid()) 1397 { 1398 if (log) 1399 log->Printf("RenderScriptRuntime::JITSubelements - Failed to find allocation details"); 1400 return false; 1401 } 1402 1403 const short num_exprs = 3; 1404 assert(num_exprs == (eExprSubelementsArrSize - eExprSubelementsId + 1) && "Invalid number of expressions"); 1405 1406 const int max_expr_size = 512; // Max expression size 1407 char expr_buffer[max_expr_size]; 1408 uint64_t results; 1409 1410 // Iterate over struct fields. 1411 const uint32_t field_count = *elem.field_count.get(); 1412 for (unsigned int field_index = 0; field_index < field_count; ++field_index) 1413 { 1414 Element child; 1415 for (unsigned int expr_index = 0; expr_index < num_exprs; ++expr_index) 1416 { 1417 int chars_written = snprintf(expr_buffer, max_expr_size, runtimeExpressions[eExprSubelementsId + expr_index], 1418 field_count, field_count, field_count, 1419 context, *elem.element_ptr.get(), field_count, field_index); 1420 if (chars_written < 0) 1421 { 1422 if (log) 1423 log->Printf("RenderScriptRuntime::JITSubelements - Encoding error in snprintf()"); 1424 return false; 1425 } 1426 else if (chars_written >= max_expr_size) 1427 { 1428 if (log) 1429 log->Printf("RenderScriptRuntime::JITSubelements - Expression too long"); 1430 return false; 1431 } 1432 1433 // Perform expression evaluation 1434 if (!EvalRSExpression(expr_buffer, frame_ptr, &results)) 1435 return false; 1436 1437 if (log) 1438 log->Printf("RenderScriptRuntime::JITSubelements - Expr result 0x%" PRIx64, results); 1439 1440 switch(expr_index) 1441 { 1442 case 0: // Element* of child 1443 child.element_ptr = static_cast<addr_t>(results); 1444 break; 1445 case 1: // Name of child 1446 { 1447 lldb::addr_t address = static_cast<addr_t>(results); 1448 Error err; 1449 std::string name; 1450 GetProcess()->ReadCStringFromMemory(address, name, err); 1451 if (!err.Fail()) 1452 child.type_name = ConstString(name); 1453 else 1454 { 1455 if (log) 1456 log->Printf("RenderScriptRuntime::JITSubelements - Warning: Couldn't read field name"); 1457 } 1458 break; 1459 } 1460 case 2: // Array size of child 1461 child.array_size = static_cast<uint32_t>(results); 1462 break; 1463 } 1464 } 1465 1466 // We need to recursively JIT each Element field of the struct since 1467 // structs can be nested inside structs. 1468 if (!JITElementPacked(child, context, frame_ptr)) 1469 return false; 1470 elem.children.push_back(child); 1471 } 1472 1473 // Try to infer the name of the struct type so we can pretty print the allocation contents. 1474 FindStructTypeName(elem, frame_ptr); 1475 1476 return true; 1477 } 1478 1479 // JITs the RS runtime for the address of the last element in the allocation. 1480 // The `elem_size` paramter represents the size of a single element, including padding. 1481 // Which is needed as an offset from the last element pointer. 1482 // Using this offset minus the starting address we can calculate the size of the allocation. 1483 // Returns true on success, false otherwise 1484 bool 1485 RenderScriptRuntime::JITAllocationSize(AllocationDetails* allocation, StackFrame* frame_ptr) 1486 { 1487 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 1488 1489 if (!allocation->address.isValid() || !allocation->dimension.isValid() 1490 || !allocation->data_ptr.isValid() || !allocation->element.datum_size.isValid()) 1491 { 1492 if (log) 1493 log->Printf("RenderScriptRuntime::JITAllocationSize - Failed to find allocation details"); 1494 return false; 1495 } 1496 1497 // Find dimensions 1498 unsigned int dim_x = allocation->dimension.get()->dim_1; 1499 unsigned int dim_y = allocation->dimension.get()->dim_2; 1500 unsigned int dim_z = allocation->dimension.get()->dim_3; 1501 1502 // Our plan of jitting the last element address doesn't seem to work for struct Allocations 1503 // Instead try to infer the size ourselves without any inter element padding. 1504 if (allocation->element.children.size() > 0) 1505 { 1506 if (dim_x == 0) dim_x = 1; 1507 if (dim_y == 0) dim_y = 1; 1508 if (dim_z == 0) dim_z = 1; 1509 1510 allocation->size = dim_x * dim_y * dim_z * *allocation->element.datum_size.get(); 1511 1512 if (log) 1513 log->Printf("RenderScriptRuntime::JITAllocationSize - Infered size of struct allocation %u", *allocation->size.get()); 1514 1515 return true; 1516 } 1517 1518 const char* expr_cstr = runtimeExpressions[eExprGetOffsetPtr]; 1519 const int max_expr_size = 512; 1520 char buffer[max_expr_size]; 1521 1522 // Calculate last element 1523 dim_x = dim_x == 0 ? 0 : dim_x - 1; 1524 dim_y = dim_y == 0 ? 0 : dim_y - 1; 1525 dim_z = dim_z == 0 ? 0 : dim_z - 1; 1526 1527 int chars_written = snprintf(buffer, max_expr_size, expr_cstr, *allocation->address.get(), 1528 dim_x, dim_y, dim_z); 1529 if (chars_written < 0) 1530 { 1531 if (log) 1532 log->Printf("RenderScriptRuntime::JITAllocationSize - Encoding error in snprintf()"); 1533 return false; 1534 } 1535 else if (chars_written >= max_expr_size) 1536 { 1537 if (log) 1538 log->Printf("RenderScriptRuntime::JITAllocationSize - Expression too long"); 1539 return false; 1540 } 1541 1542 uint64_t result = 0; 1543 if (!EvalRSExpression(buffer, frame_ptr, &result)) 1544 return false; 1545 1546 addr_t mem_ptr = static_cast<lldb::addr_t>(result); 1547 // Find pointer to last element and add on size of an element 1548 allocation->size = static_cast<uint32_t>(mem_ptr - *allocation->data_ptr.get()) + *allocation->element.datum_size.get(); 1549 1550 return true; 1551 } 1552 1553 // JITs the RS runtime for information about the stride between rows in the allocation. 1554 // This is done to detect padding, since allocated memory is 16-byte aligned. 1555 // Returns true on success, false otherwise 1556 bool 1557 RenderScriptRuntime::JITAllocationStride(AllocationDetails* allocation, StackFrame* frame_ptr) 1558 { 1559 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 1560 1561 if (!allocation->address.isValid() || !allocation->data_ptr.isValid()) 1562 { 1563 if (log) 1564 log->Printf("RenderScriptRuntime::JITAllocationStride - Failed to find allocation details"); 1565 return false; 1566 } 1567 1568 const char* expr_cstr = runtimeExpressions[eExprGetOffsetPtr]; 1569 const int max_expr_size = 512; // Max expression size 1570 char buffer[max_expr_size]; 1571 1572 int chars_written = snprintf(buffer, max_expr_size, expr_cstr, *allocation->address.get(), 1573 0, 1, 0); 1574 if (chars_written < 0) 1575 { 1576 if (log) 1577 log->Printf("RenderScriptRuntime::JITAllocationStride - Encoding error in snprintf()"); 1578 return false; 1579 } 1580 else if (chars_written >= max_expr_size) 1581 { 1582 if (log) 1583 log->Printf("RenderScriptRuntime::JITAllocationStride - Expression too long"); 1584 return false; 1585 } 1586 1587 uint64_t result = 0; 1588 if (!EvalRSExpression(buffer, frame_ptr, &result)) 1589 return false; 1590 1591 addr_t mem_ptr = static_cast<lldb::addr_t>(result); 1592 allocation->stride = static_cast<uint32_t>(mem_ptr - *allocation->data_ptr.get()); 1593 1594 return true; 1595 } 1596 1597 // JIT all the current runtime info regarding an allocation 1598 bool 1599 RenderScriptRuntime::RefreshAllocation(AllocationDetails* allocation, StackFrame* frame_ptr) 1600 { 1601 // GetOffsetPointer() 1602 if (!JITDataPointer(allocation, frame_ptr)) 1603 return false; 1604 1605 // rsaAllocationGetType() 1606 if (!JITTypePointer(allocation, frame_ptr)) 1607 return false; 1608 1609 // rsaTypeGetNativeData() 1610 if (!JITTypePacked(allocation, frame_ptr)) 1611 return false; 1612 1613 // rsaElementGetNativeData() 1614 if (!JITElementPacked(allocation->element, *allocation->context.get(), frame_ptr)) 1615 return false; 1616 1617 // Sets the datum_size member in Element 1618 SetElementSize(allocation->element); 1619 1620 // Use GetOffsetPointer() to infer size of the allocation 1621 if (!JITAllocationSize(allocation, frame_ptr)) 1622 return false; 1623 1624 return true; 1625 } 1626 1627 // Function attempts to set the type_name member of the paramaterised Element object. 1628 // This string should be the name of the struct type the Element represents. 1629 // We need this string for pretty printing the Element to users. 1630 void 1631 RenderScriptRuntime::FindStructTypeName(Element& elem, StackFrame* frame_ptr) 1632 { 1633 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 1634 1635 if (!elem.type_name.IsEmpty()) // Name already set 1636 return; 1637 else 1638 elem.type_name = Element::GetFallbackStructName(); // Default type name if we don't succeed 1639 1640 // Find all the global variables from the script rs modules 1641 VariableList variable_list; 1642 for (auto module_sp : m_rsmodules) 1643 module_sp->m_module->FindGlobalVariables(RegularExpression("."), true, UINT32_MAX, variable_list); 1644 1645 // Iterate over all the global variables looking for one with a matching type to the Element. 1646 // We make the assumption a match exists since there needs to be a global variable to reflect the 1647 // struct type back into java host code. 1648 for (uint32_t var_index = 0; var_index < variable_list.GetSize(); ++var_index) 1649 { 1650 const VariableSP var_sp(variable_list.GetVariableAtIndex(var_index)); 1651 if (!var_sp) 1652 continue; 1653 1654 ValueObjectSP valobj_sp = ValueObjectVariable::Create(frame_ptr, var_sp); 1655 if (!valobj_sp) 1656 continue; 1657 1658 // Find the number of variable fields. 1659 // If it has no fields, or more fields than our Element, then it can't be the struct we're looking for. 1660 // Don't check for equality since RS can add extra struct members for padding. 1661 size_t num_children = valobj_sp->GetNumChildren(); 1662 if (num_children > elem.children.size() || num_children == 0) 1663 continue; 1664 1665 // Iterate over children looking for members with matching field names. 1666 // If all the field names match, this is likely the struct we want. 1667 // 1668 // TODO: This could be made more robust by also checking children data sizes, or array size 1669 bool found = true; 1670 for (size_t child_index = 0; child_index < num_children; ++child_index) 1671 { 1672 ValueObjectSP child = valobj_sp->GetChildAtIndex(child_index, true); 1673 if (!child || (child->GetName() != elem.children[child_index].type_name)) 1674 { 1675 found = false; 1676 break; 1677 } 1678 } 1679 1680 // RS can add extra struct members for padding in the format '#rs_padding_[0-9]+' 1681 if (found && num_children < elem.children.size()) 1682 { 1683 const unsigned int size_diff = elem.children.size() - num_children; 1684 if (log) 1685 log->Printf("RenderScriptRuntime::FindStructTypeName - %u padding struct entries", size_diff); 1686 1687 for (unsigned int padding_index = 0; padding_index < size_diff; ++padding_index) 1688 { 1689 const ConstString& name = elem.children[num_children + padding_index].type_name; 1690 if (strcmp(name.AsCString(), "#rs_padding") < 0) 1691 found = false; 1692 } 1693 } 1694 1695 // We've found a global var with matching type 1696 if (found) 1697 { 1698 // Dereference since our Element type isn't a pointer. 1699 if (valobj_sp->IsPointerType()) 1700 { 1701 Error err; 1702 ValueObjectSP deref_valobj = valobj_sp->Dereference(err); 1703 if (!err.Fail()) 1704 valobj_sp = deref_valobj; 1705 } 1706 1707 // Save name of variable in Element. 1708 elem.type_name = valobj_sp->GetTypeName(); 1709 if (log) 1710 log->Printf("RenderScriptRuntime::FindStructTypeName - Element name set to %s", elem.type_name.AsCString()); 1711 1712 return; 1713 } 1714 } 1715 } 1716 1717 // Function sets the datum_size member of Element. Representing the size of a single instance including padding. 1718 // Assumes the relevant allocation information has already been jitted. 1719 void 1720 RenderScriptRuntime::SetElementSize(Element& elem) 1721 { 1722 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 1723 const Element::DataType type = *elem.type.get(); 1724 assert(type >= Element::RS_TYPE_NONE && type <= Element::RS_TYPE_BOOLEAN 1725 && "Invalid allocation type"); 1726 1727 const unsigned int vec_size = *elem.type_vec_size.get(); 1728 unsigned int data_size = 0; 1729 const unsigned int padding = vec_size == 3 ? AllocationDetails::RSTypeToFormat[type][eElementSize] : 0; 1730 1731 // Element is of a struct type, calculate size recursively. 1732 if ((type == Element::RS_TYPE_NONE) && (elem.children.size() > 0)) 1733 { 1734 for (Element& child : elem.children) 1735 { 1736 SetElementSize(child); 1737 const unsigned int array_size = child.array_size.isValid() ? *child.array_size.get() : 1; 1738 data_size += *child.datum_size.get() * array_size; 1739 } 1740 } 1741 else 1742 data_size = vec_size * AllocationDetails::RSTypeToFormat[type][eElementSize]; 1743 1744 elem.padding = padding; 1745 elem.datum_size = data_size + padding; 1746 if (log) 1747 log->Printf("RenderScriptRuntime::SetElementSize - element size set to %u", data_size + padding); 1748 } 1749 1750 // Given an allocation, this function copies the allocation contents from device into a buffer on the heap. 1751 // Returning a shared pointer to the buffer containing the data. 1752 std::shared_ptr<uint8_t> 1753 RenderScriptRuntime::GetAllocationData(AllocationDetails* allocation, StackFrame* frame_ptr) 1754 { 1755 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 1756 1757 // JIT all the allocation details 1758 if (!allocation->data_ptr.isValid() || !allocation->element.type.isValid() 1759 || !allocation->element.type_vec_size.isValid() || !allocation->size.isValid()) 1760 { 1761 if (log) 1762 log->Printf("RenderScriptRuntime::GetAllocationData - Allocation details not calculated yet, jitting info"); 1763 1764 if (!RefreshAllocation(allocation, frame_ptr)) 1765 { 1766 if (log) 1767 log->Printf("RenderScriptRuntime::GetAllocationData - Couldn't JIT allocation details"); 1768 return nullptr; 1769 } 1770 } 1771 1772 assert(allocation->data_ptr.isValid() && allocation->element.type.isValid() && allocation->element.type_vec_size.isValid() 1773 && allocation->size.isValid() && "Allocation information not available"); 1774 1775 // Allocate a buffer to copy data into 1776 const unsigned int size = *allocation->size.get(); 1777 std::shared_ptr<uint8_t> buffer(new uint8_t[size]); 1778 if (!buffer) 1779 { 1780 if (log) 1781 log->Printf("RenderScriptRuntime::GetAllocationData - Couldn't allocate a %u byte buffer", size); 1782 return nullptr; 1783 } 1784 1785 // Read the inferior memory 1786 Error error; 1787 lldb::addr_t data_ptr = *allocation->data_ptr.get(); 1788 GetProcess()->ReadMemory(data_ptr, buffer.get(), size, error); 1789 if (error.Fail()) 1790 { 1791 if (log) 1792 log->Printf("RenderScriptRuntime::GetAllocationData - '%s' Couldn't read %u bytes of allocation data from 0x%" PRIx64, 1793 error.AsCString(), size, data_ptr); 1794 return nullptr; 1795 } 1796 1797 return buffer; 1798 } 1799 1800 // Function copies data from a binary file into an allocation. 1801 // There is a header at the start of the file, FileHeader, before the data content itself. 1802 // Information from this header is used to display warnings to the user about incompatabilities 1803 bool 1804 RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id, const char* filename, StackFrame* frame_ptr) 1805 { 1806 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 1807 1808 // Find allocation with the given id 1809 AllocationDetails* alloc = FindAllocByID(strm, alloc_id); 1810 if (!alloc) 1811 return false; 1812 1813 if (log) 1814 log->Printf("RenderScriptRuntime::LoadAllocation - Found allocation 0x%" PRIx64, *alloc->address.get()); 1815 1816 // JIT all the allocation details 1817 if (!alloc->data_ptr.isValid() || !alloc->element.type.isValid() || !alloc->element.datum_size.isValid() 1818 || !alloc->element.type_vec_size.isValid() || !alloc->size.isValid()) 1819 { 1820 if (log) 1821 log->Printf("RenderScriptRuntime::LoadAllocation - Allocation details not calculated yet, jitting info"); 1822 1823 if (!RefreshAllocation(alloc, frame_ptr)) 1824 { 1825 if (log) 1826 log->Printf("RenderScriptRuntime::LoadAllocation - Couldn't JIT allocation details"); 1827 return false; 1828 } 1829 } 1830 1831 assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() && alloc->element.type_vec_size.isValid() 1832 && alloc->size.isValid() && alloc->element.datum_size.isValid() && "Allocation information not available"); 1833 1834 // Check we can read from file 1835 FileSpec file(filename, true); 1836 if (!file.Exists()) 1837 { 1838 strm.Printf("Error: File %s does not exist", filename); 1839 strm.EOL(); 1840 return false; 1841 } 1842 1843 if (!file.Readable()) 1844 { 1845 strm.Printf("Error: File %s does not have readable permissions", filename); 1846 strm.EOL(); 1847 return false; 1848 } 1849 1850 // Read file into data buffer 1851 DataBufferSP data_sp(file.ReadFileContents()); 1852 1853 // Cast start of buffer to FileHeader and use pointer to read metadata 1854 void* file_buffer = data_sp->GetBytes(); 1855 const AllocationDetails::FileHeader* head = static_cast<AllocationDetails::FileHeader*>(file_buffer); 1856 1857 // Advance buffer past header 1858 file_buffer = static_cast<uint8_t*>(file_buffer) + head->hdr_size; 1859 1860 if (log) 1861 log->Printf("RenderScriptRuntime::LoadAllocation - header type %u, element size %u", 1862 head->type, head->element_size); 1863 1864 // Check if the target allocation and file both have the same number of bytes for an Element 1865 if (*alloc->element.datum_size.get() != head->element_size) 1866 { 1867 strm.Printf("Warning: Mismatched Element sizes - file %u bytes, allocation %u bytes", 1868 head->element_size, *alloc->element.datum_size.get()); 1869 strm.EOL(); 1870 } 1871 1872 // Check if the target allocation and file both have the same integral type 1873 const unsigned int type = static_cast<unsigned int>(*alloc->element.type.get()); 1874 if (type != head->type) 1875 { 1876 const char* file_type_cstr = AllocationDetails::RsDataTypeToString[head->type][0]; 1877 const char* alloc_type_cstr = AllocationDetails::RsDataTypeToString[type][0]; 1878 1879 strm.Printf("Warning: Mismatched Types - file '%s' type, allocation '%s' type", 1880 file_type_cstr, alloc_type_cstr); 1881 strm.EOL(); 1882 } 1883 1884 // Calculate size of allocation data in file 1885 size_t length = data_sp->GetByteSize() - head->hdr_size; 1886 1887 // Check if the target allocation and file both have the same total data size. 1888 const unsigned int alloc_size = *alloc->size.get(); 1889 if (alloc_size != length) 1890 { 1891 strm.Printf("Warning: Mismatched allocation sizes - file 0x%" PRIx64 " bytes, allocation 0x%x bytes", 1892 (uint64_t) length, alloc_size); 1893 strm.EOL(); 1894 length = alloc_size < length ? alloc_size : length; // Set length to copy to minimum 1895 } 1896 1897 // Copy file data from our buffer into the target allocation. 1898 lldb::addr_t alloc_data = *alloc->data_ptr.get(); 1899 Error error; 1900 size_t bytes_written = GetProcess()->WriteMemory(alloc_data, file_buffer, length, error); 1901 if (!error.Success() || bytes_written != length) 1902 { 1903 strm.Printf("Error: Couldn't write data to allocation %s", error.AsCString()); 1904 strm.EOL(); 1905 return false; 1906 } 1907 1908 strm.Printf("Contents of file '%s' read into allocation %u", filename, alloc->id); 1909 strm.EOL(); 1910 1911 return true; 1912 } 1913 1914 // Function copies allocation contents into a binary file. 1915 // This file can then be loaded later into a different allocation. 1916 // There is a header, FileHeader, before the allocation data containing meta-data. 1917 bool 1918 RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id, const char* filename, StackFrame* frame_ptr) 1919 { 1920 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 1921 1922 // Find allocation with the given id 1923 AllocationDetails* alloc = FindAllocByID(strm, alloc_id); 1924 if (!alloc) 1925 return false; 1926 1927 if (log) 1928 log->Printf("RenderScriptRuntime::SaveAllocation - Found allocation 0x%" PRIx64, *alloc->address.get()); 1929 1930 // JIT all the allocation details 1931 if (!alloc->data_ptr.isValid() || !alloc->element.type.isValid() || !alloc->element.type_vec_size.isValid() 1932 || !alloc->element.type_kind.isValid() || !alloc->dimension.isValid()) 1933 { 1934 if (log) 1935 log->Printf("RenderScriptRuntime::SaveAllocation - Allocation details not calculated yet, jitting info"); 1936 1937 if (!RefreshAllocation(alloc, frame_ptr)) 1938 { 1939 if (log) 1940 log->Printf("RenderScriptRuntime::SaveAllocation - Couldn't JIT allocation details"); 1941 return false; 1942 } 1943 } 1944 1945 assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() && alloc->element.type_vec_size.isValid() && alloc->element.datum_size.get() 1946 && alloc->element.type_kind.isValid() && alloc->dimension.isValid() && "Allocation information not available"); 1947 1948 // Check we can create writable file 1949 FileSpec file_spec(filename, true); 1950 File file(file_spec, File::eOpenOptionWrite | File::eOpenOptionCanCreate | File::eOpenOptionTruncate); 1951 if (!file) 1952 { 1953 strm.Printf("Error: Failed to open '%s' for writing", filename); 1954 strm.EOL(); 1955 return false; 1956 } 1957 1958 // Read allocation into buffer of heap memory 1959 const std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr); 1960 if (!buffer) 1961 { 1962 strm.Printf("Error: Couldn't read allocation data into buffer"); 1963 strm.EOL(); 1964 return false; 1965 } 1966 1967 // Create the file header 1968 AllocationDetails::FileHeader head; 1969 head.ident[0] = 'R'; head.ident[1] = 'S'; head.ident[2] = 'A'; head.ident[3] = 'D'; 1970 head.hdr_size = static_cast<uint16_t>(sizeof(AllocationDetails::FileHeader)); 1971 head.type = static_cast<uint16_t>(*alloc->element.type.get()); 1972 head.kind = static_cast<uint32_t>(*alloc->element.type_kind.get()); 1973 head.dims[0] = static_cast<uint32_t>(alloc->dimension.get()->dim_1); 1974 head.dims[1] = static_cast<uint32_t>(alloc->dimension.get()->dim_2); 1975 head.dims[2] = static_cast<uint32_t>(alloc->dimension.get()->dim_3); 1976 head.element_size = static_cast<uint32_t>(*alloc->element.datum_size.get()); 1977 1978 // Write the file header 1979 size_t num_bytes = sizeof(AllocationDetails::FileHeader); 1980 Error err = file.Write(static_cast<const void*>(&head), num_bytes); 1981 if (!err.Success()) 1982 { 1983 strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), filename); 1984 strm.EOL(); 1985 return false; 1986 } 1987 1988 // Write allocation data to file 1989 num_bytes = static_cast<size_t>(*alloc->size.get()); 1990 if (log) 1991 log->Printf("RenderScriptRuntime::SaveAllocation - Writing 0x%" PRIx64 " bytes from %p", (uint64_t) num_bytes, buffer.get()); 1992 1993 err = file.Write(buffer.get(), num_bytes); 1994 if (!err.Success()) 1995 { 1996 strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), filename); 1997 strm.EOL(); 1998 return false; 1999 } 2000 2001 strm.Printf("Allocation written to file '%s'", filename); 2002 strm.EOL(); 2003 return true; 2004 } 2005 2006 bool 2007 RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp) 2008 { 2009 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 2010 2011 if (module_sp) 2012 { 2013 for (const auto &rs_module : m_rsmodules) 2014 { 2015 if (rs_module->m_module == module_sp) 2016 { 2017 // Check if the user has enabled automatically breaking on 2018 // all RS kernels. 2019 if (m_breakAllKernels) 2020 BreakOnModuleKernels(rs_module); 2021 2022 return false; 2023 } 2024 } 2025 bool module_loaded = false; 2026 switch (GetModuleKind(module_sp)) 2027 { 2028 case eModuleKindKernelObj: 2029 { 2030 RSModuleDescriptorSP module_desc; 2031 module_desc.reset(new RSModuleDescriptor(module_sp)); 2032 if (module_desc->ParseRSInfo()) 2033 { 2034 m_rsmodules.push_back(module_desc); 2035 module_loaded = true; 2036 } 2037 if (module_loaded) 2038 { 2039 FixupScriptDetails(module_desc); 2040 } 2041 break; 2042 } 2043 case eModuleKindDriver: 2044 { 2045 if (!m_libRSDriver) 2046 { 2047 m_libRSDriver = module_sp; 2048 LoadRuntimeHooks(m_libRSDriver, RenderScriptRuntime::eModuleKindDriver); 2049 } 2050 break; 2051 } 2052 case eModuleKindImpl: 2053 { 2054 m_libRSCpuRef = module_sp; 2055 break; 2056 } 2057 case eModuleKindLibRS: 2058 { 2059 if (!m_libRS) 2060 { 2061 m_libRS = module_sp; 2062 static ConstString gDbgPresentStr("gDebuggerPresent"); 2063 const Symbol* debug_present = m_libRS->FindFirstSymbolWithNameAndType(gDbgPresentStr, eSymbolTypeData); 2064 if (debug_present) 2065 { 2066 Error error; 2067 uint32_t flag = 0x00000001U; 2068 Target &target = GetProcess()->GetTarget(); 2069 addr_t addr = debug_present->GetLoadAddress(&target); 2070 GetProcess()->WriteMemory(addr, &flag, sizeof(flag), error); 2071 if(error.Success()) 2072 { 2073 if (log) 2074 log->Printf ("RenderScriptRuntime::LoadModule - Debugger present flag set on debugee"); 2075 2076 m_debuggerPresentFlagged = true; 2077 } 2078 else if (log) 2079 { 2080 log->Printf ("RenderScriptRuntime::LoadModule - Error writing debugger present flags '%s' ", error.AsCString()); 2081 } 2082 } 2083 else if (log) 2084 { 2085 log->Printf ("RenderScriptRuntime::LoadModule - Error writing debugger present flags - symbol not found"); 2086 } 2087 } 2088 break; 2089 } 2090 default: 2091 break; 2092 } 2093 if (module_loaded) 2094 Update(); 2095 return module_loaded; 2096 } 2097 return false; 2098 } 2099 2100 void 2101 RenderScriptRuntime::Update() 2102 { 2103 if (m_rsmodules.size() > 0) 2104 { 2105 if (!m_initiated) 2106 { 2107 Initiate(); 2108 } 2109 } 2110 } 2111 2112 // The maximum line length of an .rs.info packet 2113 #define MAXLINE 500 2114 2115 // The .rs.info symbol in renderscript modules contains a string which needs to be parsed. 2116 // The string is basic and is parsed on a line by line basis. 2117 bool 2118 RSModuleDescriptor::ParseRSInfo() 2119 { 2120 const Symbol *info_sym = m_module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData); 2121 if (info_sym) 2122 { 2123 const addr_t addr = info_sym->GetAddressRef().GetFileAddress(); 2124 const addr_t size = info_sym->GetByteSize(); 2125 const FileSpec fs = m_module->GetFileSpec(); 2126 2127 DataBufferSP buffer = fs.ReadFileContents(addr, size); 2128 2129 if (!buffer) 2130 return false; 2131 2132 std::string info((const char *)buffer->GetBytes()); 2133 2134 std::vector<std::string> info_lines; 2135 size_t lpos = info.find('\n'); 2136 while (lpos != std::string::npos) 2137 { 2138 info_lines.push_back(info.substr(0, lpos)); 2139 info = info.substr(lpos + 1); 2140 lpos = info.find('\n'); 2141 } 2142 size_t offset = 0; 2143 while (offset < info_lines.size()) 2144 { 2145 std::string line = info_lines[offset]; 2146 // Parse directives 2147 uint32_t numDefns = 0; 2148 if (sscanf(line.c_str(), "exportVarCount: %u", &numDefns) == 1) 2149 { 2150 while (numDefns--) 2151 m_globals.push_back(RSGlobalDescriptor(this, info_lines[++offset].c_str())); 2152 } 2153 else if (sscanf(line.c_str(), "exportFuncCount: %u", &numDefns) == 1) 2154 { 2155 } 2156 else if (sscanf(line.c_str(), "exportForEachCount: %u", &numDefns) == 1) 2157 { 2158 char name[MAXLINE]; 2159 while (numDefns--) 2160 { 2161 uint32_t slot = 0; 2162 name[0] = '\0'; 2163 if (sscanf(info_lines[++offset].c_str(), "%u - %s", &slot, &name[0]) == 2) 2164 { 2165 m_kernels.push_back(RSKernelDescriptor(this, name, slot)); 2166 } 2167 } 2168 } 2169 else if (sscanf(line.c_str(), "pragmaCount: %u", &numDefns) == 1) 2170 { 2171 char name[MAXLINE]; 2172 char value[MAXLINE]; 2173 while (numDefns--) 2174 { 2175 name[0] = '\0'; 2176 value[0] = '\0'; 2177 if (sscanf(info_lines[++offset].c_str(), "%s - %s", &name[0], &value[0]) != 0 2178 && (name[0] != '\0')) 2179 { 2180 m_pragmas[std::string(name)] = value; 2181 } 2182 } 2183 } 2184 else if (sscanf(line.c_str(), "objectSlotCount: %u", &numDefns) == 1) 2185 { 2186 } 2187 2188 offset++; 2189 } 2190 return m_kernels.size() > 0; 2191 } 2192 return false; 2193 } 2194 2195 bool 2196 RenderScriptRuntime::ProbeModules(const ModuleList module_list) 2197 { 2198 bool rs_found = false; 2199 size_t num_modules = module_list.GetSize(); 2200 for (size_t i = 0; i < num_modules; i++) 2201 { 2202 auto module = module_list.GetModuleAtIndex(i); 2203 rs_found |= LoadModule(module); 2204 } 2205 return rs_found; 2206 } 2207 2208 void 2209 RenderScriptRuntime::Status(Stream &strm) const 2210 { 2211 if (m_libRS) 2212 { 2213 strm.Printf("Runtime Library discovered."); 2214 strm.EOL(); 2215 } 2216 if (m_libRSDriver) 2217 { 2218 strm.Printf("Runtime Driver discovered."); 2219 strm.EOL(); 2220 } 2221 if (m_libRSCpuRef) 2222 { 2223 strm.Printf("CPU Reference Implementation discovered."); 2224 strm.EOL(); 2225 } 2226 2227 if (m_runtimeHooks.size()) 2228 { 2229 strm.Printf("Runtime functions hooked:"); 2230 strm.EOL(); 2231 for (auto b : m_runtimeHooks) 2232 { 2233 strm.Indent(b.second->defn->name); 2234 strm.EOL(); 2235 } 2236 strm.EOL(); 2237 } 2238 else 2239 { 2240 strm.Printf("Runtime is not hooked."); 2241 strm.EOL(); 2242 } 2243 } 2244 2245 void 2246 RenderScriptRuntime::DumpContexts(Stream &strm) const 2247 { 2248 strm.Printf("Inferred RenderScript Contexts:"); 2249 strm.EOL(); 2250 strm.IndentMore(); 2251 2252 std::map<addr_t, uint64_t> contextReferences; 2253 2254 // Iterate over all of the currently discovered scripts. 2255 // Note: We cant push or pop from m_scripts inside this loop or it may invalidate script. 2256 for (const auto & script : m_scripts) 2257 { 2258 if (!script->context.isValid()) 2259 continue; 2260 lldb::addr_t context = *script->context; 2261 2262 if (contextReferences.find(context) != contextReferences.end()) 2263 { 2264 contextReferences[context]++; 2265 } 2266 else 2267 { 2268 contextReferences[context] = 1; 2269 } 2270 } 2271 2272 for (const auto& cRef : contextReferences) 2273 { 2274 strm.Printf("Context 0x%" PRIx64 ": %" PRIu64 " script instances", cRef.first, cRef.second); 2275 strm.EOL(); 2276 } 2277 strm.IndentLess(); 2278 } 2279 2280 void 2281 RenderScriptRuntime::DumpKernels(Stream &strm) const 2282 { 2283 strm.Printf("RenderScript Kernels:"); 2284 strm.EOL(); 2285 strm.IndentMore(); 2286 for (const auto &module : m_rsmodules) 2287 { 2288 strm.Printf("Resource '%s':",module->m_resname.c_str()); 2289 strm.EOL(); 2290 for (const auto &kernel : module->m_kernels) 2291 { 2292 strm.Indent(kernel.m_name.AsCString()); 2293 strm.EOL(); 2294 } 2295 } 2296 strm.IndentLess(); 2297 } 2298 2299 RenderScriptRuntime::AllocationDetails* 2300 RenderScriptRuntime::FindAllocByID(Stream &strm, const uint32_t alloc_id) 2301 { 2302 AllocationDetails* alloc = nullptr; 2303 2304 // See if we can find allocation using id as an index; 2305 if (alloc_id <= m_allocations.size() && alloc_id != 0 2306 && m_allocations[alloc_id-1]->id == alloc_id) 2307 { 2308 alloc = m_allocations[alloc_id-1].get(); 2309 return alloc; 2310 } 2311 2312 // Fallback to searching 2313 for (const auto & a : m_allocations) 2314 { 2315 if (a->id == alloc_id) 2316 { 2317 alloc = a.get(); 2318 break; 2319 } 2320 } 2321 2322 if (alloc == nullptr) 2323 { 2324 strm.Printf("Error: Couldn't find allocation with id matching %u", alloc_id); 2325 strm.EOL(); 2326 } 2327 2328 return alloc; 2329 } 2330 2331 // Prints the contents of an allocation to the output stream, which may be a file 2332 bool 2333 RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame* frame_ptr, const uint32_t id) 2334 { 2335 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 2336 2337 // Check we can find the desired allocation 2338 AllocationDetails* alloc = FindAllocByID(strm, id); 2339 if (!alloc) 2340 return false; // FindAllocByID() will print error message for us here 2341 2342 if (log) 2343 log->Printf("RenderScriptRuntime::DumpAllocation - Found allocation 0x%" PRIx64, *alloc->address.get()); 2344 2345 // Check we have information about the allocation, if not calculate it 2346 if (!alloc->data_ptr.isValid() || !alloc->element.type.isValid() || 2347 !alloc->element.type_vec_size.isValid() || !alloc->dimension.isValid() || !alloc->element.datum_size.isValid()) 2348 { 2349 if (log) 2350 log->Printf("RenderScriptRuntime::DumpAllocation - Allocation details not calculated yet, jitting info"); 2351 2352 // JIT all the allocation information 2353 if (!RefreshAllocation(alloc, frame_ptr)) 2354 { 2355 strm.Printf("Error: Couldn't JIT allocation details"); 2356 strm.EOL(); 2357 return false; 2358 } 2359 } 2360 2361 // Establish format and size of each data element 2362 const unsigned int vec_size = *alloc->element.type_vec_size.get(); 2363 const Element::DataType type = *alloc->element.type.get(); 2364 2365 assert(type >= Element::RS_TYPE_NONE && type <= Element::RS_TYPE_BOOLEAN 2366 && "Invalid allocation type"); 2367 2368 lldb::Format format = vec_size == 1 ? static_cast<lldb::Format>(AllocationDetails::RSTypeToFormat[type][eFormatSingle]) 2369 : static_cast<lldb::Format>(AllocationDetails::RSTypeToFormat[type][eFormatVector]); 2370 2371 const unsigned int data_size = *alloc->element.datum_size.get(); 2372 2373 if (log) 2374 log->Printf("RenderScriptRuntime::DumpAllocation - Element size %u bytes, including padding", data_size); 2375 2376 // Allocate a buffer to copy data into 2377 std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr); 2378 if (!buffer) 2379 { 2380 strm.Printf("Error: Couldn't allocate a read allocation data into memory"); 2381 strm.EOL(); 2382 return false; 2383 } 2384 2385 // Calculate stride between rows as there may be padding at end of rows since 2386 // allocated memory is 16-byte aligned 2387 if (!alloc->stride.isValid()) 2388 { 2389 if (alloc->dimension.get()->dim_2 == 0) // We only have one dimension 2390 alloc->stride = 0; 2391 else if (!JITAllocationStride(alloc, frame_ptr)) 2392 { 2393 strm.Printf("Error: Couldn't calculate allocation row stride"); 2394 strm.EOL(); 2395 return false; 2396 } 2397 } 2398 const unsigned int stride = *alloc->stride.get(); 2399 const unsigned int size = *alloc->size.get(); // Size of whole allocation 2400 const unsigned int padding = alloc->element.padding.isValid() ? *alloc->element.padding.get() : 0; 2401 if (log) 2402 log->Printf("RenderScriptRuntime::DumpAllocation - stride %u bytes, size %u bytes, padding %u", stride, size, padding); 2403 2404 // Find dimensions used to index loops, so need to be non-zero 2405 unsigned int dim_x = alloc->dimension.get()->dim_1; 2406 dim_x = dim_x == 0 ? 1 : dim_x; 2407 2408 unsigned int dim_y = alloc->dimension.get()->dim_2; 2409 dim_y = dim_y == 0 ? 1 : dim_y; 2410 2411 unsigned int dim_z = alloc->dimension.get()->dim_3; 2412 dim_z = dim_z == 0 ? 1 : dim_z; 2413 2414 // Use data extractor to format output 2415 const uint32_t archByteSize = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize(); 2416 DataExtractor alloc_data(buffer.get(), size, GetProcess()->GetByteOrder(), archByteSize); 2417 2418 unsigned int offset = 0; // Offset in buffer to next element to be printed 2419 unsigned int prev_row = 0; // Offset to the start of the previous row 2420 2421 // Iterate over allocation dimensions, printing results to user 2422 strm.Printf("Data (X, Y, Z):"); 2423 for (unsigned int z = 0; z < dim_z; ++z) 2424 { 2425 for (unsigned int y = 0; y < dim_y; ++y) 2426 { 2427 // Use stride to index start of next row. 2428 if (!(y==0 && z==0)) 2429 offset = prev_row + stride; 2430 prev_row = offset; 2431 2432 // Print each element in the row individually 2433 for (unsigned int x = 0; x < dim_x; ++x) 2434 { 2435 strm.Printf("\n(%u, %u, %u) = ", x, y, z); 2436 if ((type == Element::RS_TYPE_NONE) && (alloc->element.children.size() > 0) && 2437 (alloc->element.type_name != Element::GetFallbackStructName())) 2438 { 2439 // Here we are dumping an Element of struct type. 2440 // This is done using expression evaluation with the name of the struct type and pointer to element. 2441 2442 // Don't print the name of the resulting expression, since this will be '$[0-9]+' 2443 DumpValueObjectOptions expr_options; 2444 expr_options.SetHideName(true); 2445 2446 // Setup expression as derefrencing a pointer cast to element address. 2447 const int max_expr_size = 512; 2448 char expr_char_buffer[max_expr_size]; 2449 int chars_written = snprintf(expr_char_buffer, max_expr_size, "*(%s*) 0x%" PRIx64, 2450 alloc->element.type_name.AsCString(), *alloc->data_ptr.get() + offset); 2451 2452 if (chars_written < 0 || chars_written >= max_expr_size) 2453 { 2454 if (log) 2455 log->Printf("RenderScriptRuntime::DumpAllocation- Error in snprintf()"); 2456 continue; 2457 } 2458 2459 // Evaluate expression 2460 ValueObjectSP expr_result; 2461 GetProcess()->GetTarget().EvaluateExpression(expr_char_buffer, frame_ptr, expr_result); 2462 2463 // Print the results to our stream. 2464 expr_result->Dump(strm, expr_options); 2465 } 2466 else 2467 { 2468 alloc_data.Dump(&strm, offset, format, data_size - padding, 1, 1, LLDB_INVALID_ADDRESS, 0, 0); 2469 } 2470 offset += data_size; 2471 } 2472 } 2473 } 2474 strm.EOL(); 2475 2476 return true; 2477 } 2478 2479 // Prints infomation regarding all the currently loaded allocations. 2480 // These details are gathered by jitting the runtime, which has as latency. 2481 void 2482 RenderScriptRuntime::ListAllocations(Stream &strm, StackFrame* frame_ptr, bool recompute) 2483 { 2484 strm.Printf("RenderScript Allocations:"); 2485 strm.EOL(); 2486 strm.IndentMore(); 2487 2488 for (auto &alloc : m_allocations) 2489 { 2490 // JIT the allocation info if we haven't done it, or the user forces us to. 2491 bool do_refresh = !alloc->data_ptr.isValid() || recompute; 2492 2493 // JIT current allocation information 2494 if (do_refresh && !RefreshAllocation(alloc.get(), frame_ptr)) 2495 { 2496 strm.Printf("Error: Couldn't evaluate details for allocation %u\n", alloc->id); 2497 continue; 2498 } 2499 2500 strm.Printf("%u:\n",alloc->id); 2501 strm.IndentMore(); 2502 2503 strm.Indent("Context: "); 2504 if (!alloc->context.isValid()) 2505 strm.Printf("unknown\n"); 2506 else 2507 strm.Printf("0x%" PRIx64 "\n", *alloc->context.get()); 2508 2509 strm.Indent("Address: "); 2510 if (!alloc->address.isValid()) 2511 strm.Printf("unknown\n"); 2512 else 2513 strm.Printf("0x%" PRIx64 "\n", *alloc->address.get()); 2514 2515 strm.Indent("Data pointer: "); 2516 if (!alloc->data_ptr.isValid()) 2517 strm.Printf("unknown\n"); 2518 else 2519 strm.Printf("0x%" PRIx64 "\n", *alloc->data_ptr.get()); 2520 2521 strm.Indent("Dimensions: "); 2522 if (!alloc->dimension.isValid()) 2523 strm.Printf("unknown\n"); 2524 else 2525 strm.Printf("(%d, %d, %d)\n", alloc->dimension.get()->dim_1, 2526 alloc->dimension.get()->dim_2, 2527 alloc->dimension.get()->dim_3); 2528 2529 strm.Indent("Data Type: "); 2530 if (!alloc->element.type.isValid() || !alloc->element.type_vec_size.isValid()) 2531 strm.Printf("unknown\n"); 2532 else 2533 { 2534 const int vector_size = *alloc->element.type_vec_size.get(); 2535 const Element::DataType type = *alloc->element.type.get(); 2536 2537 if (!alloc->element.type_name.IsEmpty()) 2538 strm.Printf("%s\n", alloc->element.type_name.AsCString()); 2539 else if (vector_size > 4 || vector_size < 1 || 2540 type < Element::RS_TYPE_NONE || type > Element::RS_TYPE_BOOLEAN) 2541 strm.Printf("invalid type\n"); 2542 else 2543 strm.Printf("%s\n", AllocationDetails::RsDataTypeToString[static_cast<unsigned int>(type)][vector_size-1]); 2544 } 2545 2546 strm.Indent("Data Kind: "); 2547 if (!alloc->element.type_kind.isValid()) 2548 strm.Printf("unknown\n"); 2549 else 2550 { 2551 const Element::DataKind kind = *alloc->element.type_kind.get(); 2552 if (kind < Element::RS_KIND_USER || kind > Element::RS_KIND_PIXEL_YUV) 2553 strm.Printf("invalid kind\n"); 2554 else 2555 strm.Printf("%s\n", AllocationDetails::RsDataKindToString[static_cast<unsigned int>(kind)]); 2556 } 2557 2558 strm.EOL(); 2559 strm.IndentLess(); 2560 } 2561 strm.IndentLess(); 2562 } 2563 2564 // Set breakpoints on every kernel found in RS module 2565 void 2566 RenderScriptRuntime::BreakOnModuleKernels(const RSModuleDescriptorSP rsmodule_sp) 2567 { 2568 for (const auto &kernel : rsmodule_sp->m_kernels) 2569 { 2570 // Don't set breakpoint on 'root' kernel 2571 if (strcmp(kernel.m_name.AsCString(), "root") == 0) 2572 continue; 2573 2574 CreateKernelBreakpoint(kernel.m_name); 2575 } 2576 } 2577 2578 // Method is internally called by the 'kernel breakpoint all' command to 2579 // enable or disable breaking on all kernels. 2580 // 2581 // When do_break is true we want to enable this functionality. 2582 // When do_break is false we want to disable it. 2583 void 2584 RenderScriptRuntime::SetBreakAllKernels(bool do_break, TargetSP target) 2585 { 2586 Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS)); 2587 2588 InitSearchFilter(target); 2589 2590 // Set breakpoints on all the kernels 2591 if (do_break && !m_breakAllKernels) 2592 { 2593 m_breakAllKernels = true; 2594 2595 for (const auto &module : m_rsmodules) 2596 BreakOnModuleKernels(module); 2597 2598 if (log) 2599 log->Printf("RenderScriptRuntime::SetBreakAllKernels(True)" 2600 "- breakpoints set on all currently loaded kernels"); 2601 } 2602 else if (!do_break && m_breakAllKernels) // Breakpoints won't be set on any new kernels. 2603 { 2604 m_breakAllKernels = false; 2605 2606 if (log) 2607 log->Printf("RenderScriptRuntime::SetBreakAllKernels(False) - breakpoints no longer automatically set"); 2608 } 2609 } 2610 2611 // Given the name of a kernel this function creates a breakpoint using our 2612 // own breakpoint resolver, and returns the Breakpoint shared pointer. 2613 BreakpointSP 2614 RenderScriptRuntime::CreateKernelBreakpoint(const ConstString& name) 2615 { 2616 Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS)); 2617 2618 if (!m_filtersp) 2619 { 2620 if (log) 2621 log->Printf("RenderScriptRuntime::CreateKernelBreakpoint - Error: No breakpoint search filter set"); 2622 return nullptr; 2623 } 2624 2625 BreakpointResolverSP resolver_sp(new RSBreakpointResolver(nullptr, name)); 2626 BreakpointSP bp = GetProcess()->GetTarget().CreateBreakpoint(m_filtersp, resolver_sp, false, false, false); 2627 2628 // Give RS breakpoints a specific name, so the user can manipulate them as a group. 2629 Error err; 2630 if (!bp->AddName("RenderScriptKernel", err) && log) 2631 log->Printf("RenderScriptRuntime::CreateKernelBreakpoint: Error setting break name, %s", err.AsCString()); 2632 2633 return bp; 2634 } 2635 2636 // Given an expression for a variable this function tries to calculate the variable's value. 2637 // If this is possible it returns true and sets the uint64_t parameter to the variables unsigned value. 2638 // Otherwise function returns false. 2639 bool 2640 RenderScriptRuntime::GetFrameVarAsUnsigned(const StackFrameSP frame_sp, const char* var_name, uint64_t& val) 2641 { 2642 Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 2643 Error error; 2644 VariableSP var_sp; 2645 2646 // Find variable in stack frame 2647 ValueObjectSP value_sp(frame_sp->GetValueForVariableExpressionPath(var_name, 2648 eNoDynamicValues, 2649 StackFrame::eExpressionPathOptionCheckPtrVsMember | 2650 StackFrame::eExpressionPathOptionsAllowDirectIVarAccess, 2651 var_sp, 2652 error)); 2653 if (!error.Success()) 2654 { 2655 if (log) 2656 log->Printf("RenderScriptRuntime::GetFrameVarAsUnsigned - Error, couldn't find '%s' in frame", var_name); 2657 2658 return false; 2659 } 2660 2661 // Find the unsigned int value for the variable 2662 bool success = false; 2663 val = value_sp->GetValueAsUnsigned(0, &success); 2664 if (!success) 2665 { 2666 if (log) 2667 log->Printf("RenderScriptRuntime::GetFrameVarAsUnsigned - Error, couldn't parse '%s' as an unsigned int", var_name); 2668 2669 return false; 2670 } 2671 2672 return true; 2673 } 2674 2675 // Callback when a kernel breakpoint hits and we're looking for a specific coordinate. 2676 // Baton parameter contains a pointer to the target coordinate we want to break on. 2677 // Function then checks the .expand frame for the current coordinate and breaks to user if it matches. 2678 // Parameter 'break_id' is the id of the Breakpoint which made the callback. 2679 // Parameter 'break_loc_id' is the id for the BreakpointLocation which was hit, 2680 // a single logical breakpoint can have multiple addresses. 2681 bool 2682 RenderScriptRuntime::KernelBreakpointHit(void *baton, StoppointCallbackContext *ctx, 2683 user_id_t break_id, user_id_t break_loc_id) 2684 { 2685 Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS)); 2686 2687 assert(baton && "Error: null baton in conditional kernel breakpoint callback"); 2688 2689 // Coordinate we want to stop on 2690 const int* target_coord = static_cast<const int*>(baton); 2691 2692 if (log) 2693 log->Printf("RenderScriptRuntime::KernelBreakpointHit - Break ID %" PRIu64 ", target coord (%d, %d, %d)", 2694 break_id, target_coord[0], target_coord[1], target_coord[2]); 2695 2696 // Go up one stack frame to .expand kernel 2697 ExecutionContext context(ctx->exe_ctx_ref); 2698 ThreadSP thread_sp = context.GetThreadSP(); 2699 if (!thread_sp->SetSelectedFrameByIndex(1)) 2700 { 2701 if (log) 2702 log->Printf("RenderScriptRuntime::KernelBreakpointHit - Error, couldn't go up stack frame"); 2703 2704 return false; 2705 } 2706 2707 StackFrameSP frame_sp = thread_sp->GetSelectedFrame(); 2708 if (!frame_sp) 2709 { 2710 if (log) 2711 log->Printf("RenderScriptRuntime::KernelBreakpointHit - Error, couldn't select .expand stack frame"); 2712 2713 return false; 2714 } 2715 2716 // Get values for variables in .expand frame that tell us the current kernel invocation 2717 const char* coord_expressions[] = {"rsIndex", "p->current.y", "p->current.z"}; 2718 uint64_t current_coord[3] = {0, 0, 0}; 2719 2720 for(int i = 0; i < 3; ++i) 2721 { 2722 if (!GetFrameVarAsUnsigned(frame_sp, coord_expressions[i], current_coord[i])) 2723 return false; 2724 2725 if (log) 2726 log->Printf("RenderScriptRuntime::KernelBreakpointHit, %s = %" PRIu64, coord_expressions[i], current_coord[i]); 2727 } 2728 2729 // Check if the current kernel invocation coordinate matches our target coordinate 2730 if (current_coord[0] == static_cast<uint64_t>(target_coord[0]) && 2731 current_coord[1] == static_cast<uint64_t>(target_coord[1]) && 2732 current_coord[2] == static_cast<uint64_t>(target_coord[2])) 2733 { 2734 if (log) 2735 log->Printf("RenderScriptRuntime::KernelBreakpointHit, BREAKING %" PRIu64 ", %" PRIu64 ", %" PRIu64, 2736 current_coord[0], current_coord[1], current_coord[2]); 2737 2738 BreakpointSP breakpoint_sp = context.GetTargetPtr()->GetBreakpointByID(break_id); 2739 assert(breakpoint_sp != nullptr && "Error: Couldn't find breakpoint matching break id for callback"); 2740 breakpoint_sp->SetEnabled(false); // Optimise since conditional breakpoint should only be hit once. 2741 return true; 2742 } 2743 2744 // No match on coordinate 2745 return false; 2746 } 2747 2748 // Tries to set a breakpoint on the start of a kernel, resolved using the kernel name. 2749 // Argument 'coords', represents a three dimensional coordinate which can be used to specify 2750 // a single kernel instance to break on. If this is set then we add a callback to the breakpoint. 2751 void 2752 RenderScriptRuntime::PlaceBreakpointOnKernel(Stream &strm, const char* name, const std::array<int,3> coords, 2753 Error& error, TargetSP target) 2754 { 2755 if (!name) 2756 { 2757 error.SetErrorString("invalid kernel name"); 2758 return; 2759 } 2760 2761 InitSearchFilter(target); 2762 2763 ConstString kernel_name(name); 2764 BreakpointSP bp = CreateKernelBreakpoint(kernel_name); 2765 2766 // We have a conditional breakpoint on a specific coordinate 2767 if (coords[0] != -1) 2768 { 2769 strm.Printf("Conditional kernel breakpoint on coordinate %d, %d, %d", coords[0], coords[1], coords[2]); 2770 strm.EOL(); 2771 2772 // Allocate memory for the baton, and copy over coordinate 2773 int* baton = new int[3]; 2774 baton[0] = coords[0]; baton[1] = coords[1]; baton[2] = coords[2]; 2775 2776 // Create a callback that will be invoked everytime the breakpoint is hit. 2777 // The baton object passed to the handler is the target coordinate we want to break on. 2778 bp->SetCallback(KernelBreakpointHit, baton, true); 2779 2780 // Store a shared pointer to the baton, so the memory will eventually be cleaned up after destruction 2781 m_conditional_breaks[bp->GetID()] = std::shared_ptr<int>(baton); 2782 } 2783 2784 if (bp) 2785 bp->GetDescription(&strm, lldb::eDescriptionLevelInitial, false); 2786 } 2787 2788 void 2789 RenderScriptRuntime::DumpModules(Stream &strm) const 2790 { 2791 strm.Printf("RenderScript Modules:"); 2792 strm.EOL(); 2793 strm.IndentMore(); 2794 for (const auto &module : m_rsmodules) 2795 { 2796 module->Dump(strm); 2797 } 2798 strm.IndentLess(); 2799 } 2800 2801 RenderScriptRuntime::ScriptDetails* 2802 RenderScriptRuntime::LookUpScript(addr_t address, bool create) 2803 { 2804 for (const auto & s : m_scripts) 2805 { 2806 if (s->script.isValid()) 2807 if (*s->script == address) 2808 return s.get(); 2809 } 2810 if (create) 2811 { 2812 std::unique_ptr<ScriptDetails> s(new ScriptDetails); 2813 s->script = address; 2814 m_scripts.push_back(std::move(s)); 2815 return m_scripts.back().get(); 2816 } 2817 return nullptr; 2818 } 2819 2820 RenderScriptRuntime::AllocationDetails* 2821 RenderScriptRuntime::LookUpAllocation(addr_t address, bool create) 2822 { 2823 for (const auto & a : m_allocations) 2824 { 2825 if (a->address.isValid()) 2826 if (*a->address == address) 2827 return a.get(); 2828 } 2829 if (create) 2830 { 2831 std::unique_ptr<AllocationDetails> a(new AllocationDetails); 2832 a->address = address; 2833 m_allocations.push_back(std::move(a)); 2834 return m_allocations.back().get(); 2835 } 2836 return nullptr; 2837 } 2838 2839 void 2840 RSModuleDescriptor::Dump(Stream &strm) const 2841 { 2842 strm.Indent(); 2843 m_module->GetFileSpec().Dump(&strm); 2844 if(m_module->GetNumCompileUnits()) 2845 { 2846 strm.Indent("Debug info loaded."); 2847 } 2848 else 2849 { 2850 strm.Indent("Debug info does not exist."); 2851 } 2852 strm.EOL(); 2853 strm.IndentMore(); 2854 strm.Indent(); 2855 strm.Printf("Globals: %" PRIu64, static_cast<uint64_t>(m_globals.size())); 2856 strm.EOL(); 2857 strm.IndentMore(); 2858 for (const auto &global : m_globals) 2859 { 2860 global.Dump(strm); 2861 } 2862 strm.IndentLess(); 2863 strm.Indent(); 2864 strm.Printf("Kernels: %" PRIu64, static_cast<uint64_t>(m_kernels.size())); 2865 strm.EOL(); 2866 strm.IndentMore(); 2867 for (const auto &kernel : m_kernels) 2868 { 2869 kernel.Dump(strm); 2870 } 2871 strm.Printf("Pragmas: %" PRIu64 , static_cast<uint64_t>(m_pragmas.size())); 2872 strm.EOL(); 2873 strm.IndentMore(); 2874 for (const auto &key_val : m_pragmas) 2875 { 2876 strm.Printf("%s: %s", key_val.first.c_str(), key_val.second.c_str()); 2877 strm.EOL(); 2878 } 2879 strm.IndentLess(4); 2880 } 2881 2882 void 2883 RSGlobalDescriptor::Dump(Stream &strm) const 2884 { 2885 strm.Indent(m_name.AsCString()); 2886 VariableList var_list; 2887 m_module->m_module->FindGlobalVariables(m_name, nullptr, true, 1U, var_list); 2888 if (var_list.GetSize() == 1) 2889 { 2890 auto var = var_list.GetVariableAtIndex(0); 2891 auto type = var->GetType(); 2892 if(type) 2893 { 2894 strm.Printf(" - "); 2895 type->DumpTypeName(&strm); 2896 } 2897 else 2898 { 2899 strm.Printf(" - Unknown Type"); 2900 } 2901 } 2902 else 2903 { 2904 strm.Printf(" - variable identified, but not found in binary"); 2905 const Symbol* s = m_module->m_module->FindFirstSymbolWithNameAndType(m_name, eSymbolTypeData); 2906 if (s) 2907 { 2908 strm.Printf(" (symbol exists) "); 2909 } 2910 } 2911 2912 strm.EOL(); 2913 } 2914 2915 void 2916 RSKernelDescriptor::Dump(Stream &strm) const 2917 { 2918 strm.Indent(m_name.AsCString()); 2919 strm.EOL(); 2920 } 2921 2922 class CommandObjectRenderScriptRuntimeModuleProbe : public CommandObjectParsed 2923 { 2924 public: 2925 CommandObjectRenderScriptRuntimeModuleProbe(CommandInterpreter &interpreter) 2926 : CommandObjectParsed(interpreter, "renderscript module probe", 2927 "Initiates a Probe of all loaded modules for kernels and other renderscript objects.", 2928 "renderscript module probe", 2929 eCommandRequiresTarget | eCommandRequiresProcess | eCommandProcessMustBeLaunched) 2930 { 2931 } 2932 2933 ~CommandObjectRenderScriptRuntimeModuleProbe() override = default; 2934 2935 bool 2936 DoExecute(Args &command, CommandReturnObject &result) override 2937 { 2938 const size_t argc = command.GetArgumentCount(); 2939 if (argc == 0) 2940 { 2941 Target *target = m_exe_ctx.GetTargetPtr(); 2942 RenderScriptRuntime *runtime = 2943 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); 2944 auto module_list = target->GetImages(); 2945 bool new_rs_details = runtime->ProbeModules(module_list); 2946 if (new_rs_details) 2947 { 2948 result.AppendMessage("New renderscript modules added to runtime model."); 2949 } 2950 result.SetStatus(eReturnStatusSuccessFinishResult); 2951 return true; 2952 } 2953 2954 result.AppendErrorWithFormat("'%s' takes no arguments", m_cmd_name.c_str()); 2955 result.SetStatus(eReturnStatusFailed); 2956 return false; 2957 } 2958 }; 2959 2960 class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed 2961 { 2962 public: 2963 CommandObjectRenderScriptRuntimeModuleDump(CommandInterpreter &interpreter) 2964 : CommandObjectParsed(interpreter, "renderscript module dump", 2965 "Dumps renderscript specific information for all modules.", "renderscript module dump", 2966 eCommandRequiresProcess | eCommandProcessMustBeLaunched) 2967 { 2968 } 2969 2970 ~CommandObjectRenderScriptRuntimeModuleDump() override = default; 2971 2972 bool 2973 DoExecute(Args &command, CommandReturnObject &result) override 2974 { 2975 RenderScriptRuntime *runtime = 2976 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); 2977 runtime->DumpModules(result.GetOutputStream()); 2978 result.SetStatus(eReturnStatusSuccessFinishResult); 2979 return true; 2980 } 2981 }; 2982 2983 class CommandObjectRenderScriptRuntimeModule : public CommandObjectMultiword 2984 { 2985 public: 2986 CommandObjectRenderScriptRuntimeModule(CommandInterpreter &interpreter) 2987 : CommandObjectMultiword(interpreter, "renderscript module", "Commands that deal with renderscript modules.", 2988 NULL) 2989 { 2990 LoadSubCommand("probe", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleProbe(interpreter))); 2991 LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleDump(interpreter))); 2992 } 2993 2994 ~CommandObjectRenderScriptRuntimeModule() override = default; 2995 }; 2996 2997 class CommandObjectRenderScriptRuntimeKernelList : public CommandObjectParsed 2998 { 2999 public: 3000 CommandObjectRenderScriptRuntimeKernelList(CommandInterpreter &interpreter) 3001 : CommandObjectParsed(interpreter, "renderscript kernel list", 3002 "Lists renderscript kernel names and associated script resources.", "renderscript kernel list", 3003 eCommandRequiresProcess | eCommandProcessMustBeLaunched) 3004 { 3005 } 3006 3007 ~CommandObjectRenderScriptRuntimeKernelList() override = default; 3008 3009 bool 3010 DoExecute(Args &command, CommandReturnObject &result) override 3011 { 3012 RenderScriptRuntime *runtime = 3013 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); 3014 runtime->DumpKernels(result.GetOutputStream()); 3015 result.SetStatus(eReturnStatusSuccessFinishResult); 3016 return true; 3017 } 3018 }; 3019 3020 class CommandObjectRenderScriptRuntimeKernelBreakpointSet : public CommandObjectParsed 3021 { 3022 public: 3023 CommandObjectRenderScriptRuntimeKernelBreakpointSet(CommandInterpreter &interpreter) 3024 : CommandObjectParsed(interpreter, "renderscript kernel breakpoint set", 3025 "Sets a breakpoint on a renderscript kernel.", "renderscript kernel breakpoint set <kernel_name> [-c x,y,z]", 3026 eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), m_options(interpreter) 3027 { 3028 } 3029 3030 ~CommandObjectRenderScriptRuntimeKernelBreakpointSet() override = default; 3031 3032 Options* 3033 GetOptions() override 3034 { 3035 return &m_options; 3036 } 3037 3038 class CommandOptions : public Options 3039 { 3040 public: 3041 CommandOptions(CommandInterpreter &interpreter) : Options(interpreter) 3042 { 3043 } 3044 3045 ~CommandOptions() override = default; 3046 3047 Error 3048 SetOptionValue(uint32_t option_idx, const char *option_arg) override 3049 { 3050 Error error; 3051 const int short_option = m_getopt_table[option_idx].val; 3052 3053 switch (short_option) 3054 { 3055 case 'c': 3056 if (!ParseCoordinate(option_arg)) 3057 error.SetErrorStringWithFormat("Couldn't parse coordinate '%s', should be in format 'x,y,z'.", option_arg); 3058 break; 3059 default: 3060 error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); 3061 break; 3062 } 3063 return error; 3064 } 3065 3066 // -c takes an argument of the form 'num[,num][,num]'. 3067 // Where 'id_cstr' is this argument with the whitespace trimmed. 3068 // Missing coordinates are defaulted to zero. 3069 bool 3070 ParseCoordinate(const char* id_cstr) 3071 { 3072 RegularExpression regex; 3073 RegularExpression::Match regex_match(3); 3074 3075 bool matched = false; 3076 if(regex.Compile("^([0-9]+),([0-9]+),([0-9]+)$") && regex.Execute(id_cstr, ®ex_match)) 3077 matched = true; 3078 else if(regex.Compile("^([0-9]+),([0-9]+)$") && regex.Execute(id_cstr, ®ex_match)) 3079 matched = true; 3080 else if(regex.Compile("^([0-9]+)$") && regex.Execute(id_cstr, ®ex_match)) 3081 matched = true; 3082 for(uint32_t i = 0; i < 3; i++) 3083 { 3084 std::string group; 3085 if(regex_match.GetMatchAtIndex(id_cstr, i + 1, group)) 3086 m_coord[i] = (uint32_t)strtoul(group.c_str(), NULL, 0); 3087 else 3088 m_coord[i] = 0; 3089 } 3090 return matched; 3091 } 3092 3093 void 3094 OptionParsingStarting() override 3095 { 3096 // -1 means the -c option hasn't been set 3097 m_coord[0] = -1; 3098 m_coord[1] = -1; 3099 m_coord[2] = -1; 3100 } 3101 3102 const OptionDefinition* 3103 GetDefinitions() override 3104 { 3105 return g_option_table; 3106 } 3107 3108 static OptionDefinition g_option_table[]; 3109 std::array<int,3> m_coord; 3110 }; 3111 3112 bool 3113 DoExecute(Args &command, CommandReturnObject &result) override 3114 { 3115 const size_t argc = command.GetArgumentCount(); 3116 if (argc < 1) 3117 { 3118 result.AppendErrorWithFormat("'%s' takes 1 argument of kernel name, and an optional coordinate.", m_cmd_name.c_str()); 3119 result.SetStatus(eReturnStatusFailed); 3120 return false; 3121 } 3122 3123 RenderScriptRuntime *runtime = 3124 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); 3125 3126 Error error; 3127 runtime->PlaceBreakpointOnKernel(result.GetOutputStream(), command.GetArgumentAtIndex(0), m_options.m_coord, 3128 error, m_exe_ctx.GetTargetSP()); 3129 3130 if (error.Success()) 3131 { 3132 result.AppendMessage("Breakpoint(s) created"); 3133 result.SetStatus(eReturnStatusSuccessFinishResult); 3134 return true; 3135 } 3136 result.SetStatus(eReturnStatusFailed); 3137 result.AppendErrorWithFormat("Error: %s", error.AsCString()); 3138 return false; 3139 } 3140 3141 private: 3142 CommandOptions m_options; 3143 }; 3144 3145 OptionDefinition 3146 CommandObjectRenderScriptRuntimeKernelBreakpointSet::CommandOptions::g_option_table[] = 3147 { 3148 { LLDB_OPT_SET_1, false, "coordinate", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeValue, 3149 "Set a breakpoint on a single invocation of the kernel with specified coordinate.\n" 3150 "Coordinate takes the form 'x[,y][,z] where x,y,z are positive integers representing kernel dimensions. " 3151 "Any unset dimensions will be defaulted to zero."}, 3152 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 3153 }; 3154 3155 class CommandObjectRenderScriptRuntimeKernelBreakpointAll : public CommandObjectParsed 3156 { 3157 public: 3158 CommandObjectRenderScriptRuntimeKernelBreakpointAll(CommandInterpreter &interpreter) 3159 : CommandObjectParsed(interpreter, "renderscript kernel breakpoint all", 3160 "Automatically sets a breakpoint on all renderscript kernels that are or will be loaded.\n" 3161 "Disabling option means breakpoints will no longer be set on any kernels loaded in the future, " 3162 "but does not remove currently set breakpoints.", 3163 "renderscript kernel breakpoint all <enable/disable>", 3164 eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) 3165 { 3166 } 3167 3168 ~CommandObjectRenderScriptRuntimeKernelBreakpointAll() override = default; 3169 3170 bool 3171 DoExecute(Args &command, CommandReturnObject &result) override 3172 { 3173 const size_t argc = command.GetArgumentCount(); 3174 if (argc != 1) 3175 { 3176 result.AppendErrorWithFormat("'%s' takes 1 argument of 'enable' or 'disable'", m_cmd_name.c_str()); 3177 result.SetStatus(eReturnStatusFailed); 3178 return false; 3179 } 3180 3181 RenderScriptRuntime *runtime = 3182 static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); 3183 3184 bool do_break = false; 3185 const char* argument = command.GetArgumentAtIndex(0); 3186 if (strcmp(argument, "enable") == 0) 3187 { 3188 do_break = true; 3189 result.AppendMessage("Breakpoints will be set on all kernels."); 3190 } 3191 else if (strcmp(argument, "disable") == 0) 3192 { 3193 do_break = false; 3194 result.AppendMessage("Breakpoints will not be set on any new kernels."); 3195 } 3196 else 3197 { 3198 result.AppendErrorWithFormat("Argument must be either 'enable' or 'disable'"); 3199 result.SetStatus(eReturnStatusFailed); 3200 return false; 3201 } 3202 3203 runtime->SetBreakAllKernels(do_break, m_exe_ctx.GetTargetSP()); 3204 3205 result.SetStatus(eReturnStatusSuccessFinishResult); 3206 return true; 3207 } 3208 }; 3209 3210 class CommandObjectRenderScriptRuntimeKernelBreakpoint : public CommandObjectMultiword 3211 { 3212 public: 3213 CommandObjectRenderScriptRuntimeKernelBreakpoint(CommandInterpreter &interpreter) 3214 : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that generate breakpoints on renderscript kernels.", 3215 nullptr) 3216 { 3217 LoadSubCommand("set", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointSet(interpreter))); 3218 LoadSubCommand("all", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointAll(interpreter))); 3219 } 3220 3221 ~CommandObjectRenderScriptRuntimeKernelBreakpoint() override = default; 3222 }; 3223 3224 class CommandObjectRenderScriptRuntimeKernel : public CommandObjectMultiword 3225 { 3226 public: 3227 CommandObjectRenderScriptRuntimeKernel(CommandInterpreter &interpreter) 3228 : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that deal with renderscript kernels.", 3229 NULL) 3230 { 3231 LoadSubCommand("list", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelList(interpreter))); 3232 LoadSubCommand("breakpoint", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpoint(interpreter))); 3233 } 3234 3235 ~CommandObjectRenderScriptRuntimeKernel() override = default; 3236 }; 3237 3238 class CommandObjectRenderScriptRuntimeContextDump : public CommandObjectParsed 3239 { 3240 public: 3241 CommandObjectRenderScriptRuntimeContextDump(CommandInterpreter &interpreter) 3242 : CommandObjectParsed(interpreter, "renderscript context dump", 3243 "Dumps renderscript context information.", "renderscript context dump", 3244 eCommandRequiresProcess | eCommandProcessMustBeLaunched) 3245 { 3246 } 3247 3248 ~CommandObjectRenderScriptRuntimeContextDump() override = default; 3249 3250 bool 3251 DoExecute(Args &command, CommandReturnObject &result) override 3252 { 3253 RenderScriptRuntime *runtime = 3254 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); 3255 runtime->DumpContexts(result.GetOutputStream()); 3256 result.SetStatus(eReturnStatusSuccessFinishResult); 3257 return true; 3258 } 3259 }; 3260 3261 class CommandObjectRenderScriptRuntimeContext : public CommandObjectMultiword 3262 { 3263 public: 3264 CommandObjectRenderScriptRuntimeContext(CommandInterpreter &interpreter) 3265 : CommandObjectMultiword(interpreter, "renderscript context", "Commands that deal with renderscript contexts.", 3266 NULL) 3267 { 3268 LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeContextDump(interpreter))); 3269 } 3270 3271 ~CommandObjectRenderScriptRuntimeContext() override = default; 3272 }; 3273 3274 class CommandObjectRenderScriptRuntimeAllocationDump : public CommandObjectParsed 3275 { 3276 public: 3277 CommandObjectRenderScriptRuntimeAllocationDump(CommandInterpreter &interpreter) 3278 : CommandObjectParsed(interpreter, "renderscript allocation dump", 3279 "Displays the contents of a particular allocation", "renderscript allocation dump <ID>", 3280 eCommandRequiresProcess | eCommandProcessMustBeLaunched), m_options(interpreter) 3281 { 3282 } 3283 3284 ~CommandObjectRenderScriptRuntimeAllocationDump() override = default; 3285 3286 Options* 3287 GetOptions() override 3288 { 3289 return &m_options; 3290 } 3291 3292 class CommandOptions : public Options 3293 { 3294 public: 3295 CommandOptions(CommandInterpreter &interpreter) : Options(interpreter) 3296 { 3297 } 3298 3299 ~CommandOptions() override = default; 3300 3301 Error 3302 SetOptionValue(uint32_t option_idx, const char *option_arg) override 3303 { 3304 Error error; 3305 const int short_option = m_getopt_table[option_idx].val; 3306 3307 switch (short_option) 3308 { 3309 case 'f': 3310 m_outfile.SetFile(option_arg, true); 3311 if (m_outfile.Exists()) 3312 { 3313 m_outfile.Clear(); 3314 error.SetErrorStringWithFormat("file already exists: '%s'", option_arg); 3315 } 3316 break; 3317 default: 3318 error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); 3319 break; 3320 } 3321 return error; 3322 } 3323 3324 void 3325 OptionParsingStarting() override 3326 { 3327 m_outfile.Clear(); 3328 } 3329 3330 const OptionDefinition* 3331 GetDefinitions() override 3332 { 3333 return g_option_table; 3334 } 3335 3336 static OptionDefinition g_option_table[]; 3337 FileSpec m_outfile; 3338 }; 3339 3340 bool 3341 DoExecute(Args &command, CommandReturnObject &result) override 3342 { 3343 const size_t argc = command.GetArgumentCount(); 3344 if (argc < 1) 3345 { 3346 result.AppendErrorWithFormat("'%s' takes 1 argument, an allocation ID. As well as an optional -f argument", 3347 m_cmd_name.c_str()); 3348 result.SetStatus(eReturnStatusFailed); 3349 return false; 3350 } 3351 3352 RenderScriptRuntime *runtime = 3353 static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); 3354 3355 const char* id_cstr = command.GetArgumentAtIndex(0); 3356 bool convert_complete = false; 3357 const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete); 3358 if (!convert_complete) 3359 { 3360 result.AppendErrorWithFormat("invalid allocation id argument '%s'", id_cstr); 3361 result.SetStatus(eReturnStatusFailed); 3362 return false; 3363 } 3364 3365 Stream* output_strm = nullptr; 3366 StreamFile outfile_stream; 3367 const FileSpec &outfile_spec = m_options.m_outfile; // Dump allocation to file instead 3368 if (outfile_spec) 3369 { 3370 // Open output file 3371 char path[256]; 3372 outfile_spec.GetPath(path, sizeof(path)); 3373 if (outfile_stream.GetFile().Open(path, File::eOpenOptionWrite | File::eOpenOptionCanCreate).Success()) 3374 { 3375 output_strm = &outfile_stream; 3376 result.GetOutputStream().Printf("Results written to '%s'", path); 3377 result.GetOutputStream().EOL(); 3378 } 3379 else 3380 { 3381 result.AppendErrorWithFormat("Couldn't open file '%s'", path); 3382 result.SetStatus(eReturnStatusFailed); 3383 return false; 3384 } 3385 } 3386 else 3387 output_strm = &result.GetOutputStream(); 3388 3389 assert(output_strm != nullptr); 3390 bool success = runtime->DumpAllocation(*output_strm, m_exe_ctx.GetFramePtr(), id); 3391 3392 if (success) 3393 result.SetStatus(eReturnStatusSuccessFinishResult); 3394 else 3395 result.SetStatus(eReturnStatusFailed); 3396 3397 return true; 3398 } 3399 3400 private: 3401 CommandOptions m_options; 3402 }; 3403 3404 OptionDefinition 3405 CommandObjectRenderScriptRuntimeAllocationDump::CommandOptions::g_option_table[] = 3406 { 3407 { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFilename, 3408 "Print results to specified file instead of command line."}, 3409 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 3410 }; 3411 3412 class CommandObjectRenderScriptRuntimeAllocationList : public CommandObjectParsed 3413 { 3414 public: 3415 CommandObjectRenderScriptRuntimeAllocationList(CommandInterpreter &interpreter) 3416 : CommandObjectParsed(interpreter, "renderscript allocation list", 3417 "List renderscript allocations and their information.", "renderscript allocation list", 3418 eCommandRequiresProcess | eCommandProcessMustBeLaunched), m_options(interpreter) 3419 { 3420 } 3421 3422 ~CommandObjectRenderScriptRuntimeAllocationList() override = default; 3423 3424 Options* 3425 GetOptions() override 3426 { 3427 return &m_options; 3428 } 3429 3430 class CommandOptions : public Options 3431 { 3432 public: 3433 CommandOptions(CommandInterpreter &interpreter) : Options(interpreter), m_refresh(false) 3434 { 3435 } 3436 3437 ~CommandOptions() override = default; 3438 3439 Error 3440 SetOptionValue(uint32_t option_idx, const char *option_arg) override 3441 { 3442 Error error; 3443 const int short_option = m_getopt_table[option_idx].val; 3444 3445 switch (short_option) 3446 { 3447 case 'r': 3448 m_refresh = true; 3449 break; 3450 default: 3451 error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); 3452 break; 3453 } 3454 return error; 3455 } 3456 3457 void 3458 OptionParsingStarting() override 3459 { 3460 m_refresh = false; 3461 } 3462 3463 const OptionDefinition* 3464 GetDefinitions() override 3465 { 3466 return g_option_table; 3467 } 3468 3469 static OptionDefinition g_option_table[]; 3470 bool m_refresh; 3471 }; 3472 3473 bool 3474 DoExecute(Args &command, CommandReturnObject &result) override 3475 { 3476 RenderScriptRuntime *runtime = 3477 static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); 3478 runtime->ListAllocations(result.GetOutputStream(), m_exe_ctx.GetFramePtr(), m_options.m_refresh); 3479 result.SetStatus(eReturnStatusSuccessFinishResult); 3480 return true; 3481 } 3482 3483 private: 3484 CommandOptions m_options; 3485 }; 3486 3487 OptionDefinition 3488 CommandObjectRenderScriptRuntimeAllocationList::CommandOptions::g_option_table[] = 3489 { 3490 { LLDB_OPT_SET_1, false, "refresh", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, 3491 "Recompute allocation details."}, 3492 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 3493 }; 3494 3495 class CommandObjectRenderScriptRuntimeAllocationLoad : public CommandObjectParsed 3496 { 3497 public: 3498 CommandObjectRenderScriptRuntimeAllocationLoad(CommandInterpreter &interpreter) 3499 : CommandObjectParsed(interpreter, "renderscript allocation load", 3500 "Loads renderscript allocation contents from a file.", "renderscript allocation load <ID> <filename>", 3501 eCommandRequiresProcess | eCommandProcessMustBeLaunched) 3502 { 3503 } 3504 3505 ~CommandObjectRenderScriptRuntimeAllocationLoad() override = default; 3506 3507 bool 3508 DoExecute(Args &command, CommandReturnObject &result) override 3509 { 3510 const size_t argc = command.GetArgumentCount(); 3511 if (argc != 2) 3512 { 3513 result.AppendErrorWithFormat("'%s' takes 2 arguments, an allocation ID and filename to read from.", m_cmd_name.c_str()); 3514 result.SetStatus(eReturnStatusFailed); 3515 return false; 3516 } 3517 3518 RenderScriptRuntime *runtime = 3519 static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); 3520 3521 const char* id_cstr = command.GetArgumentAtIndex(0); 3522 bool convert_complete = false; 3523 const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete); 3524 if (!convert_complete) 3525 { 3526 result.AppendErrorWithFormat ("invalid allocation id argument '%s'", id_cstr); 3527 result.SetStatus (eReturnStatusFailed); 3528 return false; 3529 } 3530 3531 const char* filename = command.GetArgumentAtIndex(1); 3532 bool success = runtime->LoadAllocation(result.GetOutputStream(), id, filename, m_exe_ctx.GetFramePtr()); 3533 3534 if (success) 3535 result.SetStatus(eReturnStatusSuccessFinishResult); 3536 else 3537 result.SetStatus(eReturnStatusFailed); 3538 3539 return true; 3540 } 3541 }; 3542 3543 class CommandObjectRenderScriptRuntimeAllocationSave : public CommandObjectParsed 3544 { 3545 public: 3546 CommandObjectRenderScriptRuntimeAllocationSave(CommandInterpreter &interpreter) 3547 : CommandObjectParsed(interpreter, "renderscript allocation save", 3548 "Write renderscript allocation contents to a file.", "renderscript allocation save <ID> <filename>", 3549 eCommandRequiresProcess | eCommandProcessMustBeLaunched) 3550 { 3551 } 3552 3553 ~CommandObjectRenderScriptRuntimeAllocationSave() override = default; 3554 3555 bool 3556 DoExecute(Args &command, CommandReturnObject &result) override 3557 { 3558 const size_t argc = command.GetArgumentCount(); 3559 if (argc != 2) 3560 { 3561 result.AppendErrorWithFormat("'%s' takes 2 arguments, an allocation ID and filename to read from.", m_cmd_name.c_str()); 3562 result.SetStatus(eReturnStatusFailed); 3563 return false; 3564 } 3565 3566 RenderScriptRuntime *runtime = 3567 static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); 3568 3569 const char* id_cstr = command.GetArgumentAtIndex(0); 3570 bool convert_complete = false; 3571 const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete); 3572 if (!convert_complete) 3573 { 3574 result.AppendErrorWithFormat ("invalid allocation id argument '%s'", id_cstr); 3575 result.SetStatus (eReturnStatusFailed); 3576 return false; 3577 } 3578 3579 const char* filename = command.GetArgumentAtIndex(1); 3580 bool success = runtime->SaveAllocation(result.GetOutputStream(), id, filename, m_exe_ctx.GetFramePtr()); 3581 3582 if (success) 3583 result.SetStatus(eReturnStatusSuccessFinishResult); 3584 else 3585 result.SetStatus(eReturnStatusFailed); 3586 3587 return true; 3588 } 3589 }; 3590 3591 class CommandObjectRenderScriptRuntimeAllocation : public CommandObjectMultiword 3592 { 3593 public: 3594 CommandObjectRenderScriptRuntimeAllocation(CommandInterpreter &interpreter) 3595 : CommandObjectMultiword(interpreter, "renderscript allocation", "Commands that deal with renderscript allocations.", 3596 NULL) 3597 { 3598 LoadSubCommand("list", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationList(interpreter))); 3599 LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationDump(interpreter))); 3600 LoadSubCommand("save", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationSave(interpreter))); 3601 LoadSubCommand("load", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationLoad(interpreter))); 3602 } 3603 3604 ~CommandObjectRenderScriptRuntimeAllocation() override = default; 3605 }; 3606 3607 class CommandObjectRenderScriptRuntimeStatus : public CommandObjectParsed 3608 { 3609 public: 3610 CommandObjectRenderScriptRuntimeStatus(CommandInterpreter &interpreter) 3611 : CommandObjectParsed(interpreter, "renderscript status", 3612 "Displays current renderscript runtime status.", "renderscript status", 3613 eCommandRequiresProcess | eCommandProcessMustBeLaunched) 3614 { 3615 } 3616 3617 ~CommandObjectRenderScriptRuntimeStatus() override = default; 3618 3619 bool 3620 DoExecute(Args &command, CommandReturnObject &result) override 3621 { 3622 RenderScriptRuntime *runtime = 3623 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); 3624 runtime->Status(result.GetOutputStream()); 3625 result.SetStatus(eReturnStatusSuccessFinishResult); 3626 return true; 3627 } 3628 }; 3629 3630 class CommandObjectRenderScriptRuntime : public CommandObjectMultiword 3631 { 3632 public: 3633 CommandObjectRenderScriptRuntime(CommandInterpreter &interpreter) 3634 : CommandObjectMultiword(interpreter, "renderscript", "A set of commands for operating on renderscript.", 3635 "renderscript <subcommand> [<subcommand-options>]") 3636 { 3637 LoadSubCommand("module", CommandObjectSP(new CommandObjectRenderScriptRuntimeModule(interpreter))); 3638 LoadSubCommand("status", CommandObjectSP(new CommandObjectRenderScriptRuntimeStatus(interpreter))); 3639 LoadSubCommand("kernel", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernel(interpreter))); 3640 LoadSubCommand("context", CommandObjectSP(new CommandObjectRenderScriptRuntimeContext(interpreter))); 3641 LoadSubCommand("allocation", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocation(interpreter))); 3642 } 3643 3644 ~CommandObjectRenderScriptRuntime() override = default; 3645 }; 3646 3647 void 3648 RenderScriptRuntime::Initiate() 3649 { 3650 assert(!m_initiated); 3651 } 3652 3653 RenderScriptRuntime::RenderScriptRuntime(Process *process) 3654 : lldb_private::CPPLanguageRuntime(process), m_initiated(false), m_debuggerPresentFlagged(false), 3655 m_breakAllKernels(false) 3656 { 3657 ModulesDidLoad(process->GetTarget().GetImages()); 3658 } 3659 3660 lldb::CommandObjectSP 3661 RenderScriptRuntime::GetCommandObject(lldb_private::CommandInterpreter& interpreter) 3662 { 3663 static CommandObjectSP command_object; 3664 if(!command_object) 3665 { 3666 command_object.reset(new CommandObjectRenderScriptRuntime(interpreter)); 3667 } 3668 return command_object; 3669 } 3670 3671 RenderScriptRuntime::~RenderScriptRuntime() = default; 3672