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