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