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