15ec532a9SColin Riley //===-- RenderScriptRuntime.cpp ---------------------------------*- C++ -*-===// 25ec532a9SColin Riley // 35ec532a9SColin Riley // The LLVM Compiler Infrastructure 45ec532a9SColin Riley // 55ec532a9SColin Riley // This file is distributed under the University of Illinois Open Source 65ec532a9SColin Riley // License. See LICENSE.TXT for details. 75ec532a9SColin Riley // 85ec532a9SColin Riley //===----------------------------------------------------------------------===// 95ec532a9SColin Riley 10222b937cSEugene Zelenko // C Includes 11222b937cSEugene Zelenko // C++ Includes 12222b937cSEugene Zelenko // Other libraries and framework includes 13222b937cSEugene Zelenko // Project includes 145ec532a9SColin Riley #include "RenderScriptRuntime.h" 155ec532a9SColin Riley 165ec532a9SColin Riley #include "lldb/Core/ConstString.h" 175ec532a9SColin Riley #include "lldb/Core/Debugger.h" 185ec532a9SColin Riley #include "lldb/Core/Error.h" 195ec532a9SColin Riley #include "lldb/Core/Log.h" 205ec532a9SColin Riley #include "lldb/Core/PluginManager.h" 218b244e21SEwan Crawford #include "lldb/Core/ValueObjectVariable.h" 22018f5a7eSEwan Crawford #include "lldb/Core/RegularExpression.h" 238b244e21SEwan Crawford #include "lldb/DataFormatters/DumpValueObjectOptions.h" 24a0f08674SEwan Crawford #include "lldb/Host/StringConvert.h" 255ec532a9SColin Riley #include "lldb/Symbol/Symbol.h" 264640cde1SColin Riley #include "lldb/Symbol/Type.h" 275ec532a9SColin Riley #include "lldb/Target/Process.h" 285ec532a9SColin Riley #include "lldb/Target/Target.h" 29018f5a7eSEwan Crawford #include "lldb/Target/Thread.h" 305ec532a9SColin Riley #include "lldb/Interpreter/Args.h" 315ec532a9SColin Riley #include "lldb/Interpreter/Options.h" 325ec532a9SColin Riley #include "lldb/Interpreter/CommandInterpreter.h" 335ec532a9SColin Riley #include "lldb/Interpreter/CommandReturnObject.h" 345ec532a9SColin Riley #include "lldb/Interpreter/CommandObjectMultiword.h" 354640cde1SColin Riley #include "lldb/Breakpoint/StoppointCallbackContext.h" 364640cde1SColin Riley #include "lldb/Target/RegisterContext.h" 3715f2bd95SEwan Crawford #include "lldb/Expression/UserExpression.h" 384640cde1SColin Riley #include "lldb/Symbol/VariableList.h" 395ec532a9SColin Riley 405ec532a9SColin Riley using namespace lldb; 415ec532a9SColin Riley using namespace lldb_private; 4298156583SEwan Crawford using namespace lldb_renderscript; 435ec532a9SColin Riley 4478f339d1SEwan Crawford namespace { 4578f339d1SEwan Crawford 4678f339d1SEwan Crawford // The empirical_type adds a basic level of validation to arbitrary data 4778f339d1SEwan Crawford // allowing us to track if data has been discovered and stored or not. 4878f339d1SEwan Crawford // An empirical_type will be marked as valid only if it has been explicitly assigned to. 4978f339d1SEwan Crawford template <typename type_t> 5078f339d1SEwan Crawford class empirical_type 5178f339d1SEwan Crawford { 5278f339d1SEwan Crawford public: 5378f339d1SEwan Crawford // Ctor. Contents is invalid when constructed. 5478f339d1SEwan Crawford empirical_type() 5578f339d1SEwan Crawford : valid(false) 5678f339d1SEwan Crawford {} 5778f339d1SEwan Crawford 5878f339d1SEwan Crawford // Return true and copy contents to out if valid, else return false. 5978f339d1SEwan Crawford bool get(type_t& out) const 6078f339d1SEwan Crawford { 6178f339d1SEwan Crawford if (valid) 6278f339d1SEwan Crawford out = data; 6378f339d1SEwan Crawford return valid; 6478f339d1SEwan Crawford } 6578f339d1SEwan Crawford 6678f339d1SEwan Crawford // Return a pointer to the contents or nullptr if it was not valid. 6778f339d1SEwan Crawford const type_t* get() const 6878f339d1SEwan Crawford { 6978f339d1SEwan Crawford return valid ? &data : nullptr; 7078f339d1SEwan Crawford } 7178f339d1SEwan Crawford 7278f339d1SEwan Crawford // Assign data explicitly. 7378f339d1SEwan Crawford void set(const type_t in) 7478f339d1SEwan Crawford { 7578f339d1SEwan Crawford data = in; 7678f339d1SEwan Crawford valid = true; 7778f339d1SEwan Crawford } 7878f339d1SEwan Crawford 7978f339d1SEwan Crawford // Mark contents as invalid. 8078f339d1SEwan Crawford void invalidate() 8178f339d1SEwan Crawford { 8278f339d1SEwan Crawford valid = false; 8378f339d1SEwan Crawford } 8478f339d1SEwan Crawford 8578f339d1SEwan Crawford // Returns true if this type contains valid data. 8678f339d1SEwan Crawford bool isValid() const 8778f339d1SEwan Crawford { 8878f339d1SEwan Crawford return valid; 8978f339d1SEwan Crawford } 9078f339d1SEwan Crawford 9178f339d1SEwan Crawford // Assignment operator. 9278f339d1SEwan Crawford empirical_type<type_t>& operator = (const type_t in) 9378f339d1SEwan Crawford { 9478f339d1SEwan Crawford set(in); 9578f339d1SEwan Crawford return *this; 9678f339d1SEwan Crawford } 9778f339d1SEwan Crawford 9878f339d1SEwan Crawford // Dereference operator returns contents. 9978f339d1SEwan Crawford // Warning: Will assert if not valid so use only when you know data is valid. 10078f339d1SEwan Crawford const type_t& operator * () const 10178f339d1SEwan Crawford { 10278f339d1SEwan Crawford assert(valid); 10378f339d1SEwan Crawford return data; 10478f339d1SEwan Crawford } 10578f339d1SEwan Crawford 10678f339d1SEwan Crawford protected: 10778f339d1SEwan Crawford bool valid; 10878f339d1SEwan Crawford type_t data; 10978f339d1SEwan Crawford }; 11078f339d1SEwan Crawford 111222b937cSEugene Zelenko } // anonymous namespace 11278f339d1SEwan Crawford 11378f339d1SEwan Crawford // The ScriptDetails class collects data associated with a single script instance. 11478f339d1SEwan Crawford struct RenderScriptRuntime::ScriptDetails 11578f339d1SEwan Crawford { 116222b937cSEugene Zelenko ~ScriptDetails() = default; 11778f339d1SEwan Crawford 11878f339d1SEwan Crawford enum ScriptType 11978f339d1SEwan Crawford { 12078f339d1SEwan Crawford eScript, 12178f339d1SEwan Crawford eScriptC 12278f339d1SEwan Crawford }; 12378f339d1SEwan Crawford 12478f339d1SEwan Crawford // The derived type of the script. 12578f339d1SEwan Crawford empirical_type<ScriptType> type; 12678f339d1SEwan Crawford // The name of the original source file. 12778f339d1SEwan Crawford empirical_type<std::string> resName; 12878f339d1SEwan Crawford // Path to script .so file on the device. 12978f339d1SEwan Crawford empirical_type<std::string> scriptDyLib; 13078f339d1SEwan Crawford // Directory where kernel objects are cached on device. 13178f339d1SEwan Crawford empirical_type<std::string> cacheDir; 13278f339d1SEwan Crawford // Pointer to the context which owns this script. 13378f339d1SEwan Crawford empirical_type<lldb::addr_t> context; 13478f339d1SEwan Crawford // Pointer to the script object itself. 13578f339d1SEwan Crawford empirical_type<lldb::addr_t> script; 13678f339d1SEwan Crawford }; 13778f339d1SEwan Crawford 1388b244e21SEwan Crawford // This Element class represents the Element object in RS, 1398b244e21SEwan Crawford // defining the type associated with an Allocation. 1408b244e21SEwan Crawford struct RenderScriptRuntime::Element 14178f339d1SEwan Crawford { 14215f2bd95SEwan Crawford // Taken from rsDefines.h 14315f2bd95SEwan Crawford enum DataKind 14415f2bd95SEwan Crawford { 14515f2bd95SEwan Crawford RS_KIND_USER, 14615f2bd95SEwan Crawford RS_KIND_PIXEL_L = 7, 14715f2bd95SEwan Crawford RS_KIND_PIXEL_A, 14815f2bd95SEwan Crawford RS_KIND_PIXEL_LA, 14915f2bd95SEwan Crawford RS_KIND_PIXEL_RGB, 15015f2bd95SEwan Crawford RS_KIND_PIXEL_RGBA, 15115f2bd95SEwan Crawford RS_KIND_PIXEL_DEPTH, 15215f2bd95SEwan Crawford RS_KIND_PIXEL_YUV, 15315f2bd95SEwan Crawford RS_KIND_INVALID = 100 15415f2bd95SEwan Crawford }; 15578f339d1SEwan Crawford 15615f2bd95SEwan Crawford // Taken from rsDefines.h 15778f339d1SEwan Crawford enum DataType 15878f339d1SEwan Crawford { 15915f2bd95SEwan Crawford RS_TYPE_NONE = 0, 16015f2bd95SEwan Crawford RS_TYPE_FLOAT_16, 16115f2bd95SEwan Crawford RS_TYPE_FLOAT_32, 16215f2bd95SEwan Crawford RS_TYPE_FLOAT_64, 16315f2bd95SEwan Crawford RS_TYPE_SIGNED_8, 16415f2bd95SEwan Crawford RS_TYPE_SIGNED_16, 16515f2bd95SEwan Crawford RS_TYPE_SIGNED_32, 16615f2bd95SEwan Crawford RS_TYPE_SIGNED_64, 16715f2bd95SEwan Crawford RS_TYPE_UNSIGNED_8, 16815f2bd95SEwan Crawford RS_TYPE_UNSIGNED_16, 16915f2bd95SEwan Crawford RS_TYPE_UNSIGNED_32, 17015f2bd95SEwan Crawford RS_TYPE_UNSIGNED_64, 1712e920715SEwan Crawford RS_TYPE_BOOLEAN, 1722e920715SEwan Crawford 1732e920715SEwan Crawford RS_TYPE_UNSIGNED_5_6_5, 1742e920715SEwan Crawford RS_TYPE_UNSIGNED_5_5_5_1, 1752e920715SEwan Crawford RS_TYPE_UNSIGNED_4_4_4_4, 1762e920715SEwan Crawford 1772e920715SEwan Crawford RS_TYPE_MATRIX_4X4, 1782e920715SEwan Crawford RS_TYPE_MATRIX_3X3, 1792e920715SEwan Crawford RS_TYPE_MATRIX_2X2, 1802e920715SEwan Crawford 1812e920715SEwan Crawford RS_TYPE_ELEMENT = 1000, 1822e920715SEwan Crawford RS_TYPE_TYPE, 1832e920715SEwan Crawford RS_TYPE_ALLOCATION, 1842e920715SEwan Crawford RS_TYPE_SAMPLER, 1852e920715SEwan Crawford RS_TYPE_SCRIPT, 1862e920715SEwan Crawford RS_TYPE_MESH, 1872e920715SEwan Crawford RS_TYPE_PROGRAM_FRAGMENT, 1882e920715SEwan Crawford RS_TYPE_PROGRAM_VERTEX, 1892e920715SEwan Crawford RS_TYPE_PROGRAM_RASTER, 1902e920715SEwan Crawford RS_TYPE_PROGRAM_STORE, 1912e920715SEwan Crawford RS_TYPE_FONT, 1922e920715SEwan Crawford 1932e920715SEwan Crawford RS_TYPE_INVALID = 10000 19478f339d1SEwan Crawford }; 19578f339d1SEwan Crawford 1968b244e21SEwan Crawford std::vector<Element> children; // Child Element fields for structs 1978b244e21SEwan Crawford empirical_type<lldb::addr_t> element_ptr; // Pointer to the RS Element of the Type 1988b244e21SEwan Crawford empirical_type<DataType> type; // Type of each data pointer stored by the allocation 1998b244e21SEwan Crawford empirical_type<DataKind> type_kind; // Defines pixel type if Allocation is created from an image 2008b244e21SEwan Crawford empirical_type<uint32_t> type_vec_size; // Vector size of each data point, e.g '4' for uchar4 2018b244e21SEwan Crawford empirical_type<uint32_t> field_count; // Number of Subelements 2028b244e21SEwan Crawford empirical_type<uint32_t> datum_size; // Size of a single Element with padding 2038b244e21SEwan Crawford empirical_type<uint32_t> padding; // Number of padding bytes 2048b244e21SEwan Crawford empirical_type<uint32_t> array_size; // Number of items in array, only needed for strucrs 2058b244e21SEwan Crawford ConstString type_name; // Name of type, only needed for structs 2068b244e21SEwan Crawford 207fe06b5adSAdrian McCarthy static const ConstString &GetFallbackStructName(); // Print this as the type name of a struct Element 2088b244e21SEwan Crawford // If we can't resolve the actual struct name 2098b59062aSEwan Crawford 2108b59062aSEwan Crawford bool shouldRefresh() const 2118b59062aSEwan Crawford { 2128b59062aSEwan Crawford const bool valid_ptr = element_ptr.isValid() && *element_ptr.get() != 0x0; 2138b59062aSEwan Crawford const bool valid_type = type.isValid() && type_vec_size.isValid() && type_kind.isValid(); 2148b59062aSEwan Crawford return !valid_ptr || !valid_type || !datum_size.isValid(); 2158b59062aSEwan Crawford } 2168b244e21SEwan Crawford }; 2178b244e21SEwan Crawford 2188b244e21SEwan Crawford // This AllocationDetails class collects data associated with a single 2198b244e21SEwan Crawford // allocation instance. 2208b244e21SEwan Crawford struct RenderScriptRuntime::AllocationDetails 2218b244e21SEwan Crawford { 22215f2bd95SEwan Crawford struct Dimension 22378f339d1SEwan Crawford { 22415f2bd95SEwan Crawford uint32_t dim_1; 22515f2bd95SEwan Crawford uint32_t dim_2; 22615f2bd95SEwan Crawford uint32_t dim_3; 22715f2bd95SEwan Crawford uint32_t cubeMap; 22815f2bd95SEwan Crawford 22915f2bd95SEwan Crawford Dimension() 23015f2bd95SEwan Crawford { 23115f2bd95SEwan Crawford dim_1 = 0; 23215f2bd95SEwan Crawford dim_2 = 0; 23315f2bd95SEwan Crawford dim_3 = 0; 23415f2bd95SEwan Crawford cubeMap = 0; 23515f2bd95SEwan Crawford } 23678f339d1SEwan Crawford }; 23778f339d1SEwan Crawford 23855232f09SEwan Crawford // Header for reading and writing allocation contents 23955232f09SEwan Crawford // to a binary file. 24055232f09SEwan Crawford struct FileHeader 24155232f09SEwan Crawford { 24255232f09SEwan Crawford uint8_t ident[4]; // ASCII 'RSAD' identifying the file 24355232f09SEwan Crawford uint16_t hdr_size; // Header size in bytes, for backwards compatability 24455232f09SEwan Crawford uint16_t type; // DataType enum 24555232f09SEwan Crawford uint32_t kind; // DataKind enum 24655232f09SEwan Crawford uint32_t dims[3]; // Dimensions 24755232f09SEwan Crawford uint32_t element_size; // Size of a single element, including padding 24855232f09SEwan Crawford }; 24955232f09SEwan Crawford 25015f2bd95SEwan Crawford // Monotonically increasing from 1 25115f2bd95SEwan Crawford static unsigned int ID; 25215f2bd95SEwan Crawford 25315f2bd95SEwan Crawford // Maps Allocation DataType enum and vector size to printable strings 25415f2bd95SEwan Crawford // using mapping from RenderScript numerical types summary documentation 25515f2bd95SEwan Crawford static const char* RsDataTypeToString[][4]; 25615f2bd95SEwan Crawford 25715f2bd95SEwan Crawford // Maps Allocation DataKind enum to printable strings 25815f2bd95SEwan Crawford static const char* RsDataKindToString[]; 25915f2bd95SEwan Crawford 260a0f08674SEwan Crawford // Maps allocation types to format sizes for printing. 261a0f08674SEwan Crawford static const unsigned int RSTypeToFormat[][3]; 262a0f08674SEwan Crawford 26315f2bd95SEwan Crawford // Give each allocation an ID as a way 26415f2bd95SEwan Crawford // for commands to reference it. 26515f2bd95SEwan Crawford const unsigned int id; 26615f2bd95SEwan Crawford 2678b244e21SEwan Crawford RenderScriptRuntime::Element element; // Allocation Element type 26815f2bd95SEwan Crawford empirical_type<Dimension> dimension; // Dimensions of the Allocation 26915f2bd95SEwan Crawford empirical_type<lldb::addr_t> address; // Pointer to address of the RS Allocation 27015f2bd95SEwan Crawford empirical_type<lldb::addr_t> data_ptr; // Pointer to the data held by the Allocation 27115f2bd95SEwan Crawford empirical_type<lldb::addr_t> type_ptr; // Pointer to the RS Type of the Allocation 27215f2bd95SEwan Crawford empirical_type<lldb::addr_t> context; // Pointer to the RS Context of the Allocation 273a0f08674SEwan Crawford empirical_type<uint32_t> size; // Size of the allocation 274a0f08674SEwan Crawford empirical_type<uint32_t> stride; // Stride between rows of the allocation 27515f2bd95SEwan Crawford 27615f2bd95SEwan Crawford // Give each allocation an id, so we can reference it in user commands. 27715f2bd95SEwan Crawford AllocationDetails(): id(ID++) 27815f2bd95SEwan Crawford { 27915f2bd95SEwan Crawford } 2808b59062aSEwan Crawford 2818b59062aSEwan Crawford bool shouldRefresh() const 2828b59062aSEwan Crawford { 2838b59062aSEwan Crawford bool valid_ptrs = data_ptr.isValid() && *data_ptr.get() != 0x0; 2848b59062aSEwan Crawford valid_ptrs = valid_ptrs && type_ptr.isValid() && *type_ptr.get() != 0x0; 2858b59062aSEwan Crawford return !valid_ptrs || !dimension.isValid() || !size.isValid() || element.shouldRefresh(); 2868b59062aSEwan Crawford } 28715f2bd95SEwan Crawford }; 28815f2bd95SEwan Crawford 289fe06b5adSAdrian McCarthy 290fe06b5adSAdrian McCarthy const ConstString & 291fe06b5adSAdrian McCarthy RenderScriptRuntime::Element::GetFallbackStructName() 292fe06b5adSAdrian McCarthy { 293fe06b5adSAdrian McCarthy static const ConstString FallbackStructName("struct"); 294fe06b5adSAdrian McCarthy return FallbackStructName; 295fe06b5adSAdrian McCarthy } 2968b244e21SEwan Crawford 29715f2bd95SEwan Crawford unsigned int RenderScriptRuntime::AllocationDetails::ID = 1; 29815f2bd95SEwan Crawford 29915f2bd95SEwan Crawford const char* RenderScriptRuntime::AllocationDetails::RsDataKindToString[] = 30015f2bd95SEwan Crawford { 30115f2bd95SEwan Crawford "User", 30215f2bd95SEwan Crawford "Undefined", "Undefined", "Undefined", // Enum jumps from 0 to 7 30315f2bd95SEwan Crawford "Undefined", "Undefined", "Undefined", 30415f2bd95SEwan Crawford "L Pixel", 30515f2bd95SEwan Crawford "A Pixel", 30615f2bd95SEwan Crawford "LA Pixel", 30715f2bd95SEwan Crawford "RGB Pixel", 30815f2bd95SEwan Crawford "RGBA Pixel", 30915f2bd95SEwan Crawford "Pixel Depth", 31015f2bd95SEwan Crawford "YUV Pixel" 31115f2bd95SEwan Crawford }; 31215f2bd95SEwan Crawford 31315f2bd95SEwan Crawford const char* RenderScriptRuntime::AllocationDetails::RsDataTypeToString[][4] = 31415f2bd95SEwan Crawford { 31515f2bd95SEwan Crawford {"None", "None", "None", "None"}, 31615f2bd95SEwan Crawford {"half", "half2", "half3", "half4"}, 31715f2bd95SEwan Crawford {"float", "float2", "float3", "float4"}, 31815f2bd95SEwan Crawford {"double", "double2", "double3", "double4"}, 31915f2bd95SEwan Crawford {"char", "char2", "char3", "char4"}, 32015f2bd95SEwan Crawford {"short", "short2", "short3", "short4"}, 32115f2bd95SEwan Crawford {"int", "int2", "int3", "int4"}, 32215f2bd95SEwan Crawford {"long", "long2", "long3", "long4"}, 32315f2bd95SEwan Crawford {"uchar", "uchar2", "uchar3", "uchar4"}, 32415f2bd95SEwan Crawford {"ushort", "ushort2", "ushort3", "ushort4"}, 32515f2bd95SEwan Crawford {"uint", "uint2", "uint3", "uint4"}, 32615f2bd95SEwan Crawford {"ulong", "ulong2", "ulong3", "ulong4"}, 3272e920715SEwan Crawford {"bool", "bool2", "bool3", "bool4"}, 3282e920715SEwan Crawford {"packed_565", "packed_565", "packed_565", "packed_565"}, 3292e920715SEwan Crawford {"packed_5551", "packed_5551", "packed_5551", "packed_5551"}, 3302e920715SEwan Crawford {"packed_4444", "packed_4444", "packed_4444", "packed_4444"}, 3312e920715SEwan Crawford {"rs_matrix4x4", "rs_matrix4x4", "rs_matrix4x4", "rs_matrix4x4"}, 3322e920715SEwan Crawford {"rs_matrix3x3", "rs_matrix3x3", "rs_matrix3x3", "rs_matrix3x3"}, 3332e920715SEwan Crawford {"rs_matrix2x2", "rs_matrix2x2", "rs_matrix2x2", "rs_matrix2x2"}, 3342e920715SEwan Crawford 3352e920715SEwan Crawford // Handlers 3362e920715SEwan Crawford {"RS Element", "RS Element", "RS Element", "RS Element"}, 3372e920715SEwan Crawford {"RS Type", "RS Type", "RS Type", "RS Type"}, 3382e920715SEwan Crawford {"RS Allocation", "RS Allocation", "RS Allocation", "RS Allocation"}, 3392e920715SEwan Crawford {"RS Sampler", "RS Sampler", "RS Sampler", "RS Sampler"}, 3402e920715SEwan Crawford {"RS Script", "RS Script", "RS Script", "RS Script"}, 3412e920715SEwan Crawford 3422e920715SEwan Crawford // Deprecated 3432e920715SEwan Crawford {"RS Mesh", "RS Mesh", "RS Mesh", "RS Mesh"}, 3442e920715SEwan Crawford {"RS Program Fragment", "RS Program Fragment", "RS Program Fragment", "RS Program Fragment"}, 3452e920715SEwan Crawford {"RS Program Vertex", "RS Program Vertex", "RS Program Vertex", "RS Program Vertex"}, 3462e920715SEwan Crawford {"RS Program Raster", "RS Program Raster", "RS Program Raster", "RS Program Raster"}, 3472e920715SEwan Crawford {"RS Program Store", "RS Program Store", "RS Program Store", "RS Program Store"}, 3482e920715SEwan Crawford {"RS Font", "RS Font", "RS Font", "RS Font"} 34978f339d1SEwan Crawford }; 35078f339d1SEwan Crawford 351a0f08674SEwan Crawford // Used as an index into the RSTypeToFormat array elements 352a0f08674SEwan Crawford enum TypeToFormatIndex { 353a0f08674SEwan Crawford eFormatSingle = 0, 354a0f08674SEwan Crawford eFormatVector, 355a0f08674SEwan Crawford eElementSize 356a0f08674SEwan Crawford }; 357a0f08674SEwan Crawford 358a0f08674SEwan Crawford // { format enum of single element, format enum of element vector, size of element} 359a0f08674SEwan Crawford const unsigned int RenderScriptRuntime::AllocationDetails::RSTypeToFormat[][3] = 360a0f08674SEwan Crawford { 361a0f08674SEwan Crawford {eFormatHex, eFormatHex, 1}, // RS_TYPE_NONE 362a0f08674SEwan Crawford {eFormatFloat, eFormatVectorOfFloat16, 2}, // RS_TYPE_FLOAT_16 363a0f08674SEwan Crawford {eFormatFloat, eFormatVectorOfFloat32, sizeof(float)}, // RS_TYPE_FLOAT_32 364a0f08674SEwan Crawford {eFormatFloat, eFormatVectorOfFloat64, sizeof(double)}, // RS_TYPE_FLOAT_64 365a0f08674SEwan Crawford {eFormatDecimal, eFormatVectorOfSInt8, sizeof(int8_t)}, // RS_TYPE_SIGNED_8 366a0f08674SEwan Crawford {eFormatDecimal, eFormatVectorOfSInt16, sizeof(int16_t)}, // RS_TYPE_SIGNED_16 367a0f08674SEwan Crawford {eFormatDecimal, eFormatVectorOfSInt32, sizeof(int32_t)}, // RS_TYPE_SIGNED_32 368a0f08674SEwan Crawford {eFormatDecimal, eFormatVectorOfSInt64, sizeof(int64_t)}, // RS_TYPE_SIGNED_64 369a0f08674SEwan Crawford {eFormatDecimal, eFormatVectorOfUInt8, sizeof(uint8_t)}, // RS_TYPE_UNSIGNED_8 370a0f08674SEwan Crawford {eFormatDecimal, eFormatVectorOfUInt16, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_16 371a0f08674SEwan Crawford {eFormatDecimal, eFormatVectorOfUInt32, sizeof(uint32_t)}, // RS_TYPE_UNSIGNED_32 372a0f08674SEwan Crawford {eFormatDecimal, eFormatVectorOfUInt64, sizeof(uint64_t)}, // RS_TYPE_UNSIGNED_64 3732e920715SEwan Crawford {eFormatBoolean, eFormatBoolean, 1}, // RS_TYPE_BOOL 3742e920715SEwan Crawford {eFormatHex, eFormatHex, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_5_6_5 3752e920715SEwan Crawford {eFormatHex, eFormatHex, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_5_5_5_1 3762e920715SEwan Crawford {eFormatHex, eFormatHex, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_4_4_4_4 3772e920715SEwan Crawford {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 16}, // RS_TYPE_MATRIX_4X4 3782e920715SEwan Crawford {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 9}, // RS_TYPE_MATRIX_3X3 3792e920715SEwan Crawford {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 4} // RS_TYPE_MATRIX_2X2 380a0f08674SEwan Crawford }; 381a0f08674SEwan Crawford 3825ec532a9SColin Riley //------------------------------------------------------------------ 3835ec532a9SColin Riley // Static Functions 3845ec532a9SColin Riley //------------------------------------------------------------------ 3855ec532a9SColin Riley LanguageRuntime * 3865ec532a9SColin Riley RenderScriptRuntime::CreateInstance(Process *process, lldb::LanguageType language) 3875ec532a9SColin Riley { 3885ec532a9SColin Riley 3895ec532a9SColin Riley if (language == eLanguageTypeExtRenderScript) 3905ec532a9SColin Riley return new RenderScriptRuntime(process); 3915ec532a9SColin Riley else 3925ec532a9SColin Riley return NULL; 3935ec532a9SColin Riley } 3945ec532a9SColin Riley 39598156583SEwan Crawford // Callback with a module to search for matching symbols. 39698156583SEwan Crawford // We first check that the module contains RS kernels. 39798156583SEwan Crawford // Then look for a symbol which matches our kernel name. 39898156583SEwan Crawford // The breakpoint address is finally set using the address of this symbol. 39998156583SEwan Crawford Searcher::CallbackReturn 40098156583SEwan Crawford RSBreakpointResolver::SearchCallback(SearchFilter &filter, 40198156583SEwan Crawford SymbolContext &context, 40298156583SEwan Crawford Address*, 40398156583SEwan Crawford bool) 40498156583SEwan Crawford { 40598156583SEwan Crawford ModuleSP module = context.module_sp; 40698156583SEwan Crawford 40798156583SEwan Crawford if (!module) 40898156583SEwan Crawford return Searcher::eCallbackReturnContinue; 40998156583SEwan Crawford 41098156583SEwan Crawford // Is this a module containing renderscript kernels? 41198156583SEwan Crawford if (nullptr == module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData)) 41298156583SEwan Crawford return Searcher::eCallbackReturnContinue; 41398156583SEwan Crawford 41498156583SEwan Crawford // Attempt to set a breakpoint on the kernel name symbol within the module library. 41598156583SEwan Crawford // If it's not found, it's likely debug info is unavailable - try to set a 41698156583SEwan Crawford // breakpoint on <name>.expand. 41798156583SEwan Crawford 41898156583SEwan Crawford const Symbol* kernel_sym = module->FindFirstSymbolWithNameAndType(m_kernel_name, eSymbolTypeCode); 41998156583SEwan Crawford if (!kernel_sym) 42098156583SEwan Crawford { 42198156583SEwan Crawford std::string kernel_name_expanded(m_kernel_name.AsCString()); 42298156583SEwan Crawford kernel_name_expanded.append(".expand"); 42398156583SEwan Crawford kernel_sym = module->FindFirstSymbolWithNameAndType(ConstString(kernel_name_expanded.c_str()), eSymbolTypeCode); 42498156583SEwan Crawford } 42598156583SEwan Crawford 42698156583SEwan Crawford if (kernel_sym) 42798156583SEwan Crawford { 42898156583SEwan Crawford Address bp_addr = kernel_sym->GetAddress(); 42998156583SEwan Crawford if (filter.AddressPasses(bp_addr)) 43098156583SEwan Crawford m_breakpoint->AddLocation(bp_addr); 43198156583SEwan Crawford } 43298156583SEwan Crawford 43398156583SEwan Crawford return Searcher::eCallbackReturnContinue; 43498156583SEwan Crawford } 43598156583SEwan Crawford 4365ec532a9SColin Riley void 4375ec532a9SColin Riley RenderScriptRuntime::Initialize() 4385ec532a9SColin Riley { 4394640cde1SColin Riley PluginManager::RegisterPlugin(GetPluginNameStatic(), "RenderScript language support", CreateInstance, GetCommandObject); 4405ec532a9SColin Riley } 4415ec532a9SColin Riley 4425ec532a9SColin Riley void 4435ec532a9SColin Riley RenderScriptRuntime::Terminate() 4445ec532a9SColin Riley { 4455ec532a9SColin Riley PluginManager::UnregisterPlugin(CreateInstance); 4465ec532a9SColin Riley } 4475ec532a9SColin Riley 4485ec532a9SColin Riley lldb_private::ConstString 4495ec532a9SColin Riley RenderScriptRuntime::GetPluginNameStatic() 4505ec532a9SColin Riley { 4515ec532a9SColin Riley static ConstString g_name("renderscript"); 4525ec532a9SColin Riley return g_name; 4535ec532a9SColin Riley } 4545ec532a9SColin Riley 455ef20b08fSColin Riley RenderScriptRuntime::ModuleKind 456ef20b08fSColin Riley RenderScriptRuntime::GetModuleKind(const lldb::ModuleSP &module_sp) 457ef20b08fSColin Riley { 458ef20b08fSColin Riley if (module_sp) 459ef20b08fSColin Riley { 460ef20b08fSColin Riley // Is this a module containing renderscript kernels? 461ef20b08fSColin Riley const Symbol *info_sym = module_sp->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData); 462ef20b08fSColin Riley if (info_sym) 463ef20b08fSColin Riley { 464ef20b08fSColin Riley return eModuleKindKernelObj; 465ef20b08fSColin Riley } 4664640cde1SColin Riley 4674640cde1SColin Riley // Is this the main RS runtime library 4684640cde1SColin Riley const ConstString rs_lib("libRS.so"); 4694640cde1SColin Riley if (module_sp->GetFileSpec().GetFilename() == rs_lib) 4704640cde1SColin Riley { 4714640cde1SColin Riley return eModuleKindLibRS; 4724640cde1SColin Riley } 4734640cde1SColin Riley 4744640cde1SColin Riley const ConstString rs_driverlib("libRSDriver.so"); 4754640cde1SColin Riley if (module_sp->GetFileSpec().GetFilename() == rs_driverlib) 4764640cde1SColin Riley { 4774640cde1SColin Riley return eModuleKindDriver; 4784640cde1SColin Riley } 4794640cde1SColin Riley 48015f2bd95SEwan Crawford const ConstString rs_cpureflib("libRSCpuRef.so"); 4814640cde1SColin Riley if (module_sp->GetFileSpec().GetFilename() == rs_cpureflib) 4824640cde1SColin Riley { 4834640cde1SColin Riley return eModuleKindImpl; 4844640cde1SColin Riley } 4854640cde1SColin Riley 486ef20b08fSColin Riley } 487ef20b08fSColin Riley return eModuleKindIgnored; 488ef20b08fSColin Riley } 489ef20b08fSColin Riley 490ef20b08fSColin Riley bool 491ef20b08fSColin Riley RenderScriptRuntime::IsRenderScriptModule(const lldb::ModuleSP &module_sp) 492ef20b08fSColin Riley { 493ef20b08fSColin Riley return GetModuleKind(module_sp) != eModuleKindIgnored; 494ef20b08fSColin Riley } 495ef20b08fSColin Riley 496ef20b08fSColin Riley void 497ef20b08fSColin Riley RenderScriptRuntime::ModulesDidLoad(const ModuleList &module_list ) 498ef20b08fSColin Riley { 499ef20b08fSColin Riley Mutex::Locker locker (module_list.GetMutex ()); 500ef20b08fSColin Riley 501ef20b08fSColin Riley size_t num_modules = module_list.GetSize(); 502ef20b08fSColin Riley for (size_t i = 0; i < num_modules; i++) 503ef20b08fSColin Riley { 504ef20b08fSColin Riley auto mod = module_list.GetModuleAtIndex (i); 505ef20b08fSColin Riley if (IsRenderScriptModule (mod)) 506ef20b08fSColin Riley { 507ef20b08fSColin Riley LoadModule(mod); 508ef20b08fSColin Riley } 509ef20b08fSColin Riley } 510ef20b08fSColin Riley } 511ef20b08fSColin Riley 5125ec532a9SColin Riley //------------------------------------------------------------------ 5135ec532a9SColin Riley // PluginInterface protocol 5145ec532a9SColin Riley //------------------------------------------------------------------ 5155ec532a9SColin Riley lldb_private::ConstString 5165ec532a9SColin Riley RenderScriptRuntime::GetPluginName() 5175ec532a9SColin Riley { 5185ec532a9SColin Riley return GetPluginNameStatic(); 5195ec532a9SColin Riley } 5205ec532a9SColin Riley 5215ec532a9SColin Riley uint32_t 5225ec532a9SColin Riley RenderScriptRuntime::GetPluginVersion() 5235ec532a9SColin Riley { 5245ec532a9SColin Riley return 1; 5255ec532a9SColin Riley } 5265ec532a9SColin Riley 5275ec532a9SColin Riley bool 5285ec532a9SColin Riley RenderScriptRuntime::IsVTableName(const char *name) 5295ec532a9SColin Riley { 5305ec532a9SColin Riley return false; 5315ec532a9SColin Riley } 5325ec532a9SColin Riley 5335ec532a9SColin Riley bool 5345ec532a9SColin Riley RenderScriptRuntime::GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic, 5350b6003f3SEnrico Granata TypeAndOrName &class_type_or_name, Address &address, 5360b6003f3SEnrico Granata Value::ValueType &value_type) 5375ec532a9SColin Riley { 5385ec532a9SColin Riley return false; 5395ec532a9SColin Riley } 5405ec532a9SColin Riley 541c74275bcSEnrico Granata TypeAndOrName 542c74275bcSEnrico Granata RenderScriptRuntime::FixUpDynamicType (const TypeAndOrName& type_and_or_name, 5437eed4877SEnrico Granata ValueObject& static_value) 544c74275bcSEnrico Granata { 545c74275bcSEnrico Granata return type_and_or_name; 546c74275bcSEnrico Granata } 547c74275bcSEnrico Granata 5485ec532a9SColin Riley bool 5495ec532a9SColin Riley RenderScriptRuntime::CouldHaveDynamicValue(ValueObject &in_value) 5505ec532a9SColin Riley { 5515ec532a9SColin Riley return false; 5525ec532a9SColin Riley } 5535ec532a9SColin Riley 5545ec532a9SColin Riley lldb::BreakpointResolverSP 5555ec532a9SColin Riley RenderScriptRuntime::CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp) 5565ec532a9SColin Riley { 5575ec532a9SColin Riley BreakpointResolverSP resolver_sp; 5585ec532a9SColin Riley return resolver_sp; 5595ec532a9SColin Riley } 5605ec532a9SColin Riley 5614640cde1SColin Riley const RenderScriptRuntime::HookDefn RenderScriptRuntime::s_runtimeHookDefns[] = 5624640cde1SColin Riley { 5634640cde1SColin Riley //rsdScript 56482780287SAidan Dodds { 56582780287SAidan Dodds "rsdScriptInit", //name 56682780287SAidan Dodds "_Z13rsdScriptInitPKN7android12renderscript7ContextEPNS0_7ScriptCEPKcS7_PKhjj", // symbol name 32 bit 56782780287SAidan Dodds "_Z13rsdScriptInitPKN7android12renderscript7ContextEPNS0_7ScriptCEPKcS7_PKhmj", // symbol name 64 bit 56882780287SAidan Dodds 0, // version 56982780287SAidan Dodds RenderScriptRuntime::eModuleKindDriver, // type 57082780287SAidan Dodds &lldb_private::RenderScriptRuntime::CaptureScriptInit1 // handler 57182780287SAidan Dodds }, 57282780287SAidan Dodds { 57382780287SAidan Dodds "rsdScriptInvokeForEach", // name 57482780287SAidan Dodds "_Z22rsdScriptInvokeForEachPKN7android12renderscript7ContextEPNS0_6ScriptEjPKNS0_10AllocationEPS6_PKvjPK12RsScriptCall", // symbol name 32bit 57582780287SAidan Dodds "_Z22rsdScriptInvokeForEachPKN7android12renderscript7ContextEPNS0_6ScriptEjPKNS0_10AllocationEPS6_PKvmPK12RsScriptCall", // symbol name 64bit 57682780287SAidan Dodds 0, // version 57782780287SAidan Dodds RenderScriptRuntime::eModuleKindDriver, // type 57882780287SAidan Dodds nullptr // handler 57982780287SAidan Dodds }, 58082780287SAidan Dodds { 58182780287SAidan Dodds "rsdScriptInvokeForEachMulti", // name 58282780287SAidan Dodds "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0_6ScriptEjPPKNS0_10AllocationEjPS6_PKvjPK12RsScriptCall", // symbol name 32bit 58382780287SAidan Dodds "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0_6ScriptEjPPKNS0_10AllocationEmPS6_PKvmPK12RsScriptCall", // symbol name 64bit 58482780287SAidan Dodds 0, // version 58582780287SAidan Dodds RenderScriptRuntime::eModuleKindDriver, // type 58682780287SAidan Dodds nullptr // handler 58782780287SAidan Dodds }, 58882780287SAidan Dodds { 58982780287SAidan Dodds "rsdScriptInvokeFunction", // name 59082780287SAidan Dodds "_Z23rsdScriptInvokeFunctionPKN7android12renderscript7ContextEPNS0_6ScriptEjPKvj", // symbol name 32bit 59182780287SAidan Dodds "_Z23rsdScriptInvokeFunctionPKN7android12renderscript7ContextEPNS0_6ScriptEjPKvm", // symbol name 64bit 59282780287SAidan Dodds 0, // version 59382780287SAidan Dodds RenderScriptRuntime::eModuleKindDriver, // type 59482780287SAidan Dodds nullptr // handler 59582780287SAidan Dodds }, 59682780287SAidan Dodds { 59782780287SAidan Dodds "rsdScriptSetGlobalVar", // name 59882780287SAidan Dodds "_Z21rsdScriptSetGlobalVarPKN7android12renderscript7ContextEPKNS0_6ScriptEjPvj", // symbol name 32bit 59982780287SAidan Dodds "_Z21rsdScriptSetGlobalVarPKN7android12renderscript7ContextEPKNS0_6ScriptEjPvm", // symbol name 64bit 60082780287SAidan Dodds 0, // version 60182780287SAidan Dodds RenderScriptRuntime::eModuleKindDriver, // type 60282780287SAidan Dodds &lldb_private::RenderScriptRuntime::CaptureSetGlobalVar1 // handler 60382780287SAidan Dodds }, 6044640cde1SColin Riley 6054640cde1SColin Riley //rsdAllocation 60682780287SAidan Dodds { 60782780287SAidan Dodds "rsdAllocationInit", // name 60882780287SAidan Dodds "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_10AllocationEb", // symbol name 32bit 60982780287SAidan Dodds "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_10AllocationEb", // symbol name 64bit 61082780287SAidan Dodds 0, // version 61182780287SAidan Dodds RenderScriptRuntime::eModuleKindDriver, // type 61282780287SAidan Dodds &lldb_private::RenderScriptRuntime::CaptureAllocationInit1 // handler 61382780287SAidan Dodds }, 61482780287SAidan Dodds { 61582780287SAidan Dodds "rsdAllocationRead2D", //name 61682780287SAidan Dodds "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_10AllocationEjjj23RsAllocationCubemapFacejjPvjj", // symbol name 32bit 61782780287SAidan Dodds "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_10AllocationEjjj23RsAllocationCubemapFacejjPvmm", // symbol name 64bit 61882780287SAidan Dodds 0, // version 61982780287SAidan Dodds RenderScriptRuntime::eModuleKindDriver, // type 62082780287SAidan Dodds nullptr // handler 62182780287SAidan Dodds }, 622e69df382SEwan Crawford { 623e69df382SEwan Crawford "rsdAllocationDestroy", // name 624e69df382SEwan Crawford "_Z20rsdAllocationDestroyPKN7android12renderscript7ContextEPNS0_10AllocationE", // symbol name 32bit 625e69df382SEwan Crawford "_Z20rsdAllocationDestroyPKN7android12renderscript7ContextEPNS0_10AllocationE", // symbol name 64bit 626e69df382SEwan Crawford 0, // version 627e69df382SEwan Crawford RenderScriptRuntime::eModuleKindDriver, // type 628e69df382SEwan Crawford &lldb_private::RenderScriptRuntime::CaptureAllocationDestroy // handler 629e69df382SEwan Crawford }, 6304640cde1SColin Riley }; 6314640cde1SColin Riley 632222b937cSEugene Zelenko const size_t RenderScriptRuntime::s_runtimeHookCount = sizeof(s_runtimeHookDefns)/sizeof(s_runtimeHookDefns[0]); 6334640cde1SColin Riley 6344640cde1SColin Riley bool 6354640cde1SColin Riley RenderScriptRuntime::HookCallback(void *baton, StoppointCallbackContext *ctx, lldb::user_id_t break_id, lldb::user_id_t break_loc_id) 6364640cde1SColin Riley { 6374640cde1SColin Riley RuntimeHook* hook_info = (RuntimeHook*)baton; 6384640cde1SColin Riley ExecutionContext context(ctx->exe_ctx_ref); 6394640cde1SColin Riley 6404640cde1SColin Riley RenderScriptRuntime *lang_rt = (RenderScriptRuntime *)context.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); 6414640cde1SColin Riley 6424640cde1SColin Riley lang_rt->HookCallback(hook_info, context); 6434640cde1SColin Riley 6444640cde1SColin Riley return false; 6454640cde1SColin Riley } 6464640cde1SColin Riley 6474640cde1SColin Riley void 6484640cde1SColin Riley RenderScriptRuntime::HookCallback(RuntimeHook* hook_info, ExecutionContext& context) 6494640cde1SColin Riley { 6504640cde1SColin Riley Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 6514640cde1SColin Riley 6524640cde1SColin Riley if (log) 6534640cde1SColin Riley log->Printf ("RenderScriptRuntime::HookCallback - '%s' .", hook_info->defn->name); 6544640cde1SColin Riley 6554640cde1SColin Riley if (hook_info->defn->grabber) 6564640cde1SColin Riley { 6574640cde1SColin Riley (this->*(hook_info->defn->grabber))(hook_info, context); 6584640cde1SColin Riley } 6594640cde1SColin Riley } 6604640cde1SColin Riley 6614640cde1SColin Riley bool 66282780287SAidan Dodds RenderScriptRuntime::GetArgSimple(ExecutionContext &context, uint32_t arg, uint64_t *data) 6634640cde1SColin Riley { 664cdfb1485SEwan Crawford // Get a positional integer argument. 665cdfb1485SEwan Crawford // Given an ExecutionContext, ``context`` which should be a RenderScript 666cdfb1485SEwan Crawford // frame, get the value of the positional argument ``arg`` and save its value 667cdfb1485SEwan Crawford // to the address pointed to by ``data``. 668cdfb1485SEwan Crawford // returns true on success, false otherwise. 669cdfb1485SEwan Crawford // If unsuccessful, the value pointed to by ``data`` is undefined. Otherwise, 670cdfb1485SEwan Crawford // ``data`` will be set to the value of the the given ``arg``. 671cdfb1485SEwan Crawford // NOTE: only natural width integer arguments for the machine are supported. 672cdfb1485SEwan Crawford // Behaviour with non primitive arguments is undefined. 673cdfb1485SEwan Crawford 6744640cde1SColin Riley if (!data) 6754640cde1SColin Riley return false; 6764640cde1SColin Riley 67782780287SAidan Dodds Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 6784640cde1SColin Riley Error error; 6794640cde1SColin Riley RegisterContext* reg_ctx = context.GetRegisterContext(); 6804640cde1SColin Riley Process* process = context.GetProcessPtr(); 68182780287SAidan Dodds bool success = false; // return value 6824640cde1SColin Riley 68382780287SAidan Dodds if (!context.GetTargetPtr()) 68482780287SAidan Dodds { 68582780287SAidan Dodds if (log) 68682780287SAidan Dodds log->Printf("RenderScriptRuntime::GetArgSimple - Invalid target"); 68782780287SAidan Dodds 68882780287SAidan Dodds return false; 68982780287SAidan Dodds } 69082780287SAidan Dodds 69182780287SAidan Dodds switch (context.GetTargetPtr()->GetArchitecture().GetMachine()) 69282780287SAidan Dodds { 69382780287SAidan Dodds case llvm::Triple::ArchType::x86: 6944640cde1SColin Riley { 6954640cde1SColin Riley uint64_t sp = reg_ctx->GetSP(); 6964640cde1SColin Riley uint32_t offset = (1 + arg) * sizeof(uint32_t); 69782780287SAidan Dodds uint32_t result = 0; 69882780287SAidan Dodds process->ReadMemory(sp + offset, &result, sizeof(uint32_t), error); 6994640cde1SColin Riley if (error.Fail()) 7004640cde1SColin Riley { 7014640cde1SColin Riley if (log) 70282780287SAidan Dodds log->Printf("RenderScriptRuntime::GetArgSimple - error reading X86 stack: %s.", error.AsCString()); 7034640cde1SColin Riley } 70482780287SAidan Dodds else 7054640cde1SColin Riley { 70682780287SAidan Dodds *data = result; 70782780287SAidan Dodds success = true; 70882780287SAidan Dodds } 70982780287SAidan Dodds break; 71082780287SAidan Dodds } 711cdfb1485SEwan Crawford case llvm::Triple::ArchType::x86_64: 712cdfb1485SEwan Crawford { 713cdfb1485SEwan Crawford // amd64 has 6 integer registers, and 8 XMM registers for parameter passing. 714cdfb1485SEwan Crawford // Surplus args are spilled onto the stack. 715cdfb1485SEwan Crawford // rdi, rsi, rdx, rcx, r8, r9, (zmm0 - 7 for vectors) 716cdfb1485SEwan Crawford // ref: AMD64 ABI Draft 0.99.6 – October 7, 2013 – 10:35; Figure 3.4. Retrieved from 717cdfb1485SEwan Crawford // http://www.x86-64.org/documentation/abi.pdf 718cdfb1485SEwan Crawford if (arg > 5) 719cdfb1485SEwan Crawford { 720cdfb1485SEwan Crawford if (log) 721cdfb1485SEwan Crawford log->Warning("X86_64 register spill is not supported."); 722cdfb1485SEwan Crawford break; 723cdfb1485SEwan Crawford } 724cdfb1485SEwan Crawford const char * regnames[] = {"rdi", "rsi", "rdx", "rcx", "r8", "r9"}; 725cdfb1485SEwan Crawford assert((sizeof(regnames) / sizeof(const char *)) > arg); 726cdfb1485SEwan Crawford const RegisterInfo *rArg = reg_ctx->GetRegisterInfoByName(regnames[arg]); 727cdfb1485SEwan Crawford RegisterValue rVal; 728cdfb1485SEwan Crawford success = reg_ctx->ReadRegister(rArg, rVal); 729cdfb1485SEwan Crawford if (success) 730cdfb1485SEwan Crawford { 731cdfb1485SEwan Crawford *data = rVal.GetAsUInt64(0u, &success); 732cdfb1485SEwan Crawford } 733cdfb1485SEwan Crawford else 734cdfb1485SEwan Crawford { 735cdfb1485SEwan Crawford if (log) 736cdfb1485SEwan Crawford log->Printf("RenderScriptRuntime::GetArgSimple - error reading x86_64 register: %d.", arg); 737cdfb1485SEwan Crawford } 738cdfb1485SEwan Crawford break; 739cdfb1485SEwan Crawford } 74082780287SAidan Dodds case llvm::Triple::ArchType::arm: 74182780287SAidan Dodds { 74282780287SAidan Dodds // arm 32 bit 743*35e7b1adSAidan Dodds // first 4 arguments are passed via registers 7444640cde1SColin Riley if (arg < 4) 7454640cde1SColin Riley { 7464640cde1SColin Riley const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg); 7474640cde1SColin Riley RegisterValue rVal; 74802f1c5d1SEwan Crawford success = reg_ctx->ReadRegister(rArg, rVal); 74902f1c5d1SEwan Crawford if (success) 75002f1c5d1SEwan Crawford { 751cdfb1485SEwan Crawford (*data) = rVal.GetAsUInt32(0u, &success); 75202f1c5d1SEwan Crawford } 75302f1c5d1SEwan Crawford else 75402f1c5d1SEwan Crawford { 75502f1c5d1SEwan Crawford if (log) 75602f1c5d1SEwan Crawford log->Printf("RenderScriptRuntime::GetArgSimple - error reading ARM register: %d.", arg); 75702f1c5d1SEwan Crawford } 7584640cde1SColin Riley } 7594640cde1SColin Riley else 7604640cde1SColin Riley { 7614640cde1SColin Riley uint64_t sp = reg_ctx->GetSP(); 7624640cde1SColin Riley uint32_t offset = (arg-4) * sizeof(uint32_t); 763*35e7b1adSAidan Dodds uint32_t value = 0; 764*35e7b1adSAidan Dodds size_t bytes_read = process->ReadMemory(sp + offset, &value, sizeof(value), error); 765*35e7b1adSAidan Dodds if (error.Fail() || bytes_read != sizeof(value)) 7664640cde1SColin Riley { 7674640cde1SColin Riley if (log) 76882780287SAidan Dodds log->Printf("RenderScriptRuntime::GetArgSimple - error reading ARM stack: %s.", error.AsCString()); 76982780287SAidan Dodds } 77082780287SAidan Dodds else 77182780287SAidan Dodds { 772*35e7b1adSAidan Dodds *data = value; 77382780287SAidan Dodds success = true; 7744640cde1SColin Riley } 7754640cde1SColin Riley } 77682780287SAidan Dodds break; 7774640cde1SColin Riley } 77882780287SAidan Dodds case llvm::Triple::ArchType::aarch64: 77982780287SAidan Dodds { 78082780287SAidan Dodds // arm 64 bit 78182780287SAidan Dodds // first 8 arguments are in the registers 78282780287SAidan Dodds if (arg < 8) 78382780287SAidan Dodds { 78482780287SAidan Dodds const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg); 78582780287SAidan Dodds RegisterValue rVal; 78682780287SAidan Dodds success = reg_ctx->ReadRegister(rArg, rVal); 78782780287SAidan Dodds if (success) 78882780287SAidan Dodds { 789cdfb1485SEwan Crawford *data = rVal.GetAsUInt64(0u, &success); 79082780287SAidan Dodds } 79182780287SAidan Dodds else 79282780287SAidan Dodds { 79382780287SAidan Dodds if (log) 79482780287SAidan Dodds log->Printf("RenderScriptRuntime::GetArgSimple() - AARCH64 - Error while reading the argument #%d", arg); 79582780287SAidan Dodds } 79682780287SAidan Dodds } 79782780287SAidan Dodds else 79882780287SAidan Dodds { 79982780287SAidan Dodds // @TODO: need to find the argument in the stack 80082780287SAidan Dodds if (log) 80182780287SAidan Dodds log->Printf("RenderScriptRuntime::GetArgSimple - AARCH64 - FOR #ARG >= 8 NOT IMPLEMENTED YET. Argument number: %d", arg); 80282780287SAidan Dodds } 80382780287SAidan Dodds break; 80482780287SAidan Dodds } 80574b396d9SAidan Dodds case llvm::Triple::ArchType::mipsel: 80674b396d9SAidan Dodds { 80774b396d9SAidan Dodds // read from the registers 808*35e7b1adSAidan Dodds // first 4 arguments are passed in registers 80974b396d9SAidan Dodds if (arg < 4){ 81074b396d9SAidan Dodds const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg + 4); 81174b396d9SAidan Dodds RegisterValue rVal; 81274b396d9SAidan Dodds success = reg_ctx->ReadRegister(rArg, rVal); 81374b396d9SAidan Dodds if (success) 81474b396d9SAidan Dodds { 815cdfb1485SEwan Crawford *data = rVal.GetAsUInt64(0u, &success); 81674b396d9SAidan Dodds } 81774b396d9SAidan Dodds else 81874b396d9SAidan Dodds { 81974b396d9SAidan Dodds if (log) 82074b396d9SAidan Dodds log->Printf("RenderScriptRuntime::GetArgSimple() - Mips - Error while reading the argument #%d", arg); 82174b396d9SAidan Dodds } 82274b396d9SAidan Dodds } 823*35e7b1adSAidan Dodds // arguments > 4 are read from the stack 82474b396d9SAidan Dodds else 82574b396d9SAidan Dodds { 82674b396d9SAidan Dodds uint64_t sp = reg_ctx->GetSP(); 82774b396d9SAidan Dodds uint32_t offset = arg * sizeof(uint32_t); 828*35e7b1adSAidan Dodds uint32_t value = 0; 829*35e7b1adSAidan Dodds size_t bytes_read = process->ReadMemory(sp + offset, &value, sizeof(value), error); 830*35e7b1adSAidan Dodds if (error.Fail() || bytes_read != sizeof(value)) 83174b396d9SAidan Dodds { 83274b396d9SAidan Dodds if (log) 83374b396d9SAidan Dodds log->Printf("RenderScriptRuntime::GetArgSimple - error reading Mips stack: %s.", error.AsCString()); 83474b396d9SAidan Dodds } 83574b396d9SAidan Dodds else 83674b396d9SAidan Dodds { 837*35e7b1adSAidan Dodds *data = value; 83874b396d9SAidan Dodds success = true; 83974b396d9SAidan Dodds } 84074b396d9SAidan Dodds } 84174b396d9SAidan Dodds break; 84274b396d9SAidan Dodds } 84302f1c5d1SEwan Crawford case llvm::Triple::ArchType::mips64el: 84402f1c5d1SEwan Crawford { 84502f1c5d1SEwan Crawford // read from the registers 84602f1c5d1SEwan Crawford if (arg < 8) 84702f1c5d1SEwan Crawford { 84802f1c5d1SEwan Crawford const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg + 4); 84902f1c5d1SEwan Crawford RegisterValue rVal; 85002f1c5d1SEwan Crawford success = reg_ctx->ReadRegister(rArg, rVal); 85102f1c5d1SEwan Crawford if (success) 85202f1c5d1SEwan Crawford { 853cdfb1485SEwan Crawford (*data) = rVal.GetAsUInt64(0u, &success); 85402f1c5d1SEwan Crawford } 85502f1c5d1SEwan Crawford else 85602f1c5d1SEwan Crawford { 85702f1c5d1SEwan Crawford if (log) 85802f1c5d1SEwan Crawford log->Printf("RenderScriptRuntime::GetArgSimple - Mips64 - Error reading the argument #%d", arg); 85902f1c5d1SEwan Crawford } 86002f1c5d1SEwan Crawford } 861*35e7b1adSAidan Dodds // arguments > 8 are read from the stack 86202f1c5d1SEwan Crawford else 86302f1c5d1SEwan Crawford { 86402f1c5d1SEwan Crawford uint64_t sp = reg_ctx->GetSP(); 86502f1c5d1SEwan Crawford uint32_t offset = (arg - 8) * sizeof(uint64_t); 866*35e7b1adSAidan Dodds uint64_t value = 0; 867*35e7b1adSAidan Dodds size_t bytes_read = process->ReadMemory(sp + offset, &value, sizeof(value), error); 868*35e7b1adSAidan Dodds if (error.Fail() || bytes_read != sizeof(value)) 86902f1c5d1SEwan Crawford { 87002f1c5d1SEwan Crawford if (log) 87102f1c5d1SEwan Crawford log->Printf("RenderScriptRuntime::GetArgSimple - Mips64 - Error reading Mips64 stack: %s.", error.AsCString()); 87202f1c5d1SEwan Crawford } 87302f1c5d1SEwan Crawford else 87402f1c5d1SEwan Crawford { 875*35e7b1adSAidan Dodds *data = value; 87602f1c5d1SEwan Crawford success = true; 87702f1c5d1SEwan Crawford } 87802f1c5d1SEwan Crawford } 87902f1c5d1SEwan Crawford break; 88002f1c5d1SEwan Crawford } 88182780287SAidan Dodds default: 88282780287SAidan Dodds { 88382780287SAidan Dodds // invalid architecture 88482780287SAidan Dodds if (log) 88582780287SAidan Dodds log->Printf("RenderScriptRuntime::GetArgSimple - Architecture not supported"); 88682780287SAidan Dodds } 88782780287SAidan Dodds } 88882780287SAidan Dodds 889cdfb1485SEwan Crawford if (!success) 890cdfb1485SEwan Crawford { 891cdfb1485SEwan Crawford if (log) 892cdfb1485SEwan Crawford log->Printf("RenderScriptRuntime::GetArgSimple - failed to get argument at index %" PRIu32, arg); 893cdfb1485SEwan Crawford } 89482780287SAidan Dodds return success; 8954640cde1SColin Riley } 8964640cde1SColin Riley 8974640cde1SColin Riley void 8984640cde1SColin Riley RenderScriptRuntime::CaptureSetGlobalVar1(RuntimeHook* hook_info, ExecutionContext& context) 8994640cde1SColin Riley { 9004640cde1SColin Riley Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 9014640cde1SColin Riley 9024640cde1SColin Riley //Context, Script, int, data, length 9034640cde1SColin Riley 90482780287SAidan Dodds uint64_t rs_context_u64 = 0U; 90582780287SAidan Dodds uint64_t rs_script_u64 = 0U; 90682780287SAidan Dodds uint64_t rs_id_u64 = 0U; 90782780287SAidan Dodds uint64_t rs_data_u64 = 0U; 90882780287SAidan Dodds uint64_t rs_length_u64 = 0U; 9094640cde1SColin Riley 91082780287SAidan Dodds bool success = 91182780287SAidan Dodds GetArgSimple(context, 0, &rs_context_u64) && 91282780287SAidan Dodds GetArgSimple(context, 1, &rs_script_u64) && 91382780287SAidan Dodds GetArgSimple(context, 2, &rs_id_u64) && 91482780287SAidan Dodds GetArgSimple(context, 3, &rs_data_u64) && 91582780287SAidan Dodds GetArgSimple(context, 4, &rs_length_u64); 9164640cde1SColin Riley 91782780287SAidan Dodds if (!success) 91882780287SAidan Dodds { 91982780287SAidan Dodds if (log) 92082780287SAidan Dodds log->Printf("RenderScriptRuntime::CaptureSetGlobalVar1 - Error while reading the function parameters"); 92182780287SAidan Dodds return; 92282780287SAidan Dodds } 9234640cde1SColin Riley 9244640cde1SColin Riley if (log) 9254640cde1SColin Riley { 9264640cde1SColin Riley log->Printf ("RenderScriptRuntime::CaptureSetGlobalVar1 - 0x%" PRIx64 ",0x%" PRIx64 " slot %" PRIu64 " = 0x%" PRIx64 ":%" PRIu64 "bytes.", 92782780287SAidan Dodds rs_context_u64, rs_script_u64, rs_id_u64, rs_data_u64, rs_length_u64); 9284640cde1SColin Riley 92982780287SAidan Dodds addr_t script_addr = (addr_t)rs_script_u64; 9304640cde1SColin Riley if (m_scriptMappings.find( script_addr ) != m_scriptMappings.end()) 9314640cde1SColin Riley { 9324640cde1SColin Riley auto rsm = m_scriptMappings[script_addr]; 93382780287SAidan Dodds if (rs_id_u64 < rsm->m_globals.size()) 9344640cde1SColin Riley { 93582780287SAidan Dodds auto rsg = rsm->m_globals[rs_id_u64]; 9364640cde1SColin Riley log->Printf ("RenderScriptRuntime::CaptureSetGlobalVar1 - Setting of '%s' within '%s' inferred", rsg.m_name.AsCString(), 9374640cde1SColin Riley rsm->m_module->GetFileSpec().GetFilename().AsCString()); 9384640cde1SColin Riley } 9394640cde1SColin Riley } 9404640cde1SColin Riley } 9414640cde1SColin Riley } 9424640cde1SColin Riley 9434640cde1SColin Riley void 9444640cde1SColin Riley RenderScriptRuntime::CaptureAllocationInit1(RuntimeHook* hook_info, ExecutionContext& context) 9454640cde1SColin Riley { 9464640cde1SColin Riley Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 9474640cde1SColin Riley 9484640cde1SColin Riley //Context, Alloc, bool 9494640cde1SColin Riley 95082780287SAidan Dodds uint64_t rs_context_u64 = 0U; 95182780287SAidan Dodds uint64_t rs_alloc_u64 = 0U; 95282780287SAidan Dodds uint64_t rs_forceZero_u64 = 0U; 9534640cde1SColin Riley 95482780287SAidan Dodds bool success = 95582780287SAidan Dodds GetArgSimple(context, 0, &rs_context_u64) && 95682780287SAidan Dodds GetArgSimple(context, 1, &rs_alloc_u64) && 95782780287SAidan Dodds GetArgSimple(context, 2, &rs_forceZero_u64); 95882780287SAidan Dodds if (!success) // error case 95982780287SAidan Dodds { 96082780287SAidan Dodds if (log) 96182780287SAidan Dodds log->Printf("RenderScriptRuntime::CaptureAllocationInit1 - Error while reading the function parameters"); 96282780287SAidan Dodds return; // abort 96382780287SAidan Dodds } 9644640cde1SColin Riley 9654640cde1SColin Riley if (log) 9664640cde1SColin Riley log->Printf ("RenderScriptRuntime::CaptureAllocationInit1 - 0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 " .", 96782780287SAidan Dodds rs_context_u64, rs_alloc_u64, rs_forceZero_u64); 96878f339d1SEwan Crawford 96978f339d1SEwan Crawford AllocationDetails* alloc = LookUpAllocation(rs_alloc_u64, true); 97078f339d1SEwan Crawford if (alloc) 97178f339d1SEwan Crawford alloc->context = rs_context_u64; 9724640cde1SColin Riley } 9734640cde1SColin Riley 9744640cde1SColin Riley void 975e69df382SEwan Crawford RenderScriptRuntime::CaptureAllocationDestroy(RuntimeHook* hook_info, ExecutionContext& context) 976e69df382SEwan Crawford { 977e69df382SEwan Crawford Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 978e69df382SEwan Crawford 979e69df382SEwan Crawford // Context, Alloc 980e69df382SEwan Crawford uint64_t rs_context_u64 = 0U; 981e69df382SEwan Crawford uint64_t rs_alloc_u64 = 0U; 982e69df382SEwan Crawford 983e69df382SEwan Crawford bool success = GetArgSimple(context, 0, &rs_context_u64) && GetArgSimple(context, 1, &rs_alloc_u64); 984e69df382SEwan Crawford if (!success) // error case 985e69df382SEwan Crawford { 986e69df382SEwan Crawford if (log) 987e69df382SEwan Crawford log->Printf("RenderScriptRuntime::CaptureAllocationDestroy - Error while reading the function parameters"); 988e69df382SEwan Crawford return; // abort 989e69df382SEwan Crawford } 990e69df382SEwan Crawford 991e69df382SEwan Crawford if (log) 992e69df382SEwan Crawford log->Printf("RenderScriptRuntime::CaptureAllocationDestroy - 0x%" PRIx64 ", 0x%" PRIx64 ".", 993e69df382SEwan Crawford rs_context_u64, rs_alloc_u64); 994e69df382SEwan Crawford 995e69df382SEwan Crawford for (auto iter = m_allocations.begin(); iter != m_allocations.end(); ++iter) 996e69df382SEwan Crawford { 997e69df382SEwan Crawford auto& allocation_ap = *iter; // get the unique pointer 998e69df382SEwan Crawford if (allocation_ap->address.isValid() && *allocation_ap->address.get() == rs_alloc_u64) 999e69df382SEwan Crawford { 1000e69df382SEwan Crawford m_allocations.erase(iter); 1001e69df382SEwan Crawford if (log) 1002e69df382SEwan Crawford log->Printf("RenderScriptRuntime::CaptureAllocationDestroy - Deleted allocation entry"); 1003e69df382SEwan Crawford return; 1004e69df382SEwan Crawford } 1005e69df382SEwan Crawford } 1006e69df382SEwan Crawford 1007e69df382SEwan Crawford if (log) 1008e69df382SEwan Crawford log->Printf("RenderScriptRuntime::CaptureAllocationDestroy - Couldn't find destroyed allocation"); 1009e69df382SEwan Crawford } 1010e69df382SEwan Crawford 1011e69df382SEwan Crawford void 10124640cde1SColin Riley RenderScriptRuntime::CaptureScriptInit1(RuntimeHook* hook_info, ExecutionContext& context) 10134640cde1SColin Riley { 10144640cde1SColin Riley Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 10154640cde1SColin Riley 10164640cde1SColin Riley //Context, Script, resname Str, cachedir Str 10174640cde1SColin Riley Error error; 10184640cde1SColin Riley Process* process = context.GetProcessPtr(); 10194640cde1SColin Riley 102082780287SAidan Dodds uint64_t rs_context_u64 = 0U; 102182780287SAidan Dodds uint64_t rs_script_u64 = 0U; 102282780287SAidan Dodds uint64_t rs_resnameptr_u64 = 0U; 102382780287SAidan Dodds uint64_t rs_cachedirptr_u64 = 0U; 10244640cde1SColin Riley 10254640cde1SColin Riley std::string resname; 10264640cde1SColin Riley std::string cachedir; 10274640cde1SColin Riley 102882780287SAidan Dodds // read the function parameters 102982780287SAidan Dodds bool success = 103082780287SAidan Dodds GetArgSimple(context, 0, &rs_context_u64) && 103182780287SAidan Dodds GetArgSimple(context, 1, &rs_script_u64) && 103282780287SAidan Dodds GetArgSimple(context, 2, &rs_resnameptr_u64) && 103382780287SAidan Dodds GetArgSimple(context, 3, &rs_cachedirptr_u64); 10344640cde1SColin Riley 103582780287SAidan Dodds if (!success) 103682780287SAidan Dodds { 103782780287SAidan Dodds if (log) 103882780287SAidan Dodds log->Printf("RenderScriptRuntime::CaptureScriptInit1 - Error while reading the function parameters"); 103982780287SAidan Dodds return; 104082780287SAidan Dodds } 104182780287SAidan Dodds 104282780287SAidan Dodds process->ReadCStringFromMemory((lldb::addr_t)rs_resnameptr_u64, resname, error); 10434640cde1SColin Riley if (error.Fail()) 10444640cde1SColin Riley { 10454640cde1SColin Riley if (log) 10464640cde1SColin Riley log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - error reading resname: %s.", error.AsCString()); 10474640cde1SColin Riley 10484640cde1SColin Riley } 10494640cde1SColin Riley 105082780287SAidan Dodds process->ReadCStringFromMemory((lldb::addr_t)rs_cachedirptr_u64, cachedir, error); 10514640cde1SColin Riley if (error.Fail()) 10524640cde1SColin Riley { 10534640cde1SColin Riley if (log) 10544640cde1SColin Riley log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - error reading cachedir: %s.", error.AsCString()); 10554640cde1SColin Riley } 10564640cde1SColin Riley 10574640cde1SColin Riley if (log) 10584640cde1SColin Riley log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - 0x%" PRIx64 ",0x%" PRIx64 " => '%s' at '%s' .", 105982780287SAidan Dodds rs_context_u64, rs_script_u64, resname.c_str(), cachedir.c_str()); 10604640cde1SColin Riley 10614640cde1SColin Riley if (resname.size() > 0) 10624640cde1SColin Riley { 10634640cde1SColin Riley StreamString strm; 10644640cde1SColin Riley strm.Printf("librs.%s.so", resname.c_str()); 10654640cde1SColin Riley 106678f339d1SEwan Crawford ScriptDetails* script = LookUpScript(rs_script_u64, true); 106778f339d1SEwan Crawford if (script) 106878f339d1SEwan Crawford { 106978f339d1SEwan Crawford script->type = ScriptDetails::eScriptC; 107078f339d1SEwan Crawford script->cacheDir = cachedir; 107178f339d1SEwan Crawford script->resName = resname; 107278f339d1SEwan Crawford script->scriptDyLib = strm.GetData(); 107378f339d1SEwan Crawford script->context = addr_t(rs_context_u64); 107478f339d1SEwan Crawford } 10754640cde1SColin Riley 10764640cde1SColin Riley if (log) 10774640cde1SColin Riley log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - '%s' tagged with context 0x%" PRIx64 " and script 0x%" PRIx64 ".", 107882780287SAidan Dodds strm.GetData(), rs_context_u64, rs_script_u64); 10794640cde1SColin Riley } 10804640cde1SColin Riley else if (log) 10814640cde1SColin Riley { 10824640cde1SColin Riley log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - resource name invalid, Script not tagged"); 10834640cde1SColin Riley } 10844640cde1SColin Riley } 10854640cde1SColin Riley 10864640cde1SColin Riley void 10874640cde1SColin Riley RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind) 10884640cde1SColin Riley { 10894640cde1SColin Riley Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 10904640cde1SColin Riley 10914640cde1SColin Riley if (!module) 10924640cde1SColin Riley { 10934640cde1SColin Riley return; 10944640cde1SColin Riley } 10954640cde1SColin Riley 109682780287SAidan Dodds Target &target = GetProcess()->GetTarget(); 109782780287SAidan Dodds llvm::Triple::ArchType targetArchType = target.GetArchitecture().GetMachine(); 109882780287SAidan Dodds 109982780287SAidan Dodds if (targetArchType != llvm::Triple::ArchType::x86 110082780287SAidan Dodds && targetArchType != llvm::Triple::ArchType::arm 110102f1c5d1SEwan Crawford && targetArchType != llvm::Triple::ArchType::aarch64 110274b396d9SAidan Dodds && targetArchType != llvm::Triple::ArchType::mipsel 110302f1c5d1SEwan Crawford && targetArchType != llvm::Triple::ArchType::mips64el 1104cdfb1485SEwan Crawford && targetArchType != llvm::Triple::ArchType::x86_64 110502f1c5d1SEwan Crawford ) 11064640cde1SColin Riley { 11074640cde1SColin Riley if (log) 110874b396d9SAidan Dodds log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Unable to hook runtime. Only X86, ARM, Mips supported currently."); 11094640cde1SColin Riley 11104640cde1SColin Riley return; 11114640cde1SColin Riley } 11124640cde1SColin Riley 111382780287SAidan Dodds uint32_t archByteSize = target.GetArchitecture().GetAddressByteSize(); 11144640cde1SColin Riley 11154640cde1SColin Riley for (size_t idx = 0; idx < s_runtimeHookCount; idx++) 11164640cde1SColin Riley { 11174640cde1SColin Riley const HookDefn* hook_defn = &s_runtimeHookDefns[idx]; 11184640cde1SColin Riley if (hook_defn->kind != kind) { 11194640cde1SColin Riley continue; 11204640cde1SColin Riley } 11214640cde1SColin Riley 112282780287SAidan Dodds const char* symbol_name = (archByteSize == 4) ? hook_defn->symbol_name_m32 : hook_defn->symbol_name_m64; 112382780287SAidan Dodds 112482780287SAidan Dodds const Symbol *sym = module->FindFirstSymbolWithNameAndType(ConstString(symbol_name), eSymbolTypeCode); 112582780287SAidan Dodds if (!sym){ 112682780287SAidan Dodds if (log){ 112782780287SAidan Dodds log->Printf("RenderScriptRuntime::LoadRuntimeHooks - ERROR: Symbol '%s' related to the function %s not found", symbol_name, hook_defn->name); 112882780287SAidan Dodds } 112982780287SAidan Dodds continue; 113082780287SAidan Dodds } 11314640cde1SColin Riley 1132358cf1eaSGreg Clayton addr_t addr = sym->GetLoadAddress(&target); 11334640cde1SColin Riley if (addr == LLDB_INVALID_ADDRESS) 11344640cde1SColin Riley { 11354640cde1SColin Riley if (log) 11364640cde1SColin Riley log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Unable to resolve the address of hook function '%s' with symbol '%s'.", 113782780287SAidan Dodds hook_defn->name, symbol_name); 11384640cde1SColin Riley continue; 11394640cde1SColin Riley } 114082780287SAidan Dodds else 114182780287SAidan Dodds { 114282780287SAidan Dodds if (log) 114382780287SAidan Dodds log->Printf("RenderScriptRuntime::LoadRuntimeHooks - Function %s, address resolved at 0x%" PRIx64, hook_defn->name, addr); 114482780287SAidan Dodds } 11454640cde1SColin Riley 11464640cde1SColin Riley RuntimeHookSP hook(new RuntimeHook()); 11474640cde1SColin Riley hook->address = addr; 11484640cde1SColin Riley hook->defn = hook_defn; 11494640cde1SColin Riley hook->bp_sp = target.CreateBreakpoint(addr, true, false); 11504640cde1SColin Riley hook->bp_sp->SetCallback(HookCallback, hook.get(), true); 11514640cde1SColin Riley m_runtimeHooks[addr] = hook; 11524640cde1SColin Riley if (log) 11534640cde1SColin Riley { 11544640cde1SColin Riley log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Successfully hooked '%s' in '%s' version %" PRIu64 " at 0x%" PRIx64 ".", 11554640cde1SColin Riley hook_defn->name, module->GetFileSpec().GetFilename().AsCString(), (uint64_t)hook_defn->version, (uint64_t)addr); 11564640cde1SColin Riley } 11574640cde1SColin Riley } 11584640cde1SColin Riley } 11594640cde1SColin Riley 11604640cde1SColin Riley void 11614640cde1SColin Riley RenderScriptRuntime::FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp) 11624640cde1SColin Riley { 11634640cde1SColin Riley if (!rsmodule_sp) 11644640cde1SColin Riley return; 11654640cde1SColin Riley 11664640cde1SColin Riley Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 11674640cde1SColin Riley 11684640cde1SColin Riley const ModuleSP module = rsmodule_sp->m_module; 11694640cde1SColin Riley const FileSpec& file = module->GetPlatformFileSpec(); 11704640cde1SColin Riley 117178f339d1SEwan Crawford // Iterate over all of the scripts that we currently know of. 117278f339d1SEwan Crawford // Note: We cant push or pop to m_scripts here or it may invalidate rs_script. 11734640cde1SColin Riley for (const auto & rs_script : m_scripts) 11744640cde1SColin Riley { 117578f339d1SEwan Crawford // Extract the expected .so file path for this script. 117678f339d1SEwan Crawford std::string dylib; 117778f339d1SEwan Crawford if (!rs_script->scriptDyLib.get(dylib)) 117878f339d1SEwan Crawford continue; 117978f339d1SEwan Crawford 118078f339d1SEwan Crawford // Only proceed if the module that has loaded corresponds to this script. 118178f339d1SEwan Crawford if (file.GetFilename() != ConstString(dylib.c_str())) 118278f339d1SEwan Crawford continue; 118378f339d1SEwan Crawford 118478f339d1SEwan Crawford // Obtain the script address which we use as a key. 118578f339d1SEwan Crawford lldb::addr_t script; 118678f339d1SEwan Crawford if (!rs_script->script.get(script)) 118778f339d1SEwan Crawford continue; 118878f339d1SEwan Crawford 118978f339d1SEwan Crawford // If we have a script mapping for the current script. 119078f339d1SEwan Crawford if (m_scriptMappings.find(script) != m_scriptMappings.end()) 11914640cde1SColin Riley { 119278f339d1SEwan Crawford // if the module we have stored is different to the one we just received. 119378f339d1SEwan Crawford if (m_scriptMappings[script] != rsmodule_sp) 11944640cde1SColin Riley { 11954640cde1SColin Riley if (log) 11964640cde1SColin Riley log->Printf ("RenderScriptRuntime::FixupScriptDetails - Error: script %" PRIx64 " wants reassigned to new rsmodule '%s'.", 119778f339d1SEwan Crawford (uint64_t)script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString()); 11984640cde1SColin Riley } 11994640cde1SColin Riley } 120078f339d1SEwan Crawford // We don't have a script mapping for the current script. 12014640cde1SColin Riley else 12024640cde1SColin Riley { 120378f339d1SEwan Crawford // Obtain the script resource name. 120478f339d1SEwan Crawford std::string resName; 120578f339d1SEwan Crawford if (rs_script->resName.get(resName)) 120678f339d1SEwan Crawford // Set the modules resource name. 120778f339d1SEwan Crawford rsmodule_sp->m_resname = resName; 120878f339d1SEwan Crawford // Add Script/Module pair to map. 120978f339d1SEwan Crawford m_scriptMappings[script] = rsmodule_sp; 12104640cde1SColin Riley if (log) 12114640cde1SColin Riley log->Printf ("RenderScriptRuntime::FixupScriptDetails - script %" PRIx64 " associated with rsmodule '%s'.", 121278f339d1SEwan Crawford (uint64_t)script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString()); 12134640cde1SColin Riley } 12144640cde1SColin Riley } 12154640cde1SColin Riley } 12164640cde1SColin Riley 121715f2bd95SEwan Crawford // Uses the Target API to evaluate the expression passed as a parameter to the function 121815f2bd95SEwan Crawford // The result of that expression is returned an unsigned 64 bit int, via the result* paramter. 121915f2bd95SEwan Crawford // Function returns true on success, and false on failure 122015f2bd95SEwan Crawford bool 122115f2bd95SEwan Crawford RenderScriptRuntime::EvalRSExpression(const char* expression, StackFrame* frame_ptr, uint64_t* result) 122215f2bd95SEwan Crawford { 122315f2bd95SEwan Crawford Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 122415f2bd95SEwan Crawford if (log) 122515f2bd95SEwan Crawford log->Printf("RenderScriptRuntime::EvalRSExpression(%s)", expression); 122615f2bd95SEwan Crawford 122715f2bd95SEwan Crawford ValueObjectSP expr_result; 122815f2bd95SEwan Crawford // Perform the actual expression evaluation 122915f2bd95SEwan Crawford GetProcess()->GetTarget().EvaluateExpression(expression, frame_ptr, expr_result); 123015f2bd95SEwan Crawford 123115f2bd95SEwan Crawford if (!expr_result) 123215f2bd95SEwan Crawford { 123315f2bd95SEwan Crawford if (log) 123415f2bd95SEwan Crawford log->Printf("RenderScriptRuntime::EvalRSExpression - Error: Couldn't evaluate expression"); 123515f2bd95SEwan Crawford return false; 123615f2bd95SEwan Crawford } 123715f2bd95SEwan Crawford 123815f2bd95SEwan Crawford // The result of the expression is invalid 123915f2bd95SEwan Crawford if (!expr_result->GetError().Success()) 124015f2bd95SEwan Crawford { 124115f2bd95SEwan Crawford Error err = expr_result->GetError(); 124215f2bd95SEwan Crawford if (err.GetError() == UserExpression::kNoResult) // Expression returned void, so this is actually a success 124315f2bd95SEwan Crawford { 124415f2bd95SEwan Crawford if (log) 124515f2bd95SEwan Crawford log->Printf("RenderScriptRuntime::EvalRSExpression - Expression returned void"); 124615f2bd95SEwan Crawford 124715f2bd95SEwan Crawford result = nullptr; 124815f2bd95SEwan Crawford return true; 124915f2bd95SEwan Crawford } 125015f2bd95SEwan Crawford 125115f2bd95SEwan Crawford if (log) 125215f2bd95SEwan Crawford log->Printf("RenderScriptRuntime::EvalRSExpression - Error evaluating expression result: %s", err.AsCString()); 125315f2bd95SEwan Crawford return false; 125415f2bd95SEwan Crawford } 125515f2bd95SEwan Crawford 125615f2bd95SEwan Crawford bool success = false; 125715f2bd95SEwan Crawford *result = expr_result->GetValueAsUnsigned(0, &success); // We only read the result as an unsigned int. 125815f2bd95SEwan Crawford 125915f2bd95SEwan Crawford if (!success) 126015f2bd95SEwan Crawford { 126115f2bd95SEwan Crawford if (log) 126215f2bd95SEwan Crawford log->Printf("RenderScriptRuntime::EvalRSExpression - Error: Couldn't convert expression result to unsigned int"); 126315f2bd95SEwan Crawford return false; 126415f2bd95SEwan Crawford } 126515f2bd95SEwan Crawford 126615f2bd95SEwan Crawford return true; 126715f2bd95SEwan Crawford } 126815f2bd95SEwan Crawford 1269b1651b8dSEwan Crawford namespace // anonymous 127015f2bd95SEwan Crawford { 1271b1651b8dSEwan Crawford // max length of an expanded expression 1272b1651b8dSEwan Crawford const int jit_max_expr_size = 768; 127315f2bd95SEwan Crawford 127415f2bd95SEwan Crawford // Format strings containing the expressions we may need to evaluate. 127515f2bd95SEwan Crawford const char runtimeExpressions[][256] = 127615f2bd95SEwan Crawford { 127715f2bd95SEwan Crawford // Mangled GetOffsetPointer(Allocation*, xoff, yoff, zoff, lod, cubemap) 127815f2bd95SEwan Crawford "(int*)_Z12GetOffsetPtrPKN7android12renderscript10AllocationEjjjj23RsAllocationCubemapFace(0x%lx, %u, %u, %u, 0, 0)", 127915f2bd95SEwan Crawford 128015f2bd95SEwan Crawford // Type* rsaAllocationGetType(Context*, Allocation*) 128115f2bd95SEwan Crawford "(void*)rsaAllocationGetType(0x%lx, 0x%lx)", 128215f2bd95SEwan Crawford 128315f2bd95SEwan Crawford // rsaTypeGetNativeData(Context*, Type*, void* typeData, size) 128415f2bd95SEwan Crawford // Pack the data in the following way mHal.state.dimX; mHal.state.dimY; mHal.state.dimZ; 128515f2bd95SEwan Crawford // mHal.state.lodCount; mHal.state.faces; mElement; into typeData 128615f2bd95SEwan Crawford // Need to specify 32 or 64 bit for uint_t since this differs between devices 128715f2bd95SEwan Crawford "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[0]", // X dim 128815f2bd95SEwan Crawford "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[1]", // Y dim 128915f2bd95SEwan Crawford "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[2]", // Z dim 129015f2bd95SEwan Crawford "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[5]", // Element ptr 129115f2bd95SEwan Crawford 129215f2bd95SEwan Crawford // rsaElementGetNativeData(Context*, Element*, uint32_t* elemData,size) 129315f2bd95SEwan Crawford // Pack mType; mKind; mNormalized; mVectorSize; NumSubElements into elemData 12948b244e21SEwan Crawford "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[0]", // Type 12958b244e21SEwan Crawford "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[1]", // Kind 12968b244e21SEwan Crawford "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[3]", // Vector Size 12978b244e21SEwan Crawford "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[4]", // Field Count 12988b244e21SEwan Crawford 12998b244e21SEwan Crawford // rsaElementGetSubElements(RsContext con, RsElement elem, uintptr_t *ids, const char **names, 13008b244e21SEwan Crawford // size_t *arraySizes, uint32_t dataSize) 13018b244e21SEwan Crawford // Needed for Allocations of structs to gather details about fields/Subelements 13028b244e21SEwan Crawford "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];" 13038b244e21SEwan Crawford "(void*)rsaElementGetSubElements(0x%lx, 0x%lx, ids, names, arr_size, %u); ids[%u]", // Element* of field 13048b244e21SEwan Crawford 13058b244e21SEwan Crawford "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];" 13068b244e21SEwan Crawford "(void*)rsaElementGetSubElements(0x%lx, 0x%lx, ids, names, arr_size, %u); names[%u]", // Name of field 13078b244e21SEwan Crawford 13088b244e21SEwan Crawford "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];" 13098b244e21SEwan Crawford "(void*)rsaElementGetSubElements(0x%lx, 0x%lx, ids, names, arr_size, %u); arr_size[%u]" // Array size of field 131015f2bd95SEwan Crawford }; 131115f2bd95SEwan Crawford 1312b1651b8dSEwan Crawford 1313b1651b8dSEwan Crawford // Temporary workaround for MIPS, until the compiler emits the JAL instruction when invoking directly the function. 1314b1651b8dSEwan Crawford // At the moment, when evaluating an expression involving a function call, the LLVM codegen for Mips emits a JAL 1315b1651b8dSEwan Crawford // instruction, which is able to jump in the range +/- 128MB with respect to the current program counter ($pc). If 1316b1651b8dSEwan Crawford // the requested function happens to reside outside the above region, the function address will be truncated and the 1317b1651b8dSEwan Crawford // function invocation will fail. This is a problem in the RS plugin as we rely on the RS API to probe the number and 1318b1651b8dSEwan Crawford // the nature of allocations. A proper solution in the MIPS compiler is currently being investigated. As temporary 1319b1651b8dSEwan Crawford // work around for this context, we'll invoke the RS API through function pointers, which cause the compiler to emit a 1320b1651b8dSEwan Crawford // register based JALR instruction. 1321b1651b8dSEwan Crawford const char runtimeExpressions_mips[][512] = 1322b1651b8dSEwan Crawford { 1323b1651b8dSEwan Crawford // Mangled GetOffsetPointer(Allocation*, xoff, yoff, zoff, lod, cubemap) 1324b1651b8dSEwan Crawford "int* (*f) (void*, int, int, int, int, int) = (int* (*) (void*, int, int, int, int, int)) " 1325b1651b8dSEwan Crawford "_Z12GetOffsetPtrPKN7android12renderscript10AllocationEjjjj23RsAllocationCubemapFace; " 1326b1651b8dSEwan Crawford "(int*) f((void*) 0x%lx, %u, %u, %u, 0, 0)", 1327b1651b8dSEwan Crawford 1328b1651b8dSEwan Crawford // Type* rsaAllocationGetType(Context*, Allocation*) 1329b1651b8dSEwan Crawford "void* (*f) (void*, void*) = (void* (*) (void*, void*)) rsaAllocationGetType; (void*) f((void*) 0x%lx, (void*) 0x%lx)", 1330b1651b8dSEwan Crawford 1331b1651b8dSEwan Crawford // rsaTypeGetNativeData(Context*, Type*, void* typeData, size) 1332b1651b8dSEwan Crawford // Pack the data in the following way mHal.state.dimX; mHal.state.dimY; mHal.state.dimZ; 1333b1651b8dSEwan Crawford // mHal.state.lodCount; mHal.state.faces; mElement; into typeData 1334b1651b8dSEwan Crawford // Need to specify 32 or 64 bit for uint_t since this differs between devices 1335b1651b8dSEwan Crawford "uint%u_t data[6]; void* (*f)(void*, void*, uintptr_t*, uint32_t) = (void* (*)(void*, void*, uintptr_t*, uint32_t)) " 1336b1651b8dSEwan Crawford "rsaTypeGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 6); data[0]", 1337b1651b8dSEwan Crawford "uint%u_t data[6]; void* (*f)(void*, void*, uintptr_t*, uint32_t) = (void* (*)(void*, void*, uintptr_t*, uint32_t)) " 1338b1651b8dSEwan Crawford "rsaTypeGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 6); data[1]", 1339b1651b8dSEwan Crawford "uint%u_t data[6]; void* (*f)(void*, void*, uintptr_t*, uint32_t) = (void* (*)(void*, void*, uintptr_t*, uint32_t)) " 1340b1651b8dSEwan Crawford "rsaTypeGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 6); data[2]", 1341b1651b8dSEwan Crawford "uint%u_t data[6]; void* (*f)(void*, void*, uintptr_t*, uint32_t) = (void* (*)(void*, void*, uintptr_t*, uint32_t)) " 1342b1651b8dSEwan Crawford "rsaTypeGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 6); data[5]", 1343b1651b8dSEwan Crawford 1344b1651b8dSEwan Crawford // rsaElementGetNativeData(Context*, Element*, uint32_t* elemData,size) 1345b1651b8dSEwan Crawford // Pack mType; mKind; mNormalized; mVectorSize; NumSubElements into elemData 1346b1651b8dSEwan Crawford "uint32_t data[5]; void* (*f)(void*, void*, uint32_t*, uint32_t) = (void* (*)(void*, void*, uint32_t*, uint32_t)) " 1347b1651b8dSEwan Crawford "rsaElementGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 5); data[0]", // Type 1348b1651b8dSEwan Crawford "uint32_t data[5]; void* (*f)(void*, void*, uint32_t*, uint32_t) = (void* (*)(void*, void*, uint32_t*, uint32_t)) " 1349b1651b8dSEwan Crawford "rsaElementGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 5); data[1]", // Kind 1350b1651b8dSEwan Crawford "uint32_t data[5]; void* (*f)(void*, void*, uint32_t*, uint32_t) = (void* (*)(void*, void*, uint32_t*, uint32_t)) " 1351b1651b8dSEwan Crawford "rsaElementGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 5); data[3]", // Vector size 1352b1651b8dSEwan Crawford "uint32_t data[5]; void* (*f)(void*, void*, uint32_t*, uint32_t) = (void* (*)(void*, void*, uint32_t*, uint32_t)) " 1353b1651b8dSEwan Crawford "rsaElementGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 5); data[4]", // Field count 1354b1651b8dSEwan Crawford 1355b1651b8dSEwan Crawford // rsaElementGetSubElements(RsContext con, RsElement elem, uintptr_t *ids, const char **names, 1356b1651b8dSEwan Crawford // size_t *arraySizes, uint32_t dataSize) 1357b1651b8dSEwan Crawford // Needed for Allocations of structs to gather details about fields/Subelements 1358b1651b8dSEwan Crawford "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];" 1359b1651b8dSEwan Crawford "void* (*f) (void*, void*, uintptr_t*, const char**, size_t*, uint32_t) = " 1360b1651b8dSEwan Crawford "(void* (*) (void*, void*, uintptr_t*, const char**, size_t*, uint32_t)) rsaElementGetSubElements;" 1361b1651b8dSEwan Crawford "(void*) f((void*) 0x%lx, (void*) 0x%lx, (uintptr_t*) ids, names, arr_size, (uint32_t) %u);" 1362b1651b8dSEwan Crawford "ids[%u]", // Element* of field 1363b1651b8dSEwan Crawford "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];" 1364b1651b8dSEwan Crawford "void* (*f) (void*, void*, uintptr_t*, const char**, size_t*, uint32_t) = " 1365b1651b8dSEwan Crawford "(void* (*) (void*, void*, uintptr_t*, const char**, size_t*, uint32_t)) rsaElementGetSubElements;" 1366b1651b8dSEwan Crawford "(void*) f((void*) 0x%lx, (void*) 0x%lx, (uintptr_t*) ids, names, arr_size, (uint32_t) %u);" 1367b1651b8dSEwan Crawford "names[%u]", // Name of field 1368b1651b8dSEwan Crawford "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];" 1369b1651b8dSEwan Crawford "void* (*f) (void*, void*, uintptr_t*, const char**, size_t*, uint32_t) = " 1370b1651b8dSEwan Crawford "(void* (*) (void*, void*, uintptr_t*, const char**, size_t*, uint32_t)) rsaElementGetSubElements;" 1371b1651b8dSEwan Crawford "(void*) f((void*) 0x%lx, (void*) 0x%lx, (uintptr_t*) ids, names, arr_size, (uint32_t) %u);" 1372b1651b8dSEwan Crawford "arr_size[%u]" // Array size of field 1373b1651b8dSEwan Crawford }; 1374b1651b8dSEwan Crawford 1375b1651b8dSEwan Crawford } // end of the anonymous namespace 1376b1651b8dSEwan Crawford 1377b1651b8dSEwan Crawford 1378b1651b8dSEwan Crawford // Retrieve the string to JIT for the given expression 1379b1651b8dSEwan Crawford const char* 1380b1651b8dSEwan Crawford RenderScriptRuntime::JITTemplate(ExpressionStrings e) 1381b1651b8dSEwan Crawford { 1382b1651b8dSEwan Crawford // be nice to your Mips friend when adding new expression strings 1383b1651b8dSEwan Crawford static_assert(sizeof(runtimeExpressions)/sizeof(runtimeExpressions[0]) == 1384b1651b8dSEwan Crawford sizeof(runtimeExpressions_mips)/sizeof(runtimeExpressions_mips[0]), 1385b1651b8dSEwan Crawford "#runtimeExpressions != #runtimeExpressions_mips"); 1386b1651b8dSEwan Crawford 1387b1651b8dSEwan Crawford assert((e >= eExprGetOffsetPtr && e <= eExprSubelementsArrSize) && 1388b1651b8dSEwan Crawford "Expression string out of bounds"); 1389b1651b8dSEwan Crawford 1390b1651b8dSEwan Crawford llvm::Triple::ArchType arch = GetTargetRef().GetArchitecture().GetMachine(); 1391b1651b8dSEwan Crawford 1392b1651b8dSEwan Crawford // mips JAL workaround 1393b1651b8dSEwan Crawford if(arch == llvm::Triple::ArchType::mips64el || arch == llvm::Triple::ArchType::mipsel) 1394b1651b8dSEwan Crawford return runtimeExpressions_mips[e]; 1395b1651b8dSEwan Crawford else 1396b1651b8dSEwan Crawford return runtimeExpressions[e]; 1397b1651b8dSEwan Crawford } 1398b1651b8dSEwan Crawford 1399b1651b8dSEwan Crawford 140015f2bd95SEwan Crawford // JITs the RS runtime for the internal data pointer of an allocation. 140115f2bd95SEwan Crawford // Is passed x,y,z coordinates for the pointer to a specific element. 140215f2bd95SEwan Crawford // Then sets the data_ptr member in Allocation with the result. 140315f2bd95SEwan Crawford // Returns true on success, false otherwise 140415f2bd95SEwan Crawford bool 140515f2bd95SEwan Crawford RenderScriptRuntime::JITDataPointer(AllocationDetails* allocation, StackFrame* frame_ptr, 140615f2bd95SEwan Crawford unsigned int x, unsigned int y, unsigned int z) 140715f2bd95SEwan Crawford { 140815f2bd95SEwan Crawford Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 140915f2bd95SEwan Crawford 141015f2bd95SEwan Crawford if (!allocation->address.isValid()) 141115f2bd95SEwan Crawford { 141215f2bd95SEwan Crawford if (log) 141315f2bd95SEwan Crawford log->Printf("RenderScriptRuntime::JITDataPointer - Failed to find allocation details"); 141415f2bd95SEwan Crawford return false; 141515f2bd95SEwan Crawford } 141615f2bd95SEwan Crawford 1417b1651b8dSEwan Crawford const char* expr_cstr = JITTemplate(eExprGetOffsetPtr); 1418b1651b8dSEwan Crawford char buffer[jit_max_expr_size]; 141915f2bd95SEwan Crawford 1420b1651b8dSEwan Crawford int chars_written = snprintf(buffer, jit_max_expr_size, expr_cstr, *allocation->address.get(), x, y, z); 142115f2bd95SEwan Crawford if (chars_written < 0) 142215f2bd95SEwan Crawford { 142315f2bd95SEwan Crawford if (log) 142415f2bd95SEwan Crawford log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()"); 142515f2bd95SEwan Crawford return false; 142615f2bd95SEwan Crawford } 1427b1651b8dSEwan Crawford else if (chars_written >= jit_max_expr_size) 142815f2bd95SEwan Crawford { 142915f2bd95SEwan Crawford if (log) 143015f2bd95SEwan Crawford log->Printf("RenderScriptRuntime::JITDataPointer - Expression too long"); 143115f2bd95SEwan Crawford return false; 143215f2bd95SEwan Crawford } 143315f2bd95SEwan Crawford 143415f2bd95SEwan Crawford uint64_t result = 0; 143515f2bd95SEwan Crawford if (!EvalRSExpression(buffer, frame_ptr, &result)) 143615f2bd95SEwan Crawford return false; 143715f2bd95SEwan Crawford 143815f2bd95SEwan Crawford addr_t mem_ptr = static_cast<lldb::addr_t>(result); 143915f2bd95SEwan Crawford allocation->data_ptr = mem_ptr; 144015f2bd95SEwan Crawford 144115f2bd95SEwan Crawford return true; 144215f2bd95SEwan Crawford } 144315f2bd95SEwan Crawford 144415f2bd95SEwan Crawford // JITs the RS runtime for the internal pointer to the RS Type of an allocation 144515f2bd95SEwan Crawford // Then sets the type_ptr member in Allocation with the result. 144615f2bd95SEwan Crawford // Returns true on success, false otherwise 144715f2bd95SEwan Crawford bool 144815f2bd95SEwan Crawford RenderScriptRuntime::JITTypePointer(AllocationDetails* allocation, StackFrame* frame_ptr) 144915f2bd95SEwan Crawford { 145015f2bd95SEwan Crawford Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 145115f2bd95SEwan Crawford 145215f2bd95SEwan Crawford if (!allocation->address.isValid() || !allocation->context.isValid()) 145315f2bd95SEwan Crawford { 145415f2bd95SEwan Crawford if (log) 145515f2bd95SEwan Crawford log->Printf("RenderScriptRuntime::JITTypePointer - Failed to find allocation details"); 145615f2bd95SEwan Crawford return false; 145715f2bd95SEwan Crawford } 145815f2bd95SEwan Crawford 1459b1651b8dSEwan Crawford const char* expr_cstr = JITTemplate(eExprAllocGetType); 1460b1651b8dSEwan Crawford char buffer[jit_max_expr_size]; 146115f2bd95SEwan Crawford 1462b1651b8dSEwan Crawford int chars_written = snprintf(buffer, jit_max_expr_size, expr_cstr, *allocation->context.get(), *allocation->address.get()); 146315f2bd95SEwan Crawford if (chars_written < 0) 146415f2bd95SEwan Crawford { 146515f2bd95SEwan Crawford if (log) 146615f2bd95SEwan Crawford log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()"); 146715f2bd95SEwan Crawford return false; 146815f2bd95SEwan Crawford } 1469b1651b8dSEwan Crawford else if (chars_written >= jit_max_expr_size) 147015f2bd95SEwan Crawford { 147115f2bd95SEwan Crawford if (log) 147215f2bd95SEwan Crawford log->Printf("RenderScriptRuntime::JITTypePointer - Expression too long"); 147315f2bd95SEwan Crawford return false; 147415f2bd95SEwan Crawford } 147515f2bd95SEwan Crawford 147615f2bd95SEwan Crawford uint64_t result = 0; 147715f2bd95SEwan Crawford if (!EvalRSExpression(buffer, frame_ptr, &result)) 147815f2bd95SEwan Crawford return false; 147915f2bd95SEwan Crawford 148015f2bd95SEwan Crawford addr_t type_ptr = static_cast<lldb::addr_t>(result); 148115f2bd95SEwan Crawford allocation->type_ptr = type_ptr; 148215f2bd95SEwan Crawford 148315f2bd95SEwan Crawford return true; 148415f2bd95SEwan Crawford } 148515f2bd95SEwan Crawford 148615f2bd95SEwan Crawford // JITs the RS runtime for information about the dimensions and type of an allocation 148715f2bd95SEwan Crawford // Then sets dimension and element_ptr members in Allocation with the result. 148815f2bd95SEwan Crawford // Returns true on success, false otherwise 148915f2bd95SEwan Crawford bool 149015f2bd95SEwan Crawford RenderScriptRuntime::JITTypePacked(AllocationDetails* allocation, StackFrame* frame_ptr) 149115f2bd95SEwan Crawford { 149215f2bd95SEwan Crawford Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 149315f2bd95SEwan Crawford 149415f2bd95SEwan Crawford if (!allocation->type_ptr.isValid() || !allocation->context.isValid()) 149515f2bd95SEwan Crawford { 149615f2bd95SEwan Crawford if (log) 149715f2bd95SEwan Crawford log->Printf("RenderScriptRuntime::JITTypePacked - Failed to find allocation details"); 149815f2bd95SEwan Crawford return false; 149915f2bd95SEwan Crawford } 150015f2bd95SEwan Crawford 150115f2bd95SEwan Crawford // Expression is different depending on if device is 32 or 64 bit 150215f2bd95SEwan Crawford uint32_t archByteSize = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize(); 150315f2bd95SEwan Crawford const unsigned int bits = archByteSize == 4 ? 32 : 64; 150415f2bd95SEwan Crawford 150515f2bd95SEwan Crawford // We want 4 elements from packed data 150615f2bd95SEwan Crawford const unsigned int num_exprs = 4; 150715f2bd95SEwan Crawford assert(num_exprs == (eExprTypeElemPtr - eExprTypeDimX + 1) && "Invalid number of expressions"); 150815f2bd95SEwan Crawford 1509b1651b8dSEwan Crawford char buffer[num_exprs][jit_max_expr_size]; 151015f2bd95SEwan Crawford uint64_t results[num_exprs]; 151115f2bd95SEwan Crawford 151215f2bd95SEwan Crawford for (unsigned int i = 0; i < num_exprs; ++i) 151315f2bd95SEwan Crawford { 1514b1651b8dSEwan Crawford const char* expr_cstr = JITTemplate((ExpressionStrings) (eExprTypeDimX + i)); 1515b1651b8dSEwan Crawford int chars_written = snprintf(buffer[i], jit_max_expr_size, expr_cstr, bits, 151615f2bd95SEwan Crawford *allocation->context.get(), *allocation->type_ptr.get()); 151715f2bd95SEwan Crawford if (chars_written < 0) 151815f2bd95SEwan Crawford { 151915f2bd95SEwan Crawford if (log) 152015f2bd95SEwan Crawford log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()"); 152115f2bd95SEwan Crawford return false; 152215f2bd95SEwan Crawford } 1523b1651b8dSEwan Crawford else if (chars_written >= jit_max_expr_size) 152415f2bd95SEwan Crawford { 152515f2bd95SEwan Crawford if (log) 152615f2bd95SEwan Crawford log->Printf("RenderScriptRuntime::JITTypePacked - Expression too long"); 152715f2bd95SEwan Crawford return false; 152815f2bd95SEwan Crawford } 152915f2bd95SEwan Crawford 153015f2bd95SEwan Crawford // Perform expression evaluation 153115f2bd95SEwan Crawford if (!EvalRSExpression(buffer[i], frame_ptr, &results[i])) 153215f2bd95SEwan Crawford return false; 153315f2bd95SEwan Crawford } 153415f2bd95SEwan Crawford 153515f2bd95SEwan Crawford // Assign results to allocation members 153615f2bd95SEwan Crawford AllocationDetails::Dimension dims; 153715f2bd95SEwan Crawford dims.dim_1 = static_cast<uint32_t>(results[0]); 153815f2bd95SEwan Crawford dims.dim_2 = static_cast<uint32_t>(results[1]); 153915f2bd95SEwan Crawford dims.dim_3 = static_cast<uint32_t>(results[2]); 154015f2bd95SEwan Crawford allocation->dimension = dims; 154115f2bd95SEwan Crawford 154215f2bd95SEwan Crawford addr_t elem_ptr = static_cast<lldb::addr_t>(results[3]); 15438b244e21SEwan Crawford allocation->element.element_ptr = elem_ptr; 154415f2bd95SEwan Crawford 154515f2bd95SEwan Crawford if (log) 154615f2bd95SEwan Crawford log->Printf("RenderScriptRuntime::JITTypePacked - dims (%u, %u, %u) Element*: 0x%" PRIx64, 154715f2bd95SEwan Crawford dims.dim_1, dims.dim_2, dims.dim_3, elem_ptr); 154815f2bd95SEwan Crawford 154915f2bd95SEwan Crawford return true; 155015f2bd95SEwan Crawford } 155115f2bd95SEwan Crawford 155215f2bd95SEwan Crawford // JITs the RS runtime for information about the Element of an allocation 15538b244e21SEwan Crawford // Then sets type, type_vec_size, field_count and type_kind members in Element with the result. 155415f2bd95SEwan Crawford // Returns true on success, false otherwise 155515f2bd95SEwan Crawford bool 15568b244e21SEwan Crawford RenderScriptRuntime::JITElementPacked(Element& elem, const lldb::addr_t context, StackFrame* frame_ptr) 155715f2bd95SEwan Crawford { 155815f2bd95SEwan Crawford Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 155915f2bd95SEwan Crawford 15608b244e21SEwan Crawford if (!elem.element_ptr.isValid()) 156115f2bd95SEwan Crawford { 156215f2bd95SEwan Crawford if (log) 156315f2bd95SEwan Crawford log->Printf("RenderScriptRuntime::JITElementPacked - Failed to find allocation details"); 156415f2bd95SEwan Crawford return false; 156515f2bd95SEwan Crawford } 156615f2bd95SEwan Crawford 15678b244e21SEwan Crawford // We want 4 elements from packed data 15688b244e21SEwan Crawford const unsigned int num_exprs = 4; 15698b244e21SEwan Crawford assert(num_exprs == (eExprElementFieldCount - eExprElementType + 1) && "Invalid number of expressions"); 157015f2bd95SEwan Crawford 1571b1651b8dSEwan Crawford char buffer[num_exprs][jit_max_expr_size]; 157215f2bd95SEwan Crawford uint64_t results[num_exprs]; 157315f2bd95SEwan Crawford 157415f2bd95SEwan Crawford for (unsigned int i = 0; i < num_exprs; i++) 157515f2bd95SEwan Crawford { 1576b1651b8dSEwan Crawford const char* expr_cstr = JITTemplate((ExpressionStrings) (eExprElementType + i)); 1577b1651b8dSEwan Crawford int chars_written = snprintf(buffer[i], jit_max_expr_size, expr_cstr, context, *elem.element_ptr.get()); 157815f2bd95SEwan Crawford if (chars_written < 0) 157915f2bd95SEwan Crawford { 158015f2bd95SEwan Crawford if (log) 15818b244e21SEwan Crawford log->Printf("RenderScriptRuntime::JITElementPacked - Encoding error in snprintf()"); 158215f2bd95SEwan Crawford return false; 158315f2bd95SEwan Crawford } 1584b1651b8dSEwan Crawford else if (chars_written >= jit_max_expr_size) 158515f2bd95SEwan Crawford { 158615f2bd95SEwan Crawford if (log) 158715f2bd95SEwan Crawford log->Printf("RenderScriptRuntime::JITElementPacked - Expression too long"); 158815f2bd95SEwan Crawford return false; 158915f2bd95SEwan Crawford } 159015f2bd95SEwan Crawford 159115f2bd95SEwan Crawford // Perform expression evaluation 159215f2bd95SEwan Crawford if (!EvalRSExpression(buffer[i], frame_ptr, &results[i])) 159315f2bd95SEwan Crawford return false; 159415f2bd95SEwan Crawford } 159515f2bd95SEwan Crawford 159615f2bd95SEwan Crawford // Assign results to allocation members 15978b244e21SEwan Crawford elem.type = static_cast<RenderScriptRuntime::Element::DataType>(results[0]); 15988b244e21SEwan Crawford elem.type_kind = static_cast<RenderScriptRuntime::Element::DataKind>(results[1]); 15998b244e21SEwan Crawford elem.type_vec_size = static_cast<uint32_t>(results[2]); 16008b244e21SEwan Crawford elem.field_count = static_cast<uint32_t>(results[3]); 160115f2bd95SEwan Crawford 160215f2bd95SEwan Crawford if (log) 16038b244e21SEwan Crawford log->Printf("RenderScriptRuntime::JITElementPacked - data type %u, pixel type %u, vector size %u, field count %u", 16048b244e21SEwan Crawford *elem.type.get(), *elem.type_kind.get(), *elem.type_vec_size.get(), *elem.field_count.get()); 16058b244e21SEwan Crawford 16068b244e21SEwan Crawford // If this Element has subelements then JIT rsaElementGetSubElements() for details about its fields 16078b244e21SEwan Crawford if (*elem.field_count.get() > 0 && !JITSubelements(elem, context, frame_ptr)) 16088b244e21SEwan Crawford return false; 16098b244e21SEwan Crawford 16108b244e21SEwan Crawford return true; 16118b244e21SEwan Crawford } 16128b244e21SEwan Crawford 16138b244e21SEwan Crawford // JITs the RS runtime for information about the subelements/fields of a struct allocation 16148b244e21SEwan Crawford // This is necessary for infering the struct type so we can pretty print the allocation's contents. 16158b244e21SEwan Crawford // Returns true on success, false otherwise 16168b244e21SEwan Crawford bool 16178b244e21SEwan Crawford RenderScriptRuntime::JITSubelements(Element& elem, const lldb::addr_t context, StackFrame* frame_ptr) 16188b244e21SEwan Crawford { 16198b244e21SEwan Crawford Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 16208b244e21SEwan Crawford 16218b244e21SEwan Crawford if (!elem.element_ptr.isValid() || !elem.field_count.isValid()) 16228b244e21SEwan Crawford { 16238b244e21SEwan Crawford if (log) 16248b244e21SEwan Crawford log->Printf("RenderScriptRuntime::JITSubelements - Failed to find allocation details"); 16258b244e21SEwan Crawford return false; 16268b244e21SEwan Crawford } 16278b244e21SEwan Crawford 16288b244e21SEwan Crawford const short num_exprs = 3; 16298b244e21SEwan Crawford assert(num_exprs == (eExprSubelementsArrSize - eExprSubelementsId + 1) && "Invalid number of expressions"); 16308b244e21SEwan Crawford 1631b1651b8dSEwan Crawford char expr_buffer[jit_max_expr_size]; 16328b244e21SEwan Crawford uint64_t results; 16338b244e21SEwan Crawford 16348b244e21SEwan Crawford // Iterate over struct fields. 16358b244e21SEwan Crawford const uint32_t field_count = *elem.field_count.get(); 16368b244e21SEwan Crawford for (unsigned int field_index = 0; field_index < field_count; ++field_index) 16378b244e21SEwan Crawford { 16388b244e21SEwan Crawford Element child; 16398b244e21SEwan Crawford for (unsigned int expr_index = 0; expr_index < num_exprs; ++expr_index) 16408b244e21SEwan Crawford { 1641b1651b8dSEwan Crawford const char* expr_cstr = JITTemplate((ExpressionStrings) (eExprSubelementsId + expr_index)); 1642b1651b8dSEwan Crawford int chars_written = snprintf(expr_buffer, jit_max_expr_size, expr_cstr, 16438b244e21SEwan Crawford field_count, field_count, field_count, 16448b244e21SEwan Crawford context, *elem.element_ptr.get(), field_count, field_index); 16458b244e21SEwan Crawford if (chars_written < 0) 16468b244e21SEwan Crawford { 16478b244e21SEwan Crawford if (log) 16488b244e21SEwan Crawford log->Printf("RenderScriptRuntime::JITSubelements - Encoding error in snprintf()"); 16498b244e21SEwan Crawford return false; 16508b244e21SEwan Crawford } 1651b1651b8dSEwan Crawford else if (chars_written >= jit_max_expr_size) 16528b244e21SEwan Crawford { 16538b244e21SEwan Crawford if (log) 16548b244e21SEwan Crawford log->Printf("RenderScriptRuntime::JITSubelements - Expression too long"); 16558b244e21SEwan Crawford return false; 16568b244e21SEwan Crawford } 16578b244e21SEwan Crawford 16588b244e21SEwan Crawford // Perform expression evaluation 16598b244e21SEwan Crawford if (!EvalRSExpression(expr_buffer, frame_ptr, &results)) 16608b244e21SEwan Crawford return false; 16618b244e21SEwan Crawford 16628b244e21SEwan Crawford if (log) 16638b244e21SEwan Crawford log->Printf("RenderScriptRuntime::JITSubelements - Expr result 0x%" PRIx64, results); 16648b244e21SEwan Crawford 16658b244e21SEwan Crawford switch(expr_index) 16668b244e21SEwan Crawford { 16678b244e21SEwan Crawford case 0: // Element* of child 16688b244e21SEwan Crawford child.element_ptr = static_cast<addr_t>(results); 16698b244e21SEwan Crawford break; 16708b244e21SEwan Crawford case 1: // Name of child 16718b244e21SEwan Crawford { 16728b244e21SEwan Crawford lldb::addr_t address = static_cast<addr_t>(results); 16738b244e21SEwan Crawford Error err; 16748b244e21SEwan Crawford std::string name; 16758b244e21SEwan Crawford GetProcess()->ReadCStringFromMemory(address, name, err); 16768b244e21SEwan Crawford if (!err.Fail()) 16778b244e21SEwan Crawford child.type_name = ConstString(name); 16788b244e21SEwan Crawford else 16798b244e21SEwan Crawford { 16808b244e21SEwan Crawford if (log) 16818b244e21SEwan Crawford log->Printf("RenderScriptRuntime::JITSubelements - Warning: Couldn't read field name"); 16828b244e21SEwan Crawford } 16838b244e21SEwan Crawford break; 16848b244e21SEwan Crawford } 16858b244e21SEwan Crawford case 2: // Array size of child 16868b244e21SEwan Crawford child.array_size = static_cast<uint32_t>(results); 16878b244e21SEwan Crawford break; 16888b244e21SEwan Crawford } 16898b244e21SEwan Crawford } 16908b244e21SEwan Crawford 16918b244e21SEwan Crawford // We need to recursively JIT each Element field of the struct since 16928b244e21SEwan Crawford // structs can be nested inside structs. 16938b244e21SEwan Crawford if (!JITElementPacked(child, context, frame_ptr)) 16948b244e21SEwan Crawford return false; 16958b244e21SEwan Crawford elem.children.push_back(child); 16968b244e21SEwan Crawford } 16978b244e21SEwan Crawford 16988b244e21SEwan Crawford // Try to infer the name of the struct type so we can pretty print the allocation contents. 16998b244e21SEwan Crawford FindStructTypeName(elem, frame_ptr); 170015f2bd95SEwan Crawford 170115f2bd95SEwan Crawford return true; 170215f2bd95SEwan Crawford } 170315f2bd95SEwan Crawford 1704a0f08674SEwan Crawford // JITs the RS runtime for the address of the last element in the allocation. 1705a0f08674SEwan Crawford // The `elem_size` paramter represents the size of a single element, including padding. 1706a0f08674SEwan Crawford // Which is needed as an offset from the last element pointer. 1707a0f08674SEwan Crawford // Using this offset minus the starting address we can calculate the size of the allocation. 1708a0f08674SEwan Crawford // Returns true on success, false otherwise 1709a0f08674SEwan Crawford bool 17108b244e21SEwan Crawford RenderScriptRuntime::JITAllocationSize(AllocationDetails* allocation, StackFrame* frame_ptr) 1711a0f08674SEwan Crawford { 1712a0f08674SEwan Crawford Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 1713a0f08674SEwan Crawford 1714a0f08674SEwan Crawford if (!allocation->address.isValid() || !allocation->dimension.isValid() 17158b244e21SEwan Crawford || !allocation->data_ptr.isValid() || !allocation->element.datum_size.isValid()) 1716a0f08674SEwan Crawford { 1717a0f08674SEwan Crawford if (log) 1718a0f08674SEwan Crawford log->Printf("RenderScriptRuntime::JITAllocationSize - Failed to find allocation details"); 1719a0f08674SEwan Crawford return false; 1720a0f08674SEwan Crawford } 1721a0f08674SEwan Crawford 1722a0f08674SEwan Crawford // Find dimensions 1723a0f08674SEwan Crawford unsigned int dim_x = allocation->dimension.get()->dim_1; 1724a0f08674SEwan Crawford unsigned int dim_y = allocation->dimension.get()->dim_2; 1725a0f08674SEwan Crawford unsigned int dim_z = allocation->dimension.get()->dim_3; 1726a0f08674SEwan Crawford 17278b244e21SEwan Crawford // Our plan of jitting the last element address doesn't seem to work for struct Allocations 17288b244e21SEwan Crawford // Instead try to infer the size ourselves without any inter element padding. 17298b244e21SEwan Crawford if (allocation->element.children.size() > 0) 17308b244e21SEwan Crawford { 17318b244e21SEwan Crawford if (dim_x == 0) dim_x = 1; 17328b244e21SEwan Crawford if (dim_y == 0) dim_y = 1; 17338b244e21SEwan Crawford if (dim_z == 0) dim_z = 1; 17348b244e21SEwan Crawford 17358b244e21SEwan Crawford allocation->size = dim_x * dim_y * dim_z * *allocation->element.datum_size.get(); 17368b244e21SEwan Crawford 17378b244e21SEwan Crawford if (log) 17388b244e21SEwan Crawford log->Printf("RenderScriptRuntime::JITAllocationSize - Infered size of struct allocation %u", *allocation->size.get()); 17398b244e21SEwan Crawford 17408b244e21SEwan Crawford return true; 17418b244e21SEwan Crawford } 17428b244e21SEwan Crawford 1743b1651b8dSEwan Crawford const char* expr_cstr = JITTemplate(eExprGetOffsetPtr); 1744b1651b8dSEwan Crawford char buffer[jit_max_expr_size]; 17458b244e21SEwan Crawford 1746a0f08674SEwan Crawford // Calculate last element 1747a0f08674SEwan Crawford dim_x = dim_x == 0 ? 0 : dim_x - 1; 1748a0f08674SEwan Crawford dim_y = dim_y == 0 ? 0 : dim_y - 1; 1749a0f08674SEwan Crawford dim_z = dim_z == 0 ? 0 : dim_z - 1; 1750a0f08674SEwan Crawford 1751b1651b8dSEwan Crawford int chars_written = snprintf(buffer, jit_max_expr_size, expr_cstr, *allocation->address.get(), 1752a0f08674SEwan Crawford dim_x, dim_y, dim_z); 1753a0f08674SEwan Crawford if (chars_written < 0) 1754a0f08674SEwan Crawford { 1755a0f08674SEwan Crawford if (log) 1756a0f08674SEwan Crawford log->Printf("RenderScriptRuntime::JITAllocationSize - Encoding error in snprintf()"); 1757a0f08674SEwan Crawford return false; 1758a0f08674SEwan Crawford } 1759b1651b8dSEwan Crawford else if (chars_written >= jit_max_expr_size) 1760a0f08674SEwan Crawford { 1761a0f08674SEwan Crawford if (log) 1762a0f08674SEwan Crawford log->Printf("RenderScriptRuntime::JITAllocationSize - Expression too long"); 1763a0f08674SEwan Crawford return false; 1764a0f08674SEwan Crawford } 1765a0f08674SEwan Crawford 1766a0f08674SEwan Crawford uint64_t result = 0; 1767a0f08674SEwan Crawford if (!EvalRSExpression(buffer, frame_ptr, &result)) 1768a0f08674SEwan Crawford return false; 1769a0f08674SEwan Crawford 1770a0f08674SEwan Crawford addr_t mem_ptr = static_cast<lldb::addr_t>(result); 1771a0f08674SEwan Crawford // Find pointer to last element and add on size of an element 17728b244e21SEwan Crawford allocation->size = static_cast<uint32_t>(mem_ptr - *allocation->data_ptr.get()) + *allocation->element.datum_size.get(); 1773a0f08674SEwan Crawford 1774a0f08674SEwan Crawford return true; 1775a0f08674SEwan Crawford } 1776a0f08674SEwan Crawford 1777a0f08674SEwan Crawford // JITs the RS runtime for information about the stride between rows in the allocation. 1778a0f08674SEwan Crawford // This is done to detect padding, since allocated memory is 16-byte aligned. 1779a0f08674SEwan Crawford // Returns true on success, false otherwise 1780a0f08674SEwan Crawford bool 1781a0f08674SEwan Crawford RenderScriptRuntime::JITAllocationStride(AllocationDetails* allocation, StackFrame* frame_ptr) 1782a0f08674SEwan Crawford { 1783a0f08674SEwan Crawford Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 1784a0f08674SEwan Crawford 1785a0f08674SEwan Crawford if (!allocation->address.isValid() || !allocation->data_ptr.isValid()) 1786a0f08674SEwan Crawford { 1787a0f08674SEwan Crawford if (log) 1788a0f08674SEwan Crawford log->Printf("RenderScriptRuntime::JITAllocationStride - Failed to find allocation details"); 1789a0f08674SEwan Crawford return false; 1790a0f08674SEwan Crawford } 1791a0f08674SEwan Crawford 1792b1651b8dSEwan Crawford const char* expr_cstr = JITTemplate(eExprGetOffsetPtr); 1793b1651b8dSEwan Crawford char buffer[jit_max_expr_size]; 1794a0f08674SEwan Crawford 1795b1651b8dSEwan Crawford int chars_written = snprintf(buffer, jit_max_expr_size, expr_cstr, *allocation->address.get(), 1796a0f08674SEwan Crawford 0, 1, 0); 1797a0f08674SEwan Crawford if (chars_written < 0) 1798a0f08674SEwan Crawford { 1799a0f08674SEwan Crawford if (log) 1800a0f08674SEwan Crawford log->Printf("RenderScriptRuntime::JITAllocationStride - Encoding error in snprintf()"); 1801a0f08674SEwan Crawford return false; 1802a0f08674SEwan Crawford } 1803b1651b8dSEwan Crawford else if (chars_written >= jit_max_expr_size) 1804a0f08674SEwan Crawford { 1805a0f08674SEwan Crawford if (log) 1806a0f08674SEwan Crawford log->Printf("RenderScriptRuntime::JITAllocationStride - Expression too long"); 1807a0f08674SEwan Crawford return false; 1808a0f08674SEwan Crawford } 1809a0f08674SEwan Crawford 1810a0f08674SEwan Crawford uint64_t result = 0; 1811a0f08674SEwan Crawford if (!EvalRSExpression(buffer, frame_ptr, &result)) 1812a0f08674SEwan Crawford return false; 1813a0f08674SEwan Crawford 1814a0f08674SEwan Crawford addr_t mem_ptr = static_cast<lldb::addr_t>(result); 1815a0f08674SEwan Crawford allocation->stride = static_cast<uint32_t>(mem_ptr - *allocation->data_ptr.get()); 1816a0f08674SEwan Crawford 1817a0f08674SEwan Crawford return true; 1818a0f08674SEwan Crawford } 1819a0f08674SEwan Crawford 182015f2bd95SEwan Crawford // JIT all the current runtime info regarding an allocation 182115f2bd95SEwan Crawford bool 182215f2bd95SEwan Crawford RenderScriptRuntime::RefreshAllocation(AllocationDetails* allocation, StackFrame* frame_ptr) 182315f2bd95SEwan Crawford { 182415f2bd95SEwan Crawford // GetOffsetPointer() 182515f2bd95SEwan Crawford if (!JITDataPointer(allocation, frame_ptr)) 182615f2bd95SEwan Crawford return false; 182715f2bd95SEwan Crawford 182815f2bd95SEwan Crawford // rsaAllocationGetType() 182915f2bd95SEwan Crawford if (!JITTypePointer(allocation, frame_ptr)) 183015f2bd95SEwan Crawford return false; 183115f2bd95SEwan Crawford 183215f2bd95SEwan Crawford // rsaTypeGetNativeData() 183315f2bd95SEwan Crawford if (!JITTypePacked(allocation, frame_ptr)) 183415f2bd95SEwan Crawford return false; 183515f2bd95SEwan Crawford 183615f2bd95SEwan Crawford // rsaElementGetNativeData() 18378b244e21SEwan Crawford if (!JITElementPacked(allocation->element, *allocation->context.get(), frame_ptr)) 183815f2bd95SEwan Crawford return false; 183915f2bd95SEwan Crawford 18408b244e21SEwan Crawford // Sets the datum_size member in Element 18418b244e21SEwan Crawford SetElementSize(allocation->element); 18428b244e21SEwan Crawford 184355232f09SEwan Crawford // Use GetOffsetPointer() to infer size of the allocation 18448b244e21SEwan Crawford if (!JITAllocationSize(allocation, frame_ptr)) 184555232f09SEwan Crawford return false; 184655232f09SEwan Crawford 184755232f09SEwan Crawford return true; 184855232f09SEwan Crawford } 184955232f09SEwan Crawford 18508b244e21SEwan Crawford // Function attempts to set the type_name member of the paramaterised Element object. 18518b244e21SEwan Crawford // This string should be the name of the struct type the Element represents. 18528b244e21SEwan Crawford // We need this string for pretty printing the Element to users. 18538b244e21SEwan Crawford void 18548b244e21SEwan Crawford RenderScriptRuntime::FindStructTypeName(Element& elem, StackFrame* frame_ptr) 185555232f09SEwan Crawford { 18568b244e21SEwan Crawford Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 18578b244e21SEwan Crawford 18588b244e21SEwan Crawford if (!elem.type_name.IsEmpty()) // Name already set 18598b244e21SEwan Crawford return; 18608b244e21SEwan Crawford else 1861fe06b5adSAdrian McCarthy elem.type_name = Element::GetFallbackStructName(); // Default type name if we don't succeed 18628b244e21SEwan Crawford 18638b244e21SEwan Crawford // Find all the global variables from the script rs modules 18648b244e21SEwan Crawford VariableList variable_list; 18658b244e21SEwan Crawford for (auto module_sp : m_rsmodules) 18668b244e21SEwan Crawford module_sp->m_module->FindGlobalVariables(RegularExpression("."), true, UINT32_MAX, variable_list); 18678b244e21SEwan Crawford 18688b244e21SEwan Crawford // Iterate over all the global variables looking for one with a matching type to the Element. 18698b244e21SEwan Crawford // We make the assumption a match exists since there needs to be a global variable to reflect the 18708b244e21SEwan Crawford // struct type back into java host code. 18718b244e21SEwan Crawford for (uint32_t var_index = 0; var_index < variable_list.GetSize(); ++var_index) 18728b244e21SEwan Crawford { 18738b244e21SEwan Crawford const VariableSP var_sp(variable_list.GetVariableAtIndex(var_index)); 18748b244e21SEwan Crawford if (!var_sp) 18758b244e21SEwan Crawford continue; 18768b244e21SEwan Crawford 18778b244e21SEwan Crawford ValueObjectSP valobj_sp = ValueObjectVariable::Create(frame_ptr, var_sp); 18788b244e21SEwan Crawford if (!valobj_sp) 18798b244e21SEwan Crawford continue; 18808b244e21SEwan Crawford 18818b244e21SEwan Crawford // Find the number of variable fields. 18828b244e21SEwan Crawford // If it has no fields, or more fields than our Element, then it can't be the struct we're looking for. 18838b244e21SEwan Crawford // Don't check for equality since RS can add extra struct members for padding. 18848b244e21SEwan Crawford size_t num_children = valobj_sp->GetNumChildren(); 18858b244e21SEwan Crawford if (num_children > elem.children.size() || num_children == 0) 18868b244e21SEwan Crawford continue; 18878b244e21SEwan Crawford 18888b244e21SEwan Crawford // Iterate over children looking for members with matching field names. 18898b244e21SEwan Crawford // If all the field names match, this is likely the struct we want. 18908b244e21SEwan Crawford // 18918b244e21SEwan Crawford // TODO: This could be made more robust by also checking children data sizes, or array size 18928b244e21SEwan Crawford bool found = true; 18938b244e21SEwan Crawford for (size_t child_index = 0; child_index < num_children; ++child_index) 18948b244e21SEwan Crawford { 18958b244e21SEwan Crawford ValueObjectSP child = valobj_sp->GetChildAtIndex(child_index, true); 18968b244e21SEwan Crawford if (!child || (child->GetName() != elem.children[child_index].type_name)) 18978b244e21SEwan Crawford { 18988b244e21SEwan Crawford found = false; 18998b244e21SEwan Crawford break; 19008b244e21SEwan Crawford } 19018b244e21SEwan Crawford } 19028b244e21SEwan Crawford 19038b244e21SEwan Crawford // RS can add extra struct members for padding in the format '#rs_padding_[0-9]+' 19048b244e21SEwan Crawford if (found && num_children < elem.children.size()) 19058b244e21SEwan Crawford { 19068b244e21SEwan Crawford const unsigned int size_diff = elem.children.size() - num_children; 19078b244e21SEwan Crawford if (log) 19088b244e21SEwan Crawford log->Printf("RenderScriptRuntime::FindStructTypeName - %u padding struct entries", size_diff); 19098b244e21SEwan Crawford 19108b244e21SEwan Crawford for (unsigned int padding_index = 0; padding_index < size_diff; ++padding_index) 19118b244e21SEwan Crawford { 19128b244e21SEwan Crawford const ConstString& name = elem.children[num_children + padding_index].type_name; 19138b244e21SEwan Crawford if (strcmp(name.AsCString(), "#rs_padding") < 0) 19148b244e21SEwan Crawford found = false; 19158b244e21SEwan Crawford } 19168b244e21SEwan Crawford } 19178b244e21SEwan Crawford 19188b244e21SEwan Crawford // We've found a global var with matching type 19198b244e21SEwan Crawford if (found) 19208b244e21SEwan Crawford { 19218b244e21SEwan Crawford // Dereference since our Element type isn't a pointer. 19228b244e21SEwan Crawford if (valobj_sp->IsPointerType()) 19238b244e21SEwan Crawford { 19248b244e21SEwan Crawford Error err; 19258b244e21SEwan Crawford ValueObjectSP deref_valobj = valobj_sp->Dereference(err); 19268b244e21SEwan Crawford if (!err.Fail()) 19278b244e21SEwan Crawford valobj_sp = deref_valobj; 19288b244e21SEwan Crawford } 19298b244e21SEwan Crawford 19308b244e21SEwan Crawford // Save name of variable in Element. 19318b244e21SEwan Crawford elem.type_name = valobj_sp->GetTypeName(); 19328b244e21SEwan Crawford if (log) 19338b244e21SEwan Crawford log->Printf("RenderScriptRuntime::FindStructTypeName - Element name set to %s", elem.type_name.AsCString()); 19348b244e21SEwan Crawford 19358b244e21SEwan Crawford return; 19368b244e21SEwan Crawford } 19378b244e21SEwan Crawford } 19388b244e21SEwan Crawford } 19398b244e21SEwan Crawford 19408b244e21SEwan Crawford // Function sets the datum_size member of Element. Representing the size of a single instance including padding. 19418b244e21SEwan Crawford // Assumes the relevant allocation information has already been jitted. 19428b244e21SEwan Crawford void 19438b244e21SEwan Crawford RenderScriptRuntime::SetElementSize(Element& elem) 19448b244e21SEwan Crawford { 19458b244e21SEwan Crawford Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 19468b244e21SEwan Crawford const Element::DataType type = *elem.type.get(); 19472e920715SEwan Crawford assert(type >= Element::RS_TYPE_NONE && type <= Element::RS_TYPE_FONT 194855232f09SEwan Crawford && "Invalid allocation type"); 194955232f09SEwan Crawford 19508b244e21SEwan Crawford const unsigned int vec_size = *elem.type_vec_size.get(); 19518b244e21SEwan Crawford unsigned int data_size = 0; 19522e920715SEwan Crawford unsigned int padding = 0; 195355232f09SEwan Crawford 19548b244e21SEwan Crawford // Element is of a struct type, calculate size recursively. 19558b244e21SEwan Crawford if ((type == Element::RS_TYPE_NONE) && (elem.children.size() > 0)) 19568b244e21SEwan Crawford { 19578b244e21SEwan Crawford for (Element& child : elem.children) 19588b244e21SEwan Crawford { 19598b244e21SEwan Crawford SetElementSize(child); 19608b244e21SEwan Crawford const unsigned int array_size = child.array_size.isValid() ? *child.array_size.get() : 1; 19618b244e21SEwan Crawford data_size += *child.datum_size.get() * array_size; 19628b244e21SEwan Crawford } 19638b244e21SEwan Crawford } 19642e920715SEwan Crawford else if (type == Element::RS_TYPE_UNSIGNED_5_6_5 || type == Element::RS_TYPE_UNSIGNED_5_5_5_1 || 19652e920715SEwan Crawford type == Element::RS_TYPE_UNSIGNED_4_4_4_4) // These have been packed already 19662e920715SEwan Crawford { 19672e920715SEwan Crawford data_size = AllocationDetails::RSTypeToFormat[type][eElementSize]; 19682e920715SEwan Crawford } 19692e920715SEwan Crawford else if (type < Element::RS_TYPE_ELEMENT) 19702e920715SEwan Crawford { 19718b244e21SEwan Crawford data_size = vec_size * AllocationDetails::RSTypeToFormat[type][eElementSize]; 19722e920715SEwan Crawford if (vec_size == 3) 19732e920715SEwan Crawford padding = AllocationDetails::RSTypeToFormat[type][eElementSize]; 19742e920715SEwan Crawford } 19752e920715SEwan Crawford else 19762e920715SEwan Crawford data_size = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize(); 19778b244e21SEwan Crawford 19788b244e21SEwan Crawford elem.padding = padding; 19798b244e21SEwan Crawford elem.datum_size = data_size + padding; 19808b244e21SEwan Crawford if (log) 19818b244e21SEwan Crawford log->Printf("RenderScriptRuntime::SetElementSize - element size set to %u", data_size + padding); 198255232f09SEwan Crawford } 198355232f09SEwan Crawford 198455232f09SEwan Crawford // Given an allocation, this function copies the allocation contents from device into a buffer on the heap. 198555232f09SEwan Crawford // Returning a shared pointer to the buffer containing the data. 198655232f09SEwan Crawford std::shared_ptr<uint8_t> 198755232f09SEwan Crawford RenderScriptRuntime::GetAllocationData(AllocationDetails* allocation, StackFrame* frame_ptr) 198855232f09SEwan Crawford { 198955232f09SEwan Crawford Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 199055232f09SEwan Crawford 199155232f09SEwan Crawford // JIT all the allocation details 19928b59062aSEwan Crawford if (allocation->shouldRefresh()) 199355232f09SEwan Crawford { 199455232f09SEwan Crawford if (log) 199555232f09SEwan Crawford log->Printf("RenderScriptRuntime::GetAllocationData - Allocation details not calculated yet, jitting info"); 199655232f09SEwan Crawford 199755232f09SEwan Crawford if (!RefreshAllocation(allocation, frame_ptr)) 199855232f09SEwan Crawford { 199955232f09SEwan Crawford if (log) 200055232f09SEwan Crawford log->Printf("RenderScriptRuntime::GetAllocationData - Couldn't JIT allocation details"); 200155232f09SEwan Crawford return nullptr; 200255232f09SEwan Crawford } 200355232f09SEwan Crawford } 200455232f09SEwan Crawford 20058b244e21SEwan Crawford assert(allocation->data_ptr.isValid() && allocation->element.type.isValid() && allocation->element.type_vec_size.isValid() 200655232f09SEwan Crawford && allocation->size.isValid() && "Allocation information not available"); 200755232f09SEwan Crawford 200855232f09SEwan Crawford // Allocate a buffer to copy data into 200955232f09SEwan Crawford const unsigned int size = *allocation->size.get(); 201055232f09SEwan Crawford std::shared_ptr<uint8_t> buffer(new uint8_t[size]); 201155232f09SEwan Crawford if (!buffer) 201255232f09SEwan Crawford { 201355232f09SEwan Crawford if (log) 201455232f09SEwan Crawford log->Printf("RenderScriptRuntime::GetAllocationData - Couldn't allocate a %u byte buffer", size); 201555232f09SEwan Crawford return nullptr; 201655232f09SEwan Crawford } 201755232f09SEwan Crawford 201855232f09SEwan Crawford // Read the inferior memory 201955232f09SEwan Crawford Error error; 202055232f09SEwan Crawford lldb::addr_t data_ptr = *allocation->data_ptr.get(); 202155232f09SEwan Crawford GetProcess()->ReadMemory(data_ptr, buffer.get(), size, error); 202255232f09SEwan Crawford if (error.Fail()) 202355232f09SEwan Crawford { 202455232f09SEwan Crawford if (log) 202555232f09SEwan Crawford log->Printf("RenderScriptRuntime::GetAllocationData - '%s' Couldn't read %u bytes of allocation data from 0x%" PRIx64, 202655232f09SEwan Crawford error.AsCString(), size, data_ptr); 202755232f09SEwan Crawford return nullptr; 202855232f09SEwan Crawford } 202955232f09SEwan Crawford 203055232f09SEwan Crawford return buffer; 203155232f09SEwan Crawford } 203255232f09SEwan Crawford 203355232f09SEwan Crawford // Function copies data from a binary file into an allocation. 203455232f09SEwan Crawford // There is a header at the start of the file, FileHeader, before the data content itself. 203555232f09SEwan Crawford // Information from this header is used to display warnings to the user about incompatabilities 203655232f09SEwan Crawford bool 203755232f09SEwan Crawford RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id, const char* filename, StackFrame* frame_ptr) 203855232f09SEwan Crawford { 203955232f09SEwan Crawford Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 204055232f09SEwan Crawford 204155232f09SEwan Crawford // Find allocation with the given id 204255232f09SEwan Crawford AllocationDetails* alloc = FindAllocByID(strm, alloc_id); 204355232f09SEwan Crawford if (!alloc) 204455232f09SEwan Crawford return false; 204555232f09SEwan Crawford 204655232f09SEwan Crawford if (log) 204755232f09SEwan Crawford log->Printf("RenderScriptRuntime::LoadAllocation - Found allocation 0x%" PRIx64, *alloc->address.get()); 204855232f09SEwan Crawford 204955232f09SEwan Crawford // JIT all the allocation details 20508b59062aSEwan Crawford if (alloc->shouldRefresh()) 205155232f09SEwan Crawford { 205255232f09SEwan Crawford if (log) 205355232f09SEwan Crawford log->Printf("RenderScriptRuntime::LoadAllocation - Allocation details not calculated yet, jitting info"); 205455232f09SEwan Crawford 205555232f09SEwan Crawford if (!RefreshAllocation(alloc, frame_ptr)) 205655232f09SEwan Crawford { 205755232f09SEwan Crawford if (log) 205855232f09SEwan Crawford log->Printf("RenderScriptRuntime::LoadAllocation - Couldn't JIT allocation details"); 20594cfc9198SSylvestre Ledru return false; 206055232f09SEwan Crawford } 206155232f09SEwan Crawford } 206255232f09SEwan Crawford 20638b244e21SEwan Crawford assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() && alloc->element.type_vec_size.isValid() 20648b244e21SEwan Crawford && alloc->size.isValid() && alloc->element.datum_size.isValid() && "Allocation information not available"); 206555232f09SEwan Crawford 206655232f09SEwan Crawford // Check we can read from file 206755232f09SEwan Crawford FileSpec file(filename, true); 206855232f09SEwan Crawford if (!file.Exists()) 206955232f09SEwan Crawford { 207055232f09SEwan Crawford strm.Printf("Error: File %s does not exist", filename); 207155232f09SEwan Crawford strm.EOL(); 207255232f09SEwan Crawford return false; 207355232f09SEwan Crawford } 207455232f09SEwan Crawford 207555232f09SEwan Crawford if (!file.Readable()) 207655232f09SEwan Crawford { 207755232f09SEwan Crawford strm.Printf("Error: File %s does not have readable permissions", filename); 207855232f09SEwan Crawford strm.EOL(); 207955232f09SEwan Crawford return false; 208055232f09SEwan Crawford } 208155232f09SEwan Crawford 208255232f09SEwan Crawford // Read file into data buffer 208355232f09SEwan Crawford DataBufferSP data_sp(file.ReadFileContents()); 208455232f09SEwan Crawford 208555232f09SEwan Crawford // Cast start of buffer to FileHeader and use pointer to read metadata 208655232f09SEwan Crawford void* file_buffer = data_sp->GetBytes(); 208755232f09SEwan Crawford const AllocationDetails::FileHeader* head = static_cast<AllocationDetails::FileHeader*>(file_buffer); 208855232f09SEwan Crawford 208955232f09SEwan Crawford // Advance buffer past header 209055232f09SEwan Crawford file_buffer = static_cast<uint8_t*>(file_buffer) + head->hdr_size; 209155232f09SEwan Crawford 209255232f09SEwan Crawford if (log) 209355232f09SEwan Crawford log->Printf("RenderScriptRuntime::LoadAllocation - header type %u, element size %u", 209455232f09SEwan Crawford head->type, head->element_size); 209555232f09SEwan Crawford 209655232f09SEwan Crawford // Check if the target allocation and file both have the same number of bytes for an Element 20978b244e21SEwan Crawford if (*alloc->element.datum_size.get() != head->element_size) 209855232f09SEwan Crawford { 209955232f09SEwan Crawford strm.Printf("Warning: Mismatched Element sizes - file %u bytes, allocation %u bytes", 21008b244e21SEwan Crawford head->element_size, *alloc->element.datum_size.get()); 210155232f09SEwan Crawford strm.EOL(); 210255232f09SEwan Crawford } 210355232f09SEwan Crawford 210455232f09SEwan Crawford // Check if the target allocation and file both have the same integral type 21058b244e21SEwan Crawford const unsigned int type = static_cast<unsigned int>(*alloc->element.type.get()); 210655232f09SEwan Crawford if (type != head->type) 210755232f09SEwan Crawford { 21082e920715SEwan Crawford // Enum value isn't monotonous, so doesn't always index RsDataTypeToString array 21092e920715SEwan Crawford unsigned int printable_target_type_index = type; 21102e920715SEwan Crawford unsigned int printable_head_type_index = head->type; 21112e920715SEwan Crawford if (type >= Element::RS_TYPE_ELEMENT && type <= Element::RS_TYPE_FONT) 21122e920715SEwan Crawford printable_target_type_index = static_cast<Element::DataType>( 21132e920715SEwan Crawford (type - Element::RS_TYPE_ELEMENT) + Element::RS_TYPE_MATRIX_2X2 + 1); 21142e920715SEwan Crawford 21152e920715SEwan Crawford if (head->type >= Element::RS_TYPE_ELEMENT && head->type <= Element::RS_TYPE_FONT) 21162e920715SEwan Crawford printable_head_type_index = static_cast<Element::DataType>( 21172e920715SEwan Crawford (head->type - Element::RS_TYPE_ELEMENT) + Element::RS_TYPE_MATRIX_2X2 + 1); 21182e920715SEwan Crawford 21192e920715SEwan Crawford const char* file_type_cstr = AllocationDetails::RsDataTypeToString[printable_head_type_index][0]; 21202e920715SEwan Crawford const char* target_type_cstr = AllocationDetails::RsDataTypeToString[printable_target_type_index][0]; 212155232f09SEwan Crawford 212255232f09SEwan Crawford strm.Printf("Warning: Mismatched Types - file '%s' type, allocation '%s' type", 21232e920715SEwan Crawford file_type_cstr, target_type_cstr); 212455232f09SEwan Crawford strm.EOL(); 212555232f09SEwan Crawford } 212655232f09SEwan Crawford 212755232f09SEwan Crawford // Calculate size of allocation data in file 212855232f09SEwan Crawford size_t length = data_sp->GetByteSize() - head->hdr_size; 212955232f09SEwan Crawford 213055232f09SEwan Crawford // Check if the target allocation and file both have the same total data size. 213155232f09SEwan Crawford const unsigned int alloc_size = *alloc->size.get(); 213255232f09SEwan Crawford if (alloc_size != length) 213355232f09SEwan Crawford { 213455232f09SEwan Crawford strm.Printf("Warning: Mismatched allocation sizes - file 0x%" PRIx64 " bytes, allocation 0x%x bytes", 2135eba832beSJason Molenda (uint64_t) length, alloc_size); 213655232f09SEwan Crawford strm.EOL(); 213755232f09SEwan Crawford length = alloc_size < length ? alloc_size : length; // Set length to copy to minimum 213855232f09SEwan Crawford } 213955232f09SEwan Crawford 214055232f09SEwan Crawford // Copy file data from our buffer into the target allocation. 214155232f09SEwan Crawford lldb::addr_t alloc_data = *alloc->data_ptr.get(); 214255232f09SEwan Crawford Error error; 214355232f09SEwan Crawford size_t bytes_written = GetProcess()->WriteMemory(alloc_data, file_buffer, length, error); 214455232f09SEwan Crawford if (!error.Success() || bytes_written != length) 214555232f09SEwan Crawford { 214655232f09SEwan Crawford strm.Printf("Error: Couldn't write data to allocation %s", error.AsCString()); 214755232f09SEwan Crawford strm.EOL(); 214855232f09SEwan Crawford return false; 214955232f09SEwan Crawford } 215055232f09SEwan Crawford 215155232f09SEwan Crawford strm.Printf("Contents of file '%s' read into allocation %u", filename, alloc->id); 215255232f09SEwan Crawford strm.EOL(); 215355232f09SEwan Crawford 215455232f09SEwan Crawford return true; 215555232f09SEwan Crawford } 215655232f09SEwan Crawford 215755232f09SEwan Crawford // Function copies allocation contents into a binary file. 215855232f09SEwan Crawford // This file can then be loaded later into a different allocation. 215955232f09SEwan Crawford // There is a header, FileHeader, before the allocation data containing meta-data. 216055232f09SEwan Crawford bool 216155232f09SEwan Crawford RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id, const char* filename, StackFrame* frame_ptr) 216255232f09SEwan Crawford { 216355232f09SEwan Crawford Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 216455232f09SEwan Crawford 216555232f09SEwan Crawford // Find allocation with the given id 216655232f09SEwan Crawford AllocationDetails* alloc = FindAllocByID(strm, alloc_id); 216755232f09SEwan Crawford if (!alloc) 216855232f09SEwan Crawford return false; 216955232f09SEwan Crawford 217055232f09SEwan Crawford if (log) 217155232f09SEwan Crawford log->Printf("RenderScriptRuntime::SaveAllocation - Found allocation 0x%" PRIx64, *alloc->address.get()); 217255232f09SEwan Crawford 217355232f09SEwan Crawford // JIT all the allocation details 21748b59062aSEwan Crawford if (alloc->shouldRefresh()) 217555232f09SEwan Crawford { 217655232f09SEwan Crawford if (log) 217755232f09SEwan Crawford log->Printf("RenderScriptRuntime::SaveAllocation - Allocation details not calculated yet, jitting info"); 217855232f09SEwan Crawford 217955232f09SEwan Crawford if (!RefreshAllocation(alloc, frame_ptr)) 218055232f09SEwan Crawford { 218155232f09SEwan Crawford if (log) 218255232f09SEwan Crawford log->Printf("RenderScriptRuntime::SaveAllocation - Couldn't JIT allocation details"); 21834cfc9198SSylvestre Ledru return false; 218455232f09SEwan Crawford } 218555232f09SEwan Crawford } 218655232f09SEwan Crawford 21878b244e21SEwan Crawford assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() && alloc->element.type_vec_size.isValid() && alloc->element.datum_size.get() 21888b244e21SEwan Crawford && alloc->element.type_kind.isValid() && alloc->dimension.isValid() && "Allocation information not available"); 218955232f09SEwan Crawford 219055232f09SEwan Crawford // Check we can create writable file 219155232f09SEwan Crawford FileSpec file_spec(filename, true); 219255232f09SEwan Crawford File file(file_spec, File::eOpenOptionWrite | File::eOpenOptionCanCreate | File::eOpenOptionTruncate); 219355232f09SEwan Crawford if (!file) 219455232f09SEwan Crawford { 219555232f09SEwan Crawford strm.Printf("Error: Failed to open '%s' for writing", filename); 219655232f09SEwan Crawford strm.EOL(); 219755232f09SEwan Crawford return false; 219855232f09SEwan Crawford } 219955232f09SEwan Crawford 220055232f09SEwan Crawford // Read allocation into buffer of heap memory 220155232f09SEwan Crawford const std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr); 220255232f09SEwan Crawford if (!buffer) 220355232f09SEwan Crawford { 220455232f09SEwan Crawford strm.Printf("Error: Couldn't read allocation data into buffer"); 220555232f09SEwan Crawford strm.EOL(); 220655232f09SEwan Crawford return false; 220755232f09SEwan Crawford } 220855232f09SEwan Crawford 220955232f09SEwan Crawford // Create the file header 221055232f09SEwan Crawford AllocationDetails::FileHeader head; 221155232f09SEwan Crawford head.ident[0] = 'R'; head.ident[1] = 'S'; head.ident[2] = 'A'; head.ident[3] = 'D'; 221255232f09SEwan Crawford head.hdr_size = static_cast<uint16_t>(sizeof(AllocationDetails::FileHeader)); 22138b244e21SEwan Crawford head.type = static_cast<uint16_t>(*alloc->element.type.get()); 22148b244e21SEwan Crawford head.kind = static_cast<uint32_t>(*alloc->element.type_kind.get()); 22152d62328aSEwan Crawford head.dims[0] = static_cast<uint32_t>(alloc->dimension.get()->dim_1); 22162d62328aSEwan Crawford head.dims[1] = static_cast<uint32_t>(alloc->dimension.get()->dim_2); 22172d62328aSEwan Crawford head.dims[2] = static_cast<uint32_t>(alloc->dimension.get()->dim_3); 22188b244e21SEwan Crawford head.element_size = static_cast<uint32_t>(*alloc->element.datum_size.get()); 221955232f09SEwan Crawford 222055232f09SEwan Crawford // Write the file header 222155232f09SEwan Crawford size_t num_bytes = sizeof(AllocationDetails::FileHeader); 222255232f09SEwan Crawford Error err = file.Write(static_cast<const void*>(&head), num_bytes); 222355232f09SEwan Crawford if (!err.Success()) 222455232f09SEwan Crawford { 222555232f09SEwan Crawford strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), filename); 222655232f09SEwan Crawford strm.EOL(); 222755232f09SEwan Crawford return false; 222855232f09SEwan Crawford } 222955232f09SEwan Crawford 223055232f09SEwan Crawford // Write allocation data to file 223155232f09SEwan Crawford num_bytes = static_cast<size_t>(*alloc->size.get()); 223255232f09SEwan Crawford if (log) 22337093cccfSEwan Crawford log->Printf("RenderScriptRuntime::SaveAllocation - Writing 0x%" PRIx64 " bytes from %p", (uint64_t) num_bytes, (void*) buffer.get()); 223455232f09SEwan Crawford 223555232f09SEwan Crawford err = file.Write(buffer.get(), num_bytes); 223655232f09SEwan Crawford if (!err.Success()) 223755232f09SEwan Crawford { 223855232f09SEwan Crawford strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), filename); 223955232f09SEwan Crawford strm.EOL(); 224055232f09SEwan Crawford return false; 224155232f09SEwan Crawford } 224255232f09SEwan Crawford 224355232f09SEwan Crawford strm.Printf("Allocation written to file '%s'", filename); 224455232f09SEwan Crawford strm.EOL(); 224515f2bd95SEwan Crawford return true; 224615f2bd95SEwan Crawford } 224715f2bd95SEwan Crawford 22485ec532a9SColin Riley bool 22495ec532a9SColin Riley RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp) 22505ec532a9SColin Riley { 22514640cde1SColin Riley Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 22524640cde1SColin Riley 22535ec532a9SColin Riley if (module_sp) 22545ec532a9SColin Riley { 22555ec532a9SColin Riley for (const auto &rs_module : m_rsmodules) 22565ec532a9SColin Riley { 22574640cde1SColin Riley if (rs_module->m_module == module_sp) 22587dc7771cSEwan Crawford { 22597dc7771cSEwan Crawford // Check if the user has enabled automatically breaking on 22607dc7771cSEwan Crawford // all RS kernels. 22617dc7771cSEwan Crawford if (m_breakAllKernels) 22627dc7771cSEwan Crawford BreakOnModuleKernels(rs_module); 22637dc7771cSEwan Crawford 22645ec532a9SColin Riley return false; 22655ec532a9SColin Riley } 22667dc7771cSEwan Crawford } 2267ef20b08fSColin Riley bool module_loaded = false; 2268ef20b08fSColin Riley switch (GetModuleKind(module_sp)) 2269ef20b08fSColin Riley { 2270ef20b08fSColin Riley case eModuleKindKernelObj: 2271ef20b08fSColin Riley { 22724640cde1SColin Riley RSModuleDescriptorSP module_desc; 22734640cde1SColin Riley module_desc.reset(new RSModuleDescriptor(module_sp)); 22744640cde1SColin Riley if (module_desc->ParseRSInfo()) 22755ec532a9SColin Riley { 22765ec532a9SColin Riley m_rsmodules.push_back(module_desc); 2277ef20b08fSColin Riley module_loaded = true; 22785ec532a9SColin Riley } 22794640cde1SColin Riley if (module_loaded) 22804640cde1SColin Riley { 22814640cde1SColin Riley FixupScriptDetails(module_desc); 22824640cde1SColin Riley } 2283ef20b08fSColin Riley break; 2284ef20b08fSColin Riley } 2285ef20b08fSColin Riley case eModuleKindDriver: 22864640cde1SColin Riley { 22874640cde1SColin Riley if (!m_libRSDriver) 22884640cde1SColin Riley { 22894640cde1SColin Riley m_libRSDriver = module_sp; 22904640cde1SColin Riley LoadRuntimeHooks(m_libRSDriver, RenderScriptRuntime::eModuleKindDriver); 22914640cde1SColin Riley } 22924640cde1SColin Riley break; 22934640cde1SColin Riley } 2294ef20b08fSColin Riley case eModuleKindImpl: 22954640cde1SColin Riley { 22964640cde1SColin Riley m_libRSCpuRef = module_sp; 22974640cde1SColin Riley break; 22984640cde1SColin Riley } 2299ef20b08fSColin Riley case eModuleKindLibRS: 23004640cde1SColin Riley { 23014640cde1SColin Riley if (!m_libRS) 23024640cde1SColin Riley { 23034640cde1SColin Riley m_libRS = module_sp; 23044640cde1SColin Riley static ConstString gDbgPresentStr("gDebuggerPresent"); 23054640cde1SColin Riley const Symbol* debug_present = m_libRS->FindFirstSymbolWithNameAndType(gDbgPresentStr, eSymbolTypeData); 23064640cde1SColin Riley if (debug_present) 23074640cde1SColin Riley { 23084640cde1SColin Riley Error error; 23094640cde1SColin Riley uint32_t flag = 0x00000001U; 23104640cde1SColin Riley Target &target = GetProcess()->GetTarget(); 2311358cf1eaSGreg Clayton addr_t addr = debug_present->GetLoadAddress(&target); 23124640cde1SColin Riley GetProcess()->WriteMemory(addr, &flag, sizeof(flag), error); 23134640cde1SColin Riley if(error.Success()) 23144640cde1SColin Riley { 23154640cde1SColin Riley if (log) 23164640cde1SColin Riley log->Printf ("RenderScriptRuntime::LoadModule - Debugger present flag set on debugee"); 23174640cde1SColin Riley 23184640cde1SColin Riley m_debuggerPresentFlagged = true; 23194640cde1SColin Riley } 23204640cde1SColin Riley else if (log) 23214640cde1SColin Riley { 23224640cde1SColin Riley log->Printf ("RenderScriptRuntime::LoadModule - Error writing debugger present flags '%s' ", error.AsCString()); 23234640cde1SColin Riley } 23244640cde1SColin Riley } 23254640cde1SColin Riley else if (log) 23264640cde1SColin Riley { 23274640cde1SColin Riley log->Printf ("RenderScriptRuntime::LoadModule - Error writing debugger present flags - symbol not found"); 23284640cde1SColin Riley } 23294640cde1SColin Riley } 23304640cde1SColin Riley break; 23314640cde1SColin Riley } 2332ef20b08fSColin Riley default: 2333ef20b08fSColin Riley break; 2334ef20b08fSColin Riley } 2335ef20b08fSColin Riley if (module_loaded) 2336ef20b08fSColin Riley Update(); 2337ef20b08fSColin Riley return module_loaded; 23385ec532a9SColin Riley } 23395ec532a9SColin Riley return false; 23405ec532a9SColin Riley } 23415ec532a9SColin Riley 2342ef20b08fSColin Riley void 2343ef20b08fSColin Riley RenderScriptRuntime::Update() 2344ef20b08fSColin Riley { 2345ef20b08fSColin Riley if (m_rsmodules.size() > 0) 2346ef20b08fSColin Riley { 2347ef20b08fSColin Riley if (!m_initiated) 2348ef20b08fSColin Riley { 2349ef20b08fSColin Riley Initiate(); 2350ef20b08fSColin Riley } 2351ef20b08fSColin Riley } 2352ef20b08fSColin Riley } 2353ef20b08fSColin Riley 23545ec532a9SColin Riley // The maximum line length of an .rs.info packet 23555ec532a9SColin Riley #define MAXLINE 500 23565ec532a9SColin Riley 23575ec532a9SColin Riley // The .rs.info symbol in renderscript modules contains a string which needs to be parsed. 23585ec532a9SColin Riley // The string is basic and is parsed on a line by line basis. 23595ec532a9SColin Riley bool 23605ec532a9SColin Riley RSModuleDescriptor::ParseRSInfo() 23615ec532a9SColin Riley { 23625ec532a9SColin Riley const Symbol *info_sym = m_module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData); 23635ec532a9SColin Riley if (info_sym) 23645ec532a9SColin Riley { 2365358cf1eaSGreg Clayton const addr_t addr = info_sym->GetAddressRef().GetFileAddress(); 23665ec532a9SColin Riley const addr_t size = info_sym->GetByteSize(); 23675ec532a9SColin Riley const FileSpec fs = m_module->GetFileSpec(); 23685ec532a9SColin Riley 23695ec532a9SColin Riley DataBufferSP buffer = fs.ReadFileContents(addr, size); 23705ec532a9SColin Riley 23715ec532a9SColin Riley if (!buffer) 23725ec532a9SColin Riley return false; 23735ec532a9SColin Riley 23745ec532a9SColin Riley std::string info((const char *)buffer->GetBytes()); 23755ec532a9SColin Riley 23765ec532a9SColin Riley std::vector<std::string> info_lines; 2377e8433cc1SBruce Mitchener size_t lpos = info.find('\n'); 23785ec532a9SColin Riley while (lpos != std::string::npos) 23795ec532a9SColin Riley { 23805ec532a9SColin Riley info_lines.push_back(info.substr(0, lpos)); 23815ec532a9SColin Riley info = info.substr(lpos + 1); 2382e8433cc1SBruce Mitchener lpos = info.find('\n'); 23835ec532a9SColin Riley } 23845ec532a9SColin Riley size_t offset = 0; 23855ec532a9SColin Riley while (offset < info_lines.size()) 23865ec532a9SColin Riley { 23875ec532a9SColin Riley std::string line = info_lines[offset]; 23885ec532a9SColin Riley // Parse directives 23895ec532a9SColin Riley uint32_t numDefns = 0; 23905ec532a9SColin Riley if (sscanf(line.c_str(), "exportVarCount: %u", &numDefns) == 1) 23915ec532a9SColin Riley { 23925ec532a9SColin Riley while (numDefns--) 23934640cde1SColin Riley m_globals.push_back(RSGlobalDescriptor(this, info_lines[++offset].c_str())); 23945ec532a9SColin Riley } 23955ec532a9SColin Riley else if (sscanf(line.c_str(), "exportFuncCount: %u", &numDefns) == 1) 23965ec532a9SColin Riley { 23975ec532a9SColin Riley } 23985ec532a9SColin Riley else if (sscanf(line.c_str(), "exportForEachCount: %u", &numDefns) == 1) 23995ec532a9SColin Riley { 24005ec532a9SColin Riley char name[MAXLINE]; 24015ec532a9SColin Riley while (numDefns--) 24025ec532a9SColin Riley { 24035ec532a9SColin Riley uint32_t slot = 0; 24045ec532a9SColin Riley name[0] = '\0'; 24055ec532a9SColin Riley if (sscanf(info_lines[++offset].c_str(), "%u - %s", &slot, &name[0]) == 2) 24065ec532a9SColin Riley { 24074640cde1SColin Riley m_kernels.push_back(RSKernelDescriptor(this, name, slot)); 24084640cde1SColin Riley } 24094640cde1SColin Riley } 24104640cde1SColin Riley } 24114640cde1SColin Riley else if (sscanf(line.c_str(), "pragmaCount: %u", &numDefns) == 1) 24124640cde1SColin Riley { 24134640cde1SColin Riley char name[MAXLINE]; 24144640cde1SColin Riley char value[MAXLINE]; 24154640cde1SColin Riley while (numDefns--) 24164640cde1SColin Riley { 24174640cde1SColin Riley name[0] = '\0'; 24184640cde1SColin Riley value[0] = '\0'; 24194640cde1SColin Riley if (sscanf(info_lines[++offset].c_str(), "%s - %s", &name[0], &value[0]) != 0 24204640cde1SColin Riley && (name[0] != '\0')) 24214640cde1SColin Riley { 24224640cde1SColin Riley m_pragmas[std::string(name)] = value; 24235ec532a9SColin Riley } 24245ec532a9SColin Riley } 24255ec532a9SColin Riley } 24265ec532a9SColin Riley else if (sscanf(line.c_str(), "objectSlotCount: %u", &numDefns) == 1) 24275ec532a9SColin Riley { 24285ec532a9SColin Riley } 24295ec532a9SColin Riley 24305ec532a9SColin Riley offset++; 24315ec532a9SColin Riley } 24325ec532a9SColin Riley return m_kernels.size() > 0; 24335ec532a9SColin Riley } 24345ec532a9SColin Riley return false; 24355ec532a9SColin Riley } 24365ec532a9SColin Riley 24375ec532a9SColin Riley bool 24385ec532a9SColin Riley RenderScriptRuntime::ProbeModules(const ModuleList module_list) 24395ec532a9SColin Riley { 24405ec532a9SColin Riley bool rs_found = false; 24415ec532a9SColin Riley size_t num_modules = module_list.GetSize(); 24425ec532a9SColin Riley for (size_t i = 0; i < num_modules; i++) 24435ec532a9SColin Riley { 24445ec532a9SColin Riley auto module = module_list.GetModuleAtIndex(i); 24455ec532a9SColin Riley rs_found |= LoadModule(module); 24465ec532a9SColin Riley } 24475ec532a9SColin Riley return rs_found; 24485ec532a9SColin Riley } 24495ec532a9SColin Riley 24505ec532a9SColin Riley void 24514640cde1SColin Riley RenderScriptRuntime::Status(Stream &strm) const 24524640cde1SColin Riley { 24534640cde1SColin Riley if (m_libRS) 24544640cde1SColin Riley { 24554640cde1SColin Riley strm.Printf("Runtime Library discovered."); 24564640cde1SColin Riley strm.EOL(); 24574640cde1SColin Riley } 24584640cde1SColin Riley if (m_libRSDriver) 24594640cde1SColin Riley { 24604640cde1SColin Riley strm.Printf("Runtime Driver discovered."); 24614640cde1SColin Riley strm.EOL(); 24624640cde1SColin Riley } 24634640cde1SColin Riley if (m_libRSCpuRef) 24644640cde1SColin Riley { 24654640cde1SColin Riley strm.Printf("CPU Reference Implementation discovered."); 24664640cde1SColin Riley strm.EOL(); 24674640cde1SColin Riley } 24684640cde1SColin Riley 24694640cde1SColin Riley if (m_runtimeHooks.size()) 24704640cde1SColin Riley { 24714640cde1SColin Riley strm.Printf("Runtime functions hooked:"); 24724640cde1SColin Riley strm.EOL(); 24734640cde1SColin Riley for (auto b : m_runtimeHooks) 24744640cde1SColin Riley { 24754640cde1SColin Riley strm.Indent(b.second->defn->name); 24764640cde1SColin Riley strm.EOL(); 24774640cde1SColin Riley } 24784640cde1SColin Riley } 24794640cde1SColin Riley else 24804640cde1SColin Riley { 24814640cde1SColin Riley strm.Printf("Runtime is not hooked."); 24824640cde1SColin Riley strm.EOL(); 24834640cde1SColin Riley } 24844640cde1SColin Riley } 24854640cde1SColin Riley 24864640cde1SColin Riley void 24874640cde1SColin Riley RenderScriptRuntime::DumpContexts(Stream &strm) const 24884640cde1SColin Riley { 24894640cde1SColin Riley strm.Printf("Inferred RenderScript Contexts:"); 24904640cde1SColin Riley strm.EOL(); 24914640cde1SColin Riley strm.IndentMore(); 24924640cde1SColin Riley 24934640cde1SColin Riley std::map<addr_t, uint64_t> contextReferences; 24944640cde1SColin Riley 249578f339d1SEwan Crawford // Iterate over all of the currently discovered scripts. 249678f339d1SEwan Crawford // Note: We cant push or pop from m_scripts inside this loop or it may invalidate script. 24974640cde1SColin Riley for (const auto & script : m_scripts) 24984640cde1SColin Riley { 249978f339d1SEwan Crawford if (!script->context.isValid()) 250078f339d1SEwan Crawford continue; 250178f339d1SEwan Crawford lldb::addr_t context = *script->context; 250278f339d1SEwan Crawford 250378f339d1SEwan Crawford if (contextReferences.find(context) != contextReferences.end()) 25044640cde1SColin Riley { 250578f339d1SEwan Crawford contextReferences[context]++; 25064640cde1SColin Riley } 25074640cde1SColin Riley else 25084640cde1SColin Riley { 250978f339d1SEwan Crawford contextReferences[context] = 1; 25104640cde1SColin Riley } 25114640cde1SColin Riley } 25124640cde1SColin Riley 25134640cde1SColin Riley for (const auto& cRef : contextReferences) 25144640cde1SColin Riley { 25154640cde1SColin Riley strm.Printf("Context 0x%" PRIx64 ": %" PRIu64 " script instances", cRef.first, cRef.second); 25164640cde1SColin Riley strm.EOL(); 25174640cde1SColin Riley } 25184640cde1SColin Riley strm.IndentLess(); 25194640cde1SColin Riley } 25204640cde1SColin Riley 25214640cde1SColin Riley void 25224640cde1SColin Riley RenderScriptRuntime::DumpKernels(Stream &strm) const 25234640cde1SColin Riley { 25244640cde1SColin Riley strm.Printf("RenderScript Kernels:"); 25254640cde1SColin Riley strm.EOL(); 25264640cde1SColin Riley strm.IndentMore(); 25274640cde1SColin Riley for (const auto &module : m_rsmodules) 25284640cde1SColin Riley { 25294640cde1SColin Riley strm.Printf("Resource '%s':",module->m_resname.c_str()); 25304640cde1SColin Riley strm.EOL(); 25314640cde1SColin Riley for (const auto &kernel : module->m_kernels) 25324640cde1SColin Riley { 25334640cde1SColin Riley strm.Indent(kernel.m_name.AsCString()); 25344640cde1SColin Riley strm.EOL(); 25354640cde1SColin Riley } 25364640cde1SColin Riley } 25374640cde1SColin Riley strm.IndentLess(); 25384640cde1SColin Riley } 25394640cde1SColin Riley 2540a0f08674SEwan Crawford RenderScriptRuntime::AllocationDetails* 2541a0f08674SEwan Crawford RenderScriptRuntime::FindAllocByID(Stream &strm, const uint32_t alloc_id) 2542a0f08674SEwan Crawford { 2543a0f08674SEwan Crawford AllocationDetails* alloc = nullptr; 2544a0f08674SEwan Crawford 2545a0f08674SEwan Crawford // See if we can find allocation using id as an index; 2546a0f08674SEwan Crawford if (alloc_id <= m_allocations.size() && alloc_id != 0 2547a0f08674SEwan Crawford && m_allocations[alloc_id-1]->id == alloc_id) 2548a0f08674SEwan Crawford { 2549a0f08674SEwan Crawford alloc = m_allocations[alloc_id-1].get(); 2550a0f08674SEwan Crawford return alloc; 2551a0f08674SEwan Crawford } 2552a0f08674SEwan Crawford 2553a0f08674SEwan Crawford // Fallback to searching 2554a0f08674SEwan Crawford for (const auto & a : m_allocations) 2555a0f08674SEwan Crawford { 2556a0f08674SEwan Crawford if (a->id == alloc_id) 2557a0f08674SEwan Crawford { 2558a0f08674SEwan Crawford alloc = a.get(); 2559a0f08674SEwan Crawford break; 2560a0f08674SEwan Crawford } 2561a0f08674SEwan Crawford } 2562a0f08674SEwan Crawford 2563a0f08674SEwan Crawford if (alloc == nullptr) 2564a0f08674SEwan Crawford { 2565a0f08674SEwan Crawford strm.Printf("Error: Couldn't find allocation with id matching %u", alloc_id); 2566a0f08674SEwan Crawford strm.EOL(); 2567a0f08674SEwan Crawford } 2568a0f08674SEwan Crawford 2569a0f08674SEwan Crawford return alloc; 2570a0f08674SEwan Crawford } 2571a0f08674SEwan Crawford 2572a0f08674SEwan Crawford // Prints the contents of an allocation to the output stream, which may be a file 2573a0f08674SEwan Crawford bool 2574a0f08674SEwan Crawford RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame* frame_ptr, const uint32_t id) 2575a0f08674SEwan Crawford { 2576a0f08674SEwan Crawford Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 2577a0f08674SEwan Crawford 2578a0f08674SEwan Crawford // Check we can find the desired allocation 2579a0f08674SEwan Crawford AllocationDetails* alloc = FindAllocByID(strm, id); 2580a0f08674SEwan Crawford if (!alloc) 2581a0f08674SEwan Crawford return false; // FindAllocByID() will print error message for us here 2582a0f08674SEwan Crawford 2583a0f08674SEwan Crawford if (log) 2584a0f08674SEwan Crawford log->Printf("RenderScriptRuntime::DumpAllocation - Found allocation 0x%" PRIx64, *alloc->address.get()); 2585a0f08674SEwan Crawford 2586a0f08674SEwan Crawford // Check we have information about the allocation, if not calculate it 25878b59062aSEwan Crawford if (alloc->shouldRefresh()) 2588a0f08674SEwan Crawford { 2589a0f08674SEwan Crawford if (log) 2590a0f08674SEwan Crawford log->Printf("RenderScriptRuntime::DumpAllocation - Allocation details not calculated yet, jitting info"); 2591a0f08674SEwan Crawford 2592a0f08674SEwan Crawford // JIT all the allocation information 2593a0f08674SEwan Crawford if (!RefreshAllocation(alloc, frame_ptr)) 2594a0f08674SEwan Crawford { 2595a0f08674SEwan Crawford strm.Printf("Error: Couldn't JIT allocation details"); 2596a0f08674SEwan Crawford strm.EOL(); 2597a0f08674SEwan Crawford return false; 2598a0f08674SEwan Crawford } 2599a0f08674SEwan Crawford } 2600a0f08674SEwan Crawford 2601a0f08674SEwan Crawford // Establish format and size of each data element 26028b244e21SEwan Crawford const unsigned int vec_size = *alloc->element.type_vec_size.get(); 26038b244e21SEwan Crawford const Element::DataType type = *alloc->element.type.get(); 2604a0f08674SEwan Crawford 26052e920715SEwan Crawford assert(type >= Element::RS_TYPE_NONE && type <= Element::RS_TYPE_FONT 2606a0f08674SEwan Crawford && "Invalid allocation type"); 2607a0f08674SEwan Crawford 26082e920715SEwan Crawford lldb::Format format; 26092e920715SEwan Crawford if (type >= Element::RS_TYPE_ELEMENT) 26102e920715SEwan Crawford format = eFormatHex; 26112e920715SEwan Crawford else 26122e920715SEwan Crawford format = vec_size == 1 ? static_cast<lldb::Format>(AllocationDetails::RSTypeToFormat[type][eFormatSingle]) 2613a0f08674SEwan Crawford : static_cast<lldb::Format>(AllocationDetails::RSTypeToFormat[type][eFormatVector]); 2614a0f08674SEwan Crawford 26158b244e21SEwan Crawford const unsigned int data_size = *alloc->element.datum_size.get(); 2616a0f08674SEwan Crawford 2617a0f08674SEwan Crawford if (log) 26188b244e21SEwan Crawford log->Printf("RenderScriptRuntime::DumpAllocation - Element size %u bytes, including padding", data_size); 2619a0f08674SEwan Crawford 262055232f09SEwan Crawford // Allocate a buffer to copy data into 262155232f09SEwan Crawford std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr); 262255232f09SEwan Crawford if (!buffer) 262355232f09SEwan Crawford { 26242e920715SEwan Crawford strm.Printf("Error: Couldn't read allocation data"); 262555232f09SEwan Crawford strm.EOL(); 262655232f09SEwan Crawford return false; 262755232f09SEwan Crawford } 262855232f09SEwan Crawford 2629a0f08674SEwan Crawford // Calculate stride between rows as there may be padding at end of rows since 2630a0f08674SEwan Crawford // allocated memory is 16-byte aligned 2631a0f08674SEwan Crawford if (!alloc->stride.isValid()) 2632a0f08674SEwan Crawford { 2633a0f08674SEwan Crawford if (alloc->dimension.get()->dim_2 == 0) // We only have one dimension 2634a0f08674SEwan Crawford alloc->stride = 0; 2635a0f08674SEwan Crawford else if (!JITAllocationStride(alloc, frame_ptr)) 2636a0f08674SEwan Crawford { 2637a0f08674SEwan Crawford strm.Printf("Error: Couldn't calculate allocation row stride"); 2638a0f08674SEwan Crawford strm.EOL(); 2639a0f08674SEwan Crawford return false; 2640a0f08674SEwan Crawford } 2641a0f08674SEwan Crawford } 2642a0f08674SEwan Crawford const unsigned int stride = *alloc->stride.get(); 26438b244e21SEwan Crawford const unsigned int size = *alloc->size.get(); // Size of whole allocation 26448b244e21SEwan Crawford const unsigned int padding = alloc->element.padding.isValid() ? *alloc->element.padding.get() : 0; 2645a0f08674SEwan Crawford if (log) 26468b244e21SEwan Crawford log->Printf("RenderScriptRuntime::DumpAllocation - stride %u bytes, size %u bytes, padding %u", stride, size, padding); 2647a0f08674SEwan Crawford 2648a0f08674SEwan Crawford // Find dimensions used to index loops, so need to be non-zero 2649a0f08674SEwan Crawford unsigned int dim_x = alloc->dimension.get()->dim_1; 2650a0f08674SEwan Crawford dim_x = dim_x == 0 ? 1 : dim_x; 2651a0f08674SEwan Crawford 2652a0f08674SEwan Crawford unsigned int dim_y = alloc->dimension.get()->dim_2; 2653a0f08674SEwan Crawford dim_y = dim_y == 0 ? 1 : dim_y; 2654a0f08674SEwan Crawford 2655a0f08674SEwan Crawford unsigned int dim_z = alloc->dimension.get()->dim_3; 2656a0f08674SEwan Crawford dim_z = dim_z == 0 ? 1 : dim_z; 2657a0f08674SEwan Crawford 265855232f09SEwan Crawford // Use data extractor to format output 265955232f09SEwan Crawford const uint32_t archByteSize = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize(); 266055232f09SEwan Crawford DataExtractor alloc_data(buffer.get(), size, GetProcess()->GetByteOrder(), archByteSize); 266155232f09SEwan Crawford 2662a0f08674SEwan Crawford unsigned int offset = 0; // Offset in buffer to next element to be printed 2663a0f08674SEwan Crawford unsigned int prev_row = 0; // Offset to the start of the previous row 2664a0f08674SEwan Crawford 2665a0f08674SEwan Crawford // Iterate over allocation dimensions, printing results to user 2666a0f08674SEwan Crawford strm.Printf("Data (X, Y, Z):"); 2667a0f08674SEwan Crawford for (unsigned int z = 0; z < dim_z; ++z) 2668a0f08674SEwan Crawford { 2669a0f08674SEwan Crawford for (unsigned int y = 0; y < dim_y; ++y) 2670a0f08674SEwan Crawford { 2671a0f08674SEwan Crawford // Use stride to index start of next row. 2672a0f08674SEwan Crawford if (!(y==0 && z==0)) 2673a0f08674SEwan Crawford offset = prev_row + stride; 2674a0f08674SEwan Crawford prev_row = offset; 2675a0f08674SEwan Crawford 2676a0f08674SEwan Crawford // Print each element in the row individually 2677a0f08674SEwan Crawford for (unsigned int x = 0; x < dim_x; ++x) 2678a0f08674SEwan Crawford { 2679a0f08674SEwan Crawford strm.Printf("\n(%u, %u, %u) = ", x, y, z); 26808b244e21SEwan Crawford if ((type == Element::RS_TYPE_NONE) && (alloc->element.children.size() > 0) && 2681fe06b5adSAdrian McCarthy (alloc->element.type_name != Element::GetFallbackStructName())) 26828b244e21SEwan Crawford { 26838b244e21SEwan Crawford // Here we are dumping an Element of struct type. 26848b244e21SEwan Crawford // This is done using expression evaluation with the name of the struct type and pointer to element. 26858b244e21SEwan Crawford 26868b244e21SEwan Crawford // Don't print the name of the resulting expression, since this will be '$[0-9]+' 26878b244e21SEwan Crawford DumpValueObjectOptions expr_options; 26888b244e21SEwan Crawford expr_options.SetHideName(true); 26898b244e21SEwan Crawford 26908b244e21SEwan Crawford // Setup expression as derefrencing a pointer cast to element address. 2691b1651b8dSEwan Crawford char expr_char_buffer[jit_max_expr_size]; 2692b1651b8dSEwan Crawford int chars_written = snprintf(expr_char_buffer, jit_max_expr_size, "*(%s*) 0x%" PRIx64, 26938b244e21SEwan Crawford alloc->element.type_name.AsCString(), *alloc->data_ptr.get() + offset); 26948b244e21SEwan Crawford 2695b1651b8dSEwan Crawford if (chars_written < 0 || chars_written >= jit_max_expr_size) 26968b244e21SEwan Crawford { 26978b244e21SEwan Crawford if (log) 26988b244e21SEwan Crawford log->Printf("RenderScriptRuntime::DumpAllocation- Error in snprintf()"); 26998b244e21SEwan Crawford continue; 27008b244e21SEwan Crawford } 27018b244e21SEwan Crawford 27028b244e21SEwan Crawford // Evaluate expression 27038b244e21SEwan Crawford ValueObjectSP expr_result; 27048b244e21SEwan Crawford GetProcess()->GetTarget().EvaluateExpression(expr_char_buffer, frame_ptr, expr_result); 27058b244e21SEwan Crawford 27068b244e21SEwan Crawford // Print the results to our stream. 27078b244e21SEwan Crawford expr_result->Dump(strm, expr_options); 27088b244e21SEwan Crawford } 27098b244e21SEwan Crawford else 27108b244e21SEwan Crawford { 27118b244e21SEwan Crawford alloc_data.Dump(&strm, offset, format, data_size - padding, 1, 1, LLDB_INVALID_ADDRESS, 0, 0); 27128b244e21SEwan Crawford } 27138b244e21SEwan Crawford offset += data_size; 2714a0f08674SEwan Crawford } 2715a0f08674SEwan Crawford } 2716a0f08674SEwan Crawford } 2717a0f08674SEwan Crawford strm.EOL(); 2718a0f08674SEwan Crawford 2719a0f08674SEwan Crawford return true; 2720a0f08674SEwan Crawford } 2721a0f08674SEwan Crawford 272215f2bd95SEwan Crawford // Prints infomation regarding all the currently loaded allocations. 272315f2bd95SEwan Crawford // These details are gathered by jitting the runtime, which has as latency. 272415f2bd95SEwan Crawford void 272515f2bd95SEwan Crawford RenderScriptRuntime::ListAllocations(Stream &strm, StackFrame* frame_ptr, bool recompute) 272615f2bd95SEwan Crawford { 272715f2bd95SEwan Crawford strm.Printf("RenderScript Allocations:"); 272815f2bd95SEwan Crawford strm.EOL(); 272915f2bd95SEwan Crawford strm.IndentMore(); 273015f2bd95SEwan Crawford 273115f2bd95SEwan Crawford for (auto &alloc : m_allocations) 273215f2bd95SEwan Crawford { 273315f2bd95SEwan Crawford // JIT the allocation info if we haven't done it, or the user forces us to. 27348b59062aSEwan Crawford bool do_refresh = alloc->shouldRefresh() || recompute; 273515f2bd95SEwan Crawford 273615f2bd95SEwan Crawford // JIT current allocation information 273715f2bd95SEwan Crawford if (do_refresh && !RefreshAllocation(alloc.get(), frame_ptr)) 273815f2bd95SEwan Crawford { 273915f2bd95SEwan Crawford strm.Printf("Error: Couldn't evaluate details for allocation %u\n", alloc->id); 274015f2bd95SEwan Crawford continue; 274115f2bd95SEwan Crawford } 274215f2bd95SEwan Crawford 274315f2bd95SEwan Crawford strm.Printf("%u:\n",alloc->id); 274415f2bd95SEwan Crawford strm.IndentMore(); 274515f2bd95SEwan Crawford 274615f2bd95SEwan Crawford strm.Indent("Context: "); 274715f2bd95SEwan Crawford if (!alloc->context.isValid()) 274815f2bd95SEwan Crawford strm.Printf("unknown\n"); 274915f2bd95SEwan Crawford else 275015f2bd95SEwan Crawford strm.Printf("0x%" PRIx64 "\n", *alloc->context.get()); 275115f2bd95SEwan Crawford 275215f2bd95SEwan Crawford strm.Indent("Address: "); 275315f2bd95SEwan Crawford if (!alloc->address.isValid()) 275415f2bd95SEwan Crawford strm.Printf("unknown\n"); 275515f2bd95SEwan Crawford else 275615f2bd95SEwan Crawford strm.Printf("0x%" PRIx64 "\n", *alloc->address.get()); 275715f2bd95SEwan Crawford 275815f2bd95SEwan Crawford strm.Indent("Data pointer: "); 275915f2bd95SEwan Crawford if (!alloc->data_ptr.isValid()) 276015f2bd95SEwan Crawford strm.Printf("unknown\n"); 276115f2bd95SEwan Crawford else 276215f2bd95SEwan Crawford strm.Printf("0x%" PRIx64 "\n", *alloc->data_ptr.get()); 276315f2bd95SEwan Crawford 276415f2bd95SEwan Crawford strm.Indent("Dimensions: "); 276515f2bd95SEwan Crawford if (!alloc->dimension.isValid()) 276615f2bd95SEwan Crawford strm.Printf("unknown\n"); 276715f2bd95SEwan Crawford else 276815f2bd95SEwan Crawford strm.Printf("(%d, %d, %d)\n", alloc->dimension.get()->dim_1, 276915f2bd95SEwan Crawford alloc->dimension.get()->dim_2, 277015f2bd95SEwan Crawford alloc->dimension.get()->dim_3); 277115f2bd95SEwan Crawford 277215f2bd95SEwan Crawford strm.Indent("Data Type: "); 27738b244e21SEwan Crawford if (!alloc->element.type.isValid() || !alloc->element.type_vec_size.isValid()) 277415f2bd95SEwan Crawford strm.Printf("unknown\n"); 277515f2bd95SEwan Crawford else 277615f2bd95SEwan Crawford { 27778b244e21SEwan Crawford const int vector_size = *alloc->element.type_vec_size.get(); 27782e920715SEwan Crawford Element::DataType type = *alloc->element.type.get(); 277915f2bd95SEwan Crawford 27808b244e21SEwan Crawford if (!alloc->element.type_name.IsEmpty()) 27818b244e21SEwan Crawford strm.Printf("%s\n", alloc->element.type_name.AsCString()); 27822e920715SEwan Crawford else 27832e920715SEwan Crawford { 27842e920715SEwan Crawford // Enum value isn't monotonous, so doesn't always index RsDataTypeToString array 27852e920715SEwan Crawford if (type >= Element::RS_TYPE_ELEMENT && type <= Element::RS_TYPE_FONT) 27862e920715SEwan Crawford type = static_cast<Element::DataType>((type - Element::RS_TYPE_ELEMENT) + Element::RS_TYPE_MATRIX_2X2 + 1); 27872e920715SEwan Crawford 27882e920715SEwan Crawford if (type >= (sizeof(AllocationDetails::RsDataTypeToString) / sizeof(AllocationDetails::RsDataTypeToString[0])) 27892e920715SEwan Crawford || vector_size > 4 || vector_size < 1) 279015f2bd95SEwan Crawford strm.Printf("invalid type\n"); 279115f2bd95SEwan Crawford else 279215f2bd95SEwan Crawford strm.Printf("%s\n", AllocationDetails::RsDataTypeToString[static_cast<unsigned int>(type)][vector_size-1]); 279315f2bd95SEwan Crawford } 27942e920715SEwan Crawford } 279515f2bd95SEwan Crawford 279615f2bd95SEwan Crawford strm.Indent("Data Kind: "); 27978b244e21SEwan Crawford if (!alloc->element.type_kind.isValid()) 279815f2bd95SEwan Crawford strm.Printf("unknown\n"); 279915f2bd95SEwan Crawford else 280015f2bd95SEwan Crawford { 28018b244e21SEwan Crawford const Element::DataKind kind = *alloc->element.type_kind.get(); 28028b244e21SEwan Crawford if (kind < Element::RS_KIND_USER || kind > Element::RS_KIND_PIXEL_YUV) 280315f2bd95SEwan Crawford strm.Printf("invalid kind\n"); 280415f2bd95SEwan Crawford else 280515f2bd95SEwan Crawford strm.Printf("%s\n", AllocationDetails::RsDataKindToString[static_cast<unsigned int>(kind)]); 280615f2bd95SEwan Crawford } 280715f2bd95SEwan Crawford 280815f2bd95SEwan Crawford strm.EOL(); 280915f2bd95SEwan Crawford strm.IndentLess(); 281015f2bd95SEwan Crawford } 281115f2bd95SEwan Crawford strm.IndentLess(); 281215f2bd95SEwan Crawford } 281315f2bd95SEwan Crawford 28147dc7771cSEwan Crawford // Set breakpoints on every kernel found in RS module 28157dc7771cSEwan Crawford void 28167dc7771cSEwan Crawford RenderScriptRuntime::BreakOnModuleKernels(const RSModuleDescriptorSP rsmodule_sp) 28177dc7771cSEwan Crawford { 28187dc7771cSEwan Crawford for (const auto &kernel : rsmodule_sp->m_kernels) 28197dc7771cSEwan Crawford { 28207dc7771cSEwan Crawford // Don't set breakpoint on 'root' kernel 28217dc7771cSEwan Crawford if (strcmp(kernel.m_name.AsCString(), "root") == 0) 28227dc7771cSEwan Crawford continue; 28237dc7771cSEwan Crawford 28247dc7771cSEwan Crawford CreateKernelBreakpoint(kernel.m_name); 28257dc7771cSEwan Crawford } 28267dc7771cSEwan Crawford } 28277dc7771cSEwan Crawford 28287dc7771cSEwan Crawford // Method is internally called by the 'kernel breakpoint all' command to 28297dc7771cSEwan Crawford // enable or disable breaking on all kernels. 28307dc7771cSEwan Crawford // 28317dc7771cSEwan Crawford // When do_break is true we want to enable this functionality. 28327dc7771cSEwan Crawford // When do_break is false we want to disable it. 28337dc7771cSEwan Crawford void 28347dc7771cSEwan Crawford RenderScriptRuntime::SetBreakAllKernels(bool do_break, TargetSP target) 28357dc7771cSEwan Crawford { 283654782db7SEwan Crawford Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS)); 28377dc7771cSEwan Crawford 28387dc7771cSEwan Crawford InitSearchFilter(target); 28397dc7771cSEwan Crawford 28407dc7771cSEwan Crawford // Set breakpoints on all the kernels 28417dc7771cSEwan Crawford if (do_break && !m_breakAllKernels) 28427dc7771cSEwan Crawford { 28437dc7771cSEwan Crawford m_breakAllKernels = true; 28447dc7771cSEwan Crawford 28457dc7771cSEwan Crawford for (const auto &module : m_rsmodules) 28467dc7771cSEwan Crawford BreakOnModuleKernels(module); 28477dc7771cSEwan Crawford 28487dc7771cSEwan Crawford if (log) 28497dc7771cSEwan Crawford log->Printf("RenderScriptRuntime::SetBreakAllKernels(True)" 28507dc7771cSEwan Crawford "- breakpoints set on all currently loaded kernels"); 28517dc7771cSEwan Crawford } 28527dc7771cSEwan Crawford else if (!do_break && m_breakAllKernels) // Breakpoints won't be set on any new kernels. 28537dc7771cSEwan Crawford { 28547dc7771cSEwan Crawford m_breakAllKernels = false; 28557dc7771cSEwan Crawford 28567dc7771cSEwan Crawford if (log) 28577dc7771cSEwan Crawford log->Printf("RenderScriptRuntime::SetBreakAllKernels(False) - breakpoints no longer automatically set"); 28587dc7771cSEwan Crawford } 28597dc7771cSEwan Crawford } 28607dc7771cSEwan Crawford 28617dc7771cSEwan Crawford // Given the name of a kernel this function creates a breakpoint using our 28627dc7771cSEwan Crawford // own breakpoint resolver, and returns the Breakpoint shared pointer. 28637dc7771cSEwan Crawford BreakpointSP 28647dc7771cSEwan Crawford RenderScriptRuntime::CreateKernelBreakpoint(const ConstString& name) 28657dc7771cSEwan Crawford { 286654782db7SEwan Crawford Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS)); 28677dc7771cSEwan Crawford 28687dc7771cSEwan Crawford if (!m_filtersp) 28697dc7771cSEwan Crawford { 28707dc7771cSEwan Crawford if (log) 28717dc7771cSEwan Crawford log->Printf("RenderScriptRuntime::CreateKernelBreakpoint - Error: No breakpoint search filter set"); 28727dc7771cSEwan Crawford return nullptr; 28737dc7771cSEwan Crawford } 28747dc7771cSEwan Crawford 28757dc7771cSEwan Crawford BreakpointResolverSP resolver_sp(new RSBreakpointResolver(nullptr, name)); 28767dc7771cSEwan Crawford BreakpointSP bp = GetProcess()->GetTarget().CreateBreakpoint(m_filtersp, resolver_sp, false, false, false); 28777dc7771cSEwan Crawford 287854782db7SEwan Crawford // Give RS breakpoints a specific name, so the user can manipulate them as a group. 287954782db7SEwan Crawford Error err; 288054782db7SEwan Crawford if (!bp->AddName("RenderScriptKernel", err) && log) 288154782db7SEwan Crawford log->Printf("RenderScriptRuntime::CreateKernelBreakpoint: Error setting break name, %s", err.AsCString()); 288254782db7SEwan Crawford 28837dc7771cSEwan Crawford return bp; 28847dc7771cSEwan Crawford } 28857dc7771cSEwan Crawford 2886018f5a7eSEwan Crawford // Given an expression for a variable this function tries to calculate the variable's value. 2887018f5a7eSEwan Crawford // If this is possible it returns true and sets the uint64_t parameter to the variables unsigned value. 2888018f5a7eSEwan Crawford // Otherwise function returns false. 2889018f5a7eSEwan Crawford bool 2890018f5a7eSEwan Crawford RenderScriptRuntime::GetFrameVarAsUnsigned(const StackFrameSP frame_sp, const char* var_name, uint64_t& val) 2891018f5a7eSEwan Crawford { 2892018f5a7eSEwan Crawford Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 2893018f5a7eSEwan Crawford Error error; 2894018f5a7eSEwan Crawford VariableSP var_sp; 2895018f5a7eSEwan Crawford 2896018f5a7eSEwan Crawford // Find variable in stack frame 2897018f5a7eSEwan Crawford ValueObjectSP value_sp(frame_sp->GetValueForVariableExpressionPath(var_name, 2898018f5a7eSEwan Crawford eNoDynamicValues, 2899018f5a7eSEwan Crawford StackFrame::eExpressionPathOptionCheckPtrVsMember | 2900018f5a7eSEwan Crawford StackFrame::eExpressionPathOptionsAllowDirectIVarAccess, 2901018f5a7eSEwan Crawford var_sp, 2902018f5a7eSEwan Crawford error)); 2903018f5a7eSEwan Crawford if (!error.Success()) 2904018f5a7eSEwan Crawford { 2905018f5a7eSEwan Crawford if (log) 2906018f5a7eSEwan Crawford log->Printf("RenderScriptRuntime::GetFrameVarAsUnsigned - Error, couldn't find '%s' in frame", var_name); 2907018f5a7eSEwan Crawford 2908018f5a7eSEwan Crawford return false; 2909018f5a7eSEwan Crawford } 2910018f5a7eSEwan Crawford 2911018f5a7eSEwan Crawford // Find the unsigned int value for the variable 2912018f5a7eSEwan Crawford bool success = false; 2913018f5a7eSEwan Crawford val = value_sp->GetValueAsUnsigned(0, &success); 2914018f5a7eSEwan Crawford if (!success) 2915018f5a7eSEwan Crawford { 2916018f5a7eSEwan Crawford if (log) 2917018f5a7eSEwan Crawford log->Printf("RenderScriptRuntime::GetFrameVarAsUnsigned - Error, couldn't parse '%s' as an unsigned int", var_name); 2918018f5a7eSEwan Crawford 2919018f5a7eSEwan Crawford return false; 2920018f5a7eSEwan Crawford } 2921018f5a7eSEwan Crawford 2922018f5a7eSEwan Crawford return true; 2923018f5a7eSEwan Crawford } 2924018f5a7eSEwan Crawford 2925018f5a7eSEwan Crawford // Callback when a kernel breakpoint hits and we're looking for a specific coordinate. 2926018f5a7eSEwan Crawford // Baton parameter contains a pointer to the target coordinate we want to break on. 2927018f5a7eSEwan Crawford // Function then checks the .expand frame for the current coordinate and breaks to user if it matches. 2928018f5a7eSEwan Crawford // Parameter 'break_id' is the id of the Breakpoint which made the callback. 2929018f5a7eSEwan Crawford // Parameter 'break_loc_id' is the id for the BreakpointLocation which was hit, 2930018f5a7eSEwan Crawford // a single logical breakpoint can have multiple addresses. 2931018f5a7eSEwan Crawford bool 2932018f5a7eSEwan Crawford RenderScriptRuntime::KernelBreakpointHit(void *baton, StoppointCallbackContext *ctx, 2933018f5a7eSEwan Crawford user_id_t break_id, user_id_t break_loc_id) 2934018f5a7eSEwan Crawford { 2935018f5a7eSEwan Crawford Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS)); 2936018f5a7eSEwan Crawford 2937018f5a7eSEwan Crawford assert(baton && "Error: null baton in conditional kernel breakpoint callback"); 2938018f5a7eSEwan Crawford 2939018f5a7eSEwan Crawford // Coordinate we want to stop on 2940018f5a7eSEwan Crawford const int* target_coord = static_cast<const int*>(baton); 2941018f5a7eSEwan Crawford 2942018f5a7eSEwan Crawford if (log) 2943018f5a7eSEwan Crawford log->Printf("RenderScriptRuntime::KernelBreakpointHit - Break ID %" PRIu64 ", target coord (%d, %d, %d)", 2944018f5a7eSEwan Crawford break_id, target_coord[0], target_coord[1], target_coord[2]); 2945018f5a7eSEwan Crawford 2946018f5a7eSEwan Crawford // Go up one stack frame to .expand kernel 2947018f5a7eSEwan Crawford ExecutionContext context(ctx->exe_ctx_ref); 2948018f5a7eSEwan Crawford ThreadSP thread_sp = context.GetThreadSP(); 2949018f5a7eSEwan Crawford if (!thread_sp->SetSelectedFrameByIndex(1)) 2950018f5a7eSEwan Crawford { 2951018f5a7eSEwan Crawford if (log) 2952018f5a7eSEwan Crawford log->Printf("RenderScriptRuntime::KernelBreakpointHit - Error, couldn't go up stack frame"); 2953018f5a7eSEwan Crawford 2954018f5a7eSEwan Crawford return false; 2955018f5a7eSEwan Crawford } 2956018f5a7eSEwan Crawford 2957018f5a7eSEwan Crawford StackFrameSP frame_sp = thread_sp->GetSelectedFrame(); 2958018f5a7eSEwan Crawford if (!frame_sp) 2959018f5a7eSEwan Crawford { 2960018f5a7eSEwan Crawford if (log) 2961018f5a7eSEwan Crawford log->Printf("RenderScriptRuntime::KernelBreakpointHit - Error, couldn't select .expand stack frame"); 2962018f5a7eSEwan Crawford 2963018f5a7eSEwan Crawford return false; 2964018f5a7eSEwan Crawford } 2965018f5a7eSEwan Crawford 2966018f5a7eSEwan Crawford // Get values for variables in .expand frame that tell us the current kernel invocation 2967018f5a7eSEwan Crawford const char* coord_expressions[] = {"rsIndex", "p->current.y", "p->current.z"}; 2968018f5a7eSEwan Crawford uint64_t current_coord[3] = {0, 0, 0}; 2969018f5a7eSEwan Crawford 2970018f5a7eSEwan Crawford for(int i = 0; i < 3; ++i) 2971018f5a7eSEwan Crawford { 2972018f5a7eSEwan Crawford if (!GetFrameVarAsUnsigned(frame_sp, coord_expressions[i], current_coord[i])) 2973018f5a7eSEwan Crawford return false; 2974018f5a7eSEwan Crawford 2975018f5a7eSEwan Crawford if (log) 2976018f5a7eSEwan Crawford log->Printf("RenderScriptRuntime::KernelBreakpointHit, %s = %" PRIu64, coord_expressions[i], current_coord[i]); 2977018f5a7eSEwan Crawford } 2978018f5a7eSEwan Crawford 2979018f5a7eSEwan Crawford // Check if the current kernel invocation coordinate matches our target coordinate 2980018f5a7eSEwan Crawford if (current_coord[0] == static_cast<uint64_t>(target_coord[0]) && 2981018f5a7eSEwan Crawford current_coord[1] == static_cast<uint64_t>(target_coord[1]) && 2982018f5a7eSEwan Crawford current_coord[2] == static_cast<uint64_t>(target_coord[2])) 2983018f5a7eSEwan Crawford { 2984018f5a7eSEwan Crawford if (log) 2985018f5a7eSEwan Crawford log->Printf("RenderScriptRuntime::KernelBreakpointHit, BREAKING %" PRIu64 ", %" PRIu64 ", %" PRIu64, 2986018f5a7eSEwan Crawford current_coord[0], current_coord[1], current_coord[2]); 2987018f5a7eSEwan Crawford 2988018f5a7eSEwan Crawford BreakpointSP breakpoint_sp = context.GetTargetPtr()->GetBreakpointByID(break_id); 2989018f5a7eSEwan Crawford assert(breakpoint_sp != nullptr && "Error: Couldn't find breakpoint matching break id for callback"); 2990018f5a7eSEwan Crawford breakpoint_sp->SetEnabled(false); // Optimise since conditional breakpoint should only be hit once. 2991018f5a7eSEwan Crawford return true; 2992018f5a7eSEwan Crawford } 2993018f5a7eSEwan Crawford 2994018f5a7eSEwan Crawford // No match on coordinate 2995018f5a7eSEwan Crawford return false; 2996018f5a7eSEwan Crawford } 2997018f5a7eSEwan Crawford 2998018f5a7eSEwan Crawford // Tries to set a breakpoint on the start of a kernel, resolved using the kernel name. 2999018f5a7eSEwan Crawford // Argument 'coords', represents a three dimensional coordinate which can be used to specify 3000018f5a7eSEwan Crawford // a single kernel instance to break on. If this is set then we add a callback to the breakpoint. 30014640cde1SColin Riley void 3002018f5a7eSEwan Crawford RenderScriptRuntime::PlaceBreakpointOnKernel(Stream &strm, const char* name, const std::array<int,3> coords, 3003018f5a7eSEwan Crawford Error& error, TargetSP target) 30044640cde1SColin Riley { 30054640cde1SColin Riley if (!name) 30064640cde1SColin Riley { 30074640cde1SColin Riley error.SetErrorString("invalid kernel name"); 30084640cde1SColin Riley return; 30094640cde1SColin Riley } 30104640cde1SColin Riley 30117dc7771cSEwan Crawford InitSearchFilter(target); 301298156583SEwan Crawford 30134640cde1SColin Riley ConstString kernel_name(name); 30147dc7771cSEwan Crawford BreakpointSP bp = CreateKernelBreakpoint(kernel_name); 3015018f5a7eSEwan Crawford 3016018f5a7eSEwan Crawford // We have a conditional breakpoint on a specific coordinate 3017018f5a7eSEwan Crawford if (coords[0] != -1) 3018018f5a7eSEwan Crawford { 3019018f5a7eSEwan Crawford strm.Printf("Conditional kernel breakpoint on coordinate %d, %d, %d", coords[0], coords[1], coords[2]); 3020018f5a7eSEwan Crawford strm.EOL(); 3021018f5a7eSEwan Crawford 3022018f5a7eSEwan Crawford // Allocate memory for the baton, and copy over coordinate 3023018f5a7eSEwan Crawford int* baton = new int[3]; 3024018f5a7eSEwan Crawford baton[0] = coords[0]; baton[1] = coords[1]; baton[2] = coords[2]; 3025018f5a7eSEwan Crawford 3026018f5a7eSEwan Crawford // Create a callback that will be invoked everytime the breakpoint is hit. 3027018f5a7eSEwan Crawford // The baton object passed to the handler is the target coordinate we want to break on. 3028018f5a7eSEwan Crawford bp->SetCallback(KernelBreakpointHit, baton, true); 3029018f5a7eSEwan Crawford 3030018f5a7eSEwan Crawford // Store a shared pointer to the baton, so the memory will eventually be cleaned up after destruction 3031018f5a7eSEwan Crawford m_conditional_breaks[bp->GetID()] = std::shared_ptr<int>(baton); 3032018f5a7eSEwan Crawford } 3033018f5a7eSEwan Crawford 303498156583SEwan Crawford if (bp) 303598156583SEwan Crawford bp->GetDescription(&strm, lldb::eDescriptionLevelInitial, false); 30364640cde1SColin Riley } 30374640cde1SColin Riley 30384640cde1SColin Riley void 30395ec532a9SColin Riley RenderScriptRuntime::DumpModules(Stream &strm) const 30405ec532a9SColin Riley { 30415ec532a9SColin Riley strm.Printf("RenderScript Modules:"); 30425ec532a9SColin Riley strm.EOL(); 30435ec532a9SColin Riley strm.IndentMore(); 30445ec532a9SColin Riley for (const auto &module : m_rsmodules) 30455ec532a9SColin Riley { 30464640cde1SColin Riley module->Dump(strm); 30475ec532a9SColin Riley } 30485ec532a9SColin Riley strm.IndentLess(); 30495ec532a9SColin Riley } 30505ec532a9SColin Riley 305178f339d1SEwan Crawford RenderScriptRuntime::ScriptDetails* 305278f339d1SEwan Crawford RenderScriptRuntime::LookUpScript(addr_t address, bool create) 305378f339d1SEwan Crawford { 305478f339d1SEwan Crawford for (const auto & s : m_scripts) 305578f339d1SEwan Crawford { 305678f339d1SEwan Crawford if (s->script.isValid()) 305778f339d1SEwan Crawford if (*s->script == address) 305878f339d1SEwan Crawford return s.get(); 305978f339d1SEwan Crawford } 306078f339d1SEwan Crawford if (create) 306178f339d1SEwan Crawford { 306278f339d1SEwan Crawford std::unique_ptr<ScriptDetails> s(new ScriptDetails); 306378f339d1SEwan Crawford s->script = address; 306478f339d1SEwan Crawford m_scripts.push_back(std::move(s)); 3065d10ca9deSEwan Crawford return m_scripts.back().get(); 306678f339d1SEwan Crawford } 306778f339d1SEwan Crawford return nullptr; 306878f339d1SEwan Crawford } 306978f339d1SEwan Crawford 307078f339d1SEwan Crawford RenderScriptRuntime::AllocationDetails* 307178f339d1SEwan Crawford RenderScriptRuntime::LookUpAllocation(addr_t address, bool create) 307278f339d1SEwan Crawford { 307378f339d1SEwan Crawford for (const auto & a : m_allocations) 307478f339d1SEwan Crawford { 307578f339d1SEwan Crawford if (a->address.isValid()) 307678f339d1SEwan Crawford if (*a->address == address) 307778f339d1SEwan Crawford return a.get(); 307878f339d1SEwan Crawford } 307978f339d1SEwan Crawford if (create) 308078f339d1SEwan Crawford { 308178f339d1SEwan Crawford std::unique_ptr<AllocationDetails> a(new AllocationDetails); 308278f339d1SEwan Crawford a->address = address; 308378f339d1SEwan Crawford m_allocations.push_back(std::move(a)); 3084d10ca9deSEwan Crawford return m_allocations.back().get(); 308578f339d1SEwan Crawford } 308678f339d1SEwan Crawford return nullptr; 308778f339d1SEwan Crawford } 308878f339d1SEwan Crawford 30895ec532a9SColin Riley void 30905ec532a9SColin Riley RSModuleDescriptor::Dump(Stream &strm) const 30915ec532a9SColin Riley { 30925ec532a9SColin Riley strm.Indent(); 30935ec532a9SColin Riley m_module->GetFileSpec().Dump(&strm); 30944640cde1SColin Riley if(m_module->GetNumCompileUnits()) 30954640cde1SColin Riley { 30964640cde1SColin Riley strm.Indent("Debug info loaded."); 30974640cde1SColin Riley } 30984640cde1SColin Riley else 30994640cde1SColin Riley { 31004640cde1SColin Riley strm.Indent("Debug info does not exist."); 31014640cde1SColin Riley } 31025ec532a9SColin Riley strm.EOL(); 31035ec532a9SColin Riley strm.IndentMore(); 31045ec532a9SColin Riley strm.Indent(); 3105189598edSColin Riley strm.Printf("Globals: %" PRIu64, static_cast<uint64_t>(m_globals.size())); 31065ec532a9SColin Riley strm.EOL(); 31075ec532a9SColin Riley strm.IndentMore(); 31085ec532a9SColin Riley for (const auto &global : m_globals) 31095ec532a9SColin Riley { 31105ec532a9SColin Riley global.Dump(strm); 31115ec532a9SColin Riley } 31125ec532a9SColin Riley strm.IndentLess(); 31135ec532a9SColin Riley strm.Indent(); 3114189598edSColin Riley strm.Printf("Kernels: %" PRIu64, static_cast<uint64_t>(m_kernels.size())); 31155ec532a9SColin Riley strm.EOL(); 31165ec532a9SColin Riley strm.IndentMore(); 31175ec532a9SColin Riley for (const auto &kernel : m_kernels) 31185ec532a9SColin Riley { 31195ec532a9SColin Riley kernel.Dump(strm); 31205ec532a9SColin Riley } 31214640cde1SColin Riley strm.Printf("Pragmas: %" PRIu64 , static_cast<uint64_t>(m_pragmas.size())); 31224640cde1SColin Riley strm.EOL(); 31234640cde1SColin Riley strm.IndentMore(); 31244640cde1SColin Riley for (const auto &key_val : m_pragmas) 31254640cde1SColin Riley { 31264640cde1SColin Riley strm.Printf("%s: %s", key_val.first.c_str(), key_val.second.c_str()); 31274640cde1SColin Riley strm.EOL(); 31284640cde1SColin Riley } 31295ec532a9SColin Riley strm.IndentLess(4); 31305ec532a9SColin Riley } 31315ec532a9SColin Riley 31325ec532a9SColin Riley void 31335ec532a9SColin Riley RSGlobalDescriptor::Dump(Stream &strm) const 31345ec532a9SColin Riley { 31355ec532a9SColin Riley strm.Indent(m_name.AsCString()); 31364640cde1SColin Riley VariableList var_list; 31374640cde1SColin Riley m_module->m_module->FindGlobalVariables(m_name, nullptr, true, 1U, var_list); 31384640cde1SColin Riley if (var_list.GetSize() == 1) 31394640cde1SColin Riley { 31404640cde1SColin Riley auto var = var_list.GetVariableAtIndex(0); 31414640cde1SColin Riley auto type = var->GetType(); 31424640cde1SColin Riley if(type) 31434640cde1SColin Riley { 31444640cde1SColin Riley strm.Printf(" - "); 31454640cde1SColin Riley type->DumpTypeName(&strm); 31464640cde1SColin Riley } 31474640cde1SColin Riley else 31484640cde1SColin Riley { 31494640cde1SColin Riley strm.Printf(" - Unknown Type"); 31504640cde1SColin Riley } 31514640cde1SColin Riley } 31524640cde1SColin Riley else 31534640cde1SColin Riley { 31544640cde1SColin Riley strm.Printf(" - variable identified, but not found in binary"); 31554640cde1SColin Riley const Symbol* s = m_module->m_module->FindFirstSymbolWithNameAndType(m_name, eSymbolTypeData); 31564640cde1SColin Riley if (s) 31574640cde1SColin Riley { 31584640cde1SColin Riley strm.Printf(" (symbol exists) "); 31594640cde1SColin Riley } 31604640cde1SColin Riley } 31614640cde1SColin Riley 31625ec532a9SColin Riley strm.EOL(); 31635ec532a9SColin Riley } 31645ec532a9SColin Riley 31655ec532a9SColin Riley void 31665ec532a9SColin Riley RSKernelDescriptor::Dump(Stream &strm) const 31675ec532a9SColin Riley { 31685ec532a9SColin Riley strm.Indent(m_name.AsCString()); 31695ec532a9SColin Riley strm.EOL(); 31705ec532a9SColin Riley } 31715ec532a9SColin Riley 31725ec532a9SColin Riley class CommandObjectRenderScriptRuntimeModuleProbe : public CommandObjectParsed 31735ec532a9SColin Riley { 31745ec532a9SColin Riley public: 31755ec532a9SColin Riley CommandObjectRenderScriptRuntimeModuleProbe(CommandInterpreter &interpreter) 31765ec532a9SColin Riley : CommandObjectParsed(interpreter, "renderscript module probe", 31775ec532a9SColin Riley "Initiates a Probe of all loaded modules for kernels and other renderscript objects.", 31785ec532a9SColin Riley "renderscript module probe", 3179e87764f2SEnrico Granata eCommandRequiresTarget | eCommandRequiresProcess | eCommandProcessMustBeLaunched) 31805ec532a9SColin Riley { 31815ec532a9SColin Riley } 31825ec532a9SColin Riley 3183222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeModuleProbe() override = default; 31845ec532a9SColin Riley 31855ec532a9SColin Riley bool 3186222b937cSEugene Zelenko DoExecute(Args &command, CommandReturnObject &result) override 31875ec532a9SColin Riley { 31885ec532a9SColin Riley const size_t argc = command.GetArgumentCount(); 31895ec532a9SColin Riley if (argc == 0) 31905ec532a9SColin Riley { 31915ec532a9SColin Riley Target *target = m_exe_ctx.GetTargetPtr(); 31925ec532a9SColin Riley RenderScriptRuntime *runtime = 31935ec532a9SColin Riley (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); 31945ec532a9SColin Riley auto module_list = target->GetImages(); 31955ec532a9SColin Riley bool new_rs_details = runtime->ProbeModules(module_list); 31965ec532a9SColin Riley if (new_rs_details) 31975ec532a9SColin Riley { 31985ec532a9SColin Riley result.AppendMessage("New renderscript modules added to runtime model."); 31995ec532a9SColin Riley } 32005ec532a9SColin Riley result.SetStatus(eReturnStatusSuccessFinishResult); 32015ec532a9SColin Riley return true; 32025ec532a9SColin Riley } 32035ec532a9SColin Riley 32045ec532a9SColin Riley result.AppendErrorWithFormat("'%s' takes no arguments", m_cmd_name.c_str()); 32055ec532a9SColin Riley result.SetStatus(eReturnStatusFailed); 32065ec532a9SColin Riley return false; 32075ec532a9SColin Riley } 32085ec532a9SColin Riley }; 32095ec532a9SColin Riley 32105ec532a9SColin Riley class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed 32115ec532a9SColin Riley { 32125ec532a9SColin Riley public: 32135ec532a9SColin Riley CommandObjectRenderScriptRuntimeModuleDump(CommandInterpreter &interpreter) 32145ec532a9SColin Riley : CommandObjectParsed(interpreter, "renderscript module dump", 32155ec532a9SColin Riley "Dumps renderscript specific information for all modules.", "renderscript module dump", 3216e87764f2SEnrico Granata eCommandRequiresProcess | eCommandProcessMustBeLaunched) 32175ec532a9SColin Riley { 32185ec532a9SColin Riley } 32195ec532a9SColin Riley 3220222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeModuleDump() override = default; 32215ec532a9SColin Riley 32225ec532a9SColin Riley bool 3223222b937cSEugene Zelenko DoExecute(Args &command, CommandReturnObject &result) override 32245ec532a9SColin Riley { 32255ec532a9SColin Riley RenderScriptRuntime *runtime = 32265ec532a9SColin Riley (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); 32275ec532a9SColin Riley runtime->DumpModules(result.GetOutputStream()); 32285ec532a9SColin Riley result.SetStatus(eReturnStatusSuccessFinishResult); 32295ec532a9SColin Riley return true; 32305ec532a9SColin Riley } 32315ec532a9SColin Riley }; 32325ec532a9SColin Riley 32335ec532a9SColin Riley class CommandObjectRenderScriptRuntimeModule : public CommandObjectMultiword 32345ec532a9SColin Riley { 32355ec532a9SColin Riley public: 32365ec532a9SColin Riley CommandObjectRenderScriptRuntimeModule(CommandInterpreter &interpreter) 32375ec532a9SColin Riley : CommandObjectMultiword(interpreter, "renderscript module", "Commands that deal with renderscript modules.", 32385ec532a9SColin Riley NULL) 32395ec532a9SColin Riley { 32405ec532a9SColin Riley LoadSubCommand("probe", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleProbe(interpreter))); 32415ec532a9SColin Riley LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleDump(interpreter))); 32425ec532a9SColin Riley } 32435ec532a9SColin Riley 3244222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeModule() override = default; 32455ec532a9SColin Riley }; 32465ec532a9SColin Riley 32474640cde1SColin Riley class CommandObjectRenderScriptRuntimeKernelList : public CommandObjectParsed 32484640cde1SColin Riley { 32494640cde1SColin Riley public: 32504640cde1SColin Riley CommandObjectRenderScriptRuntimeKernelList(CommandInterpreter &interpreter) 32514640cde1SColin Riley : CommandObjectParsed(interpreter, "renderscript kernel list", 32524640cde1SColin Riley "Lists renderscript kernel names and associated script resources.", "renderscript kernel list", 32534640cde1SColin Riley eCommandRequiresProcess | eCommandProcessMustBeLaunched) 32544640cde1SColin Riley { 32554640cde1SColin Riley } 32564640cde1SColin Riley 3257222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeKernelList() override = default; 32584640cde1SColin Riley 32594640cde1SColin Riley bool 3260222b937cSEugene Zelenko DoExecute(Args &command, CommandReturnObject &result) override 32614640cde1SColin Riley { 32624640cde1SColin Riley RenderScriptRuntime *runtime = 32634640cde1SColin Riley (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); 32644640cde1SColin Riley runtime->DumpKernels(result.GetOutputStream()); 32654640cde1SColin Riley result.SetStatus(eReturnStatusSuccessFinishResult); 32664640cde1SColin Riley return true; 32674640cde1SColin Riley } 32684640cde1SColin Riley }; 32694640cde1SColin Riley 32707dc7771cSEwan Crawford class CommandObjectRenderScriptRuntimeKernelBreakpointSet : public CommandObjectParsed 32714640cde1SColin Riley { 32724640cde1SColin Riley public: 32737dc7771cSEwan Crawford CommandObjectRenderScriptRuntimeKernelBreakpointSet(CommandInterpreter &interpreter) 32747dc7771cSEwan Crawford : CommandObjectParsed(interpreter, "renderscript kernel breakpoint set", 3275018f5a7eSEwan Crawford "Sets a breakpoint on a renderscript kernel.", "renderscript kernel breakpoint set <kernel_name> [-c x,y,z]", 3276018f5a7eSEwan Crawford eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), m_options(interpreter) 32774640cde1SColin Riley { 32784640cde1SColin Riley } 32794640cde1SColin Riley 3280222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeKernelBreakpointSet() override = default; 3281222b937cSEugene Zelenko 3282222b937cSEugene Zelenko Options* 3283222b937cSEugene Zelenko GetOptions() override 3284018f5a7eSEwan Crawford { 3285018f5a7eSEwan Crawford return &m_options; 3286018f5a7eSEwan Crawford } 3287018f5a7eSEwan Crawford 3288018f5a7eSEwan Crawford class CommandOptions : public Options 3289018f5a7eSEwan Crawford { 3290018f5a7eSEwan Crawford public: 3291018f5a7eSEwan Crawford CommandOptions(CommandInterpreter &interpreter) : Options(interpreter) 3292018f5a7eSEwan Crawford { 3293018f5a7eSEwan Crawford } 3294018f5a7eSEwan Crawford 3295222b937cSEugene Zelenko ~CommandOptions() override = default; 3296018f5a7eSEwan Crawford 3297222b937cSEugene Zelenko Error 3298222b937cSEugene Zelenko SetOptionValue(uint32_t option_idx, const char *option_arg) override 3299018f5a7eSEwan Crawford { 3300018f5a7eSEwan Crawford Error error; 3301018f5a7eSEwan Crawford const int short_option = m_getopt_table[option_idx].val; 3302018f5a7eSEwan Crawford 3303018f5a7eSEwan Crawford switch (short_option) 3304018f5a7eSEwan Crawford { 3305018f5a7eSEwan Crawford case 'c': 3306018f5a7eSEwan Crawford if (!ParseCoordinate(option_arg)) 3307018f5a7eSEwan Crawford error.SetErrorStringWithFormat("Couldn't parse coordinate '%s', should be in format 'x,y,z'.", option_arg); 3308018f5a7eSEwan Crawford break; 3309018f5a7eSEwan Crawford default: 3310018f5a7eSEwan Crawford error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); 3311018f5a7eSEwan Crawford break; 3312018f5a7eSEwan Crawford } 3313018f5a7eSEwan Crawford return error; 3314018f5a7eSEwan Crawford } 3315018f5a7eSEwan Crawford 3316018f5a7eSEwan Crawford // -c takes an argument of the form 'num[,num][,num]'. 3317018f5a7eSEwan Crawford // Where 'id_cstr' is this argument with the whitespace trimmed. 3318018f5a7eSEwan Crawford // Missing coordinates are defaulted to zero. 3319018f5a7eSEwan Crawford bool 3320018f5a7eSEwan Crawford ParseCoordinate(const char* id_cstr) 3321018f5a7eSEwan Crawford { 3322018f5a7eSEwan Crawford RegularExpression regex; 3323018f5a7eSEwan Crawford RegularExpression::Match regex_match(3); 3324018f5a7eSEwan Crawford 3325018f5a7eSEwan Crawford bool matched = false; 3326018f5a7eSEwan Crawford if(regex.Compile("^([0-9]+),([0-9]+),([0-9]+)$") && regex.Execute(id_cstr, ®ex_match)) 3327018f5a7eSEwan Crawford matched = true; 3328018f5a7eSEwan Crawford else if(regex.Compile("^([0-9]+),([0-9]+)$") && regex.Execute(id_cstr, ®ex_match)) 3329018f5a7eSEwan Crawford matched = true; 3330018f5a7eSEwan Crawford else if(regex.Compile("^([0-9]+)$") && regex.Execute(id_cstr, ®ex_match)) 3331018f5a7eSEwan Crawford matched = true; 3332018f5a7eSEwan Crawford for(uint32_t i = 0; i < 3; i++) 3333018f5a7eSEwan Crawford { 3334018f5a7eSEwan Crawford std::string group; 3335018f5a7eSEwan Crawford if(regex_match.GetMatchAtIndex(id_cstr, i + 1, group)) 3336018f5a7eSEwan Crawford m_coord[i] = (uint32_t)strtoul(group.c_str(), NULL, 0); 3337018f5a7eSEwan Crawford else 3338018f5a7eSEwan Crawford m_coord[i] = 0; 3339018f5a7eSEwan Crawford } 3340018f5a7eSEwan Crawford return matched; 3341018f5a7eSEwan Crawford } 3342018f5a7eSEwan Crawford 3343018f5a7eSEwan Crawford void 3344222b937cSEugene Zelenko OptionParsingStarting() override 3345018f5a7eSEwan Crawford { 3346018f5a7eSEwan Crawford // -1 means the -c option hasn't been set 3347018f5a7eSEwan Crawford m_coord[0] = -1; 3348018f5a7eSEwan Crawford m_coord[1] = -1; 3349018f5a7eSEwan Crawford m_coord[2] = -1; 3350018f5a7eSEwan Crawford } 3351018f5a7eSEwan Crawford 3352018f5a7eSEwan Crawford const OptionDefinition* 3353222b937cSEugene Zelenko GetDefinitions() override 3354018f5a7eSEwan Crawford { 3355018f5a7eSEwan Crawford return g_option_table; 3356018f5a7eSEwan Crawford } 3357018f5a7eSEwan Crawford 3358018f5a7eSEwan Crawford static OptionDefinition g_option_table[]; 3359018f5a7eSEwan Crawford std::array<int,3> m_coord; 3360018f5a7eSEwan Crawford }; 3361018f5a7eSEwan Crawford 33624640cde1SColin Riley bool 3363222b937cSEugene Zelenko DoExecute(Args &command, CommandReturnObject &result) override 33644640cde1SColin Riley { 33654640cde1SColin Riley const size_t argc = command.GetArgumentCount(); 3366018f5a7eSEwan Crawford if (argc < 1) 33674640cde1SColin Riley { 3368018f5a7eSEwan Crawford result.AppendErrorWithFormat("'%s' takes 1 argument of kernel name, and an optional coordinate.", m_cmd_name.c_str()); 3369018f5a7eSEwan Crawford result.SetStatus(eReturnStatusFailed); 3370018f5a7eSEwan Crawford return false; 3371018f5a7eSEwan Crawford } 3372018f5a7eSEwan Crawford 33734640cde1SColin Riley RenderScriptRuntime *runtime = 33744640cde1SColin Riley (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); 33754640cde1SColin Riley 33764640cde1SColin Riley Error error; 3377018f5a7eSEwan Crawford runtime->PlaceBreakpointOnKernel(result.GetOutputStream(), command.GetArgumentAtIndex(0), m_options.m_coord, 337898156583SEwan Crawford error, m_exe_ctx.GetTargetSP()); 33794640cde1SColin Riley 33804640cde1SColin Riley if (error.Success()) 33814640cde1SColin Riley { 33824640cde1SColin Riley result.AppendMessage("Breakpoint(s) created"); 33834640cde1SColin Riley result.SetStatus(eReturnStatusSuccessFinishResult); 33844640cde1SColin Riley return true; 33854640cde1SColin Riley } 33864640cde1SColin Riley result.SetStatus(eReturnStatusFailed); 33874640cde1SColin Riley result.AppendErrorWithFormat("Error: %s", error.AsCString()); 33884640cde1SColin Riley return false; 33894640cde1SColin Riley } 33904640cde1SColin Riley 3391018f5a7eSEwan Crawford private: 3392018f5a7eSEwan Crawford CommandOptions m_options; 33934640cde1SColin Riley }; 33944640cde1SColin Riley 3395018f5a7eSEwan Crawford OptionDefinition 3396018f5a7eSEwan Crawford CommandObjectRenderScriptRuntimeKernelBreakpointSet::CommandOptions::g_option_table[] = 3397018f5a7eSEwan Crawford { 3398018f5a7eSEwan Crawford { LLDB_OPT_SET_1, false, "coordinate", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeValue, 3399018f5a7eSEwan Crawford "Set a breakpoint on a single invocation of the kernel with specified coordinate.\n" 3400018f5a7eSEwan Crawford "Coordinate takes the form 'x[,y][,z] where x,y,z are positive integers representing kernel dimensions. " 3401018f5a7eSEwan Crawford "Any unset dimensions will be defaulted to zero."}, 3402018f5a7eSEwan Crawford { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 3403018f5a7eSEwan Crawford }; 3404018f5a7eSEwan Crawford 34057dc7771cSEwan Crawford class CommandObjectRenderScriptRuntimeKernelBreakpointAll : public CommandObjectParsed 34067dc7771cSEwan Crawford { 34077dc7771cSEwan Crawford public: 34087dc7771cSEwan Crawford CommandObjectRenderScriptRuntimeKernelBreakpointAll(CommandInterpreter &interpreter) 34097dc7771cSEwan Crawford : CommandObjectParsed(interpreter, "renderscript kernel breakpoint all", 34107dc7771cSEwan Crawford "Automatically sets a breakpoint on all renderscript kernels that are or will be loaded.\n" 34117dc7771cSEwan Crawford "Disabling option means breakpoints will no longer be set on any kernels loaded in the future, " 34127dc7771cSEwan Crawford "but does not remove currently set breakpoints.", 34137dc7771cSEwan Crawford "renderscript kernel breakpoint all <enable/disable>", 34147dc7771cSEwan Crawford eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) 34157dc7771cSEwan Crawford { 34167dc7771cSEwan Crawford } 34177dc7771cSEwan Crawford 3418222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeKernelBreakpointAll() override = default; 34197dc7771cSEwan Crawford 34207dc7771cSEwan Crawford bool 3421222b937cSEugene Zelenko DoExecute(Args &command, CommandReturnObject &result) override 34227dc7771cSEwan Crawford { 34237dc7771cSEwan Crawford const size_t argc = command.GetArgumentCount(); 34247dc7771cSEwan Crawford if (argc != 1) 34257dc7771cSEwan Crawford { 34267dc7771cSEwan Crawford result.AppendErrorWithFormat("'%s' takes 1 argument of 'enable' or 'disable'", m_cmd_name.c_str()); 34277dc7771cSEwan Crawford result.SetStatus(eReturnStatusFailed); 34287dc7771cSEwan Crawford return false; 34297dc7771cSEwan Crawford } 34307dc7771cSEwan Crawford 34317dc7771cSEwan Crawford RenderScriptRuntime *runtime = 34327dc7771cSEwan Crawford static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); 34337dc7771cSEwan Crawford 34347dc7771cSEwan Crawford bool do_break = false; 34357dc7771cSEwan Crawford const char* argument = command.GetArgumentAtIndex(0); 34367dc7771cSEwan Crawford if (strcmp(argument, "enable") == 0) 34377dc7771cSEwan Crawford { 34387dc7771cSEwan Crawford do_break = true; 34397dc7771cSEwan Crawford result.AppendMessage("Breakpoints will be set on all kernels."); 34407dc7771cSEwan Crawford } 34417dc7771cSEwan Crawford else if (strcmp(argument, "disable") == 0) 34427dc7771cSEwan Crawford { 34437dc7771cSEwan Crawford do_break = false; 34447dc7771cSEwan Crawford result.AppendMessage("Breakpoints will not be set on any new kernels."); 34457dc7771cSEwan Crawford } 34467dc7771cSEwan Crawford else 34477dc7771cSEwan Crawford { 34487dc7771cSEwan Crawford result.AppendErrorWithFormat("Argument must be either 'enable' or 'disable'"); 34497dc7771cSEwan Crawford result.SetStatus(eReturnStatusFailed); 34507dc7771cSEwan Crawford return false; 34517dc7771cSEwan Crawford } 34527dc7771cSEwan Crawford 34537dc7771cSEwan Crawford runtime->SetBreakAllKernels(do_break, m_exe_ctx.GetTargetSP()); 34547dc7771cSEwan Crawford 34557dc7771cSEwan Crawford result.SetStatus(eReturnStatusSuccessFinishResult); 34567dc7771cSEwan Crawford return true; 34577dc7771cSEwan Crawford } 34587dc7771cSEwan Crawford }; 34597dc7771cSEwan Crawford 34607dc7771cSEwan Crawford class CommandObjectRenderScriptRuntimeKernelBreakpoint : public CommandObjectMultiword 34617dc7771cSEwan Crawford { 34627dc7771cSEwan Crawford public: 34637dc7771cSEwan Crawford CommandObjectRenderScriptRuntimeKernelBreakpoint(CommandInterpreter &interpreter) 34647dc7771cSEwan Crawford : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that generate breakpoints on renderscript kernels.", 34657dc7771cSEwan Crawford nullptr) 34667dc7771cSEwan Crawford { 34677dc7771cSEwan Crawford LoadSubCommand("set", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointSet(interpreter))); 34687dc7771cSEwan Crawford LoadSubCommand("all", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointAll(interpreter))); 34697dc7771cSEwan Crawford } 34707dc7771cSEwan Crawford 3471222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeKernelBreakpoint() override = default; 34727dc7771cSEwan Crawford }; 34737dc7771cSEwan Crawford 34744640cde1SColin Riley class CommandObjectRenderScriptRuntimeKernel : public CommandObjectMultiword 34754640cde1SColin Riley { 34764640cde1SColin Riley public: 34774640cde1SColin Riley CommandObjectRenderScriptRuntimeKernel(CommandInterpreter &interpreter) 34784640cde1SColin Riley : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that deal with renderscript kernels.", 34794640cde1SColin Riley NULL) 34804640cde1SColin Riley { 34814640cde1SColin Riley LoadSubCommand("list", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelList(interpreter))); 34824640cde1SColin Riley LoadSubCommand("breakpoint", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpoint(interpreter))); 34834640cde1SColin Riley } 34844640cde1SColin Riley 3485222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeKernel() override = default; 34864640cde1SColin Riley }; 34874640cde1SColin Riley 34884640cde1SColin Riley class CommandObjectRenderScriptRuntimeContextDump : public CommandObjectParsed 34894640cde1SColin Riley { 34904640cde1SColin Riley public: 34914640cde1SColin Riley CommandObjectRenderScriptRuntimeContextDump(CommandInterpreter &interpreter) 34924640cde1SColin Riley : CommandObjectParsed(interpreter, "renderscript context dump", 34934640cde1SColin Riley "Dumps renderscript context information.", "renderscript context dump", 34944640cde1SColin Riley eCommandRequiresProcess | eCommandProcessMustBeLaunched) 34954640cde1SColin Riley { 34964640cde1SColin Riley } 34974640cde1SColin Riley 3498222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeContextDump() override = default; 34994640cde1SColin Riley 35004640cde1SColin Riley bool 3501222b937cSEugene Zelenko DoExecute(Args &command, CommandReturnObject &result) override 35024640cde1SColin Riley { 35034640cde1SColin Riley RenderScriptRuntime *runtime = 35044640cde1SColin Riley (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); 35054640cde1SColin Riley runtime->DumpContexts(result.GetOutputStream()); 35064640cde1SColin Riley result.SetStatus(eReturnStatusSuccessFinishResult); 35074640cde1SColin Riley return true; 35084640cde1SColin Riley } 35094640cde1SColin Riley }; 35104640cde1SColin Riley 35114640cde1SColin Riley class CommandObjectRenderScriptRuntimeContext : public CommandObjectMultiword 35124640cde1SColin Riley { 35134640cde1SColin Riley public: 35144640cde1SColin Riley CommandObjectRenderScriptRuntimeContext(CommandInterpreter &interpreter) 35154640cde1SColin Riley : CommandObjectMultiword(interpreter, "renderscript context", "Commands that deal with renderscript contexts.", 35164640cde1SColin Riley NULL) 35174640cde1SColin Riley { 35184640cde1SColin Riley LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeContextDump(interpreter))); 35194640cde1SColin Riley } 35204640cde1SColin Riley 3521222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeContext() override = default; 35224640cde1SColin Riley }; 35234640cde1SColin Riley 3524a0f08674SEwan Crawford class CommandObjectRenderScriptRuntimeAllocationDump : public CommandObjectParsed 3525a0f08674SEwan Crawford { 3526a0f08674SEwan Crawford public: 3527a0f08674SEwan Crawford CommandObjectRenderScriptRuntimeAllocationDump(CommandInterpreter &interpreter) 3528a0f08674SEwan Crawford : CommandObjectParsed(interpreter, "renderscript allocation dump", 3529a0f08674SEwan Crawford "Displays the contents of a particular allocation", "renderscript allocation dump <ID>", 3530a0f08674SEwan Crawford eCommandRequiresProcess | eCommandProcessMustBeLaunched), m_options(interpreter) 3531a0f08674SEwan Crawford { 3532a0f08674SEwan Crawford } 3533a0f08674SEwan Crawford 3534222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeAllocationDump() override = default; 3535222b937cSEugene Zelenko 3536222b937cSEugene Zelenko Options* 3537222b937cSEugene Zelenko GetOptions() override 3538a0f08674SEwan Crawford { 3539a0f08674SEwan Crawford return &m_options; 3540a0f08674SEwan Crawford } 3541a0f08674SEwan Crawford 3542a0f08674SEwan Crawford class CommandOptions : public Options 3543a0f08674SEwan Crawford { 3544a0f08674SEwan Crawford public: 3545a0f08674SEwan Crawford CommandOptions(CommandInterpreter &interpreter) : Options(interpreter) 3546a0f08674SEwan Crawford { 3547a0f08674SEwan Crawford } 3548a0f08674SEwan Crawford 3549222b937cSEugene Zelenko ~CommandOptions() override = default; 3550a0f08674SEwan Crawford 3551222b937cSEugene Zelenko Error 3552222b937cSEugene Zelenko SetOptionValue(uint32_t option_idx, const char *option_arg) override 3553a0f08674SEwan Crawford { 3554a0f08674SEwan Crawford Error error; 3555a0f08674SEwan Crawford const int short_option = m_getopt_table[option_idx].val; 3556a0f08674SEwan Crawford 3557a0f08674SEwan Crawford switch (short_option) 3558a0f08674SEwan Crawford { 3559a0f08674SEwan Crawford case 'f': 3560a0f08674SEwan Crawford m_outfile.SetFile(option_arg, true); 3561a0f08674SEwan Crawford if (m_outfile.Exists()) 3562a0f08674SEwan Crawford { 3563a0f08674SEwan Crawford m_outfile.Clear(); 3564a0f08674SEwan Crawford error.SetErrorStringWithFormat("file already exists: '%s'", option_arg); 3565a0f08674SEwan Crawford } 3566a0f08674SEwan Crawford break; 3567a0f08674SEwan Crawford default: 3568a0f08674SEwan Crawford error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); 3569a0f08674SEwan Crawford break; 3570a0f08674SEwan Crawford } 3571a0f08674SEwan Crawford return error; 3572a0f08674SEwan Crawford } 3573a0f08674SEwan Crawford 3574a0f08674SEwan Crawford void 3575222b937cSEugene Zelenko OptionParsingStarting() override 3576a0f08674SEwan Crawford { 3577a0f08674SEwan Crawford m_outfile.Clear(); 3578a0f08674SEwan Crawford } 3579a0f08674SEwan Crawford 3580a0f08674SEwan Crawford const OptionDefinition* 3581222b937cSEugene Zelenko GetDefinitions() override 3582a0f08674SEwan Crawford { 3583a0f08674SEwan Crawford return g_option_table; 3584a0f08674SEwan Crawford } 3585a0f08674SEwan Crawford 3586a0f08674SEwan Crawford static OptionDefinition g_option_table[]; 3587a0f08674SEwan Crawford FileSpec m_outfile; 3588a0f08674SEwan Crawford }; 3589a0f08674SEwan Crawford 3590a0f08674SEwan Crawford bool 3591222b937cSEugene Zelenko DoExecute(Args &command, CommandReturnObject &result) override 3592a0f08674SEwan Crawford { 3593a0f08674SEwan Crawford const size_t argc = command.GetArgumentCount(); 3594a0f08674SEwan Crawford if (argc < 1) 3595a0f08674SEwan Crawford { 3596a0f08674SEwan Crawford result.AppendErrorWithFormat("'%s' takes 1 argument, an allocation ID. As well as an optional -f argument", 3597a0f08674SEwan Crawford m_cmd_name.c_str()); 3598a0f08674SEwan Crawford result.SetStatus(eReturnStatusFailed); 3599a0f08674SEwan Crawford return false; 3600a0f08674SEwan Crawford } 3601a0f08674SEwan Crawford 3602a0f08674SEwan Crawford RenderScriptRuntime *runtime = 3603a0f08674SEwan Crawford static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); 3604a0f08674SEwan Crawford 3605a0f08674SEwan Crawford const char* id_cstr = command.GetArgumentAtIndex(0); 3606a0f08674SEwan Crawford bool convert_complete = false; 3607a0f08674SEwan Crawford const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete); 3608a0f08674SEwan Crawford if (!convert_complete) 3609a0f08674SEwan Crawford { 3610a0f08674SEwan Crawford result.AppendErrorWithFormat("invalid allocation id argument '%s'", id_cstr); 3611a0f08674SEwan Crawford result.SetStatus(eReturnStatusFailed); 3612a0f08674SEwan Crawford return false; 3613a0f08674SEwan Crawford } 3614a0f08674SEwan Crawford 3615a0f08674SEwan Crawford Stream* output_strm = nullptr; 3616a0f08674SEwan Crawford StreamFile outfile_stream; 3617a0f08674SEwan Crawford const FileSpec &outfile_spec = m_options.m_outfile; // Dump allocation to file instead 3618a0f08674SEwan Crawford if (outfile_spec) 3619a0f08674SEwan Crawford { 3620a0f08674SEwan Crawford // Open output file 3621a0f08674SEwan Crawford char path[256]; 3622a0f08674SEwan Crawford outfile_spec.GetPath(path, sizeof(path)); 3623a0f08674SEwan Crawford if (outfile_stream.GetFile().Open(path, File::eOpenOptionWrite | File::eOpenOptionCanCreate).Success()) 3624a0f08674SEwan Crawford { 3625a0f08674SEwan Crawford output_strm = &outfile_stream; 3626a0f08674SEwan Crawford result.GetOutputStream().Printf("Results written to '%s'", path); 3627a0f08674SEwan Crawford result.GetOutputStream().EOL(); 3628a0f08674SEwan Crawford } 3629a0f08674SEwan Crawford else 3630a0f08674SEwan Crawford { 3631a0f08674SEwan Crawford result.AppendErrorWithFormat("Couldn't open file '%s'", path); 3632a0f08674SEwan Crawford result.SetStatus(eReturnStatusFailed); 3633a0f08674SEwan Crawford return false; 3634a0f08674SEwan Crawford } 3635a0f08674SEwan Crawford } 3636a0f08674SEwan Crawford else 3637a0f08674SEwan Crawford output_strm = &result.GetOutputStream(); 3638a0f08674SEwan Crawford 3639a0f08674SEwan Crawford assert(output_strm != nullptr); 3640a0f08674SEwan Crawford bool success = runtime->DumpAllocation(*output_strm, m_exe_ctx.GetFramePtr(), id); 3641a0f08674SEwan Crawford 3642a0f08674SEwan Crawford if (success) 3643a0f08674SEwan Crawford result.SetStatus(eReturnStatusSuccessFinishResult); 3644a0f08674SEwan Crawford else 3645a0f08674SEwan Crawford result.SetStatus(eReturnStatusFailed); 3646a0f08674SEwan Crawford 3647a0f08674SEwan Crawford return true; 3648a0f08674SEwan Crawford } 3649a0f08674SEwan Crawford 3650a0f08674SEwan Crawford private: 3651a0f08674SEwan Crawford CommandOptions m_options; 3652a0f08674SEwan Crawford }; 3653a0f08674SEwan Crawford 3654a0f08674SEwan Crawford OptionDefinition 3655a0f08674SEwan Crawford CommandObjectRenderScriptRuntimeAllocationDump::CommandOptions::g_option_table[] = 3656a0f08674SEwan Crawford { 3657a0f08674SEwan Crawford { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFilename, 3658a0f08674SEwan Crawford "Print results to specified file instead of command line."}, 3659a0f08674SEwan Crawford { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 3660a0f08674SEwan Crawford }; 3661a0f08674SEwan Crawford 366215f2bd95SEwan Crawford class CommandObjectRenderScriptRuntimeAllocationList : public CommandObjectParsed 366315f2bd95SEwan Crawford { 366415f2bd95SEwan Crawford public: 366515f2bd95SEwan Crawford CommandObjectRenderScriptRuntimeAllocationList(CommandInterpreter &interpreter) 366615f2bd95SEwan Crawford : CommandObjectParsed(interpreter, "renderscript allocation list", 366715f2bd95SEwan Crawford "List renderscript allocations and their information.", "renderscript allocation list", 366815f2bd95SEwan Crawford eCommandRequiresProcess | eCommandProcessMustBeLaunched), m_options(interpreter) 366915f2bd95SEwan Crawford { 367015f2bd95SEwan Crawford } 367115f2bd95SEwan Crawford 3672222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeAllocationList() override = default; 3673222b937cSEugene Zelenko 3674222b937cSEugene Zelenko Options* 3675222b937cSEugene Zelenko GetOptions() override 367615f2bd95SEwan Crawford { 367715f2bd95SEwan Crawford return &m_options; 367815f2bd95SEwan Crawford } 367915f2bd95SEwan Crawford 368015f2bd95SEwan Crawford class CommandOptions : public Options 368115f2bd95SEwan Crawford { 368215f2bd95SEwan Crawford public: 368315f2bd95SEwan Crawford CommandOptions(CommandInterpreter &interpreter) : Options(interpreter), m_refresh(false) 368415f2bd95SEwan Crawford { 368515f2bd95SEwan Crawford } 368615f2bd95SEwan Crawford 3687222b937cSEugene Zelenko ~CommandOptions() override = default; 368815f2bd95SEwan Crawford 3689222b937cSEugene Zelenko Error 3690222b937cSEugene Zelenko SetOptionValue(uint32_t option_idx, const char *option_arg) override 369115f2bd95SEwan Crawford { 369215f2bd95SEwan Crawford Error error; 369315f2bd95SEwan Crawford const int short_option = m_getopt_table[option_idx].val; 369415f2bd95SEwan Crawford 369515f2bd95SEwan Crawford switch (short_option) 369615f2bd95SEwan Crawford { 369715f2bd95SEwan Crawford case 'r': 369815f2bd95SEwan Crawford m_refresh = true; 369915f2bd95SEwan Crawford break; 370015f2bd95SEwan Crawford default: 370115f2bd95SEwan Crawford error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); 370215f2bd95SEwan Crawford break; 370315f2bd95SEwan Crawford } 370415f2bd95SEwan Crawford return error; 370515f2bd95SEwan Crawford } 370615f2bd95SEwan Crawford 370715f2bd95SEwan Crawford void 3708222b937cSEugene Zelenko OptionParsingStarting() override 370915f2bd95SEwan Crawford { 371015f2bd95SEwan Crawford m_refresh = false; 371115f2bd95SEwan Crawford } 371215f2bd95SEwan Crawford 371315f2bd95SEwan Crawford const OptionDefinition* 3714222b937cSEugene Zelenko GetDefinitions() override 371515f2bd95SEwan Crawford { 371615f2bd95SEwan Crawford return g_option_table; 371715f2bd95SEwan Crawford } 371815f2bd95SEwan Crawford 371915f2bd95SEwan Crawford static OptionDefinition g_option_table[]; 372015f2bd95SEwan Crawford bool m_refresh; 372115f2bd95SEwan Crawford }; 372215f2bd95SEwan Crawford 372315f2bd95SEwan Crawford bool 3724222b937cSEugene Zelenko DoExecute(Args &command, CommandReturnObject &result) override 372515f2bd95SEwan Crawford { 372615f2bd95SEwan Crawford RenderScriptRuntime *runtime = 372715f2bd95SEwan Crawford static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); 372815f2bd95SEwan Crawford runtime->ListAllocations(result.GetOutputStream(), m_exe_ctx.GetFramePtr(), m_options.m_refresh); 372915f2bd95SEwan Crawford result.SetStatus(eReturnStatusSuccessFinishResult); 373015f2bd95SEwan Crawford return true; 373115f2bd95SEwan Crawford } 373215f2bd95SEwan Crawford 373315f2bd95SEwan Crawford private: 373415f2bd95SEwan Crawford CommandOptions m_options; 373515f2bd95SEwan Crawford }; 373615f2bd95SEwan Crawford 373715f2bd95SEwan Crawford OptionDefinition 373815f2bd95SEwan Crawford CommandObjectRenderScriptRuntimeAllocationList::CommandOptions::g_option_table[] = 373915f2bd95SEwan Crawford { 374015f2bd95SEwan Crawford { LLDB_OPT_SET_1, false, "refresh", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, 374115f2bd95SEwan Crawford "Recompute allocation details."}, 374215f2bd95SEwan Crawford { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 374315f2bd95SEwan Crawford }; 374415f2bd95SEwan Crawford 374555232f09SEwan Crawford class CommandObjectRenderScriptRuntimeAllocationLoad : public CommandObjectParsed 374655232f09SEwan Crawford { 374755232f09SEwan Crawford public: 374855232f09SEwan Crawford CommandObjectRenderScriptRuntimeAllocationLoad(CommandInterpreter &interpreter) 374955232f09SEwan Crawford : CommandObjectParsed(interpreter, "renderscript allocation load", 375055232f09SEwan Crawford "Loads renderscript allocation contents from a file.", "renderscript allocation load <ID> <filename>", 375155232f09SEwan Crawford eCommandRequiresProcess | eCommandProcessMustBeLaunched) 375255232f09SEwan Crawford { 375355232f09SEwan Crawford } 375455232f09SEwan Crawford 3755222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeAllocationLoad() override = default; 375655232f09SEwan Crawford 375755232f09SEwan Crawford bool 3758222b937cSEugene Zelenko DoExecute(Args &command, CommandReturnObject &result) override 375955232f09SEwan Crawford { 376055232f09SEwan Crawford const size_t argc = command.GetArgumentCount(); 376155232f09SEwan Crawford if (argc != 2) 376255232f09SEwan Crawford { 376355232f09SEwan Crawford result.AppendErrorWithFormat("'%s' takes 2 arguments, an allocation ID and filename to read from.", m_cmd_name.c_str()); 376455232f09SEwan Crawford result.SetStatus(eReturnStatusFailed); 376555232f09SEwan Crawford return false; 376655232f09SEwan Crawford } 376755232f09SEwan Crawford 376855232f09SEwan Crawford RenderScriptRuntime *runtime = 376955232f09SEwan Crawford static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); 377055232f09SEwan Crawford 377155232f09SEwan Crawford const char* id_cstr = command.GetArgumentAtIndex(0); 377255232f09SEwan Crawford bool convert_complete = false; 377355232f09SEwan Crawford const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete); 377455232f09SEwan Crawford if (!convert_complete) 377555232f09SEwan Crawford { 377655232f09SEwan Crawford result.AppendErrorWithFormat ("invalid allocation id argument '%s'", id_cstr); 377755232f09SEwan Crawford result.SetStatus (eReturnStatusFailed); 377855232f09SEwan Crawford return false; 377955232f09SEwan Crawford } 378055232f09SEwan Crawford 378155232f09SEwan Crawford const char* filename = command.GetArgumentAtIndex(1); 378255232f09SEwan Crawford bool success = runtime->LoadAllocation(result.GetOutputStream(), id, filename, m_exe_ctx.GetFramePtr()); 378355232f09SEwan Crawford 378455232f09SEwan Crawford if (success) 378555232f09SEwan Crawford result.SetStatus(eReturnStatusSuccessFinishResult); 378655232f09SEwan Crawford else 378755232f09SEwan Crawford result.SetStatus(eReturnStatusFailed); 378855232f09SEwan Crawford 378955232f09SEwan Crawford return true; 379055232f09SEwan Crawford } 379155232f09SEwan Crawford }; 379255232f09SEwan Crawford 379355232f09SEwan Crawford class CommandObjectRenderScriptRuntimeAllocationSave : public CommandObjectParsed 379455232f09SEwan Crawford { 379555232f09SEwan Crawford public: 379655232f09SEwan Crawford CommandObjectRenderScriptRuntimeAllocationSave(CommandInterpreter &interpreter) 379755232f09SEwan Crawford : CommandObjectParsed(interpreter, "renderscript allocation save", 379855232f09SEwan Crawford "Write renderscript allocation contents to a file.", "renderscript allocation save <ID> <filename>", 379955232f09SEwan Crawford eCommandRequiresProcess | eCommandProcessMustBeLaunched) 380055232f09SEwan Crawford { 380155232f09SEwan Crawford } 380255232f09SEwan Crawford 3803222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeAllocationSave() override = default; 380455232f09SEwan Crawford 380555232f09SEwan Crawford bool 3806222b937cSEugene Zelenko DoExecute(Args &command, CommandReturnObject &result) override 380755232f09SEwan Crawford { 380855232f09SEwan Crawford const size_t argc = command.GetArgumentCount(); 380955232f09SEwan Crawford if (argc != 2) 381055232f09SEwan Crawford { 381155232f09SEwan Crawford result.AppendErrorWithFormat("'%s' takes 2 arguments, an allocation ID and filename to read from.", m_cmd_name.c_str()); 381255232f09SEwan Crawford result.SetStatus(eReturnStatusFailed); 381355232f09SEwan Crawford return false; 381455232f09SEwan Crawford } 381555232f09SEwan Crawford 381655232f09SEwan Crawford RenderScriptRuntime *runtime = 381755232f09SEwan Crawford static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); 381855232f09SEwan Crawford 381955232f09SEwan Crawford const char* id_cstr = command.GetArgumentAtIndex(0); 382055232f09SEwan Crawford bool convert_complete = false; 382155232f09SEwan Crawford const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete); 382255232f09SEwan Crawford if (!convert_complete) 382355232f09SEwan Crawford { 382455232f09SEwan Crawford result.AppendErrorWithFormat ("invalid allocation id argument '%s'", id_cstr); 382555232f09SEwan Crawford result.SetStatus (eReturnStatusFailed); 382655232f09SEwan Crawford return false; 382755232f09SEwan Crawford } 382855232f09SEwan Crawford 382955232f09SEwan Crawford const char* filename = command.GetArgumentAtIndex(1); 383055232f09SEwan Crawford bool success = runtime->SaveAllocation(result.GetOutputStream(), id, filename, m_exe_ctx.GetFramePtr()); 383155232f09SEwan Crawford 383255232f09SEwan Crawford if (success) 383355232f09SEwan Crawford result.SetStatus(eReturnStatusSuccessFinishResult); 383455232f09SEwan Crawford else 383555232f09SEwan Crawford result.SetStatus(eReturnStatusFailed); 383655232f09SEwan Crawford 383755232f09SEwan Crawford return true; 383855232f09SEwan Crawford } 383955232f09SEwan Crawford }; 384055232f09SEwan Crawford 384115f2bd95SEwan Crawford class CommandObjectRenderScriptRuntimeAllocation : public CommandObjectMultiword 384215f2bd95SEwan Crawford { 384315f2bd95SEwan Crawford public: 384415f2bd95SEwan Crawford CommandObjectRenderScriptRuntimeAllocation(CommandInterpreter &interpreter) 384515f2bd95SEwan Crawford : CommandObjectMultiword(interpreter, "renderscript allocation", "Commands that deal with renderscript allocations.", 384615f2bd95SEwan Crawford NULL) 384715f2bd95SEwan Crawford { 384815f2bd95SEwan Crawford LoadSubCommand("list", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationList(interpreter))); 3849a0f08674SEwan Crawford LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationDump(interpreter))); 385055232f09SEwan Crawford LoadSubCommand("save", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationSave(interpreter))); 385155232f09SEwan Crawford LoadSubCommand("load", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationLoad(interpreter))); 385215f2bd95SEwan Crawford } 385315f2bd95SEwan Crawford 3854222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeAllocation() override = default; 385515f2bd95SEwan Crawford }; 385615f2bd95SEwan Crawford 38574640cde1SColin Riley class CommandObjectRenderScriptRuntimeStatus : public CommandObjectParsed 38584640cde1SColin Riley { 38594640cde1SColin Riley public: 38604640cde1SColin Riley CommandObjectRenderScriptRuntimeStatus(CommandInterpreter &interpreter) 38614640cde1SColin Riley : CommandObjectParsed(interpreter, "renderscript status", 38624640cde1SColin Riley "Displays current renderscript runtime status.", "renderscript status", 38634640cde1SColin Riley eCommandRequiresProcess | eCommandProcessMustBeLaunched) 38644640cde1SColin Riley { 38654640cde1SColin Riley } 38664640cde1SColin Riley 3867222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeStatus() override = default; 38684640cde1SColin Riley 38694640cde1SColin Riley bool 3870222b937cSEugene Zelenko DoExecute(Args &command, CommandReturnObject &result) override 38714640cde1SColin Riley { 38724640cde1SColin Riley RenderScriptRuntime *runtime = 38734640cde1SColin Riley (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); 38744640cde1SColin Riley runtime->Status(result.GetOutputStream()); 38754640cde1SColin Riley result.SetStatus(eReturnStatusSuccessFinishResult); 38764640cde1SColin Riley return true; 38774640cde1SColin Riley } 38784640cde1SColin Riley }; 38794640cde1SColin Riley 38805ec532a9SColin Riley class CommandObjectRenderScriptRuntime : public CommandObjectMultiword 38815ec532a9SColin Riley { 38825ec532a9SColin Riley public: 38835ec532a9SColin Riley CommandObjectRenderScriptRuntime(CommandInterpreter &interpreter) 38845ec532a9SColin Riley : CommandObjectMultiword(interpreter, "renderscript", "A set of commands for operating on renderscript.", 38855ec532a9SColin Riley "renderscript <subcommand> [<subcommand-options>]") 38865ec532a9SColin Riley { 38875ec532a9SColin Riley LoadSubCommand("module", CommandObjectSP(new CommandObjectRenderScriptRuntimeModule(interpreter))); 38884640cde1SColin Riley LoadSubCommand("status", CommandObjectSP(new CommandObjectRenderScriptRuntimeStatus(interpreter))); 38894640cde1SColin Riley LoadSubCommand("kernel", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernel(interpreter))); 38904640cde1SColin Riley LoadSubCommand("context", CommandObjectSP(new CommandObjectRenderScriptRuntimeContext(interpreter))); 389115f2bd95SEwan Crawford LoadSubCommand("allocation", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocation(interpreter))); 38925ec532a9SColin Riley } 38935ec532a9SColin Riley 3894222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntime() override = default; 38955ec532a9SColin Riley }; 3896ef20b08fSColin Riley 3897ef20b08fSColin Riley void 3898ef20b08fSColin Riley RenderScriptRuntime::Initiate() 38995ec532a9SColin Riley { 3900ef20b08fSColin Riley assert(!m_initiated); 39015ec532a9SColin Riley } 3902ef20b08fSColin Riley 3903ef20b08fSColin Riley RenderScriptRuntime::RenderScriptRuntime(Process *process) 39047dc7771cSEwan Crawford : lldb_private::CPPLanguageRuntime(process), m_initiated(false), m_debuggerPresentFlagged(false), 39057dc7771cSEwan Crawford m_breakAllKernels(false) 3906ef20b08fSColin Riley { 39074640cde1SColin Riley ModulesDidLoad(process->GetTarget().GetImages()); 3908ef20b08fSColin Riley } 39094640cde1SColin Riley 39104640cde1SColin Riley lldb::CommandObjectSP 39114640cde1SColin Riley RenderScriptRuntime::GetCommandObject(lldb_private::CommandInterpreter& interpreter) 39124640cde1SColin Riley { 39134640cde1SColin Riley static CommandObjectSP command_object; 39144640cde1SColin Riley if(!command_object) 39154640cde1SColin Riley { 39164640cde1SColin Riley command_object.reset(new CommandObjectRenderScriptRuntime(interpreter)); 39174640cde1SColin Riley } 39184640cde1SColin Riley return command_object; 39194640cde1SColin Riley } 39204640cde1SColin Riley 392178f339d1SEwan Crawford RenderScriptRuntime::~RenderScriptRuntime() = default; 3922