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 
105ec532a9SColin Riley #include "RenderScriptRuntime.h"
115ec532a9SColin Riley 
125ec532a9SColin Riley #include "lldb/Core/ConstString.h"
135ec532a9SColin Riley #include "lldb/Core/Debugger.h"
145ec532a9SColin Riley #include "lldb/Core/Error.h"
155ec532a9SColin Riley #include "lldb/Core/Log.h"
165ec532a9SColin Riley #include "lldb/Core/PluginManager.h"
17a0f08674SEwan Crawford #include "lldb/Host/StringConvert.h"
185ec532a9SColin Riley #include "lldb/Symbol/Symbol.h"
194640cde1SColin Riley #include "lldb/Symbol/Type.h"
205ec532a9SColin Riley #include "lldb/Target/Process.h"
215ec532a9SColin Riley #include "lldb/Target/Target.h"
225ec532a9SColin Riley #include "lldb/Interpreter/Args.h"
235ec532a9SColin Riley #include "lldb/Interpreter/Options.h"
245ec532a9SColin Riley #include "lldb/Interpreter/CommandInterpreter.h"
255ec532a9SColin Riley #include "lldb/Interpreter/CommandReturnObject.h"
265ec532a9SColin Riley #include "lldb/Interpreter/CommandObjectMultiword.h"
274640cde1SColin Riley #include "lldb/Breakpoint/StoppointCallbackContext.h"
284640cde1SColin Riley #include "lldb/Target/RegisterContext.h"
2915f2bd95SEwan Crawford #include "lldb/Expression/UserExpression.h"
304640cde1SColin Riley #include "lldb/Symbol/VariableList.h"
315ec532a9SColin Riley 
325ec532a9SColin Riley using namespace lldb;
335ec532a9SColin Riley using namespace lldb_private;
3498156583SEwan Crawford using namespace lldb_renderscript;
355ec532a9SColin Riley 
3678f339d1SEwan Crawford namespace {
3778f339d1SEwan Crawford 
3878f339d1SEwan Crawford // The empirical_type adds a basic level of validation to arbitrary data
3978f339d1SEwan Crawford // allowing us to track if data has been discovered and stored or not.
4078f339d1SEwan Crawford // An empirical_type will be marked as valid only if it has been explicitly assigned to.
4178f339d1SEwan Crawford template <typename type_t>
4278f339d1SEwan Crawford class empirical_type
4378f339d1SEwan Crawford {
4478f339d1SEwan Crawford   public:
4578f339d1SEwan Crawford     // Ctor. Contents is invalid when constructed.
4678f339d1SEwan Crawford     empirical_type()
4778f339d1SEwan Crawford         : valid(false)
4878f339d1SEwan Crawford     {}
4978f339d1SEwan Crawford 
5078f339d1SEwan Crawford     // Return true and copy contents to out if valid, else return false.
5178f339d1SEwan Crawford     bool get(type_t& out) const
5278f339d1SEwan Crawford     {
5378f339d1SEwan Crawford         if (valid)
5478f339d1SEwan Crawford             out = data;
5578f339d1SEwan Crawford         return valid;
5678f339d1SEwan Crawford     }
5778f339d1SEwan Crawford 
5878f339d1SEwan Crawford     // Return a pointer to the contents or nullptr if it was not valid.
5978f339d1SEwan Crawford     const type_t* get() const
6078f339d1SEwan Crawford     {
6178f339d1SEwan Crawford         return valid ? &data : nullptr;
6278f339d1SEwan Crawford     }
6378f339d1SEwan Crawford 
6478f339d1SEwan Crawford     // Assign data explicitly.
6578f339d1SEwan Crawford     void set(const type_t in)
6678f339d1SEwan Crawford     {
6778f339d1SEwan Crawford         data = in;
6878f339d1SEwan Crawford         valid = true;
6978f339d1SEwan Crawford     }
7078f339d1SEwan Crawford 
7178f339d1SEwan Crawford     // Mark contents as invalid.
7278f339d1SEwan Crawford     void invalidate()
7378f339d1SEwan Crawford     {
7478f339d1SEwan Crawford         valid = false;
7578f339d1SEwan Crawford     }
7678f339d1SEwan Crawford 
7778f339d1SEwan Crawford     // Returns true if this type contains valid data.
7878f339d1SEwan Crawford     bool isValid() const
7978f339d1SEwan Crawford     {
8078f339d1SEwan Crawford         return valid;
8178f339d1SEwan Crawford     }
8278f339d1SEwan Crawford 
8378f339d1SEwan Crawford     // Assignment operator.
8478f339d1SEwan Crawford     empirical_type<type_t>& operator = (const type_t in)
8578f339d1SEwan Crawford     {
8678f339d1SEwan Crawford         set(in);
8778f339d1SEwan Crawford         return *this;
8878f339d1SEwan Crawford     }
8978f339d1SEwan Crawford 
9078f339d1SEwan Crawford     // Dereference operator returns contents.
9178f339d1SEwan Crawford     // Warning: Will assert if not valid so use only when you know data is valid.
9278f339d1SEwan Crawford     const type_t& operator * () const
9378f339d1SEwan Crawford     {
9478f339d1SEwan Crawford         assert(valid);
9578f339d1SEwan Crawford         return data;
9678f339d1SEwan Crawford     }
9778f339d1SEwan Crawford 
9878f339d1SEwan Crawford   protected:
9978f339d1SEwan Crawford     bool valid;
10078f339d1SEwan Crawford     type_t data;
10178f339d1SEwan Crawford };
10278f339d1SEwan Crawford 
10378f339d1SEwan Crawford } // namespace {}
10478f339d1SEwan Crawford 
10578f339d1SEwan Crawford // The ScriptDetails class collects data associated with a single script instance.
10678f339d1SEwan Crawford struct RenderScriptRuntime::ScriptDetails
10778f339d1SEwan Crawford {
10878f339d1SEwan Crawford     ~ScriptDetails() {};
10978f339d1SEwan Crawford 
11078f339d1SEwan Crawford     enum ScriptType
11178f339d1SEwan Crawford     {
11278f339d1SEwan Crawford         eScript,
11378f339d1SEwan Crawford         eScriptC
11478f339d1SEwan Crawford     };
11578f339d1SEwan Crawford 
11678f339d1SEwan Crawford     // The derived type of the script.
11778f339d1SEwan Crawford     empirical_type<ScriptType> type;
11878f339d1SEwan Crawford     // The name of the original source file.
11978f339d1SEwan Crawford     empirical_type<std::string> resName;
12078f339d1SEwan Crawford     // Path to script .so file on the device.
12178f339d1SEwan Crawford     empirical_type<std::string> scriptDyLib;
12278f339d1SEwan Crawford     // Directory where kernel objects are cached on device.
12378f339d1SEwan Crawford     empirical_type<std::string> cacheDir;
12478f339d1SEwan Crawford     // Pointer to the context which owns this script.
12578f339d1SEwan Crawford     empirical_type<lldb::addr_t> context;
12678f339d1SEwan Crawford     // Pointer to the script object itself.
12778f339d1SEwan Crawford     empirical_type<lldb::addr_t> script;
12878f339d1SEwan Crawford };
12978f339d1SEwan Crawford 
13078f339d1SEwan Crawford // This AllocationDetails class collects data associated with a single
13178f339d1SEwan Crawford // allocation instance.
13278f339d1SEwan Crawford struct RenderScriptRuntime::AllocationDetails
13378f339d1SEwan Crawford {
13415f2bd95SEwan Crawford    // Taken from rsDefines.h
13515f2bd95SEwan Crawford    enum DataKind
13615f2bd95SEwan Crawford    {
13715f2bd95SEwan Crawford        RS_KIND_USER,
13815f2bd95SEwan Crawford        RS_KIND_PIXEL_L = 7,
13915f2bd95SEwan Crawford        RS_KIND_PIXEL_A,
14015f2bd95SEwan Crawford        RS_KIND_PIXEL_LA,
14115f2bd95SEwan Crawford        RS_KIND_PIXEL_RGB,
14215f2bd95SEwan Crawford        RS_KIND_PIXEL_RGBA,
14315f2bd95SEwan Crawford        RS_KIND_PIXEL_DEPTH,
14415f2bd95SEwan Crawford        RS_KIND_PIXEL_YUV,
14515f2bd95SEwan Crawford        RS_KIND_INVALID = 100
14615f2bd95SEwan Crawford    };
14778f339d1SEwan Crawford 
14815f2bd95SEwan Crawford    // Taken from rsDefines.h
14978f339d1SEwan Crawford    enum DataType
15078f339d1SEwan Crawford    {
15115f2bd95SEwan Crawford        RS_TYPE_NONE = 0,
15215f2bd95SEwan Crawford        RS_TYPE_FLOAT_16,
15315f2bd95SEwan Crawford        RS_TYPE_FLOAT_32,
15415f2bd95SEwan Crawford        RS_TYPE_FLOAT_64,
15515f2bd95SEwan Crawford        RS_TYPE_SIGNED_8,
15615f2bd95SEwan Crawford        RS_TYPE_SIGNED_16,
15715f2bd95SEwan Crawford        RS_TYPE_SIGNED_32,
15815f2bd95SEwan Crawford        RS_TYPE_SIGNED_64,
15915f2bd95SEwan Crawford        RS_TYPE_UNSIGNED_8,
16015f2bd95SEwan Crawford        RS_TYPE_UNSIGNED_16,
16115f2bd95SEwan Crawford        RS_TYPE_UNSIGNED_32,
16215f2bd95SEwan Crawford        RS_TYPE_UNSIGNED_64,
16315f2bd95SEwan Crawford        RS_TYPE_BOOLEAN
16478f339d1SEwan Crawford     };
16578f339d1SEwan Crawford 
16615f2bd95SEwan Crawford     struct Dimension
16778f339d1SEwan Crawford     {
16815f2bd95SEwan Crawford         uint32_t dim_1;
16915f2bd95SEwan Crawford         uint32_t dim_2;
17015f2bd95SEwan Crawford         uint32_t dim_3;
17115f2bd95SEwan Crawford         uint32_t cubeMap;
17215f2bd95SEwan Crawford 
17315f2bd95SEwan Crawford         Dimension()
17415f2bd95SEwan Crawford         {
17515f2bd95SEwan Crawford              dim_1 = 0;
17615f2bd95SEwan Crawford              dim_2 = 0;
17715f2bd95SEwan Crawford              dim_3 = 0;
17815f2bd95SEwan Crawford              cubeMap = 0;
17915f2bd95SEwan Crawford         }
18078f339d1SEwan Crawford     };
18178f339d1SEwan Crawford 
18255232f09SEwan Crawford     // Header for reading and writing allocation contents
18355232f09SEwan Crawford     // to a binary file.
18455232f09SEwan Crawford     struct FileHeader
18555232f09SEwan Crawford     {
18655232f09SEwan Crawford         uint8_t ident[4];      // ASCII 'RSAD' identifying the file
18755232f09SEwan Crawford         uint16_t hdr_size;     // Header size in bytes, for backwards compatability
18855232f09SEwan Crawford         uint16_t type;         // DataType enum
18955232f09SEwan Crawford         uint32_t kind;         // DataKind enum
19055232f09SEwan Crawford         uint32_t dims[3];      // Dimensions
19155232f09SEwan Crawford         uint32_t element_size; // Size of a single element, including padding
19255232f09SEwan Crawford     };
19355232f09SEwan Crawford 
19415f2bd95SEwan Crawford     // Monotonically increasing from 1
19515f2bd95SEwan Crawford     static unsigned int ID;
19615f2bd95SEwan Crawford 
19715f2bd95SEwan Crawford     // Maps Allocation DataType enum and vector size to printable strings
19815f2bd95SEwan Crawford     // using mapping from RenderScript numerical types summary documentation
19915f2bd95SEwan Crawford     static const char* RsDataTypeToString[][4];
20015f2bd95SEwan Crawford 
20115f2bd95SEwan Crawford     // Maps Allocation DataKind enum to printable strings
20215f2bd95SEwan Crawford     static const char* RsDataKindToString[];
20315f2bd95SEwan Crawford 
204a0f08674SEwan Crawford     // Maps allocation types to format sizes for printing.
205a0f08674SEwan Crawford     static const unsigned int RSTypeToFormat[][3];
206a0f08674SEwan Crawford 
20715f2bd95SEwan Crawford     // Give each allocation an ID as a way
20815f2bd95SEwan Crawford     // for commands to reference it.
20915f2bd95SEwan Crawford     const unsigned int id;
21015f2bd95SEwan Crawford 
21115f2bd95SEwan Crawford     empirical_type<DataType> type;            // Type of each data pointer stored by the allocation
21215f2bd95SEwan Crawford     empirical_type<DataKind> type_kind;       // Defines pixel type if Allocation is created from an image
21315f2bd95SEwan Crawford     empirical_type<uint32_t> type_vec_size;   // Vector size of each data point, e.g '4' for uchar4
21415f2bd95SEwan Crawford     empirical_type<Dimension> dimension;      // Dimensions of the Allocation
21515f2bd95SEwan Crawford     empirical_type<lldb::addr_t> address;     // Pointer to address of the RS Allocation
21615f2bd95SEwan Crawford     empirical_type<lldb::addr_t> data_ptr;    // Pointer to the data held by the Allocation
21715f2bd95SEwan Crawford     empirical_type<lldb::addr_t> type_ptr;    // Pointer to the RS Type of the Allocation
21815f2bd95SEwan Crawford     empirical_type<lldb::addr_t> element_ptr; // Pointer to the RS Element of the Type
21915f2bd95SEwan Crawford     empirical_type<lldb::addr_t> context;     // Pointer to the RS Context of the Allocation
220a0f08674SEwan Crawford     empirical_type<uint32_t> size;            // Size of the allocation
221a0f08674SEwan Crawford     empirical_type<uint32_t> stride;          // Stride between rows of the allocation
22215f2bd95SEwan Crawford 
22315f2bd95SEwan Crawford     // Give each allocation an id, so we can reference it in user commands.
22415f2bd95SEwan Crawford     AllocationDetails(): id(ID++)
22515f2bd95SEwan Crawford     {
22615f2bd95SEwan Crawford     }
22715f2bd95SEwan Crawford 
22815f2bd95SEwan Crawford };
22915f2bd95SEwan Crawford 
23015f2bd95SEwan Crawford unsigned int RenderScriptRuntime::AllocationDetails::ID = 1;
23115f2bd95SEwan Crawford 
23215f2bd95SEwan Crawford const char* RenderScriptRuntime::AllocationDetails::RsDataKindToString[] =
23315f2bd95SEwan Crawford {
23415f2bd95SEwan Crawford    "User",
23515f2bd95SEwan Crawford    "Undefined", "Undefined", "Undefined", // Enum jumps from 0 to 7
23615f2bd95SEwan Crawford    "Undefined", "Undefined", "Undefined",
23715f2bd95SEwan Crawford    "L Pixel",
23815f2bd95SEwan Crawford    "A Pixel",
23915f2bd95SEwan Crawford    "LA Pixel",
24015f2bd95SEwan Crawford    "RGB Pixel",
24115f2bd95SEwan Crawford    "RGBA Pixel",
24215f2bd95SEwan Crawford    "Pixel Depth",
24315f2bd95SEwan Crawford    "YUV Pixel"
24415f2bd95SEwan Crawford };
24515f2bd95SEwan Crawford 
24615f2bd95SEwan Crawford const char* RenderScriptRuntime::AllocationDetails::RsDataTypeToString[][4] =
24715f2bd95SEwan Crawford {
24815f2bd95SEwan Crawford     {"None", "None", "None", "None"},
24915f2bd95SEwan Crawford     {"half", "half2", "half3", "half4"},
25015f2bd95SEwan Crawford     {"float", "float2", "float3", "float4"},
25115f2bd95SEwan Crawford     {"double", "double2", "double3", "double4"},
25215f2bd95SEwan Crawford     {"char", "char2", "char3", "char4"},
25315f2bd95SEwan Crawford     {"short", "short2", "short3", "short4"},
25415f2bd95SEwan Crawford     {"int", "int2", "int3", "int4"},
25515f2bd95SEwan Crawford     {"long", "long2", "long3", "long4"},
25615f2bd95SEwan Crawford     {"uchar", "uchar2", "uchar3", "uchar4"},
25715f2bd95SEwan Crawford     {"ushort", "ushort2", "ushort3", "ushort4"},
25815f2bd95SEwan Crawford     {"uint", "uint2", "uint3", "uint4"},
25915f2bd95SEwan Crawford     {"ulong", "ulong2", "ulong3", "ulong4"},
26015f2bd95SEwan Crawford     {"bool", "bool2", "bool3", "bool4"}
26178f339d1SEwan Crawford };
26278f339d1SEwan Crawford 
263a0f08674SEwan Crawford // Used as an index into the RSTypeToFormat array elements
264a0f08674SEwan Crawford enum TypeToFormatIndex {
265a0f08674SEwan Crawford    eFormatSingle = 0,
266a0f08674SEwan Crawford    eFormatVector,
267a0f08674SEwan Crawford    eElementSize
268a0f08674SEwan Crawford };
269a0f08674SEwan Crawford 
270a0f08674SEwan Crawford // { format enum of single element, format enum of element vector, size of element}
271a0f08674SEwan Crawford const unsigned int RenderScriptRuntime::AllocationDetails::RSTypeToFormat[][3] =
272a0f08674SEwan Crawford {
273a0f08674SEwan Crawford     {eFormatHex, eFormatHex, 1}, // RS_TYPE_NONE
274a0f08674SEwan Crawford     {eFormatFloat, eFormatVectorOfFloat16, 2}, // RS_TYPE_FLOAT_16
275a0f08674SEwan Crawford     {eFormatFloat, eFormatVectorOfFloat32, sizeof(float)}, // RS_TYPE_FLOAT_32
276a0f08674SEwan Crawford     {eFormatFloat, eFormatVectorOfFloat64, sizeof(double)}, // RS_TYPE_FLOAT_64
277a0f08674SEwan Crawford     {eFormatDecimal, eFormatVectorOfSInt8, sizeof(int8_t)}, // RS_TYPE_SIGNED_8
278a0f08674SEwan Crawford     {eFormatDecimal, eFormatVectorOfSInt16, sizeof(int16_t)}, // RS_TYPE_SIGNED_16
279a0f08674SEwan Crawford     {eFormatDecimal, eFormatVectorOfSInt32, sizeof(int32_t)}, // RS_TYPE_SIGNED_32
280a0f08674SEwan Crawford     {eFormatDecimal, eFormatVectorOfSInt64, sizeof(int64_t)}, // RS_TYPE_SIGNED_64
281a0f08674SEwan Crawford     {eFormatDecimal, eFormatVectorOfUInt8, sizeof(uint8_t)}, // RS_TYPE_UNSIGNED_8
282a0f08674SEwan Crawford     {eFormatDecimal, eFormatVectorOfUInt16, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_16
283a0f08674SEwan Crawford     {eFormatDecimal, eFormatVectorOfUInt32, sizeof(uint32_t)}, // RS_TYPE_UNSIGNED_32
284a0f08674SEwan Crawford     {eFormatDecimal, eFormatVectorOfUInt64, sizeof(uint64_t)}, // RS_TYPE_UNSIGNED_64
285a0f08674SEwan Crawford     {eFormatBoolean, eFormatBoolean, sizeof(bool)} // RS_TYPE_BOOL
286a0f08674SEwan Crawford };
287a0f08674SEwan Crawford 
2885ec532a9SColin Riley //------------------------------------------------------------------
2895ec532a9SColin Riley // Static Functions
2905ec532a9SColin Riley //------------------------------------------------------------------
2915ec532a9SColin Riley LanguageRuntime *
2925ec532a9SColin Riley RenderScriptRuntime::CreateInstance(Process *process, lldb::LanguageType language)
2935ec532a9SColin Riley {
2945ec532a9SColin Riley 
2955ec532a9SColin Riley     if (language == eLanguageTypeExtRenderScript)
2965ec532a9SColin Riley         return new RenderScriptRuntime(process);
2975ec532a9SColin Riley     else
2985ec532a9SColin Riley         return NULL;
2995ec532a9SColin Riley }
3005ec532a9SColin Riley 
30198156583SEwan Crawford // Callback with a module to search for matching symbols.
30298156583SEwan Crawford // We first check that the module contains RS kernels.
30398156583SEwan Crawford // Then look for a symbol which matches our kernel name.
30498156583SEwan Crawford // The breakpoint address is finally set using the address of this symbol.
30598156583SEwan Crawford Searcher::CallbackReturn
30698156583SEwan Crawford RSBreakpointResolver::SearchCallback(SearchFilter &filter,
30798156583SEwan Crawford                                      SymbolContext &context,
30898156583SEwan Crawford                                      Address*,
30998156583SEwan Crawford                                      bool)
31098156583SEwan Crawford {
31198156583SEwan Crawford     ModuleSP module = context.module_sp;
31298156583SEwan Crawford 
31398156583SEwan Crawford     if (!module)
31498156583SEwan Crawford         return Searcher::eCallbackReturnContinue;
31598156583SEwan Crawford 
31698156583SEwan Crawford     // Is this a module containing renderscript kernels?
31798156583SEwan Crawford     if (nullptr == module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData))
31898156583SEwan Crawford         return Searcher::eCallbackReturnContinue;
31998156583SEwan Crawford 
32098156583SEwan Crawford     // Attempt to set a breakpoint on the kernel name symbol within the module library.
32198156583SEwan Crawford     // If it's not found, it's likely debug info is unavailable - try to set a
32298156583SEwan Crawford     // breakpoint on <name>.expand.
32398156583SEwan Crawford 
32498156583SEwan Crawford     const Symbol* kernel_sym = module->FindFirstSymbolWithNameAndType(m_kernel_name, eSymbolTypeCode);
32598156583SEwan Crawford     if (!kernel_sym)
32698156583SEwan Crawford     {
32798156583SEwan Crawford         std::string kernel_name_expanded(m_kernel_name.AsCString());
32898156583SEwan Crawford         kernel_name_expanded.append(".expand");
32998156583SEwan Crawford         kernel_sym = module->FindFirstSymbolWithNameAndType(ConstString(kernel_name_expanded.c_str()), eSymbolTypeCode);
33098156583SEwan Crawford     }
33198156583SEwan Crawford 
33298156583SEwan Crawford     if (kernel_sym)
33398156583SEwan Crawford     {
33498156583SEwan Crawford         Address bp_addr = kernel_sym->GetAddress();
33598156583SEwan Crawford         if (filter.AddressPasses(bp_addr))
33698156583SEwan Crawford             m_breakpoint->AddLocation(bp_addr);
33798156583SEwan Crawford     }
33898156583SEwan Crawford 
33998156583SEwan Crawford     return Searcher::eCallbackReturnContinue;
34098156583SEwan Crawford }
34198156583SEwan Crawford 
3425ec532a9SColin Riley void
3435ec532a9SColin Riley RenderScriptRuntime::Initialize()
3445ec532a9SColin Riley {
3454640cde1SColin Riley     PluginManager::RegisterPlugin(GetPluginNameStatic(), "RenderScript language support", CreateInstance, GetCommandObject);
3465ec532a9SColin Riley }
3475ec532a9SColin Riley 
3485ec532a9SColin Riley void
3495ec532a9SColin Riley RenderScriptRuntime::Terminate()
3505ec532a9SColin Riley {
3515ec532a9SColin Riley     PluginManager::UnregisterPlugin(CreateInstance);
3525ec532a9SColin Riley }
3535ec532a9SColin Riley 
3545ec532a9SColin Riley lldb_private::ConstString
3555ec532a9SColin Riley RenderScriptRuntime::GetPluginNameStatic()
3565ec532a9SColin Riley {
3575ec532a9SColin Riley     static ConstString g_name("renderscript");
3585ec532a9SColin Riley     return g_name;
3595ec532a9SColin Riley }
3605ec532a9SColin Riley 
361ef20b08fSColin Riley RenderScriptRuntime::ModuleKind
362ef20b08fSColin Riley RenderScriptRuntime::GetModuleKind(const lldb::ModuleSP &module_sp)
363ef20b08fSColin Riley {
364ef20b08fSColin Riley     if (module_sp)
365ef20b08fSColin Riley     {
366ef20b08fSColin Riley         // Is this a module containing renderscript kernels?
367ef20b08fSColin Riley         const Symbol *info_sym = module_sp->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData);
368ef20b08fSColin Riley         if (info_sym)
369ef20b08fSColin Riley         {
370ef20b08fSColin Riley             return eModuleKindKernelObj;
371ef20b08fSColin Riley         }
3724640cde1SColin Riley 
3734640cde1SColin Riley         // Is this the main RS runtime library
3744640cde1SColin Riley         const ConstString rs_lib("libRS.so");
3754640cde1SColin Riley         if (module_sp->GetFileSpec().GetFilename() == rs_lib)
3764640cde1SColin Riley         {
3774640cde1SColin Riley             return eModuleKindLibRS;
3784640cde1SColin Riley         }
3794640cde1SColin Riley 
3804640cde1SColin Riley         const ConstString rs_driverlib("libRSDriver.so");
3814640cde1SColin Riley         if (module_sp->GetFileSpec().GetFilename() == rs_driverlib)
3824640cde1SColin Riley         {
3834640cde1SColin Riley             return eModuleKindDriver;
3844640cde1SColin Riley         }
3854640cde1SColin Riley 
38615f2bd95SEwan Crawford         const ConstString rs_cpureflib("libRSCpuRef.so");
3874640cde1SColin Riley         if (module_sp->GetFileSpec().GetFilename() == rs_cpureflib)
3884640cde1SColin Riley         {
3894640cde1SColin Riley             return eModuleKindImpl;
3904640cde1SColin Riley         }
3914640cde1SColin Riley 
392ef20b08fSColin Riley     }
393ef20b08fSColin Riley     return eModuleKindIgnored;
394ef20b08fSColin Riley }
395ef20b08fSColin Riley 
396ef20b08fSColin Riley bool
397ef20b08fSColin Riley RenderScriptRuntime::IsRenderScriptModule(const lldb::ModuleSP &module_sp)
398ef20b08fSColin Riley {
399ef20b08fSColin Riley     return GetModuleKind(module_sp) != eModuleKindIgnored;
400ef20b08fSColin Riley }
401ef20b08fSColin Riley 
402ef20b08fSColin Riley 
403ef20b08fSColin Riley void
404ef20b08fSColin Riley RenderScriptRuntime::ModulesDidLoad(const ModuleList &module_list )
405ef20b08fSColin Riley {
406ef20b08fSColin Riley     Mutex::Locker locker (module_list.GetMutex ());
407ef20b08fSColin Riley 
408ef20b08fSColin Riley     size_t num_modules = module_list.GetSize();
409ef20b08fSColin Riley     for (size_t i = 0; i < num_modules; i++)
410ef20b08fSColin Riley     {
411ef20b08fSColin Riley         auto mod = module_list.GetModuleAtIndex (i);
412ef20b08fSColin Riley         if (IsRenderScriptModule (mod))
413ef20b08fSColin Riley         {
414ef20b08fSColin Riley             LoadModule(mod);
415ef20b08fSColin Riley         }
416ef20b08fSColin Riley     }
417ef20b08fSColin Riley }
418ef20b08fSColin Riley 
419ef20b08fSColin Riley 
4205ec532a9SColin Riley //------------------------------------------------------------------
4215ec532a9SColin Riley // PluginInterface protocol
4225ec532a9SColin Riley //------------------------------------------------------------------
4235ec532a9SColin Riley lldb_private::ConstString
4245ec532a9SColin Riley RenderScriptRuntime::GetPluginName()
4255ec532a9SColin Riley {
4265ec532a9SColin Riley     return GetPluginNameStatic();
4275ec532a9SColin Riley }
4285ec532a9SColin Riley 
4295ec532a9SColin Riley uint32_t
4305ec532a9SColin Riley RenderScriptRuntime::GetPluginVersion()
4315ec532a9SColin Riley {
4325ec532a9SColin Riley     return 1;
4335ec532a9SColin Riley }
4345ec532a9SColin Riley 
4355ec532a9SColin Riley bool
4365ec532a9SColin Riley RenderScriptRuntime::IsVTableName(const char *name)
4375ec532a9SColin Riley {
4385ec532a9SColin Riley     return false;
4395ec532a9SColin Riley }
4405ec532a9SColin Riley 
4415ec532a9SColin Riley bool
4425ec532a9SColin Riley RenderScriptRuntime::GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic,
4430b6003f3SEnrico Granata                                               TypeAndOrName &class_type_or_name, Address &address,
4440b6003f3SEnrico Granata                                               Value::ValueType &value_type)
4455ec532a9SColin Riley {
4465ec532a9SColin Riley     return false;
4475ec532a9SColin Riley }
4485ec532a9SColin Riley 
449c74275bcSEnrico Granata TypeAndOrName
450c74275bcSEnrico Granata RenderScriptRuntime::FixUpDynamicType (const TypeAndOrName& type_and_or_name,
4517eed4877SEnrico Granata                                        ValueObject& static_value)
452c74275bcSEnrico Granata {
453c74275bcSEnrico Granata     return type_and_or_name;
454c74275bcSEnrico Granata }
455c74275bcSEnrico Granata 
4565ec532a9SColin Riley bool
4575ec532a9SColin Riley RenderScriptRuntime::CouldHaveDynamicValue(ValueObject &in_value)
4585ec532a9SColin Riley {
4595ec532a9SColin Riley     return false;
4605ec532a9SColin Riley }
4615ec532a9SColin Riley 
4625ec532a9SColin Riley lldb::BreakpointResolverSP
4635ec532a9SColin Riley RenderScriptRuntime::CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp)
4645ec532a9SColin Riley {
4655ec532a9SColin Riley     BreakpointResolverSP resolver_sp;
4665ec532a9SColin Riley     return resolver_sp;
4675ec532a9SColin Riley }
4685ec532a9SColin Riley 
4694640cde1SColin Riley 
4704640cde1SColin Riley const RenderScriptRuntime::HookDefn RenderScriptRuntime::s_runtimeHookDefns[] =
4714640cde1SColin Riley {
4724640cde1SColin Riley     //rsdScript
47382780287SAidan Dodds     {
47482780287SAidan Dodds         "rsdScriptInit", //name
47582780287SAidan Dodds         "_Z13rsdScriptInitPKN7android12renderscript7ContextEPNS0_7ScriptCEPKcS7_PKhjj", // symbol name 32 bit
47682780287SAidan Dodds         "_Z13rsdScriptInitPKN7android12renderscript7ContextEPNS0_7ScriptCEPKcS7_PKhmj", // symbol name 64 bit
47782780287SAidan Dodds         0, // version
47882780287SAidan Dodds         RenderScriptRuntime::eModuleKindDriver, // type
47982780287SAidan Dodds         &lldb_private::RenderScriptRuntime::CaptureScriptInit1 // handler
48082780287SAidan Dodds     },
48182780287SAidan Dodds     {
48282780287SAidan Dodds         "rsdScriptInvokeForEach", // name
48382780287SAidan Dodds         "_Z22rsdScriptInvokeForEachPKN7android12renderscript7ContextEPNS0_6ScriptEjPKNS0_10AllocationEPS6_PKvjPK12RsScriptCall", // symbol name 32bit
48482780287SAidan Dodds         "_Z22rsdScriptInvokeForEachPKN7android12renderscript7ContextEPNS0_6ScriptEjPKNS0_10AllocationEPS6_PKvmPK12RsScriptCall", // symbol name 64bit
48582780287SAidan Dodds         0, // version
48682780287SAidan Dodds         RenderScriptRuntime::eModuleKindDriver, // type
48782780287SAidan Dodds         nullptr // handler
48882780287SAidan Dodds     },
48982780287SAidan Dodds     {
49082780287SAidan Dodds         "rsdScriptInvokeForEachMulti", // name
49182780287SAidan Dodds         "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0_6ScriptEjPPKNS0_10AllocationEjPS6_PKvjPK12RsScriptCall", // symbol name 32bit
49282780287SAidan Dodds         "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0_6ScriptEjPPKNS0_10AllocationEmPS6_PKvmPK12RsScriptCall", // symbol name 64bit
49382780287SAidan Dodds         0, // version
49482780287SAidan Dodds         RenderScriptRuntime::eModuleKindDriver, // type
49582780287SAidan Dodds         nullptr // handler
49682780287SAidan Dodds     },
49782780287SAidan Dodds     {
49882780287SAidan Dodds         "rsdScriptInvokeFunction", // name
49982780287SAidan Dodds         "_Z23rsdScriptInvokeFunctionPKN7android12renderscript7ContextEPNS0_6ScriptEjPKvj", // symbol name 32bit
50082780287SAidan Dodds         "_Z23rsdScriptInvokeFunctionPKN7android12renderscript7ContextEPNS0_6ScriptEjPKvm", // symbol name 64bit
50182780287SAidan Dodds         0, // version
50282780287SAidan Dodds         RenderScriptRuntime::eModuleKindDriver, // type
50382780287SAidan Dodds         nullptr // handler
50482780287SAidan Dodds     },
50582780287SAidan Dodds     {
50682780287SAidan Dodds         "rsdScriptSetGlobalVar", // name
50782780287SAidan Dodds         "_Z21rsdScriptSetGlobalVarPKN7android12renderscript7ContextEPKNS0_6ScriptEjPvj", // symbol name 32bit
50882780287SAidan Dodds         "_Z21rsdScriptSetGlobalVarPKN7android12renderscript7ContextEPKNS0_6ScriptEjPvm", // symbol name 64bit
50982780287SAidan Dodds         0, // version
51082780287SAidan Dodds         RenderScriptRuntime::eModuleKindDriver, // type
51182780287SAidan Dodds         &lldb_private::RenderScriptRuntime::CaptureSetGlobalVar1 // handler
51282780287SAidan Dodds     },
5134640cde1SColin Riley 
5144640cde1SColin Riley     //rsdAllocation
51582780287SAidan Dodds     {
51682780287SAidan Dodds         "rsdAllocationInit", // name
51782780287SAidan Dodds         "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_10AllocationEb", // symbol name 32bit
51882780287SAidan Dodds         "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_10AllocationEb", // symbol name 64bit
51982780287SAidan Dodds         0, // version
52082780287SAidan Dodds         RenderScriptRuntime::eModuleKindDriver, // type
52182780287SAidan Dodds         &lldb_private::RenderScriptRuntime::CaptureAllocationInit1 // handler
52282780287SAidan Dodds     },
52382780287SAidan Dodds     {
52482780287SAidan Dodds         "rsdAllocationRead2D", //name
52582780287SAidan Dodds         "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_10AllocationEjjj23RsAllocationCubemapFacejjPvjj", // symbol name 32bit
52682780287SAidan Dodds         "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_10AllocationEjjj23RsAllocationCubemapFacejjPvmm", // symbol name 64bit
52782780287SAidan Dodds         0, // version
52882780287SAidan Dodds         RenderScriptRuntime::eModuleKindDriver, // type
52982780287SAidan Dodds         nullptr // handler
53082780287SAidan Dodds     },
5314640cde1SColin Riley };
5324640cde1SColin Riley const size_t RenderScriptRuntime::s_runtimeHookCount = sizeof(s_runtimeHookDefns)/sizeof(s_runtimeHookDefns[0]);
5334640cde1SColin Riley 
5344640cde1SColin Riley 
5354640cde1SColin Riley bool
5364640cde1SColin Riley RenderScriptRuntime::HookCallback(void *baton, StoppointCallbackContext *ctx, lldb::user_id_t break_id, lldb::user_id_t break_loc_id)
5374640cde1SColin Riley {
5384640cde1SColin Riley     RuntimeHook* hook_info = (RuntimeHook*)baton;
5394640cde1SColin Riley     ExecutionContext context(ctx->exe_ctx_ref);
5404640cde1SColin Riley 
5414640cde1SColin Riley     RenderScriptRuntime *lang_rt = (RenderScriptRuntime *)context.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
5424640cde1SColin Riley 
5434640cde1SColin Riley     lang_rt->HookCallback(hook_info, context);
5444640cde1SColin Riley 
5454640cde1SColin Riley     return false;
5464640cde1SColin Riley }
5474640cde1SColin Riley 
5484640cde1SColin Riley 
5494640cde1SColin Riley void
5504640cde1SColin Riley RenderScriptRuntime::HookCallback(RuntimeHook* hook_info, ExecutionContext& context)
5514640cde1SColin Riley {
5524640cde1SColin Riley     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
5534640cde1SColin Riley 
5544640cde1SColin Riley     if (log)
5554640cde1SColin Riley         log->Printf ("RenderScriptRuntime::HookCallback - '%s' .", hook_info->defn->name);
5564640cde1SColin Riley 
5574640cde1SColin Riley     if (hook_info->defn->grabber)
5584640cde1SColin Riley     {
5594640cde1SColin Riley         (this->*(hook_info->defn->grabber))(hook_info, context);
5604640cde1SColin Riley     }
5614640cde1SColin Riley }
5624640cde1SColin Riley 
5634640cde1SColin Riley 
5644640cde1SColin Riley bool
56582780287SAidan Dodds RenderScriptRuntime::GetArgSimple(ExecutionContext &context, uint32_t arg, uint64_t *data)
5664640cde1SColin Riley {
5674640cde1SColin Riley     if (!data)
5684640cde1SColin Riley         return false;
5694640cde1SColin Riley 
57082780287SAidan Dodds     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
5714640cde1SColin Riley     Error error;
5724640cde1SColin Riley     RegisterContext* reg_ctx = context.GetRegisterContext();
5734640cde1SColin Riley     Process* process = context.GetProcessPtr();
57482780287SAidan Dodds     bool success = false; // return value
5754640cde1SColin Riley 
57682780287SAidan Dodds     if (!context.GetTargetPtr())
57782780287SAidan Dodds     {
57882780287SAidan Dodds         if (log)
57982780287SAidan Dodds             log->Printf("RenderScriptRuntime::GetArgSimple - Invalid target");
58082780287SAidan Dodds 
58182780287SAidan Dodds         return false;
58282780287SAidan Dodds     }
58382780287SAidan Dodds 
58482780287SAidan Dodds     switch (context.GetTargetPtr()->GetArchitecture().GetMachine())
58582780287SAidan Dodds     {
58682780287SAidan Dodds         case llvm::Triple::ArchType::x86:
5874640cde1SColin Riley         {
5884640cde1SColin Riley             uint64_t sp = reg_ctx->GetSP();
5894640cde1SColin Riley             uint32_t offset = (1 + arg) * sizeof(uint32_t);
59082780287SAidan Dodds             uint32_t result = 0;
59182780287SAidan Dodds             process->ReadMemory(sp + offset, &result, sizeof(uint32_t), error);
5924640cde1SColin Riley             if (error.Fail())
5934640cde1SColin Riley             {
5944640cde1SColin Riley                 if (log)
59582780287SAidan Dodds                     log->Printf ("RenderScriptRuntime:: GetArgSimple - error reading X86 stack: %s.", error.AsCString());
5964640cde1SColin Riley             }
59782780287SAidan Dodds             else
5984640cde1SColin Riley             {
59982780287SAidan Dodds                 *data = result;
60082780287SAidan Dodds                 success = true;
60182780287SAidan Dodds             }
60282780287SAidan Dodds 
60382780287SAidan Dodds             break;
60482780287SAidan Dodds         }
60582780287SAidan Dodds         case llvm::Triple::ArchType::arm:
60682780287SAidan Dodds         {
60782780287SAidan Dodds             // arm 32 bit
6084640cde1SColin Riley             if (arg < 4)
6094640cde1SColin Riley             {
6104640cde1SColin Riley                 const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg);
6114640cde1SColin Riley                 RegisterValue rVal;
612*02f1c5d1SEwan Crawford                 success = reg_ctx->ReadRegister(rArg, rVal);
613*02f1c5d1SEwan Crawford                 if (success)
614*02f1c5d1SEwan Crawford                 {
6154640cde1SColin Riley                     (*data) = rVal.GetAsUInt32();
616*02f1c5d1SEwan Crawford                 }
617*02f1c5d1SEwan Crawford                 else
618*02f1c5d1SEwan Crawford                 {
619*02f1c5d1SEwan Crawford                     if (log)
620*02f1c5d1SEwan Crawford                         log->Printf ("RenderScriptRuntime:: GetArgSimple - error reading ARM register: %d.", arg);
621*02f1c5d1SEwan Crawford                 }
6224640cde1SColin Riley             }
6234640cde1SColin Riley             else
6244640cde1SColin Riley             {
6254640cde1SColin Riley                 uint64_t sp = reg_ctx->GetSP();
6264640cde1SColin Riley                 uint32_t offset = (arg-4) * sizeof(uint32_t);
6274640cde1SColin Riley                 process->ReadMemory(sp + offset, &data, sizeof(uint32_t), error);
6284640cde1SColin Riley                 if (error.Fail())
6294640cde1SColin Riley                 {
6304640cde1SColin Riley                     if (log)
63182780287SAidan Dodds                         log->Printf ("RenderScriptRuntime:: GetArgSimple - error reading ARM stack: %s.", error.AsCString());
63282780287SAidan Dodds                 }
63382780287SAidan Dodds                 else
63482780287SAidan Dodds                 {
63582780287SAidan Dodds                     success = true;
6364640cde1SColin Riley                 }
6374640cde1SColin Riley             }
63882780287SAidan Dodds 
63982780287SAidan Dodds             break;
6404640cde1SColin Riley         }
64182780287SAidan Dodds         case llvm::Triple::ArchType::aarch64:
64282780287SAidan Dodds         {
64382780287SAidan Dodds             // arm 64 bit
64482780287SAidan Dodds             // first 8 arguments are in the registers
64582780287SAidan Dodds             if (arg < 8)
64682780287SAidan Dodds             {
64782780287SAidan Dodds                 const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg);
64882780287SAidan Dodds                 RegisterValue rVal;
64982780287SAidan Dodds                 success = reg_ctx->ReadRegister(rArg, rVal);
65082780287SAidan Dodds                 if (success)
65182780287SAidan Dodds                 {
65282780287SAidan Dodds                     *data = rVal.GetAsUInt64();
65382780287SAidan Dodds                 }
65482780287SAidan Dodds                 else
65582780287SAidan Dodds                 {
65682780287SAidan Dodds                     if (log)
65782780287SAidan Dodds                         log->Printf("RenderScriptRuntime::GetArgSimple() - AARCH64 - Error while reading the argument #%d", arg);
65882780287SAidan Dodds                 }
65982780287SAidan Dodds             }
66082780287SAidan Dodds             else
66182780287SAidan Dodds             {
66282780287SAidan Dodds                 // @TODO: need to find the argument in the stack
66382780287SAidan Dodds                 if (log)
66482780287SAidan Dodds                     log->Printf("RenderScriptRuntime::GetArgSimple - AARCH64 - FOR #ARG >= 8 NOT IMPLEMENTED YET. Argument number: %d", arg);
66582780287SAidan Dodds             }
66682780287SAidan Dodds             break;
66782780287SAidan Dodds         }
668*02f1c5d1SEwan Crawford         case llvm::Triple::ArchType::mips64el:
669*02f1c5d1SEwan Crawford         {
670*02f1c5d1SEwan Crawford             // read from the registers
671*02f1c5d1SEwan Crawford             if (arg < 8)
672*02f1c5d1SEwan Crawford             {
673*02f1c5d1SEwan Crawford                 const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg + 4);
674*02f1c5d1SEwan Crawford                 RegisterValue rVal;
675*02f1c5d1SEwan Crawford                 success = reg_ctx->ReadRegister(rArg, rVal);
676*02f1c5d1SEwan Crawford                 if (success)
677*02f1c5d1SEwan Crawford                 {
678*02f1c5d1SEwan Crawford                     (*data) = rVal.GetAsUInt64();
679*02f1c5d1SEwan Crawford                 }
680*02f1c5d1SEwan Crawford                 else
681*02f1c5d1SEwan Crawford                 {
682*02f1c5d1SEwan Crawford                     if (log)
683*02f1c5d1SEwan Crawford                         log->Printf("RenderScriptRuntime::GetArgSimple - Mips64 - Error reading the argument #%d", arg);
684*02f1c5d1SEwan Crawford                 }
685*02f1c5d1SEwan Crawford             }
686*02f1c5d1SEwan Crawford 
687*02f1c5d1SEwan Crawford             // read from the stack
688*02f1c5d1SEwan Crawford             else
689*02f1c5d1SEwan Crawford             {
690*02f1c5d1SEwan Crawford                 uint64_t sp = reg_ctx->GetSP();
691*02f1c5d1SEwan Crawford                 uint32_t offset = (arg - 8) * sizeof(uint64_t);
692*02f1c5d1SEwan Crawford                 process->ReadMemory(sp + offset, &data, sizeof(uint64_t), error);
693*02f1c5d1SEwan Crawford                 if (error.Fail())
694*02f1c5d1SEwan Crawford                 {
695*02f1c5d1SEwan Crawford                     if (log)
696*02f1c5d1SEwan Crawford                         log->Printf ("RenderScriptRuntime::GetArgSimple - Mips64 - Error reading Mips64 stack: %s.", error.AsCString());
697*02f1c5d1SEwan Crawford                 }
698*02f1c5d1SEwan Crawford                 else
699*02f1c5d1SEwan Crawford                 {
700*02f1c5d1SEwan Crawford                     success = true;
701*02f1c5d1SEwan Crawford                 }
702*02f1c5d1SEwan Crawford             }
703*02f1c5d1SEwan Crawford 
704*02f1c5d1SEwan Crawford             break;
705*02f1c5d1SEwan Crawford         }
70682780287SAidan Dodds         default:
70782780287SAidan Dodds         {
70882780287SAidan Dodds             // invalid architecture
70982780287SAidan Dodds             if (log)
71082780287SAidan Dodds                 log->Printf("RenderScriptRuntime::GetArgSimple - Architecture not supported");
71182780287SAidan Dodds 
71282780287SAidan Dodds         }
71382780287SAidan Dodds     }
71482780287SAidan Dodds 
71582780287SAidan Dodds 
71682780287SAidan Dodds     return success;
7174640cde1SColin Riley }
7184640cde1SColin Riley 
7194640cde1SColin Riley void
7204640cde1SColin Riley RenderScriptRuntime::CaptureSetGlobalVar1(RuntimeHook* hook_info, ExecutionContext& context)
7214640cde1SColin Riley {
7224640cde1SColin Riley     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
7234640cde1SColin Riley 
7244640cde1SColin Riley     //Context, Script, int, data, length
7254640cde1SColin Riley 
72682780287SAidan Dodds     uint64_t rs_context_u64 = 0U;
72782780287SAidan Dodds     uint64_t rs_script_u64 = 0U;
72882780287SAidan Dodds     uint64_t rs_id_u64 = 0U;
72982780287SAidan Dodds     uint64_t rs_data_u64 = 0U;
73082780287SAidan Dodds     uint64_t rs_length_u64 = 0U;
7314640cde1SColin Riley 
73282780287SAidan Dodds     bool success =
73382780287SAidan Dodds         GetArgSimple(context, 0, &rs_context_u64) &&
73482780287SAidan Dodds         GetArgSimple(context, 1, &rs_script_u64) &&
73582780287SAidan Dodds         GetArgSimple(context, 2, &rs_id_u64) &&
73682780287SAidan Dodds         GetArgSimple(context, 3, &rs_data_u64) &&
73782780287SAidan Dodds         GetArgSimple(context, 4, &rs_length_u64);
7384640cde1SColin Riley 
73982780287SAidan Dodds     if (!success)
74082780287SAidan Dodds     {
74182780287SAidan Dodds         if (log)
74282780287SAidan Dodds             log->Printf("RenderScriptRuntime::CaptureSetGlobalVar1 - Error while reading the function parameters");
74382780287SAidan Dodds         return;
74482780287SAidan Dodds     }
7454640cde1SColin Riley 
7464640cde1SColin Riley     if (log)
7474640cde1SColin Riley     {
7484640cde1SColin Riley         log->Printf ("RenderScriptRuntime::CaptureSetGlobalVar1 - 0x%" PRIx64 ",0x%" PRIx64 " slot %" PRIu64 " = 0x%" PRIx64 ":%" PRIu64 "bytes.",
74982780287SAidan Dodds                         rs_context_u64, rs_script_u64, rs_id_u64, rs_data_u64, rs_length_u64);
7504640cde1SColin Riley 
75182780287SAidan Dodds         addr_t script_addr =  (addr_t)rs_script_u64;
7524640cde1SColin Riley         if (m_scriptMappings.find( script_addr ) != m_scriptMappings.end())
7534640cde1SColin Riley         {
7544640cde1SColin Riley             auto rsm = m_scriptMappings[script_addr];
75582780287SAidan Dodds             if (rs_id_u64 < rsm->m_globals.size())
7564640cde1SColin Riley             {
75782780287SAidan Dodds                 auto rsg = rsm->m_globals[rs_id_u64];
7584640cde1SColin Riley                 log->Printf ("RenderScriptRuntime::CaptureSetGlobalVar1 - Setting of '%s' within '%s' inferred", rsg.m_name.AsCString(),
7594640cde1SColin Riley                                 rsm->m_module->GetFileSpec().GetFilename().AsCString());
7604640cde1SColin Riley             }
7614640cde1SColin Riley         }
7624640cde1SColin Riley     }
7634640cde1SColin Riley }
7644640cde1SColin Riley 
7654640cde1SColin Riley void
7664640cde1SColin Riley RenderScriptRuntime::CaptureAllocationInit1(RuntimeHook* hook_info, ExecutionContext& context)
7674640cde1SColin Riley {
7684640cde1SColin Riley     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
7694640cde1SColin Riley 
7704640cde1SColin Riley     //Context, Alloc, bool
7714640cde1SColin Riley 
77282780287SAidan Dodds     uint64_t rs_context_u64 = 0U;
77382780287SAidan Dodds     uint64_t rs_alloc_u64 = 0U;
77482780287SAidan Dodds     uint64_t rs_forceZero_u64 = 0U;
7754640cde1SColin Riley 
77682780287SAidan Dodds     bool success =
77782780287SAidan Dodds         GetArgSimple(context, 0, &rs_context_u64) &&
77882780287SAidan Dodds         GetArgSimple(context, 1, &rs_alloc_u64) &&
77982780287SAidan Dodds         GetArgSimple(context, 2, &rs_forceZero_u64);
78082780287SAidan Dodds     if (!success) // error case
78182780287SAidan Dodds     {
78282780287SAidan Dodds         if (log)
78382780287SAidan Dodds             log->Printf("RenderScriptRuntime::CaptureAllocationInit1 - Error while reading the function parameters");
78482780287SAidan Dodds         return; // abort
78582780287SAidan Dodds     }
7864640cde1SColin Riley 
7874640cde1SColin Riley     if (log)
7884640cde1SColin Riley         log->Printf ("RenderScriptRuntime::CaptureAllocationInit1 - 0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 " .",
78982780287SAidan Dodds                         rs_context_u64, rs_alloc_u64, rs_forceZero_u64);
79078f339d1SEwan Crawford 
79178f339d1SEwan Crawford     AllocationDetails* alloc = LookUpAllocation(rs_alloc_u64, true);
79278f339d1SEwan Crawford     if (alloc)
79378f339d1SEwan Crawford         alloc->context = rs_context_u64;
7944640cde1SColin Riley }
7954640cde1SColin Riley 
7964640cde1SColin Riley void
7974640cde1SColin Riley RenderScriptRuntime::CaptureScriptInit1(RuntimeHook* hook_info, ExecutionContext& context)
7984640cde1SColin Riley {
7994640cde1SColin Riley     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
8004640cde1SColin Riley 
8014640cde1SColin Riley     //Context, Script, resname Str, cachedir Str
8024640cde1SColin Riley     Error error;
8034640cde1SColin Riley     Process* process = context.GetProcessPtr();
8044640cde1SColin Riley 
80582780287SAidan Dodds     uint64_t rs_context_u64 = 0U;
80682780287SAidan Dodds     uint64_t rs_script_u64 = 0U;
80782780287SAidan Dodds     uint64_t rs_resnameptr_u64 = 0U;
80882780287SAidan Dodds     uint64_t rs_cachedirptr_u64 = 0U;
8094640cde1SColin Riley 
8104640cde1SColin Riley     std::string resname;
8114640cde1SColin Riley     std::string cachedir;
8124640cde1SColin Riley 
81382780287SAidan Dodds     // read the function parameters
81482780287SAidan Dodds     bool success =
81582780287SAidan Dodds         GetArgSimple(context, 0, &rs_context_u64) &&
81682780287SAidan Dodds         GetArgSimple(context, 1, &rs_script_u64) &&
81782780287SAidan Dodds         GetArgSimple(context, 2, &rs_resnameptr_u64) &&
81882780287SAidan Dodds         GetArgSimple(context, 3, &rs_cachedirptr_u64);
8194640cde1SColin Riley 
82082780287SAidan Dodds     if (!success)
82182780287SAidan Dodds     {
82282780287SAidan Dodds         if (log)
82382780287SAidan Dodds             log->Printf("RenderScriptRuntime::CaptureScriptInit1 - Error while reading the function parameters");
82482780287SAidan Dodds         return;
82582780287SAidan Dodds     }
82682780287SAidan Dodds 
82782780287SAidan Dodds     process->ReadCStringFromMemory((lldb::addr_t)rs_resnameptr_u64, resname, error);
8284640cde1SColin Riley     if (error.Fail())
8294640cde1SColin Riley     {
8304640cde1SColin Riley         if (log)
8314640cde1SColin Riley             log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - error reading resname: %s.", error.AsCString());
8324640cde1SColin Riley 
8334640cde1SColin Riley     }
8344640cde1SColin Riley 
83582780287SAidan Dodds     process->ReadCStringFromMemory((lldb::addr_t)rs_cachedirptr_u64, cachedir, error);
8364640cde1SColin Riley     if (error.Fail())
8374640cde1SColin Riley     {
8384640cde1SColin Riley         if (log)
8394640cde1SColin Riley             log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - error reading cachedir: %s.", error.AsCString());
8404640cde1SColin Riley     }
8414640cde1SColin Riley 
8424640cde1SColin Riley     if (log)
8434640cde1SColin Riley         log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - 0x%" PRIx64 ",0x%" PRIx64 " => '%s' at '%s' .",
84482780287SAidan Dodds                      rs_context_u64, rs_script_u64, resname.c_str(), cachedir.c_str());
8454640cde1SColin Riley 
8464640cde1SColin Riley     if (resname.size() > 0)
8474640cde1SColin Riley     {
8484640cde1SColin Riley         StreamString strm;
8494640cde1SColin Riley         strm.Printf("librs.%s.so", resname.c_str());
8504640cde1SColin Riley 
85178f339d1SEwan Crawford         ScriptDetails* script = LookUpScript(rs_script_u64, true);
85278f339d1SEwan Crawford         if (script)
85378f339d1SEwan Crawford         {
85478f339d1SEwan Crawford             script->type = ScriptDetails::eScriptC;
85578f339d1SEwan Crawford             script->cacheDir = cachedir;
85678f339d1SEwan Crawford             script->resName = resname;
85778f339d1SEwan Crawford             script->scriptDyLib = strm.GetData();
85878f339d1SEwan Crawford             script->context = addr_t(rs_context_u64);
85978f339d1SEwan Crawford         }
8604640cde1SColin Riley 
8614640cde1SColin Riley         if (log)
8624640cde1SColin Riley             log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - '%s' tagged with context 0x%" PRIx64 " and script 0x%" PRIx64 ".",
86382780287SAidan Dodds                          strm.GetData(), rs_context_u64, rs_script_u64);
8644640cde1SColin Riley     }
8654640cde1SColin Riley     else if (log)
8664640cde1SColin Riley     {
8674640cde1SColin Riley         log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - resource name invalid, Script not tagged");
8684640cde1SColin Riley     }
8694640cde1SColin Riley 
8704640cde1SColin Riley }
8714640cde1SColin Riley 
8724640cde1SColin Riley void
8734640cde1SColin Riley RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind)
8744640cde1SColin Riley {
8754640cde1SColin Riley     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
8764640cde1SColin Riley 
8774640cde1SColin Riley     if (!module)
8784640cde1SColin Riley     {
8794640cde1SColin Riley         return;
8804640cde1SColin Riley     }
8814640cde1SColin Riley 
88282780287SAidan Dodds     Target &target = GetProcess()->GetTarget();
88382780287SAidan Dodds     llvm::Triple::ArchType targetArchType = target.GetArchitecture().GetMachine();
88482780287SAidan Dodds 
88582780287SAidan Dodds     if (targetArchType != llvm::Triple::ArchType::x86
88682780287SAidan Dodds         && targetArchType != llvm::Triple::ArchType::arm
887*02f1c5d1SEwan Crawford         && targetArchType != llvm::Triple::ArchType::aarch64
888*02f1c5d1SEwan Crawford         && targetArchType != llvm::Triple::ArchType::mips64el
889*02f1c5d1SEwan Crawford     )
8904640cde1SColin Riley     {
8914640cde1SColin Riley         if (log)
892*02f1c5d1SEwan Crawford             log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Unable to hook runtime. Only X86, ARM, Mips64 supported currently.");
8934640cde1SColin Riley 
8944640cde1SColin Riley         return;
8954640cde1SColin Riley     }
8964640cde1SColin Riley 
89782780287SAidan Dodds     uint32_t archByteSize = target.GetArchitecture().GetAddressByteSize();
8984640cde1SColin Riley 
8994640cde1SColin Riley     for (size_t idx = 0; idx < s_runtimeHookCount; idx++)
9004640cde1SColin Riley     {
9014640cde1SColin Riley         const HookDefn* hook_defn = &s_runtimeHookDefns[idx];
9024640cde1SColin Riley         if (hook_defn->kind != kind) {
9034640cde1SColin Riley             continue;
9044640cde1SColin Riley         }
9054640cde1SColin Riley 
90682780287SAidan Dodds         const char* symbol_name = (archByteSize == 4) ? hook_defn->symbol_name_m32 : hook_defn->symbol_name_m64;
90782780287SAidan Dodds 
90882780287SAidan Dodds         const Symbol *sym = module->FindFirstSymbolWithNameAndType(ConstString(symbol_name), eSymbolTypeCode);
90982780287SAidan Dodds         if (!sym){
91082780287SAidan Dodds             if (log){
91182780287SAidan Dodds                 log->Printf("RenderScriptRuntime::LoadRuntimeHooks - ERROR: Symbol '%s' related to the function %s not found", symbol_name, hook_defn->name);
91282780287SAidan Dodds             }
91382780287SAidan Dodds             continue;
91482780287SAidan Dodds         }
9154640cde1SColin Riley 
916358cf1eaSGreg Clayton         addr_t addr = sym->GetLoadAddress(&target);
9174640cde1SColin Riley         if (addr == LLDB_INVALID_ADDRESS)
9184640cde1SColin Riley         {
9194640cde1SColin Riley             if (log)
9204640cde1SColin Riley                 log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Unable to resolve the address of hook function '%s' with symbol '%s'.",
92182780287SAidan Dodds                              hook_defn->name, symbol_name);
9224640cde1SColin Riley             continue;
9234640cde1SColin Riley         }
92482780287SAidan Dodds         else
92582780287SAidan Dodds         {
92682780287SAidan Dodds             if (log)
92782780287SAidan Dodds                 log->Printf("RenderScriptRuntime::LoadRuntimeHooks - Function %s, address resolved at 0x%" PRIx64, hook_defn->name, addr);
92882780287SAidan Dodds         }
9294640cde1SColin Riley 
9304640cde1SColin Riley         RuntimeHookSP hook(new RuntimeHook());
9314640cde1SColin Riley         hook->address = addr;
9324640cde1SColin Riley         hook->defn = hook_defn;
9334640cde1SColin Riley         hook->bp_sp = target.CreateBreakpoint(addr, true, false);
9344640cde1SColin Riley         hook->bp_sp->SetCallback(HookCallback, hook.get(), true);
9354640cde1SColin Riley         m_runtimeHooks[addr] = hook;
9364640cde1SColin Riley         if (log)
9374640cde1SColin Riley         {
9384640cde1SColin Riley             log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Successfully hooked '%s' in '%s' version %" PRIu64 " at 0x%" PRIx64 ".",
9394640cde1SColin Riley                 hook_defn->name, module->GetFileSpec().GetFilename().AsCString(), (uint64_t)hook_defn->version, (uint64_t)addr);
9404640cde1SColin Riley         }
9414640cde1SColin Riley     }
9424640cde1SColin Riley }
9434640cde1SColin Riley 
9444640cde1SColin Riley void
9454640cde1SColin Riley RenderScriptRuntime::FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp)
9464640cde1SColin Riley {
9474640cde1SColin Riley     if (!rsmodule_sp)
9484640cde1SColin Riley         return;
9494640cde1SColin Riley 
9504640cde1SColin Riley     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
9514640cde1SColin Riley 
9524640cde1SColin Riley     const ModuleSP module = rsmodule_sp->m_module;
9534640cde1SColin Riley     const FileSpec& file = module->GetPlatformFileSpec();
9544640cde1SColin Riley 
95578f339d1SEwan Crawford     // Iterate over all of the scripts that we currently know of.
95678f339d1SEwan Crawford     // Note: We cant push or pop to m_scripts here or it may invalidate rs_script.
9574640cde1SColin Riley     for (const auto & rs_script : m_scripts)
9584640cde1SColin Riley     {
95978f339d1SEwan Crawford         // Extract the expected .so file path for this script.
96078f339d1SEwan Crawford         std::string dylib;
96178f339d1SEwan Crawford         if (!rs_script->scriptDyLib.get(dylib))
96278f339d1SEwan Crawford             continue;
96378f339d1SEwan Crawford 
96478f339d1SEwan Crawford         // Only proceed if the module that has loaded corresponds to this script.
96578f339d1SEwan Crawford         if (file.GetFilename() != ConstString(dylib.c_str()))
96678f339d1SEwan Crawford             continue;
96778f339d1SEwan Crawford 
96878f339d1SEwan Crawford         // Obtain the script address which we use as a key.
96978f339d1SEwan Crawford         lldb::addr_t script;
97078f339d1SEwan Crawford         if (!rs_script->script.get(script))
97178f339d1SEwan Crawford             continue;
97278f339d1SEwan Crawford 
97378f339d1SEwan Crawford         // If we have a script mapping for the current script.
97478f339d1SEwan Crawford         if (m_scriptMappings.find(script) != m_scriptMappings.end())
9754640cde1SColin Riley         {
97678f339d1SEwan Crawford             // if the module we have stored is different to the one we just received.
97778f339d1SEwan Crawford             if (m_scriptMappings[script] != rsmodule_sp)
9784640cde1SColin Riley             {
9794640cde1SColin Riley                 if (log)
9804640cde1SColin Riley                     log->Printf ("RenderScriptRuntime::FixupScriptDetails - Error: script %" PRIx64 " wants reassigned to new rsmodule '%s'.",
98178f339d1SEwan Crawford                                     (uint64_t)script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
9824640cde1SColin Riley             }
9834640cde1SColin Riley         }
98478f339d1SEwan Crawford         // We don't have a script mapping for the current script.
9854640cde1SColin Riley         else
9864640cde1SColin Riley         {
98778f339d1SEwan Crawford             // Obtain the script resource name.
98878f339d1SEwan Crawford             std::string resName;
98978f339d1SEwan Crawford             if (rs_script->resName.get(resName))
99078f339d1SEwan Crawford                 // Set the modules resource name.
99178f339d1SEwan Crawford                 rsmodule_sp->m_resname = resName;
99278f339d1SEwan Crawford             // Add Script/Module pair to map.
99378f339d1SEwan Crawford             m_scriptMappings[script] = rsmodule_sp;
9944640cde1SColin Riley             if (log)
9954640cde1SColin Riley                 log->Printf ("RenderScriptRuntime::FixupScriptDetails - script %" PRIx64 " associated with rsmodule '%s'.",
99678f339d1SEwan Crawford                                 (uint64_t)script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
9974640cde1SColin Riley         }
9984640cde1SColin Riley     }
9994640cde1SColin Riley }
10004640cde1SColin Riley 
100115f2bd95SEwan Crawford // Uses the Target API to evaluate the expression passed as a parameter to the function
100215f2bd95SEwan Crawford // The result of that expression is returned an unsigned 64 bit int, via the result* paramter.
100315f2bd95SEwan Crawford // Function returns true on success, and false on failure
100415f2bd95SEwan Crawford bool
100515f2bd95SEwan Crawford RenderScriptRuntime::EvalRSExpression(const char* expression, StackFrame* frame_ptr, uint64_t* result)
100615f2bd95SEwan Crawford {
100715f2bd95SEwan Crawford     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
100815f2bd95SEwan Crawford     if (log)
100915f2bd95SEwan Crawford         log->Printf("RenderScriptRuntime::EvalRSExpression(%s)", expression);
101015f2bd95SEwan Crawford 
101115f2bd95SEwan Crawford     ValueObjectSP expr_result;
101215f2bd95SEwan Crawford     // Perform the actual expression evaluation
101315f2bd95SEwan Crawford     GetProcess()->GetTarget().EvaluateExpression(expression, frame_ptr, expr_result);
101415f2bd95SEwan Crawford 
101515f2bd95SEwan Crawford     if (!expr_result)
101615f2bd95SEwan Crawford     {
101715f2bd95SEwan Crawford        if (log)
101815f2bd95SEwan Crawford            log->Printf("RenderScriptRuntime::EvalRSExpression -  Error: Couldn't evaluate expression");
101915f2bd95SEwan Crawford        return false;
102015f2bd95SEwan Crawford     }
102115f2bd95SEwan Crawford 
102215f2bd95SEwan Crawford     // The result of the expression is invalid
102315f2bd95SEwan Crawford     if (!expr_result->GetError().Success())
102415f2bd95SEwan Crawford     {
102515f2bd95SEwan Crawford         Error err = expr_result->GetError();
102615f2bd95SEwan Crawford         if (err.GetError() == UserExpression::kNoResult) // Expression returned void, so this is actually a success
102715f2bd95SEwan Crawford         {
102815f2bd95SEwan Crawford             if (log)
102915f2bd95SEwan Crawford                 log->Printf("RenderScriptRuntime::EvalRSExpression - Expression returned void");
103015f2bd95SEwan Crawford 
103115f2bd95SEwan Crawford             result = nullptr;
103215f2bd95SEwan Crawford             return true;
103315f2bd95SEwan Crawford         }
103415f2bd95SEwan Crawford 
103515f2bd95SEwan Crawford         if (log)
103615f2bd95SEwan Crawford             log->Printf("RenderScriptRuntime::EvalRSExpression - Error evaluating expression result: %s", err.AsCString());
103715f2bd95SEwan Crawford         return false;
103815f2bd95SEwan Crawford     }
103915f2bd95SEwan Crawford 
104015f2bd95SEwan Crawford     bool success = false;
104115f2bd95SEwan Crawford     *result = expr_result->GetValueAsUnsigned(0, &success); // We only read the result as an unsigned int.
104215f2bd95SEwan Crawford 
104315f2bd95SEwan Crawford     if (!success)
104415f2bd95SEwan Crawford     {
104515f2bd95SEwan Crawford        if (log)
104615f2bd95SEwan Crawford            log->Printf("RenderScriptRuntime::EvalRSExpression -  Error: Couldn't convert expression result to unsigned int");
104715f2bd95SEwan Crawford        return false;
104815f2bd95SEwan Crawford     }
104915f2bd95SEwan Crawford 
105015f2bd95SEwan Crawford     return true;
105115f2bd95SEwan Crawford }
105215f2bd95SEwan Crawford 
105315f2bd95SEwan Crawford // Used to index expression format strings
105415f2bd95SEwan Crawford enum ExpressionStrings
105515f2bd95SEwan Crawford {
105615f2bd95SEwan Crawford    eExprGetOffsetPtr = 0,
105715f2bd95SEwan Crawford    eExprAllocGetType,
105815f2bd95SEwan Crawford    eExprTypeDimX,
105915f2bd95SEwan Crawford    eExprTypeDimY,
106015f2bd95SEwan Crawford    eExprTypeDimZ,
106115f2bd95SEwan Crawford    eExprTypeElemPtr,
106215f2bd95SEwan Crawford    eExprElementType,
106315f2bd95SEwan Crawford    eExprElementKind,
106415f2bd95SEwan Crawford    eExprElementVec
106515f2bd95SEwan Crawford };
106615f2bd95SEwan Crawford 
106715f2bd95SEwan Crawford // Format strings containing the expressions we may need to evaluate.
106815f2bd95SEwan Crawford const char runtimeExpressions[][256] =
106915f2bd95SEwan Crawford {
107015f2bd95SEwan Crawford  // Mangled GetOffsetPointer(Allocation*, xoff, yoff, zoff, lod, cubemap)
107115f2bd95SEwan Crawford  "(int*)_Z12GetOffsetPtrPKN7android12renderscript10AllocationEjjjj23RsAllocationCubemapFace(0x%lx, %u, %u, %u, 0, 0)",
107215f2bd95SEwan Crawford 
107315f2bd95SEwan Crawford  // Type* rsaAllocationGetType(Context*, Allocation*)
107415f2bd95SEwan Crawford  "(void*)rsaAllocationGetType(0x%lx, 0x%lx)",
107515f2bd95SEwan Crawford 
107615f2bd95SEwan Crawford  // rsaTypeGetNativeData(Context*, Type*, void* typeData, size)
107715f2bd95SEwan Crawford  // Pack the data in the following way mHal.state.dimX; mHal.state.dimY; mHal.state.dimZ;
107815f2bd95SEwan Crawford  // mHal.state.lodCount; mHal.state.faces; mElement; into typeData
107915f2bd95SEwan Crawford  // Need to specify 32 or 64 bit for uint_t since this differs between devices
108015f2bd95SEwan Crawford  "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[0]", // X dim
108115f2bd95SEwan Crawford  "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[1]", // Y dim
108215f2bd95SEwan Crawford  "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[2]", // Z dim
108315f2bd95SEwan Crawford  "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[5]", // Element ptr
108415f2bd95SEwan Crawford 
108515f2bd95SEwan Crawford  // rsaElementGetNativeData(Context*, Element*, uint32_t* elemData,size)
108615f2bd95SEwan Crawford  // Pack mType; mKind; mNormalized; mVectorSize; NumSubElements into elemData
108715f2bd95SEwan Crawford  "uint32_t data[6]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[0]", // Type
108815f2bd95SEwan Crawford  "uint32_t data[6]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[1]", // Kind
108915f2bd95SEwan Crawford  "uint32_t data[6]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[3]"  // Vector Size
109015f2bd95SEwan Crawford };
109115f2bd95SEwan Crawford 
109215f2bd95SEwan Crawford // JITs the RS runtime for the internal data pointer of an allocation.
109315f2bd95SEwan Crawford // Is passed x,y,z coordinates for the pointer to a specific element.
109415f2bd95SEwan Crawford // Then sets the data_ptr member in Allocation with the result.
109515f2bd95SEwan Crawford // Returns true on success, false otherwise
109615f2bd95SEwan Crawford bool
109715f2bd95SEwan Crawford RenderScriptRuntime::JITDataPointer(AllocationDetails* allocation, StackFrame* frame_ptr,
109815f2bd95SEwan Crawford                                     unsigned int x, unsigned int y, unsigned int z)
109915f2bd95SEwan Crawford {
110015f2bd95SEwan Crawford     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
110115f2bd95SEwan Crawford 
110215f2bd95SEwan Crawford     if (!allocation->address.isValid())
110315f2bd95SEwan Crawford     {
110415f2bd95SEwan Crawford         if (log)
110515f2bd95SEwan Crawford             log->Printf("RenderScriptRuntime::JITDataPointer - Failed to find allocation details");
110615f2bd95SEwan Crawford         return false;
110715f2bd95SEwan Crawford     }
110815f2bd95SEwan Crawford 
110915f2bd95SEwan Crawford     const char* expr_cstr = runtimeExpressions[eExprGetOffsetPtr];
111015f2bd95SEwan Crawford     const int max_expr_size = 512; // Max expression size
111115f2bd95SEwan Crawford     char buffer[max_expr_size];
111215f2bd95SEwan Crawford 
111315f2bd95SEwan Crawford     int chars_written = snprintf(buffer, max_expr_size, expr_cstr, *allocation->address.get(), x, y, z);
111415f2bd95SEwan Crawford     if (chars_written < 0)
111515f2bd95SEwan Crawford     {
111615f2bd95SEwan Crawford         if (log)
111715f2bd95SEwan Crawford             log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()");
111815f2bd95SEwan Crawford         return false;
111915f2bd95SEwan Crawford     }
112015f2bd95SEwan Crawford     else if (chars_written >= max_expr_size)
112115f2bd95SEwan Crawford     {
112215f2bd95SEwan Crawford         if (log)
112315f2bd95SEwan Crawford             log->Printf("RenderScriptRuntime::JITDataPointer - Expression too long");
112415f2bd95SEwan Crawford         return false;
112515f2bd95SEwan Crawford     }
112615f2bd95SEwan Crawford 
112715f2bd95SEwan Crawford     uint64_t result = 0;
112815f2bd95SEwan Crawford     if (!EvalRSExpression(buffer, frame_ptr, &result))
112915f2bd95SEwan Crawford         return false;
113015f2bd95SEwan Crawford 
113115f2bd95SEwan Crawford     addr_t mem_ptr = static_cast<lldb::addr_t>(result);
113215f2bd95SEwan Crawford     allocation->data_ptr = mem_ptr;
113315f2bd95SEwan Crawford 
113415f2bd95SEwan Crawford     return true;
113515f2bd95SEwan Crawford }
113615f2bd95SEwan Crawford 
113715f2bd95SEwan Crawford // JITs the RS runtime for the internal pointer to the RS Type of an allocation
113815f2bd95SEwan Crawford // Then sets the type_ptr member in Allocation with the result.
113915f2bd95SEwan Crawford // Returns true on success, false otherwise
114015f2bd95SEwan Crawford bool
114115f2bd95SEwan Crawford RenderScriptRuntime::JITTypePointer(AllocationDetails* allocation, StackFrame* frame_ptr)
114215f2bd95SEwan Crawford {
114315f2bd95SEwan Crawford     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
114415f2bd95SEwan Crawford 
114515f2bd95SEwan Crawford     if (!allocation->address.isValid() || !allocation->context.isValid())
114615f2bd95SEwan Crawford     {
114715f2bd95SEwan Crawford         if (log)
114815f2bd95SEwan Crawford             log->Printf("RenderScriptRuntime::JITTypePointer - Failed to find allocation details");
114915f2bd95SEwan Crawford         return false;
115015f2bd95SEwan Crawford     }
115115f2bd95SEwan Crawford 
115215f2bd95SEwan Crawford     const char* expr_cstr = runtimeExpressions[eExprAllocGetType];
115315f2bd95SEwan Crawford     const int max_expr_size = 512; // Max expression size
115415f2bd95SEwan Crawford     char buffer[max_expr_size];
115515f2bd95SEwan Crawford 
115615f2bd95SEwan Crawford     int chars_written = snprintf(buffer, max_expr_size, expr_cstr, *allocation->context.get(), *allocation->address.get());
115715f2bd95SEwan Crawford     if (chars_written < 0)
115815f2bd95SEwan Crawford     {
115915f2bd95SEwan Crawford         if (log)
116015f2bd95SEwan Crawford             log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()");
116115f2bd95SEwan Crawford         return false;
116215f2bd95SEwan Crawford     }
116315f2bd95SEwan Crawford     else if (chars_written >= max_expr_size)
116415f2bd95SEwan Crawford     {
116515f2bd95SEwan Crawford         if (log)
116615f2bd95SEwan Crawford             log->Printf("RenderScriptRuntime::JITTypePointer - Expression too long");
116715f2bd95SEwan Crawford         return false;
116815f2bd95SEwan Crawford     }
116915f2bd95SEwan Crawford 
117015f2bd95SEwan Crawford     uint64_t result = 0;
117115f2bd95SEwan Crawford     if (!EvalRSExpression(buffer, frame_ptr, &result))
117215f2bd95SEwan Crawford         return false;
117315f2bd95SEwan Crawford 
117415f2bd95SEwan Crawford     addr_t type_ptr = static_cast<lldb::addr_t>(result);
117515f2bd95SEwan Crawford     allocation->type_ptr = type_ptr;
117615f2bd95SEwan Crawford 
117715f2bd95SEwan Crawford     return true;
117815f2bd95SEwan Crawford }
117915f2bd95SEwan Crawford 
118015f2bd95SEwan Crawford // JITs the RS runtime for information about the dimensions and type of an allocation
118115f2bd95SEwan Crawford // Then sets dimension and element_ptr members in Allocation with the result.
118215f2bd95SEwan Crawford // Returns true on success, false otherwise
118315f2bd95SEwan Crawford bool
118415f2bd95SEwan Crawford RenderScriptRuntime::JITTypePacked(AllocationDetails* allocation, StackFrame* frame_ptr)
118515f2bd95SEwan Crawford {
118615f2bd95SEwan Crawford     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
118715f2bd95SEwan Crawford 
118815f2bd95SEwan Crawford     if (!allocation->type_ptr.isValid() || !allocation->context.isValid())
118915f2bd95SEwan Crawford     {
119015f2bd95SEwan Crawford         if (log)
119115f2bd95SEwan Crawford             log->Printf("RenderScriptRuntime::JITTypePacked - Failed to find allocation details");
119215f2bd95SEwan Crawford         return false;
119315f2bd95SEwan Crawford     }
119415f2bd95SEwan Crawford 
119515f2bd95SEwan Crawford     // Expression is different depending on if device is 32 or 64 bit
119615f2bd95SEwan Crawford     uint32_t archByteSize = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
119715f2bd95SEwan Crawford     const unsigned int bits = archByteSize == 4 ? 32 : 64;
119815f2bd95SEwan Crawford 
119915f2bd95SEwan Crawford     // We want 4 elements from packed data
120015f2bd95SEwan Crawford     const unsigned int num_exprs = 4;
120115f2bd95SEwan Crawford     assert(num_exprs == (eExprTypeElemPtr - eExprTypeDimX + 1) && "Invalid number of expressions");
120215f2bd95SEwan Crawford 
120315f2bd95SEwan Crawford     const int max_expr_size = 512; // Max expression size
120415f2bd95SEwan Crawford     char buffer[num_exprs][max_expr_size];
120515f2bd95SEwan Crawford     uint64_t results[num_exprs];
120615f2bd95SEwan Crawford 
120715f2bd95SEwan Crawford     for (unsigned int i = 0; i < num_exprs; ++i)
120815f2bd95SEwan Crawford     {
120915f2bd95SEwan Crawford         int chars_written = snprintf(buffer[i], max_expr_size, runtimeExpressions[eExprTypeDimX + i], bits,
121015f2bd95SEwan Crawford                                      *allocation->context.get(), *allocation->type_ptr.get());
121115f2bd95SEwan Crawford         if (chars_written < 0)
121215f2bd95SEwan Crawford         {
121315f2bd95SEwan Crawford             if (log)
121415f2bd95SEwan Crawford                 log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()");
121515f2bd95SEwan Crawford             return false;
121615f2bd95SEwan Crawford         }
121715f2bd95SEwan Crawford         else if (chars_written >= max_expr_size)
121815f2bd95SEwan Crawford         {
121915f2bd95SEwan Crawford             if (log)
122015f2bd95SEwan Crawford                 log->Printf("RenderScriptRuntime::JITTypePacked - Expression too long");
122115f2bd95SEwan Crawford             return false;
122215f2bd95SEwan Crawford         }
122315f2bd95SEwan Crawford 
122415f2bd95SEwan Crawford         // Perform expression evaluation
122515f2bd95SEwan Crawford         if (!EvalRSExpression(buffer[i], frame_ptr, &results[i]))
122615f2bd95SEwan Crawford             return false;
122715f2bd95SEwan Crawford     }
122815f2bd95SEwan Crawford 
122915f2bd95SEwan Crawford     // Assign results to allocation members
123015f2bd95SEwan Crawford     AllocationDetails::Dimension dims;
123115f2bd95SEwan Crawford     dims.dim_1 = static_cast<uint32_t>(results[0]);
123215f2bd95SEwan Crawford     dims.dim_2 = static_cast<uint32_t>(results[1]);
123315f2bd95SEwan Crawford     dims.dim_3 = static_cast<uint32_t>(results[2]);
123415f2bd95SEwan Crawford     allocation->dimension = dims;
123515f2bd95SEwan Crawford 
123615f2bd95SEwan Crawford     addr_t elem_ptr = static_cast<lldb::addr_t>(results[3]);
123715f2bd95SEwan Crawford     allocation->element_ptr = elem_ptr;
123815f2bd95SEwan Crawford 
123915f2bd95SEwan Crawford     if (log)
124015f2bd95SEwan Crawford         log->Printf("RenderScriptRuntime::JITTypePacked - dims (%u, %u, %u) Element*: 0x%" PRIx64,
124115f2bd95SEwan Crawford                     dims.dim_1, dims.dim_2, dims.dim_3, elem_ptr);
124215f2bd95SEwan Crawford 
124315f2bd95SEwan Crawford     return true;
124415f2bd95SEwan Crawford }
124515f2bd95SEwan Crawford 
124615f2bd95SEwan Crawford // JITs the RS runtime for information about the Element of an allocation
124715f2bd95SEwan Crawford // Then sets type, type_vec_size, and type_kind members in Allocation with the result.
124815f2bd95SEwan Crawford // Returns true on success, false otherwise
124915f2bd95SEwan Crawford bool
125015f2bd95SEwan Crawford RenderScriptRuntime::JITElementPacked(AllocationDetails* allocation, StackFrame* frame_ptr)
125115f2bd95SEwan Crawford {
125215f2bd95SEwan Crawford     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
125315f2bd95SEwan Crawford 
125415f2bd95SEwan Crawford     if (!allocation->element_ptr.isValid() || !allocation->context.isValid())
125515f2bd95SEwan Crawford     {
125615f2bd95SEwan Crawford         if (log)
125715f2bd95SEwan Crawford             log->Printf("RenderScriptRuntime::JITElementPacked - Failed to find allocation details");
125815f2bd95SEwan Crawford         return false;
125915f2bd95SEwan Crawford     }
126015f2bd95SEwan Crawford 
126115f2bd95SEwan Crawford     // We want 3 elements from packed data
126215f2bd95SEwan Crawford     const unsigned int num_exprs = 3;
126315f2bd95SEwan Crawford     assert(num_exprs == (eExprElementVec - eExprElementType + 1) && "Invalid number of expressions");
126415f2bd95SEwan Crawford 
126515f2bd95SEwan Crawford     const int max_expr_size = 512; // Max expression size
126615f2bd95SEwan Crawford     char buffer[num_exprs][max_expr_size];
126715f2bd95SEwan Crawford     uint64_t results[num_exprs];
126815f2bd95SEwan Crawford 
126915f2bd95SEwan Crawford     for (unsigned int i = 0; i < num_exprs; i++)
127015f2bd95SEwan Crawford     {
127115f2bd95SEwan Crawford         int chars_written = snprintf(buffer[i], max_expr_size, runtimeExpressions[eExprElementType + i], *allocation->context.get(), *allocation->element_ptr.get());
127215f2bd95SEwan Crawford         if (chars_written < 0)
127315f2bd95SEwan Crawford         {
127415f2bd95SEwan Crawford             if (log)
127515f2bd95SEwan Crawford                 log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()");
127615f2bd95SEwan Crawford             return false;
127715f2bd95SEwan Crawford         }
127815f2bd95SEwan Crawford         else if (chars_written >= max_expr_size)
127915f2bd95SEwan Crawford         {
128015f2bd95SEwan Crawford             if (log)
128115f2bd95SEwan Crawford                 log->Printf("RenderScriptRuntime::JITElementPacked - Expression too long");
128215f2bd95SEwan Crawford             return false;
128315f2bd95SEwan Crawford         }
128415f2bd95SEwan Crawford 
128515f2bd95SEwan Crawford         // Perform expression evaluation
128615f2bd95SEwan Crawford         if (!EvalRSExpression(buffer[i], frame_ptr, &results[i]))
128715f2bd95SEwan Crawford             return false;
128815f2bd95SEwan Crawford     }
128915f2bd95SEwan Crawford 
129015f2bd95SEwan Crawford     // Assign results to allocation members
129115f2bd95SEwan Crawford     allocation->type = static_cast<RenderScriptRuntime::AllocationDetails::DataType>(results[0]);
129215f2bd95SEwan Crawford     allocation->type_kind = static_cast<RenderScriptRuntime::AllocationDetails::DataKind>(results[1]);
129315f2bd95SEwan Crawford     allocation->type_vec_size = static_cast<uint32_t>(results[2]);
129415f2bd95SEwan Crawford 
129515f2bd95SEwan Crawford     if (log)
129615f2bd95SEwan Crawford         log->Printf("RenderScriptRuntime::JITElementPacked - data type %u, pixel type %u, vector size %u",
129715f2bd95SEwan Crawford                     *allocation->type.get(), *allocation->type_kind.get(), *allocation->type_vec_size.get());
129815f2bd95SEwan Crawford 
129915f2bd95SEwan Crawford     return true;
130015f2bd95SEwan Crawford }
130115f2bd95SEwan Crawford 
1302a0f08674SEwan Crawford // JITs the RS runtime for the address of the last element in the allocation.
1303a0f08674SEwan Crawford // The `elem_size` paramter represents the size of a single element, including padding.
1304a0f08674SEwan Crawford // Which is needed as an offset from the last element pointer.
1305a0f08674SEwan Crawford // Using this offset minus the starting address we can calculate the size of the allocation.
1306a0f08674SEwan Crawford // Returns true on success, false otherwise
1307a0f08674SEwan Crawford bool
1308a0f08674SEwan Crawford RenderScriptRuntime::JITAllocationSize(AllocationDetails* allocation, StackFrame* frame_ptr,
1309a0f08674SEwan Crawford                                        const uint32_t elem_size)
1310a0f08674SEwan Crawford {
1311a0f08674SEwan Crawford     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1312a0f08674SEwan Crawford 
1313a0f08674SEwan Crawford     if (!allocation->address.isValid() || !allocation->dimension.isValid()
1314a0f08674SEwan Crawford         || !allocation->data_ptr.isValid())
1315a0f08674SEwan Crawford     {
1316a0f08674SEwan Crawford         if (log)
1317a0f08674SEwan Crawford             log->Printf("RenderScriptRuntime::JITAllocationSize - Failed to find allocation details");
1318a0f08674SEwan Crawford         return false;
1319a0f08674SEwan Crawford     }
1320a0f08674SEwan Crawford 
1321a0f08674SEwan Crawford     const char* expr_cstr = runtimeExpressions[eExprGetOffsetPtr];
1322a0f08674SEwan Crawford     const int max_expr_size = 512; // Max expression size
1323a0f08674SEwan Crawford     char buffer[max_expr_size];
1324a0f08674SEwan Crawford 
1325a0f08674SEwan Crawford     // Find dimensions
1326a0f08674SEwan Crawford     unsigned int dim_x = allocation->dimension.get()->dim_1;
1327a0f08674SEwan Crawford     unsigned int dim_y = allocation->dimension.get()->dim_2;
1328a0f08674SEwan Crawford     unsigned int dim_z = allocation->dimension.get()->dim_3;
1329a0f08674SEwan Crawford 
1330a0f08674SEwan Crawford     // Calculate last element
1331a0f08674SEwan Crawford     dim_x = dim_x == 0 ? 0 : dim_x - 1;
1332a0f08674SEwan Crawford     dim_y = dim_y == 0 ? 0 : dim_y - 1;
1333a0f08674SEwan Crawford     dim_z = dim_z == 0 ? 0 : dim_z - 1;
1334a0f08674SEwan Crawford 
1335a0f08674SEwan Crawford     int chars_written = snprintf(buffer, max_expr_size, expr_cstr, *allocation->address.get(),
1336a0f08674SEwan Crawford                                  dim_x, dim_y, dim_z);
1337a0f08674SEwan Crawford     if (chars_written < 0)
1338a0f08674SEwan Crawford     {
1339a0f08674SEwan Crawford         if (log)
1340a0f08674SEwan Crawford             log->Printf("RenderScriptRuntime::JITAllocationSize - Encoding error in snprintf()");
1341a0f08674SEwan Crawford         return false;
1342a0f08674SEwan Crawford     }
1343a0f08674SEwan Crawford     else if (chars_written >= max_expr_size)
1344a0f08674SEwan Crawford     {
1345a0f08674SEwan Crawford         if (log)
1346a0f08674SEwan Crawford             log->Printf("RenderScriptRuntime::JITAllocationSize - Expression too long");
1347a0f08674SEwan Crawford         return false;
1348a0f08674SEwan Crawford     }
1349a0f08674SEwan Crawford 
1350a0f08674SEwan Crawford     uint64_t result = 0;
1351a0f08674SEwan Crawford     if (!EvalRSExpression(buffer, frame_ptr, &result))
1352a0f08674SEwan Crawford         return false;
1353a0f08674SEwan Crawford 
1354a0f08674SEwan Crawford     addr_t mem_ptr = static_cast<lldb::addr_t>(result);
1355a0f08674SEwan Crawford     // Find pointer to last element and add on size of an element
1356a0f08674SEwan Crawford     allocation->size = static_cast<uint32_t>(mem_ptr - *allocation->data_ptr.get()) + elem_size;
1357a0f08674SEwan Crawford 
1358a0f08674SEwan Crawford     return true;
1359a0f08674SEwan Crawford }
1360a0f08674SEwan Crawford 
1361a0f08674SEwan Crawford // JITs the RS runtime for information about the stride between rows in the allocation.
1362a0f08674SEwan Crawford // This is done to detect padding, since allocated memory is 16-byte aligned.
1363a0f08674SEwan Crawford // Returns true on success, false otherwise
1364a0f08674SEwan Crawford bool
1365a0f08674SEwan Crawford RenderScriptRuntime::JITAllocationStride(AllocationDetails* allocation, StackFrame* frame_ptr)
1366a0f08674SEwan Crawford {
1367a0f08674SEwan Crawford     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1368a0f08674SEwan Crawford 
1369a0f08674SEwan Crawford     if (!allocation->address.isValid() || !allocation->data_ptr.isValid())
1370a0f08674SEwan Crawford     {
1371a0f08674SEwan Crawford         if (log)
1372a0f08674SEwan Crawford             log->Printf("RenderScriptRuntime::JITAllocationStride - Failed to find allocation details");
1373a0f08674SEwan Crawford         return false;
1374a0f08674SEwan Crawford     }
1375a0f08674SEwan Crawford 
1376a0f08674SEwan Crawford     const char* expr_cstr = runtimeExpressions[eExprGetOffsetPtr];
1377a0f08674SEwan Crawford     const int max_expr_size = 512; // Max expression size
1378a0f08674SEwan Crawford     char buffer[max_expr_size];
1379a0f08674SEwan Crawford 
1380a0f08674SEwan Crawford     int chars_written = snprintf(buffer, max_expr_size, expr_cstr, *allocation->address.get(),
1381a0f08674SEwan Crawford                                  0, 1, 0);
1382a0f08674SEwan Crawford     if (chars_written < 0)
1383a0f08674SEwan Crawford     {
1384a0f08674SEwan Crawford         if (log)
1385a0f08674SEwan Crawford             log->Printf("RenderScriptRuntime::JITAllocationStride - Encoding error in snprintf()");
1386a0f08674SEwan Crawford         return false;
1387a0f08674SEwan Crawford     }
1388a0f08674SEwan Crawford     else if (chars_written >= max_expr_size)
1389a0f08674SEwan Crawford     {
1390a0f08674SEwan Crawford         if (log)
1391a0f08674SEwan Crawford             log->Printf("RenderScriptRuntime::JITAllocationStride - Expression too long");
1392a0f08674SEwan Crawford         return false;
1393a0f08674SEwan Crawford     }
1394a0f08674SEwan Crawford 
1395a0f08674SEwan Crawford     uint64_t result = 0;
1396a0f08674SEwan Crawford     if (!EvalRSExpression(buffer, frame_ptr, &result))
1397a0f08674SEwan Crawford         return false;
1398a0f08674SEwan Crawford 
1399a0f08674SEwan Crawford     addr_t mem_ptr = static_cast<lldb::addr_t>(result);
1400a0f08674SEwan Crawford     allocation->stride = static_cast<uint32_t>(mem_ptr - *allocation->data_ptr.get());
1401a0f08674SEwan Crawford 
1402a0f08674SEwan Crawford     return true;
1403a0f08674SEwan Crawford }
1404a0f08674SEwan Crawford 
140515f2bd95SEwan Crawford // JIT all the current runtime info regarding an allocation
140615f2bd95SEwan Crawford bool
140715f2bd95SEwan Crawford RenderScriptRuntime::RefreshAllocation(AllocationDetails* allocation, StackFrame* frame_ptr)
140815f2bd95SEwan Crawford {
140915f2bd95SEwan Crawford     // GetOffsetPointer()
141015f2bd95SEwan Crawford     if (!JITDataPointer(allocation, frame_ptr))
141115f2bd95SEwan Crawford         return false;
141215f2bd95SEwan Crawford 
141315f2bd95SEwan Crawford     // rsaAllocationGetType()
141415f2bd95SEwan Crawford     if (!JITTypePointer(allocation, frame_ptr))
141515f2bd95SEwan Crawford         return false;
141615f2bd95SEwan Crawford 
141715f2bd95SEwan Crawford     // rsaTypeGetNativeData()
141815f2bd95SEwan Crawford     if (!JITTypePacked(allocation, frame_ptr))
141915f2bd95SEwan Crawford         return false;
142015f2bd95SEwan Crawford 
142115f2bd95SEwan Crawford     // rsaElementGetNativeData()
142215f2bd95SEwan Crawford     if (!JITElementPacked(allocation, frame_ptr))
142315f2bd95SEwan Crawford         return false;
142415f2bd95SEwan Crawford 
142555232f09SEwan Crawford     // Use GetOffsetPointer() to infer size of the allocation
142655232f09SEwan Crawford     const unsigned int element_size = GetElementSize(allocation);
142755232f09SEwan Crawford     if (!JITAllocationSize(allocation, frame_ptr, element_size))
142855232f09SEwan Crawford         return false;
142955232f09SEwan Crawford 
143055232f09SEwan Crawford     return true;
143155232f09SEwan Crawford }
143255232f09SEwan Crawford 
143355232f09SEwan Crawford // Returns the size of a single allocation element including padding.
143455232f09SEwan Crawford // Assumes the relevant allocation information has already been jitted.
143555232f09SEwan Crawford unsigned int
143655232f09SEwan Crawford RenderScriptRuntime::GetElementSize(const AllocationDetails* allocation)
143755232f09SEwan Crawford {
143855232f09SEwan Crawford     const AllocationDetails::DataType type = *allocation->type.get();
143955232f09SEwan Crawford     assert(type >= AllocationDetails::RS_TYPE_NONE && type <= AllocationDetails::RS_TYPE_BOOLEAN
144055232f09SEwan Crawford                                                    && "Invalid allocation type");
144155232f09SEwan Crawford 
144255232f09SEwan Crawford     const unsigned int vec_size = *allocation->type_vec_size.get();
144355232f09SEwan Crawford     const unsigned int data_size = vec_size * AllocationDetails::RSTypeToFormat[type][eElementSize];
144455232f09SEwan Crawford     const unsigned int padding = vec_size == 3 ? AllocationDetails::RSTypeToFormat[type][eElementSize] : 0;
144555232f09SEwan Crawford 
144655232f09SEwan Crawford     return data_size + padding;
144755232f09SEwan Crawford }
144855232f09SEwan Crawford 
144955232f09SEwan Crawford // Given an allocation, this function copies the allocation contents from device into a buffer on the heap.
145055232f09SEwan Crawford // Returning a shared pointer to the buffer containing the data.
145155232f09SEwan Crawford std::shared_ptr<uint8_t>
145255232f09SEwan Crawford RenderScriptRuntime::GetAllocationData(AllocationDetails* allocation, StackFrame* frame_ptr)
145355232f09SEwan Crawford {
145455232f09SEwan Crawford     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
145555232f09SEwan Crawford 
145655232f09SEwan Crawford     // JIT all the allocation details
145755232f09SEwan Crawford     if (!allocation->data_ptr.isValid() || !allocation->type.isValid() || !allocation->type_vec_size.isValid()
145855232f09SEwan Crawford         || !allocation->size.isValid())
145955232f09SEwan Crawford     {
146055232f09SEwan Crawford         if (log)
146155232f09SEwan Crawford             log->Printf("RenderScriptRuntime::GetAllocationData - Allocation details not calculated yet, jitting info");
146255232f09SEwan Crawford 
146355232f09SEwan Crawford         if (!RefreshAllocation(allocation, frame_ptr))
146455232f09SEwan Crawford         {
146555232f09SEwan Crawford             if (log)
146655232f09SEwan Crawford                 log->Printf("RenderScriptRuntime::GetAllocationData - Couldn't JIT allocation details");
146755232f09SEwan Crawford             return nullptr;
146855232f09SEwan Crawford         }
146955232f09SEwan Crawford     }
147055232f09SEwan Crawford 
147155232f09SEwan Crawford     assert(allocation->data_ptr.isValid() && allocation->type.isValid() && allocation->type_vec_size.isValid()
147255232f09SEwan Crawford            && allocation->size.isValid() && "Allocation information not available");
147355232f09SEwan Crawford 
147455232f09SEwan Crawford     // Allocate a buffer to copy data into
147555232f09SEwan Crawford     const unsigned int size = *allocation->size.get();
147655232f09SEwan Crawford     std::shared_ptr<uint8_t> buffer(new uint8_t[size]);
147755232f09SEwan Crawford     if (!buffer)
147855232f09SEwan Crawford     {
147955232f09SEwan Crawford         if (log)
148055232f09SEwan Crawford             log->Printf("RenderScriptRuntime::GetAllocationData - Couldn't allocate a %u byte buffer", size);
148155232f09SEwan Crawford         return nullptr;
148255232f09SEwan Crawford     }
148355232f09SEwan Crawford 
148455232f09SEwan Crawford     // Read the inferior memory
148555232f09SEwan Crawford     Error error;
148655232f09SEwan Crawford     lldb::addr_t data_ptr = *allocation->data_ptr.get();
148755232f09SEwan Crawford     GetProcess()->ReadMemory(data_ptr, buffer.get(), size, error);
148855232f09SEwan Crawford     if (error.Fail())
148955232f09SEwan Crawford     {
149055232f09SEwan Crawford         if (log)
149155232f09SEwan Crawford             log->Printf("RenderScriptRuntime::GetAllocationData - '%s' Couldn't read %u bytes of allocation data from 0x%" PRIx64,
149255232f09SEwan Crawford                         error.AsCString(), size, data_ptr);
149355232f09SEwan Crawford         return nullptr;
149455232f09SEwan Crawford     }
149555232f09SEwan Crawford 
149655232f09SEwan Crawford     return buffer;
149755232f09SEwan Crawford }
149855232f09SEwan Crawford 
149955232f09SEwan Crawford // Function copies data from a binary file into an allocation.
150055232f09SEwan Crawford // There is a header at the start of the file, FileHeader, before the data content itself.
150155232f09SEwan Crawford // Information from this header is used to display warnings to the user about incompatabilities
150255232f09SEwan Crawford bool
150355232f09SEwan Crawford RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id, const char* filename, StackFrame* frame_ptr)
150455232f09SEwan Crawford {
150555232f09SEwan Crawford     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
150655232f09SEwan Crawford 
150755232f09SEwan Crawford     // Find allocation with the given id
150855232f09SEwan Crawford     AllocationDetails* alloc = FindAllocByID(strm, alloc_id);
150955232f09SEwan Crawford     if (!alloc)
151055232f09SEwan Crawford         return false;
151155232f09SEwan Crawford 
151255232f09SEwan Crawford     if (log)
151355232f09SEwan Crawford         log->Printf("RenderScriptRuntime::LoadAllocation - Found allocation 0x%" PRIx64, *alloc->address.get());
151455232f09SEwan Crawford 
151555232f09SEwan Crawford     // JIT all the allocation details
151655232f09SEwan Crawford     if (!alloc->data_ptr.isValid() || !alloc->type.isValid() || !alloc->type_vec_size.isValid() || !alloc->size.isValid())
151755232f09SEwan Crawford     {
151855232f09SEwan Crawford         if (log)
151955232f09SEwan Crawford             log->Printf("RenderScriptRuntime::LoadAllocation - Allocation details not calculated yet, jitting info");
152055232f09SEwan Crawford 
152155232f09SEwan Crawford         if (!RefreshAllocation(alloc, frame_ptr))
152255232f09SEwan Crawford         {
152355232f09SEwan Crawford             if (log)
152455232f09SEwan Crawford                 log->Printf("RenderScriptRuntime::LoadAllocation - Couldn't JIT allocation details");
152555232f09SEwan Crawford             return nullptr;
152655232f09SEwan Crawford         }
152755232f09SEwan Crawford     }
152855232f09SEwan Crawford 
152955232f09SEwan Crawford     assert(alloc->data_ptr.isValid() && alloc->type.isValid() && alloc->type_vec_size.isValid() && alloc->size.isValid()
153055232f09SEwan Crawford            && "Allocation information not available");
153155232f09SEwan Crawford 
153255232f09SEwan Crawford     // Check we can read from file
153355232f09SEwan Crawford     FileSpec file(filename, true);
153455232f09SEwan Crawford     if (!file.Exists())
153555232f09SEwan Crawford     {
153655232f09SEwan Crawford         strm.Printf("Error: File %s does not exist", filename);
153755232f09SEwan Crawford         strm.EOL();
153855232f09SEwan Crawford         return false;
153955232f09SEwan Crawford     }
154055232f09SEwan Crawford 
154155232f09SEwan Crawford     if (!file.Readable())
154255232f09SEwan Crawford     {
154355232f09SEwan Crawford         strm.Printf("Error: File %s does not have readable permissions", filename);
154455232f09SEwan Crawford         strm.EOL();
154555232f09SEwan Crawford         return false;
154655232f09SEwan Crawford     }
154755232f09SEwan Crawford 
154855232f09SEwan Crawford     // Read file into data buffer
154955232f09SEwan Crawford     DataBufferSP data_sp(file.ReadFileContents());
155055232f09SEwan Crawford 
155155232f09SEwan Crawford     // Cast start of buffer to FileHeader and use pointer to read metadata
155255232f09SEwan Crawford     void* file_buffer = data_sp->GetBytes();
155355232f09SEwan Crawford     const AllocationDetails::FileHeader* head = static_cast<AllocationDetails::FileHeader*>(file_buffer);
155455232f09SEwan Crawford 
155555232f09SEwan Crawford     // Advance buffer past header
155655232f09SEwan Crawford     file_buffer = static_cast<uint8_t*>(file_buffer) + head->hdr_size;
155755232f09SEwan Crawford 
155855232f09SEwan Crawford     if (log)
155955232f09SEwan Crawford         log->Printf("RenderScriptRuntime::LoadAllocation - header type %u, element size %u",
156055232f09SEwan Crawford                     head->type, head->element_size);
156155232f09SEwan Crawford 
156255232f09SEwan Crawford     // Check if the target allocation and file both have the same number of bytes for an Element
156355232f09SEwan Crawford     const unsigned int elem_size = GetElementSize(alloc);
156455232f09SEwan Crawford     if (elem_size != head->element_size)
156555232f09SEwan Crawford     {
156655232f09SEwan Crawford         strm.Printf("Warning: Mismatched Element sizes - file %u bytes, allocation %u bytes",
156755232f09SEwan Crawford                     head->element_size, elem_size);
156855232f09SEwan Crawford         strm.EOL();
156955232f09SEwan Crawford     }
157055232f09SEwan Crawford 
157155232f09SEwan Crawford     // Check if the target allocation and file both have the same integral type
157255232f09SEwan Crawford     const unsigned int type = static_cast<unsigned int>(*alloc->type.get());
157355232f09SEwan Crawford     if (type != head->type)
157455232f09SEwan Crawford     {
157555232f09SEwan Crawford         const char* file_type_cstr = AllocationDetails::RsDataTypeToString[head->type][0];
157655232f09SEwan Crawford         const char* alloc_type_cstr = AllocationDetails::RsDataTypeToString[type][0];
157755232f09SEwan Crawford 
157855232f09SEwan Crawford         strm.Printf("Warning: Mismatched Types - file '%s' type, allocation '%s' type",
157955232f09SEwan Crawford                     file_type_cstr, alloc_type_cstr);
158055232f09SEwan Crawford         strm.EOL();
158155232f09SEwan Crawford     }
158255232f09SEwan Crawford 
158355232f09SEwan Crawford     // Calculate size of allocation data in file
158455232f09SEwan Crawford     size_t length = data_sp->GetByteSize() - head->hdr_size;
158555232f09SEwan Crawford 
158655232f09SEwan Crawford     // Check if the target allocation and file both have the same total data size.
158755232f09SEwan Crawford     const unsigned int alloc_size = *alloc->size.get();
158855232f09SEwan Crawford     if (alloc_size != length)
158955232f09SEwan Crawford     {
159055232f09SEwan Crawford         strm.Printf("Warning: Mismatched allocation sizes - file 0x%" PRIx64 " bytes, allocation 0x%x bytes",
159155232f09SEwan Crawford                     length, alloc_size);
159255232f09SEwan Crawford         strm.EOL();
159355232f09SEwan Crawford         length = alloc_size < length ? alloc_size : length; // Set length to copy to minimum
159455232f09SEwan Crawford     }
159555232f09SEwan Crawford 
159655232f09SEwan Crawford     // Copy file data from our buffer into the target allocation.
159755232f09SEwan Crawford     lldb::addr_t alloc_data = *alloc->data_ptr.get();
159855232f09SEwan Crawford     Error error;
159955232f09SEwan Crawford     size_t bytes_written = GetProcess()->WriteMemory(alloc_data, file_buffer, length, error);
160055232f09SEwan Crawford     if (!error.Success() || bytes_written != length)
160155232f09SEwan Crawford     {
160255232f09SEwan Crawford         strm.Printf("Error: Couldn't write data to allocation %s", error.AsCString());
160355232f09SEwan Crawford         strm.EOL();
160455232f09SEwan Crawford         return false;
160555232f09SEwan Crawford     }
160655232f09SEwan Crawford 
160755232f09SEwan Crawford     strm.Printf("Contents of file '%s' read into allocation %u", filename, alloc->id);
160855232f09SEwan Crawford     strm.EOL();
160955232f09SEwan Crawford 
161055232f09SEwan Crawford     return true;
161155232f09SEwan Crawford }
161255232f09SEwan Crawford 
161355232f09SEwan Crawford // Function copies allocation contents into a binary file.
161455232f09SEwan Crawford // This file can then be loaded later into a different allocation.
161555232f09SEwan Crawford // There is a header, FileHeader, before the allocation data containing meta-data.
161655232f09SEwan Crawford bool
161755232f09SEwan Crawford RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id, const char* filename, StackFrame* frame_ptr)
161855232f09SEwan Crawford {
161955232f09SEwan Crawford     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
162055232f09SEwan Crawford 
162155232f09SEwan Crawford     // Find allocation with the given id
162255232f09SEwan Crawford     AllocationDetails* alloc = FindAllocByID(strm, alloc_id);
162355232f09SEwan Crawford     if (!alloc)
162455232f09SEwan Crawford         return false;
162555232f09SEwan Crawford 
162655232f09SEwan Crawford     if (log)
162755232f09SEwan Crawford         log->Printf("RenderScriptRuntime::SaveAllocation - Found allocation 0x%" PRIx64, *alloc->address.get());
162855232f09SEwan Crawford 
162955232f09SEwan Crawford      // JIT all the allocation details
163055232f09SEwan Crawford     if (!alloc->data_ptr.isValid() || !alloc->type.isValid() || !alloc->type_vec_size.isValid()
163155232f09SEwan Crawford         || !alloc->type_kind.isValid() || !alloc->dimension.isValid())
163255232f09SEwan Crawford     {
163355232f09SEwan Crawford         if (log)
163455232f09SEwan Crawford             log->Printf("RenderScriptRuntime::SaveAllocation - Allocation details not calculated yet, jitting info");
163555232f09SEwan Crawford 
163655232f09SEwan Crawford         if (!RefreshAllocation(alloc, frame_ptr))
163755232f09SEwan Crawford         {
163855232f09SEwan Crawford             if (log)
163955232f09SEwan Crawford                 log->Printf("RenderScriptRuntime::SaveAllocation - Couldn't JIT allocation details");
164055232f09SEwan Crawford             return nullptr;
164155232f09SEwan Crawford         }
164255232f09SEwan Crawford     }
164355232f09SEwan Crawford 
164455232f09SEwan Crawford     assert(alloc->data_ptr.isValid() && alloc->type.isValid() && alloc->type_vec_size.isValid() && alloc->type_kind.isValid()
164555232f09SEwan Crawford            && alloc->dimension.isValid() && "Allocation information not available");
164655232f09SEwan Crawford 
164755232f09SEwan Crawford     // Check we can create writable file
164855232f09SEwan Crawford     FileSpec file_spec(filename, true);
164955232f09SEwan Crawford     File file(file_spec, File::eOpenOptionWrite | File::eOpenOptionCanCreate | File::eOpenOptionTruncate);
165055232f09SEwan Crawford     if (!file)
165155232f09SEwan Crawford     {
165255232f09SEwan Crawford         strm.Printf("Error: Failed to open '%s' for writing", filename);
165355232f09SEwan Crawford         strm.EOL();
165455232f09SEwan Crawford         return false;
165555232f09SEwan Crawford     }
165655232f09SEwan Crawford 
165755232f09SEwan Crawford     // Read allocation into buffer of heap memory
165855232f09SEwan Crawford     const std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr);
165955232f09SEwan Crawford     if (!buffer)
166055232f09SEwan Crawford     {
166155232f09SEwan Crawford         strm.Printf("Error: Couldn't read allocation data into buffer");
166255232f09SEwan Crawford         strm.EOL();
166355232f09SEwan Crawford         return false;
166455232f09SEwan Crawford     }
166555232f09SEwan Crawford 
166655232f09SEwan Crawford     // Create the file header
166755232f09SEwan Crawford     AllocationDetails::FileHeader head;
166855232f09SEwan Crawford     head.ident[0] = 'R'; head.ident[1] = 'S'; head.ident[2] = 'A'; head.ident[3] = 'D';
166955232f09SEwan Crawford     head.hdr_size = static_cast<uint16_t>(sizeof(AllocationDetails::FileHeader));
167055232f09SEwan Crawford     head.type = static_cast<uint16_t>(*alloc->type.get());
167155232f09SEwan Crawford     head.kind = static_cast<uint32_t>(*alloc->type_kind.get());
16722d62328aSEwan Crawford     head.dims[0] = static_cast<uint32_t>(alloc->dimension.get()->dim_1);
16732d62328aSEwan Crawford     head.dims[1] = static_cast<uint32_t>(alloc->dimension.get()->dim_2);
16742d62328aSEwan Crawford     head.dims[2] = static_cast<uint32_t>(alloc->dimension.get()->dim_3);
167555232f09SEwan Crawford     head.element_size = static_cast<uint32_t>(GetElementSize(alloc));
167655232f09SEwan Crawford 
167755232f09SEwan Crawford     // Write the file header
167855232f09SEwan Crawford     size_t num_bytes = sizeof(AllocationDetails::FileHeader);
167955232f09SEwan Crawford     Error err = file.Write(static_cast<const void*>(&head), num_bytes);
168055232f09SEwan Crawford     if (!err.Success())
168155232f09SEwan Crawford     {
168255232f09SEwan Crawford         strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), filename);
168355232f09SEwan Crawford         strm.EOL();
168455232f09SEwan Crawford         return false;
168555232f09SEwan Crawford     }
168655232f09SEwan Crawford 
168755232f09SEwan Crawford     // Write allocation data to file
168855232f09SEwan Crawford     num_bytes = static_cast<size_t>(*alloc->size.get());
168955232f09SEwan Crawford     if (log)
169055232f09SEwan Crawford         log->Printf("RenderScriptRuntime::SaveAllocation - Writing %" PRIx64  "bytes from %p", num_bytes, buffer.get());
169155232f09SEwan Crawford 
169255232f09SEwan Crawford     err = file.Write(buffer.get(), num_bytes);
169355232f09SEwan Crawford     if (!err.Success())
169455232f09SEwan Crawford     {
169555232f09SEwan Crawford         strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), filename);
169655232f09SEwan Crawford         strm.EOL();
169755232f09SEwan Crawford         return false;
169855232f09SEwan Crawford     }
169955232f09SEwan Crawford 
170055232f09SEwan Crawford     strm.Printf("Allocation written to file '%s'", filename);
170155232f09SEwan Crawford     strm.EOL();
170215f2bd95SEwan Crawford     return true;
170315f2bd95SEwan Crawford }
170415f2bd95SEwan Crawford 
17055ec532a9SColin Riley bool
17065ec532a9SColin Riley RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp)
17075ec532a9SColin Riley {
17084640cde1SColin Riley     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
17094640cde1SColin Riley 
17105ec532a9SColin Riley     if (module_sp)
17115ec532a9SColin Riley     {
17125ec532a9SColin Riley         for (const auto &rs_module : m_rsmodules)
17135ec532a9SColin Riley         {
17144640cde1SColin Riley             if (rs_module->m_module == module_sp)
17157dc7771cSEwan Crawford             {
17167dc7771cSEwan Crawford                 // Check if the user has enabled automatically breaking on
17177dc7771cSEwan Crawford                 // all RS kernels.
17187dc7771cSEwan Crawford                 if (m_breakAllKernels)
17197dc7771cSEwan Crawford                     BreakOnModuleKernels(rs_module);
17207dc7771cSEwan Crawford 
17215ec532a9SColin Riley                 return false;
17225ec532a9SColin Riley             }
17237dc7771cSEwan Crawford         }
1724ef20b08fSColin Riley         bool module_loaded = false;
1725ef20b08fSColin Riley         switch (GetModuleKind(module_sp))
1726ef20b08fSColin Riley         {
1727ef20b08fSColin Riley             case eModuleKindKernelObj:
1728ef20b08fSColin Riley             {
17294640cde1SColin Riley                 RSModuleDescriptorSP module_desc;
17304640cde1SColin Riley                 module_desc.reset(new RSModuleDescriptor(module_sp));
17314640cde1SColin Riley                 if (module_desc->ParseRSInfo())
17325ec532a9SColin Riley                 {
17335ec532a9SColin Riley                     m_rsmodules.push_back(module_desc);
1734ef20b08fSColin Riley                     module_loaded = true;
17355ec532a9SColin Riley                 }
17364640cde1SColin Riley                 if (module_loaded)
17374640cde1SColin Riley                 {
17384640cde1SColin Riley                     FixupScriptDetails(module_desc);
17394640cde1SColin Riley                 }
1740ef20b08fSColin Riley                 break;
1741ef20b08fSColin Riley             }
1742ef20b08fSColin Riley             case eModuleKindDriver:
17434640cde1SColin Riley             {
17444640cde1SColin Riley                 if (!m_libRSDriver)
17454640cde1SColin Riley                 {
17464640cde1SColin Riley                     m_libRSDriver = module_sp;
17474640cde1SColin Riley                     LoadRuntimeHooks(m_libRSDriver, RenderScriptRuntime::eModuleKindDriver);
17484640cde1SColin Riley                 }
17494640cde1SColin Riley                 break;
17504640cde1SColin Riley             }
1751ef20b08fSColin Riley             case eModuleKindImpl:
17524640cde1SColin Riley             {
17534640cde1SColin Riley                 m_libRSCpuRef = module_sp;
17544640cde1SColin Riley                 break;
17554640cde1SColin Riley             }
1756ef20b08fSColin Riley             case eModuleKindLibRS:
17574640cde1SColin Riley             {
17584640cde1SColin Riley                 if (!m_libRS)
17594640cde1SColin Riley                 {
17604640cde1SColin Riley                     m_libRS = module_sp;
17614640cde1SColin Riley                     static ConstString gDbgPresentStr("gDebuggerPresent");
17624640cde1SColin Riley                     const Symbol* debug_present = m_libRS->FindFirstSymbolWithNameAndType(gDbgPresentStr, eSymbolTypeData);
17634640cde1SColin Riley                     if (debug_present)
17644640cde1SColin Riley                     {
17654640cde1SColin Riley                         Error error;
17664640cde1SColin Riley                         uint32_t flag = 0x00000001U;
17674640cde1SColin Riley                         Target &target = GetProcess()->GetTarget();
1768358cf1eaSGreg Clayton                         addr_t addr = debug_present->GetLoadAddress(&target);
17694640cde1SColin Riley                         GetProcess()->WriteMemory(addr, &flag, sizeof(flag), error);
17704640cde1SColin Riley                         if(error.Success())
17714640cde1SColin Riley                         {
17724640cde1SColin Riley                             if (log)
17734640cde1SColin Riley                                 log->Printf ("RenderScriptRuntime::LoadModule - Debugger present flag set on debugee");
17744640cde1SColin Riley 
17754640cde1SColin Riley                             m_debuggerPresentFlagged = true;
17764640cde1SColin Riley                         }
17774640cde1SColin Riley                         else if (log)
17784640cde1SColin Riley                         {
17794640cde1SColin Riley                             log->Printf ("RenderScriptRuntime::LoadModule - Error writing debugger present flags '%s' ", error.AsCString());
17804640cde1SColin Riley                         }
17814640cde1SColin Riley                     }
17824640cde1SColin Riley                     else if (log)
17834640cde1SColin Riley                     {
17844640cde1SColin Riley                         log->Printf ("RenderScriptRuntime::LoadModule - Error writing debugger present flags - symbol not found");
17854640cde1SColin Riley                     }
17864640cde1SColin Riley                 }
17874640cde1SColin Riley                 break;
17884640cde1SColin Riley             }
1789ef20b08fSColin Riley             default:
1790ef20b08fSColin Riley                 break;
1791ef20b08fSColin Riley         }
1792ef20b08fSColin Riley         if (module_loaded)
1793ef20b08fSColin Riley             Update();
1794ef20b08fSColin Riley         return module_loaded;
17955ec532a9SColin Riley     }
17965ec532a9SColin Riley     return false;
17975ec532a9SColin Riley }
17985ec532a9SColin Riley 
1799ef20b08fSColin Riley void
1800ef20b08fSColin Riley RenderScriptRuntime::Update()
1801ef20b08fSColin Riley {
1802ef20b08fSColin Riley     if (m_rsmodules.size() > 0)
1803ef20b08fSColin Riley     {
1804ef20b08fSColin Riley         if (!m_initiated)
1805ef20b08fSColin Riley         {
1806ef20b08fSColin Riley             Initiate();
1807ef20b08fSColin Riley         }
1808ef20b08fSColin Riley     }
1809ef20b08fSColin Riley }
1810ef20b08fSColin Riley 
1811ef20b08fSColin Riley 
18125ec532a9SColin Riley // The maximum line length of an .rs.info packet
18135ec532a9SColin Riley #define MAXLINE 500
18145ec532a9SColin Riley 
18155ec532a9SColin Riley // The .rs.info symbol in renderscript modules contains a string which needs to be parsed.
18165ec532a9SColin Riley // The string is basic and is parsed on a line by line basis.
18175ec532a9SColin Riley bool
18185ec532a9SColin Riley RSModuleDescriptor::ParseRSInfo()
18195ec532a9SColin Riley {
18205ec532a9SColin Riley     const Symbol *info_sym = m_module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData);
18215ec532a9SColin Riley     if (info_sym)
18225ec532a9SColin Riley     {
1823358cf1eaSGreg Clayton         const addr_t addr = info_sym->GetAddressRef().GetFileAddress();
18245ec532a9SColin Riley         const addr_t size = info_sym->GetByteSize();
18255ec532a9SColin Riley         const FileSpec fs = m_module->GetFileSpec();
18265ec532a9SColin Riley 
18275ec532a9SColin Riley         DataBufferSP buffer = fs.ReadFileContents(addr, size);
18285ec532a9SColin Riley 
18295ec532a9SColin Riley         if (!buffer)
18305ec532a9SColin Riley             return false;
18315ec532a9SColin Riley 
18325ec532a9SColin Riley         std::string info((const char *)buffer->GetBytes());
18335ec532a9SColin Riley 
18345ec532a9SColin Riley         std::vector<std::string> info_lines;
1835e8433cc1SBruce Mitchener         size_t lpos = info.find('\n');
18365ec532a9SColin Riley         while (lpos != std::string::npos)
18375ec532a9SColin Riley         {
18385ec532a9SColin Riley             info_lines.push_back(info.substr(0, lpos));
18395ec532a9SColin Riley             info = info.substr(lpos + 1);
1840e8433cc1SBruce Mitchener             lpos = info.find('\n');
18415ec532a9SColin Riley         }
18425ec532a9SColin Riley         size_t offset = 0;
18435ec532a9SColin Riley         while (offset < info_lines.size())
18445ec532a9SColin Riley         {
18455ec532a9SColin Riley             std::string line = info_lines[offset];
18465ec532a9SColin Riley             // Parse directives
18475ec532a9SColin Riley             uint32_t numDefns = 0;
18485ec532a9SColin Riley             if (sscanf(line.c_str(), "exportVarCount: %u", &numDefns) == 1)
18495ec532a9SColin Riley             {
18505ec532a9SColin Riley                 while (numDefns--)
18514640cde1SColin Riley                     m_globals.push_back(RSGlobalDescriptor(this, info_lines[++offset].c_str()));
18525ec532a9SColin Riley             }
18535ec532a9SColin Riley             else if (sscanf(line.c_str(), "exportFuncCount: %u", &numDefns) == 1)
18545ec532a9SColin Riley             {
18555ec532a9SColin Riley             }
18565ec532a9SColin Riley             else if (sscanf(line.c_str(), "exportForEachCount: %u", &numDefns) == 1)
18575ec532a9SColin Riley             {
18585ec532a9SColin Riley                 char name[MAXLINE];
18595ec532a9SColin Riley                 while (numDefns--)
18605ec532a9SColin Riley                 {
18615ec532a9SColin Riley                     uint32_t slot = 0;
18625ec532a9SColin Riley                     name[0] = '\0';
18635ec532a9SColin Riley                     if (sscanf(info_lines[++offset].c_str(), "%u - %s", &slot, &name[0]) == 2)
18645ec532a9SColin Riley                     {
18654640cde1SColin Riley                         m_kernels.push_back(RSKernelDescriptor(this, name, slot));
18664640cde1SColin Riley                     }
18674640cde1SColin Riley                 }
18684640cde1SColin Riley             }
18694640cde1SColin Riley             else if (sscanf(line.c_str(), "pragmaCount: %u", &numDefns) == 1)
18704640cde1SColin Riley             {
18714640cde1SColin Riley                 char name[MAXLINE];
18724640cde1SColin Riley                 char value[MAXLINE];
18734640cde1SColin Riley                 while (numDefns--)
18744640cde1SColin Riley                 {
18754640cde1SColin Riley                     name[0] = '\0';
18764640cde1SColin Riley                     value[0] = '\0';
18774640cde1SColin Riley                     if (sscanf(info_lines[++offset].c_str(), "%s - %s", &name[0], &value[0]) != 0
18784640cde1SColin Riley                         && (name[0] != '\0'))
18794640cde1SColin Riley                     {
18804640cde1SColin Riley                         m_pragmas[std::string(name)] = value;
18815ec532a9SColin Riley                     }
18825ec532a9SColin Riley                 }
18835ec532a9SColin Riley             }
18845ec532a9SColin Riley             else if (sscanf(line.c_str(), "objectSlotCount: %u", &numDefns) == 1)
18855ec532a9SColin Riley             {
18865ec532a9SColin Riley             }
18875ec532a9SColin Riley 
18885ec532a9SColin Riley             offset++;
18895ec532a9SColin Riley         }
18905ec532a9SColin Riley         return m_kernels.size() > 0;
18915ec532a9SColin Riley     }
18925ec532a9SColin Riley     return false;
18935ec532a9SColin Riley }
18945ec532a9SColin Riley 
18955ec532a9SColin Riley bool
18965ec532a9SColin Riley RenderScriptRuntime::ProbeModules(const ModuleList module_list)
18975ec532a9SColin Riley {
18985ec532a9SColin Riley     bool rs_found = false;
18995ec532a9SColin Riley     size_t num_modules = module_list.GetSize();
19005ec532a9SColin Riley     for (size_t i = 0; i < num_modules; i++)
19015ec532a9SColin Riley     {
19025ec532a9SColin Riley         auto module = module_list.GetModuleAtIndex(i);
19035ec532a9SColin Riley         rs_found |= LoadModule(module);
19045ec532a9SColin Riley     }
19055ec532a9SColin Riley     return rs_found;
19065ec532a9SColin Riley }
19075ec532a9SColin Riley 
19085ec532a9SColin Riley void
19094640cde1SColin Riley RenderScriptRuntime::Status(Stream &strm) const
19104640cde1SColin Riley {
19114640cde1SColin Riley     if (m_libRS)
19124640cde1SColin Riley     {
19134640cde1SColin Riley         strm.Printf("Runtime Library discovered.");
19144640cde1SColin Riley         strm.EOL();
19154640cde1SColin Riley     }
19164640cde1SColin Riley     if (m_libRSDriver)
19174640cde1SColin Riley     {
19184640cde1SColin Riley         strm.Printf("Runtime Driver discovered.");
19194640cde1SColin Riley         strm.EOL();
19204640cde1SColin Riley     }
19214640cde1SColin Riley     if (m_libRSCpuRef)
19224640cde1SColin Riley     {
19234640cde1SColin Riley         strm.Printf("CPU Reference Implementation discovered.");
19244640cde1SColin Riley         strm.EOL();
19254640cde1SColin Riley     }
19264640cde1SColin Riley 
19274640cde1SColin Riley     if (m_runtimeHooks.size())
19284640cde1SColin Riley     {
19294640cde1SColin Riley         strm.Printf("Runtime functions hooked:");
19304640cde1SColin Riley         strm.EOL();
19314640cde1SColin Riley         for (auto b : m_runtimeHooks)
19324640cde1SColin Riley         {
19334640cde1SColin Riley             strm.Indent(b.second->defn->name);
19344640cde1SColin Riley             strm.EOL();
19354640cde1SColin Riley         }
19364640cde1SColin Riley         strm.EOL();
19374640cde1SColin Riley     }
19384640cde1SColin Riley     else
19394640cde1SColin Riley     {
19404640cde1SColin Riley         strm.Printf("Runtime is not hooked.");
19414640cde1SColin Riley         strm.EOL();
19424640cde1SColin Riley     }
19434640cde1SColin Riley }
19444640cde1SColin Riley 
19454640cde1SColin Riley void
19464640cde1SColin Riley RenderScriptRuntime::DumpContexts(Stream &strm) const
19474640cde1SColin Riley {
19484640cde1SColin Riley     strm.Printf("Inferred RenderScript Contexts:");
19494640cde1SColin Riley     strm.EOL();
19504640cde1SColin Riley     strm.IndentMore();
19514640cde1SColin Riley 
19524640cde1SColin Riley     std::map<addr_t, uint64_t> contextReferences;
19534640cde1SColin Riley 
195478f339d1SEwan Crawford     // Iterate over all of the currently discovered scripts.
195578f339d1SEwan Crawford     // Note: We cant push or pop from m_scripts inside this loop or it may invalidate script.
19564640cde1SColin Riley     for (const auto & script : m_scripts)
19574640cde1SColin Riley     {
195878f339d1SEwan Crawford         if (!script->context.isValid())
195978f339d1SEwan Crawford             continue;
196078f339d1SEwan Crawford         lldb::addr_t context = *script->context;
196178f339d1SEwan Crawford 
196278f339d1SEwan Crawford         if (contextReferences.find(context) != contextReferences.end())
19634640cde1SColin Riley         {
196478f339d1SEwan Crawford             contextReferences[context]++;
19654640cde1SColin Riley         }
19664640cde1SColin Riley         else
19674640cde1SColin Riley         {
196878f339d1SEwan Crawford             contextReferences[context] = 1;
19694640cde1SColin Riley         }
19704640cde1SColin Riley     }
19714640cde1SColin Riley 
19724640cde1SColin Riley     for (const auto& cRef : contextReferences)
19734640cde1SColin Riley     {
19744640cde1SColin Riley         strm.Printf("Context 0x%" PRIx64 ": %" PRIu64 " script instances", cRef.first, cRef.second);
19754640cde1SColin Riley         strm.EOL();
19764640cde1SColin Riley     }
19774640cde1SColin Riley     strm.IndentLess();
19784640cde1SColin Riley }
19794640cde1SColin Riley 
19804640cde1SColin Riley void
19814640cde1SColin Riley RenderScriptRuntime::DumpKernels(Stream &strm) const
19824640cde1SColin Riley {
19834640cde1SColin Riley     strm.Printf("RenderScript Kernels:");
19844640cde1SColin Riley     strm.EOL();
19854640cde1SColin Riley     strm.IndentMore();
19864640cde1SColin Riley     for (const auto &module : m_rsmodules)
19874640cde1SColin Riley     {
19884640cde1SColin Riley         strm.Printf("Resource '%s':",module->m_resname.c_str());
19894640cde1SColin Riley         strm.EOL();
19904640cde1SColin Riley         for (const auto &kernel : module->m_kernels)
19914640cde1SColin Riley         {
19924640cde1SColin Riley             strm.Indent(kernel.m_name.AsCString());
19934640cde1SColin Riley             strm.EOL();
19944640cde1SColin Riley         }
19954640cde1SColin Riley     }
19964640cde1SColin Riley     strm.IndentLess();
19974640cde1SColin Riley }
19984640cde1SColin Riley 
1999a0f08674SEwan Crawford RenderScriptRuntime::AllocationDetails*
2000a0f08674SEwan Crawford RenderScriptRuntime::FindAllocByID(Stream &strm, const uint32_t alloc_id)
2001a0f08674SEwan Crawford {
2002a0f08674SEwan Crawford     AllocationDetails* alloc = nullptr;
2003a0f08674SEwan Crawford 
2004a0f08674SEwan Crawford     // See if we can find allocation using id as an index;
2005a0f08674SEwan Crawford     if (alloc_id <= m_allocations.size() && alloc_id != 0
2006a0f08674SEwan Crawford         && m_allocations[alloc_id-1]->id == alloc_id)
2007a0f08674SEwan Crawford     {
2008a0f08674SEwan Crawford         alloc = m_allocations[alloc_id-1].get();
2009a0f08674SEwan Crawford         return alloc;
2010a0f08674SEwan Crawford     }
2011a0f08674SEwan Crawford 
2012a0f08674SEwan Crawford     // Fallback to searching
2013a0f08674SEwan Crawford     for (const auto & a : m_allocations)
2014a0f08674SEwan Crawford     {
2015a0f08674SEwan Crawford        if (a->id == alloc_id)
2016a0f08674SEwan Crawford        {
2017a0f08674SEwan Crawford            alloc = a.get();
2018a0f08674SEwan Crawford            break;
2019a0f08674SEwan Crawford        }
2020a0f08674SEwan Crawford     }
2021a0f08674SEwan Crawford 
2022a0f08674SEwan Crawford     if (alloc == nullptr)
2023a0f08674SEwan Crawford     {
2024a0f08674SEwan Crawford         strm.Printf("Error: Couldn't find allocation with id matching %u", alloc_id);
2025a0f08674SEwan Crawford         strm.EOL();
2026a0f08674SEwan Crawford     }
2027a0f08674SEwan Crawford 
2028a0f08674SEwan Crawford     return alloc;
2029a0f08674SEwan Crawford }
2030a0f08674SEwan Crawford 
2031a0f08674SEwan Crawford // Prints the contents of an allocation to the output stream, which may be a file
2032a0f08674SEwan Crawford bool
2033a0f08674SEwan Crawford RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame* frame_ptr, const uint32_t id)
2034a0f08674SEwan Crawford {
2035a0f08674SEwan Crawford     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
2036a0f08674SEwan Crawford 
2037a0f08674SEwan Crawford     // Check we can find the desired allocation
2038a0f08674SEwan Crawford     AllocationDetails* alloc = FindAllocByID(strm, id);
2039a0f08674SEwan Crawford     if (!alloc)
2040a0f08674SEwan Crawford         return false; // FindAllocByID() will print error message for us here
2041a0f08674SEwan Crawford 
2042a0f08674SEwan Crawford     if (log)
2043a0f08674SEwan Crawford         log->Printf("RenderScriptRuntime::DumpAllocation - Found allocation 0x%" PRIx64, *alloc->address.get());
2044a0f08674SEwan Crawford 
2045a0f08674SEwan Crawford     // Check we have information about the allocation, if not calculate it
2046a0f08674SEwan Crawford     if (!alloc->data_ptr.isValid() || !alloc->type.isValid() ||
2047a0f08674SEwan Crawford         !alloc->type_vec_size.isValid() || !alloc->dimension.isValid())
2048a0f08674SEwan Crawford     {
2049a0f08674SEwan Crawford         if (log)
2050a0f08674SEwan Crawford             log->Printf("RenderScriptRuntime::DumpAllocation - Allocation details not calculated yet, jitting info");
2051a0f08674SEwan Crawford 
2052a0f08674SEwan Crawford         // JIT all the allocation information
2053a0f08674SEwan Crawford         if (!RefreshAllocation(alloc, frame_ptr))
2054a0f08674SEwan Crawford         {
2055a0f08674SEwan Crawford             strm.Printf("Error: Couldn't JIT allocation details");
2056a0f08674SEwan Crawford             strm.EOL();
2057a0f08674SEwan Crawford             return false;
2058a0f08674SEwan Crawford         }
2059a0f08674SEwan Crawford     }
2060a0f08674SEwan Crawford 
2061a0f08674SEwan Crawford     // Establish format and size of each data element
2062a0f08674SEwan Crawford     const unsigned int vec_size = *alloc->type_vec_size.get();
2063a0f08674SEwan Crawford     const AllocationDetails::DataType type = *alloc->type.get();
2064a0f08674SEwan Crawford 
2065a0f08674SEwan Crawford     assert(type >= AllocationDetails::RS_TYPE_NONE && type <= AllocationDetails::RS_TYPE_BOOLEAN
2066a0f08674SEwan Crawford                                                    && "Invalid allocation type");
2067a0f08674SEwan Crawford 
2068a0f08674SEwan Crawford     lldb::Format format = vec_size == 1 ? static_cast<lldb::Format>(AllocationDetails::RSTypeToFormat[type][eFormatSingle])
2069a0f08674SEwan Crawford                                         : static_cast<lldb::Format>(AllocationDetails::RSTypeToFormat[type][eFormatVector]);
2070a0f08674SEwan Crawford 
2071a0f08674SEwan Crawford     const unsigned int data_size = vec_size * AllocationDetails::RSTypeToFormat[type][eElementSize];
2072a0f08674SEwan Crawford     // Renderscript pads vector 3 elements to vector 4
2073a0f08674SEwan Crawford     const unsigned int elem_padding = vec_size == 3 ? AllocationDetails::RSTypeToFormat[type][eElementSize] : 0;
2074a0f08674SEwan Crawford 
2075a0f08674SEwan Crawford     if (log)
2076a0f08674SEwan Crawford         log->Printf("RenderScriptRuntime::DumpAllocation - Element size %u bytes, element padding %u bytes",
2077a0f08674SEwan Crawford                     data_size, elem_padding);
2078a0f08674SEwan Crawford 
207955232f09SEwan Crawford     // Allocate a buffer to copy data into
208055232f09SEwan Crawford     std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr);
208155232f09SEwan Crawford     if (!buffer)
208255232f09SEwan Crawford     {
208355232f09SEwan Crawford         strm.Printf("Error: Couldn't allocate a read allocation data into memory");
208455232f09SEwan Crawford         strm.EOL();
208555232f09SEwan Crawford         return false;
208655232f09SEwan Crawford     }
208755232f09SEwan Crawford 
2088a0f08674SEwan Crawford     // Calculate stride between rows as there may be padding at end of rows since
2089a0f08674SEwan Crawford     // allocated memory is 16-byte aligned
2090a0f08674SEwan Crawford     if (!alloc->stride.isValid())
2091a0f08674SEwan Crawford     {
2092a0f08674SEwan Crawford         if (alloc->dimension.get()->dim_2 == 0) // We only have one dimension
2093a0f08674SEwan Crawford             alloc->stride = 0;
2094a0f08674SEwan Crawford         else if (!JITAllocationStride(alloc, frame_ptr))
2095a0f08674SEwan Crawford         {
2096a0f08674SEwan Crawford             strm.Printf("Error: Couldn't calculate allocation row stride");
2097a0f08674SEwan Crawford             strm.EOL();
2098a0f08674SEwan Crawford             return false;
2099a0f08674SEwan Crawford         }
2100a0f08674SEwan Crawford     }
2101a0f08674SEwan Crawford     const unsigned int stride = *alloc->stride.get();
2102a0f08674SEwan Crawford     const unsigned int size = *alloc->size.get(); //size of last element
2103a0f08674SEwan Crawford 
2104a0f08674SEwan Crawford     if (log)
2105a0f08674SEwan Crawford         log->Printf("RenderScriptRuntime::DumpAllocation - stride %u bytes, size %u bytes", stride, size);
2106a0f08674SEwan Crawford 
2107a0f08674SEwan Crawford     // Find dimensions used to index loops, so need to be non-zero
2108a0f08674SEwan Crawford     unsigned int dim_x = alloc->dimension.get()->dim_1;
2109a0f08674SEwan Crawford     dim_x = dim_x == 0 ? 1 : dim_x;
2110a0f08674SEwan Crawford 
2111a0f08674SEwan Crawford     unsigned int dim_y = alloc->dimension.get()->dim_2;
2112a0f08674SEwan Crawford     dim_y = dim_y == 0 ? 1 : dim_y;
2113a0f08674SEwan Crawford 
2114a0f08674SEwan Crawford     unsigned int dim_z = alloc->dimension.get()->dim_3;
2115a0f08674SEwan Crawford     dim_z = dim_z == 0 ? 1 : dim_z;
2116a0f08674SEwan Crawford 
211755232f09SEwan Crawford     // Use data extractor to format output
211855232f09SEwan Crawford     const uint32_t archByteSize = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
211955232f09SEwan Crawford     DataExtractor alloc_data(buffer.get(), size, GetProcess()->GetByteOrder(), archByteSize);
212055232f09SEwan Crawford 
2121a0f08674SEwan Crawford     unsigned int offset = 0;   // Offset in buffer to next element to be printed
2122a0f08674SEwan Crawford     unsigned int prev_row = 0; // Offset to the start of the previous row
2123a0f08674SEwan Crawford 
2124a0f08674SEwan Crawford     // Iterate over allocation dimensions, printing results to user
2125a0f08674SEwan Crawford     strm.Printf("Data (X, Y, Z):");
2126a0f08674SEwan Crawford     for (unsigned int z = 0; z < dim_z; ++z)
2127a0f08674SEwan Crawford     {
2128a0f08674SEwan Crawford         for (unsigned int y = 0; y < dim_y; ++y)
2129a0f08674SEwan Crawford         {
2130a0f08674SEwan Crawford             // Use stride to index start of next row.
2131a0f08674SEwan Crawford             if (!(y==0 && z==0))
2132a0f08674SEwan Crawford                 offset = prev_row + stride;
2133a0f08674SEwan Crawford             prev_row = offset;
2134a0f08674SEwan Crawford 
2135a0f08674SEwan Crawford             // Print each element in the row individually
2136a0f08674SEwan Crawford             for (unsigned int x = 0; x < dim_x; ++x)
2137a0f08674SEwan Crawford             {
2138a0f08674SEwan Crawford                 strm.Printf("\n(%u, %u, %u) = ", x, y, z);
2139a0f08674SEwan Crawford                 alloc_data.Dump(&strm, offset, format, data_size, 1, 1, LLDB_INVALID_ADDRESS, 0, 0);
2140a0f08674SEwan Crawford                 offset += data_size + elem_padding;
2141a0f08674SEwan Crawford             }
2142a0f08674SEwan Crawford         }
2143a0f08674SEwan Crawford     }
2144a0f08674SEwan Crawford     strm.EOL();
2145a0f08674SEwan Crawford 
2146a0f08674SEwan Crawford     return true;
2147a0f08674SEwan Crawford }
2148a0f08674SEwan Crawford 
214915f2bd95SEwan Crawford // Prints infomation regarding all the currently loaded allocations.
215015f2bd95SEwan Crawford // These details are gathered by jitting the runtime, which has as latency.
215115f2bd95SEwan Crawford void
215215f2bd95SEwan Crawford RenderScriptRuntime::ListAllocations(Stream &strm, StackFrame* frame_ptr, bool recompute)
215315f2bd95SEwan Crawford {
215415f2bd95SEwan Crawford     strm.Printf("RenderScript Allocations:");
215515f2bd95SEwan Crawford     strm.EOL();
215615f2bd95SEwan Crawford     strm.IndentMore();
215715f2bd95SEwan Crawford 
215815f2bd95SEwan Crawford     for (auto &alloc : m_allocations)
215915f2bd95SEwan Crawford     {
216015f2bd95SEwan Crawford         // JIT the allocation info if we haven't done it, or the user forces us to.
216115f2bd95SEwan Crawford         bool do_refresh = !alloc->data_ptr.isValid() || recompute;
216215f2bd95SEwan Crawford 
216315f2bd95SEwan Crawford         // JIT current allocation information
216415f2bd95SEwan Crawford         if (do_refresh && !RefreshAllocation(alloc.get(), frame_ptr))
216515f2bd95SEwan Crawford         {
216615f2bd95SEwan Crawford             strm.Printf("Error: Couldn't evaluate details for allocation %u\n", alloc->id);
216715f2bd95SEwan Crawford             continue;
216815f2bd95SEwan Crawford         }
216915f2bd95SEwan Crawford 
217015f2bd95SEwan Crawford         strm.Printf("%u:\n",alloc->id);
217115f2bd95SEwan Crawford         strm.IndentMore();
217215f2bd95SEwan Crawford 
217315f2bd95SEwan Crawford         strm.Indent("Context: ");
217415f2bd95SEwan Crawford         if (!alloc->context.isValid())
217515f2bd95SEwan Crawford             strm.Printf("unknown\n");
217615f2bd95SEwan Crawford         else
217715f2bd95SEwan Crawford             strm.Printf("0x%" PRIx64 "\n", *alloc->context.get());
217815f2bd95SEwan Crawford 
217915f2bd95SEwan Crawford         strm.Indent("Address: ");
218015f2bd95SEwan Crawford         if (!alloc->address.isValid())
218115f2bd95SEwan Crawford             strm.Printf("unknown\n");
218215f2bd95SEwan Crawford         else
218315f2bd95SEwan Crawford             strm.Printf("0x%" PRIx64 "\n", *alloc->address.get());
218415f2bd95SEwan Crawford 
218515f2bd95SEwan Crawford         strm.Indent("Data pointer: ");
218615f2bd95SEwan Crawford         if (!alloc->data_ptr.isValid())
218715f2bd95SEwan Crawford             strm.Printf("unknown\n");
218815f2bd95SEwan Crawford         else
218915f2bd95SEwan Crawford             strm.Printf("0x%" PRIx64 "\n", *alloc->data_ptr.get());
219015f2bd95SEwan Crawford 
219115f2bd95SEwan Crawford         strm.Indent("Dimensions: ");
219215f2bd95SEwan Crawford         if (!alloc->dimension.isValid())
219315f2bd95SEwan Crawford             strm.Printf("unknown\n");
219415f2bd95SEwan Crawford         else
219515f2bd95SEwan Crawford             strm.Printf("(%d, %d, %d)\n", alloc->dimension.get()->dim_1,
219615f2bd95SEwan Crawford                                           alloc->dimension.get()->dim_2,
219715f2bd95SEwan Crawford                                           alloc->dimension.get()->dim_3);
219815f2bd95SEwan Crawford 
219915f2bd95SEwan Crawford         strm.Indent("Data Type: ");
220015f2bd95SEwan Crawford         if (!alloc->type.isValid() || !alloc->type_vec_size.isValid())
220115f2bd95SEwan Crawford             strm.Printf("unknown\n");
220215f2bd95SEwan Crawford         else
220315f2bd95SEwan Crawford         {
220415f2bd95SEwan Crawford             const int vector_size = *alloc->type_vec_size.get();
220515f2bd95SEwan Crawford             const AllocationDetails::DataType type = *alloc->type.get();
220615f2bd95SEwan Crawford 
220715f2bd95SEwan Crawford             if (vector_size > 4 || vector_size < 1 ||
220815f2bd95SEwan Crawford                 type < AllocationDetails::RS_TYPE_NONE || type > AllocationDetails::RS_TYPE_BOOLEAN)
220915f2bd95SEwan Crawford                 strm.Printf("invalid type\n");
221015f2bd95SEwan Crawford             else
221115f2bd95SEwan Crawford                 strm.Printf("%s\n", AllocationDetails::RsDataTypeToString[static_cast<unsigned int>(type)][vector_size-1]);
221215f2bd95SEwan Crawford         }
221315f2bd95SEwan Crawford 
221415f2bd95SEwan Crawford         strm.Indent("Data Kind: ");
221515f2bd95SEwan Crawford         if (!alloc->type_kind.isValid())
221615f2bd95SEwan Crawford             strm.Printf("unknown\n");
221715f2bd95SEwan Crawford         else
221815f2bd95SEwan Crawford         {
221915f2bd95SEwan Crawford             const AllocationDetails::DataKind kind = *alloc->type_kind.get();
222015f2bd95SEwan Crawford             if (kind < AllocationDetails::RS_KIND_USER || kind > AllocationDetails::RS_KIND_PIXEL_YUV)
222115f2bd95SEwan Crawford                 strm.Printf("invalid kind\n");
222215f2bd95SEwan Crawford             else
222315f2bd95SEwan Crawford                 strm.Printf("%s\n", AllocationDetails::RsDataKindToString[static_cast<unsigned int>(kind)]);
222415f2bd95SEwan Crawford         }
222515f2bd95SEwan Crawford 
222615f2bd95SEwan Crawford         strm.EOL();
222715f2bd95SEwan Crawford         strm.IndentLess();
222815f2bd95SEwan Crawford     }
222915f2bd95SEwan Crawford     strm.IndentLess();
223015f2bd95SEwan Crawford }
223115f2bd95SEwan Crawford 
22327dc7771cSEwan Crawford // Set breakpoints on every kernel found in RS module
22337dc7771cSEwan Crawford void
22347dc7771cSEwan Crawford RenderScriptRuntime::BreakOnModuleKernels(const RSModuleDescriptorSP rsmodule_sp)
22357dc7771cSEwan Crawford {
22367dc7771cSEwan Crawford     for (const auto &kernel : rsmodule_sp->m_kernels)
22377dc7771cSEwan Crawford     {
22387dc7771cSEwan Crawford         // Don't set breakpoint on 'root' kernel
22397dc7771cSEwan Crawford         if (strcmp(kernel.m_name.AsCString(), "root") == 0)
22407dc7771cSEwan Crawford             continue;
22417dc7771cSEwan Crawford 
22427dc7771cSEwan Crawford         CreateKernelBreakpoint(kernel.m_name);
22437dc7771cSEwan Crawford     }
22447dc7771cSEwan Crawford }
22457dc7771cSEwan Crawford 
22467dc7771cSEwan Crawford // Method is internally called by the 'kernel breakpoint all' command to
22477dc7771cSEwan Crawford // enable or disable breaking on all kernels.
22487dc7771cSEwan Crawford //
22497dc7771cSEwan Crawford // When do_break is true we want to enable this functionality.
22507dc7771cSEwan Crawford // When do_break is false we want to disable it.
22517dc7771cSEwan Crawford void
22527dc7771cSEwan Crawford RenderScriptRuntime::SetBreakAllKernels(bool do_break, TargetSP target)
22537dc7771cSEwan Crawford {
225454782db7SEwan Crawford     Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
22557dc7771cSEwan Crawford 
22567dc7771cSEwan Crawford     InitSearchFilter(target);
22577dc7771cSEwan Crawford 
22587dc7771cSEwan Crawford     // Set breakpoints on all the kernels
22597dc7771cSEwan Crawford     if (do_break && !m_breakAllKernels)
22607dc7771cSEwan Crawford     {
22617dc7771cSEwan Crawford         m_breakAllKernels = true;
22627dc7771cSEwan Crawford 
22637dc7771cSEwan Crawford         for (const auto &module : m_rsmodules)
22647dc7771cSEwan Crawford             BreakOnModuleKernels(module);
22657dc7771cSEwan Crawford 
22667dc7771cSEwan Crawford         if (log)
22677dc7771cSEwan Crawford             log->Printf("RenderScriptRuntime::SetBreakAllKernels(True)"
22687dc7771cSEwan Crawford                         "- breakpoints set on all currently loaded kernels");
22697dc7771cSEwan Crawford     }
22707dc7771cSEwan Crawford     else if (!do_break && m_breakAllKernels) // Breakpoints won't be set on any new kernels.
22717dc7771cSEwan Crawford     {
22727dc7771cSEwan Crawford         m_breakAllKernels = false;
22737dc7771cSEwan Crawford 
22747dc7771cSEwan Crawford         if (log)
22757dc7771cSEwan Crawford             log->Printf("RenderScriptRuntime::SetBreakAllKernels(False) - breakpoints no longer automatically set");
22767dc7771cSEwan Crawford     }
22777dc7771cSEwan Crawford }
22787dc7771cSEwan Crawford 
22797dc7771cSEwan Crawford // Given the name of a kernel this function creates a breakpoint using our
22807dc7771cSEwan Crawford // own breakpoint resolver, and returns the Breakpoint shared pointer.
22817dc7771cSEwan Crawford BreakpointSP
22827dc7771cSEwan Crawford RenderScriptRuntime::CreateKernelBreakpoint(const ConstString& name)
22837dc7771cSEwan Crawford {
228454782db7SEwan Crawford     Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
22857dc7771cSEwan Crawford 
22867dc7771cSEwan Crawford     if (!m_filtersp)
22877dc7771cSEwan Crawford     {
22887dc7771cSEwan Crawford         if (log)
22897dc7771cSEwan Crawford             log->Printf("RenderScriptRuntime::CreateKernelBreakpoint - Error: No breakpoint search filter set");
22907dc7771cSEwan Crawford         return nullptr;
22917dc7771cSEwan Crawford     }
22927dc7771cSEwan Crawford 
22937dc7771cSEwan Crawford     BreakpointResolverSP resolver_sp(new RSBreakpointResolver(nullptr, name));
22947dc7771cSEwan Crawford     BreakpointSP bp = GetProcess()->GetTarget().CreateBreakpoint(m_filtersp, resolver_sp, false, false, false);
22957dc7771cSEwan Crawford 
229654782db7SEwan Crawford     // Give RS breakpoints a specific name, so the user can manipulate them as a group.
229754782db7SEwan Crawford     Error err;
229854782db7SEwan Crawford     if (!bp->AddName("RenderScriptKernel", err) && log)
229954782db7SEwan Crawford         log->Printf("RenderScriptRuntime::CreateKernelBreakpoint: Error setting break name, %s", err.AsCString());
230054782db7SEwan Crawford 
23017dc7771cSEwan Crawford     return bp;
23027dc7771cSEwan Crawford }
23037dc7771cSEwan Crawford 
23044640cde1SColin Riley void
230598156583SEwan Crawford RenderScriptRuntime::AttemptBreakpointAtKernelName(Stream &strm, const char* name, Error& error, TargetSP target)
23064640cde1SColin Riley {
23074640cde1SColin Riley     if (!name)
23084640cde1SColin Riley     {
23094640cde1SColin Riley         error.SetErrorString("invalid kernel name");
23104640cde1SColin Riley         return;
23114640cde1SColin Riley     }
23124640cde1SColin Riley 
23137dc7771cSEwan Crawford     InitSearchFilter(target);
231498156583SEwan Crawford 
23154640cde1SColin Riley     ConstString kernel_name(name);
23167dc7771cSEwan Crawford     BreakpointSP bp = CreateKernelBreakpoint(kernel_name);
231798156583SEwan Crawford     if (bp)
231898156583SEwan Crawford         bp->GetDescription(&strm, lldb::eDescriptionLevelInitial, false);
23194640cde1SColin Riley 
23204640cde1SColin Riley     return;
23214640cde1SColin Riley }
23224640cde1SColin Riley 
23234640cde1SColin Riley void
23245ec532a9SColin Riley RenderScriptRuntime::DumpModules(Stream &strm) const
23255ec532a9SColin Riley {
23265ec532a9SColin Riley     strm.Printf("RenderScript Modules:");
23275ec532a9SColin Riley     strm.EOL();
23285ec532a9SColin Riley     strm.IndentMore();
23295ec532a9SColin Riley     for (const auto &module : m_rsmodules)
23305ec532a9SColin Riley     {
23314640cde1SColin Riley         module->Dump(strm);
23325ec532a9SColin Riley     }
23335ec532a9SColin Riley     strm.IndentLess();
23345ec532a9SColin Riley }
23355ec532a9SColin Riley 
233678f339d1SEwan Crawford RenderScriptRuntime::ScriptDetails*
233778f339d1SEwan Crawford RenderScriptRuntime::LookUpScript(addr_t address, bool create)
233878f339d1SEwan Crawford {
233978f339d1SEwan Crawford     for (const auto & s : m_scripts)
234078f339d1SEwan Crawford     {
234178f339d1SEwan Crawford         if (s->script.isValid())
234278f339d1SEwan Crawford             if (*s->script == address)
234378f339d1SEwan Crawford                 return s.get();
234478f339d1SEwan Crawford     }
234578f339d1SEwan Crawford     if (create)
234678f339d1SEwan Crawford     {
234778f339d1SEwan Crawford         std::unique_ptr<ScriptDetails> s(new ScriptDetails);
234878f339d1SEwan Crawford         s->script = address;
234978f339d1SEwan Crawford         m_scripts.push_back(std::move(s));
2350d10ca9deSEwan Crawford         return m_scripts.back().get();
235178f339d1SEwan Crawford     }
235278f339d1SEwan Crawford     return nullptr;
235378f339d1SEwan Crawford }
235478f339d1SEwan Crawford 
235578f339d1SEwan Crawford RenderScriptRuntime::AllocationDetails*
235678f339d1SEwan Crawford RenderScriptRuntime::LookUpAllocation(addr_t address, bool create)
235778f339d1SEwan Crawford {
235878f339d1SEwan Crawford     for (const auto & a : m_allocations)
235978f339d1SEwan Crawford     {
236078f339d1SEwan Crawford         if (a->address.isValid())
236178f339d1SEwan Crawford             if (*a->address == address)
236278f339d1SEwan Crawford                 return a.get();
236378f339d1SEwan Crawford     }
236478f339d1SEwan Crawford     if (create)
236578f339d1SEwan Crawford     {
236678f339d1SEwan Crawford         std::unique_ptr<AllocationDetails> a(new AllocationDetails);
236778f339d1SEwan Crawford         a->address = address;
236878f339d1SEwan Crawford         m_allocations.push_back(std::move(a));
2369d10ca9deSEwan Crawford         return m_allocations.back().get();
237078f339d1SEwan Crawford     }
237178f339d1SEwan Crawford     return nullptr;
237278f339d1SEwan Crawford }
237378f339d1SEwan Crawford 
23745ec532a9SColin Riley void
23755ec532a9SColin Riley RSModuleDescriptor::Dump(Stream &strm) const
23765ec532a9SColin Riley {
23775ec532a9SColin Riley     strm.Indent();
23785ec532a9SColin Riley     m_module->GetFileSpec().Dump(&strm);
23794640cde1SColin Riley     if(m_module->GetNumCompileUnits())
23804640cde1SColin Riley     {
23814640cde1SColin Riley         strm.Indent("Debug info loaded.");
23824640cde1SColin Riley     }
23834640cde1SColin Riley     else
23844640cde1SColin Riley     {
23854640cde1SColin Riley         strm.Indent("Debug info does not exist.");
23864640cde1SColin Riley     }
23875ec532a9SColin Riley     strm.EOL();
23885ec532a9SColin Riley     strm.IndentMore();
23895ec532a9SColin Riley     strm.Indent();
2390189598edSColin Riley     strm.Printf("Globals: %" PRIu64, static_cast<uint64_t>(m_globals.size()));
23915ec532a9SColin Riley     strm.EOL();
23925ec532a9SColin Riley     strm.IndentMore();
23935ec532a9SColin Riley     for (const auto &global : m_globals)
23945ec532a9SColin Riley     {
23955ec532a9SColin Riley         global.Dump(strm);
23965ec532a9SColin Riley     }
23975ec532a9SColin Riley     strm.IndentLess();
23985ec532a9SColin Riley     strm.Indent();
2399189598edSColin Riley     strm.Printf("Kernels: %" PRIu64, static_cast<uint64_t>(m_kernels.size()));
24005ec532a9SColin Riley     strm.EOL();
24015ec532a9SColin Riley     strm.IndentMore();
24025ec532a9SColin Riley     for (const auto &kernel : m_kernels)
24035ec532a9SColin Riley     {
24045ec532a9SColin Riley         kernel.Dump(strm);
24055ec532a9SColin Riley     }
24064640cde1SColin Riley     strm.Printf("Pragmas: %"  PRIu64 , static_cast<uint64_t>(m_pragmas.size()));
24074640cde1SColin Riley     strm.EOL();
24084640cde1SColin Riley     strm.IndentMore();
24094640cde1SColin Riley     for (const auto &key_val : m_pragmas)
24104640cde1SColin Riley     {
24114640cde1SColin Riley         strm.Printf("%s: %s", key_val.first.c_str(), key_val.second.c_str());
24124640cde1SColin Riley         strm.EOL();
24134640cde1SColin Riley     }
24145ec532a9SColin Riley     strm.IndentLess(4);
24155ec532a9SColin Riley }
24165ec532a9SColin Riley 
24175ec532a9SColin Riley void
24185ec532a9SColin Riley RSGlobalDescriptor::Dump(Stream &strm) const
24195ec532a9SColin Riley {
24205ec532a9SColin Riley     strm.Indent(m_name.AsCString());
24214640cde1SColin Riley     VariableList var_list;
24224640cde1SColin Riley     m_module->m_module->FindGlobalVariables(m_name, nullptr, true, 1U, var_list);
24234640cde1SColin Riley     if (var_list.GetSize() == 1)
24244640cde1SColin Riley     {
24254640cde1SColin Riley         auto var = var_list.GetVariableAtIndex(0);
24264640cde1SColin Riley         auto type = var->GetType();
24274640cde1SColin Riley         if(type)
24284640cde1SColin Riley         {
24294640cde1SColin Riley             strm.Printf(" - ");
24304640cde1SColin Riley             type->DumpTypeName(&strm);
24314640cde1SColin Riley         }
24324640cde1SColin Riley         else
24334640cde1SColin Riley         {
24344640cde1SColin Riley             strm.Printf(" - Unknown Type");
24354640cde1SColin Riley         }
24364640cde1SColin Riley     }
24374640cde1SColin Riley     else
24384640cde1SColin Riley     {
24394640cde1SColin Riley         strm.Printf(" - variable identified, but not found in binary");
24404640cde1SColin Riley         const Symbol* s = m_module->m_module->FindFirstSymbolWithNameAndType(m_name, eSymbolTypeData);
24414640cde1SColin Riley         if (s)
24424640cde1SColin Riley         {
24434640cde1SColin Riley             strm.Printf(" (symbol exists) ");
24444640cde1SColin Riley         }
24454640cde1SColin Riley     }
24464640cde1SColin Riley 
24475ec532a9SColin Riley     strm.EOL();
24485ec532a9SColin Riley }
24495ec532a9SColin Riley 
24505ec532a9SColin Riley void
24515ec532a9SColin Riley RSKernelDescriptor::Dump(Stream &strm) const
24525ec532a9SColin Riley {
24535ec532a9SColin Riley     strm.Indent(m_name.AsCString());
24545ec532a9SColin Riley     strm.EOL();
24555ec532a9SColin Riley }
24565ec532a9SColin Riley 
24575ec532a9SColin Riley class CommandObjectRenderScriptRuntimeModuleProbe : public CommandObjectParsed
24585ec532a9SColin Riley {
24595ec532a9SColin Riley   private:
24605ec532a9SColin Riley   public:
24615ec532a9SColin Riley     CommandObjectRenderScriptRuntimeModuleProbe(CommandInterpreter &interpreter)
24625ec532a9SColin Riley         : CommandObjectParsed(interpreter, "renderscript module probe",
24635ec532a9SColin Riley                               "Initiates a Probe of all loaded modules for kernels and other renderscript objects.",
24645ec532a9SColin Riley                               "renderscript module probe",
2465e87764f2SEnrico Granata                               eCommandRequiresTarget | eCommandRequiresProcess | eCommandProcessMustBeLaunched)
24665ec532a9SColin Riley     {
24675ec532a9SColin Riley     }
24685ec532a9SColin Riley 
24695ec532a9SColin Riley     ~CommandObjectRenderScriptRuntimeModuleProbe() {}
24705ec532a9SColin Riley 
24715ec532a9SColin Riley     bool
24725ec532a9SColin Riley     DoExecute(Args &command, CommandReturnObject &result)
24735ec532a9SColin Riley     {
24745ec532a9SColin Riley         const size_t argc = command.GetArgumentCount();
24755ec532a9SColin Riley         if (argc == 0)
24765ec532a9SColin Riley         {
24775ec532a9SColin Riley             Target *target = m_exe_ctx.GetTargetPtr();
24785ec532a9SColin Riley             RenderScriptRuntime *runtime =
24795ec532a9SColin Riley                 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
24805ec532a9SColin Riley             auto module_list = target->GetImages();
24815ec532a9SColin Riley             bool new_rs_details = runtime->ProbeModules(module_list);
24825ec532a9SColin Riley             if (new_rs_details)
24835ec532a9SColin Riley             {
24845ec532a9SColin Riley                 result.AppendMessage("New renderscript modules added to runtime model.");
24855ec532a9SColin Riley             }
24865ec532a9SColin Riley             result.SetStatus(eReturnStatusSuccessFinishResult);
24875ec532a9SColin Riley             return true;
24885ec532a9SColin Riley         }
24895ec532a9SColin Riley 
24905ec532a9SColin Riley         result.AppendErrorWithFormat("'%s' takes no arguments", m_cmd_name.c_str());
24915ec532a9SColin Riley         result.SetStatus(eReturnStatusFailed);
24925ec532a9SColin Riley         return false;
24935ec532a9SColin Riley     }
24945ec532a9SColin Riley };
24955ec532a9SColin Riley 
24965ec532a9SColin Riley class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed
24975ec532a9SColin Riley {
24985ec532a9SColin Riley   private:
24995ec532a9SColin Riley   public:
25005ec532a9SColin Riley     CommandObjectRenderScriptRuntimeModuleDump(CommandInterpreter &interpreter)
25015ec532a9SColin Riley         : CommandObjectParsed(interpreter, "renderscript module dump",
25025ec532a9SColin Riley                               "Dumps renderscript specific information for all modules.", "renderscript module dump",
2503e87764f2SEnrico Granata                               eCommandRequiresProcess | eCommandProcessMustBeLaunched)
25045ec532a9SColin Riley     {
25055ec532a9SColin Riley     }
25065ec532a9SColin Riley 
25075ec532a9SColin Riley     ~CommandObjectRenderScriptRuntimeModuleDump() {}
25085ec532a9SColin Riley 
25095ec532a9SColin Riley     bool
25105ec532a9SColin Riley     DoExecute(Args &command, CommandReturnObject &result)
25115ec532a9SColin Riley     {
25125ec532a9SColin Riley         RenderScriptRuntime *runtime =
25135ec532a9SColin Riley             (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
25145ec532a9SColin Riley         runtime->DumpModules(result.GetOutputStream());
25155ec532a9SColin Riley         result.SetStatus(eReturnStatusSuccessFinishResult);
25165ec532a9SColin Riley         return true;
25175ec532a9SColin Riley     }
25185ec532a9SColin Riley };
25195ec532a9SColin Riley 
25205ec532a9SColin Riley class CommandObjectRenderScriptRuntimeModule : public CommandObjectMultiword
25215ec532a9SColin Riley {
25225ec532a9SColin Riley   private:
25235ec532a9SColin Riley   public:
25245ec532a9SColin Riley     CommandObjectRenderScriptRuntimeModule(CommandInterpreter &interpreter)
25255ec532a9SColin Riley         : CommandObjectMultiword(interpreter, "renderscript module", "Commands that deal with renderscript modules.",
25265ec532a9SColin Riley                                  NULL)
25275ec532a9SColin Riley     {
25285ec532a9SColin Riley         LoadSubCommand("probe", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleProbe(interpreter)));
25295ec532a9SColin Riley         LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleDump(interpreter)));
25305ec532a9SColin Riley     }
25315ec532a9SColin Riley 
25325ec532a9SColin Riley     ~CommandObjectRenderScriptRuntimeModule() {}
25335ec532a9SColin Riley };
25345ec532a9SColin Riley 
25354640cde1SColin Riley class CommandObjectRenderScriptRuntimeKernelList : public CommandObjectParsed
25364640cde1SColin Riley {
25374640cde1SColin Riley   private:
25384640cde1SColin Riley   public:
25394640cde1SColin Riley     CommandObjectRenderScriptRuntimeKernelList(CommandInterpreter &interpreter)
25404640cde1SColin Riley         : CommandObjectParsed(interpreter, "renderscript kernel list",
25414640cde1SColin Riley                               "Lists renderscript kernel names and associated script resources.", "renderscript kernel list",
25424640cde1SColin Riley                               eCommandRequiresProcess | eCommandProcessMustBeLaunched)
25434640cde1SColin Riley     {
25444640cde1SColin Riley     }
25454640cde1SColin Riley 
25464640cde1SColin Riley     ~CommandObjectRenderScriptRuntimeKernelList() {}
25474640cde1SColin Riley 
25484640cde1SColin Riley     bool
25494640cde1SColin Riley     DoExecute(Args &command, CommandReturnObject &result)
25504640cde1SColin Riley     {
25514640cde1SColin Riley         RenderScriptRuntime *runtime =
25524640cde1SColin Riley             (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
25534640cde1SColin Riley         runtime->DumpKernels(result.GetOutputStream());
25544640cde1SColin Riley         result.SetStatus(eReturnStatusSuccessFinishResult);
25554640cde1SColin Riley         return true;
25564640cde1SColin Riley     }
25574640cde1SColin Riley };
25584640cde1SColin Riley 
25597dc7771cSEwan Crawford class CommandObjectRenderScriptRuntimeKernelBreakpointSet : public CommandObjectParsed
25604640cde1SColin Riley {
25614640cde1SColin Riley   private:
25624640cde1SColin Riley   public:
25637dc7771cSEwan Crawford     CommandObjectRenderScriptRuntimeKernelBreakpointSet(CommandInterpreter &interpreter)
25647dc7771cSEwan Crawford         : CommandObjectParsed(interpreter, "renderscript kernel breakpoint set",
25657dc7771cSEwan Crawford                               "Sets a breakpoint on a renderscript kernel.", "renderscript kernel breakpoint set <kernel_name>",
25664640cde1SColin Riley                               eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused)
25674640cde1SColin Riley     {
25684640cde1SColin Riley     }
25694640cde1SColin Riley 
25707dc7771cSEwan Crawford     ~CommandObjectRenderScriptRuntimeKernelBreakpointSet() {}
25714640cde1SColin Riley 
25724640cde1SColin Riley     bool
25734640cde1SColin Riley     DoExecute(Args &command, CommandReturnObject &result)
25744640cde1SColin Riley     {
25754640cde1SColin Riley         const size_t argc = command.GetArgumentCount();
25764640cde1SColin Riley         if (argc == 1)
25774640cde1SColin Riley         {
25784640cde1SColin Riley             RenderScriptRuntime *runtime =
25794640cde1SColin Riley                 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
25804640cde1SColin Riley 
25814640cde1SColin Riley             Error error;
258298156583SEwan Crawford             runtime->AttemptBreakpointAtKernelName(result.GetOutputStream(), command.GetArgumentAtIndex(0),
258398156583SEwan Crawford                                                    error, m_exe_ctx.GetTargetSP());
25844640cde1SColin Riley 
25854640cde1SColin Riley             if (error.Success())
25864640cde1SColin Riley             {
25874640cde1SColin Riley                 result.AppendMessage("Breakpoint(s) created");
25884640cde1SColin Riley                 result.SetStatus(eReturnStatusSuccessFinishResult);
25894640cde1SColin Riley                 return true;
25904640cde1SColin Riley             }
25914640cde1SColin Riley             result.SetStatus(eReturnStatusFailed);
25924640cde1SColin Riley             result.AppendErrorWithFormat("Error: %s", error.AsCString());
25934640cde1SColin Riley             return false;
25944640cde1SColin Riley         }
25954640cde1SColin Riley 
25964640cde1SColin Riley         result.AppendErrorWithFormat("'%s' takes 1 argument of kernel name", m_cmd_name.c_str());
25974640cde1SColin Riley         result.SetStatus(eReturnStatusFailed);
25984640cde1SColin Riley         return false;
25994640cde1SColin Riley     }
26004640cde1SColin Riley };
26014640cde1SColin Riley 
26027dc7771cSEwan Crawford class CommandObjectRenderScriptRuntimeKernelBreakpointAll : public CommandObjectParsed
26037dc7771cSEwan Crawford {
26047dc7771cSEwan Crawford   private:
26057dc7771cSEwan Crawford   public:
26067dc7771cSEwan Crawford     CommandObjectRenderScriptRuntimeKernelBreakpointAll(CommandInterpreter &interpreter)
26077dc7771cSEwan Crawford         : CommandObjectParsed(interpreter, "renderscript kernel breakpoint all",
26087dc7771cSEwan Crawford                               "Automatically sets a breakpoint on all renderscript kernels that are or will be loaded.\n"
26097dc7771cSEwan Crawford                               "Disabling option means breakpoints will no longer be set on any kernels loaded in the future, "
26107dc7771cSEwan Crawford                               "but does not remove currently set breakpoints.",
26117dc7771cSEwan Crawford                               "renderscript kernel breakpoint all <enable/disable>",
26127dc7771cSEwan Crawford                               eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused)
26137dc7771cSEwan Crawford     {
26147dc7771cSEwan Crawford     }
26157dc7771cSEwan Crawford 
26167dc7771cSEwan Crawford     ~CommandObjectRenderScriptRuntimeKernelBreakpointAll() {}
26177dc7771cSEwan Crawford 
26187dc7771cSEwan Crawford     bool
26197dc7771cSEwan Crawford     DoExecute(Args &command, CommandReturnObject &result)
26207dc7771cSEwan Crawford     {
26217dc7771cSEwan Crawford         const size_t argc = command.GetArgumentCount();
26227dc7771cSEwan Crawford         if (argc != 1)
26237dc7771cSEwan Crawford         {
26247dc7771cSEwan Crawford             result.AppendErrorWithFormat("'%s' takes 1 argument of 'enable' or 'disable'", m_cmd_name.c_str());
26257dc7771cSEwan Crawford             result.SetStatus(eReturnStatusFailed);
26267dc7771cSEwan Crawford             return false;
26277dc7771cSEwan Crawford         }
26287dc7771cSEwan Crawford 
26297dc7771cSEwan Crawford         RenderScriptRuntime *runtime =
26307dc7771cSEwan Crawford           static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
26317dc7771cSEwan Crawford 
26327dc7771cSEwan Crawford         bool do_break = false;
26337dc7771cSEwan Crawford         const char* argument = command.GetArgumentAtIndex(0);
26347dc7771cSEwan Crawford         if (strcmp(argument, "enable") == 0)
26357dc7771cSEwan Crawford         {
26367dc7771cSEwan Crawford             do_break = true;
26377dc7771cSEwan Crawford             result.AppendMessage("Breakpoints will be set on all kernels.");
26387dc7771cSEwan Crawford         }
26397dc7771cSEwan Crawford         else if (strcmp(argument, "disable") == 0)
26407dc7771cSEwan Crawford         {
26417dc7771cSEwan Crawford             do_break = false;
26427dc7771cSEwan Crawford             result.AppendMessage("Breakpoints will not be set on any new kernels.");
26437dc7771cSEwan Crawford         }
26447dc7771cSEwan Crawford         else
26457dc7771cSEwan Crawford         {
26467dc7771cSEwan Crawford             result.AppendErrorWithFormat("Argument must be either 'enable' or 'disable'");
26477dc7771cSEwan Crawford             result.SetStatus(eReturnStatusFailed);
26487dc7771cSEwan Crawford             return false;
26497dc7771cSEwan Crawford         }
26507dc7771cSEwan Crawford 
26517dc7771cSEwan Crawford         runtime->SetBreakAllKernels(do_break, m_exe_ctx.GetTargetSP());
26527dc7771cSEwan Crawford 
26537dc7771cSEwan Crawford         result.SetStatus(eReturnStatusSuccessFinishResult);
26547dc7771cSEwan Crawford         return true;
26557dc7771cSEwan Crawford     }
26567dc7771cSEwan Crawford };
26577dc7771cSEwan Crawford 
26587dc7771cSEwan Crawford class CommandObjectRenderScriptRuntimeKernelBreakpoint : public CommandObjectMultiword
26597dc7771cSEwan Crawford {
26607dc7771cSEwan Crawford   private:
26617dc7771cSEwan Crawford   public:
26627dc7771cSEwan Crawford     CommandObjectRenderScriptRuntimeKernelBreakpoint(CommandInterpreter &interpreter)
26637dc7771cSEwan Crawford         : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that generate breakpoints on renderscript kernels.",
26647dc7771cSEwan Crawford                                  nullptr)
26657dc7771cSEwan Crawford     {
26667dc7771cSEwan Crawford         LoadSubCommand("set", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointSet(interpreter)));
26677dc7771cSEwan Crawford         LoadSubCommand("all", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointAll(interpreter)));
26687dc7771cSEwan Crawford     }
26697dc7771cSEwan Crawford 
26707dc7771cSEwan Crawford     ~CommandObjectRenderScriptRuntimeKernelBreakpoint() {}
26717dc7771cSEwan Crawford };
26727dc7771cSEwan Crawford 
26734640cde1SColin Riley class CommandObjectRenderScriptRuntimeKernel : public CommandObjectMultiword
26744640cde1SColin Riley {
26754640cde1SColin Riley   private:
26764640cde1SColin Riley   public:
26774640cde1SColin Riley     CommandObjectRenderScriptRuntimeKernel(CommandInterpreter &interpreter)
26784640cde1SColin Riley         : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that deal with renderscript kernels.",
26794640cde1SColin Riley                                  NULL)
26804640cde1SColin Riley     {
26814640cde1SColin Riley         LoadSubCommand("list", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelList(interpreter)));
26824640cde1SColin Riley         LoadSubCommand("breakpoint", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpoint(interpreter)));
26834640cde1SColin Riley     }
26844640cde1SColin Riley 
26854640cde1SColin Riley     ~CommandObjectRenderScriptRuntimeKernel() {}
26864640cde1SColin Riley };
26874640cde1SColin Riley 
26884640cde1SColin Riley class CommandObjectRenderScriptRuntimeContextDump : public CommandObjectParsed
26894640cde1SColin Riley {
26904640cde1SColin Riley   private:
26914640cde1SColin Riley   public:
26924640cde1SColin Riley     CommandObjectRenderScriptRuntimeContextDump(CommandInterpreter &interpreter)
26934640cde1SColin Riley         : CommandObjectParsed(interpreter, "renderscript context dump",
26944640cde1SColin Riley                               "Dumps renderscript context information.", "renderscript context dump",
26954640cde1SColin Riley                               eCommandRequiresProcess | eCommandProcessMustBeLaunched)
26964640cde1SColin Riley     {
26974640cde1SColin Riley     }
26984640cde1SColin Riley 
26994640cde1SColin Riley     ~CommandObjectRenderScriptRuntimeContextDump() {}
27004640cde1SColin Riley 
27014640cde1SColin Riley     bool
27024640cde1SColin Riley     DoExecute(Args &command, CommandReturnObject &result)
27034640cde1SColin Riley     {
27044640cde1SColin Riley         RenderScriptRuntime *runtime =
27054640cde1SColin Riley             (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
27064640cde1SColin Riley         runtime->DumpContexts(result.GetOutputStream());
27074640cde1SColin Riley         result.SetStatus(eReturnStatusSuccessFinishResult);
27084640cde1SColin Riley         return true;
27094640cde1SColin Riley     }
27104640cde1SColin Riley };
27114640cde1SColin Riley 
27124640cde1SColin Riley class CommandObjectRenderScriptRuntimeContext : public CommandObjectMultiword
27134640cde1SColin Riley {
27144640cde1SColin Riley   private:
27154640cde1SColin Riley   public:
27164640cde1SColin Riley     CommandObjectRenderScriptRuntimeContext(CommandInterpreter &interpreter)
27174640cde1SColin Riley         : CommandObjectMultiword(interpreter, "renderscript context", "Commands that deal with renderscript contexts.",
27184640cde1SColin Riley                                  NULL)
27194640cde1SColin Riley     {
27204640cde1SColin Riley         LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeContextDump(interpreter)));
27214640cde1SColin Riley     }
27224640cde1SColin Riley 
27234640cde1SColin Riley     ~CommandObjectRenderScriptRuntimeContext() {}
27244640cde1SColin Riley };
27254640cde1SColin Riley 
2726a0f08674SEwan Crawford 
2727a0f08674SEwan Crawford class CommandObjectRenderScriptRuntimeAllocationDump : public CommandObjectParsed
2728a0f08674SEwan Crawford {
2729a0f08674SEwan Crawford   private:
2730a0f08674SEwan Crawford   public:
2731a0f08674SEwan Crawford     CommandObjectRenderScriptRuntimeAllocationDump(CommandInterpreter &interpreter)
2732a0f08674SEwan Crawford         : CommandObjectParsed(interpreter, "renderscript allocation dump",
2733a0f08674SEwan Crawford                               "Displays the contents of a particular allocation", "renderscript allocation dump <ID>",
2734a0f08674SEwan Crawford                               eCommandRequiresProcess | eCommandProcessMustBeLaunched), m_options(interpreter)
2735a0f08674SEwan Crawford     {
2736a0f08674SEwan Crawford     }
2737a0f08674SEwan Crawford 
2738a0f08674SEwan Crawford     virtual Options*
2739a0f08674SEwan Crawford     GetOptions()
2740a0f08674SEwan Crawford     {
2741a0f08674SEwan Crawford         return &m_options;
2742a0f08674SEwan Crawford     }
2743a0f08674SEwan Crawford 
2744a0f08674SEwan Crawford     class CommandOptions : public Options
2745a0f08674SEwan Crawford     {
2746a0f08674SEwan Crawford       public:
2747a0f08674SEwan Crawford         CommandOptions(CommandInterpreter &interpreter) : Options(interpreter)
2748a0f08674SEwan Crawford         {
2749a0f08674SEwan Crawford         }
2750a0f08674SEwan Crawford 
2751a0f08674SEwan Crawford         virtual
2752a0f08674SEwan Crawford         ~CommandOptions()
2753a0f08674SEwan Crawford         {
2754a0f08674SEwan Crawford         }
2755a0f08674SEwan Crawford 
2756a0f08674SEwan Crawford         virtual Error
2757a0f08674SEwan Crawford         SetOptionValue(uint32_t option_idx, const char *option_arg)
2758a0f08674SEwan Crawford         {
2759a0f08674SEwan Crawford             Error error;
2760a0f08674SEwan Crawford             const int short_option = m_getopt_table[option_idx].val;
2761a0f08674SEwan Crawford 
2762a0f08674SEwan Crawford             switch (short_option)
2763a0f08674SEwan Crawford             {
2764a0f08674SEwan Crawford                 case 'f':
2765a0f08674SEwan Crawford                     m_outfile.SetFile(option_arg, true);
2766a0f08674SEwan Crawford                     if (m_outfile.Exists())
2767a0f08674SEwan Crawford                     {
2768a0f08674SEwan Crawford                         m_outfile.Clear();
2769a0f08674SEwan Crawford                         error.SetErrorStringWithFormat("file already exists: '%s'", option_arg);
2770a0f08674SEwan Crawford                     }
2771a0f08674SEwan Crawford                     break;
2772a0f08674SEwan Crawford                 default:
2773a0f08674SEwan Crawford                     error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
2774a0f08674SEwan Crawford                     break;
2775a0f08674SEwan Crawford             }
2776a0f08674SEwan Crawford             return error;
2777a0f08674SEwan Crawford         }
2778a0f08674SEwan Crawford 
2779a0f08674SEwan Crawford         void
2780a0f08674SEwan Crawford         OptionParsingStarting()
2781a0f08674SEwan Crawford         {
2782a0f08674SEwan Crawford             m_outfile.Clear();
2783a0f08674SEwan Crawford         }
2784a0f08674SEwan Crawford 
2785a0f08674SEwan Crawford         const OptionDefinition*
2786a0f08674SEwan Crawford         GetDefinitions()
2787a0f08674SEwan Crawford         {
2788a0f08674SEwan Crawford             return g_option_table;
2789a0f08674SEwan Crawford         }
2790a0f08674SEwan Crawford 
2791a0f08674SEwan Crawford         static OptionDefinition g_option_table[];
2792a0f08674SEwan Crawford         FileSpec m_outfile;
2793a0f08674SEwan Crawford     };
2794a0f08674SEwan Crawford 
2795a0f08674SEwan Crawford     ~CommandObjectRenderScriptRuntimeAllocationDump() {}
2796a0f08674SEwan Crawford 
2797a0f08674SEwan Crawford     bool
2798a0f08674SEwan Crawford     DoExecute(Args &command, CommandReturnObject &result)
2799a0f08674SEwan Crawford     {
2800a0f08674SEwan Crawford         const size_t argc = command.GetArgumentCount();
2801a0f08674SEwan Crawford         if (argc < 1)
2802a0f08674SEwan Crawford         {
2803a0f08674SEwan Crawford             result.AppendErrorWithFormat("'%s' takes 1 argument, an allocation ID. As well as an optional -f argument",
2804a0f08674SEwan Crawford                                          m_cmd_name.c_str());
2805a0f08674SEwan Crawford             result.SetStatus(eReturnStatusFailed);
2806a0f08674SEwan Crawford             return false;
2807a0f08674SEwan Crawford         }
2808a0f08674SEwan Crawford 
2809a0f08674SEwan Crawford         RenderScriptRuntime *runtime =
2810a0f08674SEwan Crawford           static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
2811a0f08674SEwan Crawford 
2812a0f08674SEwan Crawford         const char* id_cstr = command.GetArgumentAtIndex(0);
2813a0f08674SEwan Crawford         bool convert_complete = false;
2814a0f08674SEwan Crawford         const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete);
2815a0f08674SEwan Crawford         if (!convert_complete)
2816a0f08674SEwan Crawford         {
2817a0f08674SEwan Crawford             result.AppendErrorWithFormat("invalid allocation id argument '%s'", id_cstr);
2818a0f08674SEwan Crawford             result.SetStatus(eReturnStatusFailed);
2819a0f08674SEwan Crawford             return false;
2820a0f08674SEwan Crawford         }
2821a0f08674SEwan Crawford 
2822a0f08674SEwan Crawford         Stream* output_strm = nullptr;
2823a0f08674SEwan Crawford         StreamFile outfile_stream;
2824a0f08674SEwan Crawford         const FileSpec &outfile_spec = m_options.m_outfile; // Dump allocation to file instead
2825a0f08674SEwan Crawford         if (outfile_spec)
2826a0f08674SEwan Crawford         {
2827a0f08674SEwan Crawford             // Open output file
2828a0f08674SEwan Crawford             char path[256];
2829a0f08674SEwan Crawford             outfile_spec.GetPath(path, sizeof(path));
2830a0f08674SEwan Crawford             if (outfile_stream.GetFile().Open(path, File::eOpenOptionWrite | File::eOpenOptionCanCreate).Success())
2831a0f08674SEwan Crawford             {
2832a0f08674SEwan Crawford                 output_strm = &outfile_stream;
2833a0f08674SEwan Crawford                 result.GetOutputStream().Printf("Results written to '%s'", path);
2834a0f08674SEwan Crawford                 result.GetOutputStream().EOL();
2835a0f08674SEwan Crawford             }
2836a0f08674SEwan Crawford             else
2837a0f08674SEwan Crawford             {
2838a0f08674SEwan Crawford                 result.AppendErrorWithFormat("Couldn't open file '%s'", path);
2839a0f08674SEwan Crawford                 result.SetStatus(eReturnStatusFailed);
2840a0f08674SEwan Crawford                 return false;
2841a0f08674SEwan Crawford             }
2842a0f08674SEwan Crawford         }
2843a0f08674SEwan Crawford         else
2844a0f08674SEwan Crawford             output_strm = &result.GetOutputStream();
2845a0f08674SEwan Crawford 
2846a0f08674SEwan Crawford         assert(output_strm != nullptr);
2847a0f08674SEwan Crawford         bool success = runtime->DumpAllocation(*output_strm, m_exe_ctx.GetFramePtr(), id);
2848a0f08674SEwan Crawford 
2849a0f08674SEwan Crawford         if (success)
2850a0f08674SEwan Crawford             result.SetStatus(eReturnStatusSuccessFinishResult);
2851a0f08674SEwan Crawford         else
2852a0f08674SEwan Crawford             result.SetStatus(eReturnStatusFailed);
2853a0f08674SEwan Crawford 
2854a0f08674SEwan Crawford         return true;
2855a0f08674SEwan Crawford     }
2856a0f08674SEwan Crawford 
2857a0f08674SEwan Crawford     private:
2858a0f08674SEwan Crawford         CommandOptions m_options;
2859a0f08674SEwan Crawford };
2860a0f08674SEwan Crawford 
2861a0f08674SEwan Crawford OptionDefinition
2862a0f08674SEwan Crawford CommandObjectRenderScriptRuntimeAllocationDump::CommandOptions::g_option_table[] =
2863a0f08674SEwan Crawford {
2864a0f08674SEwan Crawford     { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFilename,
2865a0f08674SEwan Crawford       "Print results to specified file instead of command line."},
2866a0f08674SEwan Crawford     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
2867a0f08674SEwan Crawford };
2868a0f08674SEwan Crawford 
2869a0f08674SEwan Crawford 
287015f2bd95SEwan Crawford class CommandObjectRenderScriptRuntimeAllocationList : public CommandObjectParsed
287115f2bd95SEwan Crawford {
287215f2bd95SEwan Crawford   public:
287315f2bd95SEwan Crawford     CommandObjectRenderScriptRuntimeAllocationList(CommandInterpreter &interpreter)
287415f2bd95SEwan Crawford         : CommandObjectParsed(interpreter, "renderscript allocation list",
287515f2bd95SEwan Crawford                               "List renderscript allocations and their information.", "renderscript allocation list",
287615f2bd95SEwan Crawford                               eCommandRequiresProcess | eCommandProcessMustBeLaunched), m_options(interpreter)
287715f2bd95SEwan Crawford     {
287815f2bd95SEwan Crawford     }
287915f2bd95SEwan Crawford 
288015f2bd95SEwan Crawford     virtual Options*
288115f2bd95SEwan Crawford     GetOptions()
288215f2bd95SEwan Crawford     {
288315f2bd95SEwan Crawford         return &m_options;
288415f2bd95SEwan Crawford     }
288515f2bd95SEwan Crawford 
288615f2bd95SEwan Crawford     class CommandOptions : public Options
288715f2bd95SEwan Crawford     {
288815f2bd95SEwan Crawford       public:
288915f2bd95SEwan Crawford         CommandOptions(CommandInterpreter &interpreter) : Options(interpreter), m_refresh(false)
289015f2bd95SEwan Crawford         {
289115f2bd95SEwan Crawford         }
289215f2bd95SEwan Crawford 
289315f2bd95SEwan Crawford         virtual
289415f2bd95SEwan Crawford         ~CommandOptions()
289515f2bd95SEwan Crawford         {
289615f2bd95SEwan Crawford         }
289715f2bd95SEwan Crawford 
289815f2bd95SEwan Crawford         virtual Error
289915f2bd95SEwan Crawford         SetOptionValue(uint32_t option_idx, const char *option_arg)
290015f2bd95SEwan Crawford         {
290115f2bd95SEwan Crawford             Error error;
290215f2bd95SEwan Crawford             const int short_option = m_getopt_table[option_idx].val;
290315f2bd95SEwan Crawford 
290415f2bd95SEwan Crawford             switch (short_option)
290515f2bd95SEwan Crawford             {
290615f2bd95SEwan Crawford                 case 'r':
290715f2bd95SEwan Crawford                     m_refresh = true;
290815f2bd95SEwan Crawford                     break;
290915f2bd95SEwan Crawford                 default:
291015f2bd95SEwan Crawford                     error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
291115f2bd95SEwan Crawford                     break;
291215f2bd95SEwan Crawford             }
291315f2bd95SEwan Crawford             return error;
291415f2bd95SEwan Crawford         }
291515f2bd95SEwan Crawford 
291615f2bd95SEwan Crawford         void
291715f2bd95SEwan Crawford         OptionParsingStarting()
291815f2bd95SEwan Crawford         {
291915f2bd95SEwan Crawford             m_refresh = false;
292015f2bd95SEwan Crawford         }
292115f2bd95SEwan Crawford 
292215f2bd95SEwan Crawford         const OptionDefinition*
292315f2bd95SEwan Crawford         GetDefinitions()
292415f2bd95SEwan Crawford         {
292515f2bd95SEwan Crawford             return g_option_table;
292615f2bd95SEwan Crawford         }
292715f2bd95SEwan Crawford 
292815f2bd95SEwan Crawford         static OptionDefinition g_option_table[];
292915f2bd95SEwan Crawford         bool m_refresh;
293015f2bd95SEwan Crawford     };
293115f2bd95SEwan Crawford 
293215f2bd95SEwan Crawford     ~CommandObjectRenderScriptRuntimeAllocationList() {}
293315f2bd95SEwan Crawford 
293415f2bd95SEwan Crawford     bool
293515f2bd95SEwan Crawford     DoExecute(Args &command, CommandReturnObject &result)
293615f2bd95SEwan Crawford     {
293715f2bd95SEwan Crawford         RenderScriptRuntime *runtime =
293815f2bd95SEwan Crawford           static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
293915f2bd95SEwan Crawford         runtime->ListAllocations(result.GetOutputStream(), m_exe_ctx.GetFramePtr(), m_options.m_refresh);
294015f2bd95SEwan Crawford         result.SetStatus(eReturnStatusSuccessFinishResult);
294115f2bd95SEwan Crawford         return true;
294215f2bd95SEwan Crawford     }
294315f2bd95SEwan Crawford 
294415f2bd95SEwan Crawford   private:
294515f2bd95SEwan Crawford     CommandOptions m_options;
294615f2bd95SEwan Crawford };
294715f2bd95SEwan Crawford 
294815f2bd95SEwan Crawford OptionDefinition
294915f2bd95SEwan Crawford CommandObjectRenderScriptRuntimeAllocationList::CommandOptions::g_option_table[] =
295015f2bd95SEwan Crawford {
295115f2bd95SEwan Crawford     { LLDB_OPT_SET_1, false, "refresh", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
295215f2bd95SEwan Crawford       "Recompute allocation details."},
295315f2bd95SEwan Crawford     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
295415f2bd95SEwan Crawford };
295515f2bd95SEwan Crawford 
295615f2bd95SEwan Crawford 
295755232f09SEwan Crawford class CommandObjectRenderScriptRuntimeAllocationLoad : public CommandObjectParsed
295855232f09SEwan Crawford {
295955232f09SEwan Crawford   private:
296055232f09SEwan Crawford   public:
296155232f09SEwan Crawford     CommandObjectRenderScriptRuntimeAllocationLoad(CommandInterpreter &interpreter)
296255232f09SEwan Crawford         : CommandObjectParsed(interpreter, "renderscript allocation load",
296355232f09SEwan Crawford                               "Loads renderscript allocation contents from a file.", "renderscript allocation load <ID> <filename>",
296455232f09SEwan Crawford                               eCommandRequiresProcess | eCommandProcessMustBeLaunched)
296555232f09SEwan Crawford     {
296655232f09SEwan Crawford     }
296755232f09SEwan Crawford 
296855232f09SEwan Crawford     ~CommandObjectRenderScriptRuntimeAllocationLoad() {}
296955232f09SEwan Crawford 
297055232f09SEwan Crawford     bool
297155232f09SEwan Crawford     DoExecute(Args &command, CommandReturnObject &result)
297255232f09SEwan Crawford     {
297355232f09SEwan Crawford         const size_t argc = command.GetArgumentCount();
297455232f09SEwan Crawford         if (argc != 2)
297555232f09SEwan Crawford         {
297655232f09SEwan Crawford             result.AppendErrorWithFormat("'%s' takes 2 arguments, an allocation ID and filename to read from.", m_cmd_name.c_str());
297755232f09SEwan Crawford             result.SetStatus(eReturnStatusFailed);
297855232f09SEwan Crawford             return false;
297955232f09SEwan Crawford         }
298055232f09SEwan Crawford 
298155232f09SEwan Crawford         RenderScriptRuntime *runtime =
298255232f09SEwan Crawford           static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
298355232f09SEwan Crawford 
298455232f09SEwan Crawford         const char* id_cstr = command.GetArgumentAtIndex(0);
298555232f09SEwan Crawford         bool convert_complete = false;
298655232f09SEwan Crawford         const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete);
298755232f09SEwan Crawford         if (!convert_complete)
298855232f09SEwan Crawford         {
298955232f09SEwan Crawford             result.AppendErrorWithFormat ("invalid allocation id argument '%s'", id_cstr);
299055232f09SEwan Crawford             result.SetStatus (eReturnStatusFailed);
299155232f09SEwan Crawford             return false;
299255232f09SEwan Crawford         }
299355232f09SEwan Crawford 
299455232f09SEwan Crawford         const char* filename = command.GetArgumentAtIndex(1);
299555232f09SEwan Crawford         bool success = runtime->LoadAllocation(result.GetOutputStream(), id, filename, m_exe_ctx.GetFramePtr());
299655232f09SEwan Crawford 
299755232f09SEwan Crawford         if (success)
299855232f09SEwan Crawford             result.SetStatus(eReturnStatusSuccessFinishResult);
299955232f09SEwan Crawford         else
300055232f09SEwan Crawford             result.SetStatus(eReturnStatusFailed);
300155232f09SEwan Crawford 
300255232f09SEwan Crawford         return true;
300355232f09SEwan Crawford     }
300455232f09SEwan Crawford };
300555232f09SEwan Crawford 
300655232f09SEwan Crawford 
300755232f09SEwan Crawford class CommandObjectRenderScriptRuntimeAllocationSave : public CommandObjectParsed
300855232f09SEwan Crawford {
300955232f09SEwan Crawford   private:
301055232f09SEwan Crawford   public:
301155232f09SEwan Crawford     CommandObjectRenderScriptRuntimeAllocationSave(CommandInterpreter &interpreter)
301255232f09SEwan Crawford         : CommandObjectParsed(interpreter, "renderscript allocation save",
301355232f09SEwan Crawford                               "Write renderscript allocation contents to a file.", "renderscript allocation save <ID> <filename>",
301455232f09SEwan Crawford                               eCommandRequiresProcess | eCommandProcessMustBeLaunched)
301555232f09SEwan Crawford     {
301655232f09SEwan Crawford     }
301755232f09SEwan Crawford 
301855232f09SEwan Crawford     ~CommandObjectRenderScriptRuntimeAllocationSave() {}
301955232f09SEwan Crawford 
302055232f09SEwan Crawford     bool
302155232f09SEwan Crawford     DoExecute(Args &command, CommandReturnObject &result)
302255232f09SEwan Crawford     {
302355232f09SEwan Crawford         const size_t argc = command.GetArgumentCount();
302455232f09SEwan Crawford         if (argc != 2)
302555232f09SEwan Crawford         {
302655232f09SEwan Crawford             result.AppendErrorWithFormat("'%s' takes 2 arguments, an allocation ID and filename to read from.", m_cmd_name.c_str());
302755232f09SEwan Crawford             result.SetStatus(eReturnStatusFailed);
302855232f09SEwan Crawford             return false;
302955232f09SEwan Crawford         }
303055232f09SEwan Crawford 
303155232f09SEwan Crawford         RenderScriptRuntime *runtime =
303255232f09SEwan Crawford           static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
303355232f09SEwan Crawford 
303455232f09SEwan Crawford         const char* id_cstr = command.GetArgumentAtIndex(0);
303555232f09SEwan Crawford         bool convert_complete = false;
303655232f09SEwan Crawford         const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete);
303755232f09SEwan Crawford         if (!convert_complete)
303855232f09SEwan Crawford         {
303955232f09SEwan Crawford             result.AppendErrorWithFormat ("invalid allocation id argument '%s'", id_cstr);
304055232f09SEwan Crawford             result.SetStatus (eReturnStatusFailed);
304155232f09SEwan Crawford             return false;
304255232f09SEwan Crawford         }
304355232f09SEwan Crawford 
304455232f09SEwan Crawford         const char* filename = command.GetArgumentAtIndex(1);
304555232f09SEwan Crawford         bool success = runtime->SaveAllocation(result.GetOutputStream(), id, filename, m_exe_ctx.GetFramePtr());
304655232f09SEwan Crawford 
304755232f09SEwan Crawford         if (success)
304855232f09SEwan Crawford             result.SetStatus(eReturnStatusSuccessFinishResult);
304955232f09SEwan Crawford         else
305055232f09SEwan Crawford             result.SetStatus(eReturnStatusFailed);
305155232f09SEwan Crawford 
305255232f09SEwan Crawford         return true;
305355232f09SEwan Crawford     }
305455232f09SEwan Crawford };
305555232f09SEwan Crawford 
305615f2bd95SEwan Crawford class CommandObjectRenderScriptRuntimeAllocation : public CommandObjectMultiword
305715f2bd95SEwan Crawford {
305815f2bd95SEwan Crawford   private:
305915f2bd95SEwan Crawford   public:
306015f2bd95SEwan Crawford     CommandObjectRenderScriptRuntimeAllocation(CommandInterpreter &interpreter)
306115f2bd95SEwan Crawford         : CommandObjectMultiword(interpreter, "renderscript allocation", "Commands that deal with renderscript allocations.",
306215f2bd95SEwan Crawford                                  NULL)
306315f2bd95SEwan Crawford     {
306415f2bd95SEwan Crawford         LoadSubCommand("list", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationList(interpreter)));
3065a0f08674SEwan Crawford         LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationDump(interpreter)));
306655232f09SEwan Crawford         LoadSubCommand("save", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationSave(interpreter)));
306755232f09SEwan Crawford         LoadSubCommand("load", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationLoad(interpreter)));
306815f2bd95SEwan Crawford     }
306915f2bd95SEwan Crawford 
307015f2bd95SEwan Crawford     ~CommandObjectRenderScriptRuntimeAllocation() {}
307115f2bd95SEwan Crawford };
307215f2bd95SEwan Crawford 
307315f2bd95SEwan Crawford 
30744640cde1SColin Riley class CommandObjectRenderScriptRuntimeStatus : public CommandObjectParsed
30754640cde1SColin Riley {
30764640cde1SColin Riley   private:
30774640cde1SColin Riley   public:
30784640cde1SColin Riley     CommandObjectRenderScriptRuntimeStatus(CommandInterpreter &interpreter)
30794640cde1SColin Riley         : CommandObjectParsed(interpreter, "renderscript status",
30804640cde1SColin Riley                               "Displays current renderscript runtime status.", "renderscript status",
30814640cde1SColin Riley                               eCommandRequiresProcess | eCommandProcessMustBeLaunched)
30824640cde1SColin Riley     {
30834640cde1SColin Riley     }
30844640cde1SColin Riley 
30854640cde1SColin Riley     ~CommandObjectRenderScriptRuntimeStatus() {}
30864640cde1SColin Riley 
30874640cde1SColin Riley     bool
30884640cde1SColin Riley     DoExecute(Args &command, CommandReturnObject &result)
30894640cde1SColin Riley     {
30904640cde1SColin Riley         RenderScriptRuntime *runtime =
30914640cde1SColin Riley             (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
30924640cde1SColin Riley         runtime->Status(result.GetOutputStream());
30934640cde1SColin Riley         result.SetStatus(eReturnStatusSuccessFinishResult);
30944640cde1SColin Riley         return true;
30954640cde1SColin Riley     }
30964640cde1SColin Riley };
30974640cde1SColin Riley 
30985ec532a9SColin Riley class CommandObjectRenderScriptRuntime : public CommandObjectMultiword
30995ec532a9SColin Riley {
31005ec532a9SColin Riley   public:
31015ec532a9SColin Riley     CommandObjectRenderScriptRuntime(CommandInterpreter &interpreter)
31025ec532a9SColin Riley         : CommandObjectMultiword(interpreter, "renderscript", "A set of commands for operating on renderscript.",
31035ec532a9SColin Riley                                  "renderscript <subcommand> [<subcommand-options>]")
31045ec532a9SColin Riley     {
31055ec532a9SColin Riley         LoadSubCommand("module", CommandObjectSP(new CommandObjectRenderScriptRuntimeModule(interpreter)));
31064640cde1SColin Riley         LoadSubCommand("status", CommandObjectSP(new CommandObjectRenderScriptRuntimeStatus(interpreter)));
31074640cde1SColin Riley         LoadSubCommand("kernel", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernel(interpreter)));
31084640cde1SColin Riley         LoadSubCommand("context", CommandObjectSP(new CommandObjectRenderScriptRuntimeContext(interpreter)));
310915f2bd95SEwan Crawford         LoadSubCommand("allocation", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocation(interpreter)));
31105ec532a9SColin Riley     }
31115ec532a9SColin Riley 
31125ec532a9SColin Riley     ~CommandObjectRenderScriptRuntime() {}
31135ec532a9SColin Riley };
3114ef20b08fSColin Riley 
3115ef20b08fSColin Riley void
3116ef20b08fSColin Riley RenderScriptRuntime::Initiate()
31175ec532a9SColin Riley {
3118ef20b08fSColin Riley     assert(!m_initiated);
31195ec532a9SColin Riley }
3120ef20b08fSColin Riley 
3121ef20b08fSColin Riley RenderScriptRuntime::RenderScriptRuntime(Process *process)
31227dc7771cSEwan Crawford     : lldb_private::CPPLanguageRuntime(process), m_initiated(false), m_debuggerPresentFlagged(false),
31237dc7771cSEwan Crawford       m_breakAllKernels(false)
3124ef20b08fSColin Riley {
31254640cde1SColin Riley     ModulesDidLoad(process->GetTarget().GetImages());
3126ef20b08fSColin Riley }
31274640cde1SColin Riley 
31284640cde1SColin Riley lldb::CommandObjectSP
31294640cde1SColin Riley RenderScriptRuntime::GetCommandObject(lldb_private::CommandInterpreter& interpreter)
31304640cde1SColin Riley {
31314640cde1SColin Riley     static CommandObjectSP command_object;
31324640cde1SColin Riley     if(!command_object)
31334640cde1SColin Riley     {
31344640cde1SColin Riley         command_object.reset(new CommandObjectRenderScriptRuntime(interpreter));
31354640cde1SColin Riley     }
31364640cde1SColin Riley     return command_object;
31374640cde1SColin Riley }
31384640cde1SColin Riley 
313978f339d1SEwan Crawford RenderScriptRuntime::~RenderScriptRuntime() = default;
3140