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