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 71082780287SAidan Dodds break; 71182780287SAidan Dodds } 712cdfb1485SEwan Crawford case llvm::Triple::ArchType::x86_64: 713cdfb1485SEwan Crawford { 714cdfb1485SEwan Crawford // amd64 has 6 integer registers, and 8 XMM registers for parameter passing. 715cdfb1485SEwan Crawford // Surplus args are spilled onto the stack. 716cdfb1485SEwan Crawford // rdi, rsi, rdx, rcx, r8, r9, (zmm0 - 7 for vectors) 717cdfb1485SEwan Crawford // ref: AMD64 ABI Draft 0.99.6 – October 7, 2013 – 10:35; Figure 3.4. Retrieved from 718cdfb1485SEwan Crawford // http://www.x86-64.org/documentation/abi.pdf 719cdfb1485SEwan Crawford if (arg > 5) 720cdfb1485SEwan Crawford { 721cdfb1485SEwan Crawford if (log) 722cdfb1485SEwan Crawford log->Warning("X86_64 register spill is not supported."); 723cdfb1485SEwan Crawford break; 724cdfb1485SEwan Crawford } 725cdfb1485SEwan Crawford const char * regnames[] = {"rdi", "rsi", "rdx", "rcx", "r8", "r9"}; 726cdfb1485SEwan Crawford assert((sizeof(regnames) / sizeof(const char *)) > arg); 727cdfb1485SEwan Crawford const RegisterInfo *rArg = reg_ctx->GetRegisterInfoByName(regnames[arg]); 728cdfb1485SEwan Crawford RegisterValue rVal; 729cdfb1485SEwan Crawford success = reg_ctx->ReadRegister(rArg, rVal); 730cdfb1485SEwan Crawford if (success) 731cdfb1485SEwan Crawford { 732cdfb1485SEwan Crawford *data = rVal.GetAsUInt64(0u, &success); 733cdfb1485SEwan Crawford } 734cdfb1485SEwan Crawford else 735cdfb1485SEwan Crawford { 736cdfb1485SEwan Crawford if (log) 737cdfb1485SEwan Crawford log->Printf("RenderScriptRuntime::GetArgSimple - error reading x86_64 register: %d.", arg); 738cdfb1485SEwan Crawford } 739cdfb1485SEwan Crawford break; 740cdfb1485SEwan Crawford } 74182780287SAidan Dodds case llvm::Triple::ArchType::arm: 74282780287SAidan Dodds { 74382780287SAidan Dodds // arm 32 bit 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); 7634640cde1SColin Riley process->ReadMemory(sp + offset, &data, sizeof(uint32_t), error); 7644640cde1SColin Riley if (error.Fail()) 7654640cde1SColin Riley { 7664640cde1SColin Riley if (log) 76782780287SAidan Dodds log->Printf("RenderScriptRuntime::GetArgSimple - error reading ARM stack: %s.", error.AsCString()); 76882780287SAidan Dodds } 76982780287SAidan Dodds else 77082780287SAidan Dodds { 77182780287SAidan Dodds success = true; 7724640cde1SColin Riley } 7734640cde1SColin Riley } 77482780287SAidan Dodds 77582780287SAidan Dodds break; 7764640cde1SColin Riley } 77782780287SAidan Dodds case llvm::Triple::ArchType::aarch64: 77882780287SAidan Dodds { 77982780287SAidan Dodds // arm 64 bit 78082780287SAidan Dodds // first 8 arguments are in the registers 78182780287SAidan Dodds if (arg < 8) 78282780287SAidan Dodds { 78382780287SAidan Dodds const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg); 78482780287SAidan Dodds RegisterValue rVal; 78582780287SAidan Dodds success = reg_ctx->ReadRegister(rArg, rVal); 78682780287SAidan Dodds if (success) 78782780287SAidan Dodds { 788cdfb1485SEwan Crawford *data = rVal.GetAsUInt64(0u, &success); 78982780287SAidan Dodds } 79082780287SAidan Dodds else 79182780287SAidan Dodds { 79282780287SAidan Dodds if (log) 79382780287SAidan Dodds log->Printf("RenderScriptRuntime::GetArgSimple() - AARCH64 - Error while reading the argument #%d", arg); 79482780287SAidan Dodds } 79582780287SAidan Dodds } 79682780287SAidan Dodds else 79782780287SAidan Dodds { 79882780287SAidan Dodds // @TODO: need to find the argument in the stack 79982780287SAidan Dodds if (log) 80082780287SAidan Dodds log->Printf("RenderScriptRuntime::GetArgSimple - AARCH64 - FOR #ARG >= 8 NOT IMPLEMENTED YET. Argument number: %d", arg); 80182780287SAidan Dodds } 80282780287SAidan Dodds break; 80382780287SAidan Dodds } 80474b396d9SAidan Dodds case llvm::Triple::ArchType::mipsel: 80574b396d9SAidan Dodds { 80674b396d9SAidan Dodds 80774b396d9SAidan Dodds // read from the registers 80874b396d9SAidan Dodds if (arg < 4){ 80974b396d9SAidan Dodds const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg + 4); 81074b396d9SAidan Dodds RegisterValue rVal; 81174b396d9SAidan Dodds success = reg_ctx->ReadRegister(rArg, rVal); 81274b396d9SAidan Dodds if (success) 81374b396d9SAidan Dodds { 814cdfb1485SEwan Crawford *data = rVal.GetAsUInt64(0u, &success); 81574b396d9SAidan Dodds } 81674b396d9SAidan Dodds else 81774b396d9SAidan Dodds { 81874b396d9SAidan Dodds if (log) 81974b396d9SAidan Dodds log->Printf("RenderScriptRuntime::GetArgSimple() - Mips - Error while reading the argument #%d", arg); 82074b396d9SAidan Dodds } 82174b396d9SAidan Dodds 82274b396d9SAidan Dodds } 82374b396d9SAidan Dodds 82474b396d9SAidan Dodds // read from the stack 82574b396d9SAidan Dodds else 82674b396d9SAidan Dodds { 82774b396d9SAidan Dodds uint64_t sp = reg_ctx->GetSP(); 82874b396d9SAidan Dodds uint32_t offset = arg * sizeof(uint32_t); 82974b396d9SAidan Dodds process->ReadMemory(sp + offset, &data, sizeof(uint32_t), error); 83074b396d9SAidan Dodds if (error.Fail()) 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 { 83774b396d9SAidan Dodds success = true; 83874b396d9SAidan Dodds } 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 } 86102f1c5d1SEwan Crawford 86202f1c5d1SEwan Crawford // read from the stack 86302f1c5d1SEwan Crawford else 86402f1c5d1SEwan Crawford { 86502f1c5d1SEwan Crawford uint64_t sp = reg_ctx->GetSP(); 86602f1c5d1SEwan Crawford uint32_t offset = (arg - 8) * sizeof(uint64_t); 86702f1c5d1SEwan Crawford process->ReadMemory(sp + offset, &data, sizeof(uint64_t), error); 86802f1c5d1SEwan Crawford if (error.Fail()) 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 { 87502f1c5d1SEwan Crawford success = true; 87602f1c5d1SEwan Crawford } 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 } 88982780287SAidan Dodds 890cdfb1485SEwan Crawford if (!success) 891cdfb1485SEwan Crawford { 892cdfb1485SEwan Crawford if (log) 893cdfb1485SEwan Crawford log->Printf("RenderScriptRuntime::GetArgSimple - failed to get argument at index %" PRIu32, arg); 894cdfb1485SEwan Crawford } 89582780287SAidan Dodds return success; 8964640cde1SColin Riley } 8974640cde1SColin Riley 8984640cde1SColin Riley void 8994640cde1SColin Riley RenderScriptRuntime::CaptureSetGlobalVar1(RuntimeHook* hook_info, ExecutionContext& context) 9004640cde1SColin Riley { 9014640cde1SColin Riley Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 9024640cde1SColin Riley 9034640cde1SColin Riley //Context, Script, int, data, length 9044640cde1SColin Riley 90582780287SAidan Dodds uint64_t rs_context_u64 = 0U; 90682780287SAidan Dodds uint64_t rs_script_u64 = 0U; 90782780287SAidan Dodds uint64_t rs_id_u64 = 0U; 90882780287SAidan Dodds uint64_t rs_data_u64 = 0U; 90982780287SAidan Dodds uint64_t rs_length_u64 = 0U; 9104640cde1SColin Riley 91182780287SAidan Dodds bool success = 91282780287SAidan Dodds GetArgSimple(context, 0, &rs_context_u64) && 91382780287SAidan Dodds GetArgSimple(context, 1, &rs_script_u64) && 91482780287SAidan Dodds GetArgSimple(context, 2, &rs_id_u64) && 91582780287SAidan Dodds GetArgSimple(context, 3, &rs_data_u64) && 91682780287SAidan Dodds GetArgSimple(context, 4, &rs_length_u64); 9174640cde1SColin Riley 91882780287SAidan Dodds if (!success) 91982780287SAidan Dodds { 92082780287SAidan Dodds if (log) 92182780287SAidan Dodds log->Printf("RenderScriptRuntime::CaptureSetGlobalVar1 - Error while reading the function parameters"); 92282780287SAidan Dodds return; 92382780287SAidan Dodds } 9244640cde1SColin Riley 9254640cde1SColin Riley if (log) 9264640cde1SColin Riley { 9274640cde1SColin Riley log->Printf ("RenderScriptRuntime::CaptureSetGlobalVar1 - 0x%" PRIx64 ",0x%" PRIx64 " slot %" PRIu64 " = 0x%" PRIx64 ":%" PRIu64 "bytes.", 92882780287SAidan Dodds rs_context_u64, rs_script_u64, rs_id_u64, rs_data_u64, rs_length_u64); 9294640cde1SColin Riley 93082780287SAidan Dodds addr_t script_addr = (addr_t)rs_script_u64; 9314640cde1SColin Riley if (m_scriptMappings.find( script_addr ) != m_scriptMappings.end()) 9324640cde1SColin Riley { 9334640cde1SColin Riley auto rsm = m_scriptMappings[script_addr]; 93482780287SAidan Dodds if (rs_id_u64 < rsm->m_globals.size()) 9354640cde1SColin Riley { 93682780287SAidan Dodds auto rsg = rsm->m_globals[rs_id_u64]; 9374640cde1SColin Riley log->Printf ("RenderScriptRuntime::CaptureSetGlobalVar1 - Setting of '%s' within '%s' inferred", rsg.m_name.AsCString(), 9384640cde1SColin Riley rsm->m_module->GetFileSpec().GetFilename().AsCString()); 9394640cde1SColin Riley } 9404640cde1SColin Riley } 9414640cde1SColin Riley } 9424640cde1SColin Riley } 9434640cde1SColin Riley 9444640cde1SColin Riley void 9454640cde1SColin Riley RenderScriptRuntime::CaptureAllocationInit1(RuntimeHook* hook_info, ExecutionContext& context) 9464640cde1SColin Riley { 9474640cde1SColin Riley Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 9484640cde1SColin Riley 9494640cde1SColin Riley //Context, Alloc, bool 9504640cde1SColin Riley 95182780287SAidan Dodds uint64_t rs_context_u64 = 0U; 95282780287SAidan Dodds uint64_t rs_alloc_u64 = 0U; 95382780287SAidan Dodds uint64_t rs_forceZero_u64 = 0U; 9544640cde1SColin Riley 95582780287SAidan Dodds bool success = 95682780287SAidan Dodds GetArgSimple(context, 0, &rs_context_u64) && 95782780287SAidan Dodds GetArgSimple(context, 1, &rs_alloc_u64) && 95882780287SAidan Dodds GetArgSimple(context, 2, &rs_forceZero_u64); 95982780287SAidan Dodds if (!success) // error case 96082780287SAidan Dodds { 96182780287SAidan Dodds if (log) 96282780287SAidan Dodds log->Printf("RenderScriptRuntime::CaptureAllocationInit1 - Error while reading the function parameters"); 96382780287SAidan Dodds return; // abort 96482780287SAidan Dodds } 9654640cde1SColin Riley 9664640cde1SColin Riley if (log) 9674640cde1SColin Riley log->Printf ("RenderScriptRuntime::CaptureAllocationInit1 - 0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 " .", 96882780287SAidan Dodds rs_context_u64, rs_alloc_u64, rs_forceZero_u64); 96978f339d1SEwan Crawford 97078f339d1SEwan Crawford AllocationDetails* alloc = LookUpAllocation(rs_alloc_u64, true); 97178f339d1SEwan Crawford if (alloc) 97278f339d1SEwan Crawford alloc->context = rs_context_u64; 9734640cde1SColin Riley } 9744640cde1SColin Riley 9754640cde1SColin Riley void 976e69df382SEwan Crawford RenderScriptRuntime::CaptureAllocationDestroy(RuntimeHook* hook_info, ExecutionContext& context) 977e69df382SEwan Crawford { 978e69df382SEwan Crawford Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 979e69df382SEwan Crawford 980e69df382SEwan Crawford // Context, Alloc 981e69df382SEwan Crawford uint64_t rs_context_u64 = 0U; 982e69df382SEwan Crawford uint64_t rs_alloc_u64 = 0U; 983e69df382SEwan Crawford 984e69df382SEwan Crawford bool success = GetArgSimple(context, 0, &rs_context_u64) && GetArgSimple(context, 1, &rs_alloc_u64); 985e69df382SEwan Crawford if (!success) // error case 986e69df382SEwan Crawford { 987e69df382SEwan Crawford if (log) 988e69df382SEwan Crawford log->Printf("RenderScriptRuntime::CaptureAllocationDestroy - Error while reading the function parameters"); 989e69df382SEwan Crawford return; // abort 990e69df382SEwan Crawford } 991e69df382SEwan Crawford 992e69df382SEwan Crawford if (log) 993e69df382SEwan Crawford log->Printf("RenderScriptRuntime::CaptureAllocationDestroy - 0x%" PRIx64 ", 0x%" PRIx64 ".", 994e69df382SEwan Crawford rs_context_u64, rs_alloc_u64); 995e69df382SEwan Crawford 996e69df382SEwan Crawford for (auto iter = m_allocations.begin(); iter != m_allocations.end(); ++iter) 997e69df382SEwan Crawford { 998e69df382SEwan Crawford auto& allocation_ap = *iter; // get the unique pointer 999e69df382SEwan Crawford if (allocation_ap->address.isValid() && *allocation_ap->address.get() == rs_alloc_u64) 1000e69df382SEwan Crawford { 1001e69df382SEwan Crawford m_allocations.erase(iter); 1002e69df382SEwan Crawford if (log) 1003e69df382SEwan Crawford log->Printf("RenderScriptRuntime::CaptureAllocationDestroy - Deleted allocation entry"); 1004e69df382SEwan Crawford return; 1005e69df382SEwan Crawford } 1006e69df382SEwan Crawford } 1007e69df382SEwan Crawford 1008e69df382SEwan Crawford if (log) 1009e69df382SEwan Crawford log->Printf("RenderScriptRuntime::CaptureAllocationDestroy - Couldn't find destroyed allocation"); 1010e69df382SEwan Crawford } 1011e69df382SEwan Crawford 1012e69df382SEwan Crawford void 10134640cde1SColin Riley RenderScriptRuntime::CaptureScriptInit1(RuntimeHook* hook_info, ExecutionContext& context) 10144640cde1SColin Riley { 10154640cde1SColin Riley Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 10164640cde1SColin Riley 10174640cde1SColin Riley //Context, Script, resname Str, cachedir Str 10184640cde1SColin Riley Error error; 10194640cde1SColin Riley Process* process = context.GetProcessPtr(); 10204640cde1SColin Riley 102182780287SAidan Dodds uint64_t rs_context_u64 = 0U; 102282780287SAidan Dodds uint64_t rs_script_u64 = 0U; 102382780287SAidan Dodds uint64_t rs_resnameptr_u64 = 0U; 102482780287SAidan Dodds uint64_t rs_cachedirptr_u64 = 0U; 10254640cde1SColin Riley 10264640cde1SColin Riley std::string resname; 10274640cde1SColin Riley std::string cachedir; 10284640cde1SColin Riley 102982780287SAidan Dodds // read the function parameters 103082780287SAidan Dodds bool success = 103182780287SAidan Dodds GetArgSimple(context, 0, &rs_context_u64) && 103282780287SAidan Dodds GetArgSimple(context, 1, &rs_script_u64) && 103382780287SAidan Dodds GetArgSimple(context, 2, &rs_resnameptr_u64) && 103482780287SAidan Dodds GetArgSimple(context, 3, &rs_cachedirptr_u64); 10354640cde1SColin Riley 103682780287SAidan Dodds if (!success) 103782780287SAidan Dodds { 103882780287SAidan Dodds if (log) 103982780287SAidan Dodds log->Printf("RenderScriptRuntime::CaptureScriptInit1 - Error while reading the function parameters"); 104082780287SAidan Dodds return; 104182780287SAidan Dodds } 104282780287SAidan Dodds 104382780287SAidan Dodds process->ReadCStringFromMemory((lldb::addr_t)rs_resnameptr_u64, resname, error); 10444640cde1SColin Riley if (error.Fail()) 10454640cde1SColin Riley { 10464640cde1SColin Riley if (log) 10474640cde1SColin Riley log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - error reading resname: %s.", error.AsCString()); 10484640cde1SColin Riley 10494640cde1SColin Riley } 10504640cde1SColin Riley 105182780287SAidan Dodds process->ReadCStringFromMemory((lldb::addr_t)rs_cachedirptr_u64, cachedir, error); 10524640cde1SColin Riley if (error.Fail()) 10534640cde1SColin Riley { 10544640cde1SColin Riley if (log) 10554640cde1SColin Riley log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - error reading cachedir: %s.", error.AsCString()); 10564640cde1SColin Riley } 10574640cde1SColin Riley 10584640cde1SColin Riley if (log) 10594640cde1SColin Riley log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - 0x%" PRIx64 ",0x%" PRIx64 " => '%s' at '%s' .", 106082780287SAidan Dodds rs_context_u64, rs_script_u64, resname.c_str(), cachedir.c_str()); 10614640cde1SColin Riley 10624640cde1SColin Riley if (resname.size() > 0) 10634640cde1SColin Riley { 10644640cde1SColin Riley StreamString strm; 10654640cde1SColin Riley strm.Printf("librs.%s.so", resname.c_str()); 10664640cde1SColin Riley 106778f339d1SEwan Crawford ScriptDetails* script = LookUpScript(rs_script_u64, true); 106878f339d1SEwan Crawford if (script) 106978f339d1SEwan Crawford { 107078f339d1SEwan Crawford script->type = ScriptDetails::eScriptC; 107178f339d1SEwan Crawford script->cacheDir = cachedir; 107278f339d1SEwan Crawford script->resName = resname; 107378f339d1SEwan Crawford script->scriptDyLib = strm.GetData(); 107478f339d1SEwan Crawford script->context = addr_t(rs_context_u64); 107578f339d1SEwan Crawford } 10764640cde1SColin Riley 10774640cde1SColin Riley if (log) 10784640cde1SColin Riley log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - '%s' tagged with context 0x%" PRIx64 " and script 0x%" PRIx64 ".", 107982780287SAidan Dodds strm.GetData(), rs_context_u64, rs_script_u64); 10804640cde1SColin Riley } 10814640cde1SColin Riley else if (log) 10824640cde1SColin Riley { 10834640cde1SColin Riley log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - resource name invalid, Script not tagged"); 10844640cde1SColin Riley } 10854640cde1SColin Riley } 10864640cde1SColin Riley 10874640cde1SColin Riley void 10884640cde1SColin Riley RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind) 10894640cde1SColin Riley { 10904640cde1SColin Riley Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 10914640cde1SColin Riley 10924640cde1SColin Riley if (!module) 10934640cde1SColin Riley { 10944640cde1SColin Riley return; 10954640cde1SColin Riley } 10964640cde1SColin Riley 109782780287SAidan Dodds Target &target = GetProcess()->GetTarget(); 109882780287SAidan Dodds llvm::Triple::ArchType targetArchType = target.GetArchitecture().GetMachine(); 109982780287SAidan Dodds 110082780287SAidan Dodds if (targetArchType != llvm::Triple::ArchType::x86 110182780287SAidan Dodds && targetArchType != llvm::Triple::ArchType::arm 110202f1c5d1SEwan Crawford && targetArchType != llvm::Triple::ArchType::aarch64 110374b396d9SAidan Dodds && targetArchType != llvm::Triple::ArchType::mipsel 110402f1c5d1SEwan Crawford && targetArchType != llvm::Triple::ArchType::mips64el 1105cdfb1485SEwan Crawford && targetArchType != llvm::Triple::ArchType::x86_64 110602f1c5d1SEwan Crawford ) 11074640cde1SColin Riley { 11084640cde1SColin Riley if (log) 110974b396d9SAidan Dodds log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Unable to hook runtime. Only X86, ARM, Mips supported currently."); 11104640cde1SColin Riley 11114640cde1SColin Riley return; 11124640cde1SColin Riley } 11134640cde1SColin Riley 111482780287SAidan Dodds uint32_t archByteSize = target.GetArchitecture().GetAddressByteSize(); 11154640cde1SColin Riley 11164640cde1SColin Riley for (size_t idx = 0; idx < s_runtimeHookCount; idx++) 11174640cde1SColin Riley { 11184640cde1SColin Riley const HookDefn* hook_defn = &s_runtimeHookDefns[idx]; 11194640cde1SColin Riley if (hook_defn->kind != kind) { 11204640cde1SColin Riley continue; 11214640cde1SColin Riley } 11224640cde1SColin Riley 112382780287SAidan Dodds const char* symbol_name = (archByteSize == 4) ? hook_defn->symbol_name_m32 : hook_defn->symbol_name_m64; 112482780287SAidan Dodds 112582780287SAidan Dodds const Symbol *sym = module->FindFirstSymbolWithNameAndType(ConstString(symbol_name), eSymbolTypeCode); 112682780287SAidan Dodds if (!sym){ 112782780287SAidan Dodds if (log){ 112882780287SAidan Dodds log->Printf("RenderScriptRuntime::LoadRuntimeHooks - ERROR: Symbol '%s' related to the function %s not found", symbol_name, hook_defn->name); 112982780287SAidan Dodds } 113082780287SAidan Dodds continue; 113182780287SAidan Dodds } 11324640cde1SColin Riley 1133358cf1eaSGreg Clayton addr_t addr = sym->GetLoadAddress(&target); 11344640cde1SColin Riley if (addr == LLDB_INVALID_ADDRESS) 11354640cde1SColin Riley { 11364640cde1SColin Riley if (log) 11374640cde1SColin Riley log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Unable to resolve the address of hook function '%s' with symbol '%s'.", 113882780287SAidan Dodds hook_defn->name, symbol_name); 11394640cde1SColin Riley continue; 11404640cde1SColin Riley } 114182780287SAidan Dodds else 114282780287SAidan Dodds { 114382780287SAidan Dodds if (log) 114482780287SAidan Dodds log->Printf("RenderScriptRuntime::LoadRuntimeHooks - Function %s, address resolved at 0x%" PRIx64, hook_defn->name, addr); 114582780287SAidan Dodds } 11464640cde1SColin Riley 11474640cde1SColin Riley RuntimeHookSP hook(new RuntimeHook()); 11484640cde1SColin Riley hook->address = addr; 11494640cde1SColin Riley hook->defn = hook_defn; 11504640cde1SColin Riley hook->bp_sp = target.CreateBreakpoint(addr, true, false); 11514640cde1SColin Riley hook->bp_sp->SetCallback(HookCallback, hook.get(), true); 11524640cde1SColin Riley m_runtimeHooks[addr] = hook; 11534640cde1SColin Riley if (log) 11544640cde1SColin Riley { 11554640cde1SColin Riley log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Successfully hooked '%s' in '%s' version %" PRIu64 " at 0x%" PRIx64 ".", 11564640cde1SColin Riley hook_defn->name, module->GetFileSpec().GetFilename().AsCString(), (uint64_t)hook_defn->version, (uint64_t)addr); 11574640cde1SColin Riley } 11584640cde1SColin Riley } 11594640cde1SColin Riley } 11604640cde1SColin Riley 11614640cde1SColin Riley void 11624640cde1SColin Riley RenderScriptRuntime::FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp) 11634640cde1SColin Riley { 11644640cde1SColin Riley if (!rsmodule_sp) 11654640cde1SColin Riley return; 11664640cde1SColin Riley 11674640cde1SColin Riley Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 11684640cde1SColin Riley 11694640cde1SColin Riley const ModuleSP module = rsmodule_sp->m_module; 11704640cde1SColin Riley const FileSpec& file = module->GetPlatformFileSpec(); 11714640cde1SColin Riley 117278f339d1SEwan Crawford // Iterate over all of the scripts that we currently know of. 117378f339d1SEwan Crawford // Note: We cant push or pop to m_scripts here or it may invalidate rs_script. 11744640cde1SColin Riley for (const auto & rs_script : m_scripts) 11754640cde1SColin Riley { 117678f339d1SEwan Crawford // Extract the expected .so file path for this script. 117778f339d1SEwan Crawford std::string dylib; 117878f339d1SEwan Crawford if (!rs_script->scriptDyLib.get(dylib)) 117978f339d1SEwan Crawford continue; 118078f339d1SEwan Crawford 118178f339d1SEwan Crawford // Only proceed if the module that has loaded corresponds to this script. 118278f339d1SEwan Crawford if (file.GetFilename() != ConstString(dylib.c_str())) 118378f339d1SEwan Crawford continue; 118478f339d1SEwan Crawford 118578f339d1SEwan Crawford // Obtain the script address which we use as a key. 118678f339d1SEwan Crawford lldb::addr_t script; 118778f339d1SEwan Crawford if (!rs_script->script.get(script)) 118878f339d1SEwan Crawford continue; 118978f339d1SEwan Crawford 119078f339d1SEwan Crawford // If we have a script mapping for the current script. 119178f339d1SEwan Crawford if (m_scriptMappings.find(script) != m_scriptMappings.end()) 11924640cde1SColin Riley { 119378f339d1SEwan Crawford // if the module we have stored is different to the one we just received. 119478f339d1SEwan Crawford if (m_scriptMappings[script] != rsmodule_sp) 11954640cde1SColin Riley { 11964640cde1SColin Riley if (log) 11974640cde1SColin Riley log->Printf ("RenderScriptRuntime::FixupScriptDetails - Error: script %" PRIx64 " wants reassigned to new rsmodule '%s'.", 119878f339d1SEwan Crawford (uint64_t)script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString()); 11994640cde1SColin Riley } 12004640cde1SColin Riley } 120178f339d1SEwan Crawford // We don't have a script mapping for the current script. 12024640cde1SColin Riley else 12034640cde1SColin Riley { 120478f339d1SEwan Crawford // Obtain the script resource name. 120578f339d1SEwan Crawford std::string resName; 120678f339d1SEwan Crawford if (rs_script->resName.get(resName)) 120778f339d1SEwan Crawford // Set the modules resource name. 120878f339d1SEwan Crawford rsmodule_sp->m_resname = resName; 120978f339d1SEwan Crawford // Add Script/Module pair to map. 121078f339d1SEwan Crawford m_scriptMappings[script] = rsmodule_sp; 12114640cde1SColin Riley if (log) 12124640cde1SColin Riley log->Printf ("RenderScriptRuntime::FixupScriptDetails - script %" PRIx64 " associated with rsmodule '%s'.", 121378f339d1SEwan Crawford (uint64_t)script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString()); 12144640cde1SColin Riley } 12154640cde1SColin Riley } 12164640cde1SColin Riley } 12174640cde1SColin Riley 121815f2bd95SEwan Crawford // Uses the Target API to evaluate the expression passed as a parameter to the function 121915f2bd95SEwan Crawford // The result of that expression is returned an unsigned 64 bit int, via the result* paramter. 122015f2bd95SEwan Crawford // Function returns true on success, and false on failure 122115f2bd95SEwan Crawford bool 122215f2bd95SEwan Crawford RenderScriptRuntime::EvalRSExpression(const char* expression, StackFrame* frame_ptr, uint64_t* result) 122315f2bd95SEwan Crawford { 122415f2bd95SEwan Crawford Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 122515f2bd95SEwan Crawford if (log) 122615f2bd95SEwan Crawford log->Printf("RenderScriptRuntime::EvalRSExpression(%s)", expression); 122715f2bd95SEwan Crawford 122815f2bd95SEwan Crawford ValueObjectSP expr_result; 122915f2bd95SEwan Crawford // Perform the actual expression evaluation 123015f2bd95SEwan Crawford GetProcess()->GetTarget().EvaluateExpression(expression, frame_ptr, expr_result); 123115f2bd95SEwan Crawford 123215f2bd95SEwan Crawford if (!expr_result) 123315f2bd95SEwan Crawford { 123415f2bd95SEwan Crawford if (log) 123515f2bd95SEwan Crawford log->Printf("RenderScriptRuntime::EvalRSExpression - Error: Couldn't evaluate expression"); 123615f2bd95SEwan Crawford return false; 123715f2bd95SEwan Crawford } 123815f2bd95SEwan Crawford 123915f2bd95SEwan Crawford // The result of the expression is invalid 124015f2bd95SEwan Crawford if (!expr_result->GetError().Success()) 124115f2bd95SEwan Crawford { 124215f2bd95SEwan Crawford Error err = expr_result->GetError(); 124315f2bd95SEwan Crawford if (err.GetError() == UserExpression::kNoResult) // Expression returned void, so this is actually a success 124415f2bd95SEwan Crawford { 124515f2bd95SEwan Crawford if (log) 124615f2bd95SEwan Crawford log->Printf("RenderScriptRuntime::EvalRSExpression - Expression returned void"); 124715f2bd95SEwan Crawford 124815f2bd95SEwan Crawford result = nullptr; 124915f2bd95SEwan Crawford return true; 125015f2bd95SEwan Crawford } 125115f2bd95SEwan Crawford 125215f2bd95SEwan Crawford if (log) 125315f2bd95SEwan Crawford log->Printf("RenderScriptRuntime::EvalRSExpression - Error evaluating expression result: %s", err.AsCString()); 125415f2bd95SEwan Crawford return false; 125515f2bd95SEwan Crawford } 125615f2bd95SEwan Crawford 125715f2bd95SEwan Crawford bool success = false; 125815f2bd95SEwan Crawford *result = expr_result->GetValueAsUnsigned(0, &success); // We only read the result as an unsigned int. 125915f2bd95SEwan Crawford 126015f2bd95SEwan Crawford if (!success) 126115f2bd95SEwan Crawford { 126215f2bd95SEwan Crawford if (log) 126315f2bd95SEwan Crawford log->Printf("RenderScriptRuntime::EvalRSExpression - Error: Couldn't convert expression result to unsigned int"); 126415f2bd95SEwan Crawford return false; 126515f2bd95SEwan Crawford } 126615f2bd95SEwan Crawford 126715f2bd95SEwan Crawford return true; 126815f2bd95SEwan Crawford } 126915f2bd95SEwan Crawford 1270b1651b8dSEwan Crawford namespace // anonymous 127115f2bd95SEwan Crawford { 1272b1651b8dSEwan Crawford // max length of an expanded expression 1273b1651b8dSEwan Crawford const int jit_max_expr_size = 768; 127415f2bd95SEwan Crawford 127515f2bd95SEwan Crawford // Format strings containing the expressions we may need to evaluate. 127615f2bd95SEwan Crawford const char runtimeExpressions[][256] = 127715f2bd95SEwan Crawford { 127815f2bd95SEwan Crawford // Mangled GetOffsetPointer(Allocation*, xoff, yoff, zoff, lod, cubemap) 127915f2bd95SEwan Crawford "(int*)_Z12GetOffsetPtrPKN7android12renderscript10AllocationEjjjj23RsAllocationCubemapFace(0x%lx, %u, %u, %u, 0, 0)", 128015f2bd95SEwan Crawford 128115f2bd95SEwan Crawford // Type* rsaAllocationGetType(Context*, Allocation*) 128215f2bd95SEwan Crawford "(void*)rsaAllocationGetType(0x%lx, 0x%lx)", 128315f2bd95SEwan Crawford 128415f2bd95SEwan Crawford // rsaTypeGetNativeData(Context*, Type*, void* typeData, size) 128515f2bd95SEwan Crawford // Pack the data in the following way mHal.state.dimX; mHal.state.dimY; mHal.state.dimZ; 128615f2bd95SEwan Crawford // mHal.state.lodCount; mHal.state.faces; mElement; into typeData 128715f2bd95SEwan Crawford // Need to specify 32 or 64 bit for uint_t since this differs between devices 128815f2bd95SEwan Crawford "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[0]", // X dim 128915f2bd95SEwan Crawford "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[1]", // Y dim 129015f2bd95SEwan Crawford "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[2]", // Z dim 129115f2bd95SEwan Crawford "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[5]", // Element ptr 129215f2bd95SEwan Crawford 129315f2bd95SEwan Crawford // rsaElementGetNativeData(Context*, Element*, uint32_t* elemData,size) 129415f2bd95SEwan Crawford // Pack mType; mKind; mNormalized; mVectorSize; NumSubElements into elemData 12958b244e21SEwan Crawford "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[0]", // Type 12968b244e21SEwan Crawford "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[1]", // Kind 12978b244e21SEwan Crawford "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[3]", // Vector Size 12988b244e21SEwan Crawford "uint32_t data[5]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[4]", // Field Count 12998b244e21SEwan Crawford 13008b244e21SEwan Crawford // rsaElementGetSubElements(RsContext con, RsElement elem, uintptr_t *ids, const char **names, 13018b244e21SEwan Crawford // size_t *arraySizes, uint32_t dataSize) 13028b244e21SEwan Crawford // Needed for Allocations of structs to gather details about fields/Subelements 13038b244e21SEwan Crawford "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];" 13048b244e21SEwan Crawford "(void*)rsaElementGetSubElements(0x%lx, 0x%lx, ids, names, arr_size, %u); ids[%u]", // Element* of field 13058b244e21SEwan Crawford 13068b244e21SEwan Crawford "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];" 13078b244e21SEwan Crawford "(void*)rsaElementGetSubElements(0x%lx, 0x%lx, ids, names, arr_size, %u); names[%u]", // Name of field 13088b244e21SEwan Crawford 13098b244e21SEwan Crawford "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];" 13108b244e21SEwan Crawford "(void*)rsaElementGetSubElements(0x%lx, 0x%lx, ids, names, arr_size, %u); arr_size[%u]" // Array size of field 131115f2bd95SEwan Crawford }; 131215f2bd95SEwan Crawford 1313b1651b8dSEwan Crawford 1314b1651b8dSEwan Crawford // Temporary workaround for MIPS, until the compiler emits the JAL instruction when invoking directly the function. 1315b1651b8dSEwan Crawford // At the moment, when evaluating an expression involving a function call, the LLVM codegen for Mips emits a JAL 1316b1651b8dSEwan Crawford // instruction, which is able to jump in the range +/- 128MB with respect to the current program counter ($pc). If 1317b1651b8dSEwan Crawford // the requested function happens to reside outside the above region, the function address will be truncated and the 1318b1651b8dSEwan 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 1319b1651b8dSEwan Crawford // the nature of allocations. A proper solution in the MIPS compiler is currently being investigated. As temporary 1320b1651b8dSEwan Crawford // work around for this context, we'll invoke the RS API through function pointers, which cause the compiler to emit a 1321b1651b8dSEwan Crawford // register based JALR instruction. 1322b1651b8dSEwan Crawford const char runtimeExpressions_mips[][512] = 1323b1651b8dSEwan Crawford { 1324b1651b8dSEwan Crawford // Mangled GetOffsetPointer(Allocation*, xoff, yoff, zoff, lod, cubemap) 1325b1651b8dSEwan Crawford "int* (*f) (void*, int, int, int, int, int) = (int* (*) (void*, int, int, int, int, int)) " 1326b1651b8dSEwan Crawford "_Z12GetOffsetPtrPKN7android12renderscript10AllocationEjjjj23RsAllocationCubemapFace; " 1327b1651b8dSEwan Crawford "(int*) f((void*) 0x%lx, %u, %u, %u, 0, 0)", 1328b1651b8dSEwan Crawford 1329b1651b8dSEwan Crawford // Type* rsaAllocationGetType(Context*, Allocation*) 1330b1651b8dSEwan Crawford "void* (*f) (void*, void*) = (void* (*) (void*, void*)) rsaAllocationGetType; (void*) f((void*) 0x%lx, (void*) 0x%lx)", 1331b1651b8dSEwan Crawford 1332b1651b8dSEwan Crawford // rsaTypeGetNativeData(Context*, Type*, void* typeData, size) 1333b1651b8dSEwan Crawford // Pack the data in the following way mHal.state.dimX; mHal.state.dimY; mHal.state.dimZ; 1334b1651b8dSEwan Crawford // mHal.state.lodCount; mHal.state.faces; mElement; into typeData 1335b1651b8dSEwan Crawford // Need to specify 32 or 64 bit for uint_t since this differs between devices 1336b1651b8dSEwan Crawford "uint%u_t data[6]; void* (*f)(void*, void*, uintptr_t*, uint32_t) = (void* (*)(void*, void*, uintptr_t*, uint32_t)) " 1337b1651b8dSEwan Crawford "rsaTypeGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 6); data[0]", 1338b1651b8dSEwan Crawford "uint%u_t data[6]; void* (*f)(void*, void*, uintptr_t*, uint32_t) = (void* (*)(void*, void*, uintptr_t*, uint32_t)) " 1339b1651b8dSEwan Crawford "rsaTypeGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 6); data[1]", 1340b1651b8dSEwan Crawford "uint%u_t data[6]; void* (*f)(void*, void*, uintptr_t*, uint32_t) = (void* (*)(void*, void*, uintptr_t*, uint32_t)) " 1341b1651b8dSEwan Crawford "rsaTypeGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 6); data[2]", 1342b1651b8dSEwan Crawford "uint%u_t data[6]; void* (*f)(void*, void*, uintptr_t*, uint32_t) = (void* (*)(void*, void*, uintptr_t*, uint32_t)) " 1343b1651b8dSEwan Crawford "rsaTypeGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 6); data[5]", 1344b1651b8dSEwan Crawford 1345b1651b8dSEwan Crawford // rsaElementGetNativeData(Context*, Element*, uint32_t* elemData,size) 1346b1651b8dSEwan Crawford // Pack mType; mKind; mNormalized; mVectorSize; NumSubElements into elemData 1347b1651b8dSEwan Crawford "uint32_t data[5]; void* (*f)(void*, void*, uint32_t*, uint32_t) = (void* (*)(void*, void*, uint32_t*, uint32_t)) " 1348b1651b8dSEwan Crawford "rsaElementGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 5); data[0]", // Type 1349b1651b8dSEwan Crawford "uint32_t data[5]; void* (*f)(void*, void*, uint32_t*, uint32_t) = (void* (*)(void*, void*, uint32_t*, uint32_t)) " 1350b1651b8dSEwan Crawford "rsaElementGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 5); data[1]", // Kind 1351b1651b8dSEwan Crawford "uint32_t data[5]; void* (*f)(void*, void*, uint32_t*, uint32_t) = (void* (*)(void*, void*, uint32_t*, uint32_t)) " 1352b1651b8dSEwan Crawford "rsaElementGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 5); data[3]", // Vector size 1353b1651b8dSEwan Crawford "uint32_t data[5]; void* (*f)(void*, void*, uint32_t*, uint32_t) = (void* (*)(void*, void*, uint32_t*, uint32_t)) " 1354b1651b8dSEwan Crawford "rsaElementGetNativeData; (void*) f((void*) 0x%lx, (void*) 0x%lx, data, 5); data[4]", // Field count 1355b1651b8dSEwan Crawford 1356b1651b8dSEwan Crawford // rsaElementGetSubElements(RsContext con, RsElement elem, uintptr_t *ids, const char **names, 1357b1651b8dSEwan Crawford // size_t *arraySizes, uint32_t dataSize) 1358b1651b8dSEwan Crawford // Needed for Allocations of structs to gather details about fields/Subelements 1359b1651b8dSEwan Crawford "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];" 1360b1651b8dSEwan Crawford "void* (*f) (void*, void*, uintptr_t*, const char**, size_t*, uint32_t) = " 1361b1651b8dSEwan Crawford "(void* (*) (void*, void*, uintptr_t*, const char**, size_t*, uint32_t)) rsaElementGetSubElements;" 1362b1651b8dSEwan Crawford "(void*) f((void*) 0x%lx, (void*) 0x%lx, (uintptr_t*) ids, names, arr_size, (uint32_t) %u);" 1363b1651b8dSEwan Crawford "ids[%u]", // Element* of field 1364b1651b8dSEwan Crawford "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];" 1365b1651b8dSEwan Crawford "void* (*f) (void*, void*, uintptr_t*, const char**, size_t*, uint32_t) = " 1366b1651b8dSEwan Crawford "(void* (*) (void*, void*, uintptr_t*, const char**, size_t*, uint32_t)) rsaElementGetSubElements;" 1367b1651b8dSEwan Crawford "(void*) f((void*) 0x%lx, (void*) 0x%lx, (uintptr_t*) ids, names, arr_size, (uint32_t) %u);" 1368b1651b8dSEwan Crawford "names[%u]", // Name of field 1369b1651b8dSEwan Crawford "void* ids[%u]; const char* names[%u]; size_t arr_size[%u];" 1370b1651b8dSEwan Crawford "void* (*f) (void*, void*, uintptr_t*, const char**, size_t*, uint32_t) = " 1371b1651b8dSEwan Crawford "(void* (*) (void*, void*, uintptr_t*, const char**, size_t*, uint32_t)) rsaElementGetSubElements;" 1372b1651b8dSEwan Crawford "(void*) f((void*) 0x%lx, (void*) 0x%lx, (uintptr_t*) ids, names, arr_size, (uint32_t) %u);" 1373b1651b8dSEwan Crawford "arr_size[%u]" // Array size of field 1374b1651b8dSEwan Crawford }; 1375b1651b8dSEwan Crawford 1376b1651b8dSEwan Crawford } // end of the anonymous namespace 1377b1651b8dSEwan Crawford 1378b1651b8dSEwan Crawford 1379b1651b8dSEwan Crawford // Retrieve the string to JIT for the given expression 1380b1651b8dSEwan Crawford const char* 1381b1651b8dSEwan Crawford RenderScriptRuntime::JITTemplate(ExpressionStrings e) 1382b1651b8dSEwan Crawford { 1383b1651b8dSEwan Crawford // be nice to your Mips friend when adding new expression strings 1384b1651b8dSEwan Crawford static_assert(sizeof(runtimeExpressions)/sizeof(runtimeExpressions[0]) == 1385b1651b8dSEwan Crawford sizeof(runtimeExpressions_mips)/sizeof(runtimeExpressions_mips[0]), 1386b1651b8dSEwan Crawford "#runtimeExpressions != #runtimeExpressions_mips"); 1387b1651b8dSEwan Crawford 1388b1651b8dSEwan Crawford assert((e >= eExprGetOffsetPtr && e <= eExprSubelementsArrSize) && 1389b1651b8dSEwan Crawford "Expression string out of bounds"); 1390b1651b8dSEwan Crawford 1391b1651b8dSEwan Crawford llvm::Triple::ArchType arch = GetTargetRef().GetArchitecture().GetMachine(); 1392b1651b8dSEwan Crawford 1393b1651b8dSEwan Crawford // mips JAL workaround 1394b1651b8dSEwan Crawford if(arch == llvm::Triple::ArchType::mips64el || arch == llvm::Triple::ArchType::mipsel) 1395b1651b8dSEwan Crawford return runtimeExpressions_mips[e]; 1396b1651b8dSEwan Crawford else 1397b1651b8dSEwan Crawford return runtimeExpressions[e]; 1398b1651b8dSEwan Crawford } 1399b1651b8dSEwan Crawford 1400b1651b8dSEwan Crawford 140115f2bd95SEwan Crawford // JITs the RS runtime for the internal data pointer of an allocation. 140215f2bd95SEwan Crawford // Is passed x,y,z coordinates for the pointer to a specific element. 140315f2bd95SEwan Crawford // Then sets the data_ptr member in Allocation with the result. 140415f2bd95SEwan Crawford // Returns true on success, false otherwise 140515f2bd95SEwan Crawford bool 140615f2bd95SEwan Crawford RenderScriptRuntime::JITDataPointer(AllocationDetails* allocation, StackFrame* frame_ptr, 140715f2bd95SEwan Crawford unsigned int x, unsigned int y, unsigned int z) 140815f2bd95SEwan Crawford { 140915f2bd95SEwan Crawford Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 141015f2bd95SEwan Crawford 141115f2bd95SEwan Crawford if (!allocation->address.isValid()) 141215f2bd95SEwan Crawford { 141315f2bd95SEwan Crawford if (log) 141415f2bd95SEwan Crawford log->Printf("RenderScriptRuntime::JITDataPointer - Failed to find allocation details"); 141515f2bd95SEwan Crawford return false; 141615f2bd95SEwan Crawford } 141715f2bd95SEwan Crawford 1418b1651b8dSEwan Crawford const char* expr_cstr = JITTemplate(eExprGetOffsetPtr); 1419b1651b8dSEwan Crawford char buffer[jit_max_expr_size]; 142015f2bd95SEwan Crawford 1421b1651b8dSEwan Crawford int chars_written = snprintf(buffer, jit_max_expr_size, expr_cstr, *allocation->address.get(), x, y, z); 142215f2bd95SEwan Crawford if (chars_written < 0) 142315f2bd95SEwan Crawford { 142415f2bd95SEwan Crawford if (log) 142515f2bd95SEwan Crawford log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()"); 142615f2bd95SEwan Crawford return false; 142715f2bd95SEwan Crawford } 1428b1651b8dSEwan Crawford else if (chars_written >= jit_max_expr_size) 142915f2bd95SEwan Crawford { 143015f2bd95SEwan Crawford if (log) 143115f2bd95SEwan Crawford log->Printf("RenderScriptRuntime::JITDataPointer - Expression too long"); 143215f2bd95SEwan Crawford return false; 143315f2bd95SEwan Crawford } 143415f2bd95SEwan Crawford 143515f2bd95SEwan Crawford uint64_t result = 0; 143615f2bd95SEwan Crawford if (!EvalRSExpression(buffer, frame_ptr, &result)) 143715f2bd95SEwan Crawford return false; 143815f2bd95SEwan Crawford 143915f2bd95SEwan Crawford addr_t mem_ptr = static_cast<lldb::addr_t>(result); 144015f2bd95SEwan Crawford allocation->data_ptr = mem_ptr; 144115f2bd95SEwan Crawford 144215f2bd95SEwan Crawford return true; 144315f2bd95SEwan Crawford } 144415f2bd95SEwan Crawford 144515f2bd95SEwan Crawford // JITs the RS runtime for the internal pointer to the RS Type of an allocation 144615f2bd95SEwan Crawford // Then sets the type_ptr member in Allocation with the result. 144715f2bd95SEwan Crawford // Returns true on success, false otherwise 144815f2bd95SEwan Crawford bool 144915f2bd95SEwan Crawford RenderScriptRuntime::JITTypePointer(AllocationDetails* allocation, StackFrame* frame_ptr) 145015f2bd95SEwan Crawford { 145115f2bd95SEwan Crawford Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 145215f2bd95SEwan Crawford 145315f2bd95SEwan Crawford if (!allocation->address.isValid() || !allocation->context.isValid()) 145415f2bd95SEwan Crawford { 145515f2bd95SEwan Crawford if (log) 145615f2bd95SEwan Crawford log->Printf("RenderScriptRuntime::JITTypePointer - Failed to find allocation details"); 145715f2bd95SEwan Crawford return false; 145815f2bd95SEwan Crawford } 145915f2bd95SEwan Crawford 1460b1651b8dSEwan Crawford const char* expr_cstr = JITTemplate(eExprAllocGetType); 1461b1651b8dSEwan Crawford char buffer[jit_max_expr_size]; 146215f2bd95SEwan Crawford 1463b1651b8dSEwan Crawford int chars_written = snprintf(buffer, jit_max_expr_size, expr_cstr, *allocation->context.get(), *allocation->address.get()); 146415f2bd95SEwan Crawford if (chars_written < 0) 146515f2bd95SEwan Crawford { 146615f2bd95SEwan Crawford if (log) 146715f2bd95SEwan Crawford log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()"); 146815f2bd95SEwan Crawford return false; 146915f2bd95SEwan Crawford } 1470b1651b8dSEwan Crawford else if (chars_written >= jit_max_expr_size) 147115f2bd95SEwan Crawford { 147215f2bd95SEwan Crawford if (log) 147315f2bd95SEwan Crawford log->Printf("RenderScriptRuntime::JITTypePointer - Expression too long"); 147415f2bd95SEwan Crawford return false; 147515f2bd95SEwan Crawford } 147615f2bd95SEwan Crawford 147715f2bd95SEwan Crawford uint64_t result = 0; 147815f2bd95SEwan Crawford if (!EvalRSExpression(buffer, frame_ptr, &result)) 147915f2bd95SEwan Crawford return false; 148015f2bd95SEwan Crawford 148115f2bd95SEwan Crawford addr_t type_ptr = static_cast<lldb::addr_t>(result); 148215f2bd95SEwan Crawford allocation->type_ptr = type_ptr; 148315f2bd95SEwan Crawford 148415f2bd95SEwan Crawford return true; 148515f2bd95SEwan Crawford } 148615f2bd95SEwan Crawford 148715f2bd95SEwan Crawford // JITs the RS runtime for information about the dimensions and type of an allocation 148815f2bd95SEwan Crawford // Then sets dimension and element_ptr members in Allocation with the result. 148915f2bd95SEwan Crawford // Returns true on success, false otherwise 149015f2bd95SEwan Crawford bool 149115f2bd95SEwan Crawford RenderScriptRuntime::JITTypePacked(AllocationDetails* allocation, StackFrame* frame_ptr) 149215f2bd95SEwan Crawford { 149315f2bd95SEwan Crawford Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 149415f2bd95SEwan Crawford 149515f2bd95SEwan Crawford if (!allocation->type_ptr.isValid() || !allocation->context.isValid()) 149615f2bd95SEwan Crawford { 149715f2bd95SEwan Crawford if (log) 149815f2bd95SEwan Crawford log->Printf("RenderScriptRuntime::JITTypePacked - Failed to find allocation details"); 149915f2bd95SEwan Crawford return false; 150015f2bd95SEwan Crawford } 150115f2bd95SEwan Crawford 150215f2bd95SEwan Crawford // Expression is different depending on if device is 32 or 64 bit 150315f2bd95SEwan Crawford uint32_t archByteSize = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize(); 150415f2bd95SEwan Crawford const unsigned int bits = archByteSize == 4 ? 32 : 64; 150515f2bd95SEwan Crawford 150615f2bd95SEwan Crawford // We want 4 elements from packed data 150715f2bd95SEwan Crawford const unsigned int num_exprs = 4; 150815f2bd95SEwan Crawford assert(num_exprs == (eExprTypeElemPtr - eExprTypeDimX + 1) && "Invalid number of expressions"); 150915f2bd95SEwan Crawford 1510b1651b8dSEwan Crawford char buffer[num_exprs][jit_max_expr_size]; 151115f2bd95SEwan Crawford uint64_t results[num_exprs]; 151215f2bd95SEwan Crawford 151315f2bd95SEwan Crawford for (unsigned int i = 0; i < num_exprs; ++i) 151415f2bd95SEwan Crawford { 1515b1651b8dSEwan Crawford const char* expr_cstr = JITTemplate((ExpressionStrings) (eExprTypeDimX + i)); 1516b1651b8dSEwan Crawford int chars_written = snprintf(buffer[i], jit_max_expr_size, expr_cstr, bits, 151715f2bd95SEwan Crawford *allocation->context.get(), *allocation->type_ptr.get()); 151815f2bd95SEwan Crawford if (chars_written < 0) 151915f2bd95SEwan Crawford { 152015f2bd95SEwan Crawford if (log) 152115f2bd95SEwan Crawford log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()"); 152215f2bd95SEwan Crawford return false; 152315f2bd95SEwan Crawford } 1524b1651b8dSEwan Crawford else if (chars_written >= jit_max_expr_size) 152515f2bd95SEwan Crawford { 152615f2bd95SEwan Crawford if (log) 152715f2bd95SEwan Crawford log->Printf("RenderScriptRuntime::JITTypePacked - Expression too long"); 152815f2bd95SEwan Crawford return false; 152915f2bd95SEwan Crawford } 153015f2bd95SEwan Crawford 153115f2bd95SEwan Crawford // Perform expression evaluation 153215f2bd95SEwan Crawford if (!EvalRSExpression(buffer[i], frame_ptr, &results[i])) 153315f2bd95SEwan Crawford return false; 153415f2bd95SEwan Crawford } 153515f2bd95SEwan Crawford 153615f2bd95SEwan Crawford // Assign results to allocation members 153715f2bd95SEwan Crawford AllocationDetails::Dimension dims; 153815f2bd95SEwan Crawford dims.dim_1 = static_cast<uint32_t>(results[0]); 153915f2bd95SEwan Crawford dims.dim_2 = static_cast<uint32_t>(results[1]); 154015f2bd95SEwan Crawford dims.dim_3 = static_cast<uint32_t>(results[2]); 154115f2bd95SEwan Crawford allocation->dimension = dims; 154215f2bd95SEwan Crawford 154315f2bd95SEwan Crawford addr_t elem_ptr = static_cast<lldb::addr_t>(results[3]); 15448b244e21SEwan Crawford allocation->element.element_ptr = elem_ptr; 154515f2bd95SEwan Crawford 154615f2bd95SEwan Crawford if (log) 154715f2bd95SEwan Crawford log->Printf("RenderScriptRuntime::JITTypePacked - dims (%u, %u, %u) Element*: 0x%" PRIx64, 154815f2bd95SEwan Crawford dims.dim_1, dims.dim_2, dims.dim_3, elem_ptr); 154915f2bd95SEwan Crawford 155015f2bd95SEwan Crawford return true; 155115f2bd95SEwan Crawford } 155215f2bd95SEwan Crawford 155315f2bd95SEwan Crawford // JITs the RS runtime for information about the Element of an allocation 15548b244e21SEwan Crawford // Then sets type, type_vec_size, field_count and type_kind members in Element with the result. 155515f2bd95SEwan Crawford // Returns true on success, false otherwise 155615f2bd95SEwan Crawford bool 15578b244e21SEwan Crawford RenderScriptRuntime::JITElementPacked(Element& elem, const lldb::addr_t context, StackFrame* frame_ptr) 155815f2bd95SEwan Crawford { 155915f2bd95SEwan Crawford Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 156015f2bd95SEwan Crawford 15618b244e21SEwan Crawford if (!elem.element_ptr.isValid()) 156215f2bd95SEwan Crawford { 156315f2bd95SEwan Crawford if (log) 156415f2bd95SEwan Crawford log->Printf("RenderScriptRuntime::JITElementPacked - Failed to find allocation details"); 156515f2bd95SEwan Crawford return false; 156615f2bd95SEwan Crawford } 156715f2bd95SEwan Crawford 15688b244e21SEwan Crawford // We want 4 elements from packed data 15698b244e21SEwan Crawford const unsigned int num_exprs = 4; 15708b244e21SEwan Crawford assert(num_exprs == (eExprElementFieldCount - eExprElementType + 1) && "Invalid number of expressions"); 157115f2bd95SEwan Crawford 1572b1651b8dSEwan Crawford char buffer[num_exprs][jit_max_expr_size]; 157315f2bd95SEwan Crawford uint64_t results[num_exprs]; 157415f2bd95SEwan Crawford 157515f2bd95SEwan Crawford for (unsigned int i = 0; i < num_exprs; i++) 157615f2bd95SEwan Crawford { 1577b1651b8dSEwan Crawford const char* expr_cstr = JITTemplate((ExpressionStrings) (eExprElementType + i)); 1578b1651b8dSEwan Crawford int chars_written = snprintf(buffer[i], jit_max_expr_size, expr_cstr, context, *elem.element_ptr.get()); 157915f2bd95SEwan Crawford if (chars_written < 0) 158015f2bd95SEwan Crawford { 158115f2bd95SEwan Crawford if (log) 15828b244e21SEwan Crawford log->Printf("RenderScriptRuntime::JITElementPacked - Encoding error in snprintf()"); 158315f2bd95SEwan Crawford return false; 158415f2bd95SEwan Crawford } 1585b1651b8dSEwan Crawford else if (chars_written >= jit_max_expr_size) 158615f2bd95SEwan Crawford { 158715f2bd95SEwan Crawford if (log) 158815f2bd95SEwan Crawford log->Printf("RenderScriptRuntime::JITElementPacked - Expression too long"); 158915f2bd95SEwan Crawford return false; 159015f2bd95SEwan Crawford } 159115f2bd95SEwan Crawford 159215f2bd95SEwan Crawford // Perform expression evaluation 159315f2bd95SEwan Crawford if (!EvalRSExpression(buffer[i], frame_ptr, &results[i])) 159415f2bd95SEwan Crawford return false; 159515f2bd95SEwan Crawford } 159615f2bd95SEwan Crawford 159715f2bd95SEwan Crawford // Assign results to allocation members 15988b244e21SEwan Crawford elem.type = static_cast<RenderScriptRuntime::Element::DataType>(results[0]); 15998b244e21SEwan Crawford elem.type_kind = static_cast<RenderScriptRuntime::Element::DataKind>(results[1]); 16008b244e21SEwan Crawford elem.type_vec_size = static_cast<uint32_t>(results[2]); 16018b244e21SEwan Crawford elem.field_count = static_cast<uint32_t>(results[3]); 160215f2bd95SEwan Crawford 160315f2bd95SEwan Crawford if (log) 16048b244e21SEwan Crawford log->Printf("RenderScriptRuntime::JITElementPacked - data type %u, pixel type %u, vector size %u, field count %u", 16058b244e21SEwan Crawford *elem.type.get(), *elem.type_kind.get(), *elem.type_vec_size.get(), *elem.field_count.get()); 16068b244e21SEwan Crawford 16078b244e21SEwan Crawford // If this Element has subelements then JIT rsaElementGetSubElements() for details about its fields 16088b244e21SEwan Crawford if (*elem.field_count.get() > 0 && !JITSubelements(elem, context, frame_ptr)) 16098b244e21SEwan Crawford return false; 16108b244e21SEwan Crawford 16118b244e21SEwan Crawford return true; 16128b244e21SEwan Crawford } 16138b244e21SEwan Crawford 16148b244e21SEwan Crawford // JITs the RS runtime for information about the subelements/fields of a struct allocation 16158b244e21SEwan Crawford // This is necessary for infering the struct type so we can pretty print the allocation's contents. 16168b244e21SEwan Crawford // Returns true on success, false otherwise 16178b244e21SEwan Crawford bool 16188b244e21SEwan Crawford RenderScriptRuntime::JITSubelements(Element& elem, const lldb::addr_t context, StackFrame* frame_ptr) 16198b244e21SEwan Crawford { 16208b244e21SEwan Crawford Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 16218b244e21SEwan Crawford 16228b244e21SEwan Crawford if (!elem.element_ptr.isValid() || !elem.field_count.isValid()) 16238b244e21SEwan Crawford { 16248b244e21SEwan Crawford if (log) 16258b244e21SEwan Crawford log->Printf("RenderScriptRuntime::JITSubelements - Failed to find allocation details"); 16268b244e21SEwan Crawford return false; 16278b244e21SEwan Crawford } 16288b244e21SEwan Crawford 16298b244e21SEwan Crawford const short num_exprs = 3; 16308b244e21SEwan Crawford assert(num_exprs == (eExprSubelementsArrSize - eExprSubelementsId + 1) && "Invalid number of expressions"); 16318b244e21SEwan Crawford 1632b1651b8dSEwan Crawford char expr_buffer[jit_max_expr_size]; 16338b244e21SEwan Crawford uint64_t results; 16348b244e21SEwan Crawford 16358b244e21SEwan Crawford // Iterate over struct fields. 16368b244e21SEwan Crawford const uint32_t field_count = *elem.field_count.get(); 16378b244e21SEwan Crawford for (unsigned int field_index = 0; field_index < field_count; ++field_index) 16388b244e21SEwan Crawford { 16398b244e21SEwan Crawford Element child; 16408b244e21SEwan Crawford for (unsigned int expr_index = 0; expr_index < num_exprs; ++expr_index) 16418b244e21SEwan Crawford { 1642b1651b8dSEwan Crawford const char* expr_cstr = JITTemplate((ExpressionStrings) (eExprSubelementsId + expr_index)); 1643b1651b8dSEwan Crawford int chars_written = snprintf(expr_buffer, jit_max_expr_size, expr_cstr, 16448b244e21SEwan Crawford field_count, field_count, field_count, 16458b244e21SEwan Crawford context, *elem.element_ptr.get(), field_count, field_index); 16468b244e21SEwan Crawford if (chars_written < 0) 16478b244e21SEwan Crawford { 16488b244e21SEwan Crawford if (log) 16498b244e21SEwan Crawford log->Printf("RenderScriptRuntime::JITSubelements - Encoding error in snprintf()"); 16508b244e21SEwan Crawford return false; 16518b244e21SEwan Crawford } 1652b1651b8dSEwan Crawford else if (chars_written >= jit_max_expr_size) 16538b244e21SEwan Crawford { 16548b244e21SEwan Crawford if (log) 16558b244e21SEwan Crawford log->Printf("RenderScriptRuntime::JITSubelements - Expression too long"); 16568b244e21SEwan Crawford return false; 16578b244e21SEwan Crawford } 16588b244e21SEwan Crawford 16598b244e21SEwan Crawford // Perform expression evaluation 16608b244e21SEwan Crawford if (!EvalRSExpression(expr_buffer, frame_ptr, &results)) 16618b244e21SEwan Crawford return false; 16628b244e21SEwan Crawford 16638b244e21SEwan Crawford if (log) 16648b244e21SEwan Crawford log->Printf("RenderScriptRuntime::JITSubelements - Expr result 0x%" PRIx64, results); 16658b244e21SEwan Crawford 16668b244e21SEwan Crawford switch(expr_index) 16678b244e21SEwan Crawford { 16688b244e21SEwan Crawford case 0: // Element* of child 16698b244e21SEwan Crawford child.element_ptr = static_cast<addr_t>(results); 16708b244e21SEwan Crawford break; 16718b244e21SEwan Crawford case 1: // Name of child 16728b244e21SEwan Crawford { 16738b244e21SEwan Crawford lldb::addr_t address = static_cast<addr_t>(results); 16748b244e21SEwan Crawford Error err; 16758b244e21SEwan Crawford std::string name; 16768b244e21SEwan Crawford GetProcess()->ReadCStringFromMemory(address, name, err); 16778b244e21SEwan Crawford if (!err.Fail()) 16788b244e21SEwan Crawford child.type_name = ConstString(name); 16798b244e21SEwan Crawford else 16808b244e21SEwan Crawford { 16818b244e21SEwan Crawford if (log) 16828b244e21SEwan Crawford log->Printf("RenderScriptRuntime::JITSubelements - Warning: Couldn't read field name"); 16838b244e21SEwan Crawford } 16848b244e21SEwan Crawford break; 16858b244e21SEwan Crawford } 16868b244e21SEwan Crawford case 2: // Array size of child 16878b244e21SEwan Crawford child.array_size = static_cast<uint32_t>(results); 16888b244e21SEwan Crawford break; 16898b244e21SEwan Crawford } 16908b244e21SEwan Crawford } 16918b244e21SEwan Crawford 16928b244e21SEwan Crawford // We need to recursively JIT each Element field of the struct since 16938b244e21SEwan Crawford // structs can be nested inside structs. 16948b244e21SEwan Crawford if (!JITElementPacked(child, context, frame_ptr)) 16958b244e21SEwan Crawford return false; 16968b244e21SEwan Crawford elem.children.push_back(child); 16978b244e21SEwan Crawford } 16988b244e21SEwan Crawford 16998b244e21SEwan Crawford // Try to infer the name of the struct type so we can pretty print the allocation contents. 17008b244e21SEwan Crawford FindStructTypeName(elem, frame_ptr); 170115f2bd95SEwan Crawford 170215f2bd95SEwan Crawford return true; 170315f2bd95SEwan Crawford } 170415f2bd95SEwan Crawford 1705a0f08674SEwan Crawford // JITs the RS runtime for the address of the last element in the allocation. 1706a0f08674SEwan Crawford // The `elem_size` paramter represents the size of a single element, including padding. 1707a0f08674SEwan Crawford // Which is needed as an offset from the last element pointer. 1708a0f08674SEwan Crawford // Using this offset minus the starting address we can calculate the size of the allocation. 1709a0f08674SEwan Crawford // Returns true on success, false otherwise 1710a0f08674SEwan Crawford bool 17118b244e21SEwan Crawford RenderScriptRuntime::JITAllocationSize(AllocationDetails* allocation, StackFrame* frame_ptr) 1712a0f08674SEwan Crawford { 1713a0f08674SEwan Crawford Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 1714a0f08674SEwan Crawford 1715a0f08674SEwan Crawford if (!allocation->address.isValid() || !allocation->dimension.isValid() 17168b244e21SEwan Crawford || !allocation->data_ptr.isValid() || !allocation->element.datum_size.isValid()) 1717a0f08674SEwan Crawford { 1718a0f08674SEwan Crawford if (log) 1719a0f08674SEwan Crawford log->Printf("RenderScriptRuntime::JITAllocationSize - Failed to find allocation details"); 1720a0f08674SEwan Crawford return false; 1721a0f08674SEwan Crawford } 1722a0f08674SEwan Crawford 1723a0f08674SEwan Crawford // Find dimensions 1724a0f08674SEwan Crawford unsigned int dim_x = allocation->dimension.get()->dim_1; 1725a0f08674SEwan Crawford unsigned int dim_y = allocation->dimension.get()->dim_2; 1726a0f08674SEwan Crawford unsigned int dim_z = allocation->dimension.get()->dim_3; 1727a0f08674SEwan Crawford 17288b244e21SEwan Crawford // Our plan of jitting the last element address doesn't seem to work for struct Allocations 17298b244e21SEwan Crawford // Instead try to infer the size ourselves without any inter element padding. 17308b244e21SEwan Crawford if (allocation->element.children.size() > 0) 17318b244e21SEwan Crawford { 17328b244e21SEwan Crawford if (dim_x == 0) dim_x = 1; 17338b244e21SEwan Crawford if (dim_y == 0) dim_y = 1; 17348b244e21SEwan Crawford if (dim_z == 0) dim_z = 1; 17358b244e21SEwan Crawford 17368b244e21SEwan Crawford allocation->size = dim_x * dim_y * dim_z * *allocation->element.datum_size.get(); 17378b244e21SEwan Crawford 17388b244e21SEwan Crawford if (log) 17398b244e21SEwan Crawford log->Printf("RenderScriptRuntime::JITAllocationSize - Infered size of struct allocation %u", *allocation->size.get()); 17408b244e21SEwan Crawford 17418b244e21SEwan Crawford return true; 17428b244e21SEwan Crawford } 17438b244e21SEwan Crawford 1744b1651b8dSEwan Crawford const char* expr_cstr = JITTemplate(eExprGetOffsetPtr); 1745b1651b8dSEwan Crawford char buffer[jit_max_expr_size]; 17468b244e21SEwan Crawford 1747a0f08674SEwan Crawford // Calculate last element 1748a0f08674SEwan Crawford dim_x = dim_x == 0 ? 0 : dim_x - 1; 1749a0f08674SEwan Crawford dim_y = dim_y == 0 ? 0 : dim_y - 1; 1750a0f08674SEwan Crawford dim_z = dim_z == 0 ? 0 : dim_z - 1; 1751a0f08674SEwan Crawford 1752b1651b8dSEwan Crawford int chars_written = snprintf(buffer, jit_max_expr_size, expr_cstr, *allocation->address.get(), 1753a0f08674SEwan Crawford dim_x, dim_y, dim_z); 1754a0f08674SEwan Crawford if (chars_written < 0) 1755a0f08674SEwan Crawford { 1756a0f08674SEwan Crawford if (log) 1757a0f08674SEwan Crawford log->Printf("RenderScriptRuntime::JITAllocationSize - Encoding error in snprintf()"); 1758a0f08674SEwan Crawford return false; 1759a0f08674SEwan Crawford } 1760b1651b8dSEwan Crawford else if (chars_written >= jit_max_expr_size) 1761a0f08674SEwan Crawford { 1762a0f08674SEwan Crawford if (log) 1763a0f08674SEwan Crawford log->Printf("RenderScriptRuntime::JITAllocationSize - Expression too long"); 1764a0f08674SEwan Crawford return false; 1765a0f08674SEwan Crawford } 1766a0f08674SEwan Crawford 1767a0f08674SEwan Crawford uint64_t result = 0; 1768a0f08674SEwan Crawford if (!EvalRSExpression(buffer, frame_ptr, &result)) 1769a0f08674SEwan Crawford return false; 1770a0f08674SEwan Crawford 1771a0f08674SEwan Crawford addr_t mem_ptr = static_cast<lldb::addr_t>(result); 1772a0f08674SEwan Crawford // Find pointer to last element and add on size of an element 17738b244e21SEwan Crawford allocation->size = static_cast<uint32_t>(mem_ptr - *allocation->data_ptr.get()) + *allocation->element.datum_size.get(); 1774a0f08674SEwan Crawford 1775a0f08674SEwan Crawford return true; 1776a0f08674SEwan Crawford } 1777a0f08674SEwan Crawford 1778a0f08674SEwan Crawford // JITs the RS runtime for information about the stride between rows in the allocation. 1779a0f08674SEwan Crawford // This is done to detect padding, since allocated memory is 16-byte aligned. 1780a0f08674SEwan Crawford // Returns true on success, false otherwise 1781a0f08674SEwan Crawford bool 1782a0f08674SEwan Crawford RenderScriptRuntime::JITAllocationStride(AllocationDetails* allocation, StackFrame* frame_ptr) 1783a0f08674SEwan Crawford { 1784a0f08674SEwan Crawford Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 1785a0f08674SEwan Crawford 1786a0f08674SEwan Crawford if (!allocation->address.isValid() || !allocation->data_ptr.isValid()) 1787a0f08674SEwan Crawford { 1788a0f08674SEwan Crawford if (log) 1789a0f08674SEwan Crawford log->Printf("RenderScriptRuntime::JITAllocationStride - Failed to find allocation details"); 1790a0f08674SEwan Crawford return false; 1791a0f08674SEwan Crawford } 1792a0f08674SEwan Crawford 1793b1651b8dSEwan Crawford const char* expr_cstr = JITTemplate(eExprGetOffsetPtr); 1794b1651b8dSEwan Crawford char buffer[jit_max_expr_size]; 1795a0f08674SEwan Crawford 1796b1651b8dSEwan Crawford int chars_written = snprintf(buffer, jit_max_expr_size, expr_cstr, *allocation->address.get(), 1797a0f08674SEwan Crawford 0, 1, 0); 1798a0f08674SEwan Crawford if (chars_written < 0) 1799a0f08674SEwan Crawford { 1800a0f08674SEwan Crawford if (log) 1801a0f08674SEwan Crawford log->Printf("RenderScriptRuntime::JITAllocationStride - Encoding error in snprintf()"); 1802a0f08674SEwan Crawford return false; 1803a0f08674SEwan Crawford } 1804b1651b8dSEwan Crawford else if (chars_written >= jit_max_expr_size) 1805a0f08674SEwan Crawford { 1806a0f08674SEwan Crawford if (log) 1807a0f08674SEwan Crawford log->Printf("RenderScriptRuntime::JITAllocationStride - Expression too long"); 1808a0f08674SEwan Crawford return false; 1809a0f08674SEwan Crawford } 1810a0f08674SEwan Crawford 1811a0f08674SEwan Crawford uint64_t result = 0; 1812a0f08674SEwan Crawford if (!EvalRSExpression(buffer, frame_ptr, &result)) 1813a0f08674SEwan Crawford return false; 1814a0f08674SEwan Crawford 1815a0f08674SEwan Crawford addr_t mem_ptr = static_cast<lldb::addr_t>(result); 1816a0f08674SEwan Crawford allocation->stride = static_cast<uint32_t>(mem_ptr - *allocation->data_ptr.get()); 1817a0f08674SEwan Crawford 1818a0f08674SEwan Crawford return true; 1819a0f08674SEwan Crawford } 1820a0f08674SEwan Crawford 182115f2bd95SEwan Crawford // JIT all the current runtime info regarding an allocation 182215f2bd95SEwan Crawford bool 182315f2bd95SEwan Crawford RenderScriptRuntime::RefreshAllocation(AllocationDetails* allocation, StackFrame* frame_ptr) 182415f2bd95SEwan Crawford { 182515f2bd95SEwan Crawford // GetOffsetPointer() 182615f2bd95SEwan Crawford if (!JITDataPointer(allocation, frame_ptr)) 182715f2bd95SEwan Crawford return false; 182815f2bd95SEwan Crawford 182915f2bd95SEwan Crawford // rsaAllocationGetType() 183015f2bd95SEwan Crawford if (!JITTypePointer(allocation, frame_ptr)) 183115f2bd95SEwan Crawford return false; 183215f2bd95SEwan Crawford 183315f2bd95SEwan Crawford // rsaTypeGetNativeData() 183415f2bd95SEwan Crawford if (!JITTypePacked(allocation, frame_ptr)) 183515f2bd95SEwan Crawford return false; 183615f2bd95SEwan Crawford 183715f2bd95SEwan Crawford // rsaElementGetNativeData() 18388b244e21SEwan Crawford if (!JITElementPacked(allocation->element, *allocation->context.get(), frame_ptr)) 183915f2bd95SEwan Crawford return false; 184015f2bd95SEwan Crawford 18418b244e21SEwan Crawford // Sets the datum_size member in Element 18428b244e21SEwan Crawford SetElementSize(allocation->element); 18438b244e21SEwan Crawford 184455232f09SEwan Crawford // Use GetOffsetPointer() to infer size of the allocation 18458b244e21SEwan Crawford if (!JITAllocationSize(allocation, frame_ptr)) 184655232f09SEwan Crawford return false; 184755232f09SEwan Crawford 184855232f09SEwan Crawford return true; 184955232f09SEwan Crawford } 185055232f09SEwan Crawford 18518b244e21SEwan Crawford // Function attempts to set the type_name member of the paramaterised Element object. 18528b244e21SEwan Crawford // This string should be the name of the struct type the Element represents. 18538b244e21SEwan Crawford // We need this string for pretty printing the Element to users. 18548b244e21SEwan Crawford void 18558b244e21SEwan Crawford RenderScriptRuntime::FindStructTypeName(Element& elem, StackFrame* frame_ptr) 185655232f09SEwan Crawford { 18578b244e21SEwan Crawford Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 18588b244e21SEwan Crawford 18598b244e21SEwan Crawford if (!elem.type_name.IsEmpty()) // Name already set 18608b244e21SEwan Crawford return; 18618b244e21SEwan Crawford else 1862fe06b5adSAdrian McCarthy elem.type_name = Element::GetFallbackStructName(); // Default type name if we don't succeed 18638b244e21SEwan Crawford 18648b244e21SEwan Crawford // Find all the global variables from the script rs modules 18658b244e21SEwan Crawford VariableList variable_list; 18668b244e21SEwan Crawford for (auto module_sp : m_rsmodules) 18678b244e21SEwan Crawford module_sp->m_module->FindGlobalVariables(RegularExpression("."), true, UINT32_MAX, variable_list); 18688b244e21SEwan Crawford 18698b244e21SEwan Crawford // Iterate over all the global variables looking for one with a matching type to the Element. 18708b244e21SEwan Crawford // We make the assumption a match exists since there needs to be a global variable to reflect the 18718b244e21SEwan Crawford // struct type back into java host code. 18728b244e21SEwan Crawford for (uint32_t var_index = 0; var_index < variable_list.GetSize(); ++var_index) 18738b244e21SEwan Crawford { 18748b244e21SEwan Crawford const VariableSP var_sp(variable_list.GetVariableAtIndex(var_index)); 18758b244e21SEwan Crawford if (!var_sp) 18768b244e21SEwan Crawford continue; 18778b244e21SEwan Crawford 18788b244e21SEwan Crawford ValueObjectSP valobj_sp = ValueObjectVariable::Create(frame_ptr, var_sp); 18798b244e21SEwan Crawford if (!valobj_sp) 18808b244e21SEwan Crawford continue; 18818b244e21SEwan Crawford 18828b244e21SEwan Crawford // Find the number of variable fields. 18838b244e21SEwan Crawford // If it has no fields, or more fields than our Element, then it can't be the struct we're looking for. 18848b244e21SEwan Crawford // Don't check for equality since RS can add extra struct members for padding. 18858b244e21SEwan Crawford size_t num_children = valobj_sp->GetNumChildren(); 18868b244e21SEwan Crawford if (num_children > elem.children.size() || num_children == 0) 18878b244e21SEwan Crawford continue; 18888b244e21SEwan Crawford 18898b244e21SEwan Crawford // Iterate over children looking for members with matching field names. 18908b244e21SEwan Crawford // If all the field names match, this is likely the struct we want. 18918b244e21SEwan Crawford // 18928b244e21SEwan Crawford // TODO: This could be made more robust by also checking children data sizes, or array size 18938b244e21SEwan Crawford bool found = true; 18948b244e21SEwan Crawford for (size_t child_index = 0; child_index < num_children; ++child_index) 18958b244e21SEwan Crawford { 18968b244e21SEwan Crawford ValueObjectSP child = valobj_sp->GetChildAtIndex(child_index, true); 18978b244e21SEwan Crawford if (!child || (child->GetName() != elem.children[child_index].type_name)) 18988b244e21SEwan Crawford { 18998b244e21SEwan Crawford found = false; 19008b244e21SEwan Crawford break; 19018b244e21SEwan Crawford } 19028b244e21SEwan Crawford } 19038b244e21SEwan Crawford 19048b244e21SEwan Crawford // RS can add extra struct members for padding in the format '#rs_padding_[0-9]+' 19058b244e21SEwan Crawford if (found && num_children < elem.children.size()) 19068b244e21SEwan Crawford { 19078b244e21SEwan Crawford const unsigned int size_diff = elem.children.size() - num_children; 19088b244e21SEwan Crawford if (log) 19098b244e21SEwan Crawford log->Printf("RenderScriptRuntime::FindStructTypeName - %u padding struct entries", size_diff); 19108b244e21SEwan Crawford 19118b244e21SEwan Crawford for (unsigned int padding_index = 0; padding_index < size_diff; ++padding_index) 19128b244e21SEwan Crawford { 19138b244e21SEwan Crawford const ConstString& name = elem.children[num_children + padding_index].type_name; 19148b244e21SEwan Crawford if (strcmp(name.AsCString(), "#rs_padding") < 0) 19158b244e21SEwan Crawford found = false; 19168b244e21SEwan Crawford } 19178b244e21SEwan Crawford } 19188b244e21SEwan Crawford 19198b244e21SEwan Crawford // We've found a global var with matching type 19208b244e21SEwan Crawford if (found) 19218b244e21SEwan Crawford { 19228b244e21SEwan Crawford // Dereference since our Element type isn't a pointer. 19238b244e21SEwan Crawford if (valobj_sp->IsPointerType()) 19248b244e21SEwan Crawford { 19258b244e21SEwan Crawford Error err; 19268b244e21SEwan Crawford ValueObjectSP deref_valobj = valobj_sp->Dereference(err); 19278b244e21SEwan Crawford if (!err.Fail()) 19288b244e21SEwan Crawford valobj_sp = deref_valobj; 19298b244e21SEwan Crawford } 19308b244e21SEwan Crawford 19318b244e21SEwan Crawford // Save name of variable in Element. 19328b244e21SEwan Crawford elem.type_name = valobj_sp->GetTypeName(); 19338b244e21SEwan Crawford if (log) 19348b244e21SEwan Crawford log->Printf("RenderScriptRuntime::FindStructTypeName - Element name set to %s", elem.type_name.AsCString()); 19358b244e21SEwan Crawford 19368b244e21SEwan Crawford return; 19378b244e21SEwan Crawford } 19388b244e21SEwan Crawford } 19398b244e21SEwan Crawford } 19408b244e21SEwan Crawford 19418b244e21SEwan Crawford // Function sets the datum_size member of Element. Representing the size of a single instance including padding. 19428b244e21SEwan Crawford // Assumes the relevant allocation information has already been jitted. 19438b244e21SEwan Crawford void 19448b244e21SEwan Crawford RenderScriptRuntime::SetElementSize(Element& elem) 19458b244e21SEwan Crawford { 19468b244e21SEwan Crawford Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 19478b244e21SEwan Crawford const Element::DataType type = *elem.type.get(); 19482e920715SEwan Crawford assert(type >= Element::RS_TYPE_NONE && type <= Element::RS_TYPE_FONT 194955232f09SEwan Crawford && "Invalid allocation type"); 195055232f09SEwan Crawford 19518b244e21SEwan Crawford const unsigned int vec_size = *elem.type_vec_size.get(); 19528b244e21SEwan Crawford unsigned int data_size = 0; 19532e920715SEwan Crawford unsigned int padding = 0; 195455232f09SEwan Crawford 19558b244e21SEwan Crawford // Element is of a struct type, calculate size recursively. 19568b244e21SEwan Crawford if ((type == Element::RS_TYPE_NONE) && (elem.children.size() > 0)) 19578b244e21SEwan Crawford { 19588b244e21SEwan Crawford for (Element& child : elem.children) 19598b244e21SEwan Crawford { 19608b244e21SEwan Crawford SetElementSize(child); 19618b244e21SEwan Crawford const unsigned int array_size = child.array_size.isValid() ? *child.array_size.get() : 1; 19628b244e21SEwan Crawford data_size += *child.datum_size.get() * array_size; 19638b244e21SEwan Crawford } 19648b244e21SEwan Crawford } 19652e920715SEwan Crawford else if (type == Element::RS_TYPE_UNSIGNED_5_6_5 || type == Element::RS_TYPE_UNSIGNED_5_5_5_1 || 19662e920715SEwan Crawford type == Element::RS_TYPE_UNSIGNED_4_4_4_4) // These have been packed already 19672e920715SEwan Crawford { 19682e920715SEwan Crawford data_size = AllocationDetails::RSTypeToFormat[type][eElementSize]; 19692e920715SEwan Crawford } 19702e920715SEwan Crawford else if (type < Element::RS_TYPE_ELEMENT) 19712e920715SEwan Crawford { 19728b244e21SEwan Crawford data_size = vec_size * AllocationDetails::RSTypeToFormat[type][eElementSize]; 19732e920715SEwan Crawford if (vec_size == 3) 19742e920715SEwan Crawford padding = AllocationDetails::RSTypeToFormat[type][eElementSize]; 19752e920715SEwan Crawford } 19762e920715SEwan Crawford else 19772e920715SEwan Crawford data_size = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize(); 19788b244e21SEwan Crawford 19798b244e21SEwan Crawford elem.padding = padding; 19808b244e21SEwan Crawford elem.datum_size = data_size + padding; 19818b244e21SEwan Crawford if (log) 19828b244e21SEwan Crawford log->Printf("RenderScriptRuntime::SetElementSize - element size set to %u", data_size + padding); 198355232f09SEwan Crawford } 198455232f09SEwan Crawford 198555232f09SEwan Crawford // Given an allocation, this function copies the allocation contents from device into a buffer on the heap. 198655232f09SEwan Crawford // Returning a shared pointer to the buffer containing the data. 198755232f09SEwan Crawford std::shared_ptr<uint8_t> 198855232f09SEwan Crawford RenderScriptRuntime::GetAllocationData(AllocationDetails* allocation, StackFrame* frame_ptr) 198955232f09SEwan Crawford { 199055232f09SEwan Crawford Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 199155232f09SEwan Crawford 199255232f09SEwan Crawford // JIT all the allocation details 19938b59062aSEwan Crawford if (allocation->shouldRefresh()) 199455232f09SEwan Crawford { 199555232f09SEwan Crawford if (log) 199655232f09SEwan Crawford log->Printf("RenderScriptRuntime::GetAllocationData - Allocation details not calculated yet, jitting info"); 199755232f09SEwan Crawford 199855232f09SEwan Crawford if (!RefreshAllocation(allocation, frame_ptr)) 199955232f09SEwan Crawford { 200055232f09SEwan Crawford if (log) 200155232f09SEwan Crawford log->Printf("RenderScriptRuntime::GetAllocationData - Couldn't JIT allocation details"); 200255232f09SEwan Crawford return nullptr; 200355232f09SEwan Crawford } 200455232f09SEwan Crawford } 200555232f09SEwan Crawford 20068b244e21SEwan Crawford assert(allocation->data_ptr.isValid() && allocation->element.type.isValid() && allocation->element.type_vec_size.isValid() 200755232f09SEwan Crawford && allocation->size.isValid() && "Allocation information not available"); 200855232f09SEwan Crawford 200955232f09SEwan Crawford // Allocate a buffer to copy data into 201055232f09SEwan Crawford const unsigned int size = *allocation->size.get(); 201155232f09SEwan Crawford std::shared_ptr<uint8_t> buffer(new uint8_t[size]); 201255232f09SEwan Crawford if (!buffer) 201355232f09SEwan Crawford { 201455232f09SEwan Crawford if (log) 201555232f09SEwan Crawford log->Printf("RenderScriptRuntime::GetAllocationData - Couldn't allocate a %u byte buffer", size); 201655232f09SEwan Crawford return nullptr; 201755232f09SEwan Crawford } 201855232f09SEwan Crawford 201955232f09SEwan Crawford // Read the inferior memory 202055232f09SEwan Crawford Error error; 202155232f09SEwan Crawford lldb::addr_t data_ptr = *allocation->data_ptr.get(); 202255232f09SEwan Crawford GetProcess()->ReadMemory(data_ptr, buffer.get(), size, error); 202355232f09SEwan Crawford if (error.Fail()) 202455232f09SEwan Crawford { 202555232f09SEwan Crawford if (log) 202655232f09SEwan Crawford log->Printf("RenderScriptRuntime::GetAllocationData - '%s' Couldn't read %u bytes of allocation data from 0x%" PRIx64, 202755232f09SEwan Crawford error.AsCString(), size, data_ptr); 202855232f09SEwan Crawford return nullptr; 202955232f09SEwan Crawford } 203055232f09SEwan Crawford 203155232f09SEwan Crawford return buffer; 203255232f09SEwan Crawford } 203355232f09SEwan Crawford 203455232f09SEwan Crawford // Function copies data from a binary file into an allocation. 203555232f09SEwan Crawford // There is a header at the start of the file, FileHeader, before the data content itself. 203655232f09SEwan Crawford // Information from this header is used to display warnings to the user about incompatabilities 203755232f09SEwan Crawford bool 203855232f09SEwan Crawford RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id, const char* filename, StackFrame* frame_ptr) 203955232f09SEwan Crawford { 204055232f09SEwan Crawford Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 204155232f09SEwan Crawford 204255232f09SEwan Crawford // Find allocation with the given id 204355232f09SEwan Crawford AllocationDetails* alloc = FindAllocByID(strm, alloc_id); 204455232f09SEwan Crawford if (!alloc) 204555232f09SEwan Crawford return false; 204655232f09SEwan Crawford 204755232f09SEwan Crawford if (log) 204855232f09SEwan Crawford log->Printf("RenderScriptRuntime::LoadAllocation - Found allocation 0x%" PRIx64, *alloc->address.get()); 204955232f09SEwan Crawford 205055232f09SEwan Crawford // JIT all the allocation details 20518b59062aSEwan Crawford if (alloc->shouldRefresh()) 205255232f09SEwan Crawford { 205355232f09SEwan Crawford if (log) 205455232f09SEwan Crawford log->Printf("RenderScriptRuntime::LoadAllocation - Allocation details not calculated yet, jitting info"); 205555232f09SEwan Crawford 205655232f09SEwan Crawford if (!RefreshAllocation(alloc, frame_ptr)) 205755232f09SEwan Crawford { 205855232f09SEwan Crawford if (log) 205955232f09SEwan Crawford log->Printf("RenderScriptRuntime::LoadAllocation - Couldn't JIT allocation details"); 20604cfc9198SSylvestre Ledru return false; 206155232f09SEwan Crawford } 206255232f09SEwan Crawford } 206355232f09SEwan Crawford 20648b244e21SEwan Crawford assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() && alloc->element.type_vec_size.isValid() 20658b244e21SEwan Crawford && alloc->size.isValid() && alloc->element.datum_size.isValid() && "Allocation information not available"); 206655232f09SEwan Crawford 206755232f09SEwan Crawford // Check we can read from file 206855232f09SEwan Crawford FileSpec file(filename, true); 206955232f09SEwan Crawford if (!file.Exists()) 207055232f09SEwan Crawford { 207155232f09SEwan Crawford strm.Printf("Error: File %s does not exist", filename); 207255232f09SEwan Crawford strm.EOL(); 207355232f09SEwan Crawford return false; 207455232f09SEwan Crawford } 207555232f09SEwan Crawford 207655232f09SEwan Crawford if (!file.Readable()) 207755232f09SEwan Crawford { 207855232f09SEwan Crawford strm.Printf("Error: File %s does not have readable permissions", filename); 207955232f09SEwan Crawford strm.EOL(); 208055232f09SEwan Crawford return false; 208155232f09SEwan Crawford } 208255232f09SEwan Crawford 208355232f09SEwan Crawford // Read file into data buffer 208455232f09SEwan Crawford DataBufferSP data_sp(file.ReadFileContents()); 208555232f09SEwan Crawford 208655232f09SEwan Crawford // Cast start of buffer to FileHeader and use pointer to read metadata 208755232f09SEwan Crawford void* file_buffer = data_sp->GetBytes(); 208855232f09SEwan Crawford const AllocationDetails::FileHeader* head = static_cast<AllocationDetails::FileHeader*>(file_buffer); 208955232f09SEwan Crawford 209055232f09SEwan Crawford // Advance buffer past header 209155232f09SEwan Crawford file_buffer = static_cast<uint8_t*>(file_buffer) + head->hdr_size; 209255232f09SEwan Crawford 209355232f09SEwan Crawford if (log) 209455232f09SEwan Crawford log->Printf("RenderScriptRuntime::LoadAllocation - header type %u, element size %u", 209555232f09SEwan Crawford head->type, head->element_size); 209655232f09SEwan Crawford 209755232f09SEwan Crawford // Check if the target allocation and file both have the same number of bytes for an Element 20988b244e21SEwan Crawford if (*alloc->element.datum_size.get() != head->element_size) 209955232f09SEwan Crawford { 210055232f09SEwan Crawford strm.Printf("Warning: Mismatched Element sizes - file %u bytes, allocation %u bytes", 21018b244e21SEwan Crawford head->element_size, *alloc->element.datum_size.get()); 210255232f09SEwan Crawford strm.EOL(); 210355232f09SEwan Crawford } 210455232f09SEwan Crawford 210555232f09SEwan Crawford // Check if the target allocation and file both have the same integral type 21068b244e21SEwan Crawford const unsigned int type = static_cast<unsigned int>(*alloc->element.type.get()); 210755232f09SEwan Crawford if (type != head->type) 210855232f09SEwan Crawford { 21092e920715SEwan Crawford // Enum value isn't monotonous, so doesn't always index RsDataTypeToString array 21102e920715SEwan Crawford unsigned int printable_target_type_index = type; 21112e920715SEwan Crawford unsigned int printable_head_type_index = head->type; 21122e920715SEwan Crawford if (type >= Element::RS_TYPE_ELEMENT && type <= Element::RS_TYPE_FONT) 21132e920715SEwan Crawford printable_target_type_index = static_cast<Element::DataType>( 21142e920715SEwan Crawford (type - Element::RS_TYPE_ELEMENT) + Element::RS_TYPE_MATRIX_2X2 + 1); 21152e920715SEwan Crawford 21162e920715SEwan Crawford if (head->type >= Element::RS_TYPE_ELEMENT && head->type <= Element::RS_TYPE_FONT) 21172e920715SEwan Crawford printable_head_type_index = static_cast<Element::DataType>( 21182e920715SEwan Crawford (head->type - Element::RS_TYPE_ELEMENT) + Element::RS_TYPE_MATRIX_2X2 + 1); 21192e920715SEwan Crawford 21202e920715SEwan Crawford const char* file_type_cstr = AllocationDetails::RsDataTypeToString[printable_head_type_index][0]; 21212e920715SEwan Crawford const char* target_type_cstr = AllocationDetails::RsDataTypeToString[printable_target_type_index][0]; 212255232f09SEwan Crawford 212355232f09SEwan Crawford strm.Printf("Warning: Mismatched Types - file '%s' type, allocation '%s' type", 21242e920715SEwan Crawford file_type_cstr, target_type_cstr); 212555232f09SEwan Crawford strm.EOL(); 212655232f09SEwan Crawford } 212755232f09SEwan Crawford 212855232f09SEwan Crawford // Calculate size of allocation data in file 212955232f09SEwan Crawford size_t length = data_sp->GetByteSize() - head->hdr_size; 213055232f09SEwan Crawford 213155232f09SEwan Crawford // Check if the target allocation and file both have the same total data size. 213255232f09SEwan Crawford const unsigned int alloc_size = *alloc->size.get(); 213355232f09SEwan Crawford if (alloc_size != length) 213455232f09SEwan Crawford { 213555232f09SEwan Crawford strm.Printf("Warning: Mismatched allocation sizes - file 0x%" PRIx64 " bytes, allocation 0x%x bytes", 2136eba832beSJason Molenda (uint64_t) length, alloc_size); 213755232f09SEwan Crawford strm.EOL(); 213855232f09SEwan Crawford length = alloc_size < length ? alloc_size : length; // Set length to copy to minimum 213955232f09SEwan Crawford } 214055232f09SEwan Crawford 214155232f09SEwan Crawford // Copy file data from our buffer into the target allocation. 214255232f09SEwan Crawford lldb::addr_t alloc_data = *alloc->data_ptr.get(); 214355232f09SEwan Crawford Error error; 214455232f09SEwan Crawford size_t bytes_written = GetProcess()->WriteMemory(alloc_data, file_buffer, length, error); 214555232f09SEwan Crawford if (!error.Success() || bytes_written != length) 214655232f09SEwan Crawford { 214755232f09SEwan Crawford strm.Printf("Error: Couldn't write data to allocation %s", error.AsCString()); 214855232f09SEwan Crawford strm.EOL(); 214955232f09SEwan Crawford return false; 215055232f09SEwan Crawford } 215155232f09SEwan Crawford 215255232f09SEwan Crawford strm.Printf("Contents of file '%s' read into allocation %u", filename, alloc->id); 215355232f09SEwan Crawford strm.EOL(); 215455232f09SEwan Crawford 215555232f09SEwan Crawford return true; 215655232f09SEwan Crawford } 215755232f09SEwan Crawford 215855232f09SEwan Crawford // Function copies allocation contents into a binary file. 215955232f09SEwan Crawford // This file can then be loaded later into a different allocation. 216055232f09SEwan Crawford // There is a header, FileHeader, before the allocation data containing meta-data. 216155232f09SEwan Crawford bool 216255232f09SEwan Crawford RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id, const char* filename, StackFrame* frame_ptr) 216355232f09SEwan Crawford { 216455232f09SEwan Crawford Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 216555232f09SEwan Crawford 216655232f09SEwan Crawford // Find allocation with the given id 216755232f09SEwan Crawford AllocationDetails* alloc = FindAllocByID(strm, alloc_id); 216855232f09SEwan Crawford if (!alloc) 216955232f09SEwan Crawford return false; 217055232f09SEwan Crawford 217155232f09SEwan Crawford if (log) 217255232f09SEwan Crawford log->Printf("RenderScriptRuntime::SaveAllocation - Found allocation 0x%" PRIx64, *alloc->address.get()); 217355232f09SEwan Crawford 217455232f09SEwan Crawford // JIT all the allocation details 21758b59062aSEwan Crawford if (alloc->shouldRefresh()) 217655232f09SEwan Crawford { 217755232f09SEwan Crawford if (log) 217855232f09SEwan Crawford log->Printf("RenderScriptRuntime::SaveAllocation - Allocation details not calculated yet, jitting info"); 217955232f09SEwan Crawford 218055232f09SEwan Crawford if (!RefreshAllocation(alloc, frame_ptr)) 218155232f09SEwan Crawford { 218255232f09SEwan Crawford if (log) 218355232f09SEwan Crawford log->Printf("RenderScriptRuntime::SaveAllocation - Couldn't JIT allocation details"); 21844cfc9198SSylvestre Ledru return false; 218555232f09SEwan Crawford } 218655232f09SEwan Crawford } 218755232f09SEwan Crawford 21888b244e21SEwan Crawford assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() && alloc->element.type_vec_size.isValid() && alloc->element.datum_size.get() 21898b244e21SEwan Crawford && alloc->element.type_kind.isValid() && alloc->dimension.isValid() && "Allocation information not available"); 219055232f09SEwan Crawford 219155232f09SEwan Crawford // Check we can create writable file 219255232f09SEwan Crawford FileSpec file_spec(filename, true); 219355232f09SEwan Crawford File file(file_spec, File::eOpenOptionWrite | File::eOpenOptionCanCreate | File::eOpenOptionTruncate); 219455232f09SEwan Crawford if (!file) 219555232f09SEwan Crawford { 219655232f09SEwan Crawford strm.Printf("Error: Failed to open '%s' for writing", filename); 219755232f09SEwan Crawford strm.EOL(); 219855232f09SEwan Crawford return false; 219955232f09SEwan Crawford } 220055232f09SEwan Crawford 220155232f09SEwan Crawford // Read allocation into buffer of heap memory 220255232f09SEwan Crawford const std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr); 220355232f09SEwan Crawford if (!buffer) 220455232f09SEwan Crawford { 220555232f09SEwan Crawford strm.Printf("Error: Couldn't read allocation data into buffer"); 220655232f09SEwan Crawford strm.EOL(); 220755232f09SEwan Crawford return false; 220855232f09SEwan Crawford } 220955232f09SEwan Crawford 221055232f09SEwan Crawford // Create the file header 221155232f09SEwan Crawford AllocationDetails::FileHeader head; 221255232f09SEwan Crawford head.ident[0] = 'R'; head.ident[1] = 'S'; head.ident[2] = 'A'; head.ident[3] = 'D'; 221355232f09SEwan Crawford head.hdr_size = static_cast<uint16_t>(sizeof(AllocationDetails::FileHeader)); 22148b244e21SEwan Crawford head.type = static_cast<uint16_t>(*alloc->element.type.get()); 22158b244e21SEwan Crawford head.kind = static_cast<uint32_t>(*alloc->element.type_kind.get()); 22162d62328aSEwan Crawford head.dims[0] = static_cast<uint32_t>(alloc->dimension.get()->dim_1); 22172d62328aSEwan Crawford head.dims[1] = static_cast<uint32_t>(alloc->dimension.get()->dim_2); 22182d62328aSEwan Crawford head.dims[2] = static_cast<uint32_t>(alloc->dimension.get()->dim_3); 22198b244e21SEwan Crawford head.element_size = static_cast<uint32_t>(*alloc->element.datum_size.get()); 222055232f09SEwan Crawford 222155232f09SEwan Crawford // Write the file header 222255232f09SEwan Crawford size_t num_bytes = sizeof(AllocationDetails::FileHeader); 222355232f09SEwan Crawford Error err = file.Write(static_cast<const void*>(&head), num_bytes); 222455232f09SEwan Crawford if (!err.Success()) 222555232f09SEwan Crawford { 222655232f09SEwan Crawford strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), filename); 222755232f09SEwan Crawford strm.EOL(); 222855232f09SEwan Crawford return false; 222955232f09SEwan Crawford } 223055232f09SEwan Crawford 223155232f09SEwan Crawford // Write allocation data to file 223255232f09SEwan Crawford num_bytes = static_cast<size_t>(*alloc->size.get()); 223355232f09SEwan Crawford if (log) 2234*7093cccfSEwan Crawford log->Printf("RenderScriptRuntime::SaveAllocation - Writing 0x%" PRIx64 " bytes from %p", (uint64_t) num_bytes, (void*) buffer.get()); 223555232f09SEwan Crawford 223655232f09SEwan Crawford err = file.Write(buffer.get(), num_bytes); 223755232f09SEwan Crawford if (!err.Success()) 223855232f09SEwan Crawford { 223955232f09SEwan Crawford strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), filename); 224055232f09SEwan Crawford strm.EOL(); 224155232f09SEwan Crawford return false; 224255232f09SEwan Crawford } 224355232f09SEwan Crawford 224455232f09SEwan Crawford strm.Printf("Allocation written to file '%s'", filename); 224555232f09SEwan Crawford strm.EOL(); 224615f2bd95SEwan Crawford return true; 224715f2bd95SEwan Crawford } 224815f2bd95SEwan Crawford 22495ec532a9SColin Riley bool 22505ec532a9SColin Riley RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp) 22515ec532a9SColin Riley { 22524640cde1SColin Riley Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 22534640cde1SColin Riley 22545ec532a9SColin Riley if (module_sp) 22555ec532a9SColin Riley { 22565ec532a9SColin Riley for (const auto &rs_module : m_rsmodules) 22575ec532a9SColin Riley { 22584640cde1SColin Riley if (rs_module->m_module == module_sp) 22597dc7771cSEwan Crawford { 22607dc7771cSEwan Crawford // Check if the user has enabled automatically breaking on 22617dc7771cSEwan Crawford // all RS kernels. 22627dc7771cSEwan Crawford if (m_breakAllKernels) 22637dc7771cSEwan Crawford BreakOnModuleKernels(rs_module); 22647dc7771cSEwan Crawford 22655ec532a9SColin Riley return false; 22665ec532a9SColin Riley } 22677dc7771cSEwan Crawford } 2268ef20b08fSColin Riley bool module_loaded = false; 2269ef20b08fSColin Riley switch (GetModuleKind(module_sp)) 2270ef20b08fSColin Riley { 2271ef20b08fSColin Riley case eModuleKindKernelObj: 2272ef20b08fSColin Riley { 22734640cde1SColin Riley RSModuleDescriptorSP module_desc; 22744640cde1SColin Riley module_desc.reset(new RSModuleDescriptor(module_sp)); 22754640cde1SColin Riley if (module_desc->ParseRSInfo()) 22765ec532a9SColin Riley { 22775ec532a9SColin Riley m_rsmodules.push_back(module_desc); 2278ef20b08fSColin Riley module_loaded = true; 22795ec532a9SColin Riley } 22804640cde1SColin Riley if (module_loaded) 22814640cde1SColin Riley { 22824640cde1SColin Riley FixupScriptDetails(module_desc); 22834640cde1SColin Riley } 2284ef20b08fSColin Riley break; 2285ef20b08fSColin Riley } 2286ef20b08fSColin Riley case eModuleKindDriver: 22874640cde1SColin Riley { 22884640cde1SColin Riley if (!m_libRSDriver) 22894640cde1SColin Riley { 22904640cde1SColin Riley m_libRSDriver = module_sp; 22914640cde1SColin Riley LoadRuntimeHooks(m_libRSDriver, RenderScriptRuntime::eModuleKindDriver); 22924640cde1SColin Riley } 22934640cde1SColin Riley break; 22944640cde1SColin Riley } 2295ef20b08fSColin Riley case eModuleKindImpl: 22964640cde1SColin Riley { 22974640cde1SColin Riley m_libRSCpuRef = module_sp; 22984640cde1SColin Riley break; 22994640cde1SColin Riley } 2300ef20b08fSColin Riley case eModuleKindLibRS: 23014640cde1SColin Riley { 23024640cde1SColin Riley if (!m_libRS) 23034640cde1SColin Riley { 23044640cde1SColin Riley m_libRS = module_sp; 23054640cde1SColin Riley static ConstString gDbgPresentStr("gDebuggerPresent"); 23064640cde1SColin Riley const Symbol* debug_present = m_libRS->FindFirstSymbolWithNameAndType(gDbgPresentStr, eSymbolTypeData); 23074640cde1SColin Riley if (debug_present) 23084640cde1SColin Riley { 23094640cde1SColin Riley Error error; 23104640cde1SColin Riley uint32_t flag = 0x00000001U; 23114640cde1SColin Riley Target &target = GetProcess()->GetTarget(); 2312358cf1eaSGreg Clayton addr_t addr = debug_present->GetLoadAddress(&target); 23134640cde1SColin Riley GetProcess()->WriteMemory(addr, &flag, sizeof(flag), error); 23144640cde1SColin Riley if(error.Success()) 23154640cde1SColin Riley { 23164640cde1SColin Riley if (log) 23174640cde1SColin Riley log->Printf ("RenderScriptRuntime::LoadModule - Debugger present flag set on debugee"); 23184640cde1SColin Riley 23194640cde1SColin Riley m_debuggerPresentFlagged = true; 23204640cde1SColin Riley } 23214640cde1SColin Riley else if (log) 23224640cde1SColin Riley { 23234640cde1SColin Riley log->Printf ("RenderScriptRuntime::LoadModule - Error writing debugger present flags '%s' ", error.AsCString()); 23244640cde1SColin Riley } 23254640cde1SColin Riley } 23264640cde1SColin Riley else if (log) 23274640cde1SColin Riley { 23284640cde1SColin Riley log->Printf ("RenderScriptRuntime::LoadModule - Error writing debugger present flags - symbol not found"); 23294640cde1SColin Riley } 23304640cde1SColin Riley } 23314640cde1SColin Riley break; 23324640cde1SColin Riley } 2333ef20b08fSColin Riley default: 2334ef20b08fSColin Riley break; 2335ef20b08fSColin Riley } 2336ef20b08fSColin Riley if (module_loaded) 2337ef20b08fSColin Riley Update(); 2338ef20b08fSColin Riley return module_loaded; 23395ec532a9SColin Riley } 23405ec532a9SColin Riley return false; 23415ec532a9SColin Riley } 23425ec532a9SColin Riley 2343ef20b08fSColin Riley void 2344ef20b08fSColin Riley RenderScriptRuntime::Update() 2345ef20b08fSColin Riley { 2346ef20b08fSColin Riley if (m_rsmodules.size() > 0) 2347ef20b08fSColin Riley { 2348ef20b08fSColin Riley if (!m_initiated) 2349ef20b08fSColin Riley { 2350ef20b08fSColin Riley Initiate(); 2351ef20b08fSColin Riley } 2352ef20b08fSColin Riley } 2353ef20b08fSColin Riley } 2354ef20b08fSColin Riley 23555ec532a9SColin Riley // The maximum line length of an .rs.info packet 23565ec532a9SColin Riley #define MAXLINE 500 23575ec532a9SColin Riley 23585ec532a9SColin Riley // The .rs.info symbol in renderscript modules contains a string which needs to be parsed. 23595ec532a9SColin Riley // The string is basic and is parsed on a line by line basis. 23605ec532a9SColin Riley bool 23615ec532a9SColin Riley RSModuleDescriptor::ParseRSInfo() 23625ec532a9SColin Riley { 23635ec532a9SColin Riley const Symbol *info_sym = m_module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData); 23645ec532a9SColin Riley if (info_sym) 23655ec532a9SColin Riley { 2366358cf1eaSGreg Clayton const addr_t addr = info_sym->GetAddressRef().GetFileAddress(); 23675ec532a9SColin Riley const addr_t size = info_sym->GetByteSize(); 23685ec532a9SColin Riley const FileSpec fs = m_module->GetFileSpec(); 23695ec532a9SColin Riley 23705ec532a9SColin Riley DataBufferSP buffer = fs.ReadFileContents(addr, size); 23715ec532a9SColin Riley 23725ec532a9SColin Riley if (!buffer) 23735ec532a9SColin Riley return false; 23745ec532a9SColin Riley 23755ec532a9SColin Riley std::string info((const char *)buffer->GetBytes()); 23765ec532a9SColin Riley 23775ec532a9SColin Riley std::vector<std::string> info_lines; 2378e8433cc1SBruce Mitchener size_t lpos = info.find('\n'); 23795ec532a9SColin Riley while (lpos != std::string::npos) 23805ec532a9SColin Riley { 23815ec532a9SColin Riley info_lines.push_back(info.substr(0, lpos)); 23825ec532a9SColin Riley info = info.substr(lpos + 1); 2383e8433cc1SBruce Mitchener lpos = info.find('\n'); 23845ec532a9SColin Riley } 23855ec532a9SColin Riley size_t offset = 0; 23865ec532a9SColin Riley while (offset < info_lines.size()) 23875ec532a9SColin Riley { 23885ec532a9SColin Riley std::string line = info_lines[offset]; 23895ec532a9SColin Riley // Parse directives 23905ec532a9SColin Riley uint32_t numDefns = 0; 23915ec532a9SColin Riley if (sscanf(line.c_str(), "exportVarCount: %u", &numDefns) == 1) 23925ec532a9SColin Riley { 23935ec532a9SColin Riley while (numDefns--) 23944640cde1SColin Riley m_globals.push_back(RSGlobalDescriptor(this, info_lines[++offset].c_str())); 23955ec532a9SColin Riley } 23965ec532a9SColin Riley else if (sscanf(line.c_str(), "exportFuncCount: %u", &numDefns) == 1) 23975ec532a9SColin Riley { 23985ec532a9SColin Riley } 23995ec532a9SColin Riley else if (sscanf(line.c_str(), "exportForEachCount: %u", &numDefns) == 1) 24005ec532a9SColin Riley { 24015ec532a9SColin Riley char name[MAXLINE]; 24025ec532a9SColin Riley while (numDefns--) 24035ec532a9SColin Riley { 24045ec532a9SColin Riley uint32_t slot = 0; 24055ec532a9SColin Riley name[0] = '\0'; 24065ec532a9SColin Riley if (sscanf(info_lines[++offset].c_str(), "%u - %s", &slot, &name[0]) == 2) 24075ec532a9SColin Riley { 24084640cde1SColin Riley m_kernels.push_back(RSKernelDescriptor(this, name, slot)); 24094640cde1SColin Riley } 24104640cde1SColin Riley } 24114640cde1SColin Riley } 24124640cde1SColin Riley else if (sscanf(line.c_str(), "pragmaCount: %u", &numDefns) == 1) 24134640cde1SColin Riley { 24144640cde1SColin Riley char name[MAXLINE]; 24154640cde1SColin Riley char value[MAXLINE]; 24164640cde1SColin Riley while (numDefns--) 24174640cde1SColin Riley { 24184640cde1SColin Riley name[0] = '\0'; 24194640cde1SColin Riley value[0] = '\0'; 24204640cde1SColin Riley if (sscanf(info_lines[++offset].c_str(), "%s - %s", &name[0], &value[0]) != 0 24214640cde1SColin Riley && (name[0] != '\0')) 24224640cde1SColin Riley { 24234640cde1SColin Riley m_pragmas[std::string(name)] = value; 24245ec532a9SColin Riley } 24255ec532a9SColin Riley } 24265ec532a9SColin Riley } 24275ec532a9SColin Riley else if (sscanf(line.c_str(), "objectSlotCount: %u", &numDefns) == 1) 24285ec532a9SColin Riley { 24295ec532a9SColin Riley } 24305ec532a9SColin Riley 24315ec532a9SColin Riley offset++; 24325ec532a9SColin Riley } 24335ec532a9SColin Riley return m_kernels.size() > 0; 24345ec532a9SColin Riley } 24355ec532a9SColin Riley return false; 24365ec532a9SColin Riley } 24375ec532a9SColin Riley 24385ec532a9SColin Riley bool 24395ec532a9SColin Riley RenderScriptRuntime::ProbeModules(const ModuleList module_list) 24405ec532a9SColin Riley { 24415ec532a9SColin Riley bool rs_found = false; 24425ec532a9SColin Riley size_t num_modules = module_list.GetSize(); 24435ec532a9SColin Riley for (size_t i = 0; i < num_modules; i++) 24445ec532a9SColin Riley { 24455ec532a9SColin Riley auto module = module_list.GetModuleAtIndex(i); 24465ec532a9SColin Riley rs_found |= LoadModule(module); 24475ec532a9SColin Riley } 24485ec532a9SColin Riley return rs_found; 24495ec532a9SColin Riley } 24505ec532a9SColin Riley 24515ec532a9SColin Riley void 24524640cde1SColin Riley RenderScriptRuntime::Status(Stream &strm) const 24534640cde1SColin Riley { 24544640cde1SColin Riley if (m_libRS) 24554640cde1SColin Riley { 24564640cde1SColin Riley strm.Printf("Runtime Library discovered."); 24574640cde1SColin Riley strm.EOL(); 24584640cde1SColin Riley } 24594640cde1SColin Riley if (m_libRSDriver) 24604640cde1SColin Riley { 24614640cde1SColin Riley strm.Printf("Runtime Driver discovered."); 24624640cde1SColin Riley strm.EOL(); 24634640cde1SColin Riley } 24644640cde1SColin Riley if (m_libRSCpuRef) 24654640cde1SColin Riley { 24664640cde1SColin Riley strm.Printf("CPU Reference Implementation discovered."); 24674640cde1SColin Riley strm.EOL(); 24684640cde1SColin Riley } 24694640cde1SColin Riley 24704640cde1SColin Riley if (m_runtimeHooks.size()) 24714640cde1SColin Riley { 24724640cde1SColin Riley strm.Printf("Runtime functions hooked:"); 24734640cde1SColin Riley strm.EOL(); 24744640cde1SColin Riley for (auto b : m_runtimeHooks) 24754640cde1SColin Riley { 24764640cde1SColin Riley strm.Indent(b.second->defn->name); 24774640cde1SColin Riley strm.EOL(); 24784640cde1SColin Riley } 24794640cde1SColin Riley } 24804640cde1SColin Riley else 24814640cde1SColin Riley { 24824640cde1SColin Riley strm.Printf("Runtime is not hooked."); 24834640cde1SColin Riley strm.EOL(); 24844640cde1SColin Riley } 24854640cde1SColin Riley } 24864640cde1SColin Riley 24874640cde1SColin Riley void 24884640cde1SColin Riley RenderScriptRuntime::DumpContexts(Stream &strm) const 24894640cde1SColin Riley { 24904640cde1SColin Riley strm.Printf("Inferred RenderScript Contexts:"); 24914640cde1SColin Riley strm.EOL(); 24924640cde1SColin Riley strm.IndentMore(); 24934640cde1SColin Riley 24944640cde1SColin Riley std::map<addr_t, uint64_t> contextReferences; 24954640cde1SColin Riley 249678f339d1SEwan Crawford // Iterate over all of the currently discovered scripts. 249778f339d1SEwan Crawford // Note: We cant push or pop from m_scripts inside this loop or it may invalidate script. 24984640cde1SColin Riley for (const auto & script : m_scripts) 24994640cde1SColin Riley { 250078f339d1SEwan Crawford if (!script->context.isValid()) 250178f339d1SEwan Crawford continue; 250278f339d1SEwan Crawford lldb::addr_t context = *script->context; 250378f339d1SEwan Crawford 250478f339d1SEwan Crawford if (contextReferences.find(context) != contextReferences.end()) 25054640cde1SColin Riley { 250678f339d1SEwan Crawford contextReferences[context]++; 25074640cde1SColin Riley } 25084640cde1SColin Riley else 25094640cde1SColin Riley { 251078f339d1SEwan Crawford contextReferences[context] = 1; 25114640cde1SColin Riley } 25124640cde1SColin Riley } 25134640cde1SColin Riley 25144640cde1SColin Riley for (const auto& cRef : contextReferences) 25154640cde1SColin Riley { 25164640cde1SColin Riley strm.Printf("Context 0x%" PRIx64 ": %" PRIu64 " script instances", cRef.first, cRef.second); 25174640cde1SColin Riley strm.EOL(); 25184640cde1SColin Riley } 25194640cde1SColin Riley strm.IndentLess(); 25204640cde1SColin Riley } 25214640cde1SColin Riley 25224640cde1SColin Riley void 25234640cde1SColin Riley RenderScriptRuntime::DumpKernels(Stream &strm) const 25244640cde1SColin Riley { 25254640cde1SColin Riley strm.Printf("RenderScript Kernels:"); 25264640cde1SColin Riley strm.EOL(); 25274640cde1SColin Riley strm.IndentMore(); 25284640cde1SColin Riley for (const auto &module : m_rsmodules) 25294640cde1SColin Riley { 25304640cde1SColin Riley strm.Printf("Resource '%s':",module->m_resname.c_str()); 25314640cde1SColin Riley strm.EOL(); 25324640cde1SColin Riley for (const auto &kernel : module->m_kernels) 25334640cde1SColin Riley { 25344640cde1SColin Riley strm.Indent(kernel.m_name.AsCString()); 25354640cde1SColin Riley strm.EOL(); 25364640cde1SColin Riley } 25374640cde1SColin Riley } 25384640cde1SColin Riley strm.IndentLess(); 25394640cde1SColin Riley } 25404640cde1SColin Riley 2541a0f08674SEwan Crawford RenderScriptRuntime::AllocationDetails* 2542a0f08674SEwan Crawford RenderScriptRuntime::FindAllocByID(Stream &strm, const uint32_t alloc_id) 2543a0f08674SEwan Crawford { 2544a0f08674SEwan Crawford AllocationDetails* alloc = nullptr; 2545a0f08674SEwan Crawford 2546a0f08674SEwan Crawford // See if we can find allocation using id as an index; 2547a0f08674SEwan Crawford if (alloc_id <= m_allocations.size() && alloc_id != 0 2548a0f08674SEwan Crawford && m_allocations[alloc_id-1]->id == alloc_id) 2549a0f08674SEwan Crawford { 2550a0f08674SEwan Crawford alloc = m_allocations[alloc_id-1].get(); 2551a0f08674SEwan Crawford return alloc; 2552a0f08674SEwan Crawford } 2553a0f08674SEwan Crawford 2554a0f08674SEwan Crawford // Fallback to searching 2555a0f08674SEwan Crawford for (const auto & a : m_allocations) 2556a0f08674SEwan Crawford { 2557a0f08674SEwan Crawford if (a->id == alloc_id) 2558a0f08674SEwan Crawford { 2559a0f08674SEwan Crawford alloc = a.get(); 2560a0f08674SEwan Crawford break; 2561a0f08674SEwan Crawford } 2562a0f08674SEwan Crawford } 2563a0f08674SEwan Crawford 2564a0f08674SEwan Crawford if (alloc == nullptr) 2565a0f08674SEwan Crawford { 2566a0f08674SEwan Crawford strm.Printf("Error: Couldn't find allocation with id matching %u", alloc_id); 2567a0f08674SEwan Crawford strm.EOL(); 2568a0f08674SEwan Crawford } 2569a0f08674SEwan Crawford 2570a0f08674SEwan Crawford return alloc; 2571a0f08674SEwan Crawford } 2572a0f08674SEwan Crawford 2573a0f08674SEwan Crawford // Prints the contents of an allocation to the output stream, which may be a file 2574a0f08674SEwan Crawford bool 2575a0f08674SEwan Crawford RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame* frame_ptr, const uint32_t id) 2576a0f08674SEwan Crawford { 2577a0f08674SEwan Crawford Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 2578a0f08674SEwan Crawford 2579a0f08674SEwan Crawford // Check we can find the desired allocation 2580a0f08674SEwan Crawford AllocationDetails* alloc = FindAllocByID(strm, id); 2581a0f08674SEwan Crawford if (!alloc) 2582a0f08674SEwan Crawford return false; // FindAllocByID() will print error message for us here 2583a0f08674SEwan Crawford 2584a0f08674SEwan Crawford if (log) 2585a0f08674SEwan Crawford log->Printf("RenderScriptRuntime::DumpAllocation - Found allocation 0x%" PRIx64, *alloc->address.get()); 2586a0f08674SEwan Crawford 2587a0f08674SEwan Crawford // Check we have information about the allocation, if not calculate it 25888b59062aSEwan Crawford if (alloc->shouldRefresh()) 2589a0f08674SEwan Crawford { 2590a0f08674SEwan Crawford if (log) 2591a0f08674SEwan Crawford log->Printf("RenderScriptRuntime::DumpAllocation - Allocation details not calculated yet, jitting info"); 2592a0f08674SEwan Crawford 2593a0f08674SEwan Crawford // JIT all the allocation information 2594a0f08674SEwan Crawford if (!RefreshAllocation(alloc, frame_ptr)) 2595a0f08674SEwan Crawford { 2596a0f08674SEwan Crawford strm.Printf("Error: Couldn't JIT allocation details"); 2597a0f08674SEwan Crawford strm.EOL(); 2598a0f08674SEwan Crawford return false; 2599a0f08674SEwan Crawford } 2600a0f08674SEwan Crawford } 2601a0f08674SEwan Crawford 2602a0f08674SEwan Crawford // Establish format and size of each data element 26038b244e21SEwan Crawford const unsigned int vec_size = *alloc->element.type_vec_size.get(); 26048b244e21SEwan Crawford const Element::DataType type = *alloc->element.type.get(); 2605a0f08674SEwan Crawford 26062e920715SEwan Crawford assert(type >= Element::RS_TYPE_NONE && type <= Element::RS_TYPE_FONT 2607a0f08674SEwan Crawford && "Invalid allocation type"); 2608a0f08674SEwan Crawford 26092e920715SEwan Crawford lldb::Format format; 26102e920715SEwan Crawford if (type >= Element::RS_TYPE_ELEMENT) 26112e920715SEwan Crawford format = eFormatHex; 26122e920715SEwan Crawford else 26132e920715SEwan Crawford format = vec_size == 1 ? static_cast<lldb::Format>(AllocationDetails::RSTypeToFormat[type][eFormatSingle]) 2614a0f08674SEwan Crawford : static_cast<lldb::Format>(AllocationDetails::RSTypeToFormat[type][eFormatVector]); 2615a0f08674SEwan Crawford 26168b244e21SEwan Crawford const unsigned int data_size = *alloc->element.datum_size.get(); 2617a0f08674SEwan Crawford 2618a0f08674SEwan Crawford if (log) 26198b244e21SEwan Crawford log->Printf("RenderScriptRuntime::DumpAllocation - Element size %u bytes, including padding", data_size); 2620a0f08674SEwan Crawford 262155232f09SEwan Crawford // Allocate a buffer to copy data into 262255232f09SEwan Crawford std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr); 262355232f09SEwan Crawford if (!buffer) 262455232f09SEwan Crawford { 26252e920715SEwan Crawford strm.Printf("Error: Couldn't read allocation data"); 262655232f09SEwan Crawford strm.EOL(); 262755232f09SEwan Crawford return false; 262855232f09SEwan Crawford } 262955232f09SEwan Crawford 2630a0f08674SEwan Crawford // Calculate stride between rows as there may be padding at end of rows since 2631a0f08674SEwan Crawford // allocated memory is 16-byte aligned 2632a0f08674SEwan Crawford if (!alloc->stride.isValid()) 2633a0f08674SEwan Crawford { 2634a0f08674SEwan Crawford if (alloc->dimension.get()->dim_2 == 0) // We only have one dimension 2635a0f08674SEwan Crawford alloc->stride = 0; 2636a0f08674SEwan Crawford else if (!JITAllocationStride(alloc, frame_ptr)) 2637a0f08674SEwan Crawford { 2638a0f08674SEwan Crawford strm.Printf("Error: Couldn't calculate allocation row stride"); 2639a0f08674SEwan Crawford strm.EOL(); 2640a0f08674SEwan Crawford return false; 2641a0f08674SEwan Crawford } 2642a0f08674SEwan Crawford } 2643a0f08674SEwan Crawford const unsigned int stride = *alloc->stride.get(); 26448b244e21SEwan Crawford const unsigned int size = *alloc->size.get(); // Size of whole allocation 26458b244e21SEwan Crawford const unsigned int padding = alloc->element.padding.isValid() ? *alloc->element.padding.get() : 0; 2646a0f08674SEwan Crawford if (log) 26478b244e21SEwan Crawford log->Printf("RenderScriptRuntime::DumpAllocation - stride %u bytes, size %u bytes, padding %u", stride, size, padding); 2648a0f08674SEwan Crawford 2649a0f08674SEwan Crawford // Find dimensions used to index loops, so need to be non-zero 2650a0f08674SEwan Crawford unsigned int dim_x = alloc->dimension.get()->dim_1; 2651a0f08674SEwan Crawford dim_x = dim_x == 0 ? 1 : dim_x; 2652a0f08674SEwan Crawford 2653a0f08674SEwan Crawford unsigned int dim_y = alloc->dimension.get()->dim_2; 2654a0f08674SEwan Crawford dim_y = dim_y == 0 ? 1 : dim_y; 2655a0f08674SEwan Crawford 2656a0f08674SEwan Crawford unsigned int dim_z = alloc->dimension.get()->dim_3; 2657a0f08674SEwan Crawford dim_z = dim_z == 0 ? 1 : dim_z; 2658a0f08674SEwan Crawford 265955232f09SEwan Crawford // Use data extractor to format output 266055232f09SEwan Crawford const uint32_t archByteSize = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize(); 266155232f09SEwan Crawford DataExtractor alloc_data(buffer.get(), size, GetProcess()->GetByteOrder(), archByteSize); 266255232f09SEwan Crawford 2663a0f08674SEwan Crawford unsigned int offset = 0; // Offset in buffer to next element to be printed 2664a0f08674SEwan Crawford unsigned int prev_row = 0; // Offset to the start of the previous row 2665a0f08674SEwan Crawford 2666a0f08674SEwan Crawford // Iterate over allocation dimensions, printing results to user 2667a0f08674SEwan Crawford strm.Printf("Data (X, Y, Z):"); 2668a0f08674SEwan Crawford for (unsigned int z = 0; z < dim_z; ++z) 2669a0f08674SEwan Crawford { 2670a0f08674SEwan Crawford for (unsigned int y = 0; y < dim_y; ++y) 2671a0f08674SEwan Crawford { 2672a0f08674SEwan Crawford // Use stride to index start of next row. 2673a0f08674SEwan Crawford if (!(y==0 && z==0)) 2674a0f08674SEwan Crawford offset = prev_row + stride; 2675a0f08674SEwan Crawford prev_row = offset; 2676a0f08674SEwan Crawford 2677a0f08674SEwan Crawford // Print each element in the row individually 2678a0f08674SEwan Crawford for (unsigned int x = 0; x < dim_x; ++x) 2679a0f08674SEwan Crawford { 2680a0f08674SEwan Crawford strm.Printf("\n(%u, %u, %u) = ", x, y, z); 26818b244e21SEwan Crawford if ((type == Element::RS_TYPE_NONE) && (alloc->element.children.size() > 0) && 2682fe06b5adSAdrian McCarthy (alloc->element.type_name != Element::GetFallbackStructName())) 26838b244e21SEwan Crawford { 26848b244e21SEwan Crawford // Here we are dumping an Element of struct type. 26858b244e21SEwan Crawford // This is done using expression evaluation with the name of the struct type and pointer to element. 26868b244e21SEwan Crawford 26878b244e21SEwan Crawford // Don't print the name of the resulting expression, since this will be '$[0-9]+' 26888b244e21SEwan Crawford DumpValueObjectOptions expr_options; 26898b244e21SEwan Crawford expr_options.SetHideName(true); 26908b244e21SEwan Crawford 26918b244e21SEwan Crawford // Setup expression as derefrencing a pointer cast to element address. 2692b1651b8dSEwan Crawford char expr_char_buffer[jit_max_expr_size]; 2693b1651b8dSEwan Crawford int chars_written = snprintf(expr_char_buffer, jit_max_expr_size, "*(%s*) 0x%" PRIx64, 26948b244e21SEwan Crawford alloc->element.type_name.AsCString(), *alloc->data_ptr.get() + offset); 26958b244e21SEwan Crawford 2696b1651b8dSEwan Crawford if (chars_written < 0 || chars_written >= jit_max_expr_size) 26978b244e21SEwan Crawford { 26988b244e21SEwan Crawford if (log) 26998b244e21SEwan Crawford log->Printf("RenderScriptRuntime::DumpAllocation- Error in snprintf()"); 27008b244e21SEwan Crawford continue; 27018b244e21SEwan Crawford } 27028b244e21SEwan Crawford 27038b244e21SEwan Crawford // Evaluate expression 27048b244e21SEwan Crawford ValueObjectSP expr_result; 27058b244e21SEwan Crawford GetProcess()->GetTarget().EvaluateExpression(expr_char_buffer, frame_ptr, expr_result); 27068b244e21SEwan Crawford 27078b244e21SEwan Crawford // Print the results to our stream. 27088b244e21SEwan Crawford expr_result->Dump(strm, expr_options); 27098b244e21SEwan Crawford } 27108b244e21SEwan Crawford else 27118b244e21SEwan Crawford { 27128b244e21SEwan Crawford alloc_data.Dump(&strm, offset, format, data_size - padding, 1, 1, LLDB_INVALID_ADDRESS, 0, 0); 27138b244e21SEwan Crawford } 27148b244e21SEwan Crawford offset += data_size; 2715a0f08674SEwan Crawford } 2716a0f08674SEwan Crawford } 2717a0f08674SEwan Crawford } 2718a0f08674SEwan Crawford strm.EOL(); 2719a0f08674SEwan Crawford 2720a0f08674SEwan Crawford return true; 2721a0f08674SEwan Crawford } 2722a0f08674SEwan Crawford 272315f2bd95SEwan Crawford // Prints infomation regarding all the currently loaded allocations. 272415f2bd95SEwan Crawford // These details are gathered by jitting the runtime, which has as latency. 272515f2bd95SEwan Crawford void 272615f2bd95SEwan Crawford RenderScriptRuntime::ListAllocations(Stream &strm, StackFrame* frame_ptr, bool recompute) 272715f2bd95SEwan Crawford { 272815f2bd95SEwan Crawford strm.Printf("RenderScript Allocations:"); 272915f2bd95SEwan Crawford strm.EOL(); 273015f2bd95SEwan Crawford strm.IndentMore(); 273115f2bd95SEwan Crawford 273215f2bd95SEwan Crawford for (auto &alloc : m_allocations) 273315f2bd95SEwan Crawford { 273415f2bd95SEwan Crawford // JIT the allocation info if we haven't done it, or the user forces us to. 27358b59062aSEwan Crawford bool do_refresh = alloc->shouldRefresh() || recompute; 273615f2bd95SEwan Crawford 273715f2bd95SEwan Crawford // JIT current allocation information 273815f2bd95SEwan Crawford if (do_refresh && !RefreshAllocation(alloc.get(), frame_ptr)) 273915f2bd95SEwan Crawford { 274015f2bd95SEwan Crawford strm.Printf("Error: Couldn't evaluate details for allocation %u\n", alloc->id); 274115f2bd95SEwan Crawford continue; 274215f2bd95SEwan Crawford } 274315f2bd95SEwan Crawford 274415f2bd95SEwan Crawford strm.Printf("%u:\n",alloc->id); 274515f2bd95SEwan Crawford strm.IndentMore(); 274615f2bd95SEwan Crawford 274715f2bd95SEwan Crawford strm.Indent("Context: "); 274815f2bd95SEwan Crawford if (!alloc->context.isValid()) 274915f2bd95SEwan Crawford strm.Printf("unknown\n"); 275015f2bd95SEwan Crawford else 275115f2bd95SEwan Crawford strm.Printf("0x%" PRIx64 "\n", *alloc->context.get()); 275215f2bd95SEwan Crawford 275315f2bd95SEwan Crawford strm.Indent("Address: "); 275415f2bd95SEwan Crawford if (!alloc->address.isValid()) 275515f2bd95SEwan Crawford strm.Printf("unknown\n"); 275615f2bd95SEwan Crawford else 275715f2bd95SEwan Crawford strm.Printf("0x%" PRIx64 "\n", *alloc->address.get()); 275815f2bd95SEwan Crawford 275915f2bd95SEwan Crawford strm.Indent("Data pointer: "); 276015f2bd95SEwan Crawford if (!alloc->data_ptr.isValid()) 276115f2bd95SEwan Crawford strm.Printf("unknown\n"); 276215f2bd95SEwan Crawford else 276315f2bd95SEwan Crawford strm.Printf("0x%" PRIx64 "\n", *alloc->data_ptr.get()); 276415f2bd95SEwan Crawford 276515f2bd95SEwan Crawford strm.Indent("Dimensions: "); 276615f2bd95SEwan Crawford if (!alloc->dimension.isValid()) 276715f2bd95SEwan Crawford strm.Printf("unknown\n"); 276815f2bd95SEwan Crawford else 276915f2bd95SEwan Crawford strm.Printf("(%d, %d, %d)\n", alloc->dimension.get()->dim_1, 277015f2bd95SEwan Crawford alloc->dimension.get()->dim_2, 277115f2bd95SEwan Crawford alloc->dimension.get()->dim_3); 277215f2bd95SEwan Crawford 277315f2bd95SEwan Crawford strm.Indent("Data Type: "); 27748b244e21SEwan Crawford if (!alloc->element.type.isValid() || !alloc->element.type_vec_size.isValid()) 277515f2bd95SEwan Crawford strm.Printf("unknown\n"); 277615f2bd95SEwan Crawford else 277715f2bd95SEwan Crawford { 27788b244e21SEwan Crawford const int vector_size = *alloc->element.type_vec_size.get(); 27792e920715SEwan Crawford Element::DataType type = *alloc->element.type.get(); 278015f2bd95SEwan Crawford 27818b244e21SEwan Crawford if (!alloc->element.type_name.IsEmpty()) 27828b244e21SEwan Crawford strm.Printf("%s\n", alloc->element.type_name.AsCString()); 27832e920715SEwan Crawford else 27842e920715SEwan Crawford { 27852e920715SEwan Crawford // Enum value isn't monotonous, so doesn't always index RsDataTypeToString array 27862e920715SEwan Crawford if (type >= Element::RS_TYPE_ELEMENT && type <= Element::RS_TYPE_FONT) 27872e920715SEwan Crawford type = static_cast<Element::DataType>((type - Element::RS_TYPE_ELEMENT) + Element::RS_TYPE_MATRIX_2X2 + 1); 27882e920715SEwan Crawford 27892e920715SEwan Crawford if (type >= (sizeof(AllocationDetails::RsDataTypeToString) / sizeof(AllocationDetails::RsDataTypeToString[0])) 27902e920715SEwan Crawford || vector_size > 4 || vector_size < 1) 279115f2bd95SEwan Crawford strm.Printf("invalid type\n"); 279215f2bd95SEwan Crawford else 279315f2bd95SEwan Crawford strm.Printf("%s\n", AllocationDetails::RsDataTypeToString[static_cast<unsigned int>(type)][vector_size-1]); 279415f2bd95SEwan Crawford } 27952e920715SEwan Crawford } 279615f2bd95SEwan Crawford 279715f2bd95SEwan Crawford strm.Indent("Data Kind: "); 27988b244e21SEwan Crawford if (!alloc->element.type_kind.isValid()) 279915f2bd95SEwan Crawford strm.Printf("unknown\n"); 280015f2bd95SEwan Crawford else 280115f2bd95SEwan Crawford { 28028b244e21SEwan Crawford const Element::DataKind kind = *alloc->element.type_kind.get(); 28038b244e21SEwan Crawford if (kind < Element::RS_KIND_USER || kind > Element::RS_KIND_PIXEL_YUV) 280415f2bd95SEwan Crawford strm.Printf("invalid kind\n"); 280515f2bd95SEwan Crawford else 280615f2bd95SEwan Crawford strm.Printf("%s\n", AllocationDetails::RsDataKindToString[static_cast<unsigned int>(kind)]); 280715f2bd95SEwan Crawford } 280815f2bd95SEwan Crawford 280915f2bd95SEwan Crawford strm.EOL(); 281015f2bd95SEwan Crawford strm.IndentLess(); 281115f2bd95SEwan Crawford } 281215f2bd95SEwan Crawford strm.IndentLess(); 281315f2bd95SEwan Crawford } 281415f2bd95SEwan Crawford 28157dc7771cSEwan Crawford // Set breakpoints on every kernel found in RS module 28167dc7771cSEwan Crawford void 28177dc7771cSEwan Crawford RenderScriptRuntime::BreakOnModuleKernels(const RSModuleDescriptorSP rsmodule_sp) 28187dc7771cSEwan Crawford { 28197dc7771cSEwan Crawford for (const auto &kernel : rsmodule_sp->m_kernels) 28207dc7771cSEwan Crawford { 28217dc7771cSEwan Crawford // Don't set breakpoint on 'root' kernel 28227dc7771cSEwan Crawford if (strcmp(kernel.m_name.AsCString(), "root") == 0) 28237dc7771cSEwan Crawford continue; 28247dc7771cSEwan Crawford 28257dc7771cSEwan Crawford CreateKernelBreakpoint(kernel.m_name); 28267dc7771cSEwan Crawford } 28277dc7771cSEwan Crawford } 28287dc7771cSEwan Crawford 28297dc7771cSEwan Crawford // Method is internally called by the 'kernel breakpoint all' command to 28307dc7771cSEwan Crawford // enable or disable breaking on all kernels. 28317dc7771cSEwan Crawford // 28327dc7771cSEwan Crawford // When do_break is true we want to enable this functionality. 28337dc7771cSEwan Crawford // When do_break is false we want to disable it. 28347dc7771cSEwan Crawford void 28357dc7771cSEwan Crawford RenderScriptRuntime::SetBreakAllKernels(bool do_break, TargetSP target) 28367dc7771cSEwan Crawford { 283754782db7SEwan Crawford Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS)); 28387dc7771cSEwan Crawford 28397dc7771cSEwan Crawford InitSearchFilter(target); 28407dc7771cSEwan Crawford 28417dc7771cSEwan Crawford // Set breakpoints on all the kernels 28427dc7771cSEwan Crawford if (do_break && !m_breakAllKernels) 28437dc7771cSEwan Crawford { 28447dc7771cSEwan Crawford m_breakAllKernels = true; 28457dc7771cSEwan Crawford 28467dc7771cSEwan Crawford for (const auto &module : m_rsmodules) 28477dc7771cSEwan Crawford BreakOnModuleKernels(module); 28487dc7771cSEwan Crawford 28497dc7771cSEwan Crawford if (log) 28507dc7771cSEwan Crawford log->Printf("RenderScriptRuntime::SetBreakAllKernels(True)" 28517dc7771cSEwan Crawford "- breakpoints set on all currently loaded kernels"); 28527dc7771cSEwan Crawford } 28537dc7771cSEwan Crawford else if (!do_break && m_breakAllKernels) // Breakpoints won't be set on any new kernels. 28547dc7771cSEwan Crawford { 28557dc7771cSEwan Crawford m_breakAllKernels = false; 28567dc7771cSEwan Crawford 28577dc7771cSEwan Crawford if (log) 28587dc7771cSEwan Crawford log->Printf("RenderScriptRuntime::SetBreakAllKernels(False) - breakpoints no longer automatically set"); 28597dc7771cSEwan Crawford } 28607dc7771cSEwan Crawford } 28617dc7771cSEwan Crawford 28627dc7771cSEwan Crawford // Given the name of a kernel this function creates a breakpoint using our 28637dc7771cSEwan Crawford // own breakpoint resolver, and returns the Breakpoint shared pointer. 28647dc7771cSEwan Crawford BreakpointSP 28657dc7771cSEwan Crawford RenderScriptRuntime::CreateKernelBreakpoint(const ConstString& name) 28667dc7771cSEwan Crawford { 286754782db7SEwan Crawford Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS)); 28687dc7771cSEwan Crawford 28697dc7771cSEwan Crawford if (!m_filtersp) 28707dc7771cSEwan Crawford { 28717dc7771cSEwan Crawford if (log) 28727dc7771cSEwan Crawford log->Printf("RenderScriptRuntime::CreateKernelBreakpoint - Error: No breakpoint search filter set"); 28737dc7771cSEwan Crawford return nullptr; 28747dc7771cSEwan Crawford } 28757dc7771cSEwan Crawford 28767dc7771cSEwan Crawford BreakpointResolverSP resolver_sp(new RSBreakpointResolver(nullptr, name)); 28777dc7771cSEwan Crawford BreakpointSP bp = GetProcess()->GetTarget().CreateBreakpoint(m_filtersp, resolver_sp, false, false, false); 28787dc7771cSEwan Crawford 287954782db7SEwan Crawford // Give RS breakpoints a specific name, so the user can manipulate them as a group. 288054782db7SEwan Crawford Error err; 288154782db7SEwan Crawford if (!bp->AddName("RenderScriptKernel", err) && log) 288254782db7SEwan Crawford log->Printf("RenderScriptRuntime::CreateKernelBreakpoint: Error setting break name, %s", err.AsCString()); 288354782db7SEwan Crawford 28847dc7771cSEwan Crawford return bp; 28857dc7771cSEwan Crawford } 28867dc7771cSEwan Crawford 2887018f5a7eSEwan Crawford // Given an expression for a variable this function tries to calculate the variable's value. 2888018f5a7eSEwan Crawford // If this is possible it returns true and sets the uint64_t parameter to the variables unsigned value. 2889018f5a7eSEwan Crawford // Otherwise function returns false. 2890018f5a7eSEwan Crawford bool 2891018f5a7eSEwan Crawford RenderScriptRuntime::GetFrameVarAsUnsigned(const StackFrameSP frame_sp, const char* var_name, uint64_t& val) 2892018f5a7eSEwan Crawford { 2893018f5a7eSEwan Crawford Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE)); 2894018f5a7eSEwan Crawford Error error; 2895018f5a7eSEwan Crawford VariableSP var_sp; 2896018f5a7eSEwan Crawford 2897018f5a7eSEwan Crawford // Find variable in stack frame 2898018f5a7eSEwan Crawford ValueObjectSP value_sp(frame_sp->GetValueForVariableExpressionPath(var_name, 2899018f5a7eSEwan Crawford eNoDynamicValues, 2900018f5a7eSEwan Crawford StackFrame::eExpressionPathOptionCheckPtrVsMember | 2901018f5a7eSEwan Crawford StackFrame::eExpressionPathOptionsAllowDirectIVarAccess, 2902018f5a7eSEwan Crawford var_sp, 2903018f5a7eSEwan Crawford error)); 2904018f5a7eSEwan Crawford if (!error.Success()) 2905018f5a7eSEwan Crawford { 2906018f5a7eSEwan Crawford if (log) 2907018f5a7eSEwan Crawford log->Printf("RenderScriptRuntime::GetFrameVarAsUnsigned - Error, couldn't find '%s' in frame", var_name); 2908018f5a7eSEwan Crawford 2909018f5a7eSEwan Crawford return false; 2910018f5a7eSEwan Crawford } 2911018f5a7eSEwan Crawford 2912018f5a7eSEwan Crawford // Find the unsigned int value for the variable 2913018f5a7eSEwan Crawford bool success = false; 2914018f5a7eSEwan Crawford val = value_sp->GetValueAsUnsigned(0, &success); 2915018f5a7eSEwan Crawford if (!success) 2916018f5a7eSEwan Crawford { 2917018f5a7eSEwan Crawford if (log) 2918018f5a7eSEwan Crawford log->Printf("RenderScriptRuntime::GetFrameVarAsUnsigned - Error, couldn't parse '%s' as an unsigned int", var_name); 2919018f5a7eSEwan Crawford 2920018f5a7eSEwan Crawford return false; 2921018f5a7eSEwan Crawford } 2922018f5a7eSEwan Crawford 2923018f5a7eSEwan Crawford return true; 2924018f5a7eSEwan Crawford } 2925018f5a7eSEwan Crawford 2926018f5a7eSEwan Crawford // Callback when a kernel breakpoint hits and we're looking for a specific coordinate. 2927018f5a7eSEwan Crawford // Baton parameter contains a pointer to the target coordinate we want to break on. 2928018f5a7eSEwan Crawford // Function then checks the .expand frame for the current coordinate and breaks to user if it matches. 2929018f5a7eSEwan Crawford // Parameter 'break_id' is the id of the Breakpoint which made the callback. 2930018f5a7eSEwan Crawford // Parameter 'break_loc_id' is the id for the BreakpointLocation which was hit, 2931018f5a7eSEwan Crawford // a single logical breakpoint can have multiple addresses. 2932018f5a7eSEwan Crawford bool 2933018f5a7eSEwan Crawford RenderScriptRuntime::KernelBreakpointHit(void *baton, StoppointCallbackContext *ctx, 2934018f5a7eSEwan Crawford user_id_t break_id, user_id_t break_loc_id) 2935018f5a7eSEwan Crawford { 2936018f5a7eSEwan Crawford Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS)); 2937018f5a7eSEwan Crawford 2938018f5a7eSEwan Crawford assert(baton && "Error: null baton in conditional kernel breakpoint callback"); 2939018f5a7eSEwan Crawford 2940018f5a7eSEwan Crawford // Coordinate we want to stop on 2941018f5a7eSEwan Crawford const int* target_coord = static_cast<const int*>(baton); 2942018f5a7eSEwan Crawford 2943018f5a7eSEwan Crawford if (log) 2944018f5a7eSEwan Crawford log->Printf("RenderScriptRuntime::KernelBreakpointHit - Break ID %" PRIu64 ", target coord (%d, %d, %d)", 2945018f5a7eSEwan Crawford break_id, target_coord[0], target_coord[1], target_coord[2]); 2946018f5a7eSEwan Crawford 2947018f5a7eSEwan Crawford // Go up one stack frame to .expand kernel 2948018f5a7eSEwan Crawford ExecutionContext context(ctx->exe_ctx_ref); 2949018f5a7eSEwan Crawford ThreadSP thread_sp = context.GetThreadSP(); 2950018f5a7eSEwan Crawford if (!thread_sp->SetSelectedFrameByIndex(1)) 2951018f5a7eSEwan Crawford { 2952018f5a7eSEwan Crawford if (log) 2953018f5a7eSEwan Crawford log->Printf("RenderScriptRuntime::KernelBreakpointHit - Error, couldn't go up stack frame"); 2954018f5a7eSEwan Crawford 2955018f5a7eSEwan Crawford return false; 2956018f5a7eSEwan Crawford } 2957018f5a7eSEwan Crawford 2958018f5a7eSEwan Crawford StackFrameSP frame_sp = thread_sp->GetSelectedFrame(); 2959018f5a7eSEwan Crawford if (!frame_sp) 2960018f5a7eSEwan Crawford { 2961018f5a7eSEwan Crawford if (log) 2962018f5a7eSEwan Crawford log->Printf("RenderScriptRuntime::KernelBreakpointHit - Error, couldn't select .expand stack frame"); 2963018f5a7eSEwan Crawford 2964018f5a7eSEwan Crawford return false; 2965018f5a7eSEwan Crawford } 2966018f5a7eSEwan Crawford 2967018f5a7eSEwan Crawford // Get values for variables in .expand frame that tell us the current kernel invocation 2968018f5a7eSEwan Crawford const char* coord_expressions[] = {"rsIndex", "p->current.y", "p->current.z"}; 2969018f5a7eSEwan Crawford uint64_t current_coord[3] = {0, 0, 0}; 2970018f5a7eSEwan Crawford 2971018f5a7eSEwan Crawford for(int i = 0; i < 3; ++i) 2972018f5a7eSEwan Crawford { 2973018f5a7eSEwan Crawford if (!GetFrameVarAsUnsigned(frame_sp, coord_expressions[i], current_coord[i])) 2974018f5a7eSEwan Crawford return false; 2975018f5a7eSEwan Crawford 2976018f5a7eSEwan Crawford if (log) 2977018f5a7eSEwan Crawford log->Printf("RenderScriptRuntime::KernelBreakpointHit, %s = %" PRIu64, coord_expressions[i], current_coord[i]); 2978018f5a7eSEwan Crawford } 2979018f5a7eSEwan Crawford 2980018f5a7eSEwan Crawford // Check if the current kernel invocation coordinate matches our target coordinate 2981018f5a7eSEwan Crawford if (current_coord[0] == static_cast<uint64_t>(target_coord[0]) && 2982018f5a7eSEwan Crawford current_coord[1] == static_cast<uint64_t>(target_coord[1]) && 2983018f5a7eSEwan Crawford current_coord[2] == static_cast<uint64_t>(target_coord[2])) 2984018f5a7eSEwan Crawford { 2985018f5a7eSEwan Crawford if (log) 2986018f5a7eSEwan Crawford log->Printf("RenderScriptRuntime::KernelBreakpointHit, BREAKING %" PRIu64 ", %" PRIu64 ", %" PRIu64, 2987018f5a7eSEwan Crawford current_coord[0], current_coord[1], current_coord[2]); 2988018f5a7eSEwan Crawford 2989018f5a7eSEwan Crawford BreakpointSP breakpoint_sp = context.GetTargetPtr()->GetBreakpointByID(break_id); 2990018f5a7eSEwan Crawford assert(breakpoint_sp != nullptr && "Error: Couldn't find breakpoint matching break id for callback"); 2991018f5a7eSEwan Crawford breakpoint_sp->SetEnabled(false); // Optimise since conditional breakpoint should only be hit once. 2992018f5a7eSEwan Crawford return true; 2993018f5a7eSEwan Crawford } 2994018f5a7eSEwan Crawford 2995018f5a7eSEwan Crawford // No match on coordinate 2996018f5a7eSEwan Crawford return false; 2997018f5a7eSEwan Crawford } 2998018f5a7eSEwan Crawford 2999018f5a7eSEwan Crawford // Tries to set a breakpoint on the start of a kernel, resolved using the kernel name. 3000018f5a7eSEwan Crawford // Argument 'coords', represents a three dimensional coordinate which can be used to specify 3001018f5a7eSEwan Crawford // a single kernel instance to break on. If this is set then we add a callback to the breakpoint. 30024640cde1SColin Riley void 3003018f5a7eSEwan Crawford RenderScriptRuntime::PlaceBreakpointOnKernel(Stream &strm, const char* name, const std::array<int,3> coords, 3004018f5a7eSEwan Crawford Error& error, TargetSP target) 30054640cde1SColin Riley { 30064640cde1SColin Riley if (!name) 30074640cde1SColin Riley { 30084640cde1SColin Riley error.SetErrorString("invalid kernel name"); 30094640cde1SColin Riley return; 30104640cde1SColin Riley } 30114640cde1SColin Riley 30127dc7771cSEwan Crawford InitSearchFilter(target); 301398156583SEwan Crawford 30144640cde1SColin Riley ConstString kernel_name(name); 30157dc7771cSEwan Crawford BreakpointSP bp = CreateKernelBreakpoint(kernel_name); 3016018f5a7eSEwan Crawford 3017018f5a7eSEwan Crawford // We have a conditional breakpoint on a specific coordinate 3018018f5a7eSEwan Crawford if (coords[0] != -1) 3019018f5a7eSEwan Crawford { 3020018f5a7eSEwan Crawford strm.Printf("Conditional kernel breakpoint on coordinate %d, %d, %d", coords[0], coords[1], coords[2]); 3021018f5a7eSEwan Crawford strm.EOL(); 3022018f5a7eSEwan Crawford 3023018f5a7eSEwan Crawford // Allocate memory for the baton, and copy over coordinate 3024018f5a7eSEwan Crawford int* baton = new int[3]; 3025018f5a7eSEwan Crawford baton[0] = coords[0]; baton[1] = coords[1]; baton[2] = coords[2]; 3026018f5a7eSEwan Crawford 3027018f5a7eSEwan Crawford // Create a callback that will be invoked everytime the breakpoint is hit. 3028018f5a7eSEwan Crawford // The baton object passed to the handler is the target coordinate we want to break on. 3029018f5a7eSEwan Crawford bp->SetCallback(KernelBreakpointHit, baton, true); 3030018f5a7eSEwan Crawford 3031018f5a7eSEwan Crawford // Store a shared pointer to the baton, so the memory will eventually be cleaned up after destruction 3032018f5a7eSEwan Crawford m_conditional_breaks[bp->GetID()] = std::shared_ptr<int>(baton); 3033018f5a7eSEwan Crawford } 3034018f5a7eSEwan Crawford 303598156583SEwan Crawford if (bp) 303698156583SEwan Crawford bp->GetDescription(&strm, lldb::eDescriptionLevelInitial, false); 30374640cde1SColin Riley } 30384640cde1SColin Riley 30394640cde1SColin Riley void 30405ec532a9SColin Riley RenderScriptRuntime::DumpModules(Stream &strm) const 30415ec532a9SColin Riley { 30425ec532a9SColin Riley strm.Printf("RenderScript Modules:"); 30435ec532a9SColin Riley strm.EOL(); 30445ec532a9SColin Riley strm.IndentMore(); 30455ec532a9SColin Riley for (const auto &module : m_rsmodules) 30465ec532a9SColin Riley { 30474640cde1SColin Riley module->Dump(strm); 30485ec532a9SColin Riley } 30495ec532a9SColin Riley strm.IndentLess(); 30505ec532a9SColin Riley } 30515ec532a9SColin Riley 305278f339d1SEwan Crawford RenderScriptRuntime::ScriptDetails* 305378f339d1SEwan Crawford RenderScriptRuntime::LookUpScript(addr_t address, bool create) 305478f339d1SEwan Crawford { 305578f339d1SEwan Crawford for (const auto & s : m_scripts) 305678f339d1SEwan Crawford { 305778f339d1SEwan Crawford if (s->script.isValid()) 305878f339d1SEwan Crawford if (*s->script == address) 305978f339d1SEwan Crawford return s.get(); 306078f339d1SEwan Crawford } 306178f339d1SEwan Crawford if (create) 306278f339d1SEwan Crawford { 306378f339d1SEwan Crawford std::unique_ptr<ScriptDetails> s(new ScriptDetails); 306478f339d1SEwan Crawford s->script = address; 306578f339d1SEwan Crawford m_scripts.push_back(std::move(s)); 3066d10ca9deSEwan Crawford return m_scripts.back().get(); 306778f339d1SEwan Crawford } 306878f339d1SEwan Crawford return nullptr; 306978f339d1SEwan Crawford } 307078f339d1SEwan Crawford 307178f339d1SEwan Crawford RenderScriptRuntime::AllocationDetails* 307278f339d1SEwan Crawford RenderScriptRuntime::LookUpAllocation(addr_t address, bool create) 307378f339d1SEwan Crawford { 307478f339d1SEwan Crawford for (const auto & a : m_allocations) 307578f339d1SEwan Crawford { 307678f339d1SEwan Crawford if (a->address.isValid()) 307778f339d1SEwan Crawford if (*a->address == address) 307878f339d1SEwan Crawford return a.get(); 307978f339d1SEwan Crawford } 308078f339d1SEwan Crawford if (create) 308178f339d1SEwan Crawford { 308278f339d1SEwan Crawford std::unique_ptr<AllocationDetails> a(new AllocationDetails); 308378f339d1SEwan Crawford a->address = address; 308478f339d1SEwan Crawford m_allocations.push_back(std::move(a)); 3085d10ca9deSEwan Crawford return m_allocations.back().get(); 308678f339d1SEwan Crawford } 308778f339d1SEwan Crawford return nullptr; 308878f339d1SEwan Crawford } 308978f339d1SEwan Crawford 30905ec532a9SColin Riley void 30915ec532a9SColin Riley RSModuleDescriptor::Dump(Stream &strm) const 30925ec532a9SColin Riley { 30935ec532a9SColin Riley strm.Indent(); 30945ec532a9SColin Riley m_module->GetFileSpec().Dump(&strm); 30954640cde1SColin Riley if(m_module->GetNumCompileUnits()) 30964640cde1SColin Riley { 30974640cde1SColin Riley strm.Indent("Debug info loaded."); 30984640cde1SColin Riley } 30994640cde1SColin Riley else 31004640cde1SColin Riley { 31014640cde1SColin Riley strm.Indent("Debug info does not exist."); 31024640cde1SColin Riley } 31035ec532a9SColin Riley strm.EOL(); 31045ec532a9SColin Riley strm.IndentMore(); 31055ec532a9SColin Riley strm.Indent(); 3106189598edSColin Riley strm.Printf("Globals: %" PRIu64, static_cast<uint64_t>(m_globals.size())); 31075ec532a9SColin Riley strm.EOL(); 31085ec532a9SColin Riley strm.IndentMore(); 31095ec532a9SColin Riley for (const auto &global : m_globals) 31105ec532a9SColin Riley { 31115ec532a9SColin Riley global.Dump(strm); 31125ec532a9SColin Riley } 31135ec532a9SColin Riley strm.IndentLess(); 31145ec532a9SColin Riley strm.Indent(); 3115189598edSColin Riley strm.Printf("Kernels: %" PRIu64, static_cast<uint64_t>(m_kernels.size())); 31165ec532a9SColin Riley strm.EOL(); 31175ec532a9SColin Riley strm.IndentMore(); 31185ec532a9SColin Riley for (const auto &kernel : m_kernels) 31195ec532a9SColin Riley { 31205ec532a9SColin Riley kernel.Dump(strm); 31215ec532a9SColin Riley } 31224640cde1SColin Riley strm.Printf("Pragmas: %" PRIu64 , static_cast<uint64_t>(m_pragmas.size())); 31234640cde1SColin Riley strm.EOL(); 31244640cde1SColin Riley strm.IndentMore(); 31254640cde1SColin Riley for (const auto &key_val : m_pragmas) 31264640cde1SColin Riley { 31274640cde1SColin Riley strm.Printf("%s: %s", key_val.first.c_str(), key_val.second.c_str()); 31284640cde1SColin Riley strm.EOL(); 31294640cde1SColin Riley } 31305ec532a9SColin Riley strm.IndentLess(4); 31315ec532a9SColin Riley } 31325ec532a9SColin Riley 31335ec532a9SColin Riley void 31345ec532a9SColin Riley RSGlobalDescriptor::Dump(Stream &strm) const 31355ec532a9SColin Riley { 31365ec532a9SColin Riley strm.Indent(m_name.AsCString()); 31374640cde1SColin Riley VariableList var_list; 31384640cde1SColin Riley m_module->m_module->FindGlobalVariables(m_name, nullptr, true, 1U, var_list); 31394640cde1SColin Riley if (var_list.GetSize() == 1) 31404640cde1SColin Riley { 31414640cde1SColin Riley auto var = var_list.GetVariableAtIndex(0); 31424640cde1SColin Riley auto type = var->GetType(); 31434640cde1SColin Riley if(type) 31444640cde1SColin Riley { 31454640cde1SColin Riley strm.Printf(" - "); 31464640cde1SColin Riley type->DumpTypeName(&strm); 31474640cde1SColin Riley } 31484640cde1SColin Riley else 31494640cde1SColin Riley { 31504640cde1SColin Riley strm.Printf(" - Unknown Type"); 31514640cde1SColin Riley } 31524640cde1SColin Riley } 31534640cde1SColin Riley else 31544640cde1SColin Riley { 31554640cde1SColin Riley strm.Printf(" - variable identified, but not found in binary"); 31564640cde1SColin Riley const Symbol* s = m_module->m_module->FindFirstSymbolWithNameAndType(m_name, eSymbolTypeData); 31574640cde1SColin Riley if (s) 31584640cde1SColin Riley { 31594640cde1SColin Riley strm.Printf(" (symbol exists) "); 31604640cde1SColin Riley } 31614640cde1SColin Riley } 31624640cde1SColin Riley 31635ec532a9SColin Riley strm.EOL(); 31645ec532a9SColin Riley } 31655ec532a9SColin Riley 31665ec532a9SColin Riley void 31675ec532a9SColin Riley RSKernelDescriptor::Dump(Stream &strm) const 31685ec532a9SColin Riley { 31695ec532a9SColin Riley strm.Indent(m_name.AsCString()); 31705ec532a9SColin Riley strm.EOL(); 31715ec532a9SColin Riley } 31725ec532a9SColin Riley 31735ec532a9SColin Riley class CommandObjectRenderScriptRuntimeModuleProbe : public CommandObjectParsed 31745ec532a9SColin Riley { 31755ec532a9SColin Riley public: 31765ec532a9SColin Riley CommandObjectRenderScriptRuntimeModuleProbe(CommandInterpreter &interpreter) 31775ec532a9SColin Riley : CommandObjectParsed(interpreter, "renderscript module probe", 31785ec532a9SColin Riley "Initiates a Probe of all loaded modules for kernels and other renderscript objects.", 31795ec532a9SColin Riley "renderscript module probe", 3180e87764f2SEnrico Granata eCommandRequiresTarget | eCommandRequiresProcess | eCommandProcessMustBeLaunched) 31815ec532a9SColin Riley { 31825ec532a9SColin Riley } 31835ec532a9SColin Riley 3184222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeModuleProbe() override = default; 31855ec532a9SColin Riley 31865ec532a9SColin Riley bool 3187222b937cSEugene Zelenko DoExecute(Args &command, CommandReturnObject &result) override 31885ec532a9SColin Riley { 31895ec532a9SColin Riley const size_t argc = command.GetArgumentCount(); 31905ec532a9SColin Riley if (argc == 0) 31915ec532a9SColin Riley { 31925ec532a9SColin Riley Target *target = m_exe_ctx.GetTargetPtr(); 31935ec532a9SColin Riley RenderScriptRuntime *runtime = 31945ec532a9SColin Riley (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); 31955ec532a9SColin Riley auto module_list = target->GetImages(); 31965ec532a9SColin Riley bool new_rs_details = runtime->ProbeModules(module_list); 31975ec532a9SColin Riley if (new_rs_details) 31985ec532a9SColin Riley { 31995ec532a9SColin Riley result.AppendMessage("New renderscript modules added to runtime model."); 32005ec532a9SColin Riley } 32015ec532a9SColin Riley result.SetStatus(eReturnStatusSuccessFinishResult); 32025ec532a9SColin Riley return true; 32035ec532a9SColin Riley } 32045ec532a9SColin Riley 32055ec532a9SColin Riley result.AppendErrorWithFormat("'%s' takes no arguments", m_cmd_name.c_str()); 32065ec532a9SColin Riley result.SetStatus(eReturnStatusFailed); 32075ec532a9SColin Riley return false; 32085ec532a9SColin Riley } 32095ec532a9SColin Riley }; 32105ec532a9SColin Riley 32115ec532a9SColin Riley class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed 32125ec532a9SColin Riley { 32135ec532a9SColin Riley public: 32145ec532a9SColin Riley CommandObjectRenderScriptRuntimeModuleDump(CommandInterpreter &interpreter) 32155ec532a9SColin Riley : CommandObjectParsed(interpreter, "renderscript module dump", 32165ec532a9SColin Riley "Dumps renderscript specific information for all modules.", "renderscript module dump", 3217e87764f2SEnrico Granata eCommandRequiresProcess | eCommandProcessMustBeLaunched) 32185ec532a9SColin Riley { 32195ec532a9SColin Riley } 32205ec532a9SColin Riley 3221222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeModuleDump() override = default; 32225ec532a9SColin Riley 32235ec532a9SColin Riley bool 3224222b937cSEugene Zelenko DoExecute(Args &command, CommandReturnObject &result) override 32255ec532a9SColin Riley { 32265ec532a9SColin Riley RenderScriptRuntime *runtime = 32275ec532a9SColin Riley (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); 32285ec532a9SColin Riley runtime->DumpModules(result.GetOutputStream()); 32295ec532a9SColin Riley result.SetStatus(eReturnStatusSuccessFinishResult); 32305ec532a9SColin Riley return true; 32315ec532a9SColin Riley } 32325ec532a9SColin Riley }; 32335ec532a9SColin Riley 32345ec532a9SColin Riley class CommandObjectRenderScriptRuntimeModule : public CommandObjectMultiword 32355ec532a9SColin Riley { 32365ec532a9SColin Riley public: 32375ec532a9SColin Riley CommandObjectRenderScriptRuntimeModule(CommandInterpreter &interpreter) 32385ec532a9SColin Riley : CommandObjectMultiword(interpreter, "renderscript module", "Commands that deal with renderscript modules.", 32395ec532a9SColin Riley NULL) 32405ec532a9SColin Riley { 32415ec532a9SColin Riley LoadSubCommand("probe", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleProbe(interpreter))); 32425ec532a9SColin Riley LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleDump(interpreter))); 32435ec532a9SColin Riley } 32445ec532a9SColin Riley 3245222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeModule() override = default; 32465ec532a9SColin Riley }; 32475ec532a9SColin Riley 32484640cde1SColin Riley class CommandObjectRenderScriptRuntimeKernelList : public CommandObjectParsed 32494640cde1SColin Riley { 32504640cde1SColin Riley public: 32514640cde1SColin Riley CommandObjectRenderScriptRuntimeKernelList(CommandInterpreter &interpreter) 32524640cde1SColin Riley : CommandObjectParsed(interpreter, "renderscript kernel list", 32534640cde1SColin Riley "Lists renderscript kernel names and associated script resources.", "renderscript kernel list", 32544640cde1SColin Riley eCommandRequiresProcess | eCommandProcessMustBeLaunched) 32554640cde1SColin Riley { 32564640cde1SColin Riley } 32574640cde1SColin Riley 3258222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeKernelList() override = default; 32594640cde1SColin Riley 32604640cde1SColin Riley bool 3261222b937cSEugene Zelenko DoExecute(Args &command, CommandReturnObject &result) override 32624640cde1SColin Riley { 32634640cde1SColin Riley RenderScriptRuntime *runtime = 32644640cde1SColin Riley (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); 32654640cde1SColin Riley runtime->DumpKernels(result.GetOutputStream()); 32664640cde1SColin Riley result.SetStatus(eReturnStatusSuccessFinishResult); 32674640cde1SColin Riley return true; 32684640cde1SColin Riley } 32694640cde1SColin Riley }; 32704640cde1SColin Riley 32717dc7771cSEwan Crawford class CommandObjectRenderScriptRuntimeKernelBreakpointSet : public CommandObjectParsed 32724640cde1SColin Riley { 32734640cde1SColin Riley public: 32747dc7771cSEwan Crawford CommandObjectRenderScriptRuntimeKernelBreakpointSet(CommandInterpreter &interpreter) 32757dc7771cSEwan Crawford : CommandObjectParsed(interpreter, "renderscript kernel breakpoint set", 3276018f5a7eSEwan Crawford "Sets a breakpoint on a renderscript kernel.", "renderscript kernel breakpoint set <kernel_name> [-c x,y,z]", 3277018f5a7eSEwan Crawford eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), m_options(interpreter) 32784640cde1SColin Riley { 32794640cde1SColin Riley } 32804640cde1SColin Riley 3281222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeKernelBreakpointSet() override = default; 3282222b937cSEugene Zelenko 3283222b937cSEugene Zelenko Options* 3284222b937cSEugene Zelenko GetOptions() override 3285018f5a7eSEwan Crawford { 3286018f5a7eSEwan Crawford return &m_options; 3287018f5a7eSEwan Crawford } 3288018f5a7eSEwan Crawford 3289018f5a7eSEwan Crawford class CommandOptions : public Options 3290018f5a7eSEwan Crawford { 3291018f5a7eSEwan Crawford public: 3292018f5a7eSEwan Crawford CommandOptions(CommandInterpreter &interpreter) : Options(interpreter) 3293018f5a7eSEwan Crawford { 3294018f5a7eSEwan Crawford } 3295018f5a7eSEwan Crawford 3296222b937cSEugene Zelenko ~CommandOptions() override = default; 3297018f5a7eSEwan Crawford 3298222b937cSEugene Zelenko Error 3299222b937cSEugene Zelenko SetOptionValue(uint32_t option_idx, const char *option_arg) override 3300018f5a7eSEwan Crawford { 3301018f5a7eSEwan Crawford Error error; 3302018f5a7eSEwan Crawford const int short_option = m_getopt_table[option_idx].val; 3303018f5a7eSEwan Crawford 3304018f5a7eSEwan Crawford switch (short_option) 3305018f5a7eSEwan Crawford { 3306018f5a7eSEwan Crawford case 'c': 3307018f5a7eSEwan Crawford if (!ParseCoordinate(option_arg)) 3308018f5a7eSEwan Crawford error.SetErrorStringWithFormat("Couldn't parse coordinate '%s', should be in format 'x,y,z'.", option_arg); 3309018f5a7eSEwan Crawford break; 3310018f5a7eSEwan Crawford default: 3311018f5a7eSEwan Crawford error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); 3312018f5a7eSEwan Crawford break; 3313018f5a7eSEwan Crawford } 3314018f5a7eSEwan Crawford return error; 3315018f5a7eSEwan Crawford } 3316018f5a7eSEwan Crawford 3317018f5a7eSEwan Crawford // -c takes an argument of the form 'num[,num][,num]'. 3318018f5a7eSEwan Crawford // Where 'id_cstr' is this argument with the whitespace trimmed. 3319018f5a7eSEwan Crawford // Missing coordinates are defaulted to zero. 3320018f5a7eSEwan Crawford bool 3321018f5a7eSEwan Crawford ParseCoordinate(const char* id_cstr) 3322018f5a7eSEwan Crawford { 3323018f5a7eSEwan Crawford RegularExpression regex; 3324018f5a7eSEwan Crawford RegularExpression::Match regex_match(3); 3325018f5a7eSEwan Crawford 3326018f5a7eSEwan Crawford bool matched = false; 3327018f5a7eSEwan Crawford if(regex.Compile("^([0-9]+),([0-9]+),([0-9]+)$") && regex.Execute(id_cstr, ®ex_match)) 3328018f5a7eSEwan Crawford matched = true; 3329018f5a7eSEwan Crawford else if(regex.Compile("^([0-9]+),([0-9]+)$") && regex.Execute(id_cstr, ®ex_match)) 3330018f5a7eSEwan Crawford matched = true; 3331018f5a7eSEwan Crawford else if(regex.Compile("^([0-9]+)$") && regex.Execute(id_cstr, ®ex_match)) 3332018f5a7eSEwan Crawford matched = true; 3333018f5a7eSEwan Crawford for(uint32_t i = 0; i < 3; i++) 3334018f5a7eSEwan Crawford { 3335018f5a7eSEwan Crawford std::string group; 3336018f5a7eSEwan Crawford if(regex_match.GetMatchAtIndex(id_cstr, i + 1, group)) 3337018f5a7eSEwan Crawford m_coord[i] = (uint32_t)strtoul(group.c_str(), NULL, 0); 3338018f5a7eSEwan Crawford else 3339018f5a7eSEwan Crawford m_coord[i] = 0; 3340018f5a7eSEwan Crawford } 3341018f5a7eSEwan Crawford return matched; 3342018f5a7eSEwan Crawford } 3343018f5a7eSEwan Crawford 3344018f5a7eSEwan Crawford void 3345222b937cSEugene Zelenko OptionParsingStarting() override 3346018f5a7eSEwan Crawford { 3347018f5a7eSEwan Crawford // -1 means the -c option hasn't been set 3348018f5a7eSEwan Crawford m_coord[0] = -1; 3349018f5a7eSEwan Crawford m_coord[1] = -1; 3350018f5a7eSEwan Crawford m_coord[2] = -1; 3351018f5a7eSEwan Crawford } 3352018f5a7eSEwan Crawford 3353018f5a7eSEwan Crawford const OptionDefinition* 3354222b937cSEugene Zelenko GetDefinitions() override 3355018f5a7eSEwan Crawford { 3356018f5a7eSEwan Crawford return g_option_table; 3357018f5a7eSEwan Crawford } 3358018f5a7eSEwan Crawford 3359018f5a7eSEwan Crawford static OptionDefinition g_option_table[]; 3360018f5a7eSEwan Crawford std::array<int,3> m_coord; 3361018f5a7eSEwan Crawford }; 3362018f5a7eSEwan Crawford 33634640cde1SColin Riley bool 3364222b937cSEugene Zelenko DoExecute(Args &command, CommandReturnObject &result) override 33654640cde1SColin Riley { 33664640cde1SColin Riley const size_t argc = command.GetArgumentCount(); 3367018f5a7eSEwan Crawford if (argc < 1) 33684640cde1SColin Riley { 3369018f5a7eSEwan Crawford result.AppendErrorWithFormat("'%s' takes 1 argument of kernel name, and an optional coordinate.", m_cmd_name.c_str()); 3370018f5a7eSEwan Crawford result.SetStatus(eReturnStatusFailed); 3371018f5a7eSEwan Crawford return false; 3372018f5a7eSEwan Crawford } 3373018f5a7eSEwan Crawford 33744640cde1SColin Riley RenderScriptRuntime *runtime = 33754640cde1SColin Riley (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); 33764640cde1SColin Riley 33774640cde1SColin Riley Error error; 3378018f5a7eSEwan Crawford runtime->PlaceBreakpointOnKernel(result.GetOutputStream(), command.GetArgumentAtIndex(0), m_options.m_coord, 337998156583SEwan Crawford error, m_exe_ctx.GetTargetSP()); 33804640cde1SColin Riley 33814640cde1SColin Riley if (error.Success()) 33824640cde1SColin Riley { 33834640cde1SColin Riley result.AppendMessage("Breakpoint(s) created"); 33844640cde1SColin Riley result.SetStatus(eReturnStatusSuccessFinishResult); 33854640cde1SColin Riley return true; 33864640cde1SColin Riley } 33874640cde1SColin Riley result.SetStatus(eReturnStatusFailed); 33884640cde1SColin Riley result.AppendErrorWithFormat("Error: %s", error.AsCString()); 33894640cde1SColin Riley return false; 33904640cde1SColin Riley } 33914640cde1SColin Riley 3392018f5a7eSEwan Crawford private: 3393018f5a7eSEwan Crawford CommandOptions m_options; 33944640cde1SColin Riley }; 33954640cde1SColin Riley 3396018f5a7eSEwan Crawford OptionDefinition 3397018f5a7eSEwan Crawford CommandObjectRenderScriptRuntimeKernelBreakpointSet::CommandOptions::g_option_table[] = 3398018f5a7eSEwan Crawford { 3399018f5a7eSEwan Crawford { LLDB_OPT_SET_1, false, "coordinate", 'c', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeValue, 3400018f5a7eSEwan Crawford "Set a breakpoint on a single invocation of the kernel with specified coordinate.\n" 3401018f5a7eSEwan Crawford "Coordinate takes the form 'x[,y][,z] where x,y,z are positive integers representing kernel dimensions. " 3402018f5a7eSEwan Crawford "Any unset dimensions will be defaulted to zero."}, 3403018f5a7eSEwan Crawford { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 3404018f5a7eSEwan Crawford }; 3405018f5a7eSEwan Crawford 34067dc7771cSEwan Crawford class CommandObjectRenderScriptRuntimeKernelBreakpointAll : public CommandObjectParsed 34077dc7771cSEwan Crawford { 34087dc7771cSEwan Crawford public: 34097dc7771cSEwan Crawford CommandObjectRenderScriptRuntimeKernelBreakpointAll(CommandInterpreter &interpreter) 34107dc7771cSEwan Crawford : CommandObjectParsed(interpreter, "renderscript kernel breakpoint all", 34117dc7771cSEwan Crawford "Automatically sets a breakpoint on all renderscript kernels that are or will be loaded.\n" 34127dc7771cSEwan Crawford "Disabling option means breakpoints will no longer be set on any kernels loaded in the future, " 34137dc7771cSEwan Crawford "but does not remove currently set breakpoints.", 34147dc7771cSEwan Crawford "renderscript kernel breakpoint all <enable/disable>", 34157dc7771cSEwan Crawford eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused) 34167dc7771cSEwan Crawford { 34177dc7771cSEwan Crawford } 34187dc7771cSEwan Crawford 3419222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeKernelBreakpointAll() override = default; 34207dc7771cSEwan Crawford 34217dc7771cSEwan Crawford bool 3422222b937cSEugene Zelenko DoExecute(Args &command, CommandReturnObject &result) override 34237dc7771cSEwan Crawford { 34247dc7771cSEwan Crawford const size_t argc = command.GetArgumentCount(); 34257dc7771cSEwan Crawford if (argc != 1) 34267dc7771cSEwan Crawford { 34277dc7771cSEwan Crawford result.AppendErrorWithFormat("'%s' takes 1 argument of 'enable' or 'disable'", m_cmd_name.c_str()); 34287dc7771cSEwan Crawford result.SetStatus(eReturnStatusFailed); 34297dc7771cSEwan Crawford return false; 34307dc7771cSEwan Crawford } 34317dc7771cSEwan Crawford 34327dc7771cSEwan Crawford RenderScriptRuntime *runtime = 34337dc7771cSEwan Crawford static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); 34347dc7771cSEwan Crawford 34357dc7771cSEwan Crawford bool do_break = false; 34367dc7771cSEwan Crawford const char* argument = command.GetArgumentAtIndex(0); 34377dc7771cSEwan Crawford if (strcmp(argument, "enable") == 0) 34387dc7771cSEwan Crawford { 34397dc7771cSEwan Crawford do_break = true; 34407dc7771cSEwan Crawford result.AppendMessage("Breakpoints will be set on all kernels."); 34417dc7771cSEwan Crawford } 34427dc7771cSEwan Crawford else if (strcmp(argument, "disable") == 0) 34437dc7771cSEwan Crawford { 34447dc7771cSEwan Crawford do_break = false; 34457dc7771cSEwan Crawford result.AppendMessage("Breakpoints will not be set on any new kernels."); 34467dc7771cSEwan Crawford } 34477dc7771cSEwan Crawford else 34487dc7771cSEwan Crawford { 34497dc7771cSEwan Crawford result.AppendErrorWithFormat("Argument must be either 'enable' or 'disable'"); 34507dc7771cSEwan Crawford result.SetStatus(eReturnStatusFailed); 34517dc7771cSEwan Crawford return false; 34527dc7771cSEwan Crawford } 34537dc7771cSEwan Crawford 34547dc7771cSEwan Crawford runtime->SetBreakAllKernels(do_break, m_exe_ctx.GetTargetSP()); 34557dc7771cSEwan Crawford 34567dc7771cSEwan Crawford result.SetStatus(eReturnStatusSuccessFinishResult); 34577dc7771cSEwan Crawford return true; 34587dc7771cSEwan Crawford } 34597dc7771cSEwan Crawford }; 34607dc7771cSEwan Crawford 34617dc7771cSEwan Crawford class CommandObjectRenderScriptRuntimeKernelBreakpoint : public CommandObjectMultiword 34627dc7771cSEwan Crawford { 34637dc7771cSEwan Crawford public: 34647dc7771cSEwan Crawford CommandObjectRenderScriptRuntimeKernelBreakpoint(CommandInterpreter &interpreter) 34657dc7771cSEwan Crawford : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that generate breakpoints on renderscript kernels.", 34667dc7771cSEwan Crawford nullptr) 34677dc7771cSEwan Crawford { 34687dc7771cSEwan Crawford LoadSubCommand("set", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointSet(interpreter))); 34697dc7771cSEwan Crawford LoadSubCommand("all", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointAll(interpreter))); 34707dc7771cSEwan Crawford } 34717dc7771cSEwan Crawford 3472222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeKernelBreakpoint() override = default; 34737dc7771cSEwan Crawford }; 34747dc7771cSEwan Crawford 34754640cde1SColin Riley class CommandObjectRenderScriptRuntimeKernel : public CommandObjectMultiword 34764640cde1SColin Riley { 34774640cde1SColin Riley public: 34784640cde1SColin Riley CommandObjectRenderScriptRuntimeKernel(CommandInterpreter &interpreter) 34794640cde1SColin Riley : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that deal with renderscript kernels.", 34804640cde1SColin Riley NULL) 34814640cde1SColin Riley { 34824640cde1SColin Riley LoadSubCommand("list", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelList(interpreter))); 34834640cde1SColin Riley LoadSubCommand("breakpoint", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpoint(interpreter))); 34844640cde1SColin Riley } 34854640cde1SColin Riley 3486222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeKernel() override = default; 34874640cde1SColin Riley }; 34884640cde1SColin Riley 34894640cde1SColin Riley class CommandObjectRenderScriptRuntimeContextDump : public CommandObjectParsed 34904640cde1SColin Riley { 34914640cde1SColin Riley public: 34924640cde1SColin Riley CommandObjectRenderScriptRuntimeContextDump(CommandInterpreter &interpreter) 34934640cde1SColin Riley : CommandObjectParsed(interpreter, "renderscript context dump", 34944640cde1SColin Riley "Dumps renderscript context information.", "renderscript context dump", 34954640cde1SColin Riley eCommandRequiresProcess | eCommandProcessMustBeLaunched) 34964640cde1SColin Riley { 34974640cde1SColin Riley } 34984640cde1SColin Riley 3499222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeContextDump() override = default; 35004640cde1SColin Riley 35014640cde1SColin Riley bool 3502222b937cSEugene Zelenko DoExecute(Args &command, CommandReturnObject &result) override 35034640cde1SColin Riley { 35044640cde1SColin Riley RenderScriptRuntime *runtime = 35054640cde1SColin Riley (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); 35064640cde1SColin Riley runtime->DumpContexts(result.GetOutputStream()); 35074640cde1SColin Riley result.SetStatus(eReturnStatusSuccessFinishResult); 35084640cde1SColin Riley return true; 35094640cde1SColin Riley } 35104640cde1SColin Riley }; 35114640cde1SColin Riley 35124640cde1SColin Riley class CommandObjectRenderScriptRuntimeContext : public CommandObjectMultiword 35134640cde1SColin Riley { 35144640cde1SColin Riley public: 35154640cde1SColin Riley CommandObjectRenderScriptRuntimeContext(CommandInterpreter &interpreter) 35164640cde1SColin Riley : CommandObjectMultiword(interpreter, "renderscript context", "Commands that deal with renderscript contexts.", 35174640cde1SColin Riley NULL) 35184640cde1SColin Riley { 35194640cde1SColin Riley LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeContextDump(interpreter))); 35204640cde1SColin Riley } 35214640cde1SColin Riley 3522222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeContext() override = default; 35234640cde1SColin Riley }; 35244640cde1SColin Riley 3525a0f08674SEwan Crawford class CommandObjectRenderScriptRuntimeAllocationDump : public CommandObjectParsed 3526a0f08674SEwan Crawford { 3527a0f08674SEwan Crawford public: 3528a0f08674SEwan Crawford CommandObjectRenderScriptRuntimeAllocationDump(CommandInterpreter &interpreter) 3529a0f08674SEwan Crawford : CommandObjectParsed(interpreter, "renderscript allocation dump", 3530a0f08674SEwan Crawford "Displays the contents of a particular allocation", "renderscript allocation dump <ID>", 3531a0f08674SEwan Crawford eCommandRequiresProcess | eCommandProcessMustBeLaunched), m_options(interpreter) 3532a0f08674SEwan Crawford { 3533a0f08674SEwan Crawford } 3534a0f08674SEwan Crawford 3535222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeAllocationDump() override = default; 3536222b937cSEugene Zelenko 3537222b937cSEugene Zelenko Options* 3538222b937cSEugene Zelenko GetOptions() override 3539a0f08674SEwan Crawford { 3540a0f08674SEwan Crawford return &m_options; 3541a0f08674SEwan Crawford } 3542a0f08674SEwan Crawford 3543a0f08674SEwan Crawford class CommandOptions : public Options 3544a0f08674SEwan Crawford { 3545a0f08674SEwan Crawford public: 3546a0f08674SEwan Crawford CommandOptions(CommandInterpreter &interpreter) : Options(interpreter) 3547a0f08674SEwan Crawford { 3548a0f08674SEwan Crawford } 3549a0f08674SEwan Crawford 3550222b937cSEugene Zelenko ~CommandOptions() override = default; 3551a0f08674SEwan Crawford 3552222b937cSEugene Zelenko Error 3553222b937cSEugene Zelenko SetOptionValue(uint32_t option_idx, const char *option_arg) override 3554a0f08674SEwan Crawford { 3555a0f08674SEwan Crawford Error error; 3556a0f08674SEwan Crawford const int short_option = m_getopt_table[option_idx].val; 3557a0f08674SEwan Crawford 3558a0f08674SEwan Crawford switch (short_option) 3559a0f08674SEwan Crawford { 3560a0f08674SEwan Crawford case 'f': 3561a0f08674SEwan Crawford m_outfile.SetFile(option_arg, true); 3562a0f08674SEwan Crawford if (m_outfile.Exists()) 3563a0f08674SEwan Crawford { 3564a0f08674SEwan Crawford m_outfile.Clear(); 3565a0f08674SEwan Crawford error.SetErrorStringWithFormat("file already exists: '%s'", option_arg); 3566a0f08674SEwan Crawford } 3567a0f08674SEwan Crawford break; 3568a0f08674SEwan Crawford default: 3569a0f08674SEwan Crawford error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); 3570a0f08674SEwan Crawford break; 3571a0f08674SEwan Crawford } 3572a0f08674SEwan Crawford return error; 3573a0f08674SEwan Crawford } 3574a0f08674SEwan Crawford 3575a0f08674SEwan Crawford void 3576222b937cSEugene Zelenko OptionParsingStarting() override 3577a0f08674SEwan Crawford { 3578a0f08674SEwan Crawford m_outfile.Clear(); 3579a0f08674SEwan Crawford } 3580a0f08674SEwan Crawford 3581a0f08674SEwan Crawford const OptionDefinition* 3582222b937cSEugene Zelenko GetDefinitions() override 3583a0f08674SEwan Crawford { 3584a0f08674SEwan Crawford return g_option_table; 3585a0f08674SEwan Crawford } 3586a0f08674SEwan Crawford 3587a0f08674SEwan Crawford static OptionDefinition g_option_table[]; 3588a0f08674SEwan Crawford FileSpec m_outfile; 3589a0f08674SEwan Crawford }; 3590a0f08674SEwan Crawford 3591a0f08674SEwan Crawford bool 3592222b937cSEugene Zelenko DoExecute(Args &command, CommandReturnObject &result) override 3593a0f08674SEwan Crawford { 3594a0f08674SEwan Crawford const size_t argc = command.GetArgumentCount(); 3595a0f08674SEwan Crawford if (argc < 1) 3596a0f08674SEwan Crawford { 3597a0f08674SEwan Crawford result.AppendErrorWithFormat("'%s' takes 1 argument, an allocation ID. As well as an optional -f argument", 3598a0f08674SEwan Crawford m_cmd_name.c_str()); 3599a0f08674SEwan Crawford result.SetStatus(eReturnStatusFailed); 3600a0f08674SEwan Crawford return false; 3601a0f08674SEwan Crawford } 3602a0f08674SEwan Crawford 3603a0f08674SEwan Crawford RenderScriptRuntime *runtime = 3604a0f08674SEwan Crawford static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); 3605a0f08674SEwan Crawford 3606a0f08674SEwan Crawford const char* id_cstr = command.GetArgumentAtIndex(0); 3607a0f08674SEwan Crawford bool convert_complete = false; 3608a0f08674SEwan Crawford const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete); 3609a0f08674SEwan Crawford if (!convert_complete) 3610a0f08674SEwan Crawford { 3611a0f08674SEwan Crawford result.AppendErrorWithFormat("invalid allocation id argument '%s'", id_cstr); 3612a0f08674SEwan Crawford result.SetStatus(eReturnStatusFailed); 3613a0f08674SEwan Crawford return false; 3614a0f08674SEwan Crawford } 3615a0f08674SEwan Crawford 3616a0f08674SEwan Crawford Stream* output_strm = nullptr; 3617a0f08674SEwan Crawford StreamFile outfile_stream; 3618a0f08674SEwan Crawford const FileSpec &outfile_spec = m_options.m_outfile; // Dump allocation to file instead 3619a0f08674SEwan Crawford if (outfile_spec) 3620a0f08674SEwan Crawford { 3621a0f08674SEwan Crawford // Open output file 3622a0f08674SEwan Crawford char path[256]; 3623a0f08674SEwan Crawford outfile_spec.GetPath(path, sizeof(path)); 3624a0f08674SEwan Crawford if (outfile_stream.GetFile().Open(path, File::eOpenOptionWrite | File::eOpenOptionCanCreate).Success()) 3625a0f08674SEwan Crawford { 3626a0f08674SEwan Crawford output_strm = &outfile_stream; 3627a0f08674SEwan Crawford result.GetOutputStream().Printf("Results written to '%s'", path); 3628a0f08674SEwan Crawford result.GetOutputStream().EOL(); 3629a0f08674SEwan Crawford } 3630a0f08674SEwan Crawford else 3631a0f08674SEwan Crawford { 3632a0f08674SEwan Crawford result.AppendErrorWithFormat("Couldn't open file '%s'", path); 3633a0f08674SEwan Crawford result.SetStatus(eReturnStatusFailed); 3634a0f08674SEwan Crawford return false; 3635a0f08674SEwan Crawford } 3636a0f08674SEwan Crawford } 3637a0f08674SEwan Crawford else 3638a0f08674SEwan Crawford output_strm = &result.GetOutputStream(); 3639a0f08674SEwan Crawford 3640a0f08674SEwan Crawford assert(output_strm != nullptr); 3641a0f08674SEwan Crawford bool success = runtime->DumpAllocation(*output_strm, m_exe_ctx.GetFramePtr(), id); 3642a0f08674SEwan Crawford 3643a0f08674SEwan Crawford if (success) 3644a0f08674SEwan Crawford result.SetStatus(eReturnStatusSuccessFinishResult); 3645a0f08674SEwan Crawford else 3646a0f08674SEwan Crawford result.SetStatus(eReturnStatusFailed); 3647a0f08674SEwan Crawford 3648a0f08674SEwan Crawford return true; 3649a0f08674SEwan Crawford } 3650a0f08674SEwan Crawford 3651a0f08674SEwan Crawford private: 3652a0f08674SEwan Crawford CommandOptions m_options; 3653a0f08674SEwan Crawford }; 3654a0f08674SEwan Crawford 3655a0f08674SEwan Crawford OptionDefinition 3656a0f08674SEwan Crawford CommandObjectRenderScriptRuntimeAllocationDump::CommandOptions::g_option_table[] = 3657a0f08674SEwan Crawford { 3658a0f08674SEwan Crawford { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFilename, 3659a0f08674SEwan Crawford "Print results to specified file instead of command line."}, 3660a0f08674SEwan Crawford { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 3661a0f08674SEwan Crawford }; 3662a0f08674SEwan Crawford 366315f2bd95SEwan Crawford class CommandObjectRenderScriptRuntimeAllocationList : public CommandObjectParsed 366415f2bd95SEwan Crawford { 366515f2bd95SEwan Crawford public: 366615f2bd95SEwan Crawford CommandObjectRenderScriptRuntimeAllocationList(CommandInterpreter &interpreter) 366715f2bd95SEwan Crawford : CommandObjectParsed(interpreter, "renderscript allocation list", 366815f2bd95SEwan Crawford "List renderscript allocations and their information.", "renderscript allocation list", 366915f2bd95SEwan Crawford eCommandRequiresProcess | eCommandProcessMustBeLaunched), m_options(interpreter) 367015f2bd95SEwan Crawford { 367115f2bd95SEwan Crawford } 367215f2bd95SEwan Crawford 3673222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeAllocationList() override = default; 3674222b937cSEugene Zelenko 3675222b937cSEugene Zelenko Options* 3676222b937cSEugene Zelenko GetOptions() override 367715f2bd95SEwan Crawford { 367815f2bd95SEwan Crawford return &m_options; 367915f2bd95SEwan Crawford } 368015f2bd95SEwan Crawford 368115f2bd95SEwan Crawford class CommandOptions : public Options 368215f2bd95SEwan Crawford { 368315f2bd95SEwan Crawford public: 368415f2bd95SEwan Crawford CommandOptions(CommandInterpreter &interpreter) : Options(interpreter), m_refresh(false) 368515f2bd95SEwan Crawford { 368615f2bd95SEwan Crawford } 368715f2bd95SEwan Crawford 3688222b937cSEugene Zelenko ~CommandOptions() override = default; 368915f2bd95SEwan Crawford 3690222b937cSEugene Zelenko Error 3691222b937cSEugene Zelenko SetOptionValue(uint32_t option_idx, const char *option_arg) override 369215f2bd95SEwan Crawford { 369315f2bd95SEwan Crawford Error error; 369415f2bd95SEwan Crawford const int short_option = m_getopt_table[option_idx].val; 369515f2bd95SEwan Crawford 369615f2bd95SEwan Crawford switch (short_option) 369715f2bd95SEwan Crawford { 369815f2bd95SEwan Crawford case 'r': 369915f2bd95SEwan Crawford m_refresh = true; 370015f2bd95SEwan Crawford break; 370115f2bd95SEwan Crawford default: 370215f2bd95SEwan Crawford error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); 370315f2bd95SEwan Crawford break; 370415f2bd95SEwan Crawford } 370515f2bd95SEwan Crawford return error; 370615f2bd95SEwan Crawford } 370715f2bd95SEwan Crawford 370815f2bd95SEwan Crawford void 3709222b937cSEugene Zelenko OptionParsingStarting() override 371015f2bd95SEwan Crawford { 371115f2bd95SEwan Crawford m_refresh = false; 371215f2bd95SEwan Crawford } 371315f2bd95SEwan Crawford 371415f2bd95SEwan Crawford const OptionDefinition* 3715222b937cSEugene Zelenko GetDefinitions() override 371615f2bd95SEwan Crawford { 371715f2bd95SEwan Crawford return g_option_table; 371815f2bd95SEwan Crawford } 371915f2bd95SEwan Crawford 372015f2bd95SEwan Crawford static OptionDefinition g_option_table[]; 372115f2bd95SEwan Crawford bool m_refresh; 372215f2bd95SEwan Crawford }; 372315f2bd95SEwan Crawford 372415f2bd95SEwan Crawford bool 3725222b937cSEugene Zelenko DoExecute(Args &command, CommandReturnObject &result) override 372615f2bd95SEwan Crawford { 372715f2bd95SEwan Crawford RenderScriptRuntime *runtime = 372815f2bd95SEwan Crawford static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); 372915f2bd95SEwan Crawford runtime->ListAllocations(result.GetOutputStream(), m_exe_ctx.GetFramePtr(), m_options.m_refresh); 373015f2bd95SEwan Crawford result.SetStatus(eReturnStatusSuccessFinishResult); 373115f2bd95SEwan Crawford return true; 373215f2bd95SEwan Crawford } 373315f2bd95SEwan Crawford 373415f2bd95SEwan Crawford private: 373515f2bd95SEwan Crawford CommandOptions m_options; 373615f2bd95SEwan Crawford }; 373715f2bd95SEwan Crawford 373815f2bd95SEwan Crawford OptionDefinition 373915f2bd95SEwan Crawford CommandObjectRenderScriptRuntimeAllocationList::CommandOptions::g_option_table[] = 374015f2bd95SEwan Crawford { 374115f2bd95SEwan Crawford { LLDB_OPT_SET_1, false, "refresh", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, 374215f2bd95SEwan Crawford "Recompute allocation details."}, 374315f2bd95SEwan Crawford { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL } 374415f2bd95SEwan Crawford }; 374515f2bd95SEwan Crawford 374655232f09SEwan Crawford class CommandObjectRenderScriptRuntimeAllocationLoad : public CommandObjectParsed 374755232f09SEwan Crawford { 374855232f09SEwan Crawford public: 374955232f09SEwan Crawford CommandObjectRenderScriptRuntimeAllocationLoad(CommandInterpreter &interpreter) 375055232f09SEwan Crawford : CommandObjectParsed(interpreter, "renderscript allocation load", 375155232f09SEwan Crawford "Loads renderscript allocation contents from a file.", "renderscript allocation load <ID> <filename>", 375255232f09SEwan Crawford eCommandRequiresProcess | eCommandProcessMustBeLaunched) 375355232f09SEwan Crawford { 375455232f09SEwan Crawford } 375555232f09SEwan Crawford 3756222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeAllocationLoad() override = default; 375755232f09SEwan Crawford 375855232f09SEwan Crawford bool 3759222b937cSEugene Zelenko DoExecute(Args &command, CommandReturnObject &result) override 376055232f09SEwan Crawford { 376155232f09SEwan Crawford const size_t argc = command.GetArgumentCount(); 376255232f09SEwan Crawford if (argc != 2) 376355232f09SEwan Crawford { 376455232f09SEwan Crawford result.AppendErrorWithFormat("'%s' takes 2 arguments, an allocation ID and filename to read from.", m_cmd_name.c_str()); 376555232f09SEwan Crawford result.SetStatus(eReturnStatusFailed); 376655232f09SEwan Crawford return false; 376755232f09SEwan Crawford } 376855232f09SEwan Crawford 376955232f09SEwan Crawford RenderScriptRuntime *runtime = 377055232f09SEwan Crawford static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); 377155232f09SEwan Crawford 377255232f09SEwan Crawford const char* id_cstr = command.GetArgumentAtIndex(0); 377355232f09SEwan Crawford bool convert_complete = false; 377455232f09SEwan Crawford const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete); 377555232f09SEwan Crawford if (!convert_complete) 377655232f09SEwan Crawford { 377755232f09SEwan Crawford result.AppendErrorWithFormat ("invalid allocation id argument '%s'", id_cstr); 377855232f09SEwan Crawford result.SetStatus (eReturnStatusFailed); 377955232f09SEwan Crawford return false; 378055232f09SEwan Crawford } 378155232f09SEwan Crawford 378255232f09SEwan Crawford const char* filename = command.GetArgumentAtIndex(1); 378355232f09SEwan Crawford bool success = runtime->LoadAllocation(result.GetOutputStream(), id, filename, m_exe_ctx.GetFramePtr()); 378455232f09SEwan Crawford 378555232f09SEwan Crawford if (success) 378655232f09SEwan Crawford result.SetStatus(eReturnStatusSuccessFinishResult); 378755232f09SEwan Crawford else 378855232f09SEwan Crawford result.SetStatus(eReturnStatusFailed); 378955232f09SEwan Crawford 379055232f09SEwan Crawford return true; 379155232f09SEwan Crawford } 379255232f09SEwan Crawford }; 379355232f09SEwan Crawford 379455232f09SEwan Crawford class CommandObjectRenderScriptRuntimeAllocationSave : public CommandObjectParsed 379555232f09SEwan Crawford { 379655232f09SEwan Crawford public: 379755232f09SEwan Crawford CommandObjectRenderScriptRuntimeAllocationSave(CommandInterpreter &interpreter) 379855232f09SEwan Crawford : CommandObjectParsed(interpreter, "renderscript allocation save", 379955232f09SEwan Crawford "Write renderscript allocation contents to a file.", "renderscript allocation save <ID> <filename>", 380055232f09SEwan Crawford eCommandRequiresProcess | eCommandProcessMustBeLaunched) 380155232f09SEwan Crawford { 380255232f09SEwan Crawford } 380355232f09SEwan Crawford 3804222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeAllocationSave() override = default; 380555232f09SEwan Crawford 380655232f09SEwan Crawford bool 3807222b937cSEugene Zelenko DoExecute(Args &command, CommandReturnObject &result) override 380855232f09SEwan Crawford { 380955232f09SEwan Crawford const size_t argc = command.GetArgumentCount(); 381055232f09SEwan Crawford if (argc != 2) 381155232f09SEwan Crawford { 381255232f09SEwan Crawford result.AppendErrorWithFormat("'%s' takes 2 arguments, an allocation ID and filename to read from.", m_cmd_name.c_str()); 381355232f09SEwan Crawford result.SetStatus(eReturnStatusFailed); 381455232f09SEwan Crawford return false; 381555232f09SEwan Crawford } 381655232f09SEwan Crawford 381755232f09SEwan Crawford RenderScriptRuntime *runtime = 381855232f09SEwan Crawford static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript)); 381955232f09SEwan Crawford 382055232f09SEwan Crawford const char* id_cstr = command.GetArgumentAtIndex(0); 382155232f09SEwan Crawford bool convert_complete = false; 382255232f09SEwan Crawford const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete); 382355232f09SEwan Crawford if (!convert_complete) 382455232f09SEwan Crawford { 382555232f09SEwan Crawford result.AppendErrorWithFormat ("invalid allocation id argument '%s'", id_cstr); 382655232f09SEwan Crawford result.SetStatus (eReturnStatusFailed); 382755232f09SEwan Crawford return false; 382855232f09SEwan Crawford } 382955232f09SEwan Crawford 383055232f09SEwan Crawford const char* filename = command.GetArgumentAtIndex(1); 383155232f09SEwan Crawford bool success = runtime->SaveAllocation(result.GetOutputStream(), id, filename, m_exe_ctx.GetFramePtr()); 383255232f09SEwan Crawford 383355232f09SEwan Crawford if (success) 383455232f09SEwan Crawford result.SetStatus(eReturnStatusSuccessFinishResult); 383555232f09SEwan Crawford else 383655232f09SEwan Crawford result.SetStatus(eReturnStatusFailed); 383755232f09SEwan Crawford 383855232f09SEwan Crawford return true; 383955232f09SEwan Crawford } 384055232f09SEwan Crawford }; 384155232f09SEwan Crawford 384215f2bd95SEwan Crawford class CommandObjectRenderScriptRuntimeAllocation : public CommandObjectMultiword 384315f2bd95SEwan Crawford { 384415f2bd95SEwan Crawford public: 384515f2bd95SEwan Crawford CommandObjectRenderScriptRuntimeAllocation(CommandInterpreter &interpreter) 384615f2bd95SEwan Crawford : CommandObjectMultiword(interpreter, "renderscript allocation", "Commands that deal with renderscript allocations.", 384715f2bd95SEwan Crawford NULL) 384815f2bd95SEwan Crawford { 384915f2bd95SEwan Crawford LoadSubCommand("list", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationList(interpreter))); 3850a0f08674SEwan Crawford LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationDump(interpreter))); 385155232f09SEwan Crawford LoadSubCommand("save", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationSave(interpreter))); 385255232f09SEwan Crawford LoadSubCommand("load", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationLoad(interpreter))); 385315f2bd95SEwan Crawford } 385415f2bd95SEwan Crawford 3855222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeAllocation() override = default; 385615f2bd95SEwan Crawford }; 385715f2bd95SEwan Crawford 38584640cde1SColin Riley class CommandObjectRenderScriptRuntimeStatus : public CommandObjectParsed 38594640cde1SColin Riley { 38604640cde1SColin Riley public: 38614640cde1SColin Riley CommandObjectRenderScriptRuntimeStatus(CommandInterpreter &interpreter) 38624640cde1SColin Riley : CommandObjectParsed(interpreter, "renderscript status", 38634640cde1SColin Riley "Displays current renderscript runtime status.", "renderscript status", 38644640cde1SColin Riley eCommandRequiresProcess | eCommandProcessMustBeLaunched) 38654640cde1SColin Riley { 38664640cde1SColin Riley } 38674640cde1SColin Riley 3868222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeStatus() override = default; 38694640cde1SColin Riley 38704640cde1SColin Riley bool 3871222b937cSEugene Zelenko DoExecute(Args &command, CommandReturnObject &result) override 38724640cde1SColin Riley { 38734640cde1SColin Riley RenderScriptRuntime *runtime = 38744640cde1SColin Riley (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript); 38754640cde1SColin Riley runtime->Status(result.GetOutputStream()); 38764640cde1SColin Riley result.SetStatus(eReturnStatusSuccessFinishResult); 38774640cde1SColin Riley return true; 38784640cde1SColin Riley } 38794640cde1SColin Riley }; 38804640cde1SColin Riley 38815ec532a9SColin Riley class CommandObjectRenderScriptRuntime : public CommandObjectMultiword 38825ec532a9SColin Riley { 38835ec532a9SColin Riley public: 38845ec532a9SColin Riley CommandObjectRenderScriptRuntime(CommandInterpreter &interpreter) 38855ec532a9SColin Riley : CommandObjectMultiword(interpreter, "renderscript", "A set of commands for operating on renderscript.", 38865ec532a9SColin Riley "renderscript <subcommand> [<subcommand-options>]") 38875ec532a9SColin Riley { 38885ec532a9SColin Riley LoadSubCommand("module", CommandObjectSP(new CommandObjectRenderScriptRuntimeModule(interpreter))); 38894640cde1SColin Riley LoadSubCommand("status", CommandObjectSP(new CommandObjectRenderScriptRuntimeStatus(interpreter))); 38904640cde1SColin Riley LoadSubCommand("kernel", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernel(interpreter))); 38914640cde1SColin Riley LoadSubCommand("context", CommandObjectSP(new CommandObjectRenderScriptRuntimeContext(interpreter))); 389215f2bd95SEwan Crawford LoadSubCommand("allocation", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocation(interpreter))); 38935ec532a9SColin Riley } 38945ec532a9SColin Riley 3895222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntime() override = default; 38965ec532a9SColin Riley }; 3897ef20b08fSColin Riley 3898ef20b08fSColin Riley void 3899ef20b08fSColin Riley RenderScriptRuntime::Initiate() 39005ec532a9SColin Riley { 3901ef20b08fSColin Riley assert(!m_initiated); 39025ec532a9SColin Riley } 3903ef20b08fSColin Riley 3904ef20b08fSColin Riley RenderScriptRuntime::RenderScriptRuntime(Process *process) 39057dc7771cSEwan Crawford : lldb_private::CPPLanguageRuntime(process), m_initiated(false), m_debuggerPresentFlagged(false), 39067dc7771cSEwan Crawford m_breakAllKernels(false) 3907ef20b08fSColin Riley { 39084640cde1SColin Riley ModulesDidLoad(process->GetTarget().GetImages()); 3909ef20b08fSColin Riley } 39104640cde1SColin Riley 39114640cde1SColin Riley lldb::CommandObjectSP 39124640cde1SColin Riley RenderScriptRuntime::GetCommandObject(lldb_private::CommandInterpreter& interpreter) 39134640cde1SColin Riley { 39144640cde1SColin Riley static CommandObjectSP command_object; 39154640cde1SColin Riley if(!command_object) 39164640cde1SColin Riley { 39174640cde1SColin Riley command_object.reset(new CommandObjectRenderScriptRuntime(interpreter)); 39184640cde1SColin Riley } 39194640cde1SColin Riley return command_object; 39204640cde1SColin Riley } 39214640cde1SColin Riley 392278f339d1SEwan Crawford RenderScriptRuntime::~RenderScriptRuntime() = default; 3923