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