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;
6124640cde1SColin Riley                 reg_ctx->ReadRegister(rArg, rVal);
6134640cde1SColin Riley                 (*data) = rVal.GetAsUInt32();
61482780287SAidan Dodds                 success = true;
6154640cde1SColin Riley             }
6164640cde1SColin Riley             else
6174640cde1SColin Riley             {
6184640cde1SColin Riley                 uint64_t sp = reg_ctx->GetSP();
6194640cde1SColin Riley                 {
6204640cde1SColin Riley                     uint32_t offset = (arg-4) * sizeof(uint32_t);
6214640cde1SColin Riley                     process->ReadMemory(sp + offset, &data, sizeof(uint32_t), error);
6224640cde1SColin Riley                     if (error.Fail())
6234640cde1SColin Riley                     {
6244640cde1SColin Riley                         if (log)
62582780287SAidan Dodds                             log->Printf ("RenderScriptRuntime:: GetArgSimple - error reading ARM stack: %s.", error.AsCString());
62682780287SAidan Dodds                     }
62782780287SAidan Dodds                     else
62882780287SAidan Dodds                     {
62982780287SAidan Dodds                         success = true;
6304640cde1SColin Riley                     }
6314640cde1SColin Riley                 }
6324640cde1SColin Riley             }
63382780287SAidan Dodds 
63482780287SAidan Dodds             break;
6354640cde1SColin Riley         }
63682780287SAidan Dodds         case llvm::Triple::ArchType::aarch64:
63782780287SAidan Dodds         {
63882780287SAidan Dodds             // arm 64 bit
63982780287SAidan Dodds             // first 8 arguments are in the registers
64082780287SAidan Dodds             if (arg < 8)
64182780287SAidan Dodds             {
64282780287SAidan Dodds                 const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg);
64382780287SAidan Dodds                 RegisterValue rVal;
64482780287SAidan Dodds                 success = reg_ctx->ReadRegister(rArg, rVal);
64582780287SAidan Dodds                 if (success)
64682780287SAidan Dodds                 {
64782780287SAidan Dodds                     *data = rVal.GetAsUInt64();
64882780287SAidan Dodds                 }
64982780287SAidan Dodds                 else
65082780287SAidan Dodds                 {
65182780287SAidan Dodds                     if (log)
65282780287SAidan Dodds                         log->Printf("RenderScriptRuntime::GetArgSimple() - AARCH64 - Error while reading the argument #%d", arg);
65382780287SAidan Dodds                 }
65482780287SAidan Dodds             }
65582780287SAidan Dodds             else
65682780287SAidan Dodds             {
65782780287SAidan Dodds                 // @TODO: need to find the argument in the stack
65882780287SAidan Dodds                 if (log)
65982780287SAidan Dodds                     log->Printf("RenderScriptRuntime::GetArgSimple - AARCH64 - FOR #ARG >= 8 NOT IMPLEMENTED YET. Argument number: %d", arg);
66082780287SAidan Dodds             }
66182780287SAidan Dodds             break;
66282780287SAidan Dodds         }
66382780287SAidan Dodds         default:
66482780287SAidan Dodds         {
66582780287SAidan Dodds             // invalid architecture
66682780287SAidan Dodds             if (log)
66782780287SAidan Dodds                 log->Printf("RenderScriptRuntime::GetArgSimple - Architecture not supported");
66882780287SAidan Dodds 
66982780287SAidan Dodds         }
67082780287SAidan Dodds     }
67182780287SAidan Dodds 
67282780287SAidan Dodds 
67382780287SAidan Dodds     return success;
6744640cde1SColin Riley }
6754640cde1SColin Riley 
6764640cde1SColin Riley void
6774640cde1SColin Riley RenderScriptRuntime::CaptureSetGlobalVar1(RuntimeHook* hook_info, ExecutionContext& context)
6784640cde1SColin Riley {
6794640cde1SColin Riley     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
6804640cde1SColin Riley 
6814640cde1SColin Riley     //Context, Script, int, data, length
6824640cde1SColin Riley 
68382780287SAidan Dodds     uint64_t rs_context_u64 = 0U;
68482780287SAidan Dodds     uint64_t rs_script_u64 = 0U;
68582780287SAidan Dodds     uint64_t rs_id_u64 = 0U;
68682780287SAidan Dodds     uint64_t rs_data_u64 = 0U;
68782780287SAidan Dodds     uint64_t rs_length_u64 = 0U;
6884640cde1SColin Riley 
68982780287SAidan Dodds     bool success =
69082780287SAidan Dodds         GetArgSimple(context, 0, &rs_context_u64) &&
69182780287SAidan Dodds         GetArgSimple(context, 1, &rs_script_u64) &&
69282780287SAidan Dodds         GetArgSimple(context, 2, &rs_id_u64) &&
69382780287SAidan Dodds         GetArgSimple(context, 3, &rs_data_u64) &&
69482780287SAidan Dodds         GetArgSimple(context, 4, &rs_length_u64);
6954640cde1SColin Riley 
69682780287SAidan Dodds     if (!success)
69782780287SAidan Dodds     {
69882780287SAidan Dodds         if (log)
69982780287SAidan Dodds             log->Printf("RenderScriptRuntime::CaptureSetGlobalVar1 - Error while reading the function parameters");
70082780287SAidan Dodds         return;
70182780287SAidan Dodds     }
7024640cde1SColin Riley 
7034640cde1SColin Riley     if (log)
7044640cde1SColin Riley     {
7054640cde1SColin Riley         log->Printf ("RenderScriptRuntime::CaptureSetGlobalVar1 - 0x%" PRIx64 ",0x%" PRIx64 " slot %" PRIu64 " = 0x%" PRIx64 ":%" PRIu64 "bytes.",
70682780287SAidan Dodds                         rs_context_u64, rs_script_u64, rs_id_u64, rs_data_u64, rs_length_u64);
7074640cde1SColin Riley 
70882780287SAidan Dodds         addr_t script_addr =  (addr_t)rs_script_u64;
7094640cde1SColin Riley         if (m_scriptMappings.find( script_addr ) != m_scriptMappings.end())
7104640cde1SColin Riley         {
7114640cde1SColin Riley             auto rsm = m_scriptMappings[script_addr];
71282780287SAidan Dodds             if (rs_id_u64 < rsm->m_globals.size())
7134640cde1SColin Riley             {
71482780287SAidan Dodds                 auto rsg = rsm->m_globals[rs_id_u64];
7154640cde1SColin Riley                 log->Printf ("RenderScriptRuntime::CaptureSetGlobalVar1 - Setting of '%s' within '%s' inferred", rsg.m_name.AsCString(),
7164640cde1SColin Riley                                 rsm->m_module->GetFileSpec().GetFilename().AsCString());
7174640cde1SColin Riley             }
7184640cde1SColin Riley         }
7194640cde1SColin Riley     }
7204640cde1SColin Riley }
7214640cde1SColin Riley 
7224640cde1SColin Riley void
7234640cde1SColin Riley RenderScriptRuntime::CaptureAllocationInit1(RuntimeHook* hook_info, ExecutionContext& context)
7244640cde1SColin Riley {
7254640cde1SColin Riley     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
7264640cde1SColin Riley 
7274640cde1SColin Riley     //Context, Alloc, bool
7284640cde1SColin Riley 
72982780287SAidan Dodds     uint64_t rs_context_u64 = 0U;
73082780287SAidan Dodds     uint64_t rs_alloc_u64 = 0U;
73182780287SAidan Dodds     uint64_t rs_forceZero_u64 = 0U;
7324640cde1SColin Riley 
73382780287SAidan Dodds     bool success =
73482780287SAidan Dodds         GetArgSimple(context, 0, &rs_context_u64) &&
73582780287SAidan Dodds         GetArgSimple(context, 1, &rs_alloc_u64) &&
73682780287SAidan Dodds         GetArgSimple(context, 2, &rs_forceZero_u64);
73782780287SAidan Dodds     if (!success) // error case
73882780287SAidan Dodds     {
73982780287SAidan Dodds         if (log)
74082780287SAidan Dodds             log->Printf("RenderScriptRuntime::CaptureAllocationInit1 - Error while reading the function parameters");
74182780287SAidan Dodds         return; // abort
74282780287SAidan Dodds     }
7434640cde1SColin Riley 
7444640cde1SColin Riley     if (log)
7454640cde1SColin Riley         log->Printf ("RenderScriptRuntime::CaptureAllocationInit1 - 0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 " .",
74682780287SAidan Dodds                         rs_context_u64, rs_alloc_u64, rs_forceZero_u64);
74778f339d1SEwan Crawford 
74878f339d1SEwan Crawford     AllocationDetails* alloc = LookUpAllocation(rs_alloc_u64, true);
74978f339d1SEwan Crawford     if (alloc)
75078f339d1SEwan Crawford         alloc->context = rs_context_u64;
7514640cde1SColin Riley }
7524640cde1SColin Riley 
7534640cde1SColin Riley void
7544640cde1SColin Riley RenderScriptRuntime::CaptureScriptInit1(RuntimeHook* hook_info, ExecutionContext& context)
7554640cde1SColin Riley {
7564640cde1SColin Riley     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
7574640cde1SColin Riley 
7584640cde1SColin Riley     //Context, Script, resname Str, cachedir Str
7594640cde1SColin Riley     Error error;
7604640cde1SColin Riley     Process* process = context.GetProcessPtr();
7614640cde1SColin Riley 
76282780287SAidan Dodds     uint64_t rs_context_u64 = 0U;
76382780287SAidan Dodds     uint64_t rs_script_u64 = 0U;
76482780287SAidan Dodds     uint64_t rs_resnameptr_u64 = 0U;
76582780287SAidan Dodds     uint64_t rs_cachedirptr_u64 = 0U;
7664640cde1SColin Riley 
7674640cde1SColin Riley     std::string resname;
7684640cde1SColin Riley     std::string cachedir;
7694640cde1SColin Riley 
77082780287SAidan Dodds     // read the function parameters
77182780287SAidan Dodds     bool success =
77282780287SAidan Dodds         GetArgSimple(context, 0, &rs_context_u64) &&
77382780287SAidan Dodds         GetArgSimple(context, 1, &rs_script_u64) &&
77482780287SAidan Dodds         GetArgSimple(context, 2, &rs_resnameptr_u64) &&
77582780287SAidan Dodds         GetArgSimple(context, 3, &rs_cachedirptr_u64);
7764640cde1SColin Riley 
77782780287SAidan Dodds     if (!success)
77882780287SAidan Dodds     {
77982780287SAidan Dodds         if (log)
78082780287SAidan Dodds             log->Printf("RenderScriptRuntime::CaptureScriptInit1 - Error while reading the function parameters");
78182780287SAidan Dodds         return;
78282780287SAidan Dodds     }
78382780287SAidan Dodds 
78482780287SAidan Dodds     process->ReadCStringFromMemory((lldb::addr_t)rs_resnameptr_u64, resname, error);
7854640cde1SColin Riley     if (error.Fail())
7864640cde1SColin Riley     {
7874640cde1SColin Riley         if (log)
7884640cde1SColin Riley             log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - error reading resname: %s.", error.AsCString());
7894640cde1SColin Riley 
7904640cde1SColin Riley     }
7914640cde1SColin Riley 
79282780287SAidan Dodds     process->ReadCStringFromMemory((lldb::addr_t)rs_cachedirptr_u64, cachedir, error);
7934640cde1SColin Riley     if (error.Fail())
7944640cde1SColin Riley     {
7954640cde1SColin Riley         if (log)
7964640cde1SColin Riley             log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - error reading cachedir: %s.", error.AsCString());
7974640cde1SColin Riley     }
7984640cde1SColin Riley 
7994640cde1SColin Riley     if (log)
8004640cde1SColin Riley         log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - 0x%" PRIx64 ",0x%" PRIx64 " => '%s' at '%s' .",
80182780287SAidan Dodds                      rs_context_u64, rs_script_u64, resname.c_str(), cachedir.c_str());
8024640cde1SColin Riley 
8034640cde1SColin Riley     if (resname.size() > 0)
8044640cde1SColin Riley     {
8054640cde1SColin Riley         StreamString strm;
8064640cde1SColin Riley         strm.Printf("librs.%s.so", resname.c_str());
8074640cde1SColin Riley 
80878f339d1SEwan Crawford         ScriptDetails* script = LookUpScript(rs_script_u64, true);
80978f339d1SEwan Crawford         if (script)
81078f339d1SEwan Crawford         {
81178f339d1SEwan Crawford             script->type = ScriptDetails::eScriptC;
81278f339d1SEwan Crawford             script->cacheDir = cachedir;
81378f339d1SEwan Crawford             script->resName = resname;
81478f339d1SEwan Crawford             script->scriptDyLib = strm.GetData();
81578f339d1SEwan Crawford             script->context = addr_t(rs_context_u64);
81678f339d1SEwan Crawford         }
8174640cde1SColin Riley 
8184640cde1SColin Riley         if (log)
8194640cde1SColin Riley             log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - '%s' tagged with context 0x%" PRIx64 " and script 0x%" PRIx64 ".",
82082780287SAidan Dodds                          strm.GetData(), rs_context_u64, rs_script_u64);
8214640cde1SColin Riley     }
8224640cde1SColin Riley     else if (log)
8234640cde1SColin Riley     {
8244640cde1SColin Riley         log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - resource name invalid, Script not tagged");
8254640cde1SColin Riley     }
8264640cde1SColin Riley 
8274640cde1SColin Riley }
8284640cde1SColin Riley 
8294640cde1SColin Riley void
8304640cde1SColin Riley RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind)
8314640cde1SColin Riley {
8324640cde1SColin Riley     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
8334640cde1SColin Riley 
8344640cde1SColin Riley     if (!module)
8354640cde1SColin Riley     {
8364640cde1SColin Riley         return;
8374640cde1SColin Riley     }
8384640cde1SColin Riley 
83982780287SAidan Dodds     Target &target = GetProcess()->GetTarget();
84082780287SAidan Dodds     llvm::Triple::ArchType targetArchType = target.GetArchitecture().GetMachine();
84182780287SAidan Dodds 
84282780287SAidan Dodds     if (targetArchType != llvm::Triple::ArchType::x86
84382780287SAidan Dodds         && targetArchType != llvm::Triple::ArchType::arm
84482780287SAidan Dodds         && targetArchType != llvm::Triple::ArchType::aarch64)
8454640cde1SColin Riley     {
8464640cde1SColin Riley         if (log)
8474640cde1SColin Riley             log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Unable to hook runtime. Only X86, ARM supported currently.");
8484640cde1SColin Riley 
8494640cde1SColin Riley         return;
8504640cde1SColin Riley     }
8514640cde1SColin Riley 
85282780287SAidan Dodds     uint32_t archByteSize = target.GetArchitecture().GetAddressByteSize();
8534640cde1SColin Riley 
8544640cde1SColin Riley     for (size_t idx = 0; idx < s_runtimeHookCount; idx++)
8554640cde1SColin Riley     {
8564640cde1SColin Riley         const HookDefn* hook_defn = &s_runtimeHookDefns[idx];
8574640cde1SColin Riley         if (hook_defn->kind != kind) {
8584640cde1SColin Riley             continue;
8594640cde1SColin Riley         }
8604640cde1SColin Riley 
86182780287SAidan Dodds         const char* symbol_name = (archByteSize == 4) ? hook_defn->symbol_name_m32 : hook_defn->symbol_name_m64;
86282780287SAidan Dodds 
86382780287SAidan Dodds         const Symbol *sym = module->FindFirstSymbolWithNameAndType(ConstString(symbol_name), eSymbolTypeCode);
86482780287SAidan Dodds         if (!sym){
86582780287SAidan Dodds             if (log){
86682780287SAidan Dodds                 log->Printf("RenderScriptRuntime::LoadRuntimeHooks - ERROR: Symbol '%s' related to the function %s not found", symbol_name, hook_defn->name);
86782780287SAidan Dodds             }
86882780287SAidan Dodds             continue;
86982780287SAidan Dodds         }
8704640cde1SColin Riley 
871358cf1eaSGreg Clayton         addr_t addr = sym->GetLoadAddress(&target);
8724640cde1SColin Riley         if (addr == LLDB_INVALID_ADDRESS)
8734640cde1SColin Riley         {
8744640cde1SColin Riley             if (log)
8754640cde1SColin Riley                 log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Unable to resolve the address of hook function '%s' with symbol '%s'.",
87682780287SAidan Dodds                              hook_defn->name, symbol_name);
8774640cde1SColin Riley             continue;
8784640cde1SColin Riley         }
87982780287SAidan Dodds         else
88082780287SAidan Dodds         {
88182780287SAidan Dodds             if (log)
88282780287SAidan Dodds                 log->Printf("RenderScriptRuntime::LoadRuntimeHooks - Function %s, address resolved at 0x%" PRIx64, hook_defn->name, addr);
88382780287SAidan Dodds         }
8844640cde1SColin Riley 
8854640cde1SColin Riley         RuntimeHookSP hook(new RuntimeHook());
8864640cde1SColin Riley         hook->address = addr;
8874640cde1SColin Riley         hook->defn = hook_defn;
8884640cde1SColin Riley         hook->bp_sp = target.CreateBreakpoint(addr, true, false);
8894640cde1SColin Riley         hook->bp_sp->SetCallback(HookCallback, hook.get(), true);
8904640cde1SColin Riley         m_runtimeHooks[addr] = hook;
8914640cde1SColin Riley         if (log)
8924640cde1SColin Riley         {
8934640cde1SColin Riley             log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Successfully hooked '%s' in '%s' version %" PRIu64 " at 0x%" PRIx64 ".",
8944640cde1SColin Riley                 hook_defn->name, module->GetFileSpec().GetFilename().AsCString(), (uint64_t)hook_defn->version, (uint64_t)addr);
8954640cde1SColin Riley         }
8964640cde1SColin Riley     }
8974640cde1SColin Riley }
8984640cde1SColin Riley 
8994640cde1SColin Riley void
9004640cde1SColin Riley RenderScriptRuntime::FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp)
9014640cde1SColin Riley {
9024640cde1SColin Riley     if (!rsmodule_sp)
9034640cde1SColin Riley         return;
9044640cde1SColin Riley 
9054640cde1SColin Riley     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
9064640cde1SColin Riley 
9074640cde1SColin Riley     const ModuleSP module = rsmodule_sp->m_module;
9084640cde1SColin Riley     const FileSpec& file = module->GetPlatformFileSpec();
9094640cde1SColin Riley 
91078f339d1SEwan Crawford     // Iterate over all of the scripts that we currently know of.
91178f339d1SEwan Crawford     // Note: We cant push or pop to m_scripts here or it may invalidate rs_script.
9124640cde1SColin Riley     for (const auto & rs_script : m_scripts)
9134640cde1SColin Riley     {
91478f339d1SEwan Crawford         // Extract the expected .so file path for this script.
91578f339d1SEwan Crawford         std::string dylib;
91678f339d1SEwan Crawford         if (!rs_script->scriptDyLib.get(dylib))
91778f339d1SEwan Crawford             continue;
91878f339d1SEwan Crawford 
91978f339d1SEwan Crawford         // Only proceed if the module that has loaded corresponds to this script.
92078f339d1SEwan Crawford         if (file.GetFilename() != ConstString(dylib.c_str()))
92178f339d1SEwan Crawford             continue;
92278f339d1SEwan Crawford 
92378f339d1SEwan Crawford         // Obtain the script address which we use as a key.
92478f339d1SEwan Crawford         lldb::addr_t script;
92578f339d1SEwan Crawford         if (!rs_script->script.get(script))
92678f339d1SEwan Crawford             continue;
92778f339d1SEwan Crawford 
92878f339d1SEwan Crawford         // If we have a script mapping for the current script.
92978f339d1SEwan Crawford         if (m_scriptMappings.find(script) != m_scriptMappings.end())
9304640cde1SColin Riley         {
93178f339d1SEwan Crawford             // if the module we have stored is different to the one we just received.
93278f339d1SEwan Crawford             if (m_scriptMappings[script] != rsmodule_sp)
9334640cde1SColin Riley             {
9344640cde1SColin Riley                 if (log)
9354640cde1SColin Riley                     log->Printf ("RenderScriptRuntime::FixupScriptDetails - Error: script %" PRIx64 " wants reassigned to new rsmodule '%s'.",
93678f339d1SEwan Crawford                                     (uint64_t)script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
9374640cde1SColin Riley             }
9384640cde1SColin Riley         }
93978f339d1SEwan Crawford         // We don't have a script mapping for the current script.
9404640cde1SColin Riley         else
9414640cde1SColin Riley         {
94278f339d1SEwan Crawford             // Obtain the script resource name.
94378f339d1SEwan Crawford             std::string resName;
94478f339d1SEwan Crawford             if (rs_script->resName.get(resName))
94578f339d1SEwan Crawford                 // Set the modules resource name.
94678f339d1SEwan Crawford                 rsmodule_sp->m_resname = resName;
94778f339d1SEwan Crawford             // Add Script/Module pair to map.
94878f339d1SEwan Crawford             m_scriptMappings[script] = rsmodule_sp;
9494640cde1SColin Riley             if (log)
9504640cde1SColin Riley                 log->Printf ("RenderScriptRuntime::FixupScriptDetails - script %" PRIx64 " associated with rsmodule '%s'.",
95178f339d1SEwan Crawford                                 (uint64_t)script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
9524640cde1SColin Riley         }
9534640cde1SColin Riley     }
9544640cde1SColin Riley }
9554640cde1SColin Riley 
95615f2bd95SEwan Crawford // Uses the Target API to evaluate the expression passed as a parameter to the function
95715f2bd95SEwan Crawford // The result of that expression is returned an unsigned 64 bit int, via the result* paramter.
95815f2bd95SEwan Crawford // Function returns true on success, and false on failure
95915f2bd95SEwan Crawford bool
96015f2bd95SEwan Crawford RenderScriptRuntime::EvalRSExpression(const char* expression, StackFrame* frame_ptr, uint64_t* result)
96115f2bd95SEwan Crawford {
96215f2bd95SEwan Crawford     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
96315f2bd95SEwan Crawford     if (log)
96415f2bd95SEwan Crawford         log->Printf("RenderScriptRuntime::EvalRSExpression(%s)", expression);
96515f2bd95SEwan Crawford 
96615f2bd95SEwan Crawford     ValueObjectSP expr_result;
96715f2bd95SEwan Crawford     // Perform the actual expression evaluation
96815f2bd95SEwan Crawford     GetProcess()->GetTarget().EvaluateExpression(expression, frame_ptr, expr_result);
96915f2bd95SEwan Crawford 
97015f2bd95SEwan Crawford     if (!expr_result)
97115f2bd95SEwan Crawford     {
97215f2bd95SEwan Crawford        if (log)
97315f2bd95SEwan Crawford            log->Printf("RenderScriptRuntime::EvalRSExpression -  Error: Couldn't evaluate expression");
97415f2bd95SEwan Crawford        return false;
97515f2bd95SEwan Crawford     }
97615f2bd95SEwan Crawford 
97715f2bd95SEwan Crawford     // The result of the expression is invalid
97815f2bd95SEwan Crawford     if (!expr_result->GetError().Success())
97915f2bd95SEwan Crawford     {
98015f2bd95SEwan Crawford         Error err = expr_result->GetError();
98115f2bd95SEwan Crawford         if (err.GetError() == UserExpression::kNoResult) // Expression returned void, so this is actually a success
98215f2bd95SEwan Crawford         {
98315f2bd95SEwan Crawford             if (log)
98415f2bd95SEwan Crawford                 log->Printf("RenderScriptRuntime::EvalRSExpression - Expression returned void");
98515f2bd95SEwan Crawford 
98615f2bd95SEwan Crawford             result = nullptr;
98715f2bd95SEwan Crawford             return true;
98815f2bd95SEwan Crawford         }
98915f2bd95SEwan Crawford 
99015f2bd95SEwan Crawford         if (log)
99115f2bd95SEwan Crawford             log->Printf("RenderScriptRuntime::EvalRSExpression - Error evaluating expression result: %s", err.AsCString());
99215f2bd95SEwan Crawford         return false;
99315f2bd95SEwan Crawford     }
99415f2bd95SEwan Crawford 
99515f2bd95SEwan Crawford     bool success = false;
99615f2bd95SEwan Crawford     *result = expr_result->GetValueAsUnsigned(0, &success); // We only read the result as an unsigned int.
99715f2bd95SEwan Crawford 
99815f2bd95SEwan Crawford     if (!success)
99915f2bd95SEwan Crawford     {
100015f2bd95SEwan Crawford        if (log)
100115f2bd95SEwan Crawford            log->Printf("RenderScriptRuntime::EvalRSExpression -  Error: Couldn't convert expression result to unsigned int");
100215f2bd95SEwan Crawford        return false;
100315f2bd95SEwan Crawford     }
100415f2bd95SEwan Crawford 
100515f2bd95SEwan Crawford     return true;
100615f2bd95SEwan Crawford }
100715f2bd95SEwan Crawford 
100815f2bd95SEwan Crawford // Used to index expression format strings
100915f2bd95SEwan Crawford enum ExpressionStrings
101015f2bd95SEwan Crawford {
101115f2bd95SEwan Crawford    eExprGetOffsetPtr = 0,
101215f2bd95SEwan Crawford    eExprAllocGetType,
101315f2bd95SEwan Crawford    eExprTypeDimX,
101415f2bd95SEwan Crawford    eExprTypeDimY,
101515f2bd95SEwan Crawford    eExprTypeDimZ,
101615f2bd95SEwan Crawford    eExprTypeElemPtr,
101715f2bd95SEwan Crawford    eExprElementType,
101815f2bd95SEwan Crawford    eExprElementKind,
101915f2bd95SEwan Crawford    eExprElementVec
102015f2bd95SEwan Crawford };
102115f2bd95SEwan Crawford 
102215f2bd95SEwan Crawford // Format strings containing the expressions we may need to evaluate.
102315f2bd95SEwan Crawford const char runtimeExpressions[][256] =
102415f2bd95SEwan Crawford {
102515f2bd95SEwan Crawford  // Mangled GetOffsetPointer(Allocation*, xoff, yoff, zoff, lod, cubemap)
102615f2bd95SEwan Crawford  "(int*)_Z12GetOffsetPtrPKN7android12renderscript10AllocationEjjjj23RsAllocationCubemapFace(0x%lx, %u, %u, %u, 0, 0)",
102715f2bd95SEwan Crawford 
102815f2bd95SEwan Crawford  // Type* rsaAllocationGetType(Context*, Allocation*)
102915f2bd95SEwan Crawford  "(void*)rsaAllocationGetType(0x%lx, 0x%lx)",
103015f2bd95SEwan Crawford 
103115f2bd95SEwan Crawford  // rsaTypeGetNativeData(Context*, Type*, void* typeData, size)
103215f2bd95SEwan Crawford  // Pack the data in the following way mHal.state.dimX; mHal.state.dimY; mHal.state.dimZ;
103315f2bd95SEwan Crawford  // mHal.state.lodCount; mHal.state.faces; mElement; into typeData
103415f2bd95SEwan Crawford  // Need to specify 32 or 64 bit for uint_t since this differs between devices
103515f2bd95SEwan Crawford  "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[0]", // X dim
103615f2bd95SEwan Crawford  "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[1]", // Y dim
103715f2bd95SEwan Crawford  "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[2]", // Z dim
103815f2bd95SEwan Crawford  "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[5]", // Element ptr
103915f2bd95SEwan Crawford 
104015f2bd95SEwan Crawford  // rsaElementGetNativeData(Context*, Element*, uint32_t* elemData,size)
104115f2bd95SEwan Crawford  // Pack mType; mKind; mNormalized; mVectorSize; NumSubElements into elemData
104215f2bd95SEwan Crawford  "uint32_t data[6]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[0]", // Type
104315f2bd95SEwan Crawford  "uint32_t data[6]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[1]", // Kind
104415f2bd95SEwan Crawford  "uint32_t data[6]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[3]"  // Vector Size
104515f2bd95SEwan Crawford };
104615f2bd95SEwan Crawford 
104715f2bd95SEwan Crawford // JITs the RS runtime for the internal data pointer of an allocation.
104815f2bd95SEwan Crawford // Is passed x,y,z coordinates for the pointer to a specific element.
104915f2bd95SEwan Crawford // Then sets the data_ptr member in Allocation with the result.
105015f2bd95SEwan Crawford // Returns true on success, false otherwise
105115f2bd95SEwan Crawford bool
105215f2bd95SEwan Crawford RenderScriptRuntime::JITDataPointer(AllocationDetails* allocation, StackFrame* frame_ptr,
105315f2bd95SEwan Crawford                                     unsigned int x, unsigned int y, unsigned int z)
105415f2bd95SEwan Crawford {
105515f2bd95SEwan Crawford     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
105615f2bd95SEwan Crawford 
105715f2bd95SEwan Crawford     if (!allocation->address.isValid())
105815f2bd95SEwan Crawford     {
105915f2bd95SEwan Crawford         if (log)
106015f2bd95SEwan Crawford             log->Printf("RenderScriptRuntime::JITDataPointer - Failed to find allocation details");
106115f2bd95SEwan Crawford         return false;
106215f2bd95SEwan Crawford     }
106315f2bd95SEwan Crawford 
106415f2bd95SEwan Crawford     const char* expr_cstr = runtimeExpressions[eExprGetOffsetPtr];
106515f2bd95SEwan Crawford     const int max_expr_size = 512; // Max expression size
106615f2bd95SEwan Crawford     char buffer[max_expr_size];
106715f2bd95SEwan Crawford 
106815f2bd95SEwan Crawford     int chars_written = snprintf(buffer, max_expr_size, expr_cstr, *allocation->address.get(), x, y, z);
106915f2bd95SEwan Crawford     if (chars_written < 0)
107015f2bd95SEwan Crawford     {
107115f2bd95SEwan Crawford         if (log)
107215f2bd95SEwan Crawford             log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()");
107315f2bd95SEwan Crawford         return false;
107415f2bd95SEwan Crawford     }
107515f2bd95SEwan Crawford     else if (chars_written >= max_expr_size)
107615f2bd95SEwan Crawford     {
107715f2bd95SEwan Crawford         if (log)
107815f2bd95SEwan Crawford             log->Printf("RenderScriptRuntime::JITDataPointer - Expression too long");
107915f2bd95SEwan Crawford         return false;
108015f2bd95SEwan Crawford     }
108115f2bd95SEwan Crawford 
108215f2bd95SEwan Crawford     uint64_t result = 0;
108315f2bd95SEwan Crawford     if (!EvalRSExpression(buffer, frame_ptr, &result))
108415f2bd95SEwan Crawford         return false;
108515f2bd95SEwan Crawford 
108615f2bd95SEwan Crawford     addr_t mem_ptr = static_cast<lldb::addr_t>(result);
108715f2bd95SEwan Crawford     allocation->data_ptr = mem_ptr;
108815f2bd95SEwan Crawford 
108915f2bd95SEwan Crawford     return true;
109015f2bd95SEwan Crawford }
109115f2bd95SEwan Crawford 
109215f2bd95SEwan Crawford // JITs the RS runtime for the internal pointer to the RS Type of an allocation
109315f2bd95SEwan Crawford // Then sets the type_ptr member in Allocation with the result.
109415f2bd95SEwan Crawford // Returns true on success, false otherwise
109515f2bd95SEwan Crawford bool
109615f2bd95SEwan Crawford RenderScriptRuntime::JITTypePointer(AllocationDetails* allocation, StackFrame* frame_ptr)
109715f2bd95SEwan Crawford {
109815f2bd95SEwan Crawford     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
109915f2bd95SEwan Crawford 
110015f2bd95SEwan Crawford     if (!allocation->address.isValid() || !allocation->context.isValid())
110115f2bd95SEwan Crawford     {
110215f2bd95SEwan Crawford         if (log)
110315f2bd95SEwan Crawford             log->Printf("RenderScriptRuntime::JITTypePointer - Failed to find allocation details");
110415f2bd95SEwan Crawford         return false;
110515f2bd95SEwan Crawford     }
110615f2bd95SEwan Crawford 
110715f2bd95SEwan Crawford     const char* expr_cstr = runtimeExpressions[eExprAllocGetType];
110815f2bd95SEwan Crawford     const int max_expr_size = 512; // Max expression size
110915f2bd95SEwan Crawford     char buffer[max_expr_size];
111015f2bd95SEwan Crawford 
111115f2bd95SEwan Crawford     int chars_written = snprintf(buffer, max_expr_size, expr_cstr, *allocation->context.get(), *allocation->address.get());
111215f2bd95SEwan Crawford     if (chars_written < 0)
111315f2bd95SEwan Crawford     {
111415f2bd95SEwan Crawford         if (log)
111515f2bd95SEwan Crawford             log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()");
111615f2bd95SEwan Crawford         return false;
111715f2bd95SEwan Crawford     }
111815f2bd95SEwan Crawford     else if (chars_written >= max_expr_size)
111915f2bd95SEwan Crawford     {
112015f2bd95SEwan Crawford         if (log)
112115f2bd95SEwan Crawford             log->Printf("RenderScriptRuntime::JITTypePointer - Expression too long");
112215f2bd95SEwan Crawford         return false;
112315f2bd95SEwan Crawford     }
112415f2bd95SEwan Crawford 
112515f2bd95SEwan Crawford     uint64_t result = 0;
112615f2bd95SEwan Crawford     if (!EvalRSExpression(buffer, frame_ptr, &result))
112715f2bd95SEwan Crawford         return false;
112815f2bd95SEwan Crawford 
112915f2bd95SEwan Crawford     addr_t type_ptr = static_cast<lldb::addr_t>(result);
113015f2bd95SEwan Crawford     allocation->type_ptr = type_ptr;
113115f2bd95SEwan Crawford 
113215f2bd95SEwan Crawford     return true;
113315f2bd95SEwan Crawford }
113415f2bd95SEwan Crawford 
113515f2bd95SEwan Crawford // JITs the RS runtime for information about the dimensions and type of an allocation
113615f2bd95SEwan Crawford // Then sets dimension and element_ptr members in Allocation with the result.
113715f2bd95SEwan Crawford // Returns true on success, false otherwise
113815f2bd95SEwan Crawford bool
113915f2bd95SEwan Crawford RenderScriptRuntime::JITTypePacked(AllocationDetails* allocation, StackFrame* frame_ptr)
114015f2bd95SEwan Crawford {
114115f2bd95SEwan Crawford     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
114215f2bd95SEwan Crawford 
114315f2bd95SEwan Crawford     if (!allocation->type_ptr.isValid() || !allocation->context.isValid())
114415f2bd95SEwan Crawford     {
114515f2bd95SEwan Crawford         if (log)
114615f2bd95SEwan Crawford             log->Printf("RenderScriptRuntime::JITTypePacked - Failed to find allocation details");
114715f2bd95SEwan Crawford         return false;
114815f2bd95SEwan Crawford     }
114915f2bd95SEwan Crawford 
115015f2bd95SEwan Crawford     // Expression is different depending on if device is 32 or 64 bit
115115f2bd95SEwan Crawford     uint32_t archByteSize = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
115215f2bd95SEwan Crawford     const unsigned int bits = archByteSize == 4 ? 32 : 64;
115315f2bd95SEwan Crawford 
115415f2bd95SEwan Crawford     // We want 4 elements from packed data
115515f2bd95SEwan Crawford     const unsigned int num_exprs = 4;
115615f2bd95SEwan Crawford     assert(num_exprs == (eExprTypeElemPtr - eExprTypeDimX + 1) && "Invalid number of expressions");
115715f2bd95SEwan Crawford 
115815f2bd95SEwan Crawford     const int max_expr_size = 512; // Max expression size
115915f2bd95SEwan Crawford     char buffer[num_exprs][max_expr_size];
116015f2bd95SEwan Crawford     uint64_t results[num_exprs];
116115f2bd95SEwan Crawford 
116215f2bd95SEwan Crawford     for (unsigned int i = 0; i < num_exprs; ++i)
116315f2bd95SEwan Crawford     {
116415f2bd95SEwan Crawford         int chars_written = snprintf(buffer[i], max_expr_size, runtimeExpressions[eExprTypeDimX + i], bits,
116515f2bd95SEwan Crawford                                      *allocation->context.get(), *allocation->type_ptr.get());
116615f2bd95SEwan Crawford         if (chars_written < 0)
116715f2bd95SEwan Crawford         {
116815f2bd95SEwan Crawford             if (log)
116915f2bd95SEwan Crawford                 log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()");
117015f2bd95SEwan Crawford             return false;
117115f2bd95SEwan Crawford         }
117215f2bd95SEwan Crawford         else if (chars_written >= max_expr_size)
117315f2bd95SEwan Crawford         {
117415f2bd95SEwan Crawford             if (log)
117515f2bd95SEwan Crawford                 log->Printf("RenderScriptRuntime::JITTypePacked - Expression too long");
117615f2bd95SEwan Crawford             return false;
117715f2bd95SEwan Crawford         }
117815f2bd95SEwan Crawford 
117915f2bd95SEwan Crawford         // Perform expression evaluation
118015f2bd95SEwan Crawford         if (!EvalRSExpression(buffer[i], frame_ptr, &results[i]))
118115f2bd95SEwan Crawford             return false;
118215f2bd95SEwan Crawford     }
118315f2bd95SEwan Crawford 
118415f2bd95SEwan Crawford     // Assign results to allocation members
118515f2bd95SEwan Crawford     AllocationDetails::Dimension dims;
118615f2bd95SEwan Crawford     dims.dim_1 = static_cast<uint32_t>(results[0]);
118715f2bd95SEwan Crawford     dims.dim_2 = static_cast<uint32_t>(results[1]);
118815f2bd95SEwan Crawford     dims.dim_3 = static_cast<uint32_t>(results[2]);
118915f2bd95SEwan Crawford     allocation->dimension = dims;
119015f2bd95SEwan Crawford 
119115f2bd95SEwan Crawford     addr_t elem_ptr = static_cast<lldb::addr_t>(results[3]);
119215f2bd95SEwan Crawford     allocation->element_ptr = elem_ptr;
119315f2bd95SEwan Crawford 
119415f2bd95SEwan Crawford     if (log)
119515f2bd95SEwan Crawford         log->Printf("RenderScriptRuntime::JITTypePacked - dims (%u, %u, %u) Element*: 0x%" PRIx64,
119615f2bd95SEwan Crawford                     dims.dim_1, dims.dim_2, dims.dim_3, elem_ptr);
119715f2bd95SEwan Crawford 
119815f2bd95SEwan Crawford     return true;
119915f2bd95SEwan Crawford }
120015f2bd95SEwan Crawford 
120115f2bd95SEwan Crawford // JITs the RS runtime for information about the Element of an allocation
120215f2bd95SEwan Crawford // Then sets type, type_vec_size, and type_kind members in Allocation with the result.
120315f2bd95SEwan Crawford // Returns true on success, false otherwise
120415f2bd95SEwan Crawford bool
120515f2bd95SEwan Crawford RenderScriptRuntime::JITElementPacked(AllocationDetails* allocation, StackFrame* frame_ptr)
120615f2bd95SEwan Crawford {
120715f2bd95SEwan Crawford     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
120815f2bd95SEwan Crawford 
120915f2bd95SEwan Crawford     if (!allocation->element_ptr.isValid() || !allocation->context.isValid())
121015f2bd95SEwan Crawford     {
121115f2bd95SEwan Crawford         if (log)
121215f2bd95SEwan Crawford             log->Printf("RenderScriptRuntime::JITElementPacked - Failed to find allocation details");
121315f2bd95SEwan Crawford         return false;
121415f2bd95SEwan Crawford     }
121515f2bd95SEwan Crawford 
121615f2bd95SEwan Crawford     // We want 3 elements from packed data
121715f2bd95SEwan Crawford     const unsigned int num_exprs = 3;
121815f2bd95SEwan Crawford     assert(num_exprs == (eExprElementVec - eExprElementType + 1) && "Invalid number of expressions");
121915f2bd95SEwan Crawford 
122015f2bd95SEwan Crawford     const int max_expr_size = 512; // Max expression size
122115f2bd95SEwan Crawford     char buffer[num_exprs][max_expr_size];
122215f2bd95SEwan Crawford     uint64_t results[num_exprs];
122315f2bd95SEwan Crawford 
122415f2bd95SEwan Crawford     for (unsigned int i = 0; i < num_exprs; i++)
122515f2bd95SEwan Crawford     {
122615f2bd95SEwan Crawford         int chars_written = snprintf(buffer[i], max_expr_size, runtimeExpressions[eExprElementType + i], *allocation->context.get(), *allocation->element_ptr.get());
122715f2bd95SEwan Crawford         if (chars_written < 0)
122815f2bd95SEwan Crawford         {
122915f2bd95SEwan Crawford             if (log)
123015f2bd95SEwan Crawford                 log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()");
123115f2bd95SEwan Crawford             return false;
123215f2bd95SEwan Crawford         }
123315f2bd95SEwan Crawford         else if (chars_written >= max_expr_size)
123415f2bd95SEwan Crawford         {
123515f2bd95SEwan Crawford             if (log)
123615f2bd95SEwan Crawford                 log->Printf("RenderScriptRuntime::JITElementPacked - Expression too long");
123715f2bd95SEwan Crawford             return false;
123815f2bd95SEwan Crawford         }
123915f2bd95SEwan Crawford 
124015f2bd95SEwan Crawford         // Perform expression evaluation
124115f2bd95SEwan Crawford         if (!EvalRSExpression(buffer[i], frame_ptr, &results[i]))
124215f2bd95SEwan Crawford             return false;
124315f2bd95SEwan Crawford     }
124415f2bd95SEwan Crawford 
124515f2bd95SEwan Crawford     // Assign results to allocation members
124615f2bd95SEwan Crawford     allocation->type = static_cast<RenderScriptRuntime::AllocationDetails::DataType>(results[0]);
124715f2bd95SEwan Crawford     allocation->type_kind = static_cast<RenderScriptRuntime::AllocationDetails::DataKind>(results[1]);
124815f2bd95SEwan Crawford     allocation->type_vec_size = static_cast<uint32_t>(results[2]);
124915f2bd95SEwan Crawford 
125015f2bd95SEwan Crawford     if (log)
125115f2bd95SEwan Crawford         log->Printf("RenderScriptRuntime::JITElementPacked - data type %u, pixel type %u, vector size %u",
125215f2bd95SEwan Crawford                     *allocation->type.get(), *allocation->type_kind.get(), *allocation->type_vec_size.get());
125315f2bd95SEwan Crawford 
125415f2bd95SEwan Crawford     return true;
125515f2bd95SEwan Crawford }
125615f2bd95SEwan Crawford 
1257a0f08674SEwan Crawford // JITs the RS runtime for the address of the last element in the allocation.
1258a0f08674SEwan Crawford // The `elem_size` paramter represents the size of a single element, including padding.
1259a0f08674SEwan Crawford // Which is needed as an offset from the last element pointer.
1260a0f08674SEwan Crawford // Using this offset minus the starting address we can calculate the size of the allocation.
1261a0f08674SEwan Crawford // Returns true on success, false otherwise
1262a0f08674SEwan Crawford bool
1263a0f08674SEwan Crawford RenderScriptRuntime::JITAllocationSize(AllocationDetails* allocation, StackFrame* frame_ptr,
1264a0f08674SEwan Crawford                                        const uint32_t elem_size)
1265a0f08674SEwan Crawford {
1266a0f08674SEwan Crawford     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1267a0f08674SEwan Crawford 
1268a0f08674SEwan Crawford     if (!allocation->address.isValid() || !allocation->dimension.isValid()
1269a0f08674SEwan Crawford         || !allocation->data_ptr.isValid())
1270a0f08674SEwan Crawford     {
1271a0f08674SEwan Crawford         if (log)
1272a0f08674SEwan Crawford             log->Printf("RenderScriptRuntime::JITAllocationSize - Failed to find allocation details");
1273a0f08674SEwan Crawford         return false;
1274a0f08674SEwan Crawford     }
1275a0f08674SEwan Crawford 
1276a0f08674SEwan Crawford     const char* expr_cstr = runtimeExpressions[eExprGetOffsetPtr];
1277a0f08674SEwan Crawford     const int max_expr_size = 512; // Max expression size
1278a0f08674SEwan Crawford     char buffer[max_expr_size];
1279a0f08674SEwan Crawford 
1280a0f08674SEwan Crawford     // Find dimensions
1281a0f08674SEwan Crawford     unsigned int dim_x = allocation->dimension.get()->dim_1;
1282a0f08674SEwan Crawford     unsigned int dim_y = allocation->dimension.get()->dim_2;
1283a0f08674SEwan Crawford     unsigned int dim_z = allocation->dimension.get()->dim_3;
1284a0f08674SEwan Crawford 
1285a0f08674SEwan Crawford     // Calculate last element
1286a0f08674SEwan Crawford     dim_x = dim_x == 0 ? 0 : dim_x - 1;
1287a0f08674SEwan Crawford     dim_y = dim_y == 0 ? 0 : dim_y - 1;
1288a0f08674SEwan Crawford     dim_z = dim_z == 0 ? 0 : dim_z - 1;
1289a0f08674SEwan Crawford 
1290a0f08674SEwan Crawford     int chars_written = snprintf(buffer, max_expr_size, expr_cstr, *allocation->address.get(),
1291a0f08674SEwan Crawford                                  dim_x, dim_y, dim_z);
1292a0f08674SEwan Crawford     if (chars_written < 0)
1293a0f08674SEwan Crawford     {
1294a0f08674SEwan Crawford         if (log)
1295a0f08674SEwan Crawford             log->Printf("RenderScriptRuntime::JITAllocationSize - Encoding error in snprintf()");
1296a0f08674SEwan Crawford         return false;
1297a0f08674SEwan Crawford     }
1298a0f08674SEwan Crawford     else if (chars_written >= max_expr_size)
1299a0f08674SEwan Crawford     {
1300a0f08674SEwan Crawford         if (log)
1301a0f08674SEwan Crawford             log->Printf("RenderScriptRuntime::JITAllocationSize - Expression too long");
1302a0f08674SEwan Crawford         return false;
1303a0f08674SEwan Crawford     }
1304a0f08674SEwan Crawford 
1305a0f08674SEwan Crawford     uint64_t result = 0;
1306a0f08674SEwan Crawford     if (!EvalRSExpression(buffer, frame_ptr, &result))
1307a0f08674SEwan Crawford         return false;
1308a0f08674SEwan Crawford 
1309a0f08674SEwan Crawford     addr_t mem_ptr = static_cast<lldb::addr_t>(result);
1310a0f08674SEwan Crawford     // Find pointer to last element and add on size of an element
1311a0f08674SEwan Crawford     allocation->size = static_cast<uint32_t>(mem_ptr - *allocation->data_ptr.get()) + elem_size;
1312a0f08674SEwan Crawford 
1313a0f08674SEwan Crawford     return true;
1314a0f08674SEwan Crawford }
1315a0f08674SEwan Crawford 
1316a0f08674SEwan Crawford // JITs the RS runtime for information about the stride between rows in the allocation.
1317a0f08674SEwan Crawford // This is done to detect padding, since allocated memory is 16-byte aligned.
1318a0f08674SEwan Crawford // Returns true on success, false otherwise
1319a0f08674SEwan Crawford bool
1320a0f08674SEwan Crawford RenderScriptRuntime::JITAllocationStride(AllocationDetails* allocation, StackFrame* frame_ptr)
1321a0f08674SEwan Crawford {
1322a0f08674SEwan Crawford     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1323a0f08674SEwan Crawford 
1324a0f08674SEwan Crawford     if (!allocation->address.isValid() || !allocation->data_ptr.isValid())
1325a0f08674SEwan Crawford     {
1326a0f08674SEwan Crawford         if (log)
1327a0f08674SEwan Crawford             log->Printf("RenderScriptRuntime::JITAllocationStride - Failed to find allocation details");
1328a0f08674SEwan Crawford         return false;
1329a0f08674SEwan Crawford     }
1330a0f08674SEwan Crawford 
1331a0f08674SEwan Crawford     const char* expr_cstr = runtimeExpressions[eExprGetOffsetPtr];
1332a0f08674SEwan Crawford     const int max_expr_size = 512; // Max expression size
1333a0f08674SEwan Crawford     char buffer[max_expr_size];
1334a0f08674SEwan Crawford 
1335a0f08674SEwan Crawford     int chars_written = snprintf(buffer, max_expr_size, expr_cstr, *allocation->address.get(),
1336a0f08674SEwan Crawford                                  0, 1, 0);
1337a0f08674SEwan Crawford     if (chars_written < 0)
1338a0f08674SEwan Crawford     {
1339a0f08674SEwan Crawford         if (log)
1340a0f08674SEwan Crawford             log->Printf("RenderScriptRuntime::JITAllocationStride - 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::JITAllocationStride - 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     allocation->stride = static_cast<uint32_t>(mem_ptr - *allocation->data_ptr.get());
1356a0f08674SEwan Crawford 
1357a0f08674SEwan Crawford     return true;
1358a0f08674SEwan Crawford }
1359a0f08674SEwan Crawford 
136015f2bd95SEwan Crawford // JIT all the current runtime info regarding an allocation
136115f2bd95SEwan Crawford bool
136215f2bd95SEwan Crawford RenderScriptRuntime::RefreshAllocation(AllocationDetails* allocation, StackFrame* frame_ptr)
136315f2bd95SEwan Crawford {
136415f2bd95SEwan Crawford     // GetOffsetPointer()
136515f2bd95SEwan Crawford     if (!JITDataPointer(allocation, frame_ptr))
136615f2bd95SEwan Crawford         return false;
136715f2bd95SEwan Crawford 
136815f2bd95SEwan Crawford     // rsaAllocationGetType()
136915f2bd95SEwan Crawford     if (!JITTypePointer(allocation, frame_ptr))
137015f2bd95SEwan Crawford         return false;
137115f2bd95SEwan Crawford 
137215f2bd95SEwan Crawford     // rsaTypeGetNativeData()
137315f2bd95SEwan Crawford     if (!JITTypePacked(allocation, frame_ptr))
137415f2bd95SEwan Crawford         return false;
137515f2bd95SEwan Crawford 
137615f2bd95SEwan Crawford     // rsaElementGetNativeData()
137715f2bd95SEwan Crawford     if (!JITElementPacked(allocation, frame_ptr))
137815f2bd95SEwan Crawford         return false;
137915f2bd95SEwan Crawford 
138055232f09SEwan Crawford     // Use GetOffsetPointer() to infer size of the allocation
138155232f09SEwan Crawford     const unsigned int element_size = GetElementSize(allocation);
138255232f09SEwan Crawford     if (!JITAllocationSize(allocation, frame_ptr, element_size))
138355232f09SEwan Crawford         return false;
138455232f09SEwan Crawford 
138555232f09SEwan Crawford     return true;
138655232f09SEwan Crawford }
138755232f09SEwan Crawford 
138855232f09SEwan Crawford // Returns the size of a single allocation element including padding.
138955232f09SEwan Crawford // Assumes the relevant allocation information has already been jitted.
139055232f09SEwan Crawford unsigned int
139155232f09SEwan Crawford RenderScriptRuntime::GetElementSize(const AllocationDetails* allocation)
139255232f09SEwan Crawford {
139355232f09SEwan Crawford     const AllocationDetails::DataType type = *allocation->type.get();
139455232f09SEwan Crawford     assert(type >= AllocationDetails::RS_TYPE_NONE && type <= AllocationDetails::RS_TYPE_BOOLEAN
139555232f09SEwan Crawford                                                    && "Invalid allocation type");
139655232f09SEwan Crawford 
139755232f09SEwan Crawford     const unsigned int vec_size = *allocation->type_vec_size.get();
139855232f09SEwan Crawford     const unsigned int data_size = vec_size * AllocationDetails::RSTypeToFormat[type][eElementSize];
139955232f09SEwan Crawford     const unsigned int padding = vec_size == 3 ? AllocationDetails::RSTypeToFormat[type][eElementSize] : 0;
140055232f09SEwan Crawford 
140155232f09SEwan Crawford     return data_size + padding;
140255232f09SEwan Crawford }
140355232f09SEwan Crawford 
140455232f09SEwan Crawford // Given an allocation, this function copies the allocation contents from device into a buffer on the heap.
140555232f09SEwan Crawford // Returning a shared pointer to the buffer containing the data.
140655232f09SEwan Crawford std::shared_ptr<uint8_t>
140755232f09SEwan Crawford RenderScriptRuntime::GetAllocationData(AllocationDetails* allocation, StackFrame* frame_ptr)
140855232f09SEwan Crawford {
140955232f09SEwan Crawford     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
141055232f09SEwan Crawford 
141155232f09SEwan Crawford     // JIT all the allocation details
141255232f09SEwan Crawford     if (!allocation->data_ptr.isValid() || !allocation->type.isValid() || !allocation->type_vec_size.isValid()
141355232f09SEwan Crawford         || !allocation->size.isValid())
141455232f09SEwan Crawford     {
141555232f09SEwan Crawford         if (log)
141655232f09SEwan Crawford             log->Printf("RenderScriptRuntime::GetAllocationData - Allocation details not calculated yet, jitting info");
141755232f09SEwan Crawford 
141855232f09SEwan Crawford         if (!RefreshAllocation(allocation, frame_ptr))
141955232f09SEwan Crawford         {
142055232f09SEwan Crawford             if (log)
142155232f09SEwan Crawford                 log->Printf("RenderScriptRuntime::GetAllocationData - Couldn't JIT allocation details");
142255232f09SEwan Crawford             return nullptr;
142355232f09SEwan Crawford         }
142455232f09SEwan Crawford     }
142555232f09SEwan Crawford 
142655232f09SEwan Crawford     assert(allocation->data_ptr.isValid() && allocation->type.isValid() && allocation->type_vec_size.isValid()
142755232f09SEwan Crawford            && allocation->size.isValid() && "Allocation information not available");
142855232f09SEwan Crawford 
142955232f09SEwan Crawford     // Allocate a buffer to copy data into
143055232f09SEwan Crawford     const unsigned int size = *allocation->size.get();
143155232f09SEwan Crawford     std::shared_ptr<uint8_t> buffer(new uint8_t[size]);
143255232f09SEwan Crawford     if (!buffer)
143355232f09SEwan Crawford     {
143455232f09SEwan Crawford         if (log)
143555232f09SEwan Crawford             log->Printf("RenderScriptRuntime::GetAllocationData - Couldn't allocate a %u byte buffer", size);
143655232f09SEwan Crawford         return nullptr;
143755232f09SEwan Crawford     }
143855232f09SEwan Crawford 
143955232f09SEwan Crawford     // Read the inferior memory
144055232f09SEwan Crawford     Error error;
144155232f09SEwan Crawford     lldb::addr_t data_ptr = *allocation->data_ptr.get();
144255232f09SEwan Crawford     GetProcess()->ReadMemory(data_ptr, buffer.get(), size, error);
144355232f09SEwan Crawford     if (error.Fail())
144455232f09SEwan Crawford     {
144555232f09SEwan Crawford         if (log)
144655232f09SEwan Crawford             log->Printf("RenderScriptRuntime::GetAllocationData - '%s' Couldn't read %u bytes of allocation data from 0x%" PRIx64,
144755232f09SEwan Crawford                         error.AsCString(), size, data_ptr);
144855232f09SEwan Crawford         return nullptr;
144955232f09SEwan Crawford     }
145055232f09SEwan Crawford 
145155232f09SEwan Crawford     return buffer;
145255232f09SEwan Crawford }
145355232f09SEwan Crawford 
145455232f09SEwan Crawford // Function copies data from a binary file into an allocation.
145555232f09SEwan Crawford // There is a header at the start of the file, FileHeader, before the data content itself.
145655232f09SEwan Crawford // Information from this header is used to display warnings to the user about incompatabilities
145755232f09SEwan Crawford bool
145855232f09SEwan Crawford RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id, const char* filename, StackFrame* frame_ptr)
145955232f09SEwan Crawford {
146055232f09SEwan Crawford     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
146155232f09SEwan Crawford 
146255232f09SEwan Crawford     // Find allocation with the given id
146355232f09SEwan Crawford     AllocationDetails* alloc = FindAllocByID(strm, alloc_id);
146455232f09SEwan Crawford     if (!alloc)
146555232f09SEwan Crawford         return false;
146655232f09SEwan Crawford 
146755232f09SEwan Crawford     if (log)
146855232f09SEwan Crawford         log->Printf("RenderScriptRuntime::LoadAllocation - Found allocation 0x%" PRIx64, *alloc->address.get());
146955232f09SEwan Crawford 
147055232f09SEwan Crawford     // JIT all the allocation details
147155232f09SEwan Crawford     if (!alloc->data_ptr.isValid() || !alloc->type.isValid() || !alloc->type_vec_size.isValid() || !alloc->size.isValid())
147255232f09SEwan Crawford     {
147355232f09SEwan Crawford         if (log)
147455232f09SEwan Crawford             log->Printf("RenderScriptRuntime::LoadAllocation - Allocation details not calculated yet, jitting info");
147555232f09SEwan Crawford 
147655232f09SEwan Crawford         if (!RefreshAllocation(alloc, frame_ptr))
147755232f09SEwan Crawford         {
147855232f09SEwan Crawford             if (log)
147955232f09SEwan Crawford                 log->Printf("RenderScriptRuntime::LoadAllocation - Couldn't JIT allocation details");
148055232f09SEwan Crawford             return nullptr;
148155232f09SEwan Crawford         }
148255232f09SEwan Crawford     }
148355232f09SEwan Crawford 
148455232f09SEwan Crawford     assert(alloc->data_ptr.isValid() && alloc->type.isValid() && alloc->type_vec_size.isValid() && alloc->size.isValid()
148555232f09SEwan Crawford            && "Allocation information not available");
148655232f09SEwan Crawford 
148755232f09SEwan Crawford     // Check we can read from file
148855232f09SEwan Crawford     FileSpec file(filename, true);
148955232f09SEwan Crawford     if (!file.Exists())
149055232f09SEwan Crawford     {
149155232f09SEwan Crawford         strm.Printf("Error: File %s does not exist", filename);
149255232f09SEwan Crawford         strm.EOL();
149355232f09SEwan Crawford         return false;
149455232f09SEwan Crawford     }
149555232f09SEwan Crawford 
149655232f09SEwan Crawford     if (!file.Readable())
149755232f09SEwan Crawford     {
149855232f09SEwan Crawford         strm.Printf("Error: File %s does not have readable permissions", filename);
149955232f09SEwan Crawford         strm.EOL();
150055232f09SEwan Crawford         return false;
150155232f09SEwan Crawford     }
150255232f09SEwan Crawford 
150355232f09SEwan Crawford     // Read file into data buffer
150455232f09SEwan Crawford     DataBufferSP data_sp(file.ReadFileContents());
150555232f09SEwan Crawford 
150655232f09SEwan Crawford     // Cast start of buffer to FileHeader and use pointer to read metadata
150755232f09SEwan Crawford     void* file_buffer = data_sp->GetBytes();
150855232f09SEwan Crawford     const AllocationDetails::FileHeader* head = static_cast<AllocationDetails::FileHeader*>(file_buffer);
150955232f09SEwan Crawford 
151055232f09SEwan Crawford     // Advance buffer past header
151155232f09SEwan Crawford     file_buffer = static_cast<uint8_t*>(file_buffer) + head->hdr_size;
151255232f09SEwan Crawford 
151355232f09SEwan Crawford     if (log)
151455232f09SEwan Crawford         log->Printf("RenderScriptRuntime::LoadAllocation - header type %u, element size %u",
151555232f09SEwan Crawford                     head->type, head->element_size);
151655232f09SEwan Crawford 
151755232f09SEwan Crawford     // Check if the target allocation and file both have the same number of bytes for an Element
151855232f09SEwan Crawford     const unsigned int elem_size = GetElementSize(alloc);
151955232f09SEwan Crawford     if (elem_size != head->element_size)
152055232f09SEwan Crawford     {
152155232f09SEwan Crawford         strm.Printf("Warning: Mismatched Element sizes - file %u bytes, allocation %u bytes",
152255232f09SEwan Crawford                     head->element_size, elem_size);
152355232f09SEwan Crawford         strm.EOL();
152455232f09SEwan Crawford     }
152555232f09SEwan Crawford 
152655232f09SEwan Crawford     // Check if the target allocation and file both have the same integral type
152755232f09SEwan Crawford     const unsigned int type = static_cast<unsigned int>(*alloc->type.get());
152855232f09SEwan Crawford     if (type != head->type)
152955232f09SEwan Crawford     {
153055232f09SEwan Crawford         const char* file_type_cstr = AllocationDetails::RsDataTypeToString[head->type][0];
153155232f09SEwan Crawford         const char* alloc_type_cstr = AllocationDetails::RsDataTypeToString[type][0];
153255232f09SEwan Crawford 
153355232f09SEwan Crawford         strm.Printf("Warning: Mismatched Types - file '%s' type, allocation '%s' type",
153455232f09SEwan Crawford                     file_type_cstr, alloc_type_cstr);
153555232f09SEwan Crawford         strm.EOL();
153655232f09SEwan Crawford     }
153755232f09SEwan Crawford 
153855232f09SEwan Crawford     // Calculate size of allocation data in file
153955232f09SEwan Crawford     size_t length = data_sp->GetByteSize() - head->hdr_size;
154055232f09SEwan Crawford 
154155232f09SEwan Crawford     // Check if the target allocation and file both have the same total data size.
154255232f09SEwan Crawford     const unsigned int alloc_size = *alloc->size.get();
154355232f09SEwan Crawford     if (alloc_size != length)
154455232f09SEwan Crawford     {
154555232f09SEwan Crawford         strm.Printf("Warning: Mismatched allocation sizes - file 0x%" PRIx64 " bytes, allocation 0x%x bytes",
154655232f09SEwan Crawford                     length, alloc_size);
154755232f09SEwan Crawford         strm.EOL();
154855232f09SEwan Crawford         length = alloc_size < length ? alloc_size : length; // Set length to copy to minimum
154955232f09SEwan Crawford     }
155055232f09SEwan Crawford 
155155232f09SEwan Crawford     // Copy file data from our buffer into the target allocation.
155255232f09SEwan Crawford     lldb::addr_t alloc_data = *alloc->data_ptr.get();
155355232f09SEwan Crawford     Error error;
155455232f09SEwan Crawford     size_t bytes_written = GetProcess()->WriteMemory(alloc_data, file_buffer, length, error);
155555232f09SEwan Crawford     if (!error.Success() || bytes_written != length)
155655232f09SEwan Crawford     {
155755232f09SEwan Crawford         strm.Printf("Error: Couldn't write data to allocation %s", error.AsCString());
155855232f09SEwan Crawford         strm.EOL();
155955232f09SEwan Crawford         return false;
156055232f09SEwan Crawford     }
156155232f09SEwan Crawford 
156255232f09SEwan Crawford     strm.Printf("Contents of file '%s' read into allocation %u", filename, alloc->id);
156355232f09SEwan Crawford     strm.EOL();
156455232f09SEwan Crawford 
156555232f09SEwan Crawford     return true;
156655232f09SEwan Crawford }
156755232f09SEwan Crawford 
156855232f09SEwan Crawford // Function copies allocation contents into a binary file.
156955232f09SEwan Crawford // This file can then be loaded later into a different allocation.
157055232f09SEwan Crawford // There is a header, FileHeader, before the allocation data containing meta-data.
157155232f09SEwan Crawford bool
157255232f09SEwan Crawford RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id, const char* filename, StackFrame* frame_ptr)
157355232f09SEwan Crawford {
157455232f09SEwan Crawford     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
157555232f09SEwan Crawford 
157655232f09SEwan Crawford     // Find allocation with the given id
157755232f09SEwan Crawford     AllocationDetails* alloc = FindAllocByID(strm, alloc_id);
157855232f09SEwan Crawford     if (!alloc)
157955232f09SEwan Crawford         return false;
158055232f09SEwan Crawford 
158155232f09SEwan Crawford     if (log)
158255232f09SEwan Crawford         log->Printf("RenderScriptRuntime::SaveAllocation - Found allocation 0x%" PRIx64, *alloc->address.get());
158355232f09SEwan Crawford 
158455232f09SEwan Crawford      // JIT all the allocation details
158555232f09SEwan Crawford     if (!alloc->data_ptr.isValid() || !alloc->type.isValid() || !alloc->type_vec_size.isValid()
158655232f09SEwan Crawford         || !alloc->type_kind.isValid() || !alloc->dimension.isValid())
158755232f09SEwan Crawford     {
158855232f09SEwan Crawford         if (log)
158955232f09SEwan Crawford             log->Printf("RenderScriptRuntime::SaveAllocation - Allocation details not calculated yet, jitting info");
159055232f09SEwan Crawford 
159155232f09SEwan Crawford         if (!RefreshAllocation(alloc, frame_ptr))
159255232f09SEwan Crawford         {
159355232f09SEwan Crawford             if (log)
159455232f09SEwan Crawford                 log->Printf("RenderScriptRuntime::SaveAllocation - Couldn't JIT allocation details");
159555232f09SEwan Crawford             return nullptr;
159655232f09SEwan Crawford         }
159755232f09SEwan Crawford     }
159855232f09SEwan Crawford 
159955232f09SEwan Crawford     assert(alloc->data_ptr.isValid() && alloc->type.isValid() && alloc->type_vec_size.isValid() && alloc->type_kind.isValid()
160055232f09SEwan Crawford            && alloc->dimension.isValid() && "Allocation information not available");
160155232f09SEwan Crawford 
160255232f09SEwan Crawford     // Check we can create writable file
160355232f09SEwan Crawford     FileSpec file_spec(filename, true);
160455232f09SEwan Crawford     File file(file_spec, File::eOpenOptionWrite | File::eOpenOptionCanCreate | File::eOpenOptionTruncate);
160555232f09SEwan Crawford     if (!file)
160655232f09SEwan Crawford     {
160755232f09SEwan Crawford         strm.Printf("Error: Failed to open '%s' for writing", filename);
160855232f09SEwan Crawford         strm.EOL();
160955232f09SEwan Crawford         return false;
161055232f09SEwan Crawford     }
161155232f09SEwan Crawford 
161255232f09SEwan Crawford     // Read allocation into buffer of heap memory
161355232f09SEwan Crawford     const std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr);
161455232f09SEwan Crawford     if (!buffer)
161555232f09SEwan Crawford     {
161655232f09SEwan Crawford         strm.Printf("Error: Couldn't read allocation data into buffer");
161755232f09SEwan Crawford         strm.EOL();
161855232f09SEwan Crawford         return false;
161955232f09SEwan Crawford     }
162055232f09SEwan Crawford 
162155232f09SEwan Crawford     // Create the file header
162255232f09SEwan Crawford     AllocationDetails::FileHeader head;
162355232f09SEwan Crawford     head.ident[0] = 'R'; head.ident[1] = 'S'; head.ident[2] = 'A'; head.ident[3] = 'D';
162455232f09SEwan Crawford     head.hdr_size = static_cast<uint16_t>(sizeof(AllocationDetails::FileHeader));
162555232f09SEwan Crawford     head.type = static_cast<uint16_t>(*alloc->type.get());
162655232f09SEwan Crawford     head.kind = static_cast<uint32_t>(*alloc->type_kind.get());
1627*2d62328aSEwan Crawford     head.dims[0] = static_cast<uint32_t>(alloc->dimension.get()->dim_1);
1628*2d62328aSEwan Crawford     head.dims[1] = static_cast<uint32_t>(alloc->dimension.get()->dim_2);
1629*2d62328aSEwan Crawford     head.dims[2] = static_cast<uint32_t>(alloc->dimension.get()->dim_3);
163055232f09SEwan Crawford     head.element_size = static_cast<uint32_t>(GetElementSize(alloc));
163155232f09SEwan Crawford 
163255232f09SEwan Crawford     // Write the file header
163355232f09SEwan Crawford     size_t num_bytes = sizeof(AllocationDetails::FileHeader);
163455232f09SEwan Crawford     Error err = file.Write(static_cast<const void*>(&head), num_bytes);
163555232f09SEwan Crawford     if (!err.Success())
163655232f09SEwan Crawford     {
163755232f09SEwan Crawford         strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), filename);
163855232f09SEwan Crawford         strm.EOL();
163955232f09SEwan Crawford         return false;
164055232f09SEwan Crawford     }
164155232f09SEwan Crawford 
164255232f09SEwan Crawford     // Write allocation data to file
164355232f09SEwan Crawford     num_bytes = static_cast<size_t>(*alloc->size.get());
164455232f09SEwan Crawford     if (log)
164555232f09SEwan Crawford         log->Printf("RenderScriptRuntime::SaveAllocation - Writing %" PRIx64  "bytes from %p", num_bytes, buffer.get());
164655232f09SEwan Crawford 
164755232f09SEwan Crawford     err = file.Write(buffer.get(), num_bytes);
164855232f09SEwan Crawford     if (!err.Success())
164955232f09SEwan Crawford     {
165055232f09SEwan Crawford         strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), filename);
165155232f09SEwan Crawford         strm.EOL();
165255232f09SEwan Crawford         return false;
165355232f09SEwan Crawford     }
165455232f09SEwan Crawford 
165555232f09SEwan Crawford     strm.Printf("Allocation written to file '%s'", filename);
165655232f09SEwan Crawford     strm.EOL();
165715f2bd95SEwan Crawford     return true;
165815f2bd95SEwan Crawford }
165915f2bd95SEwan Crawford 
16605ec532a9SColin Riley bool
16615ec532a9SColin Riley RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp)
16625ec532a9SColin Riley {
16634640cde1SColin Riley     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
16644640cde1SColin Riley 
16655ec532a9SColin Riley     if (module_sp)
16665ec532a9SColin Riley     {
16675ec532a9SColin Riley         for (const auto &rs_module : m_rsmodules)
16685ec532a9SColin Riley         {
16694640cde1SColin Riley             if (rs_module->m_module == module_sp)
16707dc7771cSEwan Crawford             {
16717dc7771cSEwan Crawford                 // Check if the user has enabled automatically breaking on
16727dc7771cSEwan Crawford                 // all RS kernels.
16737dc7771cSEwan Crawford                 if (m_breakAllKernels)
16747dc7771cSEwan Crawford                     BreakOnModuleKernels(rs_module);
16757dc7771cSEwan Crawford 
16765ec532a9SColin Riley                 return false;
16775ec532a9SColin Riley             }
16787dc7771cSEwan Crawford         }
1679ef20b08fSColin Riley         bool module_loaded = false;
1680ef20b08fSColin Riley         switch (GetModuleKind(module_sp))
1681ef20b08fSColin Riley         {
1682ef20b08fSColin Riley             case eModuleKindKernelObj:
1683ef20b08fSColin Riley             {
16844640cde1SColin Riley                 RSModuleDescriptorSP module_desc;
16854640cde1SColin Riley                 module_desc.reset(new RSModuleDescriptor(module_sp));
16864640cde1SColin Riley                 if (module_desc->ParseRSInfo())
16875ec532a9SColin Riley                 {
16885ec532a9SColin Riley                     m_rsmodules.push_back(module_desc);
1689ef20b08fSColin Riley                     module_loaded = true;
16905ec532a9SColin Riley                 }
16914640cde1SColin Riley                 if (module_loaded)
16924640cde1SColin Riley                 {
16934640cde1SColin Riley                     FixupScriptDetails(module_desc);
16944640cde1SColin Riley                 }
1695ef20b08fSColin Riley                 break;
1696ef20b08fSColin Riley             }
1697ef20b08fSColin Riley             case eModuleKindDriver:
16984640cde1SColin Riley             {
16994640cde1SColin Riley                 if (!m_libRSDriver)
17004640cde1SColin Riley                 {
17014640cde1SColin Riley                     m_libRSDriver = module_sp;
17024640cde1SColin Riley                     LoadRuntimeHooks(m_libRSDriver, RenderScriptRuntime::eModuleKindDriver);
17034640cde1SColin Riley                 }
17044640cde1SColin Riley                 break;
17054640cde1SColin Riley             }
1706ef20b08fSColin Riley             case eModuleKindImpl:
17074640cde1SColin Riley             {
17084640cde1SColin Riley                 m_libRSCpuRef = module_sp;
17094640cde1SColin Riley                 break;
17104640cde1SColin Riley             }
1711ef20b08fSColin Riley             case eModuleKindLibRS:
17124640cde1SColin Riley             {
17134640cde1SColin Riley                 if (!m_libRS)
17144640cde1SColin Riley                 {
17154640cde1SColin Riley                     m_libRS = module_sp;
17164640cde1SColin Riley                     static ConstString gDbgPresentStr("gDebuggerPresent");
17174640cde1SColin Riley                     const Symbol* debug_present = m_libRS->FindFirstSymbolWithNameAndType(gDbgPresentStr, eSymbolTypeData);
17184640cde1SColin Riley                     if (debug_present)
17194640cde1SColin Riley                     {
17204640cde1SColin Riley                         Error error;
17214640cde1SColin Riley                         uint32_t flag = 0x00000001U;
17224640cde1SColin Riley                         Target &target = GetProcess()->GetTarget();
1723358cf1eaSGreg Clayton                         addr_t addr = debug_present->GetLoadAddress(&target);
17244640cde1SColin Riley                         GetProcess()->WriteMemory(addr, &flag, sizeof(flag), error);
17254640cde1SColin Riley                         if(error.Success())
17264640cde1SColin Riley                         {
17274640cde1SColin Riley                             if (log)
17284640cde1SColin Riley                                 log->Printf ("RenderScriptRuntime::LoadModule - Debugger present flag set on debugee");
17294640cde1SColin Riley 
17304640cde1SColin Riley                             m_debuggerPresentFlagged = true;
17314640cde1SColin Riley                         }
17324640cde1SColin Riley                         else if (log)
17334640cde1SColin Riley                         {
17344640cde1SColin Riley                             log->Printf ("RenderScriptRuntime::LoadModule - Error writing debugger present flags '%s' ", error.AsCString());
17354640cde1SColin Riley                         }
17364640cde1SColin Riley                     }
17374640cde1SColin Riley                     else if (log)
17384640cde1SColin Riley                     {
17394640cde1SColin Riley                         log->Printf ("RenderScriptRuntime::LoadModule - Error writing debugger present flags - symbol not found");
17404640cde1SColin Riley                     }
17414640cde1SColin Riley                 }
17424640cde1SColin Riley                 break;
17434640cde1SColin Riley             }
1744ef20b08fSColin Riley             default:
1745ef20b08fSColin Riley                 break;
1746ef20b08fSColin Riley         }
1747ef20b08fSColin Riley         if (module_loaded)
1748ef20b08fSColin Riley             Update();
1749ef20b08fSColin Riley         return module_loaded;
17505ec532a9SColin Riley     }
17515ec532a9SColin Riley     return false;
17525ec532a9SColin Riley }
17535ec532a9SColin Riley 
1754ef20b08fSColin Riley void
1755ef20b08fSColin Riley RenderScriptRuntime::Update()
1756ef20b08fSColin Riley {
1757ef20b08fSColin Riley     if (m_rsmodules.size() > 0)
1758ef20b08fSColin Riley     {
1759ef20b08fSColin Riley         if (!m_initiated)
1760ef20b08fSColin Riley         {
1761ef20b08fSColin Riley             Initiate();
1762ef20b08fSColin Riley         }
1763ef20b08fSColin Riley     }
1764ef20b08fSColin Riley }
1765ef20b08fSColin Riley 
1766ef20b08fSColin Riley 
17675ec532a9SColin Riley // The maximum line length of an .rs.info packet
17685ec532a9SColin Riley #define MAXLINE 500
17695ec532a9SColin Riley 
17705ec532a9SColin Riley // The .rs.info symbol in renderscript modules contains a string which needs to be parsed.
17715ec532a9SColin Riley // The string is basic and is parsed on a line by line basis.
17725ec532a9SColin Riley bool
17735ec532a9SColin Riley RSModuleDescriptor::ParseRSInfo()
17745ec532a9SColin Riley {
17755ec532a9SColin Riley     const Symbol *info_sym = m_module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData);
17765ec532a9SColin Riley     if (info_sym)
17775ec532a9SColin Riley     {
1778358cf1eaSGreg Clayton         const addr_t addr = info_sym->GetAddressRef().GetFileAddress();
17795ec532a9SColin Riley         const addr_t size = info_sym->GetByteSize();
17805ec532a9SColin Riley         const FileSpec fs = m_module->GetFileSpec();
17815ec532a9SColin Riley 
17825ec532a9SColin Riley         DataBufferSP buffer = fs.ReadFileContents(addr, size);
17835ec532a9SColin Riley 
17845ec532a9SColin Riley         if (!buffer)
17855ec532a9SColin Riley             return false;
17865ec532a9SColin Riley 
17875ec532a9SColin Riley         std::string info((const char *)buffer->GetBytes());
17885ec532a9SColin Riley 
17895ec532a9SColin Riley         std::vector<std::string> info_lines;
1790e8433cc1SBruce Mitchener         size_t lpos = info.find('\n');
17915ec532a9SColin Riley         while (lpos != std::string::npos)
17925ec532a9SColin Riley         {
17935ec532a9SColin Riley             info_lines.push_back(info.substr(0, lpos));
17945ec532a9SColin Riley             info = info.substr(lpos + 1);
1795e8433cc1SBruce Mitchener             lpos = info.find('\n');
17965ec532a9SColin Riley         }
17975ec532a9SColin Riley         size_t offset = 0;
17985ec532a9SColin Riley         while (offset < info_lines.size())
17995ec532a9SColin Riley         {
18005ec532a9SColin Riley             std::string line = info_lines[offset];
18015ec532a9SColin Riley             // Parse directives
18025ec532a9SColin Riley             uint32_t numDefns = 0;
18035ec532a9SColin Riley             if (sscanf(line.c_str(), "exportVarCount: %u", &numDefns) == 1)
18045ec532a9SColin Riley             {
18055ec532a9SColin Riley                 while (numDefns--)
18064640cde1SColin Riley                     m_globals.push_back(RSGlobalDescriptor(this, info_lines[++offset].c_str()));
18075ec532a9SColin Riley             }
18085ec532a9SColin Riley             else if (sscanf(line.c_str(), "exportFuncCount: %u", &numDefns) == 1)
18095ec532a9SColin Riley             {
18105ec532a9SColin Riley             }
18115ec532a9SColin Riley             else if (sscanf(line.c_str(), "exportForEachCount: %u", &numDefns) == 1)
18125ec532a9SColin Riley             {
18135ec532a9SColin Riley                 char name[MAXLINE];
18145ec532a9SColin Riley                 while (numDefns--)
18155ec532a9SColin Riley                 {
18165ec532a9SColin Riley                     uint32_t slot = 0;
18175ec532a9SColin Riley                     name[0] = '\0';
18185ec532a9SColin Riley                     if (sscanf(info_lines[++offset].c_str(), "%u - %s", &slot, &name[0]) == 2)
18195ec532a9SColin Riley                     {
18204640cde1SColin Riley                         m_kernels.push_back(RSKernelDescriptor(this, name, slot));
18214640cde1SColin Riley                     }
18224640cde1SColin Riley                 }
18234640cde1SColin Riley             }
18244640cde1SColin Riley             else if (sscanf(line.c_str(), "pragmaCount: %u", &numDefns) == 1)
18254640cde1SColin Riley             {
18264640cde1SColin Riley                 char name[MAXLINE];
18274640cde1SColin Riley                 char value[MAXLINE];
18284640cde1SColin Riley                 while (numDefns--)
18294640cde1SColin Riley                 {
18304640cde1SColin Riley                     name[0] = '\0';
18314640cde1SColin Riley                     value[0] = '\0';
18324640cde1SColin Riley                     if (sscanf(info_lines[++offset].c_str(), "%s - %s", &name[0], &value[0]) != 0
18334640cde1SColin Riley                         && (name[0] != '\0'))
18344640cde1SColin Riley                     {
18354640cde1SColin Riley                         m_pragmas[std::string(name)] = value;
18365ec532a9SColin Riley                     }
18375ec532a9SColin Riley                 }
18385ec532a9SColin Riley             }
18395ec532a9SColin Riley             else if (sscanf(line.c_str(), "objectSlotCount: %u", &numDefns) == 1)
18405ec532a9SColin Riley             {
18415ec532a9SColin Riley             }
18425ec532a9SColin Riley 
18435ec532a9SColin Riley             offset++;
18445ec532a9SColin Riley         }
18455ec532a9SColin Riley         return m_kernels.size() > 0;
18465ec532a9SColin Riley     }
18475ec532a9SColin Riley     return false;
18485ec532a9SColin Riley }
18495ec532a9SColin Riley 
18505ec532a9SColin Riley bool
18515ec532a9SColin Riley RenderScriptRuntime::ProbeModules(const ModuleList module_list)
18525ec532a9SColin Riley {
18535ec532a9SColin Riley     bool rs_found = false;
18545ec532a9SColin Riley     size_t num_modules = module_list.GetSize();
18555ec532a9SColin Riley     for (size_t i = 0; i < num_modules; i++)
18565ec532a9SColin Riley     {
18575ec532a9SColin Riley         auto module = module_list.GetModuleAtIndex(i);
18585ec532a9SColin Riley         rs_found |= LoadModule(module);
18595ec532a9SColin Riley     }
18605ec532a9SColin Riley     return rs_found;
18615ec532a9SColin Riley }
18625ec532a9SColin Riley 
18635ec532a9SColin Riley void
18644640cde1SColin Riley RenderScriptRuntime::Status(Stream &strm) const
18654640cde1SColin Riley {
18664640cde1SColin Riley     if (m_libRS)
18674640cde1SColin Riley     {
18684640cde1SColin Riley         strm.Printf("Runtime Library discovered.");
18694640cde1SColin Riley         strm.EOL();
18704640cde1SColin Riley     }
18714640cde1SColin Riley     if (m_libRSDriver)
18724640cde1SColin Riley     {
18734640cde1SColin Riley         strm.Printf("Runtime Driver discovered.");
18744640cde1SColin Riley         strm.EOL();
18754640cde1SColin Riley     }
18764640cde1SColin Riley     if (m_libRSCpuRef)
18774640cde1SColin Riley     {
18784640cde1SColin Riley         strm.Printf("CPU Reference Implementation discovered.");
18794640cde1SColin Riley         strm.EOL();
18804640cde1SColin Riley     }
18814640cde1SColin Riley 
18824640cde1SColin Riley     if (m_runtimeHooks.size())
18834640cde1SColin Riley     {
18844640cde1SColin Riley         strm.Printf("Runtime functions hooked:");
18854640cde1SColin Riley         strm.EOL();
18864640cde1SColin Riley         for (auto b : m_runtimeHooks)
18874640cde1SColin Riley         {
18884640cde1SColin Riley             strm.Indent(b.second->defn->name);
18894640cde1SColin Riley             strm.EOL();
18904640cde1SColin Riley         }
18914640cde1SColin Riley         strm.EOL();
18924640cde1SColin Riley     }
18934640cde1SColin Riley     else
18944640cde1SColin Riley     {
18954640cde1SColin Riley         strm.Printf("Runtime is not hooked.");
18964640cde1SColin Riley         strm.EOL();
18974640cde1SColin Riley     }
18984640cde1SColin Riley }
18994640cde1SColin Riley 
19004640cde1SColin Riley void
19014640cde1SColin Riley RenderScriptRuntime::DumpContexts(Stream &strm) const
19024640cde1SColin Riley {
19034640cde1SColin Riley     strm.Printf("Inferred RenderScript Contexts:");
19044640cde1SColin Riley     strm.EOL();
19054640cde1SColin Riley     strm.IndentMore();
19064640cde1SColin Riley 
19074640cde1SColin Riley     std::map<addr_t, uint64_t> contextReferences;
19084640cde1SColin Riley 
190978f339d1SEwan Crawford     // Iterate over all of the currently discovered scripts.
191078f339d1SEwan Crawford     // Note: We cant push or pop from m_scripts inside this loop or it may invalidate script.
19114640cde1SColin Riley     for (const auto & script : m_scripts)
19124640cde1SColin Riley     {
191378f339d1SEwan Crawford         if (!script->context.isValid())
191478f339d1SEwan Crawford             continue;
191578f339d1SEwan Crawford         lldb::addr_t context = *script->context;
191678f339d1SEwan Crawford 
191778f339d1SEwan Crawford         if (contextReferences.find(context) != contextReferences.end())
19184640cde1SColin Riley         {
191978f339d1SEwan Crawford             contextReferences[context]++;
19204640cde1SColin Riley         }
19214640cde1SColin Riley         else
19224640cde1SColin Riley         {
192378f339d1SEwan Crawford             contextReferences[context] = 1;
19244640cde1SColin Riley         }
19254640cde1SColin Riley     }
19264640cde1SColin Riley 
19274640cde1SColin Riley     for (const auto& cRef : contextReferences)
19284640cde1SColin Riley     {
19294640cde1SColin Riley         strm.Printf("Context 0x%" PRIx64 ": %" PRIu64 " script instances", cRef.first, cRef.second);
19304640cde1SColin Riley         strm.EOL();
19314640cde1SColin Riley     }
19324640cde1SColin Riley     strm.IndentLess();
19334640cde1SColin Riley }
19344640cde1SColin Riley 
19354640cde1SColin Riley void
19364640cde1SColin Riley RenderScriptRuntime::DumpKernels(Stream &strm) const
19374640cde1SColin Riley {
19384640cde1SColin Riley     strm.Printf("RenderScript Kernels:");
19394640cde1SColin Riley     strm.EOL();
19404640cde1SColin Riley     strm.IndentMore();
19414640cde1SColin Riley     for (const auto &module : m_rsmodules)
19424640cde1SColin Riley     {
19434640cde1SColin Riley         strm.Printf("Resource '%s':",module->m_resname.c_str());
19444640cde1SColin Riley         strm.EOL();
19454640cde1SColin Riley         for (const auto &kernel : module->m_kernels)
19464640cde1SColin Riley         {
19474640cde1SColin Riley             strm.Indent(kernel.m_name.AsCString());
19484640cde1SColin Riley             strm.EOL();
19494640cde1SColin Riley         }
19504640cde1SColin Riley     }
19514640cde1SColin Riley     strm.IndentLess();
19524640cde1SColin Riley }
19534640cde1SColin Riley 
1954a0f08674SEwan Crawford RenderScriptRuntime::AllocationDetails*
1955a0f08674SEwan Crawford RenderScriptRuntime::FindAllocByID(Stream &strm, const uint32_t alloc_id)
1956a0f08674SEwan Crawford {
1957a0f08674SEwan Crawford     AllocationDetails* alloc = nullptr;
1958a0f08674SEwan Crawford 
1959a0f08674SEwan Crawford     // See if we can find allocation using id as an index;
1960a0f08674SEwan Crawford     if (alloc_id <= m_allocations.size() && alloc_id != 0
1961a0f08674SEwan Crawford         && m_allocations[alloc_id-1]->id == alloc_id)
1962a0f08674SEwan Crawford     {
1963a0f08674SEwan Crawford         alloc = m_allocations[alloc_id-1].get();
1964a0f08674SEwan Crawford         return alloc;
1965a0f08674SEwan Crawford     }
1966a0f08674SEwan Crawford 
1967a0f08674SEwan Crawford     // Fallback to searching
1968a0f08674SEwan Crawford     for (const auto & a : m_allocations)
1969a0f08674SEwan Crawford     {
1970a0f08674SEwan Crawford        if (a->id == alloc_id)
1971a0f08674SEwan Crawford        {
1972a0f08674SEwan Crawford            alloc = a.get();
1973a0f08674SEwan Crawford            break;
1974a0f08674SEwan Crawford        }
1975a0f08674SEwan Crawford     }
1976a0f08674SEwan Crawford 
1977a0f08674SEwan Crawford     if (alloc == nullptr)
1978a0f08674SEwan Crawford     {
1979a0f08674SEwan Crawford         strm.Printf("Error: Couldn't find allocation with id matching %u", alloc_id);
1980a0f08674SEwan Crawford         strm.EOL();
1981a0f08674SEwan Crawford     }
1982a0f08674SEwan Crawford 
1983a0f08674SEwan Crawford     return alloc;
1984a0f08674SEwan Crawford }
1985a0f08674SEwan Crawford 
1986a0f08674SEwan Crawford // Prints the contents of an allocation to the output stream, which may be a file
1987a0f08674SEwan Crawford bool
1988a0f08674SEwan Crawford RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame* frame_ptr, const uint32_t id)
1989a0f08674SEwan Crawford {
1990a0f08674SEwan Crawford     Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1991a0f08674SEwan Crawford 
1992a0f08674SEwan Crawford     // Check we can find the desired allocation
1993a0f08674SEwan Crawford     AllocationDetails* alloc = FindAllocByID(strm, id);
1994a0f08674SEwan Crawford     if (!alloc)
1995a0f08674SEwan Crawford         return false; // FindAllocByID() will print error message for us here
1996a0f08674SEwan Crawford 
1997a0f08674SEwan Crawford     if (log)
1998a0f08674SEwan Crawford         log->Printf("RenderScriptRuntime::DumpAllocation - Found allocation 0x%" PRIx64, *alloc->address.get());
1999a0f08674SEwan Crawford 
2000a0f08674SEwan Crawford     // Check we have information about the allocation, if not calculate it
2001a0f08674SEwan Crawford     if (!alloc->data_ptr.isValid() || !alloc->type.isValid() ||
2002a0f08674SEwan Crawford         !alloc->type_vec_size.isValid() || !alloc->dimension.isValid())
2003a0f08674SEwan Crawford     {
2004a0f08674SEwan Crawford         if (log)
2005a0f08674SEwan Crawford             log->Printf("RenderScriptRuntime::DumpAllocation - Allocation details not calculated yet, jitting info");
2006a0f08674SEwan Crawford 
2007a0f08674SEwan Crawford         // JIT all the allocation information
2008a0f08674SEwan Crawford         if (!RefreshAllocation(alloc, frame_ptr))
2009a0f08674SEwan Crawford         {
2010a0f08674SEwan Crawford             strm.Printf("Error: Couldn't JIT allocation details");
2011a0f08674SEwan Crawford             strm.EOL();
2012a0f08674SEwan Crawford             return false;
2013a0f08674SEwan Crawford         }
2014a0f08674SEwan Crawford     }
2015a0f08674SEwan Crawford 
2016a0f08674SEwan Crawford     // Establish format and size of each data element
2017a0f08674SEwan Crawford     const unsigned int vec_size = *alloc->type_vec_size.get();
2018a0f08674SEwan Crawford     const AllocationDetails::DataType type = *alloc->type.get();
2019a0f08674SEwan Crawford 
2020a0f08674SEwan Crawford     assert(type >= AllocationDetails::RS_TYPE_NONE && type <= AllocationDetails::RS_TYPE_BOOLEAN
2021a0f08674SEwan Crawford                                                    && "Invalid allocation type");
2022a0f08674SEwan Crawford 
2023a0f08674SEwan Crawford     lldb::Format format = vec_size == 1 ? static_cast<lldb::Format>(AllocationDetails::RSTypeToFormat[type][eFormatSingle])
2024a0f08674SEwan Crawford                                         : static_cast<lldb::Format>(AllocationDetails::RSTypeToFormat[type][eFormatVector]);
2025a0f08674SEwan Crawford 
2026a0f08674SEwan Crawford     const unsigned int data_size = vec_size * AllocationDetails::RSTypeToFormat[type][eElementSize];
2027a0f08674SEwan Crawford     // Renderscript pads vector 3 elements to vector 4
2028a0f08674SEwan Crawford     const unsigned int elem_padding = vec_size == 3 ? AllocationDetails::RSTypeToFormat[type][eElementSize] : 0;
2029a0f08674SEwan Crawford 
2030a0f08674SEwan Crawford     if (log)
2031a0f08674SEwan Crawford         log->Printf("RenderScriptRuntime::DumpAllocation - Element size %u bytes, element padding %u bytes",
2032a0f08674SEwan Crawford                     data_size, elem_padding);
2033a0f08674SEwan Crawford 
203455232f09SEwan Crawford     // Allocate a buffer to copy data into
203555232f09SEwan Crawford     std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr);
203655232f09SEwan Crawford     if (!buffer)
203755232f09SEwan Crawford     {
203855232f09SEwan Crawford         strm.Printf("Error: Couldn't allocate a read allocation data into memory");
203955232f09SEwan Crawford         strm.EOL();
204055232f09SEwan Crawford         return false;
204155232f09SEwan Crawford     }
204255232f09SEwan Crawford 
2043a0f08674SEwan Crawford     // Calculate stride between rows as there may be padding at end of rows since
2044a0f08674SEwan Crawford     // allocated memory is 16-byte aligned
2045a0f08674SEwan Crawford     if (!alloc->stride.isValid())
2046a0f08674SEwan Crawford     {
2047a0f08674SEwan Crawford         if (alloc->dimension.get()->dim_2 == 0) // We only have one dimension
2048a0f08674SEwan Crawford             alloc->stride = 0;
2049a0f08674SEwan Crawford         else if (!JITAllocationStride(alloc, frame_ptr))
2050a0f08674SEwan Crawford         {
2051a0f08674SEwan Crawford             strm.Printf("Error: Couldn't calculate allocation row stride");
2052a0f08674SEwan Crawford             strm.EOL();
2053a0f08674SEwan Crawford             return false;
2054a0f08674SEwan Crawford         }
2055a0f08674SEwan Crawford     }
2056a0f08674SEwan Crawford     const unsigned int stride = *alloc->stride.get();
2057a0f08674SEwan Crawford     const unsigned int size = *alloc->size.get(); //size of last element
2058a0f08674SEwan Crawford 
2059a0f08674SEwan Crawford     if (log)
2060a0f08674SEwan Crawford         log->Printf("RenderScriptRuntime::DumpAllocation - stride %u bytes, size %u bytes", stride, size);
2061a0f08674SEwan Crawford 
2062a0f08674SEwan Crawford     // Find dimensions used to index loops, so need to be non-zero
2063a0f08674SEwan Crawford     unsigned int dim_x = alloc->dimension.get()->dim_1;
2064a0f08674SEwan Crawford     dim_x = dim_x == 0 ? 1 : dim_x;
2065a0f08674SEwan Crawford 
2066a0f08674SEwan Crawford     unsigned int dim_y = alloc->dimension.get()->dim_2;
2067a0f08674SEwan Crawford     dim_y = dim_y == 0 ? 1 : dim_y;
2068a0f08674SEwan Crawford 
2069a0f08674SEwan Crawford     unsigned int dim_z = alloc->dimension.get()->dim_3;
2070a0f08674SEwan Crawford     dim_z = dim_z == 0 ? 1 : dim_z;
2071a0f08674SEwan Crawford 
207255232f09SEwan Crawford     // Use data extractor to format output
207355232f09SEwan Crawford     const uint32_t archByteSize = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
207455232f09SEwan Crawford     DataExtractor alloc_data(buffer.get(), size, GetProcess()->GetByteOrder(), archByteSize);
207555232f09SEwan Crawford 
2076a0f08674SEwan Crawford     unsigned int offset = 0;   // Offset in buffer to next element to be printed
2077a0f08674SEwan Crawford     unsigned int prev_row = 0; // Offset to the start of the previous row
2078a0f08674SEwan Crawford 
2079a0f08674SEwan Crawford     // Iterate over allocation dimensions, printing results to user
2080a0f08674SEwan Crawford     strm.Printf("Data (X, Y, Z):");
2081a0f08674SEwan Crawford     for (unsigned int z = 0; z < dim_z; ++z)
2082a0f08674SEwan Crawford     {
2083a0f08674SEwan Crawford         for (unsigned int y = 0; y < dim_y; ++y)
2084a0f08674SEwan Crawford         {
2085a0f08674SEwan Crawford             // Use stride to index start of next row.
2086a0f08674SEwan Crawford             if (!(y==0 && z==0))
2087a0f08674SEwan Crawford                 offset = prev_row + stride;
2088a0f08674SEwan Crawford             prev_row = offset;
2089a0f08674SEwan Crawford 
2090a0f08674SEwan Crawford             // Print each element in the row individually
2091a0f08674SEwan Crawford             for (unsigned int x = 0; x < dim_x; ++x)
2092a0f08674SEwan Crawford             {
2093a0f08674SEwan Crawford                 strm.Printf("\n(%u, %u, %u) = ", x, y, z);
2094a0f08674SEwan Crawford                 alloc_data.Dump(&strm, offset, format, data_size, 1, 1, LLDB_INVALID_ADDRESS, 0, 0);
2095a0f08674SEwan Crawford                 offset += data_size + elem_padding;
2096a0f08674SEwan Crawford             }
2097a0f08674SEwan Crawford         }
2098a0f08674SEwan Crawford     }
2099a0f08674SEwan Crawford     strm.EOL();
2100a0f08674SEwan Crawford 
2101a0f08674SEwan Crawford     return true;
2102a0f08674SEwan Crawford }
2103a0f08674SEwan Crawford 
210415f2bd95SEwan Crawford // Prints infomation regarding all the currently loaded allocations.
210515f2bd95SEwan Crawford // These details are gathered by jitting the runtime, which has as latency.
210615f2bd95SEwan Crawford void
210715f2bd95SEwan Crawford RenderScriptRuntime::ListAllocations(Stream &strm, StackFrame* frame_ptr, bool recompute)
210815f2bd95SEwan Crawford {
210915f2bd95SEwan Crawford     strm.Printf("RenderScript Allocations:");
211015f2bd95SEwan Crawford     strm.EOL();
211115f2bd95SEwan Crawford     strm.IndentMore();
211215f2bd95SEwan Crawford 
211315f2bd95SEwan Crawford     for (auto &alloc : m_allocations)
211415f2bd95SEwan Crawford     {
211515f2bd95SEwan Crawford         // JIT the allocation info if we haven't done it, or the user forces us to.
211615f2bd95SEwan Crawford         bool do_refresh = !alloc->data_ptr.isValid() || recompute;
211715f2bd95SEwan Crawford 
211815f2bd95SEwan Crawford         // JIT current allocation information
211915f2bd95SEwan Crawford         if (do_refresh && !RefreshAllocation(alloc.get(), frame_ptr))
212015f2bd95SEwan Crawford         {
212115f2bd95SEwan Crawford             strm.Printf("Error: Couldn't evaluate details for allocation %u\n", alloc->id);
212215f2bd95SEwan Crawford             continue;
212315f2bd95SEwan Crawford         }
212415f2bd95SEwan Crawford 
212515f2bd95SEwan Crawford         strm.Printf("%u:\n",alloc->id);
212615f2bd95SEwan Crawford         strm.IndentMore();
212715f2bd95SEwan Crawford 
212815f2bd95SEwan Crawford         strm.Indent("Context: ");
212915f2bd95SEwan Crawford         if (!alloc->context.isValid())
213015f2bd95SEwan Crawford             strm.Printf("unknown\n");
213115f2bd95SEwan Crawford         else
213215f2bd95SEwan Crawford             strm.Printf("0x%" PRIx64 "\n", *alloc->context.get());
213315f2bd95SEwan Crawford 
213415f2bd95SEwan Crawford         strm.Indent("Address: ");
213515f2bd95SEwan Crawford         if (!alloc->address.isValid())
213615f2bd95SEwan Crawford             strm.Printf("unknown\n");
213715f2bd95SEwan Crawford         else
213815f2bd95SEwan Crawford             strm.Printf("0x%" PRIx64 "\n", *alloc->address.get());
213915f2bd95SEwan Crawford 
214015f2bd95SEwan Crawford         strm.Indent("Data pointer: ");
214115f2bd95SEwan Crawford         if (!alloc->data_ptr.isValid())
214215f2bd95SEwan Crawford             strm.Printf("unknown\n");
214315f2bd95SEwan Crawford         else
214415f2bd95SEwan Crawford             strm.Printf("0x%" PRIx64 "\n", *alloc->data_ptr.get());
214515f2bd95SEwan Crawford 
214615f2bd95SEwan Crawford         strm.Indent("Dimensions: ");
214715f2bd95SEwan Crawford         if (!alloc->dimension.isValid())
214815f2bd95SEwan Crawford             strm.Printf("unknown\n");
214915f2bd95SEwan Crawford         else
215015f2bd95SEwan Crawford             strm.Printf("(%d, %d, %d)\n", alloc->dimension.get()->dim_1,
215115f2bd95SEwan Crawford                                           alloc->dimension.get()->dim_2,
215215f2bd95SEwan Crawford                                           alloc->dimension.get()->dim_3);
215315f2bd95SEwan Crawford 
215415f2bd95SEwan Crawford         strm.Indent("Data Type: ");
215515f2bd95SEwan Crawford         if (!alloc->type.isValid() || !alloc->type_vec_size.isValid())
215615f2bd95SEwan Crawford             strm.Printf("unknown\n");
215715f2bd95SEwan Crawford         else
215815f2bd95SEwan Crawford         {
215915f2bd95SEwan Crawford             const int vector_size = *alloc->type_vec_size.get();
216015f2bd95SEwan Crawford             const AllocationDetails::DataType type = *alloc->type.get();
216115f2bd95SEwan Crawford 
216215f2bd95SEwan Crawford             if (vector_size > 4 || vector_size < 1 ||
216315f2bd95SEwan Crawford                 type < AllocationDetails::RS_TYPE_NONE || type > AllocationDetails::RS_TYPE_BOOLEAN)
216415f2bd95SEwan Crawford                 strm.Printf("invalid type\n");
216515f2bd95SEwan Crawford             else
216615f2bd95SEwan Crawford                 strm.Printf("%s\n", AllocationDetails::RsDataTypeToString[static_cast<unsigned int>(type)][vector_size-1]);
216715f2bd95SEwan Crawford         }
216815f2bd95SEwan Crawford 
216915f2bd95SEwan Crawford         strm.Indent("Data Kind: ");
217015f2bd95SEwan Crawford         if (!alloc->type_kind.isValid())
217115f2bd95SEwan Crawford             strm.Printf("unknown\n");
217215f2bd95SEwan Crawford         else
217315f2bd95SEwan Crawford         {
217415f2bd95SEwan Crawford             const AllocationDetails::DataKind kind = *alloc->type_kind.get();
217515f2bd95SEwan Crawford             if (kind < AllocationDetails::RS_KIND_USER || kind > AllocationDetails::RS_KIND_PIXEL_YUV)
217615f2bd95SEwan Crawford                 strm.Printf("invalid kind\n");
217715f2bd95SEwan Crawford             else
217815f2bd95SEwan Crawford                 strm.Printf("%s\n", AllocationDetails::RsDataKindToString[static_cast<unsigned int>(kind)]);
217915f2bd95SEwan Crawford         }
218015f2bd95SEwan Crawford 
218115f2bd95SEwan Crawford         strm.EOL();
218215f2bd95SEwan Crawford         strm.IndentLess();
218315f2bd95SEwan Crawford     }
218415f2bd95SEwan Crawford     strm.IndentLess();
218515f2bd95SEwan Crawford }
218615f2bd95SEwan Crawford 
21877dc7771cSEwan Crawford // Set breakpoints on every kernel found in RS module
21887dc7771cSEwan Crawford void
21897dc7771cSEwan Crawford RenderScriptRuntime::BreakOnModuleKernels(const RSModuleDescriptorSP rsmodule_sp)
21907dc7771cSEwan Crawford {
21917dc7771cSEwan Crawford     for (const auto &kernel : rsmodule_sp->m_kernels)
21927dc7771cSEwan Crawford     {
21937dc7771cSEwan Crawford         // Don't set breakpoint on 'root' kernel
21947dc7771cSEwan Crawford         if (strcmp(kernel.m_name.AsCString(), "root") == 0)
21957dc7771cSEwan Crawford             continue;
21967dc7771cSEwan Crawford 
21977dc7771cSEwan Crawford         CreateKernelBreakpoint(kernel.m_name);
21987dc7771cSEwan Crawford     }
21997dc7771cSEwan Crawford }
22007dc7771cSEwan Crawford 
22017dc7771cSEwan Crawford // Method is internally called by the 'kernel breakpoint all' command to
22027dc7771cSEwan Crawford // enable or disable breaking on all kernels.
22037dc7771cSEwan Crawford //
22047dc7771cSEwan Crawford // When do_break is true we want to enable this functionality.
22057dc7771cSEwan Crawford // When do_break is false we want to disable it.
22067dc7771cSEwan Crawford void
22077dc7771cSEwan Crawford RenderScriptRuntime::SetBreakAllKernels(bool do_break, TargetSP target)
22087dc7771cSEwan Crawford {
220954782db7SEwan Crawford     Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
22107dc7771cSEwan Crawford 
22117dc7771cSEwan Crawford     InitSearchFilter(target);
22127dc7771cSEwan Crawford 
22137dc7771cSEwan Crawford     // Set breakpoints on all the kernels
22147dc7771cSEwan Crawford     if (do_break && !m_breakAllKernels)
22157dc7771cSEwan Crawford     {
22167dc7771cSEwan Crawford         m_breakAllKernels = true;
22177dc7771cSEwan Crawford 
22187dc7771cSEwan Crawford         for (const auto &module : m_rsmodules)
22197dc7771cSEwan Crawford             BreakOnModuleKernels(module);
22207dc7771cSEwan Crawford 
22217dc7771cSEwan Crawford         if (log)
22227dc7771cSEwan Crawford             log->Printf("RenderScriptRuntime::SetBreakAllKernels(True)"
22237dc7771cSEwan Crawford                         "- breakpoints set on all currently loaded kernels");
22247dc7771cSEwan Crawford     }
22257dc7771cSEwan Crawford     else if (!do_break && m_breakAllKernels) // Breakpoints won't be set on any new kernels.
22267dc7771cSEwan Crawford     {
22277dc7771cSEwan Crawford         m_breakAllKernels = false;
22287dc7771cSEwan Crawford 
22297dc7771cSEwan Crawford         if (log)
22307dc7771cSEwan Crawford             log->Printf("RenderScriptRuntime::SetBreakAllKernels(False) - breakpoints no longer automatically set");
22317dc7771cSEwan Crawford     }
22327dc7771cSEwan Crawford }
22337dc7771cSEwan Crawford 
22347dc7771cSEwan Crawford // Given the name of a kernel this function creates a breakpoint using our
22357dc7771cSEwan Crawford // own breakpoint resolver, and returns the Breakpoint shared pointer.
22367dc7771cSEwan Crawford BreakpointSP
22377dc7771cSEwan Crawford RenderScriptRuntime::CreateKernelBreakpoint(const ConstString& name)
22387dc7771cSEwan Crawford {
223954782db7SEwan Crawford     Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
22407dc7771cSEwan Crawford 
22417dc7771cSEwan Crawford     if (!m_filtersp)
22427dc7771cSEwan Crawford     {
22437dc7771cSEwan Crawford         if (log)
22447dc7771cSEwan Crawford             log->Printf("RenderScriptRuntime::CreateKernelBreakpoint - Error: No breakpoint search filter set");
22457dc7771cSEwan Crawford         return nullptr;
22467dc7771cSEwan Crawford     }
22477dc7771cSEwan Crawford 
22487dc7771cSEwan Crawford     BreakpointResolverSP resolver_sp(new RSBreakpointResolver(nullptr, name));
22497dc7771cSEwan Crawford     BreakpointSP bp = GetProcess()->GetTarget().CreateBreakpoint(m_filtersp, resolver_sp, false, false, false);
22507dc7771cSEwan Crawford 
225154782db7SEwan Crawford     // Give RS breakpoints a specific name, so the user can manipulate them as a group.
225254782db7SEwan Crawford     Error err;
225354782db7SEwan Crawford     if (!bp->AddName("RenderScriptKernel", err) && log)
225454782db7SEwan Crawford         log->Printf("RenderScriptRuntime::CreateKernelBreakpoint: Error setting break name, %s", err.AsCString());
225554782db7SEwan Crawford 
22567dc7771cSEwan Crawford     return bp;
22577dc7771cSEwan Crawford }
22587dc7771cSEwan Crawford 
22594640cde1SColin Riley void
226098156583SEwan Crawford RenderScriptRuntime::AttemptBreakpointAtKernelName(Stream &strm, const char* name, Error& error, TargetSP target)
22614640cde1SColin Riley {
22624640cde1SColin Riley     if (!name)
22634640cde1SColin Riley     {
22644640cde1SColin Riley         error.SetErrorString("invalid kernel name");
22654640cde1SColin Riley         return;
22664640cde1SColin Riley     }
22674640cde1SColin Riley 
22687dc7771cSEwan Crawford     InitSearchFilter(target);
226998156583SEwan Crawford 
22704640cde1SColin Riley     ConstString kernel_name(name);
22717dc7771cSEwan Crawford     BreakpointSP bp = CreateKernelBreakpoint(kernel_name);
227298156583SEwan Crawford     if (bp)
227398156583SEwan Crawford         bp->GetDescription(&strm, lldb::eDescriptionLevelInitial, false);
22744640cde1SColin Riley 
22754640cde1SColin Riley     return;
22764640cde1SColin Riley }
22774640cde1SColin Riley 
22784640cde1SColin Riley void
22795ec532a9SColin Riley RenderScriptRuntime::DumpModules(Stream &strm) const
22805ec532a9SColin Riley {
22815ec532a9SColin Riley     strm.Printf("RenderScript Modules:");
22825ec532a9SColin Riley     strm.EOL();
22835ec532a9SColin Riley     strm.IndentMore();
22845ec532a9SColin Riley     for (const auto &module : m_rsmodules)
22855ec532a9SColin Riley     {
22864640cde1SColin Riley         module->Dump(strm);
22875ec532a9SColin Riley     }
22885ec532a9SColin Riley     strm.IndentLess();
22895ec532a9SColin Riley }
22905ec532a9SColin Riley 
229178f339d1SEwan Crawford RenderScriptRuntime::ScriptDetails*
229278f339d1SEwan Crawford RenderScriptRuntime::LookUpScript(addr_t address, bool create)
229378f339d1SEwan Crawford {
229478f339d1SEwan Crawford     for (const auto & s : m_scripts)
229578f339d1SEwan Crawford     {
229678f339d1SEwan Crawford         if (s->script.isValid())
229778f339d1SEwan Crawford             if (*s->script == address)
229878f339d1SEwan Crawford                 return s.get();
229978f339d1SEwan Crawford     }
230078f339d1SEwan Crawford     if (create)
230178f339d1SEwan Crawford     {
230278f339d1SEwan Crawford         std::unique_ptr<ScriptDetails> s(new ScriptDetails);
230378f339d1SEwan Crawford         s->script = address;
230478f339d1SEwan Crawford         m_scripts.push_back(std::move(s));
2305d10ca9deSEwan Crawford         return m_scripts.back().get();
230678f339d1SEwan Crawford     }
230778f339d1SEwan Crawford     return nullptr;
230878f339d1SEwan Crawford }
230978f339d1SEwan Crawford 
231078f339d1SEwan Crawford RenderScriptRuntime::AllocationDetails*
231178f339d1SEwan Crawford RenderScriptRuntime::LookUpAllocation(addr_t address, bool create)
231278f339d1SEwan Crawford {
231378f339d1SEwan Crawford     for (const auto & a : m_allocations)
231478f339d1SEwan Crawford     {
231578f339d1SEwan Crawford         if (a->address.isValid())
231678f339d1SEwan Crawford             if (*a->address == address)
231778f339d1SEwan Crawford                 return a.get();
231878f339d1SEwan Crawford     }
231978f339d1SEwan Crawford     if (create)
232078f339d1SEwan Crawford     {
232178f339d1SEwan Crawford         std::unique_ptr<AllocationDetails> a(new AllocationDetails);
232278f339d1SEwan Crawford         a->address = address;
232378f339d1SEwan Crawford         m_allocations.push_back(std::move(a));
2324d10ca9deSEwan Crawford         return m_allocations.back().get();
232578f339d1SEwan Crawford     }
232678f339d1SEwan Crawford     return nullptr;
232778f339d1SEwan Crawford }
232878f339d1SEwan Crawford 
23295ec532a9SColin Riley void
23305ec532a9SColin Riley RSModuleDescriptor::Dump(Stream &strm) const
23315ec532a9SColin Riley {
23325ec532a9SColin Riley     strm.Indent();
23335ec532a9SColin Riley     m_module->GetFileSpec().Dump(&strm);
23344640cde1SColin Riley     if(m_module->GetNumCompileUnits())
23354640cde1SColin Riley     {
23364640cde1SColin Riley         strm.Indent("Debug info loaded.");
23374640cde1SColin Riley     }
23384640cde1SColin Riley     else
23394640cde1SColin Riley     {
23404640cde1SColin Riley         strm.Indent("Debug info does not exist.");
23414640cde1SColin Riley     }
23425ec532a9SColin Riley     strm.EOL();
23435ec532a9SColin Riley     strm.IndentMore();
23445ec532a9SColin Riley     strm.Indent();
2345189598edSColin Riley     strm.Printf("Globals: %" PRIu64, static_cast<uint64_t>(m_globals.size()));
23465ec532a9SColin Riley     strm.EOL();
23475ec532a9SColin Riley     strm.IndentMore();
23485ec532a9SColin Riley     for (const auto &global : m_globals)
23495ec532a9SColin Riley     {
23505ec532a9SColin Riley         global.Dump(strm);
23515ec532a9SColin Riley     }
23525ec532a9SColin Riley     strm.IndentLess();
23535ec532a9SColin Riley     strm.Indent();
2354189598edSColin Riley     strm.Printf("Kernels: %" PRIu64, static_cast<uint64_t>(m_kernels.size()));
23555ec532a9SColin Riley     strm.EOL();
23565ec532a9SColin Riley     strm.IndentMore();
23575ec532a9SColin Riley     for (const auto &kernel : m_kernels)
23585ec532a9SColin Riley     {
23595ec532a9SColin Riley         kernel.Dump(strm);
23605ec532a9SColin Riley     }
23614640cde1SColin Riley     strm.Printf("Pragmas: %"  PRIu64 , static_cast<uint64_t>(m_pragmas.size()));
23624640cde1SColin Riley     strm.EOL();
23634640cde1SColin Riley     strm.IndentMore();
23644640cde1SColin Riley     for (const auto &key_val : m_pragmas)
23654640cde1SColin Riley     {
23664640cde1SColin Riley         strm.Printf("%s: %s", key_val.first.c_str(), key_val.second.c_str());
23674640cde1SColin Riley         strm.EOL();
23684640cde1SColin Riley     }
23695ec532a9SColin Riley     strm.IndentLess(4);
23705ec532a9SColin Riley }
23715ec532a9SColin Riley 
23725ec532a9SColin Riley void
23735ec532a9SColin Riley RSGlobalDescriptor::Dump(Stream &strm) const
23745ec532a9SColin Riley {
23755ec532a9SColin Riley     strm.Indent(m_name.AsCString());
23764640cde1SColin Riley     VariableList var_list;
23774640cde1SColin Riley     m_module->m_module->FindGlobalVariables(m_name, nullptr, true, 1U, var_list);
23784640cde1SColin Riley     if (var_list.GetSize() == 1)
23794640cde1SColin Riley     {
23804640cde1SColin Riley         auto var = var_list.GetVariableAtIndex(0);
23814640cde1SColin Riley         auto type = var->GetType();
23824640cde1SColin Riley         if(type)
23834640cde1SColin Riley         {
23844640cde1SColin Riley             strm.Printf(" - ");
23854640cde1SColin Riley             type->DumpTypeName(&strm);
23864640cde1SColin Riley         }
23874640cde1SColin Riley         else
23884640cde1SColin Riley         {
23894640cde1SColin Riley             strm.Printf(" - Unknown Type");
23904640cde1SColin Riley         }
23914640cde1SColin Riley     }
23924640cde1SColin Riley     else
23934640cde1SColin Riley     {
23944640cde1SColin Riley         strm.Printf(" - variable identified, but not found in binary");
23954640cde1SColin Riley         const Symbol* s = m_module->m_module->FindFirstSymbolWithNameAndType(m_name, eSymbolTypeData);
23964640cde1SColin Riley         if (s)
23974640cde1SColin Riley         {
23984640cde1SColin Riley             strm.Printf(" (symbol exists) ");
23994640cde1SColin Riley         }
24004640cde1SColin Riley     }
24014640cde1SColin Riley 
24025ec532a9SColin Riley     strm.EOL();
24035ec532a9SColin Riley }
24045ec532a9SColin Riley 
24055ec532a9SColin Riley void
24065ec532a9SColin Riley RSKernelDescriptor::Dump(Stream &strm) const
24075ec532a9SColin Riley {
24085ec532a9SColin Riley     strm.Indent(m_name.AsCString());
24095ec532a9SColin Riley     strm.EOL();
24105ec532a9SColin Riley }
24115ec532a9SColin Riley 
24125ec532a9SColin Riley class CommandObjectRenderScriptRuntimeModuleProbe : public CommandObjectParsed
24135ec532a9SColin Riley {
24145ec532a9SColin Riley   private:
24155ec532a9SColin Riley   public:
24165ec532a9SColin Riley     CommandObjectRenderScriptRuntimeModuleProbe(CommandInterpreter &interpreter)
24175ec532a9SColin Riley         : CommandObjectParsed(interpreter, "renderscript module probe",
24185ec532a9SColin Riley                               "Initiates a Probe of all loaded modules for kernels and other renderscript objects.",
24195ec532a9SColin Riley                               "renderscript module probe",
2420e87764f2SEnrico Granata                               eCommandRequiresTarget | eCommandRequiresProcess | eCommandProcessMustBeLaunched)
24215ec532a9SColin Riley     {
24225ec532a9SColin Riley     }
24235ec532a9SColin Riley 
24245ec532a9SColin Riley     ~CommandObjectRenderScriptRuntimeModuleProbe() {}
24255ec532a9SColin Riley 
24265ec532a9SColin Riley     bool
24275ec532a9SColin Riley     DoExecute(Args &command, CommandReturnObject &result)
24285ec532a9SColin Riley     {
24295ec532a9SColin Riley         const size_t argc = command.GetArgumentCount();
24305ec532a9SColin Riley         if (argc == 0)
24315ec532a9SColin Riley         {
24325ec532a9SColin Riley             Target *target = m_exe_ctx.GetTargetPtr();
24335ec532a9SColin Riley             RenderScriptRuntime *runtime =
24345ec532a9SColin Riley                 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
24355ec532a9SColin Riley             auto module_list = target->GetImages();
24365ec532a9SColin Riley             bool new_rs_details = runtime->ProbeModules(module_list);
24375ec532a9SColin Riley             if (new_rs_details)
24385ec532a9SColin Riley             {
24395ec532a9SColin Riley                 result.AppendMessage("New renderscript modules added to runtime model.");
24405ec532a9SColin Riley             }
24415ec532a9SColin Riley             result.SetStatus(eReturnStatusSuccessFinishResult);
24425ec532a9SColin Riley             return true;
24435ec532a9SColin Riley         }
24445ec532a9SColin Riley 
24455ec532a9SColin Riley         result.AppendErrorWithFormat("'%s' takes no arguments", m_cmd_name.c_str());
24465ec532a9SColin Riley         result.SetStatus(eReturnStatusFailed);
24475ec532a9SColin Riley         return false;
24485ec532a9SColin Riley     }
24495ec532a9SColin Riley };
24505ec532a9SColin Riley 
24515ec532a9SColin Riley class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed
24525ec532a9SColin Riley {
24535ec532a9SColin Riley   private:
24545ec532a9SColin Riley   public:
24555ec532a9SColin Riley     CommandObjectRenderScriptRuntimeModuleDump(CommandInterpreter &interpreter)
24565ec532a9SColin Riley         : CommandObjectParsed(interpreter, "renderscript module dump",
24575ec532a9SColin Riley                               "Dumps renderscript specific information for all modules.", "renderscript module dump",
2458e87764f2SEnrico Granata                               eCommandRequiresProcess | eCommandProcessMustBeLaunched)
24595ec532a9SColin Riley     {
24605ec532a9SColin Riley     }
24615ec532a9SColin Riley 
24625ec532a9SColin Riley     ~CommandObjectRenderScriptRuntimeModuleDump() {}
24635ec532a9SColin Riley 
24645ec532a9SColin Riley     bool
24655ec532a9SColin Riley     DoExecute(Args &command, CommandReturnObject &result)
24665ec532a9SColin Riley     {
24675ec532a9SColin Riley         RenderScriptRuntime *runtime =
24685ec532a9SColin Riley             (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
24695ec532a9SColin Riley         runtime->DumpModules(result.GetOutputStream());
24705ec532a9SColin Riley         result.SetStatus(eReturnStatusSuccessFinishResult);
24715ec532a9SColin Riley         return true;
24725ec532a9SColin Riley     }
24735ec532a9SColin Riley };
24745ec532a9SColin Riley 
24755ec532a9SColin Riley class CommandObjectRenderScriptRuntimeModule : public CommandObjectMultiword
24765ec532a9SColin Riley {
24775ec532a9SColin Riley   private:
24785ec532a9SColin Riley   public:
24795ec532a9SColin Riley     CommandObjectRenderScriptRuntimeModule(CommandInterpreter &interpreter)
24805ec532a9SColin Riley         : CommandObjectMultiword(interpreter, "renderscript module", "Commands that deal with renderscript modules.",
24815ec532a9SColin Riley                                  NULL)
24825ec532a9SColin Riley     {
24835ec532a9SColin Riley         LoadSubCommand("probe", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleProbe(interpreter)));
24845ec532a9SColin Riley         LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleDump(interpreter)));
24855ec532a9SColin Riley     }
24865ec532a9SColin Riley 
24875ec532a9SColin Riley     ~CommandObjectRenderScriptRuntimeModule() {}
24885ec532a9SColin Riley };
24895ec532a9SColin Riley 
24904640cde1SColin Riley class CommandObjectRenderScriptRuntimeKernelList : public CommandObjectParsed
24914640cde1SColin Riley {
24924640cde1SColin Riley   private:
24934640cde1SColin Riley   public:
24944640cde1SColin Riley     CommandObjectRenderScriptRuntimeKernelList(CommandInterpreter &interpreter)
24954640cde1SColin Riley         : CommandObjectParsed(interpreter, "renderscript kernel list",
24964640cde1SColin Riley                               "Lists renderscript kernel names and associated script resources.", "renderscript kernel list",
24974640cde1SColin Riley                               eCommandRequiresProcess | eCommandProcessMustBeLaunched)
24984640cde1SColin Riley     {
24994640cde1SColin Riley     }
25004640cde1SColin Riley 
25014640cde1SColin Riley     ~CommandObjectRenderScriptRuntimeKernelList() {}
25024640cde1SColin Riley 
25034640cde1SColin Riley     bool
25044640cde1SColin Riley     DoExecute(Args &command, CommandReturnObject &result)
25054640cde1SColin Riley     {
25064640cde1SColin Riley         RenderScriptRuntime *runtime =
25074640cde1SColin Riley             (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
25084640cde1SColin Riley         runtime->DumpKernels(result.GetOutputStream());
25094640cde1SColin Riley         result.SetStatus(eReturnStatusSuccessFinishResult);
25104640cde1SColin Riley         return true;
25114640cde1SColin Riley     }
25124640cde1SColin Riley };
25134640cde1SColin Riley 
25147dc7771cSEwan Crawford class CommandObjectRenderScriptRuntimeKernelBreakpointSet : public CommandObjectParsed
25154640cde1SColin Riley {
25164640cde1SColin Riley   private:
25174640cde1SColin Riley   public:
25187dc7771cSEwan Crawford     CommandObjectRenderScriptRuntimeKernelBreakpointSet(CommandInterpreter &interpreter)
25197dc7771cSEwan Crawford         : CommandObjectParsed(interpreter, "renderscript kernel breakpoint set",
25207dc7771cSEwan Crawford                               "Sets a breakpoint on a renderscript kernel.", "renderscript kernel breakpoint set <kernel_name>",
25214640cde1SColin Riley                               eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused)
25224640cde1SColin Riley     {
25234640cde1SColin Riley     }
25244640cde1SColin Riley 
25257dc7771cSEwan Crawford     ~CommandObjectRenderScriptRuntimeKernelBreakpointSet() {}
25264640cde1SColin Riley 
25274640cde1SColin Riley     bool
25284640cde1SColin Riley     DoExecute(Args &command, CommandReturnObject &result)
25294640cde1SColin Riley     {
25304640cde1SColin Riley         const size_t argc = command.GetArgumentCount();
25314640cde1SColin Riley         if (argc == 1)
25324640cde1SColin Riley         {
25334640cde1SColin Riley             RenderScriptRuntime *runtime =
25344640cde1SColin Riley                 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
25354640cde1SColin Riley 
25364640cde1SColin Riley             Error error;
253798156583SEwan Crawford             runtime->AttemptBreakpointAtKernelName(result.GetOutputStream(), command.GetArgumentAtIndex(0),
253898156583SEwan Crawford                                                    error, m_exe_ctx.GetTargetSP());
25394640cde1SColin Riley 
25404640cde1SColin Riley             if (error.Success())
25414640cde1SColin Riley             {
25424640cde1SColin Riley                 result.AppendMessage("Breakpoint(s) created");
25434640cde1SColin Riley                 result.SetStatus(eReturnStatusSuccessFinishResult);
25444640cde1SColin Riley                 return true;
25454640cde1SColin Riley             }
25464640cde1SColin Riley             result.SetStatus(eReturnStatusFailed);
25474640cde1SColin Riley             result.AppendErrorWithFormat("Error: %s", error.AsCString());
25484640cde1SColin Riley             return false;
25494640cde1SColin Riley         }
25504640cde1SColin Riley 
25514640cde1SColin Riley         result.AppendErrorWithFormat("'%s' takes 1 argument of kernel name", m_cmd_name.c_str());
25524640cde1SColin Riley         result.SetStatus(eReturnStatusFailed);
25534640cde1SColin Riley         return false;
25544640cde1SColin Riley     }
25554640cde1SColin Riley };
25564640cde1SColin Riley 
25577dc7771cSEwan Crawford class CommandObjectRenderScriptRuntimeKernelBreakpointAll : public CommandObjectParsed
25587dc7771cSEwan Crawford {
25597dc7771cSEwan Crawford   private:
25607dc7771cSEwan Crawford   public:
25617dc7771cSEwan Crawford     CommandObjectRenderScriptRuntimeKernelBreakpointAll(CommandInterpreter &interpreter)
25627dc7771cSEwan Crawford         : CommandObjectParsed(interpreter, "renderscript kernel breakpoint all",
25637dc7771cSEwan Crawford                               "Automatically sets a breakpoint on all renderscript kernels that are or will be loaded.\n"
25647dc7771cSEwan Crawford                               "Disabling option means breakpoints will no longer be set on any kernels loaded in the future, "
25657dc7771cSEwan Crawford                               "but does not remove currently set breakpoints.",
25667dc7771cSEwan Crawford                               "renderscript kernel breakpoint all <enable/disable>",
25677dc7771cSEwan Crawford                               eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused)
25687dc7771cSEwan Crawford     {
25697dc7771cSEwan Crawford     }
25707dc7771cSEwan Crawford 
25717dc7771cSEwan Crawford     ~CommandObjectRenderScriptRuntimeKernelBreakpointAll() {}
25727dc7771cSEwan Crawford 
25737dc7771cSEwan Crawford     bool
25747dc7771cSEwan Crawford     DoExecute(Args &command, CommandReturnObject &result)
25757dc7771cSEwan Crawford     {
25767dc7771cSEwan Crawford         const size_t argc = command.GetArgumentCount();
25777dc7771cSEwan Crawford         if (argc != 1)
25787dc7771cSEwan Crawford         {
25797dc7771cSEwan Crawford             result.AppendErrorWithFormat("'%s' takes 1 argument of 'enable' or 'disable'", m_cmd_name.c_str());
25807dc7771cSEwan Crawford             result.SetStatus(eReturnStatusFailed);
25817dc7771cSEwan Crawford             return false;
25827dc7771cSEwan Crawford         }
25837dc7771cSEwan Crawford 
25847dc7771cSEwan Crawford         RenderScriptRuntime *runtime =
25857dc7771cSEwan Crawford           static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
25867dc7771cSEwan Crawford 
25877dc7771cSEwan Crawford         bool do_break = false;
25887dc7771cSEwan Crawford         const char* argument = command.GetArgumentAtIndex(0);
25897dc7771cSEwan Crawford         if (strcmp(argument, "enable") == 0)
25907dc7771cSEwan Crawford         {
25917dc7771cSEwan Crawford             do_break = true;
25927dc7771cSEwan Crawford             result.AppendMessage("Breakpoints will be set on all kernels.");
25937dc7771cSEwan Crawford         }
25947dc7771cSEwan Crawford         else if (strcmp(argument, "disable") == 0)
25957dc7771cSEwan Crawford         {
25967dc7771cSEwan Crawford             do_break = false;
25977dc7771cSEwan Crawford             result.AppendMessage("Breakpoints will not be set on any new kernels.");
25987dc7771cSEwan Crawford         }
25997dc7771cSEwan Crawford         else
26007dc7771cSEwan Crawford         {
26017dc7771cSEwan Crawford             result.AppendErrorWithFormat("Argument must be either 'enable' or 'disable'");
26027dc7771cSEwan Crawford             result.SetStatus(eReturnStatusFailed);
26037dc7771cSEwan Crawford             return false;
26047dc7771cSEwan Crawford         }
26057dc7771cSEwan Crawford 
26067dc7771cSEwan Crawford         runtime->SetBreakAllKernels(do_break, m_exe_ctx.GetTargetSP());
26077dc7771cSEwan Crawford 
26087dc7771cSEwan Crawford         result.SetStatus(eReturnStatusSuccessFinishResult);
26097dc7771cSEwan Crawford         return true;
26107dc7771cSEwan Crawford     }
26117dc7771cSEwan Crawford };
26127dc7771cSEwan Crawford 
26137dc7771cSEwan Crawford class CommandObjectRenderScriptRuntimeKernelBreakpoint : public CommandObjectMultiword
26147dc7771cSEwan Crawford {
26157dc7771cSEwan Crawford   private:
26167dc7771cSEwan Crawford   public:
26177dc7771cSEwan Crawford     CommandObjectRenderScriptRuntimeKernelBreakpoint(CommandInterpreter &interpreter)
26187dc7771cSEwan Crawford         : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that generate breakpoints on renderscript kernels.",
26197dc7771cSEwan Crawford                                  nullptr)
26207dc7771cSEwan Crawford     {
26217dc7771cSEwan Crawford         LoadSubCommand("set", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointSet(interpreter)));
26227dc7771cSEwan Crawford         LoadSubCommand("all", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointAll(interpreter)));
26237dc7771cSEwan Crawford     }
26247dc7771cSEwan Crawford 
26257dc7771cSEwan Crawford     ~CommandObjectRenderScriptRuntimeKernelBreakpoint() {}
26267dc7771cSEwan Crawford };
26277dc7771cSEwan Crawford 
26284640cde1SColin Riley class CommandObjectRenderScriptRuntimeKernel : public CommandObjectMultiword
26294640cde1SColin Riley {
26304640cde1SColin Riley   private:
26314640cde1SColin Riley   public:
26324640cde1SColin Riley     CommandObjectRenderScriptRuntimeKernel(CommandInterpreter &interpreter)
26334640cde1SColin Riley         : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that deal with renderscript kernels.",
26344640cde1SColin Riley                                  NULL)
26354640cde1SColin Riley     {
26364640cde1SColin Riley         LoadSubCommand("list", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelList(interpreter)));
26374640cde1SColin Riley         LoadSubCommand("breakpoint", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpoint(interpreter)));
26384640cde1SColin Riley     }
26394640cde1SColin Riley 
26404640cde1SColin Riley     ~CommandObjectRenderScriptRuntimeKernel() {}
26414640cde1SColin Riley };
26424640cde1SColin Riley 
26434640cde1SColin Riley class CommandObjectRenderScriptRuntimeContextDump : public CommandObjectParsed
26444640cde1SColin Riley {
26454640cde1SColin Riley   private:
26464640cde1SColin Riley   public:
26474640cde1SColin Riley     CommandObjectRenderScriptRuntimeContextDump(CommandInterpreter &interpreter)
26484640cde1SColin Riley         : CommandObjectParsed(interpreter, "renderscript context dump",
26494640cde1SColin Riley                               "Dumps renderscript context information.", "renderscript context dump",
26504640cde1SColin Riley                               eCommandRequiresProcess | eCommandProcessMustBeLaunched)
26514640cde1SColin Riley     {
26524640cde1SColin Riley     }
26534640cde1SColin Riley 
26544640cde1SColin Riley     ~CommandObjectRenderScriptRuntimeContextDump() {}
26554640cde1SColin Riley 
26564640cde1SColin Riley     bool
26574640cde1SColin Riley     DoExecute(Args &command, CommandReturnObject &result)
26584640cde1SColin Riley     {
26594640cde1SColin Riley         RenderScriptRuntime *runtime =
26604640cde1SColin Riley             (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
26614640cde1SColin Riley         runtime->DumpContexts(result.GetOutputStream());
26624640cde1SColin Riley         result.SetStatus(eReturnStatusSuccessFinishResult);
26634640cde1SColin Riley         return true;
26644640cde1SColin Riley     }
26654640cde1SColin Riley };
26664640cde1SColin Riley 
26674640cde1SColin Riley class CommandObjectRenderScriptRuntimeContext : public CommandObjectMultiword
26684640cde1SColin Riley {
26694640cde1SColin Riley   private:
26704640cde1SColin Riley   public:
26714640cde1SColin Riley     CommandObjectRenderScriptRuntimeContext(CommandInterpreter &interpreter)
26724640cde1SColin Riley         : CommandObjectMultiword(interpreter, "renderscript context", "Commands that deal with renderscript contexts.",
26734640cde1SColin Riley                                  NULL)
26744640cde1SColin Riley     {
26754640cde1SColin Riley         LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeContextDump(interpreter)));
26764640cde1SColin Riley     }
26774640cde1SColin Riley 
26784640cde1SColin Riley     ~CommandObjectRenderScriptRuntimeContext() {}
26794640cde1SColin Riley };
26804640cde1SColin Riley 
2681a0f08674SEwan Crawford 
2682a0f08674SEwan Crawford class CommandObjectRenderScriptRuntimeAllocationDump : public CommandObjectParsed
2683a0f08674SEwan Crawford {
2684a0f08674SEwan Crawford   private:
2685a0f08674SEwan Crawford   public:
2686a0f08674SEwan Crawford     CommandObjectRenderScriptRuntimeAllocationDump(CommandInterpreter &interpreter)
2687a0f08674SEwan Crawford         : CommandObjectParsed(interpreter, "renderscript allocation dump",
2688a0f08674SEwan Crawford                               "Displays the contents of a particular allocation", "renderscript allocation dump <ID>",
2689a0f08674SEwan Crawford                               eCommandRequiresProcess | eCommandProcessMustBeLaunched), m_options(interpreter)
2690a0f08674SEwan Crawford     {
2691a0f08674SEwan Crawford     }
2692a0f08674SEwan Crawford 
2693a0f08674SEwan Crawford     virtual Options*
2694a0f08674SEwan Crawford     GetOptions()
2695a0f08674SEwan Crawford     {
2696a0f08674SEwan Crawford         return &m_options;
2697a0f08674SEwan Crawford     }
2698a0f08674SEwan Crawford 
2699a0f08674SEwan Crawford     class CommandOptions : public Options
2700a0f08674SEwan Crawford     {
2701a0f08674SEwan Crawford       public:
2702a0f08674SEwan Crawford         CommandOptions(CommandInterpreter &interpreter) : Options(interpreter)
2703a0f08674SEwan Crawford         {
2704a0f08674SEwan Crawford         }
2705a0f08674SEwan Crawford 
2706a0f08674SEwan Crawford         virtual
2707a0f08674SEwan Crawford         ~CommandOptions()
2708a0f08674SEwan Crawford         {
2709a0f08674SEwan Crawford         }
2710a0f08674SEwan Crawford 
2711a0f08674SEwan Crawford         virtual Error
2712a0f08674SEwan Crawford         SetOptionValue(uint32_t option_idx, const char *option_arg)
2713a0f08674SEwan Crawford         {
2714a0f08674SEwan Crawford             Error error;
2715a0f08674SEwan Crawford             const int short_option = m_getopt_table[option_idx].val;
2716a0f08674SEwan Crawford 
2717a0f08674SEwan Crawford             switch (short_option)
2718a0f08674SEwan Crawford             {
2719a0f08674SEwan Crawford                 case 'f':
2720a0f08674SEwan Crawford                     m_outfile.SetFile(option_arg, true);
2721a0f08674SEwan Crawford                     if (m_outfile.Exists())
2722a0f08674SEwan Crawford                     {
2723a0f08674SEwan Crawford                         m_outfile.Clear();
2724a0f08674SEwan Crawford                         error.SetErrorStringWithFormat("file already exists: '%s'", option_arg);
2725a0f08674SEwan Crawford                     }
2726a0f08674SEwan Crawford                     break;
2727a0f08674SEwan Crawford                 default:
2728a0f08674SEwan Crawford                     error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
2729a0f08674SEwan Crawford                     break;
2730a0f08674SEwan Crawford             }
2731a0f08674SEwan Crawford             return error;
2732a0f08674SEwan Crawford         }
2733a0f08674SEwan Crawford 
2734a0f08674SEwan Crawford         void
2735a0f08674SEwan Crawford         OptionParsingStarting()
2736a0f08674SEwan Crawford         {
2737a0f08674SEwan Crawford             m_outfile.Clear();
2738a0f08674SEwan Crawford         }
2739a0f08674SEwan Crawford 
2740a0f08674SEwan Crawford         const OptionDefinition*
2741a0f08674SEwan Crawford         GetDefinitions()
2742a0f08674SEwan Crawford         {
2743a0f08674SEwan Crawford             return g_option_table;
2744a0f08674SEwan Crawford         }
2745a0f08674SEwan Crawford 
2746a0f08674SEwan Crawford         static OptionDefinition g_option_table[];
2747a0f08674SEwan Crawford         FileSpec m_outfile;
2748a0f08674SEwan Crawford     };
2749a0f08674SEwan Crawford 
2750a0f08674SEwan Crawford     ~CommandObjectRenderScriptRuntimeAllocationDump() {}
2751a0f08674SEwan Crawford 
2752a0f08674SEwan Crawford     bool
2753a0f08674SEwan Crawford     DoExecute(Args &command, CommandReturnObject &result)
2754a0f08674SEwan Crawford     {
2755a0f08674SEwan Crawford         const size_t argc = command.GetArgumentCount();
2756a0f08674SEwan Crawford         if (argc < 1)
2757a0f08674SEwan Crawford         {
2758a0f08674SEwan Crawford             result.AppendErrorWithFormat("'%s' takes 1 argument, an allocation ID. As well as an optional -f argument",
2759a0f08674SEwan Crawford                                          m_cmd_name.c_str());
2760a0f08674SEwan Crawford             result.SetStatus(eReturnStatusFailed);
2761a0f08674SEwan Crawford             return false;
2762a0f08674SEwan Crawford         }
2763a0f08674SEwan Crawford 
2764a0f08674SEwan Crawford         RenderScriptRuntime *runtime =
2765a0f08674SEwan Crawford           static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
2766a0f08674SEwan Crawford 
2767a0f08674SEwan Crawford         const char* id_cstr = command.GetArgumentAtIndex(0);
2768a0f08674SEwan Crawford         bool convert_complete = false;
2769a0f08674SEwan Crawford         const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete);
2770a0f08674SEwan Crawford         if (!convert_complete)
2771a0f08674SEwan Crawford         {
2772a0f08674SEwan Crawford             result.AppendErrorWithFormat("invalid allocation id argument '%s'", id_cstr);
2773a0f08674SEwan Crawford             result.SetStatus(eReturnStatusFailed);
2774a0f08674SEwan Crawford             return false;
2775a0f08674SEwan Crawford         }
2776a0f08674SEwan Crawford 
2777a0f08674SEwan Crawford         Stream* output_strm = nullptr;
2778a0f08674SEwan Crawford         StreamFile outfile_stream;
2779a0f08674SEwan Crawford         const FileSpec &outfile_spec = m_options.m_outfile; // Dump allocation to file instead
2780a0f08674SEwan Crawford         if (outfile_spec)
2781a0f08674SEwan Crawford         {
2782a0f08674SEwan Crawford             // Open output file
2783a0f08674SEwan Crawford             char path[256];
2784a0f08674SEwan Crawford             outfile_spec.GetPath(path, sizeof(path));
2785a0f08674SEwan Crawford             if (outfile_stream.GetFile().Open(path, File::eOpenOptionWrite | File::eOpenOptionCanCreate).Success())
2786a0f08674SEwan Crawford             {
2787a0f08674SEwan Crawford                 output_strm = &outfile_stream;
2788a0f08674SEwan Crawford                 result.GetOutputStream().Printf("Results written to '%s'", path);
2789a0f08674SEwan Crawford                 result.GetOutputStream().EOL();
2790a0f08674SEwan Crawford             }
2791a0f08674SEwan Crawford             else
2792a0f08674SEwan Crawford             {
2793a0f08674SEwan Crawford                 result.AppendErrorWithFormat("Couldn't open file '%s'", path);
2794a0f08674SEwan Crawford                 result.SetStatus(eReturnStatusFailed);
2795a0f08674SEwan Crawford                 return false;
2796a0f08674SEwan Crawford             }
2797a0f08674SEwan Crawford         }
2798a0f08674SEwan Crawford         else
2799a0f08674SEwan Crawford             output_strm = &result.GetOutputStream();
2800a0f08674SEwan Crawford 
2801a0f08674SEwan Crawford         assert(output_strm != nullptr);
2802a0f08674SEwan Crawford         bool success = runtime->DumpAllocation(*output_strm, m_exe_ctx.GetFramePtr(), id);
2803a0f08674SEwan Crawford 
2804a0f08674SEwan Crawford         if (success)
2805a0f08674SEwan Crawford             result.SetStatus(eReturnStatusSuccessFinishResult);
2806a0f08674SEwan Crawford         else
2807a0f08674SEwan Crawford             result.SetStatus(eReturnStatusFailed);
2808a0f08674SEwan Crawford 
2809a0f08674SEwan Crawford         return true;
2810a0f08674SEwan Crawford     }
2811a0f08674SEwan Crawford 
2812a0f08674SEwan Crawford     private:
2813a0f08674SEwan Crawford         CommandOptions m_options;
2814a0f08674SEwan Crawford };
2815a0f08674SEwan Crawford 
2816a0f08674SEwan Crawford OptionDefinition
2817a0f08674SEwan Crawford CommandObjectRenderScriptRuntimeAllocationDump::CommandOptions::g_option_table[] =
2818a0f08674SEwan Crawford {
2819a0f08674SEwan Crawford     { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFilename,
2820a0f08674SEwan Crawford       "Print results to specified file instead of command line."},
2821a0f08674SEwan Crawford     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
2822a0f08674SEwan Crawford };
2823a0f08674SEwan Crawford 
2824a0f08674SEwan Crawford 
282515f2bd95SEwan Crawford class CommandObjectRenderScriptRuntimeAllocationList : public CommandObjectParsed
282615f2bd95SEwan Crawford {
282715f2bd95SEwan Crawford   public:
282815f2bd95SEwan Crawford     CommandObjectRenderScriptRuntimeAllocationList(CommandInterpreter &interpreter)
282915f2bd95SEwan Crawford         : CommandObjectParsed(interpreter, "renderscript allocation list",
283015f2bd95SEwan Crawford                               "List renderscript allocations and their information.", "renderscript allocation list",
283115f2bd95SEwan Crawford                               eCommandRequiresProcess | eCommandProcessMustBeLaunched), m_options(interpreter)
283215f2bd95SEwan Crawford     {
283315f2bd95SEwan Crawford     }
283415f2bd95SEwan Crawford 
283515f2bd95SEwan Crawford     virtual Options*
283615f2bd95SEwan Crawford     GetOptions()
283715f2bd95SEwan Crawford     {
283815f2bd95SEwan Crawford         return &m_options;
283915f2bd95SEwan Crawford     }
284015f2bd95SEwan Crawford 
284115f2bd95SEwan Crawford     class CommandOptions : public Options
284215f2bd95SEwan Crawford     {
284315f2bd95SEwan Crawford       public:
284415f2bd95SEwan Crawford         CommandOptions(CommandInterpreter &interpreter) : Options(interpreter), m_refresh(false)
284515f2bd95SEwan Crawford         {
284615f2bd95SEwan Crawford         }
284715f2bd95SEwan Crawford 
284815f2bd95SEwan Crawford         virtual
284915f2bd95SEwan Crawford         ~CommandOptions()
285015f2bd95SEwan Crawford         {
285115f2bd95SEwan Crawford         }
285215f2bd95SEwan Crawford 
285315f2bd95SEwan Crawford         virtual Error
285415f2bd95SEwan Crawford         SetOptionValue(uint32_t option_idx, const char *option_arg)
285515f2bd95SEwan Crawford         {
285615f2bd95SEwan Crawford             Error error;
285715f2bd95SEwan Crawford             const int short_option = m_getopt_table[option_idx].val;
285815f2bd95SEwan Crawford 
285915f2bd95SEwan Crawford             switch (short_option)
286015f2bd95SEwan Crawford             {
286115f2bd95SEwan Crawford                 case 'r':
286215f2bd95SEwan Crawford                     m_refresh = true;
286315f2bd95SEwan Crawford                     break;
286415f2bd95SEwan Crawford                 default:
286515f2bd95SEwan Crawford                     error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
286615f2bd95SEwan Crawford                     break;
286715f2bd95SEwan Crawford             }
286815f2bd95SEwan Crawford             return error;
286915f2bd95SEwan Crawford         }
287015f2bd95SEwan Crawford 
287115f2bd95SEwan Crawford         void
287215f2bd95SEwan Crawford         OptionParsingStarting()
287315f2bd95SEwan Crawford         {
287415f2bd95SEwan Crawford             m_refresh = false;
287515f2bd95SEwan Crawford         }
287615f2bd95SEwan Crawford 
287715f2bd95SEwan Crawford         const OptionDefinition*
287815f2bd95SEwan Crawford         GetDefinitions()
287915f2bd95SEwan Crawford         {
288015f2bd95SEwan Crawford             return g_option_table;
288115f2bd95SEwan Crawford         }
288215f2bd95SEwan Crawford 
288315f2bd95SEwan Crawford         static OptionDefinition g_option_table[];
288415f2bd95SEwan Crawford         bool m_refresh;
288515f2bd95SEwan Crawford     };
288615f2bd95SEwan Crawford 
288715f2bd95SEwan Crawford     ~CommandObjectRenderScriptRuntimeAllocationList() {}
288815f2bd95SEwan Crawford 
288915f2bd95SEwan Crawford     bool
289015f2bd95SEwan Crawford     DoExecute(Args &command, CommandReturnObject &result)
289115f2bd95SEwan Crawford     {
289215f2bd95SEwan Crawford         RenderScriptRuntime *runtime =
289315f2bd95SEwan Crawford           static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
289415f2bd95SEwan Crawford         runtime->ListAllocations(result.GetOutputStream(), m_exe_ctx.GetFramePtr(), m_options.m_refresh);
289515f2bd95SEwan Crawford         result.SetStatus(eReturnStatusSuccessFinishResult);
289615f2bd95SEwan Crawford         return true;
289715f2bd95SEwan Crawford     }
289815f2bd95SEwan Crawford 
289915f2bd95SEwan Crawford   private:
290015f2bd95SEwan Crawford     CommandOptions m_options;
290115f2bd95SEwan Crawford };
290215f2bd95SEwan Crawford 
290315f2bd95SEwan Crawford OptionDefinition
290415f2bd95SEwan Crawford CommandObjectRenderScriptRuntimeAllocationList::CommandOptions::g_option_table[] =
290515f2bd95SEwan Crawford {
290615f2bd95SEwan Crawford     { LLDB_OPT_SET_1, false, "refresh", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
290715f2bd95SEwan Crawford       "Recompute allocation details."},
290815f2bd95SEwan Crawford     { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
290915f2bd95SEwan Crawford };
291015f2bd95SEwan Crawford 
291115f2bd95SEwan Crawford 
291255232f09SEwan Crawford class CommandObjectRenderScriptRuntimeAllocationLoad : public CommandObjectParsed
291355232f09SEwan Crawford {
291455232f09SEwan Crawford   private:
291555232f09SEwan Crawford   public:
291655232f09SEwan Crawford     CommandObjectRenderScriptRuntimeAllocationLoad(CommandInterpreter &interpreter)
291755232f09SEwan Crawford         : CommandObjectParsed(interpreter, "renderscript allocation load",
291855232f09SEwan Crawford                               "Loads renderscript allocation contents from a file.", "renderscript allocation load <ID> <filename>",
291955232f09SEwan Crawford                               eCommandRequiresProcess | eCommandProcessMustBeLaunched)
292055232f09SEwan Crawford     {
292155232f09SEwan Crawford     }
292255232f09SEwan Crawford 
292355232f09SEwan Crawford     ~CommandObjectRenderScriptRuntimeAllocationLoad() {}
292455232f09SEwan Crawford 
292555232f09SEwan Crawford     bool
292655232f09SEwan Crawford     DoExecute(Args &command, CommandReturnObject &result)
292755232f09SEwan Crawford     {
292855232f09SEwan Crawford         const size_t argc = command.GetArgumentCount();
292955232f09SEwan Crawford         if (argc != 2)
293055232f09SEwan Crawford         {
293155232f09SEwan Crawford             result.AppendErrorWithFormat("'%s' takes 2 arguments, an allocation ID and filename to read from.", m_cmd_name.c_str());
293255232f09SEwan Crawford             result.SetStatus(eReturnStatusFailed);
293355232f09SEwan Crawford             return false;
293455232f09SEwan Crawford         }
293555232f09SEwan Crawford 
293655232f09SEwan Crawford         RenderScriptRuntime *runtime =
293755232f09SEwan Crawford           static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
293855232f09SEwan Crawford 
293955232f09SEwan Crawford         const char* id_cstr = command.GetArgumentAtIndex(0);
294055232f09SEwan Crawford         bool convert_complete = false;
294155232f09SEwan Crawford         const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete);
294255232f09SEwan Crawford         if (!convert_complete)
294355232f09SEwan Crawford         {
294455232f09SEwan Crawford             result.AppendErrorWithFormat ("invalid allocation id argument '%s'", id_cstr);
294555232f09SEwan Crawford             result.SetStatus (eReturnStatusFailed);
294655232f09SEwan Crawford             return false;
294755232f09SEwan Crawford         }
294855232f09SEwan Crawford 
294955232f09SEwan Crawford         const char* filename = command.GetArgumentAtIndex(1);
295055232f09SEwan Crawford         bool success = runtime->LoadAllocation(result.GetOutputStream(), id, filename, m_exe_ctx.GetFramePtr());
295155232f09SEwan Crawford 
295255232f09SEwan Crawford         if (success)
295355232f09SEwan Crawford             result.SetStatus(eReturnStatusSuccessFinishResult);
295455232f09SEwan Crawford         else
295555232f09SEwan Crawford             result.SetStatus(eReturnStatusFailed);
295655232f09SEwan Crawford 
295755232f09SEwan Crawford         return true;
295855232f09SEwan Crawford     }
295955232f09SEwan Crawford };
296055232f09SEwan Crawford 
296155232f09SEwan Crawford 
296255232f09SEwan Crawford class CommandObjectRenderScriptRuntimeAllocationSave : public CommandObjectParsed
296355232f09SEwan Crawford {
296455232f09SEwan Crawford   private:
296555232f09SEwan Crawford   public:
296655232f09SEwan Crawford     CommandObjectRenderScriptRuntimeAllocationSave(CommandInterpreter &interpreter)
296755232f09SEwan Crawford         : CommandObjectParsed(interpreter, "renderscript allocation save",
296855232f09SEwan Crawford                               "Write renderscript allocation contents to a file.", "renderscript allocation save <ID> <filename>",
296955232f09SEwan Crawford                               eCommandRequiresProcess | eCommandProcessMustBeLaunched)
297055232f09SEwan Crawford     {
297155232f09SEwan Crawford     }
297255232f09SEwan Crawford 
297355232f09SEwan Crawford     ~CommandObjectRenderScriptRuntimeAllocationSave() {}
297455232f09SEwan Crawford 
297555232f09SEwan Crawford     bool
297655232f09SEwan Crawford     DoExecute(Args &command, CommandReturnObject &result)
297755232f09SEwan Crawford     {
297855232f09SEwan Crawford         const size_t argc = command.GetArgumentCount();
297955232f09SEwan Crawford         if (argc != 2)
298055232f09SEwan Crawford         {
298155232f09SEwan Crawford             result.AppendErrorWithFormat("'%s' takes 2 arguments, an allocation ID and filename to read from.", m_cmd_name.c_str());
298255232f09SEwan Crawford             result.SetStatus(eReturnStatusFailed);
298355232f09SEwan Crawford             return false;
298455232f09SEwan Crawford         }
298555232f09SEwan Crawford 
298655232f09SEwan Crawford         RenderScriptRuntime *runtime =
298755232f09SEwan Crawford           static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
298855232f09SEwan Crawford 
298955232f09SEwan Crawford         const char* id_cstr = command.GetArgumentAtIndex(0);
299055232f09SEwan Crawford         bool convert_complete = false;
299155232f09SEwan Crawford         const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete);
299255232f09SEwan Crawford         if (!convert_complete)
299355232f09SEwan Crawford         {
299455232f09SEwan Crawford             result.AppendErrorWithFormat ("invalid allocation id argument '%s'", id_cstr);
299555232f09SEwan Crawford             result.SetStatus (eReturnStatusFailed);
299655232f09SEwan Crawford             return false;
299755232f09SEwan Crawford         }
299855232f09SEwan Crawford 
299955232f09SEwan Crawford         const char* filename = command.GetArgumentAtIndex(1);
300055232f09SEwan Crawford         bool success = runtime->SaveAllocation(result.GetOutputStream(), id, filename, m_exe_ctx.GetFramePtr());
300155232f09SEwan Crawford 
300255232f09SEwan Crawford         if (success)
300355232f09SEwan Crawford             result.SetStatus(eReturnStatusSuccessFinishResult);
300455232f09SEwan Crawford         else
300555232f09SEwan Crawford             result.SetStatus(eReturnStatusFailed);
300655232f09SEwan Crawford 
300755232f09SEwan Crawford         return true;
300855232f09SEwan Crawford     }
300955232f09SEwan Crawford };
301055232f09SEwan Crawford 
301115f2bd95SEwan Crawford class CommandObjectRenderScriptRuntimeAllocation : public CommandObjectMultiword
301215f2bd95SEwan Crawford {
301315f2bd95SEwan Crawford   private:
301415f2bd95SEwan Crawford   public:
301515f2bd95SEwan Crawford     CommandObjectRenderScriptRuntimeAllocation(CommandInterpreter &interpreter)
301615f2bd95SEwan Crawford         : CommandObjectMultiword(interpreter, "renderscript allocation", "Commands that deal with renderscript allocations.",
301715f2bd95SEwan Crawford                                  NULL)
301815f2bd95SEwan Crawford     {
301915f2bd95SEwan Crawford         LoadSubCommand("list", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationList(interpreter)));
3020a0f08674SEwan Crawford         LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationDump(interpreter)));
302155232f09SEwan Crawford         LoadSubCommand("save", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationSave(interpreter)));
302255232f09SEwan Crawford         LoadSubCommand("load", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationLoad(interpreter)));
302315f2bd95SEwan Crawford     }
302415f2bd95SEwan Crawford 
302515f2bd95SEwan Crawford     ~CommandObjectRenderScriptRuntimeAllocation() {}
302615f2bd95SEwan Crawford };
302715f2bd95SEwan Crawford 
302815f2bd95SEwan Crawford 
30294640cde1SColin Riley class CommandObjectRenderScriptRuntimeStatus : public CommandObjectParsed
30304640cde1SColin Riley {
30314640cde1SColin Riley   private:
30324640cde1SColin Riley   public:
30334640cde1SColin Riley     CommandObjectRenderScriptRuntimeStatus(CommandInterpreter &interpreter)
30344640cde1SColin Riley         : CommandObjectParsed(interpreter, "renderscript status",
30354640cde1SColin Riley                               "Displays current renderscript runtime status.", "renderscript status",
30364640cde1SColin Riley                               eCommandRequiresProcess | eCommandProcessMustBeLaunched)
30374640cde1SColin Riley     {
30384640cde1SColin Riley     }
30394640cde1SColin Riley 
30404640cde1SColin Riley     ~CommandObjectRenderScriptRuntimeStatus() {}
30414640cde1SColin Riley 
30424640cde1SColin Riley     bool
30434640cde1SColin Riley     DoExecute(Args &command, CommandReturnObject &result)
30444640cde1SColin Riley     {
30454640cde1SColin Riley         RenderScriptRuntime *runtime =
30464640cde1SColin Riley             (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
30474640cde1SColin Riley         runtime->Status(result.GetOutputStream());
30484640cde1SColin Riley         result.SetStatus(eReturnStatusSuccessFinishResult);
30494640cde1SColin Riley         return true;
30504640cde1SColin Riley     }
30514640cde1SColin Riley };
30524640cde1SColin Riley 
30535ec532a9SColin Riley class CommandObjectRenderScriptRuntime : public CommandObjectMultiword
30545ec532a9SColin Riley {
30555ec532a9SColin Riley   public:
30565ec532a9SColin Riley     CommandObjectRenderScriptRuntime(CommandInterpreter &interpreter)
30575ec532a9SColin Riley         : CommandObjectMultiword(interpreter, "renderscript", "A set of commands for operating on renderscript.",
30585ec532a9SColin Riley                                  "renderscript <subcommand> [<subcommand-options>]")
30595ec532a9SColin Riley     {
30605ec532a9SColin Riley         LoadSubCommand("module", CommandObjectSP(new CommandObjectRenderScriptRuntimeModule(interpreter)));
30614640cde1SColin Riley         LoadSubCommand("status", CommandObjectSP(new CommandObjectRenderScriptRuntimeStatus(interpreter)));
30624640cde1SColin Riley         LoadSubCommand("kernel", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernel(interpreter)));
30634640cde1SColin Riley         LoadSubCommand("context", CommandObjectSP(new CommandObjectRenderScriptRuntimeContext(interpreter)));
306415f2bd95SEwan Crawford         LoadSubCommand("allocation", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocation(interpreter)));
30655ec532a9SColin Riley     }
30665ec532a9SColin Riley 
30675ec532a9SColin Riley     ~CommandObjectRenderScriptRuntime() {}
30685ec532a9SColin Riley };
3069ef20b08fSColin Riley 
3070ef20b08fSColin Riley void
3071ef20b08fSColin Riley RenderScriptRuntime::Initiate()
30725ec532a9SColin Riley {
3073ef20b08fSColin Riley     assert(!m_initiated);
30745ec532a9SColin Riley }
3075ef20b08fSColin Riley 
3076ef20b08fSColin Riley RenderScriptRuntime::RenderScriptRuntime(Process *process)
30777dc7771cSEwan Crawford     : lldb_private::CPPLanguageRuntime(process), m_initiated(false), m_debuggerPresentFlagged(false),
30787dc7771cSEwan Crawford       m_breakAllKernels(false)
3079ef20b08fSColin Riley {
30804640cde1SColin Riley     ModulesDidLoad(process->GetTarget().GetImages());
3081ef20b08fSColin Riley }
30824640cde1SColin Riley 
30834640cde1SColin Riley lldb::CommandObjectSP
30844640cde1SColin Riley RenderScriptRuntime::GetCommandObject(lldb_private::CommandInterpreter& interpreter)
30854640cde1SColin Riley {
30864640cde1SColin Riley     static CommandObjectSP command_object;
30874640cde1SColin Riley     if(!command_object)
30884640cde1SColin Riley     {
30894640cde1SColin Riley         command_object.reset(new CommandObjectRenderScriptRuntime(interpreter));
30904640cde1SColin Riley     }
30914640cde1SColin Riley     return command_object;
30924640cde1SColin Riley }
30934640cde1SColin Riley 
309478f339d1SEwan Crawford RenderScriptRuntime::~RenderScriptRuntime() = default;
3095