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