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,
171*2e920715SEwan Crawford         RS_TYPE_BOOLEAN,
172*2e920715SEwan Crawford 
173*2e920715SEwan Crawford         RS_TYPE_UNSIGNED_5_6_5,
174*2e920715SEwan Crawford         RS_TYPE_UNSIGNED_5_5_5_1,
175*2e920715SEwan Crawford         RS_TYPE_UNSIGNED_4_4_4_4,
176*2e920715SEwan Crawford 
177*2e920715SEwan Crawford         RS_TYPE_MATRIX_4X4,
178*2e920715SEwan Crawford         RS_TYPE_MATRIX_3X3,
179*2e920715SEwan Crawford         RS_TYPE_MATRIX_2X2,
180*2e920715SEwan Crawford 
181*2e920715SEwan Crawford         RS_TYPE_ELEMENT = 1000,
182*2e920715SEwan Crawford         RS_TYPE_TYPE,
183*2e920715SEwan Crawford         RS_TYPE_ALLOCATION,
184*2e920715SEwan Crawford         RS_TYPE_SAMPLER,
185*2e920715SEwan Crawford         RS_TYPE_SCRIPT,
186*2e920715SEwan Crawford         RS_TYPE_MESH,
187*2e920715SEwan Crawford         RS_TYPE_PROGRAM_FRAGMENT,
188*2e920715SEwan Crawford         RS_TYPE_PROGRAM_VERTEX,
189*2e920715SEwan Crawford         RS_TYPE_PROGRAM_RASTER,
190*2e920715SEwan Crawford         RS_TYPE_PROGRAM_STORE,
191*2e920715SEwan Crawford         RS_TYPE_FONT,
192*2e920715SEwan Crawford 
193*2e920715SEwan 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"},
327*2e920715SEwan Crawford     {"bool", "bool2", "bool3", "bool4"},
328*2e920715SEwan Crawford     {"packed_565", "packed_565", "packed_565", "packed_565"},
329*2e920715SEwan Crawford     {"packed_5551", "packed_5551", "packed_5551", "packed_5551"},
330*2e920715SEwan Crawford     {"packed_4444", "packed_4444", "packed_4444", "packed_4444"},
331*2e920715SEwan Crawford     {"rs_matrix4x4", "rs_matrix4x4", "rs_matrix4x4", "rs_matrix4x4"},
332*2e920715SEwan Crawford     {"rs_matrix3x3", "rs_matrix3x3", "rs_matrix3x3", "rs_matrix3x3"},
333*2e920715SEwan Crawford     {"rs_matrix2x2", "rs_matrix2x2", "rs_matrix2x2", "rs_matrix2x2"},
334*2e920715SEwan Crawford 
335*2e920715SEwan Crawford     // Handlers
336*2e920715SEwan Crawford     {"RS Element", "RS Element", "RS Element", "RS Element"},
337*2e920715SEwan Crawford     {"RS Type", "RS Type", "RS Type", "RS Type"},
338*2e920715SEwan Crawford     {"RS Allocation", "RS Allocation", "RS Allocation", "RS Allocation"},
339*2e920715SEwan Crawford     {"RS Sampler", "RS Sampler", "RS Sampler", "RS Sampler"},
340*2e920715SEwan Crawford     {"RS Script", "RS Script", "RS Script", "RS Script"},
341*2e920715SEwan Crawford 
342*2e920715SEwan Crawford     // Deprecated
343*2e920715SEwan Crawford     {"RS Mesh", "RS Mesh", "RS Mesh", "RS Mesh"},
344*2e920715SEwan Crawford     {"RS Program Fragment", "RS Program Fragment", "RS Program Fragment", "RS Program Fragment"},
345*2e920715SEwan Crawford     {"RS Program Vertex", "RS Program Vertex", "RS Program Vertex", "RS Program Vertex"},
346*2e920715SEwan Crawford     {"RS Program Raster", "RS Program Raster", "RS Program Raster", "RS Program Raster"},
347*2e920715SEwan Crawford     {"RS Program Store", "RS Program Store", "RS Program Store", "RS Program Store"},
348*2e920715SEwan 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
373*2e920715SEwan Crawford     {eFormatBoolean, eFormatBoolean, 1}, // RS_TYPE_BOOL
374*2e920715SEwan Crawford     {eFormatHex, eFormatHex, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_5_6_5
375*2e920715SEwan Crawford     {eFormatHex, eFormatHex, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_5_5_5_1
376*2e920715SEwan Crawford     {eFormatHex, eFormatHex, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_4_4_4_4
377*2e920715SEwan Crawford     {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 16}, // RS_TYPE_MATRIX_4X4
378*2e920715SEwan Crawford     {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 9}, // RS_TYPE_MATRIX_3X3
379*2e920715SEwan 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();
1948*2e920715SEwan 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;
1953*2e920715SEwan 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     }
1965*2e920715SEwan Crawford     else if (type == Element::RS_TYPE_UNSIGNED_5_6_5 || type == Element::RS_TYPE_UNSIGNED_5_5_5_1 ||
1966*2e920715SEwan Crawford              type == Element::RS_TYPE_UNSIGNED_4_4_4_4) // These have been packed already
1967*2e920715SEwan Crawford     {
1968*2e920715SEwan Crawford         data_size = AllocationDetails::RSTypeToFormat[type][eElementSize];
1969*2e920715SEwan Crawford     }
1970*2e920715SEwan Crawford     else if (type < Element::RS_TYPE_ELEMENT)
1971*2e920715SEwan Crawford     {
19728b244e21SEwan Crawford         data_size = vec_size * AllocationDetails::RSTypeToFormat[type][eElementSize];
1973*2e920715SEwan Crawford         if (vec_size == 3)
1974*2e920715SEwan Crawford             padding = AllocationDetails::RSTypeToFormat[type][eElementSize];
1975*2e920715SEwan Crawford     }
1976*2e920715SEwan Crawford     else
1977*2e920715SEwan 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     {
2109*2e920715SEwan Crawford         // Enum value isn't monotonous, so doesn't always index RsDataTypeToString array
2110*2e920715SEwan Crawford         unsigned int printable_target_type_index = type;
2111*2e920715SEwan Crawford         unsigned int printable_head_type_index = head->type;
2112*2e920715SEwan Crawford         if (type >= Element::RS_TYPE_ELEMENT && type <= Element::RS_TYPE_FONT)
2113*2e920715SEwan Crawford             printable_target_type_index = static_cast<Element::DataType>(
2114*2e920715SEwan Crawford                                          (type - Element::RS_TYPE_ELEMENT) + Element::RS_TYPE_MATRIX_2X2 + 1);
2115*2e920715SEwan Crawford 
2116*2e920715SEwan Crawford         if (head->type >= Element::RS_TYPE_ELEMENT && head->type <= Element::RS_TYPE_FONT)
2117*2e920715SEwan Crawford             printable_head_type_index = static_cast<Element::DataType>(
2118*2e920715SEwan Crawford                                         (head->type - Element::RS_TYPE_ELEMENT) + Element::RS_TYPE_MATRIX_2X2 + 1);
2119*2e920715SEwan Crawford 
2120*2e920715SEwan Crawford         const char* file_type_cstr = AllocationDetails::RsDataTypeToString[printable_head_type_index][0];
2121*2e920715SEwan 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",
2124*2e920715SEwan 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)
2234eba832beSJason Molenda         log->Printf("RenderScriptRuntime::SaveAllocation - Writing 0x%" PRIx64 " bytes from %p", (uint64_t) num_bytes, 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 
2606*2e920715SEwan Crawford     assert(type >= Element::RS_TYPE_NONE && type <= Element::RS_TYPE_FONT
2607a0f08674SEwan Crawford                                                    && "Invalid allocation type");
2608a0f08674SEwan Crawford 
2609*2e920715SEwan Crawford     lldb::Format format;
2610*2e920715SEwan Crawford     if (type >= Element::RS_TYPE_ELEMENT)
2611*2e920715SEwan Crawford         format = eFormatHex;
2612*2e920715SEwan Crawford     else
2613*2e920715SEwan 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     {
2625*2e920715SEwan 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();
2779*2e920715SEwan 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());
2783*2e920715SEwan Crawford             else
2784*2e920715SEwan Crawford             {
2785*2e920715SEwan Crawford                 // Enum value isn't monotonous, so doesn't always index RsDataTypeToString array
2786*2e920715SEwan Crawford                 if (type >= Element::RS_TYPE_ELEMENT && type <= Element::RS_TYPE_FONT)
2787*2e920715SEwan Crawford                     type = static_cast<Element::DataType>((type - Element::RS_TYPE_ELEMENT) +  Element::RS_TYPE_MATRIX_2X2 + 1);
2788*2e920715SEwan Crawford 
2789*2e920715SEwan Crawford                 if (type >= (sizeof(AllocationDetails::RsDataTypeToString) / sizeof(AllocationDetails::RsDataTypeToString[0]))
2790*2e920715SEwan 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             }
2795*2e920715SEwan 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, &regex_match))
3328018f5a7eSEwan Crawford                 matched = true;
3329018f5a7eSEwan Crawford             else if(regex.Compile("^([0-9]+),([0-9]+)$") && regex.Execute(id_cstr, &regex_match))
3330018f5a7eSEwan Crawford                 matched = true;
3331018f5a7eSEwan Crawford             else if(regex.Compile("^([0-9]+)$") && regex.Execute(id_cstr, &regex_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