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