blob: ddc5bd70f9e8b629f01d8e03866805eea2f5fa64 [file] [log] [blame]
Colin Riley5ec532a2015-04-09 16:49:25 +00001//===-- RenderScriptRuntime.cpp ---------------------------------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
10#include "RenderScriptRuntime.h"
11
12#include "lldb/Core/ConstString.h"
13#include "lldb/Core/Debugger.h"
14#include "lldb/Core/Error.h"
15#include "lldb/Core/Log.h"
16#include "lldb/Core/PluginManager.h"
Ewan Crawforda0f08672015-10-16 08:28:47 +000017#include "lldb/Host/StringConvert.h"
Colin Riley5ec532a2015-04-09 16:49:25 +000018#include "lldb/Symbol/Symbol.h"
Colin Riley4640cde2015-06-01 18:23:41 +000019#include "lldb/Symbol/Type.h"
Colin Riley5ec532a2015-04-09 16:49:25 +000020#include "lldb/Target/Process.h"
21#include "lldb/Target/Target.h"
22#include "lldb/Interpreter/Args.h"
23#include "lldb/Interpreter/Options.h"
24#include "lldb/Interpreter/CommandInterpreter.h"
25#include "lldb/Interpreter/CommandReturnObject.h"
26#include "lldb/Interpreter/CommandObjectMultiword.h"
Colin Riley4640cde2015-06-01 18:23:41 +000027#include "lldb/Breakpoint/StoppointCallbackContext.h"
28#include "lldb/Target/RegisterContext.h"
Ewan Crawford15f2bd92015-10-06 08:42:32 +000029#include "lldb/Expression/UserExpression.h"
Colin Riley4640cde2015-06-01 18:23:41 +000030#include "lldb/Symbol/VariableList.h"
Colin Riley5ec532a2015-04-09 16:49:25 +000031
32using namespace lldb;
33using namespace lldb_private;
Ewan Crawford98156582015-09-04 08:56:52 +000034using namespace lldb_renderscript;
Colin Riley5ec532a2015-04-09 16:49:25 +000035
Ewan Crawford78f339d2015-09-21 10:53:18 +000036namespace {
37
38// The empirical_type adds a basic level of validation to arbitrary data
39// allowing us to track if data has been discovered and stored or not.
40// An empirical_type will be marked as valid only if it has been explicitly assigned to.
41template <typename type_t>
42class empirical_type
43{
44 public:
45 // Ctor. Contents is invalid when constructed.
46 empirical_type()
47 : valid(false)
48 {}
49
50 // Return true and copy contents to out if valid, else return false.
51 bool get(type_t& out) const
52 {
53 if (valid)
54 out = data;
55 return valid;
56 }
57
58 // Return a pointer to the contents or nullptr if it was not valid.
59 const type_t* get() const
60 {
61 return valid ? &data : nullptr;
62 }
63
64 // Assign data explicitly.
65 void set(const type_t in)
66 {
67 data = in;
68 valid = true;
69 }
70
71 // Mark contents as invalid.
72 void invalidate()
73 {
74 valid = false;
75 }
76
77 // Returns true if this type contains valid data.
78 bool isValid() const
79 {
80 return valid;
81 }
82
83 // Assignment operator.
84 empirical_type<type_t>& operator = (const type_t in)
85 {
86 set(in);
87 return *this;
88 }
89
90 // Dereference operator returns contents.
91 // Warning: Will assert if not valid so use only when you know data is valid.
92 const type_t& operator * () const
93 {
94 assert(valid);
95 return data;
96 }
97
98 protected:
99 bool valid;
100 type_t data;
101};
102
103} // namespace {}
104
105// The ScriptDetails class collects data associated with a single script instance.
106struct RenderScriptRuntime::ScriptDetails
107{
108 ~ScriptDetails() {};
109
110 enum ScriptType
111 {
112 eScript,
113 eScriptC
114 };
115
116 // The derived type of the script.
117 empirical_type<ScriptType> type;
118 // The name of the original source file.
119 empirical_type<std::string> resName;
120 // Path to script .so file on the device.
121 empirical_type<std::string> scriptDyLib;
122 // Directory where kernel objects are cached on device.
123 empirical_type<std::string> cacheDir;
124 // Pointer to the context which owns this script.
125 empirical_type<lldb::addr_t> context;
126 // Pointer to the script object itself.
127 empirical_type<lldb::addr_t> script;
128};
129
130// This AllocationDetails class collects data associated with a single
131// allocation instance.
132struct RenderScriptRuntime::AllocationDetails
133{
Ewan Crawford15f2bd92015-10-06 08:42:32 +0000134 // Taken from rsDefines.h
135 enum DataKind
136 {
137 RS_KIND_USER,
138 RS_KIND_PIXEL_L = 7,
139 RS_KIND_PIXEL_A,
140 RS_KIND_PIXEL_LA,
141 RS_KIND_PIXEL_RGB,
142 RS_KIND_PIXEL_RGBA,
143 RS_KIND_PIXEL_DEPTH,
144 RS_KIND_PIXEL_YUV,
145 RS_KIND_INVALID = 100
146 };
Ewan Crawford78f339d2015-09-21 10:53:18 +0000147
Ewan Crawford15f2bd92015-10-06 08:42:32 +0000148 // Taken from rsDefines.h
149 enum DataType
150 {
151 RS_TYPE_NONE = 0,
152 RS_TYPE_FLOAT_16,
153 RS_TYPE_FLOAT_32,
154 RS_TYPE_FLOAT_64,
155 RS_TYPE_SIGNED_8,
156 RS_TYPE_SIGNED_16,
157 RS_TYPE_SIGNED_32,
158 RS_TYPE_SIGNED_64,
159 RS_TYPE_UNSIGNED_8,
160 RS_TYPE_UNSIGNED_16,
161 RS_TYPE_UNSIGNED_32,
162 RS_TYPE_UNSIGNED_64,
163 RS_TYPE_BOOLEAN
Ewan Crawford78f339d2015-09-21 10:53:18 +0000164 };
165
Ewan Crawford15f2bd92015-10-06 08:42:32 +0000166 struct Dimension
Ewan Crawford78f339d2015-09-21 10:53:18 +0000167 {
Ewan Crawford15f2bd92015-10-06 08:42:32 +0000168 uint32_t dim_1;
169 uint32_t dim_2;
170 uint32_t dim_3;
171 uint32_t cubeMap;
172
173 Dimension()
174 {
175 dim_1 = 0;
176 dim_2 = 0;
177 dim_3 = 0;
178 cubeMap = 0;
179 }
Ewan Crawford78f339d2015-09-21 10:53:18 +0000180 };
181
Ewan Crawford55232f02015-10-21 08:50:42 +0000182 // Header for reading and writing allocation contents
183 // to a binary file.
184 struct FileHeader
185 {
186 uint8_t ident[4]; // ASCII 'RSAD' identifying the file
187 uint16_t hdr_size; // Header size in bytes, for backwards compatability
188 uint16_t type; // DataType enum
189 uint32_t kind; // DataKind enum
190 uint32_t dims[3]; // Dimensions
191 uint32_t element_size; // Size of a single element, including padding
192 };
193
Ewan Crawford15f2bd92015-10-06 08:42:32 +0000194 // Monotonically increasing from 1
195 static unsigned int ID;
196
197 // Maps Allocation DataType enum and vector size to printable strings
198 // using mapping from RenderScript numerical types summary documentation
199 static const char* RsDataTypeToString[][4];
200
201 // Maps Allocation DataKind enum to printable strings
202 static const char* RsDataKindToString[];
203
Ewan Crawforda0f08672015-10-16 08:28:47 +0000204 // Maps allocation types to format sizes for printing.
205 static const unsigned int RSTypeToFormat[][3];
206
Ewan Crawford15f2bd92015-10-06 08:42:32 +0000207 // Give each allocation an ID as a way
208 // for commands to reference it.
209 const unsigned int id;
210
211 empirical_type<DataType> type; // Type of each data pointer stored by the allocation
212 empirical_type<DataKind> type_kind; // Defines pixel type if Allocation is created from an image
213 empirical_type<uint32_t> type_vec_size; // Vector size of each data point, e.g '4' for uchar4
214 empirical_type<Dimension> dimension; // Dimensions of the Allocation
215 empirical_type<lldb::addr_t> address; // Pointer to address of the RS Allocation
216 empirical_type<lldb::addr_t> data_ptr; // Pointer to the data held by the Allocation
217 empirical_type<lldb::addr_t> type_ptr; // Pointer to the RS Type of the Allocation
218 empirical_type<lldb::addr_t> element_ptr; // Pointer to the RS Element of the Type
219 empirical_type<lldb::addr_t> context; // Pointer to the RS Context of the Allocation
Ewan Crawforda0f08672015-10-16 08:28:47 +0000220 empirical_type<uint32_t> size; // Size of the allocation
221 empirical_type<uint32_t> stride; // Stride between rows of the allocation
Ewan Crawford15f2bd92015-10-06 08:42:32 +0000222
223 // Give each allocation an id, so we can reference it in user commands.
224 AllocationDetails(): id(ID++)
225 {
226 }
227
228};
229
230unsigned int RenderScriptRuntime::AllocationDetails::ID = 1;
231
232const char* RenderScriptRuntime::AllocationDetails::RsDataKindToString[] =
233{
234 "User",
235 "Undefined", "Undefined", "Undefined", // Enum jumps from 0 to 7
236 "Undefined", "Undefined", "Undefined",
237 "L Pixel",
238 "A Pixel",
239 "LA Pixel",
240 "RGB Pixel",
241 "RGBA Pixel",
242 "Pixel Depth",
243 "YUV Pixel"
244};
245
246const char* RenderScriptRuntime::AllocationDetails::RsDataTypeToString[][4] =
247{
248 {"None", "None", "None", "None"},
249 {"half", "half2", "half3", "half4"},
250 {"float", "float2", "float3", "float4"},
251 {"double", "double2", "double3", "double4"},
252 {"char", "char2", "char3", "char4"},
253 {"short", "short2", "short3", "short4"},
254 {"int", "int2", "int3", "int4"},
255 {"long", "long2", "long3", "long4"},
256 {"uchar", "uchar2", "uchar3", "uchar4"},
257 {"ushort", "ushort2", "ushort3", "ushort4"},
258 {"uint", "uint2", "uint3", "uint4"},
259 {"ulong", "ulong2", "ulong3", "ulong4"},
260 {"bool", "bool2", "bool3", "bool4"}
Ewan Crawford78f339d2015-09-21 10:53:18 +0000261};
262
Ewan Crawforda0f08672015-10-16 08:28:47 +0000263// Used as an index into the RSTypeToFormat array elements
264enum TypeToFormatIndex {
265 eFormatSingle = 0,
266 eFormatVector,
267 eElementSize
268};
269
270// { format enum of single element, format enum of element vector, size of element}
271const unsigned int RenderScriptRuntime::AllocationDetails::RSTypeToFormat[][3] =
272{
273 {eFormatHex, eFormatHex, 1}, // RS_TYPE_NONE
274 {eFormatFloat, eFormatVectorOfFloat16, 2}, // RS_TYPE_FLOAT_16
275 {eFormatFloat, eFormatVectorOfFloat32, sizeof(float)}, // RS_TYPE_FLOAT_32
276 {eFormatFloat, eFormatVectorOfFloat64, sizeof(double)}, // RS_TYPE_FLOAT_64
277 {eFormatDecimal, eFormatVectorOfSInt8, sizeof(int8_t)}, // RS_TYPE_SIGNED_8
278 {eFormatDecimal, eFormatVectorOfSInt16, sizeof(int16_t)}, // RS_TYPE_SIGNED_16
279 {eFormatDecimal, eFormatVectorOfSInt32, sizeof(int32_t)}, // RS_TYPE_SIGNED_32
280 {eFormatDecimal, eFormatVectorOfSInt64, sizeof(int64_t)}, // RS_TYPE_SIGNED_64
281 {eFormatDecimal, eFormatVectorOfUInt8, sizeof(uint8_t)}, // RS_TYPE_UNSIGNED_8
282 {eFormatDecimal, eFormatVectorOfUInt16, sizeof(uint16_t)}, // RS_TYPE_UNSIGNED_16
283 {eFormatDecimal, eFormatVectorOfUInt32, sizeof(uint32_t)}, // RS_TYPE_UNSIGNED_32
284 {eFormatDecimal, eFormatVectorOfUInt64, sizeof(uint64_t)}, // RS_TYPE_UNSIGNED_64
285 {eFormatBoolean, eFormatBoolean, sizeof(bool)} // RS_TYPE_BOOL
286};
287
Colin Riley5ec532a2015-04-09 16:49:25 +0000288//------------------------------------------------------------------
289// Static Functions
290//------------------------------------------------------------------
291LanguageRuntime *
292RenderScriptRuntime::CreateInstance(Process *process, lldb::LanguageType language)
293{
294
295 if (language == eLanguageTypeExtRenderScript)
296 return new RenderScriptRuntime(process);
297 else
298 return NULL;
299}
300
Ewan Crawford98156582015-09-04 08:56:52 +0000301// Callback with a module to search for matching symbols.
302// We first check that the module contains RS kernels.
303// Then look for a symbol which matches our kernel name.
304// The breakpoint address is finally set using the address of this symbol.
305Searcher::CallbackReturn
306RSBreakpointResolver::SearchCallback(SearchFilter &filter,
307 SymbolContext &context,
308 Address*,
309 bool)
310{
311 ModuleSP module = context.module_sp;
312
313 if (!module)
314 return Searcher::eCallbackReturnContinue;
315
316 // Is this a module containing renderscript kernels?
317 if (nullptr == module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData))
318 return Searcher::eCallbackReturnContinue;
319
320 // Attempt to set a breakpoint on the kernel name symbol within the module library.
321 // If it's not found, it's likely debug info is unavailable - try to set a
322 // breakpoint on <name>.expand.
323
324 const Symbol* kernel_sym = module->FindFirstSymbolWithNameAndType(m_kernel_name, eSymbolTypeCode);
325 if (!kernel_sym)
326 {
327 std::string kernel_name_expanded(m_kernel_name.AsCString());
328 kernel_name_expanded.append(".expand");
329 kernel_sym = module->FindFirstSymbolWithNameAndType(ConstString(kernel_name_expanded.c_str()), eSymbolTypeCode);
330 }
331
332 if (kernel_sym)
333 {
334 Address bp_addr = kernel_sym->GetAddress();
335 if (filter.AddressPasses(bp_addr))
336 m_breakpoint->AddLocation(bp_addr);
337 }
338
339 return Searcher::eCallbackReturnContinue;
340}
341
Colin Riley5ec532a2015-04-09 16:49:25 +0000342void
343RenderScriptRuntime::Initialize()
344{
Colin Riley4640cde2015-06-01 18:23:41 +0000345 PluginManager::RegisterPlugin(GetPluginNameStatic(), "RenderScript language support", CreateInstance, GetCommandObject);
Colin Riley5ec532a2015-04-09 16:49:25 +0000346}
347
348void
349RenderScriptRuntime::Terminate()
350{
351 PluginManager::UnregisterPlugin(CreateInstance);
352}
353
354lldb_private::ConstString
355RenderScriptRuntime::GetPluginNameStatic()
356{
357 static ConstString g_name("renderscript");
358 return g_name;
359}
360
Colin Rileyef20b082015-04-14 07:39:24 +0000361RenderScriptRuntime::ModuleKind
362RenderScriptRuntime::GetModuleKind(const lldb::ModuleSP &module_sp)
363{
364 if (module_sp)
365 {
366 // Is this a module containing renderscript kernels?
367 const Symbol *info_sym = module_sp->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData);
368 if (info_sym)
369 {
370 return eModuleKindKernelObj;
371 }
Colin Riley4640cde2015-06-01 18:23:41 +0000372
373 // Is this the main RS runtime library
374 const ConstString rs_lib("libRS.so");
375 if (module_sp->GetFileSpec().GetFilename() == rs_lib)
376 {
377 return eModuleKindLibRS;
378 }
379
380 const ConstString rs_driverlib("libRSDriver.so");
381 if (module_sp->GetFileSpec().GetFilename() == rs_driverlib)
382 {
383 return eModuleKindDriver;
384 }
385
Ewan Crawford15f2bd92015-10-06 08:42:32 +0000386 const ConstString rs_cpureflib("libRSCpuRef.so");
Colin Riley4640cde2015-06-01 18:23:41 +0000387 if (module_sp->GetFileSpec().GetFilename() == rs_cpureflib)
388 {
389 return eModuleKindImpl;
390 }
391
Colin Rileyef20b082015-04-14 07:39:24 +0000392 }
393 return eModuleKindIgnored;
394}
395
396bool
397RenderScriptRuntime::IsRenderScriptModule(const lldb::ModuleSP &module_sp)
398{
399 return GetModuleKind(module_sp) != eModuleKindIgnored;
400}
401
402
403void
404RenderScriptRuntime::ModulesDidLoad(const ModuleList &module_list )
405{
406 Mutex::Locker locker (module_list.GetMutex ());
407
408 size_t num_modules = module_list.GetSize();
409 for (size_t i = 0; i < num_modules; i++)
410 {
411 auto mod = module_list.GetModuleAtIndex (i);
412 if (IsRenderScriptModule (mod))
413 {
414 LoadModule(mod);
415 }
416 }
417}
418
419
Colin Riley5ec532a2015-04-09 16:49:25 +0000420//------------------------------------------------------------------
421// PluginInterface protocol
422//------------------------------------------------------------------
423lldb_private::ConstString
424RenderScriptRuntime::GetPluginName()
425{
426 return GetPluginNameStatic();
427}
428
429uint32_t
430RenderScriptRuntime::GetPluginVersion()
431{
432 return 1;
433}
434
435bool
436RenderScriptRuntime::IsVTableName(const char *name)
437{
438 return false;
439}
440
441bool
442RenderScriptRuntime::GetDynamicTypeAndAddress(ValueObject &in_value, lldb::DynamicValueType use_dynamic,
Enrico Granata0b6003f2015-09-17 22:56:38 +0000443 TypeAndOrName &class_type_or_name, Address &address,
444 Value::ValueType &value_type)
Colin Riley5ec532a2015-04-09 16:49:25 +0000445{
446 return false;
447}
448
Enrico Granatac74275b2015-09-22 19:45:52 +0000449TypeAndOrName
Enrico Granata7eed4872015-09-22 19:58:02 +0000450RenderScriptRuntime::FixUpDynamicType (const TypeAndOrName& type_and_or_name,
451 ValueObject& static_value)
Enrico Granatac74275b2015-09-22 19:45:52 +0000452{
453 return type_and_or_name;
454}
455
Colin Riley5ec532a2015-04-09 16:49:25 +0000456bool
457RenderScriptRuntime::CouldHaveDynamicValue(ValueObject &in_value)
458{
459 return false;
460}
461
462lldb::BreakpointResolverSP
463RenderScriptRuntime::CreateExceptionResolver(Breakpoint *bkpt, bool catch_bp, bool throw_bp)
464{
465 BreakpointResolverSP resolver_sp;
466 return resolver_sp;
467}
468
Colin Riley4640cde2015-06-01 18:23:41 +0000469
470const RenderScriptRuntime::HookDefn RenderScriptRuntime::s_runtimeHookDefns[] =
471{
472 //rsdScript
Aidan Dodds82780282015-09-18 16:49:39 +0000473 {
474 "rsdScriptInit", //name
475 "_Z13rsdScriptInitPKN7android12renderscript7ContextEPNS0_7ScriptCEPKcS7_PKhjj", // symbol name 32 bit
476 "_Z13rsdScriptInitPKN7android12renderscript7ContextEPNS0_7ScriptCEPKcS7_PKhmj", // symbol name 64 bit
477 0, // version
478 RenderScriptRuntime::eModuleKindDriver, // type
479 &lldb_private::RenderScriptRuntime::CaptureScriptInit1 // handler
480 },
481 {
482 "rsdScriptInvokeForEach", // name
483 "_Z22rsdScriptInvokeForEachPKN7android12renderscript7ContextEPNS0_6ScriptEjPKNS0_10AllocationEPS6_PKvjPK12RsScriptCall", // symbol name 32bit
484 "_Z22rsdScriptInvokeForEachPKN7android12renderscript7ContextEPNS0_6ScriptEjPKNS0_10AllocationEPS6_PKvmPK12RsScriptCall", // symbol name 64bit
485 0, // version
486 RenderScriptRuntime::eModuleKindDriver, // type
487 nullptr // handler
488 },
489 {
490 "rsdScriptInvokeForEachMulti", // name
491 "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0_6ScriptEjPPKNS0_10AllocationEjPS6_PKvjPK12RsScriptCall", // symbol name 32bit
492 "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0_6ScriptEjPPKNS0_10AllocationEmPS6_PKvmPK12RsScriptCall", // symbol name 64bit
493 0, // version
494 RenderScriptRuntime::eModuleKindDriver, // type
495 nullptr // handler
496 },
497 {
498 "rsdScriptInvokeFunction", // name
499 "_Z23rsdScriptInvokeFunctionPKN7android12renderscript7ContextEPNS0_6ScriptEjPKvj", // symbol name 32bit
500 "_Z23rsdScriptInvokeFunctionPKN7android12renderscript7ContextEPNS0_6ScriptEjPKvm", // symbol name 64bit
501 0, // version
502 RenderScriptRuntime::eModuleKindDriver, // type
503 nullptr // handler
504 },
505 {
506 "rsdScriptSetGlobalVar", // name
507 "_Z21rsdScriptSetGlobalVarPKN7android12renderscript7ContextEPKNS0_6ScriptEjPvj", // symbol name 32bit
508 "_Z21rsdScriptSetGlobalVarPKN7android12renderscript7ContextEPKNS0_6ScriptEjPvm", // symbol name 64bit
509 0, // version
510 RenderScriptRuntime::eModuleKindDriver, // type
511 &lldb_private::RenderScriptRuntime::CaptureSetGlobalVar1 // handler
512 },
Colin Riley4640cde2015-06-01 18:23:41 +0000513
514 //rsdAllocation
Aidan Dodds82780282015-09-18 16:49:39 +0000515 {
516 "rsdAllocationInit", // name
517 "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_10AllocationEb", // symbol name 32bit
518 "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_10AllocationEb", // symbol name 64bit
519 0, // version
520 RenderScriptRuntime::eModuleKindDriver, // type
521 &lldb_private::RenderScriptRuntime::CaptureAllocationInit1 // handler
522 },
523 {
524 "rsdAllocationRead2D", //name
525 "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_10AllocationEjjj23RsAllocationCubemapFacejjPvjj", // symbol name 32bit
526 "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_10AllocationEjjj23RsAllocationCubemapFacejjPvmm", // symbol name 64bit
527 0, // version
528 RenderScriptRuntime::eModuleKindDriver, // type
529 nullptr // handler
530 },
Colin Riley4640cde2015-06-01 18:23:41 +0000531};
532const size_t RenderScriptRuntime::s_runtimeHookCount = sizeof(s_runtimeHookDefns)/sizeof(s_runtimeHookDefns[0]);
533
534
535bool
536RenderScriptRuntime::HookCallback(void *baton, StoppointCallbackContext *ctx, lldb::user_id_t break_id, lldb::user_id_t break_loc_id)
537{
538 RuntimeHook* hook_info = (RuntimeHook*)baton;
539 ExecutionContext context(ctx->exe_ctx_ref);
540
541 RenderScriptRuntime *lang_rt = (RenderScriptRuntime *)context.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
542
543 lang_rt->HookCallback(hook_info, context);
544
545 return false;
546}
547
548
549void
550RenderScriptRuntime::HookCallback(RuntimeHook* hook_info, ExecutionContext& context)
551{
552 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
553
Aidan Dodds82780282015-09-18 16:49:39 +0000554 if (log)
Colin Riley4640cde2015-06-01 18:23:41 +0000555 log->Printf ("RenderScriptRuntime::HookCallback - '%s' .", hook_info->defn->name);
556
557 if (hook_info->defn->grabber)
558 {
559 (this->*(hook_info->defn->grabber))(hook_info, context);
560 }
561}
562
563
564bool
Aidan Dodds82780282015-09-18 16:49:39 +0000565RenderScriptRuntime::GetArgSimple(ExecutionContext &context, uint32_t arg, uint64_t *data)
Colin Riley4640cde2015-06-01 18:23:41 +0000566{
Colin Riley4640cde2015-06-01 18:23:41 +0000567 if (!data)
568 return false;
569
Aidan Dodds82780282015-09-18 16:49:39 +0000570 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
Colin Riley4640cde2015-06-01 18:23:41 +0000571 Error error;
572 RegisterContext* reg_ctx = context.GetRegisterContext();
573 Process* process = context.GetProcessPtr();
Aidan Dodds82780282015-09-18 16:49:39 +0000574 bool success = false; // return value
Colin Riley4640cde2015-06-01 18:23:41 +0000575
Aidan Dodds82780282015-09-18 16:49:39 +0000576 if (!context.GetTargetPtr())
Colin Riley4640cde2015-06-01 18:23:41 +0000577 {
Aidan Dodds82780282015-09-18 16:49:39 +0000578 if (log)
579 log->Printf("RenderScriptRuntime::GetArgSimple - Invalid target");
580
581 return false;
Colin Riley4640cde2015-06-01 18:23:41 +0000582 }
Aidan Dodds82780282015-09-18 16:49:39 +0000583
584 switch (context.GetTargetPtr()->GetArchitecture().GetMachine())
Colin Riley4640cde2015-06-01 18:23:41 +0000585 {
Aidan Dodds82780282015-09-18 16:49:39 +0000586 case llvm::Triple::ArchType::x86:
Colin Riley4640cde2015-06-01 18:23:41 +0000587 {
588 uint64_t sp = reg_ctx->GetSP();
Aidan Dodds82780282015-09-18 16:49:39 +0000589 uint32_t offset = (1 + arg) * sizeof(uint32_t);
590 uint32_t result = 0;
591 process->ReadMemory(sp + offset, &result, sizeof(uint32_t), error);
592 if (error.Fail())
Colin Riley4640cde2015-06-01 18:23:41 +0000593 {
Aidan Dodds82780282015-09-18 16:49:39 +0000594 if (log)
595 log->Printf ("RenderScriptRuntime:: GetArgSimple - error reading X86 stack: %s.", error.AsCString());
596 }
597 else
598 {
599 *data = result;
600 success = true;
601 }
602
603 break;
604 }
605 case llvm::Triple::ArchType::arm:
606 {
607 // arm 32 bit
608 if (arg < 4)
609 {
610 const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg);
611 RegisterValue rVal;
Ewan Crawford02f1c5d2015-10-22 09:01:05 +0000612 success = reg_ctx->ReadRegister(rArg, rVal);
613 if (success)
614 {
615 (*data) = rVal.GetAsUInt32();
616 }
617 else
618 {
619 if (log)
620 log->Printf ("RenderScriptRuntime:: GetArgSimple - error reading ARM register: %d.", arg);
621 }
Aidan Dodds82780282015-09-18 16:49:39 +0000622 }
623 else
624 {
625 uint64_t sp = reg_ctx->GetSP();
Ewan Crawford02f1c5d2015-10-22 09:01:05 +0000626 uint32_t offset = (arg-4) * sizeof(uint32_t);
627 process->ReadMemory(sp + offset, &data, sizeof(uint32_t), error);
628 if (error.Fail())
Colin Riley4640cde2015-06-01 18:23:41 +0000629 {
Ewan Crawford02f1c5d2015-10-22 09:01:05 +0000630 if (log)
631 log->Printf ("RenderScriptRuntime:: GetArgSimple - error reading ARM stack: %s.", error.AsCString());
632 }
633 else
634 {
635 success = true;
Colin Riley4640cde2015-06-01 18:23:41 +0000636 }
637 }
Aidan Dodds82780282015-09-18 16:49:39 +0000638
639 break;
640 }
641 case llvm::Triple::ArchType::aarch64:
642 {
643 // arm 64 bit
644 // first 8 arguments are in the registers
645 if (arg < 8)
646 {
647 const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg);
648 RegisterValue rVal;
649 success = reg_ctx->ReadRegister(rArg, rVal);
650 if (success)
651 {
652 *data = rVal.GetAsUInt64();
653 }
654 else
655 {
656 if (log)
657 log->Printf("RenderScriptRuntime::GetArgSimple() - AARCH64 - Error while reading the argument #%d", arg);
658 }
659 }
660 else
661 {
662 // @TODO: need to find the argument in the stack
663 if (log)
664 log->Printf("RenderScriptRuntime::GetArgSimple - AARCH64 - FOR #ARG >= 8 NOT IMPLEMENTED YET. Argument number: %d", arg);
665 }
666 break;
667 }
Ewan Crawford02f1c5d2015-10-22 09:01:05 +0000668 case llvm::Triple::ArchType::mips64el:
669 {
670 // read from the registers
671 if (arg < 8)
672 {
673 const RegisterInfo* rArg = reg_ctx->GetRegisterInfoAtIndex(arg + 4);
674 RegisterValue rVal;
675 success = reg_ctx->ReadRegister(rArg, rVal);
676 if (success)
677 {
678 (*data) = rVal.GetAsUInt64();
679 }
680 else
681 {
682 if (log)
683 log->Printf("RenderScriptRuntime::GetArgSimple - Mips64 - Error reading the argument #%d", arg);
684 }
685 }
686
687 // read from the stack
688 else
689 {
690 uint64_t sp = reg_ctx->GetSP();
691 uint32_t offset = (arg - 8) * sizeof(uint64_t);
692 process->ReadMemory(sp + offset, &data, sizeof(uint64_t), error);
693 if (error.Fail())
694 {
695 if (log)
696 log->Printf ("RenderScriptRuntime::GetArgSimple - Mips64 - Error reading Mips64 stack: %s.", error.AsCString());
697 }
698 else
699 {
700 success = true;
701 }
702 }
703
704 break;
705 }
Aidan Dodds82780282015-09-18 16:49:39 +0000706 default:
707 {
708 // invalid architecture
709 if (log)
710 log->Printf("RenderScriptRuntime::GetArgSimple - Architecture not supported");
711
712 }
Colin Riley4640cde2015-06-01 18:23:41 +0000713 }
Aidan Dodds82780282015-09-18 16:49:39 +0000714
715
716 return success;
Colin Riley4640cde2015-06-01 18:23:41 +0000717}
718
719void
720RenderScriptRuntime::CaptureSetGlobalVar1(RuntimeHook* hook_info, ExecutionContext& context)
721{
722 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
723
724 //Context, Script, int, data, length
725
Aidan Dodds82780282015-09-18 16:49:39 +0000726 uint64_t rs_context_u64 = 0U;
727 uint64_t rs_script_u64 = 0U;
728 uint64_t rs_id_u64 = 0U;
729 uint64_t rs_data_u64 = 0U;
730 uint64_t rs_length_u64 = 0U;
Colin Riley4640cde2015-06-01 18:23:41 +0000731
Aidan Dodds82780282015-09-18 16:49:39 +0000732 bool success =
733 GetArgSimple(context, 0, &rs_context_u64) &&
734 GetArgSimple(context, 1, &rs_script_u64) &&
735 GetArgSimple(context, 2, &rs_id_u64) &&
736 GetArgSimple(context, 3, &rs_data_u64) &&
737 GetArgSimple(context, 4, &rs_length_u64);
Colin Riley4640cde2015-06-01 18:23:41 +0000738
Aidan Dodds82780282015-09-18 16:49:39 +0000739 if (!success)
740 {
741 if (log)
742 log->Printf("RenderScriptRuntime::CaptureSetGlobalVar1 - Error while reading the function parameters");
743 return;
744 }
Colin Riley4640cde2015-06-01 18:23:41 +0000745
Aidan Dodds82780282015-09-18 16:49:39 +0000746 if (log)
Colin Riley4640cde2015-06-01 18:23:41 +0000747 {
748 log->Printf ("RenderScriptRuntime::CaptureSetGlobalVar1 - 0x%" PRIx64 ",0x%" PRIx64 " slot %" PRIu64 " = 0x%" PRIx64 ":%" PRIu64 "bytes.",
Aidan Dodds82780282015-09-18 16:49:39 +0000749 rs_context_u64, rs_script_u64, rs_id_u64, rs_data_u64, rs_length_u64);
Colin Riley4640cde2015-06-01 18:23:41 +0000750
Aidan Dodds82780282015-09-18 16:49:39 +0000751 addr_t script_addr = (addr_t)rs_script_u64;
Colin Riley4640cde2015-06-01 18:23:41 +0000752 if (m_scriptMappings.find( script_addr ) != m_scriptMappings.end())
753 {
754 auto rsm = m_scriptMappings[script_addr];
Aidan Dodds82780282015-09-18 16:49:39 +0000755 if (rs_id_u64 < rsm->m_globals.size())
Colin Riley4640cde2015-06-01 18:23:41 +0000756 {
Aidan Dodds82780282015-09-18 16:49:39 +0000757 auto rsg = rsm->m_globals[rs_id_u64];
Colin Riley4640cde2015-06-01 18:23:41 +0000758 log->Printf ("RenderScriptRuntime::CaptureSetGlobalVar1 - Setting of '%s' within '%s' inferred", rsg.m_name.AsCString(),
759 rsm->m_module->GetFileSpec().GetFilename().AsCString());
760 }
761 }
762 }
763}
764
765void
766RenderScriptRuntime::CaptureAllocationInit1(RuntimeHook* hook_info, ExecutionContext& context)
767{
768 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
769
770 //Context, Alloc, bool
771
Aidan Dodds82780282015-09-18 16:49:39 +0000772 uint64_t rs_context_u64 = 0U;
773 uint64_t rs_alloc_u64 = 0U;
774 uint64_t rs_forceZero_u64 = 0U;
Colin Riley4640cde2015-06-01 18:23:41 +0000775
Aidan Dodds82780282015-09-18 16:49:39 +0000776 bool success =
777 GetArgSimple(context, 0, &rs_context_u64) &&
778 GetArgSimple(context, 1, &rs_alloc_u64) &&
779 GetArgSimple(context, 2, &rs_forceZero_u64);
780 if (!success) // error case
781 {
782 if (log)
783 log->Printf("RenderScriptRuntime::CaptureAllocationInit1 - Error while reading the function parameters");
784 return; // abort
785 }
786
787 if (log)
Colin Riley4640cde2015-06-01 18:23:41 +0000788 log->Printf ("RenderScriptRuntime::CaptureAllocationInit1 - 0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 " .",
Aidan Dodds82780282015-09-18 16:49:39 +0000789 rs_context_u64, rs_alloc_u64, rs_forceZero_u64);
Ewan Crawford78f339d2015-09-21 10:53:18 +0000790
791 AllocationDetails* alloc = LookUpAllocation(rs_alloc_u64, true);
792 if (alloc)
793 alloc->context = rs_context_u64;
Colin Riley4640cde2015-06-01 18:23:41 +0000794}
795
796void
797RenderScriptRuntime::CaptureScriptInit1(RuntimeHook* hook_info, ExecutionContext& context)
798{
799 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
800
801 //Context, Script, resname Str, cachedir Str
802 Error error;
803 Process* process = context.GetProcessPtr();
804
Aidan Dodds82780282015-09-18 16:49:39 +0000805 uint64_t rs_context_u64 = 0U;
806 uint64_t rs_script_u64 = 0U;
807 uint64_t rs_resnameptr_u64 = 0U;
808 uint64_t rs_cachedirptr_u64 = 0U;
Colin Riley4640cde2015-06-01 18:23:41 +0000809
810 std::string resname;
811 std::string cachedir;
812
Aidan Dodds82780282015-09-18 16:49:39 +0000813 // read the function parameters
814 bool success =
815 GetArgSimple(context, 0, &rs_context_u64) &&
816 GetArgSimple(context, 1, &rs_script_u64) &&
817 GetArgSimple(context, 2, &rs_resnameptr_u64) &&
818 GetArgSimple(context, 3, &rs_cachedirptr_u64);
Colin Riley4640cde2015-06-01 18:23:41 +0000819
Aidan Dodds82780282015-09-18 16:49:39 +0000820 if (!success)
821 {
822 if (log)
823 log->Printf("RenderScriptRuntime::CaptureScriptInit1 - Error while reading the function parameters");
824 return;
825 }
826
827 process->ReadCStringFromMemory((lldb::addr_t)rs_resnameptr_u64, resname, error);
Colin Riley4640cde2015-06-01 18:23:41 +0000828 if (error.Fail())
829 {
Aidan Dodds82780282015-09-18 16:49:39 +0000830 if (log)
Colin Riley4640cde2015-06-01 18:23:41 +0000831 log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - error reading resname: %s.", error.AsCString());
832
833 }
834
Aidan Dodds82780282015-09-18 16:49:39 +0000835 process->ReadCStringFromMemory((lldb::addr_t)rs_cachedirptr_u64, cachedir, error);
Colin Riley4640cde2015-06-01 18:23:41 +0000836 if (error.Fail())
837 {
Aidan Dodds82780282015-09-18 16:49:39 +0000838 if (log)
Colin Riley4640cde2015-06-01 18:23:41 +0000839 log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - error reading cachedir: %s.", error.AsCString());
840 }
841
842 if (log)
843 log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - 0x%" PRIx64 ",0x%" PRIx64 " => '%s' at '%s' .",
Aidan Dodds82780282015-09-18 16:49:39 +0000844 rs_context_u64, rs_script_u64, resname.c_str(), cachedir.c_str());
Colin Riley4640cde2015-06-01 18:23:41 +0000845
846 if (resname.size() > 0)
847 {
848 StreamString strm;
849 strm.Printf("librs.%s.so", resname.c_str());
850
Ewan Crawford78f339d2015-09-21 10:53:18 +0000851 ScriptDetails* script = LookUpScript(rs_script_u64, true);
852 if (script)
853 {
854 script->type = ScriptDetails::eScriptC;
855 script->cacheDir = cachedir;
856 script->resName = resname;
857 script->scriptDyLib = strm.GetData();
858 script->context = addr_t(rs_context_u64);
859 }
Colin Riley4640cde2015-06-01 18:23:41 +0000860
861 if (log)
862 log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - '%s' tagged with context 0x%" PRIx64 " and script 0x%" PRIx64 ".",
Aidan Dodds82780282015-09-18 16:49:39 +0000863 strm.GetData(), rs_context_u64, rs_script_u64);
Colin Riley4640cde2015-06-01 18:23:41 +0000864 }
865 else if (log)
866 {
867 log->Printf ("RenderScriptRuntime::CaptureScriptInit1 - resource name invalid, Script not tagged");
868 }
869
870}
871
Colin Riley4640cde2015-06-01 18:23:41 +0000872void
873RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, ModuleKind kind)
874{
875 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
876
877 if (!module)
878 {
879 return;
880 }
881
Aidan Dodds82780282015-09-18 16:49:39 +0000882 Target &target = GetProcess()->GetTarget();
883 llvm::Triple::ArchType targetArchType = target.GetArchitecture().GetMachine();
884
885 if (targetArchType != llvm::Triple::ArchType::x86
886 && targetArchType != llvm::Triple::ArchType::arm
Ewan Crawford02f1c5d2015-10-22 09:01:05 +0000887 && targetArchType != llvm::Triple::ArchType::aarch64
888 && targetArchType != llvm::Triple::ArchType::mips64el
889 )
Colin Riley4640cde2015-06-01 18:23:41 +0000890 {
891 if (log)
Ewan Crawford02f1c5d2015-10-22 09:01:05 +0000892 log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Unable to hook runtime. Only X86, ARM, Mips64 supported currently.");
Colin Riley4640cde2015-06-01 18:23:41 +0000893
894 return;
895 }
896
Aidan Dodds82780282015-09-18 16:49:39 +0000897 uint32_t archByteSize = target.GetArchitecture().GetAddressByteSize();
Colin Riley4640cde2015-06-01 18:23:41 +0000898
899 for (size_t idx = 0; idx < s_runtimeHookCount; idx++)
900 {
901 const HookDefn* hook_defn = &s_runtimeHookDefns[idx];
902 if (hook_defn->kind != kind) {
903 continue;
904 }
905
Aidan Dodds82780282015-09-18 16:49:39 +0000906 const char* symbol_name = (archByteSize == 4) ? hook_defn->symbol_name_m32 : hook_defn->symbol_name_m64;
907
908 const Symbol *sym = module->FindFirstSymbolWithNameAndType(ConstString(symbol_name), eSymbolTypeCode);
909 if (!sym){
910 if (log){
911 log->Printf("RenderScriptRuntime::LoadRuntimeHooks - ERROR: Symbol '%s' related to the function %s not found", symbol_name, hook_defn->name);
912 }
913 continue;
914 }
Colin Riley4640cde2015-06-01 18:23:41 +0000915
Greg Clayton358cf1e2015-06-25 21:46:34 +0000916 addr_t addr = sym->GetLoadAddress(&target);
Colin Riley4640cde2015-06-01 18:23:41 +0000917 if (addr == LLDB_INVALID_ADDRESS)
918 {
Aidan Dodds82780282015-09-18 16:49:39 +0000919 if (log)
Colin Riley4640cde2015-06-01 18:23:41 +0000920 log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Unable to resolve the address of hook function '%s' with symbol '%s'.",
Aidan Dodds82780282015-09-18 16:49:39 +0000921 hook_defn->name, symbol_name);
Colin Riley4640cde2015-06-01 18:23:41 +0000922 continue;
923 }
Aidan Dodds82780282015-09-18 16:49:39 +0000924 else
925 {
926 if (log)
927 log->Printf("RenderScriptRuntime::LoadRuntimeHooks - Function %s, address resolved at 0x%" PRIx64, hook_defn->name, addr);
928 }
Colin Riley4640cde2015-06-01 18:23:41 +0000929
930 RuntimeHookSP hook(new RuntimeHook());
931 hook->address = addr;
932 hook->defn = hook_defn;
933 hook->bp_sp = target.CreateBreakpoint(addr, true, false);
934 hook->bp_sp->SetCallback(HookCallback, hook.get(), true);
935 m_runtimeHooks[addr] = hook;
936 if (log)
937 {
938 log->Printf ("RenderScriptRuntime::LoadRuntimeHooks - Successfully hooked '%s' in '%s' version %" PRIu64 " at 0x%" PRIx64 ".",
939 hook_defn->name, module->GetFileSpec().GetFilename().AsCString(), (uint64_t)hook_defn->version, (uint64_t)addr);
940 }
941 }
942}
943
944void
945RenderScriptRuntime::FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp)
946{
947 if (!rsmodule_sp)
948 return;
949
950 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
951
952 const ModuleSP module = rsmodule_sp->m_module;
953 const FileSpec& file = module->GetPlatformFileSpec();
Ewan Crawford78f339d2015-09-21 10:53:18 +0000954
955 // Iterate over all of the scripts that we currently know of.
956 // Note: We cant push or pop to m_scripts here or it may invalidate rs_script.
957 for (const auto & rs_script : m_scripts)
Colin Riley4640cde2015-06-01 18:23:41 +0000958 {
Ewan Crawford78f339d2015-09-21 10:53:18 +0000959 // Extract the expected .so file path for this script.
960 std::string dylib;
961 if (!rs_script->scriptDyLib.get(dylib))
962 continue;
963
964 // Only proceed if the module that has loaded corresponds to this script.
965 if (file.GetFilename() != ConstString(dylib.c_str()))
966 continue;
967
968 // Obtain the script address which we use as a key.
969 lldb::addr_t script;
970 if (!rs_script->script.get(script))
971 continue;
972
973 // If we have a script mapping for the current script.
974 if (m_scriptMappings.find(script) != m_scriptMappings.end())
Colin Riley4640cde2015-06-01 18:23:41 +0000975 {
Ewan Crawford78f339d2015-09-21 10:53:18 +0000976 // if the module we have stored is different to the one we just received.
977 if (m_scriptMappings[script] != rsmodule_sp)
Colin Riley4640cde2015-06-01 18:23:41 +0000978 {
Colin Riley4640cde2015-06-01 18:23:41 +0000979 if (log)
Ewan Crawford78f339d2015-09-21 10:53:18 +0000980 log->Printf ("RenderScriptRuntime::FixupScriptDetails - Error: script %" PRIx64 " wants reassigned to new rsmodule '%s'.",
981 (uint64_t)script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
Colin Riley4640cde2015-06-01 18:23:41 +0000982 }
983 }
Ewan Crawford78f339d2015-09-21 10:53:18 +0000984 // We don't have a script mapping for the current script.
985 else
986 {
987 // Obtain the script resource name.
988 std::string resName;
989 if (rs_script->resName.get(resName))
990 // Set the modules resource name.
991 rsmodule_sp->m_resname = resName;
992 // Add Script/Module pair to map.
993 m_scriptMappings[script] = rsmodule_sp;
994 if (log)
995 log->Printf ("RenderScriptRuntime::FixupScriptDetails - script %" PRIx64 " associated with rsmodule '%s'.",
996 (uint64_t)script, rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
997 }
Colin Riley4640cde2015-06-01 18:23:41 +0000998 }
Colin Riley4640cde2015-06-01 18:23:41 +0000999}
1000
Ewan Crawford15f2bd92015-10-06 08:42:32 +00001001// Uses the Target API to evaluate the expression passed as a parameter to the function
1002// The result of that expression is returned an unsigned 64 bit int, via the result* paramter.
1003// Function returns true on success, and false on failure
1004bool
1005RenderScriptRuntime::EvalRSExpression(const char* expression, StackFrame* frame_ptr, uint64_t* result)
1006{
1007 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1008 if (log)
1009 log->Printf("RenderScriptRuntime::EvalRSExpression(%s)", expression);
1010
1011 ValueObjectSP expr_result;
1012 // Perform the actual expression evaluation
1013 GetProcess()->GetTarget().EvaluateExpression(expression, frame_ptr, expr_result);
1014
1015 if (!expr_result)
1016 {
1017 if (log)
1018 log->Printf("RenderScriptRuntime::EvalRSExpression - Error: Couldn't evaluate expression");
1019 return false;
1020 }
1021
1022 // The result of the expression is invalid
1023 if (!expr_result->GetError().Success())
1024 {
1025 Error err = expr_result->GetError();
1026 if (err.GetError() == UserExpression::kNoResult) // Expression returned void, so this is actually a success
1027 {
1028 if (log)
1029 log->Printf("RenderScriptRuntime::EvalRSExpression - Expression returned void");
1030
1031 result = nullptr;
1032 return true;
1033 }
1034
1035 if (log)
1036 log->Printf("RenderScriptRuntime::EvalRSExpression - Error evaluating expression result: %s", err.AsCString());
1037 return false;
1038 }
1039
1040 bool success = false;
1041 *result = expr_result->GetValueAsUnsigned(0, &success); // We only read the result as an unsigned int.
1042
1043 if (!success)
1044 {
1045 if (log)
1046 log->Printf("RenderScriptRuntime::EvalRSExpression - Error: Couldn't convert expression result to unsigned int");
1047 return false;
1048 }
1049
1050 return true;
1051}
1052
1053// Used to index expression format strings
1054enum ExpressionStrings
1055{
1056 eExprGetOffsetPtr = 0,
1057 eExprAllocGetType,
1058 eExprTypeDimX,
1059 eExprTypeDimY,
1060 eExprTypeDimZ,
1061 eExprTypeElemPtr,
1062 eExprElementType,
1063 eExprElementKind,
1064 eExprElementVec
1065};
1066
1067// Format strings containing the expressions we may need to evaluate.
1068const char runtimeExpressions[][256] =
1069{
1070 // Mangled GetOffsetPointer(Allocation*, xoff, yoff, zoff, lod, cubemap)
1071 "(int*)_Z12GetOffsetPtrPKN7android12renderscript10AllocationEjjjj23RsAllocationCubemapFace(0x%lx, %u, %u, %u, 0, 0)",
1072
1073 // Type* rsaAllocationGetType(Context*, Allocation*)
1074 "(void*)rsaAllocationGetType(0x%lx, 0x%lx)",
1075
1076 // rsaTypeGetNativeData(Context*, Type*, void* typeData, size)
1077 // Pack the data in the following way mHal.state.dimX; mHal.state.dimY; mHal.state.dimZ;
1078 // mHal.state.lodCount; mHal.state.faces; mElement; into typeData
1079 // Need to specify 32 or 64 bit for uint_t since this differs between devices
1080 "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[0]", // X dim
1081 "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[1]", // Y dim
1082 "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[2]", // Z dim
1083 "uint%u_t data[6]; (void*)rsaTypeGetNativeData(0x%lx, 0x%lx, data, 6); data[5]", // Element ptr
1084
1085 // rsaElementGetNativeData(Context*, Element*, uint32_t* elemData,size)
1086 // Pack mType; mKind; mNormalized; mVectorSize; NumSubElements into elemData
1087 "uint32_t data[6]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[0]", // Type
1088 "uint32_t data[6]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[1]", // Kind
1089 "uint32_t data[6]; (void*)rsaElementGetNativeData(0x%lx, 0x%lx, data, 5); data[3]" // Vector Size
1090};
1091
1092// JITs the RS runtime for the internal data pointer of an allocation.
1093// Is passed x,y,z coordinates for the pointer to a specific element.
1094// Then sets the data_ptr member in Allocation with the result.
1095// Returns true on success, false otherwise
1096bool
1097RenderScriptRuntime::JITDataPointer(AllocationDetails* allocation, StackFrame* frame_ptr,
1098 unsigned int x, unsigned int y, unsigned int z)
1099{
1100 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1101
1102 if (!allocation->address.isValid())
1103 {
1104 if (log)
1105 log->Printf("RenderScriptRuntime::JITDataPointer - Failed to find allocation details");
1106 return false;
1107 }
1108
1109 const char* expr_cstr = runtimeExpressions[eExprGetOffsetPtr];
1110 const int max_expr_size = 512; // Max expression size
1111 char buffer[max_expr_size];
1112
1113 int chars_written = snprintf(buffer, max_expr_size, expr_cstr, *allocation->address.get(), x, y, z);
1114 if (chars_written < 0)
1115 {
1116 if (log)
1117 log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()");
1118 return false;
1119 }
1120 else if (chars_written >= max_expr_size)
1121 {
1122 if (log)
1123 log->Printf("RenderScriptRuntime::JITDataPointer - Expression too long");
1124 return false;
1125 }
1126
1127 uint64_t result = 0;
1128 if (!EvalRSExpression(buffer, frame_ptr, &result))
1129 return false;
1130
1131 addr_t mem_ptr = static_cast<lldb::addr_t>(result);
1132 allocation->data_ptr = mem_ptr;
1133
1134 return true;
1135}
1136
1137// JITs the RS runtime for the internal pointer to the RS Type of an allocation
1138// Then sets the type_ptr member in Allocation with the result.
1139// Returns true on success, false otherwise
1140bool
1141RenderScriptRuntime::JITTypePointer(AllocationDetails* allocation, StackFrame* frame_ptr)
1142{
1143 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1144
1145 if (!allocation->address.isValid() || !allocation->context.isValid())
1146 {
1147 if (log)
1148 log->Printf("RenderScriptRuntime::JITTypePointer - Failed to find allocation details");
1149 return false;
1150 }
1151
1152 const char* expr_cstr = runtimeExpressions[eExprAllocGetType];
1153 const int max_expr_size = 512; // Max expression size
1154 char buffer[max_expr_size];
1155
1156 int chars_written = snprintf(buffer, max_expr_size, expr_cstr, *allocation->context.get(), *allocation->address.get());
1157 if (chars_written < 0)
1158 {
1159 if (log)
1160 log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()");
1161 return false;
1162 }
1163 else if (chars_written >= max_expr_size)
1164 {
1165 if (log)
1166 log->Printf("RenderScriptRuntime::JITTypePointer - Expression too long");
1167 return false;
1168 }
1169
1170 uint64_t result = 0;
1171 if (!EvalRSExpression(buffer, frame_ptr, &result))
1172 return false;
1173
1174 addr_t type_ptr = static_cast<lldb::addr_t>(result);
1175 allocation->type_ptr = type_ptr;
1176
1177 return true;
1178}
1179
1180// JITs the RS runtime for information about the dimensions and type of an allocation
1181// Then sets dimension and element_ptr members in Allocation with the result.
1182// Returns true on success, false otherwise
1183bool
1184RenderScriptRuntime::JITTypePacked(AllocationDetails* allocation, StackFrame* frame_ptr)
1185{
1186 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1187
1188 if (!allocation->type_ptr.isValid() || !allocation->context.isValid())
1189 {
1190 if (log)
1191 log->Printf("RenderScriptRuntime::JITTypePacked - Failed to find allocation details");
1192 return false;
1193 }
1194
1195 // Expression is different depending on if device is 32 or 64 bit
1196 uint32_t archByteSize = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
1197 const unsigned int bits = archByteSize == 4 ? 32 : 64;
1198
1199 // We want 4 elements from packed data
1200 const unsigned int num_exprs = 4;
1201 assert(num_exprs == (eExprTypeElemPtr - eExprTypeDimX + 1) && "Invalid number of expressions");
1202
1203 const int max_expr_size = 512; // Max expression size
1204 char buffer[num_exprs][max_expr_size];
1205 uint64_t results[num_exprs];
1206
1207 for (unsigned int i = 0; i < num_exprs; ++i)
1208 {
1209 int chars_written = snprintf(buffer[i], max_expr_size, runtimeExpressions[eExprTypeDimX + i], bits,
1210 *allocation->context.get(), *allocation->type_ptr.get());
1211 if (chars_written < 0)
1212 {
1213 if (log)
1214 log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()");
1215 return false;
1216 }
1217 else if (chars_written >= max_expr_size)
1218 {
1219 if (log)
1220 log->Printf("RenderScriptRuntime::JITTypePacked - Expression too long");
1221 return false;
1222 }
1223
1224 // Perform expression evaluation
1225 if (!EvalRSExpression(buffer[i], frame_ptr, &results[i]))
1226 return false;
1227 }
1228
1229 // Assign results to allocation members
1230 AllocationDetails::Dimension dims;
1231 dims.dim_1 = static_cast<uint32_t>(results[0]);
1232 dims.dim_2 = static_cast<uint32_t>(results[1]);
1233 dims.dim_3 = static_cast<uint32_t>(results[2]);
1234 allocation->dimension = dims;
1235
1236 addr_t elem_ptr = static_cast<lldb::addr_t>(results[3]);
1237 allocation->element_ptr = elem_ptr;
1238
1239 if (log)
1240 log->Printf("RenderScriptRuntime::JITTypePacked - dims (%u, %u, %u) Element*: 0x%" PRIx64,
1241 dims.dim_1, dims.dim_2, dims.dim_3, elem_ptr);
1242
1243 return true;
1244}
1245
1246// JITs the RS runtime for information about the Element of an allocation
1247// Then sets type, type_vec_size, and type_kind members in Allocation with the result.
1248// Returns true on success, false otherwise
1249bool
1250RenderScriptRuntime::JITElementPacked(AllocationDetails* allocation, StackFrame* frame_ptr)
1251{
1252 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1253
1254 if (!allocation->element_ptr.isValid() || !allocation->context.isValid())
1255 {
1256 if (log)
1257 log->Printf("RenderScriptRuntime::JITElementPacked - Failed to find allocation details");
1258 return false;
1259 }
1260
1261 // We want 3 elements from packed data
1262 const unsigned int num_exprs = 3;
1263 assert(num_exprs == (eExprElementVec - eExprElementType + 1) && "Invalid number of expressions");
1264
1265 const int max_expr_size = 512; // Max expression size
1266 char buffer[num_exprs][max_expr_size];
1267 uint64_t results[num_exprs];
1268
1269 for (unsigned int i = 0; i < num_exprs; i++)
1270 {
1271 int chars_written = snprintf(buffer[i], max_expr_size, runtimeExpressions[eExprElementType + i], *allocation->context.get(), *allocation->element_ptr.get());
1272 if (chars_written < 0)
1273 {
1274 if (log)
1275 log->Printf("RenderScriptRuntime::JITDataPointer - Encoding error in snprintf()");
1276 return false;
1277 }
1278 else if (chars_written >= max_expr_size)
1279 {
1280 if (log)
1281 log->Printf("RenderScriptRuntime::JITElementPacked - Expression too long");
1282 return false;
1283 }
1284
1285 // Perform expression evaluation
1286 if (!EvalRSExpression(buffer[i], frame_ptr, &results[i]))
1287 return false;
1288 }
1289
1290 // Assign results to allocation members
1291 allocation->type = static_cast<RenderScriptRuntime::AllocationDetails::DataType>(results[0]);
1292 allocation->type_kind = static_cast<RenderScriptRuntime::AllocationDetails::DataKind>(results[1]);
1293 allocation->type_vec_size = static_cast<uint32_t>(results[2]);
1294
1295 if (log)
1296 log->Printf("RenderScriptRuntime::JITElementPacked - data type %u, pixel type %u, vector size %u",
1297 *allocation->type.get(), *allocation->type_kind.get(), *allocation->type_vec_size.get());
1298
1299 return true;
1300}
1301
Ewan Crawforda0f08672015-10-16 08:28:47 +00001302// JITs the RS runtime for the address of the last element in the allocation.
1303// The `elem_size` paramter represents the size of a single element, including padding.
1304// Which is needed as an offset from the last element pointer.
1305// Using this offset minus the starting address we can calculate the size of the allocation.
1306// Returns true on success, false otherwise
1307bool
1308RenderScriptRuntime::JITAllocationSize(AllocationDetails* allocation, StackFrame* frame_ptr,
1309 const uint32_t elem_size)
1310{
1311 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1312
1313 if (!allocation->address.isValid() || !allocation->dimension.isValid()
1314 || !allocation->data_ptr.isValid())
1315 {
1316 if (log)
1317 log->Printf("RenderScriptRuntime::JITAllocationSize - Failed to find allocation details");
1318 return false;
1319 }
1320
1321 const char* expr_cstr = runtimeExpressions[eExprGetOffsetPtr];
1322 const int max_expr_size = 512; // Max expression size
1323 char buffer[max_expr_size];
1324
1325 // Find dimensions
1326 unsigned int dim_x = allocation->dimension.get()->dim_1;
1327 unsigned int dim_y = allocation->dimension.get()->dim_2;
1328 unsigned int dim_z = allocation->dimension.get()->dim_3;
1329
1330 // Calculate last element
1331 dim_x = dim_x == 0 ? 0 : dim_x - 1;
1332 dim_y = dim_y == 0 ? 0 : dim_y - 1;
1333 dim_z = dim_z == 0 ? 0 : dim_z - 1;
1334
1335 int chars_written = snprintf(buffer, max_expr_size, expr_cstr, *allocation->address.get(),
1336 dim_x, dim_y, dim_z);
1337 if (chars_written < 0)
1338 {
1339 if (log)
1340 log->Printf("RenderScriptRuntime::JITAllocationSize - Encoding error in snprintf()");
1341 return false;
1342 }
1343 else if (chars_written >= max_expr_size)
1344 {
1345 if (log)
1346 log->Printf("RenderScriptRuntime::JITAllocationSize - Expression too long");
1347 return false;
1348 }
1349
1350 uint64_t result = 0;
1351 if (!EvalRSExpression(buffer, frame_ptr, &result))
1352 return false;
1353
1354 addr_t mem_ptr = static_cast<lldb::addr_t>(result);
1355 // Find pointer to last element and add on size of an element
1356 allocation->size = static_cast<uint32_t>(mem_ptr - *allocation->data_ptr.get()) + elem_size;
1357
1358 return true;
1359}
1360
1361// JITs the RS runtime for information about the stride between rows in the allocation.
1362// This is done to detect padding, since allocated memory is 16-byte aligned.
1363// Returns true on success, false otherwise
1364bool
1365RenderScriptRuntime::JITAllocationStride(AllocationDetails* allocation, StackFrame* frame_ptr)
1366{
1367 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1368
1369 if (!allocation->address.isValid() || !allocation->data_ptr.isValid())
1370 {
1371 if (log)
1372 log->Printf("RenderScriptRuntime::JITAllocationStride - Failed to find allocation details");
1373 return false;
1374 }
1375
1376 const char* expr_cstr = runtimeExpressions[eExprGetOffsetPtr];
1377 const int max_expr_size = 512; // Max expression size
1378 char buffer[max_expr_size];
1379
1380 int chars_written = snprintf(buffer, max_expr_size, expr_cstr, *allocation->address.get(),
1381 0, 1, 0);
1382 if (chars_written < 0)
1383 {
1384 if (log)
1385 log->Printf("RenderScriptRuntime::JITAllocationStride - Encoding error in snprintf()");
1386 return false;
1387 }
1388 else if (chars_written >= max_expr_size)
1389 {
1390 if (log)
1391 log->Printf("RenderScriptRuntime::JITAllocationStride - Expression too long");
1392 return false;
1393 }
1394
1395 uint64_t result = 0;
1396 if (!EvalRSExpression(buffer, frame_ptr, &result))
1397 return false;
1398
1399 addr_t mem_ptr = static_cast<lldb::addr_t>(result);
1400 allocation->stride = static_cast<uint32_t>(mem_ptr - *allocation->data_ptr.get());
1401
1402 return true;
1403}
1404
Ewan Crawford15f2bd92015-10-06 08:42:32 +00001405// JIT all the current runtime info regarding an allocation
1406bool
1407RenderScriptRuntime::RefreshAllocation(AllocationDetails* allocation, StackFrame* frame_ptr)
1408{
1409 // GetOffsetPointer()
1410 if (!JITDataPointer(allocation, frame_ptr))
1411 return false;
1412
1413 // rsaAllocationGetType()
1414 if (!JITTypePointer(allocation, frame_ptr))
1415 return false;
1416
1417 // rsaTypeGetNativeData()
1418 if (!JITTypePacked(allocation, frame_ptr))
1419 return false;
1420
1421 // rsaElementGetNativeData()
1422 if (!JITElementPacked(allocation, frame_ptr))
1423 return false;
1424
Ewan Crawford55232f02015-10-21 08:50:42 +00001425 // Use GetOffsetPointer() to infer size of the allocation
1426 const unsigned int element_size = GetElementSize(allocation);
1427 if (!JITAllocationSize(allocation, frame_ptr, element_size))
1428 return false;
1429
1430 return true;
1431}
1432
1433// Returns the size of a single allocation element including padding.
1434// Assumes the relevant allocation information has already been jitted.
1435unsigned int
1436RenderScriptRuntime::GetElementSize(const AllocationDetails* allocation)
1437{
1438 const AllocationDetails::DataType type = *allocation->type.get();
1439 assert(type >= AllocationDetails::RS_TYPE_NONE && type <= AllocationDetails::RS_TYPE_BOOLEAN
1440 && "Invalid allocation type");
1441
1442 const unsigned int vec_size = *allocation->type_vec_size.get();
1443 const unsigned int data_size = vec_size * AllocationDetails::RSTypeToFormat[type][eElementSize];
1444 const unsigned int padding = vec_size == 3 ? AllocationDetails::RSTypeToFormat[type][eElementSize] : 0;
1445
1446 return data_size + padding;
1447}
1448
1449// Given an allocation, this function copies the allocation contents from device into a buffer on the heap.
1450// Returning a shared pointer to the buffer containing the data.
1451std::shared_ptr<uint8_t>
1452RenderScriptRuntime::GetAllocationData(AllocationDetails* allocation, StackFrame* frame_ptr)
1453{
1454 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1455
1456 // JIT all the allocation details
1457 if (!allocation->data_ptr.isValid() || !allocation->type.isValid() || !allocation->type_vec_size.isValid()
1458 || !allocation->size.isValid())
1459 {
1460 if (log)
1461 log->Printf("RenderScriptRuntime::GetAllocationData - Allocation details not calculated yet, jitting info");
1462
1463 if (!RefreshAllocation(allocation, frame_ptr))
1464 {
1465 if (log)
1466 log->Printf("RenderScriptRuntime::GetAllocationData - Couldn't JIT allocation details");
1467 return nullptr;
1468 }
1469 }
1470
1471 assert(allocation->data_ptr.isValid() && allocation->type.isValid() && allocation->type_vec_size.isValid()
1472 && allocation->size.isValid() && "Allocation information not available");
1473
1474 // Allocate a buffer to copy data into
1475 const unsigned int size = *allocation->size.get();
1476 std::shared_ptr<uint8_t> buffer(new uint8_t[size]);
1477 if (!buffer)
1478 {
1479 if (log)
1480 log->Printf("RenderScriptRuntime::GetAllocationData - Couldn't allocate a %u byte buffer", size);
1481 return nullptr;
1482 }
1483
1484 // Read the inferior memory
1485 Error error;
1486 lldb::addr_t data_ptr = *allocation->data_ptr.get();
1487 GetProcess()->ReadMemory(data_ptr, buffer.get(), size, error);
1488 if (error.Fail())
1489 {
1490 if (log)
1491 log->Printf("RenderScriptRuntime::GetAllocationData - '%s' Couldn't read %u bytes of allocation data from 0x%" PRIx64,
1492 error.AsCString(), size, data_ptr);
1493 return nullptr;
1494 }
1495
1496 return buffer;
1497}
1498
1499// Function copies data from a binary file into an allocation.
1500// There is a header at the start of the file, FileHeader, before the data content itself.
1501// Information from this header is used to display warnings to the user about incompatabilities
1502bool
1503RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id, const char* filename, StackFrame* frame_ptr)
1504{
1505 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1506
1507 // Find allocation with the given id
1508 AllocationDetails* alloc = FindAllocByID(strm, alloc_id);
1509 if (!alloc)
1510 return false;
1511
1512 if (log)
1513 log->Printf("RenderScriptRuntime::LoadAllocation - Found allocation 0x%" PRIx64, *alloc->address.get());
1514
1515 // JIT all the allocation details
1516 if (!alloc->data_ptr.isValid() || !alloc->type.isValid() || !alloc->type_vec_size.isValid() || !alloc->size.isValid())
1517 {
1518 if (log)
1519 log->Printf("RenderScriptRuntime::LoadAllocation - Allocation details not calculated yet, jitting info");
1520
1521 if (!RefreshAllocation(alloc, frame_ptr))
1522 {
1523 if (log)
1524 log->Printf("RenderScriptRuntime::LoadAllocation - Couldn't JIT allocation details");
Sylvestre Ledru4cfc9192015-10-26 08:49:04 +00001525 return false;
Ewan Crawford55232f02015-10-21 08:50:42 +00001526 }
1527 }
1528
1529 assert(alloc->data_ptr.isValid() && alloc->type.isValid() && alloc->type_vec_size.isValid() && alloc->size.isValid()
1530 && "Allocation information not available");
1531
1532 // Check we can read from file
1533 FileSpec file(filename, true);
1534 if (!file.Exists())
1535 {
1536 strm.Printf("Error: File %s does not exist", filename);
1537 strm.EOL();
1538 return false;
1539 }
1540
1541 if (!file.Readable())
1542 {
1543 strm.Printf("Error: File %s does not have readable permissions", filename);
1544 strm.EOL();
1545 return false;
1546 }
1547
1548 // Read file into data buffer
1549 DataBufferSP data_sp(file.ReadFileContents());
1550
1551 // Cast start of buffer to FileHeader and use pointer to read metadata
1552 void* file_buffer = data_sp->GetBytes();
1553 const AllocationDetails::FileHeader* head = static_cast<AllocationDetails::FileHeader*>(file_buffer);
1554
1555 // Advance buffer past header
1556 file_buffer = static_cast<uint8_t*>(file_buffer) + head->hdr_size;
1557
1558 if (log)
1559 log->Printf("RenderScriptRuntime::LoadAllocation - header type %u, element size %u",
1560 head->type, head->element_size);
1561
1562 // Check if the target allocation and file both have the same number of bytes for an Element
1563 const unsigned int elem_size = GetElementSize(alloc);
1564 if (elem_size != head->element_size)
1565 {
1566 strm.Printf("Warning: Mismatched Element sizes - file %u bytes, allocation %u bytes",
1567 head->element_size, elem_size);
1568 strm.EOL();
1569 }
1570
1571 // Check if the target allocation and file both have the same integral type
1572 const unsigned int type = static_cast<unsigned int>(*alloc->type.get());
1573 if (type != head->type)
1574 {
1575 const char* file_type_cstr = AllocationDetails::RsDataTypeToString[head->type][0];
1576 const char* alloc_type_cstr = AllocationDetails::RsDataTypeToString[type][0];
1577
1578 strm.Printf("Warning: Mismatched Types - file '%s' type, allocation '%s' type",
1579 file_type_cstr, alloc_type_cstr);
1580 strm.EOL();
1581 }
1582
1583 // Calculate size of allocation data in file
1584 size_t length = data_sp->GetByteSize() - head->hdr_size;
1585
1586 // Check if the target allocation and file both have the same total data size.
1587 const unsigned int alloc_size = *alloc->size.get();
1588 if (alloc_size != length)
1589 {
1590 strm.Printf("Warning: Mismatched allocation sizes - file 0x%" PRIx64 " bytes, allocation 0x%x bytes",
1591 length, alloc_size);
1592 strm.EOL();
1593 length = alloc_size < length ? alloc_size : length; // Set length to copy to minimum
1594 }
1595
1596 // Copy file data from our buffer into the target allocation.
1597 lldb::addr_t alloc_data = *alloc->data_ptr.get();
1598 Error error;
1599 size_t bytes_written = GetProcess()->WriteMemory(alloc_data, file_buffer, length, error);
1600 if (!error.Success() || bytes_written != length)
1601 {
1602 strm.Printf("Error: Couldn't write data to allocation %s", error.AsCString());
1603 strm.EOL();
1604 return false;
1605 }
1606
1607 strm.Printf("Contents of file '%s' read into allocation %u", filename, alloc->id);
1608 strm.EOL();
1609
1610 return true;
1611}
1612
1613// Function copies allocation contents into a binary file.
1614// This file can then be loaded later into a different allocation.
1615// There is a header, FileHeader, before the allocation data containing meta-data.
1616bool
1617RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id, const char* filename, StackFrame* frame_ptr)
1618{
1619 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1620
1621 // Find allocation with the given id
1622 AllocationDetails* alloc = FindAllocByID(strm, alloc_id);
1623 if (!alloc)
1624 return false;
1625
1626 if (log)
1627 log->Printf("RenderScriptRuntime::SaveAllocation - Found allocation 0x%" PRIx64, *alloc->address.get());
1628
1629 // JIT all the allocation details
1630 if (!alloc->data_ptr.isValid() || !alloc->type.isValid() || !alloc->type_vec_size.isValid()
1631 || !alloc->type_kind.isValid() || !alloc->dimension.isValid())
1632 {
1633 if (log)
1634 log->Printf("RenderScriptRuntime::SaveAllocation - Allocation details not calculated yet, jitting info");
1635
1636 if (!RefreshAllocation(alloc, frame_ptr))
1637 {
1638 if (log)
1639 log->Printf("RenderScriptRuntime::SaveAllocation - Couldn't JIT allocation details");
Sylvestre Ledru4cfc9192015-10-26 08:49:04 +00001640 return false;
Ewan Crawford55232f02015-10-21 08:50:42 +00001641 }
1642 }
1643
1644 assert(alloc->data_ptr.isValid() && alloc->type.isValid() && alloc->type_vec_size.isValid() && alloc->type_kind.isValid()
1645 && alloc->dimension.isValid() && "Allocation information not available");
1646
1647 // Check we can create writable file
1648 FileSpec file_spec(filename, true);
1649 File file(file_spec, File::eOpenOptionWrite | File::eOpenOptionCanCreate | File::eOpenOptionTruncate);
1650 if (!file)
1651 {
1652 strm.Printf("Error: Failed to open '%s' for writing", filename);
1653 strm.EOL();
1654 return false;
1655 }
1656
1657 // Read allocation into buffer of heap memory
1658 const std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr);
1659 if (!buffer)
1660 {
1661 strm.Printf("Error: Couldn't read allocation data into buffer");
1662 strm.EOL();
1663 return false;
1664 }
1665
1666 // Create the file header
1667 AllocationDetails::FileHeader head;
1668 head.ident[0] = 'R'; head.ident[1] = 'S'; head.ident[2] = 'A'; head.ident[3] = 'D';
1669 head.hdr_size = static_cast<uint16_t>(sizeof(AllocationDetails::FileHeader));
1670 head.type = static_cast<uint16_t>(*alloc->type.get());
1671 head.kind = static_cast<uint32_t>(*alloc->type_kind.get());
Ewan Crawford2d623282015-10-21 10:27:10 +00001672 head.dims[0] = static_cast<uint32_t>(alloc->dimension.get()->dim_1);
1673 head.dims[1] = static_cast<uint32_t>(alloc->dimension.get()->dim_2);
1674 head.dims[2] = static_cast<uint32_t>(alloc->dimension.get()->dim_3);
Ewan Crawford55232f02015-10-21 08:50:42 +00001675 head.element_size = static_cast<uint32_t>(GetElementSize(alloc));
1676
1677 // Write the file header
1678 size_t num_bytes = sizeof(AllocationDetails::FileHeader);
1679 Error err = file.Write(static_cast<const void*>(&head), num_bytes);
1680 if (!err.Success())
1681 {
1682 strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), filename);
1683 strm.EOL();
1684 return false;
1685 }
1686
1687 // Write allocation data to file
1688 num_bytes = static_cast<size_t>(*alloc->size.get());
1689 if (log)
1690 log->Printf("RenderScriptRuntime::SaveAllocation - Writing %" PRIx64 "bytes from %p", num_bytes, buffer.get());
1691
1692 err = file.Write(buffer.get(), num_bytes);
1693 if (!err.Success())
1694 {
1695 strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), filename);
1696 strm.EOL();
1697 return false;
1698 }
1699
1700 strm.Printf("Allocation written to file '%s'", filename);
1701 strm.EOL();
Ewan Crawford15f2bd92015-10-06 08:42:32 +00001702 return true;
1703}
1704
Colin Riley5ec532a2015-04-09 16:49:25 +00001705bool
1706RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp)
1707{
Colin Riley4640cde2015-06-01 18:23:41 +00001708 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
1709
Colin Riley5ec532a2015-04-09 16:49:25 +00001710 if (module_sp)
1711 {
1712 for (const auto &rs_module : m_rsmodules)
1713 {
Colin Riley4640cde2015-06-01 18:23:41 +00001714 if (rs_module->m_module == module_sp)
Ewan Crawford7dc77712015-09-10 10:08:48 +00001715 {
1716 // Check if the user has enabled automatically breaking on
1717 // all RS kernels.
1718 if (m_breakAllKernels)
1719 BreakOnModuleKernels(rs_module);
1720
Colin Riley5ec532a2015-04-09 16:49:25 +00001721 return false;
Ewan Crawford7dc77712015-09-10 10:08:48 +00001722 }
Colin Riley5ec532a2015-04-09 16:49:25 +00001723 }
Colin Rileyef20b082015-04-14 07:39:24 +00001724 bool module_loaded = false;
1725 switch (GetModuleKind(module_sp))
Colin Riley5ec532a2015-04-09 16:49:25 +00001726 {
Colin Rileyef20b082015-04-14 07:39:24 +00001727 case eModuleKindKernelObj:
1728 {
Colin Riley4640cde2015-06-01 18:23:41 +00001729 RSModuleDescriptorSP module_desc;
1730 module_desc.reset(new RSModuleDescriptor(module_sp));
1731 if (module_desc->ParseRSInfo())
Colin Rileyef20b082015-04-14 07:39:24 +00001732 {
1733 m_rsmodules.push_back(module_desc);
1734 module_loaded = true;
1735 }
Colin Riley4640cde2015-06-01 18:23:41 +00001736 if (module_loaded)
1737 {
1738 FixupScriptDetails(module_desc);
1739 }
Colin Rileyef20b082015-04-14 07:39:24 +00001740 break;
1741 }
1742 case eModuleKindDriver:
Colin Riley4640cde2015-06-01 18:23:41 +00001743 {
1744 if (!m_libRSDriver)
1745 {
1746 m_libRSDriver = module_sp;
1747 LoadRuntimeHooks(m_libRSDriver, RenderScriptRuntime::eModuleKindDriver);
1748 }
1749 break;
1750 }
Colin Rileyef20b082015-04-14 07:39:24 +00001751 case eModuleKindImpl:
Colin Riley4640cde2015-06-01 18:23:41 +00001752 {
1753 m_libRSCpuRef = module_sp;
1754 break;
1755 }
Colin Rileyef20b082015-04-14 07:39:24 +00001756 case eModuleKindLibRS:
Colin Riley4640cde2015-06-01 18:23:41 +00001757 {
1758 if (!m_libRS)
1759 {
1760 m_libRS = module_sp;
1761 static ConstString gDbgPresentStr("gDebuggerPresent");
1762 const Symbol* debug_present = m_libRS->FindFirstSymbolWithNameAndType(gDbgPresentStr, eSymbolTypeData);
1763 if (debug_present)
1764 {
1765 Error error;
1766 uint32_t flag = 0x00000001U;
1767 Target &target = GetProcess()->GetTarget();
Greg Clayton358cf1e2015-06-25 21:46:34 +00001768 addr_t addr = debug_present->GetLoadAddress(&target);
Colin Riley4640cde2015-06-01 18:23:41 +00001769 GetProcess()->WriteMemory(addr, &flag, sizeof(flag), error);
1770 if(error.Success())
1771 {
1772 if (log)
1773 log->Printf ("RenderScriptRuntime::LoadModule - Debugger present flag set on debugee");
1774
1775 m_debuggerPresentFlagged = true;
1776 }
1777 else if (log)
1778 {
1779 log->Printf ("RenderScriptRuntime::LoadModule - Error writing debugger present flags '%s' ", error.AsCString());
1780 }
1781 }
1782 else if (log)
1783 {
1784 log->Printf ("RenderScriptRuntime::LoadModule - Error writing debugger present flags - symbol not found");
1785 }
1786 }
1787 break;
1788 }
Colin Rileyef20b082015-04-14 07:39:24 +00001789 default:
1790 break;
Colin Riley5ec532a2015-04-09 16:49:25 +00001791 }
Colin Rileyef20b082015-04-14 07:39:24 +00001792 if (module_loaded)
1793 Update();
1794 return module_loaded;
Colin Riley5ec532a2015-04-09 16:49:25 +00001795 }
1796 return false;
1797}
1798
Colin Rileyef20b082015-04-14 07:39:24 +00001799void
1800RenderScriptRuntime::Update()
1801{
1802 if (m_rsmodules.size() > 0)
1803 {
1804 if (!m_initiated)
1805 {
1806 Initiate();
1807 }
1808 }
1809}
1810
1811
Colin Riley5ec532a2015-04-09 16:49:25 +00001812// The maximum line length of an .rs.info packet
1813#define MAXLINE 500
1814
1815// The .rs.info symbol in renderscript modules contains a string which needs to be parsed.
1816// The string is basic and is parsed on a line by line basis.
1817bool
1818RSModuleDescriptor::ParseRSInfo()
1819{
1820 const Symbol *info_sym = m_module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), eSymbolTypeData);
1821 if (info_sym)
1822 {
Greg Clayton358cf1e2015-06-25 21:46:34 +00001823 const addr_t addr = info_sym->GetAddressRef().GetFileAddress();
Colin Riley5ec532a2015-04-09 16:49:25 +00001824 const addr_t size = info_sym->GetByteSize();
1825 const FileSpec fs = m_module->GetFileSpec();
1826
1827 DataBufferSP buffer = fs.ReadFileContents(addr, size);
1828
1829 if (!buffer)
1830 return false;
1831
1832 std::string info((const char *)buffer->GetBytes());
1833
1834 std::vector<std::string> info_lines;
Bruce Mitchenere8433cc2015-09-01 23:57:17 +00001835 size_t lpos = info.find('\n');
Colin Riley5ec532a2015-04-09 16:49:25 +00001836 while (lpos != std::string::npos)
1837 {
1838 info_lines.push_back(info.substr(0, lpos));
1839 info = info.substr(lpos + 1);
Bruce Mitchenere8433cc2015-09-01 23:57:17 +00001840 lpos = info.find('\n');
Colin Riley5ec532a2015-04-09 16:49:25 +00001841 }
1842 size_t offset = 0;
1843 while (offset < info_lines.size())
1844 {
1845 std::string line = info_lines[offset];
1846 // Parse directives
1847 uint32_t numDefns = 0;
1848 if (sscanf(line.c_str(), "exportVarCount: %u", &numDefns) == 1)
1849 {
1850 while (numDefns--)
Colin Riley4640cde2015-06-01 18:23:41 +00001851 m_globals.push_back(RSGlobalDescriptor(this, info_lines[++offset].c_str()));
Colin Riley5ec532a2015-04-09 16:49:25 +00001852 }
1853 else if (sscanf(line.c_str(), "exportFuncCount: %u", &numDefns) == 1)
1854 {
1855 }
1856 else if (sscanf(line.c_str(), "exportForEachCount: %u", &numDefns) == 1)
1857 {
1858 char name[MAXLINE];
1859 while (numDefns--)
1860 {
1861 uint32_t slot = 0;
1862 name[0] = '\0';
1863 if (sscanf(info_lines[++offset].c_str(), "%u - %s", &slot, &name[0]) == 2)
1864 {
Colin Riley4640cde2015-06-01 18:23:41 +00001865 m_kernels.push_back(RSKernelDescriptor(this, name, slot));
1866 }
1867 }
1868 }
1869 else if (sscanf(line.c_str(), "pragmaCount: %u", &numDefns) == 1)
1870 {
1871 char name[MAXLINE];
1872 char value[MAXLINE];
1873 while (numDefns--)
1874 {
1875 name[0] = '\0';
1876 value[0] = '\0';
1877 if (sscanf(info_lines[++offset].c_str(), "%s - %s", &name[0], &value[0]) != 0
1878 && (name[0] != '\0'))
1879 {
1880 m_pragmas[std::string(name)] = value;
Colin Riley5ec532a2015-04-09 16:49:25 +00001881 }
1882 }
1883 }
1884 else if (sscanf(line.c_str(), "objectSlotCount: %u", &numDefns) == 1)
1885 {
1886 }
1887
1888 offset++;
1889 }
1890 return m_kernels.size() > 0;
1891 }
1892 return false;
1893}
1894
1895bool
1896RenderScriptRuntime::ProbeModules(const ModuleList module_list)
1897{
1898 bool rs_found = false;
1899 size_t num_modules = module_list.GetSize();
1900 for (size_t i = 0; i < num_modules; i++)
1901 {
1902 auto module = module_list.GetModuleAtIndex(i);
1903 rs_found |= LoadModule(module);
1904 }
1905 return rs_found;
1906}
1907
1908void
Colin Riley4640cde2015-06-01 18:23:41 +00001909RenderScriptRuntime::Status(Stream &strm) const
1910{
1911 if (m_libRS)
1912 {
1913 strm.Printf("Runtime Library discovered.");
1914 strm.EOL();
1915 }
1916 if (m_libRSDriver)
1917 {
1918 strm.Printf("Runtime Driver discovered.");
1919 strm.EOL();
1920 }
1921 if (m_libRSCpuRef)
1922 {
1923 strm.Printf("CPU Reference Implementation discovered.");
1924 strm.EOL();
1925 }
1926
1927 if (m_runtimeHooks.size())
1928 {
1929 strm.Printf("Runtime functions hooked:");
1930 strm.EOL();
1931 for (auto b : m_runtimeHooks)
1932 {
1933 strm.Indent(b.second->defn->name);
1934 strm.EOL();
1935 }
1936 strm.EOL();
1937 }
1938 else
1939 {
1940 strm.Printf("Runtime is not hooked.");
1941 strm.EOL();
1942 }
1943}
1944
1945void
1946RenderScriptRuntime::DumpContexts(Stream &strm) const
1947{
1948 strm.Printf("Inferred RenderScript Contexts:");
1949 strm.EOL();
1950 strm.IndentMore();
1951
1952 std::map<addr_t, uint64_t> contextReferences;
1953
Ewan Crawford78f339d2015-09-21 10:53:18 +00001954 // Iterate over all of the currently discovered scripts.
1955 // Note: We cant push or pop from m_scripts inside this loop or it may invalidate script.
1956 for (const auto & script : m_scripts)
Colin Riley4640cde2015-06-01 18:23:41 +00001957 {
Ewan Crawford78f339d2015-09-21 10:53:18 +00001958 if (!script->context.isValid())
1959 continue;
1960 lldb::addr_t context = *script->context;
1961
1962 if (contextReferences.find(context) != contextReferences.end())
Colin Riley4640cde2015-06-01 18:23:41 +00001963 {
Ewan Crawford78f339d2015-09-21 10:53:18 +00001964 contextReferences[context]++;
Colin Riley4640cde2015-06-01 18:23:41 +00001965 }
1966 else
1967 {
Ewan Crawford78f339d2015-09-21 10:53:18 +00001968 contextReferences[context] = 1;
Colin Riley4640cde2015-06-01 18:23:41 +00001969 }
1970 }
1971
1972 for (const auto& cRef : contextReferences)
1973 {
1974 strm.Printf("Context 0x%" PRIx64 ": %" PRIu64 " script instances", cRef.first, cRef.second);
1975 strm.EOL();
1976 }
1977 strm.IndentLess();
1978}
1979
1980void
1981RenderScriptRuntime::DumpKernels(Stream &strm) const
1982{
1983 strm.Printf("RenderScript Kernels:");
1984 strm.EOL();
1985 strm.IndentMore();
1986 for (const auto &module : m_rsmodules)
1987 {
1988 strm.Printf("Resource '%s':",module->m_resname.c_str());
1989 strm.EOL();
1990 for (const auto &kernel : module->m_kernels)
1991 {
1992 strm.Indent(kernel.m_name.AsCString());
1993 strm.EOL();
1994 }
1995 }
1996 strm.IndentLess();
1997}
1998
Ewan Crawforda0f08672015-10-16 08:28:47 +00001999RenderScriptRuntime::AllocationDetails*
2000RenderScriptRuntime::FindAllocByID(Stream &strm, const uint32_t alloc_id)
2001{
2002 AllocationDetails* alloc = nullptr;
2003
2004 // See if we can find allocation using id as an index;
2005 if (alloc_id <= m_allocations.size() && alloc_id != 0
2006 && m_allocations[alloc_id-1]->id == alloc_id)
2007 {
2008 alloc = m_allocations[alloc_id-1].get();
2009 return alloc;
2010 }
2011
2012 // Fallback to searching
2013 for (const auto & a : m_allocations)
2014 {
2015 if (a->id == alloc_id)
2016 {
2017 alloc = a.get();
2018 break;
2019 }
2020 }
2021
2022 if (alloc == nullptr)
2023 {
2024 strm.Printf("Error: Couldn't find allocation with id matching %u", alloc_id);
2025 strm.EOL();
2026 }
2027
2028 return alloc;
2029}
2030
2031// Prints the contents of an allocation to the output stream, which may be a file
2032bool
2033RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame* frame_ptr, const uint32_t id)
2034{
2035 Log* log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
2036
2037 // Check we can find the desired allocation
2038 AllocationDetails* alloc = FindAllocByID(strm, id);
2039 if (!alloc)
2040 return false; // FindAllocByID() will print error message for us here
2041
2042 if (log)
2043 log->Printf("RenderScriptRuntime::DumpAllocation - Found allocation 0x%" PRIx64, *alloc->address.get());
2044
2045 // Check we have information about the allocation, if not calculate it
2046 if (!alloc->data_ptr.isValid() || !alloc->type.isValid() ||
2047 !alloc->type_vec_size.isValid() || !alloc->dimension.isValid())
2048 {
2049 if (log)
2050 log->Printf("RenderScriptRuntime::DumpAllocation - Allocation details not calculated yet, jitting info");
2051
2052 // JIT all the allocation information
2053 if (!RefreshAllocation(alloc, frame_ptr))
2054 {
2055 strm.Printf("Error: Couldn't JIT allocation details");
2056 strm.EOL();
2057 return false;
2058 }
2059 }
2060
2061 // Establish format and size of each data element
2062 const unsigned int vec_size = *alloc->type_vec_size.get();
2063 const AllocationDetails::DataType type = *alloc->type.get();
2064
2065 assert(type >= AllocationDetails::RS_TYPE_NONE && type <= AllocationDetails::RS_TYPE_BOOLEAN
2066 && "Invalid allocation type");
2067
2068 lldb::Format format = vec_size == 1 ? static_cast<lldb::Format>(AllocationDetails::RSTypeToFormat[type][eFormatSingle])
2069 : static_cast<lldb::Format>(AllocationDetails::RSTypeToFormat[type][eFormatVector]);
2070
2071 const unsigned int data_size = vec_size * AllocationDetails::RSTypeToFormat[type][eElementSize];
2072 // Renderscript pads vector 3 elements to vector 4
2073 const unsigned int elem_padding = vec_size == 3 ? AllocationDetails::RSTypeToFormat[type][eElementSize] : 0;
2074
2075 if (log)
2076 log->Printf("RenderScriptRuntime::DumpAllocation - Element size %u bytes, element padding %u bytes",
2077 data_size, elem_padding);
2078
Ewan Crawford55232f02015-10-21 08:50:42 +00002079 // Allocate a buffer to copy data into
2080 std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr);
2081 if (!buffer)
2082 {
2083 strm.Printf("Error: Couldn't allocate a read allocation data into memory");
2084 strm.EOL();
2085 return false;
2086 }
2087
Ewan Crawforda0f08672015-10-16 08:28:47 +00002088 // Calculate stride between rows as there may be padding at end of rows since
2089 // allocated memory is 16-byte aligned
2090 if (!alloc->stride.isValid())
2091 {
2092 if (alloc->dimension.get()->dim_2 == 0) // We only have one dimension
2093 alloc->stride = 0;
2094 else if (!JITAllocationStride(alloc, frame_ptr))
2095 {
2096 strm.Printf("Error: Couldn't calculate allocation row stride");
2097 strm.EOL();
2098 return false;
2099 }
2100 }
2101 const unsigned int stride = *alloc->stride.get();
Ewan Crawforda0f08672015-10-16 08:28:47 +00002102 const unsigned int size = *alloc->size.get(); //size of last element
2103
2104 if (log)
2105 log->Printf("RenderScriptRuntime::DumpAllocation - stride %u bytes, size %u bytes", stride, size);
2106
Ewan Crawforda0f08672015-10-16 08:28:47 +00002107 // Find dimensions used to index loops, so need to be non-zero
2108 unsigned int dim_x = alloc->dimension.get()->dim_1;
2109 dim_x = dim_x == 0 ? 1 : dim_x;
2110
2111 unsigned int dim_y = alloc->dimension.get()->dim_2;
2112 dim_y = dim_y == 0 ? 1 : dim_y;
2113
2114 unsigned int dim_z = alloc->dimension.get()->dim_3;
2115 dim_z = dim_z == 0 ? 1 : dim_z;
2116
Ewan Crawford55232f02015-10-21 08:50:42 +00002117 // Use data extractor to format output
2118 const uint32_t archByteSize = GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
2119 DataExtractor alloc_data(buffer.get(), size, GetProcess()->GetByteOrder(), archByteSize);
2120
Ewan Crawforda0f08672015-10-16 08:28:47 +00002121 unsigned int offset = 0; // Offset in buffer to next element to be printed
2122 unsigned int prev_row = 0; // Offset to the start of the previous row
2123
2124 // Iterate over allocation dimensions, printing results to user
2125 strm.Printf("Data (X, Y, Z):");
2126 for (unsigned int z = 0; z < dim_z; ++z)
2127 {
2128 for (unsigned int y = 0; y < dim_y; ++y)
2129 {
2130 // Use stride to index start of next row.
2131 if (!(y==0 && z==0))
2132 offset = prev_row + stride;
2133 prev_row = offset;
2134
2135 // Print each element in the row individually
2136 for (unsigned int x = 0; x < dim_x; ++x)
2137 {
2138 strm.Printf("\n(%u, %u, %u) = ", x, y, z);
2139 alloc_data.Dump(&strm, offset, format, data_size, 1, 1, LLDB_INVALID_ADDRESS, 0, 0);
2140 offset += data_size + elem_padding;
2141 }
2142 }
2143 }
2144 strm.EOL();
2145
Ewan Crawforda0f08672015-10-16 08:28:47 +00002146 return true;
2147}
2148
Ewan Crawford15f2bd92015-10-06 08:42:32 +00002149// Prints infomation regarding all the currently loaded allocations.
2150// These details are gathered by jitting the runtime, which has as latency.
2151void
2152RenderScriptRuntime::ListAllocations(Stream &strm, StackFrame* frame_ptr, bool recompute)
2153{
2154 strm.Printf("RenderScript Allocations:");
2155 strm.EOL();
2156 strm.IndentMore();
2157
2158 for (auto &alloc : m_allocations)
2159 {
2160 // JIT the allocation info if we haven't done it, or the user forces us to.
2161 bool do_refresh = !alloc->data_ptr.isValid() || recompute;
2162
2163 // JIT current allocation information
2164 if (do_refresh && !RefreshAllocation(alloc.get(), frame_ptr))
2165 {
2166 strm.Printf("Error: Couldn't evaluate details for allocation %u\n", alloc->id);
2167 continue;
2168 }
2169
2170 strm.Printf("%u:\n",alloc->id);
2171 strm.IndentMore();
2172
2173 strm.Indent("Context: ");
2174 if (!alloc->context.isValid())
2175 strm.Printf("unknown\n");
2176 else
2177 strm.Printf("0x%" PRIx64 "\n", *alloc->context.get());
2178
2179 strm.Indent("Address: ");
2180 if (!alloc->address.isValid())
2181 strm.Printf("unknown\n");
2182 else
2183 strm.Printf("0x%" PRIx64 "\n", *alloc->address.get());
2184
2185 strm.Indent("Data pointer: ");
2186 if (!alloc->data_ptr.isValid())
2187 strm.Printf("unknown\n");
2188 else
2189 strm.Printf("0x%" PRIx64 "\n", *alloc->data_ptr.get());
2190
2191 strm.Indent("Dimensions: ");
2192 if (!alloc->dimension.isValid())
2193 strm.Printf("unknown\n");
2194 else
2195 strm.Printf("(%d, %d, %d)\n", alloc->dimension.get()->dim_1,
2196 alloc->dimension.get()->dim_2,
2197 alloc->dimension.get()->dim_3);
2198
2199 strm.Indent("Data Type: ");
2200 if (!alloc->type.isValid() || !alloc->type_vec_size.isValid())
2201 strm.Printf("unknown\n");
2202 else
2203 {
2204 const int vector_size = *alloc->type_vec_size.get();
2205 const AllocationDetails::DataType type = *alloc->type.get();
2206
2207 if (vector_size > 4 || vector_size < 1 ||
2208 type < AllocationDetails::RS_TYPE_NONE || type > AllocationDetails::RS_TYPE_BOOLEAN)
2209 strm.Printf("invalid type\n");
2210 else
2211 strm.Printf("%s\n", AllocationDetails::RsDataTypeToString[static_cast<unsigned int>(type)][vector_size-1]);
2212 }
2213
2214 strm.Indent("Data Kind: ");
2215 if (!alloc->type_kind.isValid())
2216 strm.Printf("unknown\n");
2217 else
2218 {
2219 const AllocationDetails::DataKind kind = *alloc->type_kind.get();
2220 if (kind < AllocationDetails::RS_KIND_USER || kind > AllocationDetails::RS_KIND_PIXEL_YUV)
2221 strm.Printf("invalid kind\n");
2222 else
2223 strm.Printf("%s\n", AllocationDetails::RsDataKindToString[static_cast<unsigned int>(kind)]);
2224 }
2225
2226 strm.EOL();
2227 strm.IndentLess();
2228 }
2229 strm.IndentLess();
2230}
2231
Ewan Crawford7dc77712015-09-10 10:08:48 +00002232// Set breakpoints on every kernel found in RS module
2233void
2234RenderScriptRuntime::BreakOnModuleKernels(const RSModuleDescriptorSP rsmodule_sp)
2235{
2236 for (const auto &kernel : rsmodule_sp->m_kernels)
2237 {
2238 // Don't set breakpoint on 'root' kernel
2239 if (strcmp(kernel.m_name.AsCString(), "root") == 0)
2240 continue;
2241
2242 CreateKernelBreakpoint(kernel.m_name);
2243 }
2244}
2245
2246// Method is internally called by the 'kernel breakpoint all' command to
2247// enable or disable breaking on all kernels.
2248//
2249// When do_break is true we want to enable this functionality.
2250// When do_break is false we want to disable it.
2251void
2252RenderScriptRuntime::SetBreakAllKernels(bool do_break, TargetSP target)
2253{
Ewan Crawford54782db2015-09-16 10:02:57 +00002254 Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
Ewan Crawford7dc77712015-09-10 10:08:48 +00002255
2256 InitSearchFilter(target);
2257
2258 // Set breakpoints on all the kernels
2259 if (do_break && !m_breakAllKernels)
2260 {
2261 m_breakAllKernels = true;
2262
2263 for (const auto &module : m_rsmodules)
2264 BreakOnModuleKernels(module);
2265
2266 if (log)
2267 log->Printf("RenderScriptRuntime::SetBreakAllKernels(True)"
2268 "- breakpoints set on all currently loaded kernels");
2269 }
2270 else if (!do_break && m_breakAllKernels) // Breakpoints won't be set on any new kernels.
2271 {
2272 m_breakAllKernels = false;
2273
2274 if (log)
2275 log->Printf("RenderScriptRuntime::SetBreakAllKernels(False) - breakpoints no longer automatically set");
2276 }
2277}
2278
2279// Given the name of a kernel this function creates a breakpoint using our
2280// own breakpoint resolver, and returns the Breakpoint shared pointer.
2281BreakpointSP
2282RenderScriptRuntime::CreateKernelBreakpoint(const ConstString& name)
2283{
Ewan Crawford54782db2015-09-16 10:02:57 +00002284 Log* log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));
Ewan Crawford7dc77712015-09-10 10:08:48 +00002285
2286 if (!m_filtersp)
2287 {
2288 if (log)
2289 log->Printf("RenderScriptRuntime::CreateKernelBreakpoint - Error: No breakpoint search filter set");
2290 return nullptr;
2291 }
2292
2293 BreakpointResolverSP resolver_sp(new RSBreakpointResolver(nullptr, name));
2294 BreakpointSP bp = GetProcess()->GetTarget().CreateBreakpoint(m_filtersp, resolver_sp, false, false, false);
2295
Ewan Crawford54782db2015-09-16 10:02:57 +00002296 // Give RS breakpoints a specific name, so the user can manipulate them as a group.
2297 Error err;
2298 if (!bp->AddName("RenderScriptKernel", err) && log)
2299 log->Printf("RenderScriptRuntime::CreateKernelBreakpoint: Error setting break name, %s", err.AsCString());
2300
Ewan Crawford7dc77712015-09-10 10:08:48 +00002301 return bp;
2302}
2303
Ewan Crawford98156582015-09-04 08:56:52 +00002304void
2305RenderScriptRuntime::AttemptBreakpointAtKernelName(Stream &strm, const char* name, Error& error, TargetSP target)
Colin Riley4640cde2015-06-01 18:23:41 +00002306{
Ewan Crawford98156582015-09-04 08:56:52 +00002307 if (!name)
Colin Riley4640cde2015-06-01 18:23:41 +00002308 {
2309 error.SetErrorString("invalid kernel name");
2310 return;
2311 }
2312
Ewan Crawford7dc77712015-09-10 10:08:48 +00002313 InitSearchFilter(target);
Ewan Crawford98156582015-09-04 08:56:52 +00002314
Colin Riley4640cde2015-06-01 18:23:41 +00002315 ConstString kernel_name(name);
Ewan Crawford7dc77712015-09-10 10:08:48 +00002316 BreakpointSP bp = CreateKernelBreakpoint(kernel_name);
Ewan Crawford98156582015-09-04 08:56:52 +00002317 if (bp)
2318 bp->GetDescription(&strm, lldb::eDescriptionLevelInitial, false);
Colin Riley4640cde2015-06-01 18:23:41 +00002319
Colin Riley4640cde2015-06-01 18:23:41 +00002320 return;
2321}
2322
2323void
Colin Riley5ec532a2015-04-09 16:49:25 +00002324RenderScriptRuntime::DumpModules(Stream &strm) const
2325{
2326 strm.Printf("RenderScript Modules:");
2327 strm.EOL();
2328 strm.IndentMore();
2329 for (const auto &module : m_rsmodules)
2330 {
Colin Riley4640cde2015-06-01 18:23:41 +00002331 module->Dump(strm);
Colin Riley5ec532a2015-04-09 16:49:25 +00002332 }
2333 strm.IndentLess();
2334}
2335
Ewan Crawford78f339d2015-09-21 10:53:18 +00002336RenderScriptRuntime::ScriptDetails*
2337RenderScriptRuntime::LookUpScript(addr_t address, bool create)
2338{
2339 for (const auto & s : m_scripts)
2340 {
2341 if (s->script.isValid())
2342 if (*s->script == address)
2343 return s.get();
2344 }
2345 if (create)
2346 {
2347 std::unique_ptr<ScriptDetails> s(new ScriptDetails);
2348 s->script = address;
2349 m_scripts.push_back(std::move(s));
Ewan Crawfordd10ca9d2015-09-22 13:36:35 +00002350 return m_scripts.back().get();
Ewan Crawford78f339d2015-09-21 10:53:18 +00002351 }
2352 return nullptr;
2353}
2354
2355RenderScriptRuntime::AllocationDetails*
2356RenderScriptRuntime::LookUpAllocation(addr_t address, bool create)
2357{
2358 for (const auto & a : m_allocations)
2359 {
2360 if (a->address.isValid())
2361 if (*a->address == address)
2362 return a.get();
2363 }
2364 if (create)
2365 {
2366 std::unique_ptr<AllocationDetails> a(new AllocationDetails);
2367 a->address = address;
2368 m_allocations.push_back(std::move(a));
Ewan Crawfordd10ca9d2015-09-22 13:36:35 +00002369 return m_allocations.back().get();
Ewan Crawford78f339d2015-09-21 10:53:18 +00002370 }
2371 return nullptr;
2372}
2373
Colin Riley5ec532a2015-04-09 16:49:25 +00002374void
2375RSModuleDescriptor::Dump(Stream &strm) const
2376{
2377 strm.Indent();
2378 m_module->GetFileSpec().Dump(&strm);
Colin Riley4640cde2015-06-01 18:23:41 +00002379 if(m_module->GetNumCompileUnits())
2380 {
2381 strm.Indent("Debug info loaded.");
2382 }
2383 else
2384 {
2385 strm.Indent("Debug info does not exist.");
2386 }
Colin Riley5ec532a2015-04-09 16:49:25 +00002387 strm.EOL();
2388 strm.IndentMore();
2389 strm.Indent();
Colin Riley189598e2015-04-12 22:05:58 +00002390 strm.Printf("Globals: %" PRIu64, static_cast<uint64_t>(m_globals.size()));
Colin Riley5ec532a2015-04-09 16:49:25 +00002391 strm.EOL();
2392 strm.IndentMore();
2393 for (const auto &global : m_globals)
2394 {
2395 global.Dump(strm);
2396 }
2397 strm.IndentLess();
2398 strm.Indent();
Colin Riley189598e2015-04-12 22:05:58 +00002399 strm.Printf("Kernels: %" PRIu64, static_cast<uint64_t>(m_kernels.size()));
Colin Riley5ec532a2015-04-09 16:49:25 +00002400 strm.EOL();
2401 strm.IndentMore();
2402 for (const auto &kernel : m_kernels)
2403 {
2404 kernel.Dump(strm);
2405 }
Colin Riley4640cde2015-06-01 18:23:41 +00002406 strm.Printf("Pragmas: %" PRIu64 , static_cast<uint64_t>(m_pragmas.size()));
2407 strm.EOL();
2408 strm.IndentMore();
2409 for (const auto &key_val : m_pragmas)
2410 {
2411 strm.Printf("%s: %s", key_val.first.c_str(), key_val.second.c_str());
2412 strm.EOL();
2413 }
Colin Riley5ec532a2015-04-09 16:49:25 +00002414 strm.IndentLess(4);
2415}
2416
2417void
2418RSGlobalDescriptor::Dump(Stream &strm) const
2419{
2420 strm.Indent(m_name.AsCString());
Colin Riley4640cde2015-06-01 18:23:41 +00002421 VariableList var_list;
2422 m_module->m_module->FindGlobalVariables(m_name, nullptr, true, 1U, var_list);
2423 if (var_list.GetSize() == 1)
2424 {
2425 auto var = var_list.GetVariableAtIndex(0);
2426 auto type = var->GetType();
2427 if(type)
2428 {
2429 strm.Printf(" - ");
2430 type->DumpTypeName(&strm);
2431 }
2432 else
2433 {
2434 strm.Printf(" - Unknown Type");
2435 }
2436 }
2437 else
2438 {
2439 strm.Printf(" - variable identified, but not found in binary");
2440 const Symbol* s = m_module->m_module->FindFirstSymbolWithNameAndType(m_name, eSymbolTypeData);
2441 if (s)
2442 {
2443 strm.Printf(" (symbol exists) ");
2444 }
2445 }
2446
Colin Riley5ec532a2015-04-09 16:49:25 +00002447 strm.EOL();
2448}
2449
2450void
2451RSKernelDescriptor::Dump(Stream &strm) const
2452{
2453 strm.Indent(m_name.AsCString());
2454 strm.EOL();
2455}
2456
2457class CommandObjectRenderScriptRuntimeModuleProbe : public CommandObjectParsed
2458{
2459 private:
2460 public:
2461 CommandObjectRenderScriptRuntimeModuleProbe(CommandInterpreter &interpreter)
2462 : CommandObjectParsed(interpreter, "renderscript module probe",
2463 "Initiates a Probe of all loaded modules for kernels and other renderscript objects.",
2464 "renderscript module probe",
Enrico Granatae87764f2015-05-27 05:04:35 +00002465 eCommandRequiresTarget | eCommandRequiresProcess | eCommandProcessMustBeLaunched)
Colin Riley5ec532a2015-04-09 16:49:25 +00002466 {
2467 }
2468
2469 ~CommandObjectRenderScriptRuntimeModuleProbe() {}
2470
2471 bool
2472 DoExecute(Args &command, CommandReturnObject &result)
2473 {
2474 const size_t argc = command.GetArgumentCount();
2475 if (argc == 0)
2476 {
2477 Target *target = m_exe_ctx.GetTargetPtr();
2478 RenderScriptRuntime *runtime =
2479 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
2480 auto module_list = target->GetImages();
2481 bool new_rs_details = runtime->ProbeModules(module_list);
2482 if (new_rs_details)
2483 {
2484 result.AppendMessage("New renderscript modules added to runtime model.");
2485 }
2486 result.SetStatus(eReturnStatusSuccessFinishResult);
2487 return true;
2488 }
2489
2490 result.AppendErrorWithFormat("'%s' takes no arguments", m_cmd_name.c_str());
2491 result.SetStatus(eReturnStatusFailed);
2492 return false;
2493 }
2494};
2495
2496class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed
2497{
2498 private:
2499 public:
2500 CommandObjectRenderScriptRuntimeModuleDump(CommandInterpreter &interpreter)
2501 : CommandObjectParsed(interpreter, "renderscript module dump",
2502 "Dumps renderscript specific information for all modules.", "renderscript module dump",
Enrico Granatae87764f2015-05-27 05:04:35 +00002503 eCommandRequiresProcess | eCommandProcessMustBeLaunched)
Colin Riley5ec532a2015-04-09 16:49:25 +00002504 {
2505 }
2506
2507 ~CommandObjectRenderScriptRuntimeModuleDump() {}
2508
2509 bool
2510 DoExecute(Args &command, CommandReturnObject &result)
2511 {
2512 RenderScriptRuntime *runtime =
2513 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
2514 runtime->DumpModules(result.GetOutputStream());
2515 result.SetStatus(eReturnStatusSuccessFinishResult);
2516 return true;
2517 }
2518};
2519
2520class CommandObjectRenderScriptRuntimeModule : public CommandObjectMultiword
2521{
2522 private:
2523 public:
2524 CommandObjectRenderScriptRuntimeModule(CommandInterpreter &interpreter)
2525 : CommandObjectMultiword(interpreter, "renderscript module", "Commands that deal with renderscript modules.",
2526 NULL)
2527 {
2528 LoadSubCommand("probe", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleProbe(interpreter)));
2529 LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleDump(interpreter)));
2530 }
2531
2532 ~CommandObjectRenderScriptRuntimeModule() {}
2533};
2534
Colin Riley4640cde2015-06-01 18:23:41 +00002535class CommandObjectRenderScriptRuntimeKernelList : public CommandObjectParsed
2536{
2537 private:
2538 public:
2539 CommandObjectRenderScriptRuntimeKernelList(CommandInterpreter &interpreter)
2540 : CommandObjectParsed(interpreter, "renderscript kernel list",
2541 "Lists renderscript kernel names and associated script resources.", "renderscript kernel list",
2542 eCommandRequiresProcess | eCommandProcessMustBeLaunched)
2543 {
2544 }
2545
2546 ~CommandObjectRenderScriptRuntimeKernelList() {}
2547
2548 bool
2549 DoExecute(Args &command, CommandReturnObject &result)
2550 {
2551 RenderScriptRuntime *runtime =
2552 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
2553 runtime->DumpKernels(result.GetOutputStream());
2554 result.SetStatus(eReturnStatusSuccessFinishResult);
2555 return true;
2556 }
2557};
2558
Ewan Crawford7dc77712015-09-10 10:08:48 +00002559class CommandObjectRenderScriptRuntimeKernelBreakpointSet : public CommandObjectParsed
Colin Riley4640cde2015-06-01 18:23:41 +00002560{
2561 private:
2562 public:
Ewan Crawford7dc77712015-09-10 10:08:48 +00002563 CommandObjectRenderScriptRuntimeKernelBreakpointSet(CommandInterpreter &interpreter)
2564 : CommandObjectParsed(interpreter, "renderscript kernel breakpoint set",
2565 "Sets a breakpoint on a renderscript kernel.", "renderscript kernel breakpoint set <kernel_name>",
Colin Riley4640cde2015-06-01 18:23:41 +00002566 eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused)
2567 {
2568 }
2569
Ewan Crawford7dc77712015-09-10 10:08:48 +00002570 ~CommandObjectRenderScriptRuntimeKernelBreakpointSet() {}
Colin Riley4640cde2015-06-01 18:23:41 +00002571
2572 bool
2573 DoExecute(Args &command, CommandReturnObject &result)
2574 {
2575 const size_t argc = command.GetArgumentCount();
2576 if (argc == 1)
2577 {
2578 RenderScriptRuntime *runtime =
2579 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
2580
2581 Error error;
Ewan Crawford98156582015-09-04 08:56:52 +00002582 runtime->AttemptBreakpointAtKernelName(result.GetOutputStream(), command.GetArgumentAtIndex(0),
2583 error, m_exe_ctx.GetTargetSP());
Colin Riley4640cde2015-06-01 18:23:41 +00002584
2585 if (error.Success())
2586 {
2587 result.AppendMessage("Breakpoint(s) created");
2588 result.SetStatus(eReturnStatusSuccessFinishResult);
2589 return true;
2590 }
2591 result.SetStatus(eReturnStatusFailed);
2592 result.AppendErrorWithFormat("Error: %s", error.AsCString());
2593 return false;
2594 }
2595
2596 result.AppendErrorWithFormat("'%s' takes 1 argument of kernel name", m_cmd_name.c_str());
2597 result.SetStatus(eReturnStatusFailed);
2598 return false;
2599 }
2600};
2601
Ewan Crawford7dc77712015-09-10 10:08:48 +00002602class CommandObjectRenderScriptRuntimeKernelBreakpointAll : public CommandObjectParsed
2603{
2604 private:
2605 public:
2606 CommandObjectRenderScriptRuntimeKernelBreakpointAll(CommandInterpreter &interpreter)
2607 : CommandObjectParsed(interpreter, "renderscript kernel breakpoint all",
2608 "Automatically sets a breakpoint on all renderscript kernels that are or will be loaded.\n"
2609 "Disabling option means breakpoints will no longer be set on any kernels loaded in the future, "
2610 "but does not remove currently set breakpoints.",
2611 "renderscript kernel breakpoint all <enable/disable>",
2612 eCommandRequiresProcess | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused)
2613 {
2614 }
2615
2616 ~CommandObjectRenderScriptRuntimeKernelBreakpointAll() {}
2617
2618 bool
2619 DoExecute(Args &command, CommandReturnObject &result)
2620 {
2621 const size_t argc = command.GetArgumentCount();
2622 if (argc != 1)
2623 {
2624 result.AppendErrorWithFormat("'%s' takes 1 argument of 'enable' or 'disable'", m_cmd_name.c_str());
2625 result.SetStatus(eReturnStatusFailed);
2626 return false;
2627 }
2628
2629 RenderScriptRuntime *runtime =
2630 static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
2631
2632 bool do_break = false;
2633 const char* argument = command.GetArgumentAtIndex(0);
2634 if (strcmp(argument, "enable") == 0)
2635 {
2636 do_break = true;
2637 result.AppendMessage("Breakpoints will be set on all kernels.");
2638 }
2639 else if (strcmp(argument, "disable") == 0)
2640 {
2641 do_break = false;
2642 result.AppendMessage("Breakpoints will not be set on any new kernels.");
2643 }
2644 else
2645 {
2646 result.AppendErrorWithFormat("Argument must be either 'enable' or 'disable'");
2647 result.SetStatus(eReturnStatusFailed);
2648 return false;
2649 }
2650
2651 runtime->SetBreakAllKernels(do_break, m_exe_ctx.GetTargetSP());
2652
2653 result.SetStatus(eReturnStatusSuccessFinishResult);
2654 return true;
2655 }
2656};
2657
2658class CommandObjectRenderScriptRuntimeKernelBreakpoint : public CommandObjectMultiword
2659{
2660 private:
2661 public:
2662 CommandObjectRenderScriptRuntimeKernelBreakpoint(CommandInterpreter &interpreter)
2663 : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that generate breakpoints on renderscript kernels.",
2664 nullptr)
2665 {
2666 LoadSubCommand("set", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointSet(interpreter)));
2667 LoadSubCommand("all", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointAll(interpreter)));
2668 }
2669
2670 ~CommandObjectRenderScriptRuntimeKernelBreakpoint() {}
2671};
2672
Colin Riley4640cde2015-06-01 18:23:41 +00002673class CommandObjectRenderScriptRuntimeKernel : public CommandObjectMultiword
2674{
2675 private:
2676 public:
2677 CommandObjectRenderScriptRuntimeKernel(CommandInterpreter &interpreter)
2678 : CommandObjectMultiword(interpreter, "renderscript kernel", "Commands that deal with renderscript kernels.",
2679 NULL)
2680 {
2681 LoadSubCommand("list", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelList(interpreter)));
2682 LoadSubCommand("breakpoint", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpoint(interpreter)));
2683 }
2684
2685 ~CommandObjectRenderScriptRuntimeKernel() {}
2686};
2687
2688class CommandObjectRenderScriptRuntimeContextDump : public CommandObjectParsed
2689{
2690 private:
2691 public:
2692 CommandObjectRenderScriptRuntimeContextDump(CommandInterpreter &interpreter)
2693 : CommandObjectParsed(interpreter, "renderscript context dump",
2694 "Dumps renderscript context information.", "renderscript context dump",
2695 eCommandRequiresProcess | eCommandProcessMustBeLaunched)
2696 {
2697 }
2698
2699 ~CommandObjectRenderScriptRuntimeContextDump() {}
2700
2701 bool
2702 DoExecute(Args &command, CommandReturnObject &result)
2703 {
2704 RenderScriptRuntime *runtime =
2705 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
2706 runtime->DumpContexts(result.GetOutputStream());
2707 result.SetStatus(eReturnStatusSuccessFinishResult);
2708 return true;
2709 }
2710};
2711
2712class CommandObjectRenderScriptRuntimeContext : public CommandObjectMultiword
2713{
2714 private:
2715 public:
2716 CommandObjectRenderScriptRuntimeContext(CommandInterpreter &interpreter)
2717 : CommandObjectMultiword(interpreter, "renderscript context", "Commands that deal with renderscript contexts.",
2718 NULL)
2719 {
2720 LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeContextDump(interpreter)));
2721 }
2722
2723 ~CommandObjectRenderScriptRuntimeContext() {}
2724};
2725
Ewan Crawforda0f08672015-10-16 08:28:47 +00002726
2727class CommandObjectRenderScriptRuntimeAllocationDump : public CommandObjectParsed
2728{
2729 private:
2730 public:
2731 CommandObjectRenderScriptRuntimeAllocationDump(CommandInterpreter &interpreter)
2732 : CommandObjectParsed(interpreter, "renderscript allocation dump",
2733 "Displays the contents of a particular allocation", "renderscript allocation dump <ID>",
2734 eCommandRequiresProcess | eCommandProcessMustBeLaunched), m_options(interpreter)
2735 {
2736 }
2737
2738 virtual Options*
2739 GetOptions()
2740 {
2741 return &m_options;
2742 }
2743
2744 class CommandOptions : public Options
2745 {
2746 public:
2747 CommandOptions(CommandInterpreter &interpreter) : Options(interpreter)
2748 {
2749 }
2750
2751 virtual
2752 ~CommandOptions()
2753 {
2754 }
2755
2756 virtual Error
2757 SetOptionValue(uint32_t option_idx, const char *option_arg)
2758 {
2759 Error error;
2760 const int short_option = m_getopt_table[option_idx].val;
2761
2762 switch (short_option)
2763 {
2764 case 'f':
2765 m_outfile.SetFile(option_arg, true);
2766 if (m_outfile.Exists())
2767 {
2768 m_outfile.Clear();
2769 error.SetErrorStringWithFormat("file already exists: '%s'", option_arg);
2770 }
2771 break;
2772 default:
2773 error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
2774 break;
2775 }
2776 return error;
2777 }
2778
2779 void
2780 OptionParsingStarting()
2781 {
2782 m_outfile.Clear();
2783 }
2784
2785 const OptionDefinition*
2786 GetDefinitions()
2787 {
2788 return g_option_table;
2789 }
2790
2791 static OptionDefinition g_option_table[];
2792 FileSpec m_outfile;
2793 };
2794
2795 ~CommandObjectRenderScriptRuntimeAllocationDump() {}
2796
2797 bool
2798 DoExecute(Args &command, CommandReturnObject &result)
2799 {
2800 const size_t argc = command.GetArgumentCount();
2801 if (argc < 1)
2802 {
2803 result.AppendErrorWithFormat("'%s' takes 1 argument, an allocation ID. As well as an optional -f argument",
2804 m_cmd_name.c_str());
2805 result.SetStatus(eReturnStatusFailed);
2806 return false;
2807 }
2808
2809 RenderScriptRuntime *runtime =
2810 static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
2811
2812 const char* id_cstr = command.GetArgumentAtIndex(0);
2813 bool convert_complete = false;
2814 const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete);
2815 if (!convert_complete)
2816 {
2817 result.AppendErrorWithFormat("invalid allocation id argument '%s'", id_cstr);
2818 result.SetStatus(eReturnStatusFailed);
2819 return false;
2820 }
2821
2822 Stream* output_strm = nullptr;
2823 StreamFile outfile_stream;
2824 const FileSpec &outfile_spec = m_options.m_outfile; // Dump allocation to file instead
2825 if (outfile_spec)
2826 {
2827 // Open output file
2828 char path[256];
2829 outfile_spec.GetPath(path, sizeof(path));
2830 if (outfile_stream.GetFile().Open(path, File::eOpenOptionWrite | File::eOpenOptionCanCreate).Success())
2831 {
2832 output_strm = &outfile_stream;
2833 result.GetOutputStream().Printf("Results written to '%s'", path);
2834 result.GetOutputStream().EOL();
2835 }
2836 else
2837 {
2838 result.AppendErrorWithFormat("Couldn't open file '%s'", path);
2839 result.SetStatus(eReturnStatusFailed);
2840 return false;
2841 }
2842 }
2843 else
2844 output_strm = &result.GetOutputStream();
2845
2846 assert(output_strm != nullptr);
2847 bool success = runtime->DumpAllocation(*output_strm, m_exe_ctx.GetFramePtr(), id);
2848
2849 if (success)
2850 result.SetStatus(eReturnStatusSuccessFinishResult);
2851 else
2852 result.SetStatus(eReturnStatusFailed);
2853
2854 return true;
2855 }
2856
2857 private:
2858 CommandOptions m_options;
2859};
2860
2861OptionDefinition
2862CommandObjectRenderScriptRuntimeAllocationDump::CommandOptions::g_option_table[] =
2863{
2864 { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeFilename,
2865 "Print results to specified file instead of command line."},
2866 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
2867};
2868
2869
Ewan Crawford15f2bd92015-10-06 08:42:32 +00002870class CommandObjectRenderScriptRuntimeAllocationList : public CommandObjectParsed
2871{
2872 public:
2873 CommandObjectRenderScriptRuntimeAllocationList(CommandInterpreter &interpreter)
2874 : CommandObjectParsed(interpreter, "renderscript allocation list",
2875 "List renderscript allocations and their information.", "renderscript allocation list",
2876 eCommandRequiresProcess | eCommandProcessMustBeLaunched), m_options(interpreter)
2877 {
2878 }
2879
2880 virtual Options*
2881 GetOptions()
2882 {
2883 return &m_options;
2884 }
2885
2886 class CommandOptions : public Options
2887 {
2888 public:
2889 CommandOptions(CommandInterpreter &interpreter) : Options(interpreter), m_refresh(false)
2890 {
2891 }
2892
2893 virtual
2894 ~CommandOptions()
2895 {
2896 }
2897
2898 virtual Error
2899 SetOptionValue(uint32_t option_idx, const char *option_arg)
2900 {
2901 Error error;
2902 const int short_option = m_getopt_table[option_idx].val;
2903
2904 switch (short_option)
2905 {
2906 case 'r':
2907 m_refresh = true;
2908 break;
2909 default:
2910 error.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
2911 break;
2912 }
2913 return error;
2914 }
2915
2916 void
2917 OptionParsingStarting()
2918 {
2919 m_refresh = false;
2920 }
2921
2922 const OptionDefinition*
2923 GetDefinitions()
2924 {
2925 return g_option_table;
2926 }
2927
2928 static OptionDefinition g_option_table[];
2929 bool m_refresh;
2930 };
2931
2932 ~CommandObjectRenderScriptRuntimeAllocationList() {}
2933
2934 bool
2935 DoExecute(Args &command, CommandReturnObject &result)
2936 {
2937 RenderScriptRuntime *runtime =
2938 static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
2939 runtime->ListAllocations(result.GetOutputStream(), m_exe_ctx.GetFramePtr(), m_options.m_refresh);
2940 result.SetStatus(eReturnStatusSuccessFinishResult);
2941 return true;
2942 }
2943
2944 private:
2945 CommandOptions m_options;
2946};
2947
2948OptionDefinition
2949CommandObjectRenderScriptRuntimeAllocationList::CommandOptions::g_option_table[] =
2950{
2951 { LLDB_OPT_SET_1, false, "refresh", 'r', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone,
2952 "Recompute allocation details."},
2953 { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
2954};
2955
2956
Ewan Crawford55232f02015-10-21 08:50:42 +00002957class CommandObjectRenderScriptRuntimeAllocationLoad : public CommandObjectParsed
2958{
2959 private:
2960 public:
2961 CommandObjectRenderScriptRuntimeAllocationLoad(CommandInterpreter &interpreter)
2962 : CommandObjectParsed(interpreter, "renderscript allocation load",
2963 "Loads renderscript allocation contents from a file.", "renderscript allocation load <ID> <filename>",
2964 eCommandRequiresProcess | eCommandProcessMustBeLaunched)
2965 {
2966 }
2967
2968 ~CommandObjectRenderScriptRuntimeAllocationLoad() {}
2969
2970 bool
2971 DoExecute(Args &command, CommandReturnObject &result)
2972 {
2973 const size_t argc = command.GetArgumentCount();
2974 if (argc != 2)
2975 {
2976 result.AppendErrorWithFormat("'%s' takes 2 arguments, an allocation ID and filename to read from.", m_cmd_name.c_str());
2977 result.SetStatus(eReturnStatusFailed);
2978 return false;
2979 }
2980
2981 RenderScriptRuntime *runtime =
2982 static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
2983
2984 const char* id_cstr = command.GetArgumentAtIndex(0);
2985 bool convert_complete = false;
2986 const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete);
2987 if (!convert_complete)
2988 {
2989 result.AppendErrorWithFormat ("invalid allocation id argument '%s'", id_cstr);
2990 result.SetStatus (eReturnStatusFailed);
2991 return false;
2992 }
2993
2994 const char* filename = command.GetArgumentAtIndex(1);
2995 bool success = runtime->LoadAllocation(result.GetOutputStream(), id, filename, m_exe_ctx.GetFramePtr());
2996
2997 if (success)
2998 result.SetStatus(eReturnStatusSuccessFinishResult);
2999 else
3000 result.SetStatus(eReturnStatusFailed);
3001
3002 return true;
3003 }
3004};
3005
3006
3007class CommandObjectRenderScriptRuntimeAllocationSave : public CommandObjectParsed
3008{
3009 private:
3010 public:
3011 CommandObjectRenderScriptRuntimeAllocationSave(CommandInterpreter &interpreter)
3012 : CommandObjectParsed(interpreter, "renderscript allocation save",
3013 "Write renderscript allocation contents to a file.", "renderscript allocation save <ID> <filename>",
3014 eCommandRequiresProcess | eCommandProcessMustBeLaunched)
3015 {
3016 }
3017
3018 ~CommandObjectRenderScriptRuntimeAllocationSave() {}
3019
3020 bool
3021 DoExecute(Args &command, CommandReturnObject &result)
3022 {
3023 const size_t argc = command.GetArgumentCount();
3024 if (argc != 2)
3025 {
3026 result.AppendErrorWithFormat("'%s' takes 2 arguments, an allocation ID and filename to read from.", m_cmd_name.c_str());
3027 result.SetStatus(eReturnStatusFailed);
3028 return false;
3029 }
3030
3031 RenderScriptRuntime *runtime =
3032 static_cast<RenderScriptRuntime *>(m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript));
3033
3034 const char* id_cstr = command.GetArgumentAtIndex(0);
3035 bool convert_complete = false;
3036 const uint32_t id = StringConvert::ToUInt32(id_cstr, UINT32_MAX, 0, &convert_complete);
3037 if (!convert_complete)
3038 {
3039 result.AppendErrorWithFormat ("invalid allocation id argument '%s'", id_cstr);
3040 result.SetStatus (eReturnStatusFailed);
3041 return false;
3042 }
3043
3044 const char* filename = command.GetArgumentAtIndex(1);
3045 bool success = runtime->SaveAllocation(result.GetOutputStream(), id, filename, m_exe_ctx.GetFramePtr());
3046
3047 if (success)
3048 result.SetStatus(eReturnStatusSuccessFinishResult);
3049 else
3050 result.SetStatus(eReturnStatusFailed);
3051
3052 return true;
3053 }
3054};
3055
Ewan Crawford15f2bd92015-10-06 08:42:32 +00003056class CommandObjectRenderScriptRuntimeAllocation : public CommandObjectMultiword
3057{
3058 private:
3059 public:
3060 CommandObjectRenderScriptRuntimeAllocation(CommandInterpreter &interpreter)
3061 : CommandObjectMultiword(interpreter, "renderscript allocation", "Commands that deal with renderscript allocations.",
3062 NULL)
3063 {
3064 LoadSubCommand("list", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationList(interpreter)));
Ewan Crawforda0f08672015-10-16 08:28:47 +00003065 LoadSubCommand("dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationDump(interpreter)));
Ewan Crawford55232f02015-10-21 08:50:42 +00003066 LoadSubCommand("save", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationSave(interpreter)));
3067 LoadSubCommand("load", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationLoad(interpreter)));
Ewan Crawford15f2bd92015-10-06 08:42:32 +00003068 }
3069
3070 ~CommandObjectRenderScriptRuntimeAllocation() {}
3071};
3072
3073
Colin Riley4640cde2015-06-01 18:23:41 +00003074class CommandObjectRenderScriptRuntimeStatus : public CommandObjectParsed
3075{
3076 private:
3077 public:
3078 CommandObjectRenderScriptRuntimeStatus(CommandInterpreter &interpreter)
3079 : CommandObjectParsed(interpreter, "renderscript status",
3080 "Displays current renderscript runtime status.", "renderscript status",
3081 eCommandRequiresProcess | eCommandProcessMustBeLaunched)
3082 {
3083 }
3084
3085 ~CommandObjectRenderScriptRuntimeStatus() {}
3086
3087 bool
3088 DoExecute(Args &command, CommandReturnObject &result)
3089 {
3090 RenderScriptRuntime *runtime =
3091 (RenderScriptRuntime *)m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(eLanguageTypeExtRenderScript);
3092 runtime->Status(result.GetOutputStream());
3093 result.SetStatus(eReturnStatusSuccessFinishResult);
3094 return true;
3095 }
3096};
3097
Colin Riley5ec532a2015-04-09 16:49:25 +00003098class CommandObjectRenderScriptRuntime : public CommandObjectMultiword
3099{
3100 public:
3101 CommandObjectRenderScriptRuntime(CommandInterpreter &interpreter)
3102 : CommandObjectMultiword(interpreter, "renderscript", "A set of commands for operating on renderscript.",
3103 "renderscript <subcommand> [<subcommand-options>]")
3104 {
3105 LoadSubCommand("module", CommandObjectSP(new CommandObjectRenderScriptRuntimeModule(interpreter)));
Colin Riley4640cde2015-06-01 18:23:41 +00003106 LoadSubCommand("status", CommandObjectSP(new CommandObjectRenderScriptRuntimeStatus(interpreter)));
3107 LoadSubCommand("kernel", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernel(interpreter)));
3108 LoadSubCommand("context", CommandObjectSP(new CommandObjectRenderScriptRuntimeContext(interpreter)));
Ewan Crawford15f2bd92015-10-06 08:42:32 +00003109 LoadSubCommand("allocation", CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocation(interpreter)));
Colin Riley5ec532a2015-04-09 16:49:25 +00003110 }
3111
3112 ~CommandObjectRenderScriptRuntime() {}
3113};
Colin Rileyef20b082015-04-14 07:39:24 +00003114
3115void
3116RenderScriptRuntime::Initiate()
Colin Riley5ec532a2015-04-09 16:49:25 +00003117{
Colin Rileyef20b082015-04-14 07:39:24 +00003118 assert(!m_initiated);
Colin Riley5ec532a2015-04-09 16:49:25 +00003119}
Colin Rileyef20b082015-04-14 07:39:24 +00003120
3121RenderScriptRuntime::RenderScriptRuntime(Process *process)
Ewan Crawford7dc77712015-09-10 10:08:48 +00003122 : lldb_private::CPPLanguageRuntime(process), m_initiated(false), m_debuggerPresentFlagged(false),
3123 m_breakAllKernels(false)
Colin Rileyef20b082015-04-14 07:39:24 +00003124{
Colin Riley4640cde2015-06-01 18:23:41 +00003125 ModulesDidLoad(process->GetTarget().GetImages());
Colin Rileyef20b082015-04-14 07:39:24 +00003126}
Colin Riley4640cde2015-06-01 18:23:41 +00003127
3128lldb::CommandObjectSP
3129RenderScriptRuntime::GetCommandObject(lldb_private::CommandInterpreter& interpreter)
3130{
3131 static CommandObjectSP command_object;
3132 if(!command_object)
3133 {
3134 command_object.reset(new CommandObjectRenderScriptRuntime(interpreter));
3135 }
3136 return command_object;
3137}
3138
Ewan Crawford78f339d2015-09-21 10:53:18 +00003139RenderScriptRuntime::~RenderScriptRuntime() = default;