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