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