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