180814287SRaphael Isemann //===-- RenderScriptRuntime.cpp -------------------------------------------===// 25ec532a9SColin Riley // 32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information. 52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 65ec532a9SColin Riley // 75ec532a9SColin Riley //===----------------------------------------------------------------------===// 85ec532a9SColin Riley 95ec532a9SColin Riley #include "RenderScriptRuntime.h" 1021fed052SAidan Dodds #include "RenderScriptScriptGroup.h" 115ec532a9SColin Riley 12b3f7f69dSAidan Dodds #include "lldb/Breakpoint/StoppointCallbackContext.h" 135ec532a9SColin Riley #include "lldb/Core/Debugger.h" 1429cb868aSZachary Turner #include "lldb/Core/DumpDataExtractor.h" 155ec532a9SColin Riley #include "lldb/Core/PluginManager.h" 16b3f7f69dSAidan Dodds #include "lldb/Core/ValueObjectVariable.h" 178b244e21SEwan Crawford #include "lldb/DataFormatters/DumpValueObjectOptions.h" 18b3f7f69dSAidan Dodds #include "lldb/Expression/UserExpression.h" 193eb2b44dSZachary Turner #include "lldb/Host/OptionParser.h" 20b3f7f69dSAidan Dodds #include "lldb/Interpreter/CommandInterpreter.h" 21b3f7f69dSAidan Dodds #include "lldb/Interpreter/CommandObjectMultiword.h" 22b3f7f69dSAidan Dodds #include "lldb/Interpreter/CommandReturnObject.h" 23b3f7f69dSAidan Dodds #include "lldb/Interpreter/Options.h" 2421fed052SAidan Dodds #include "lldb/Symbol/Function.h" 255ec532a9SColin Riley #include "lldb/Symbol/Symbol.h" 264640cde1SColin Riley #include "lldb/Symbol/Type.h" 27b3f7f69dSAidan Dodds #include "lldb/Symbol/VariableList.h" 285ec532a9SColin Riley #include "lldb/Target/Process.h" 29b3f7f69dSAidan Dodds #include "lldb/Target/RegisterContext.h" 3021fed052SAidan Dodds #include "lldb/Target/SectionLoadList.h" 315ec532a9SColin Riley #include "lldb/Target/Target.h" 32018f5a7eSEwan Crawford #include "lldb/Target/Thread.h" 33145d95c9SPavel Labath #include "lldb/Utility/Args.h" 34bf9a7730SZachary Turner #include "lldb/Utility/ConstString.h" 356f9e6901SZachary Turner #include "lldb/Utility/Log.h" 36d821c997SPavel Labath #include "lldb/Utility/RegisterValue.h" 37bf9a7730SZachary Turner #include "lldb/Utility/RegularExpression.h" 3897206d57SZachary Turner #include "lldb/Utility/Status.h" 395ec532a9SColin Riley 40796ac80bSJonas Devlieghere #include "llvm/ADT/StringSwitch.h" 41796ac80bSJonas Devlieghere 42796ac80bSJonas Devlieghere #include <memory> 43796ac80bSJonas Devlieghere 445ec532a9SColin Riley using namespace lldb; 455ec532a9SColin Riley using namespace lldb_private; 4698156583SEwan Crawford using namespace lldb_renderscript; 475ec532a9SColin Riley 48bba9ba8dSJonas Devlieghere LLDB_PLUGIN_DEFINE(RenderScriptRuntime) 49fbb4d1e4SJonas Devlieghere 5000f56eebSLuke Drummond #define FMT_COORD "(%" PRIu32 ", %" PRIu32 ", %" PRIu32 ")" 5100f56eebSLuke Drummond 52056f6f18SAlex Langford char RenderScriptRuntime::ID = 0; 53056f6f18SAlex Langford 54b9c1b51eSKate Stone namespace { 5578f339d1SEwan Crawford 5678f339d1SEwan Crawford // The empirical_type adds a basic level of validation to arbitrary data 5780af0b9eSLuke Drummond // allowing us to track if data has been discovered and stored or not. An 5880af0b9eSLuke Drummond // empirical_type will be marked as valid only if it has been explicitly 59b9c1b51eSKate Stone // assigned to. 60b9c1b51eSKate Stone template <typename type_t> class empirical_type { 6178f339d1SEwan Crawford public: 6278f339d1SEwan Crawford // Ctor. Contents is invalid when constructed. 63fd2433e1SJonas Devlieghere empirical_type() = default; 6478f339d1SEwan Crawford 6578f339d1SEwan Crawford // Return true and copy contents to out if valid, else return false. 66b9c1b51eSKate Stone bool get(type_t &out) const { 6778f339d1SEwan Crawford if (valid) 6878f339d1SEwan Crawford out = data; 6978f339d1SEwan Crawford return valid; 7078f339d1SEwan Crawford } 7178f339d1SEwan Crawford 7278f339d1SEwan Crawford // Return a pointer to the contents or nullptr if it was not valid. 73b9c1b51eSKate Stone const type_t *get() const { return valid ? &data : nullptr; } 7478f339d1SEwan Crawford 7578f339d1SEwan Crawford // Assign data explicitly. 76b9c1b51eSKate Stone void set(const type_t in) { 7778f339d1SEwan Crawford data = in; 7878f339d1SEwan Crawford valid = true; 7978f339d1SEwan Crawford } 8078f339d1SEwan Crawford 8178f339d1SEwan Crawford // Mark contents as invalid. 82b9c1b51eSKate Stone void invalidate() { valid = false; } 8378f339d1SEwan Crawford 8478f339d1SEwan Crawford // Returns true if this type contains valid data. 85b9c1b51eSKate Stone bool isValid() const { return valid; } 8678f339d1SEwan Crawford 8778f339d1SEwan Crawford // Assignment operator. 88b9c1b51eSKate Stone empirical_type<type_t> &operator=(const type_t in) { 8978f339d1SEwan Crawford set(in); 9078f339d1SEwan Crawford return *this; 9178f339d1SEwan Crawford } 9278f339d1SEwan Crawford 9378f339d1SEwan Crawford // Dereference operator returns contents. 9478f339d1SEwan Crawford // Warning: Will assert if not valid so use only when you know data is valid. 95b9c1b51eSKate Stone const type_t &operator*() const { 9678f339d1SEwan Crawford assert(valid); 9778f339d1SEwan Crawford return data; 9878f339d1SEwan Crawford } 9978f339d1SEwan Crawford 10078f339d1SEwan Crawford protected: 1019494c510SJonas Devlieghere bool valid = false; 10278f339d1SEwan Crawford type_t data; 10378f339d1SEwan Crawford }; 10478f339d1SEwan Crawford 105b9c1b51eSKate Stone // ArgItem is used by the GetArgs() function when reading function arguments 106b9c1b51eSKate Stone // from the target. 107b9c1b51eSKate Stone struct ArgItem { 108b9c1b51eSKate Stone enum { ePointer, eInt32, eInt64, eLong, eBool } type; 109f4786785SAidan Dodds 110f4786785SAidan Dodds uint64_t value; 111f4786785SAidan Dodds 112f4786785SAidan Dodds explicit operator uint64_t() const { return value; } 113f4786785SAidan Dodds }; 114f4786785SAidan Dodds 115b9c1b51eSKate Stone // Context structure to be passed into GetArgsXXX(), argument reading functions 116b9c1b51eSKate Stone // below. 117b9c1b51eSKate Stone struct GetArgsCtx { 118f4786785SAidan Dodds RegisterContext *reg_ctx; 119f4786785SAidan Dodds Process *process; 120f4786785SAidan Dodds }; 121f4786785SAidan Dodds 122b9c1b51eSKate Stone bool GetArgsX86(const GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) { 123*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 124f4786785SAidan Dodds 12597206d57SZachary Turner Status err; 12667dc3e15SAidan Dodds 127f4786785SAidan Dodds // get the current stack pointer 128f4786785SAidan Dodds uint64_t sp = ctx.reg_ctx->GetSP(); 129f4786785SAidan Dodds 130b9c1b51eSKate Stone for (size_t i = 0; i < num_args; ++i) { 131f4786785SAidan Dodds ArgItem &arg = arg_list[i]; 132f4786785SAidan Dodds // advance up the stack by one argument 133f4786785SAidan Dodds sp += sizeof(uint32_t); 134f4786785SAidan Dodds // get the argument type size 135f4786785SAidan Dodds size_t arg_size = sizeof(uint32_t); 136f4786785SAidan Dodds // read the argument from memory 137f4786785SAidan Dodds arg.value = 0; 13897206d57SZachary Turner Status err; 139b9c1b51eSKate Stone size_t read = 14080af0b9eSLuke Drummond ctx.process->ReadMemory(sp, &arg.value, sizeof(uint32_t), err); 14180af0b9eSLuke Drummond if (read != arg_size || !err.Success()) { 14263e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - error reading argument: %" PRIu64 " '%s'", 14380af0b9eSLuke Drummond __FUNCTION__, uint64_t(i), err.AsCString()); 144f4786785SAidan Dodds return false; 145f4786785SAidan Dodds } 146f4786785SAidan Dodds } 147f4786785SAidan Dodds return true; 148f4786785SAidan Dodds } 149f4786785SAidan Dodds 150b9c1b51eSKate Stone bool GetArgsX86_64(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) { 151*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 152f4786785SAidan Dodds 153f4786785SAidan Dodds // number of arguments passed in registers 15480af0b9eSLuke Drummond static const uint32_t args_in_reg = 6; 155f4786785SAidan Dodds // register passing order 15680af0b9eSLuke Drummond static const std::array<const char *, args_in_reg> reg_names{ 157b9c1b51eSKate Stone {"rdi", "rsi", "rdx", "rcx", "r8", "r9"}}; 158f4786785SAidan Dodds // argument type to size mapping 1591ee07253SSaleem Abdulrasool static const std::array<size_t, 5> arg_size{{ 160f4786785SAidan Dodds 8, // ePointer, 161f4786785SAidan Dodds 4, // eInt32, 162f4786785SAidan Dodds 8, // eInt64, 163f4786785SAidan Dodds 8, // eLong, 164f4786785SAidan Dodds 4, // eBool, 1651ee07253SSaleem Abdulrasool }}; 166f4786785SAidan Dodds 16797206d57SZachary Turner Status err; 16817e07c0aSAidan Dodds 169f4786785SAidan Dodds // get the current stack pointer 170f4786785SAidan Dodds uint64_t sp = ctx.reg_ctx->GetSP(); 171f4786785SAidan Dodds // step over the return address 172f4786785SAidan Dodds sp += sizeof(uint64_t); 173f4786785SAidan Dodds 174f4786785SAidan Dodds // check the stack alignment was correct (16 byte aligned) 175b9c1b51eSKate Stone if ((sp & 0xf) != 0x0) { 17663e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - stack misaligned", __FUNCTION__); 177f4786785SAidan Dodds return false; 178f4786785SAidan Dodds } 179f4786785SAidan Dodds 180f4786785SAidan Dodds // find the start of arguments on the stack 181f4786785SAidan Dodds uint64_t sp_offset = 0; 18280af0b9eSLuke Drummond for (uint32_t i = args_in_reg; i < num_args; ++i) { 183f4786785SAidan Dodds sp_offset += arg_size[arg_list[i].type]; 184f4786785SAidan Dodds } 185f4786785SAidan Dodds // round up to multiple of 16 186f4786785SAidan Dodds sp_offset = (sp_offset + 0xf) & 0xf; 187f4786785SAidan Dodds sp += sp_offset; 188f4786785SAidan Dodds 189b9c1b51eSKate Stone for (size_t i = 0; i < num_args; ++i) { 190f4786785SAidan Dodds bool success = false; 191f4786785SAidan Dodds ArgItem &arg = arg_list[i]; 192f4786785SAidan Dodds // arguments passed in registers 19380af0b9eSLuke Drummond if (i < args_in_reg) { 19480af0b9eSLuke Drummond const RegisterInfo *reg = 19580af0b9eSLuke Drummond ctx.reg_ctx->GetRegisterInfoByName(reg_names[i]); 19680af0b9eSLuke Drummond RegisterValue reg_val; 19780af0b9eSLuke Drummond if (ctx.reg_ctx->ReadRegister(reg, reg_val)) 19880af0b9eSLuke Drummond arg.value = reg_val.GetAsUInt64(0, &success); 199f4786785SAidan Dodds } 200f4786785SAidan Dodds // arguments passed on the stack 201b9c1b51eSKate Stone else { 202f4786785SAidan Dodds // get the argument type size 203f4786785SAidan Dodds const size_t size = arg_size[arg_list[i].type]; 204f4786785SAidan Dodds // read the argument from memory 205f4786785SAidan Dodds arg.value = 0; 206b9c1b51eSKate Stone // note: due to little endian layout reading 4 or 8 bytes will give the 207b9c1b51eSKate Stone // correct value. 20880af0b9eSLuke Drummond size_t read = ctx.process->ReadMemory(sp, &arg.value, size, err); 20980af0b9eSLuke Drummond success = (err.Success() && read == size); 210f4786785SAidan Dodds // advance past this argument 211f4786785SAidan Dodds sp -= size; 212f4786785SAidan Dodds } 213f4786785SAidan Dodds // fail if we couldn't read this argument 214b9c1b51eSKate Stone if (!success) { 21563e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - error reading argument: %" PRIu64 ", reason: %s", 21680af0b9eSLuke Drummond __FUNCTION__, uint64_t(i), err.AsCString("n/a")); 217f4786785SAidan Dodds return false; 218f4786785SAidan Dodds } 219f4786785SAidan Dodds } 220f4786785SAidan Dodds return true; 221f4786785SAidan Dodds } 222f4786785SAidan Dodds 223b9c1b51eSKate Stone bool GetArgsArm(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) { 224f4786785SAidan Dodds // number of arguments passed in registers 22580af0b9eSLuke Drummond static const uint32_t args_in_reg = 4; 226f4786785SAidan Dodds 227*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 228f4786785SAidan Dodds 22997206d57SZachary Turner Status err; 23017e07c0aSAidan Dodds 231f4786785SAidan Dodds // get the current stack pointer 232f4786785SAidan Dodds uint64_t sp = ctx.reg_ctx->GetSP(); 233f4786785SAidan Dodds 234b9c1b51eSKate Stone for (size_t i = 0; i < num_args; ++i) { 235f4786785SAidan Dodds bool success = false; 236f4786785SAidan Dodds ArgItem &arg = arg_list[i]; 237f4786785SAidan Dodds // arguments passed in registers 23880af0b9eSLuke Drummond if (i < args_in_reg) { 23980af0b9eSLuke Drummond const RegisterInfo *reg = ctx.reg_ctx->GetRegisterInfoAtIndex(i); 24080af0b9eSLuke Drummond RegisterValue reg_val; 24180af0b9eSLuke Drummond if (ctx.reg_ctx->ReadRegister(reg, reg_val)) 24280af0b9eSLuke Drummond arg.value = reg_val.GetAsUInt32(0, &success); 243f4786785SAidan Dodds } 244f4786785SAidan Dodds // arguments passed on the stack 245b9c1b51eSKate Stone else { 246f4786785SAidan Dodds // get the argument type size 247f4786785SAidan Dodds const size_t arg_size = sizeof(uint32_t); 248f4786785SAidan Dodds // clear all 64bits 249f4786785SAidan Dodds arg.value = 0; 250f4786785SAidan Dodds // read this argument from memory 251b9c1b51eSKate Stone size_t bytes_read = 25280af0b9eSLuke Drummond ctx.process->ReadMemory(sp, &arg.value, arg_size, err); 25380af0b9eSLuke Drummond success = (err.Success() && bytes_read == arg_size); 254f4786785SAidan Dodds // advance the stack pointer 255f4786785SAidan Dodds sp += sizeof(uint32_t); 256f4786785SAidan Dodds } 257f4786785SAidan Dodds // fail if we couldn't read this argument 258b9c1b51eSKate Stone if (!success) { 25963e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - error reading argument: %" PRIu64 ", reason: %s", 26080af0b9eSLuke Drummond __FUNCTION__, uint64_t(i), err.AsCString("n/a")); 261f4786785SAidan Dodds return false; 262f4786785SAidan Dodds } 263f4786785SAidan Dodds } 264f4786785SAidan Dodds return true; 265f4786785SAidan Dodds } 266f4786785SAidan Dodds 267b9c1b51eSKate Stone bool GetArgsAarch64(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) { 268f4786785SAidan Dodds // number of arguments passed in registers 26980af0b9eSLuke Drummond static const uint32_t args_in_reg = 8; 270f4786785SAidan Dodds 271*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 272f4786785SAidan Dodds 273b9c1b51eSKate Stone for (size_t i = 0; i < num_args; ++i) { 274f4786785SAidan Dodds bool success = false; 275f4786785SAidan Dodds ArgItem &arg = arg_list[i]; 276f4786785SAidan Dodds // arguments passed in registers 27780af0b9eSLuke Drummond if (i < args_in_reg) { 27880af0b9eSLuke Drummond const RegisterInfo *reg = ctx.reg_ctx->GetRegisterInfoAtIndex(i); 27980af0b9eSLuke Drummond RegisterValue reg_val; 28080af0b9eSLuke Drummond if (ctx.reg_ctx->ReadRegister(reg, reg_val)) 28180af0b9eSLuke Drummond arg.value = reg_val.GetAsUInt64(0, &success); 282f4786785SAidan Dodds } 283f4786785SAidan Dodds // arguments passed on the stack 284b9c1b51eSKate Stone else { 28563e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - reading arguments spilled to stack not implemented", 286b9c1b51eSKate Stone __FUNCTION__); 287f4786785SAidan Dodds } 288f4786785SAidan Dodds // fail if we couldn't read this argument 289b9c1b51eSKate Stone if (!success) { 29063e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - error reading argument: %" PRIu64, __FUNCTION__, 291f4786785SAidan Dodds uint64_t(i)); 292f4786785SAidan Dodds return false; 293f4786785SAidan Dodds } 294f4786785SAidan Dodds } 295f4786785SAidan Dodds return true; 296f4786785SAidan Dodds } 297f4786785SAidan Dodds 298b9c1b51eSKate Stone bool GetArgsMipsel(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) { 299f4786785SAidan Dodds // number of arguments passed in registers 30080af0b9eSLuke Drummond static const uint32_t args_in_reg = 4; 301f4786785SAidan Dodds // register file offset to first argument 30280af0b9eSLuke Drummond static const uint32_t reg_offset = 4; 303f4786785SAidan Dodds 304*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 305f4786785SAidan Dodds 30697206d57SZachary Turner Status err; 30717e07c0aSAidan Dodds 30805097246SAdrian Prantl // find offset to arguments on the stack (+16 to skip over a0-a3 shadow 30905097246SAdrian Prantl // space) 31017e07c0aSAidan Dodds uint64_t sp = ctx.reg_ctx->GetSP() + 16; 31117e07c0aSAidan Dodds 312b9c1b51eSKate Stone for (size_t i = 0; i < num_args; ++i) { 313f4786785SAidan Dodds bool success = false; 314f4786785SAidan Dodds ArgItem &arg = arg_list[i]; 315f4786785SAidan Dodds // arguments passed in registers 31680af0b9eSLuke Drummond if (i < args_in_reg) { 31780af0b9eSLuke Drummond const RegisterInfo *reg = 31880af0b9eSLuke Drummond ctx.reg_ctx->GetRegisterInfoAtIndex(i + reg_offset); 31980af0b9eSLuke Drummond RegisterValue reg_val; 32080af0b9eSLuke Drummond if (ctx.reg_ctx->ReadRegister(reg, reg_val)) 32180af0b9eSLuke Drummond arg.value = reg_val.GetAsUInt64(0, &success); 322f4786785SAidan Dodds } 323f4786785SAidan Dodds // arguments passed on the stack 324b9c1b51eSKate Stone else { 3256dd4b579SAidan Dodds const size_t arg_size = sizeof(uint32_t); 3266dd4b579SAidan Dodds arg.value = 0; 327b9c1b51eSKate Stone size_t bytes_read = 32880af0b9eSLuke Drummond ctx.process->ReadMemory(sp, &arg.value, arg_size, err); 32980af0b9eSLuke Drummond success = (err.Success() && bytes_read == arg_size); 33067dc3e15SAidan Dodds // advance the stack pointer 33167dc3e15SAidan Dodds sp += arg_size; 332f4786785SAidan Dodds } 333f4786785SAidan Dodds // fail if we couldn't read this argument 334b9c1b51eSKate Stone if (!success) { 33563e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - error reading argument: %" PRIu64 ", reason: %s", 33680af0b9eSLuke Drummond __FUNCTION__, uint64_t(i), err.AsCString("n/a")); 337f4786785SAidan Dodds return false; 338f4786785SAidan Dodds } 339f4786785SAidan Dodds } 340f4786785SAidan Dodds return true; 341f4786785SAidan Dodds } 342f4786785SAidan Dodds 343b9c1b51eSKate Stone bool GetArgsMips64el(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) { 344f4786785SAidan Dodds // number of arguments passed in registers 34580af0b9eSLuke Drummond static const uint32_t args_in_reg = 8; 346f4786785SAidan Dodds // register file offset to first argument 34780af0b9eSLuke Drummond static const uint32_t reg_offset = 4; 348f4786785SAidan Dodds 349*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 350f4786785SAidan Dodds 35197206d57SZachary Turner Status err; 35217e07c0aSAidan Dodds 353f4786785SAidan Dodds // get the current stack pointer 354f4786785SAidan Dodds uint64_t sp = ctx.reg_ctx->GetSP(); 355f4786785SAidan Dodds 356b9c1b51eSKate Stone for (size_t i = 0; i < num_args; ++i) { 357f4786785SAidan Dodds bool success = false; 358f4786785SAidan Dodds ArgItem &arg = arg_list[i]; 359f4786785SAidan Dodds // arguments passed in registers 36080af0b9eSLuke Drummond if (i < args_in_reg) { 36180af0b9eSLuke Drummond const RegisterInfo *reg = 36280af0b9eSLuke Drummond ctx.reg_ctx->GetRegisterInfoAtIndex(i + reg_offset); 36380af0b9eSLuke Drummond RegisterValue reg_val; 36480af0b9eSLuke Drummond if (ctx.reg_ctx->ReadRegister(reg, reg_val)) 36580af0b9eSLuke Drummond arg.value = reg_val.GetAsUInt64(0, &success); 366f4786785SAidan Dodds } 367f4786785SAidan Dodds // arguments passed on the stack 368b9c1b51eSKate Stone else { 369f4786785SAidan Dodds // get the argument type size 370f4786785SAidan Dodds const size_t arg_size = sizeof(uint64_t); 371f4786785SAidan Dodds // clear all 64bits 372f4786785SAidan Dodds arg.value = 0; 373f4786785SAidan Dodds // read this argument from memory 374b9c1b51eSKate Stone size_t bytes_read = 37580af0b9eSLuke Drummond ctx.process->ReadMemory(sp, &arg.value, arg_size, err); 37680af0b9eSLuke Drummond success = (err.Success() && bytes_read == arg_size); 377f4786785SAidan Dodds // advance the stack pointer 378f4786785SAidan Dodds sp += arg_size; 379f4786785SAidan Dodds } 380f4786785SAidan Dodds // fail if we couldn't read this argument 381b9c1b51eSKate Stone if (!success) { 38263e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - error reading argument: %" PRIu64 ", reason: %s", 38380af0b9eSLuke Drummond __FUNCTION__, uint64_t(i), err.AsCString("n/a")); 384f4786785SAidan Dodds return false; 385f4786785SAidan Dodds } 386f4786785SAidan Dodds } 387f4786785SAidan Dodds return true; 388f4786785SAidan Dodds } 389f4786785SAidan Dodds 39080af0b9eSLuke Drummond bool GetArgs(ExecutionContext &exe_ctx, ArgItem *arg_list, size_t num_args) { 391*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 392f4786785SAidan Dodds 393f4786785SAidan Dodds // verify that we have a target 39480af0b9eSLuke Drummond if (!exe_ctx.GetTargetPtr()) { 39563e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - invalid target", __FUNCTION__); 396f4786785SAidan Dodds return false; 397f4786785SAidan Dodds } 398f4786785SAidan Dodds 39980af0b9eSLuke Drummond GetArgsCtx ctx = {exe_ctx.GetRegisterContext(), exe_ctx.GetProcessPtr()}; 400f4786785SAidan Dodds assert(ctx.reg_ctx && ctx.process); 401f4786785SAidan Dodds 402f4786785SAidan Dodds // dispatch based on architecture 40380af0b9eSLuke Drummond switch (exe_ctx.GetTargetPtr()->GetArchitecture().GetMachine()) { 404f4786785SAidan Dodds case llvm::Triple::ArchType::x86: 405f4786785SAidan Dodds return GetArgsX86(ctx, arg_list, num_args); 406f4786785SAidan Dodds 407f4786785SAidan Dodds case llvm::Triple::ArchType::x86_64: 408f4786785SAidan Dodds return GetArgsX86_64(ctx, arg_list, num_args); 409f4786785SAidan Dodds 410f4786785SAidan Dodds case llvm::Triple::ArchType::arm: 411f4786785SAidan Dodds return GetArgsArm(ctx, arg_list, num_args); 412f4786785SAidan Dodds 413f4786785SAidan Dodds case llvm::Triple::ArchType::aarch64: 414f4786785SAidan Dodds return GetArgsAarch64(ctx, arg_list, num_args); 415f4786785SAidan Dodds 416f4786785SAidan Dodds case llvm::Triple::ArchType::mipsel: 417f4786785SAidan Dodds return GetArgsMipsel(ctx, arg_list, num_args); 418f4786785SAidan Dodds 419f4786785SAidan Dodds case llvm::Triple::ArchType::mips64el: 420f4786785SAidan Dodds return GetArgsMips64el(ctx, arg_list, num_args); 421f4786785SAidan Dodds 422f4786785SAidan Dodds default: 423f4786785SAidan Dodds // unsupported architecture 424b9c1b51eSKate Stone if (log) { 42563e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - architecture not supported: '%s'", __FUNCTION__, 42680af0b9eSLuke Drummond exe_ctx.GetTargetRef().GetArchitecture().GetArchitectureName()); 427f4786785SAidan Dodds } 428f4786785SAidan Dodds return false; 429f4786785SAidan Dodds } 430f4786785SAidan Dodds } 43100f56eebSLuke Drummond 432b3bbcb12SLuke Drummond bool IsRenderScriptScriptModule(ModuleSP module) { 433b3bbcb12SLuke Drummond if (!module) 434b3bbcb12SLuke Drummond return false; 435b3bbcb12SLuke Drummond return module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"), 436b3bbcb12SLuke Drummond eSymbolTypeData) != nullptr; 437b3bbcb12SLuke Drummond } 438b3bbcb12SLuke Drummond 43900f56eebSLuke Drummond bool ParseCoordinate(llvm::StringRef coord_s, RSCoordinate &coord) { 44005097246SAdrian Prantl // takes an argument of the form 'num[,num][,num]'. Where 'coord_s' is a 44105097246SAdrian Prantl // comma separated 1,2 or 3-dimensional coordinate with the whitespace 44205097246SAdrian Prantl // trimmed. Missing coordinates are defaulted to zero. If parsing of any 44305097246SAdrian Prantl // elements fails the contents of &coord are undefined and `false` is 44405097246SAdrian Prantl // returned, `true` otherwise 44500f56eebSLuke Drummond 4463af3f1e8SJonas Devlieghere llvm::SmallVector<llvm::StringRef, 4> matches; 44700f56eebSLuke Drummond 448f9d90bc5SJan Kratochvil if (!RegularExpression("^([0-9]+),([0-9]+),([0-9]+)$") 449f9d90bc5SJan Kratochvil .Execute(coord_s, &matches) && 450f9d90bc5SJan Kratochvil !RegularExpression("^([0-9]+),([0-9]+)$").Execute(coord_s, &matches) && 451f9d90bc5SJan Kratochvil !RegularExpression("^([0-9]+)$").Execute(coord_s, &matches)) 45200f56eebSLuke Drummond return false; 45300f56eebSLuke Drummond 4543af3f1e8SJonas Devlieghere auto get_index = [&](size_t idx, uint32_t &i) -> bool { 45500f56eebSLuke Drummond std::string group; 45600f56eebSLuke Drummond errno = 0; 4573af3f1e8SJonas Devlieghere if (idx + 1 < matches.size()) { 4583af3f1e8SJonas Devlieghere return !llvm::StringRef(matches[idx + 1]).getAsInteger<uint32_t>(10, i); 4593af3f1e8SJonas Devlieghere } 46000f56eebSLuke Drummond return true; 46100f56eebSLuke Drummond }; 46200f56eebSLuke Drummond 46300f56eebSLuke Drummond return get_index(0, coord.x) && get_index(1, coord.y) && 46400f56eebSLuke Drummond get_index(2, coord.z); 46500f56eebSLuke Drummond } 46621fed052SAidan Dodds 46721fed052SAidan Dodds bool SkipPrologue(lldb::ModuleSP &module, Address &addr) { 468*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 46921fed052SAidan Dodds SymbolContext sc; 47021fed052SAidan Dodds uint32_t resolved_flags = 47121fed052SAidan Dodds module->ResolveSymbolContextForAddress(addr, eSymbolContextFunction, sc); 47221fed052SAidan Dodds if (resolved_flags & eSymbolContextFunction) { 47321fed052SAidan Dodds if (sc.function) { 47421fed052SAidan Dodds const uint32_t offset = sc.function->GetPrologueByteSize(); 47521fed052SAidan Dodds ConstString name = sc.GetFunctionName(); 47621fed052SAidan Dodds if (offset) 47721fed052SAidan Dodds addr.Slide(offset); 47863e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s: Prologue offset for %s is %" PRIu32, __FUNCTION__, 47921fed052SAidan Dodds name.AsCString(), offset); 48021fed052SAidan Dodds } 48121fed052SAidan Dodds return true; 48221fed052SAidan Dodds } else 48321fed052SAidan Dodds return false; 48421fed052SAidan Dodds } 485222b937cSEugene Zelenko } // anonymous namespace 48678f339d1SEwan Crawford 487b9c1b51eSKate Stone // The ScriptDetails class collects data associated with a single script 488b9c1b51eSKate Stone // instance. 489b9c1b51eSKate Stone struct RenderScriptRuntime::ScriptDetails { 490222b937cSEugene Zelenko ~ScriptDetails() = default; 49178f339d1SEwan Crawford 492b9c1b51eSKate Stone enum ScriptType { eScript, eScriptC }; 49378f339d1SEwan Crawford 49478f339d1SEwan Crawford // The derived type of the script. 49578f339d1SEwan Crawford empirical_type<ScriptType> type; 49678f339d1SEwan Crawford // The name of the original source file. 49780af0b9eSLuke Drummond empirical_type<std::string> res_name; 49878f339d1SEwan Crawford // Path to script .so file on the device. 49980af0b9eSLuke Drummond empirical_type<std::string> shared_lib; 50078f339d1SEwan Crawford // Directory where kernel objects are cached on device. 50180af0b9eSLuke Drummond empirical_type<std::string> cache_dir; 50278f339d1SEwan Crawford // Pointer to the context which owns this script. 50378f339d1SEwan Crawford empirical_type<lldb::addr_t> context; 50478f339d1SEwan Crawford // Pointer to the script object itself. 50578f339d1SEwan Crawford empirical_type<lldb::addr_t> script; 50678f339d1SEwan Crawford }; 50778f339d1SEwan Crawford 50880af0b9eSLuke Drummond // This Element class represents the Element object in RS, defining the type 50980af0b9eSLuke Drummond // associated with an Allocation. 510b9c1b51eSKate Stone struct RenderScriptRuntime::Element { 51115f2bd95SEwan Crawford // Taken from rsDefines.h 512b9c1b51eSKate Stone enum DataKind { 51315f2bd95SEwan Crawford RS_KIND_USER, 51415f2bd95SEwan Crawford RS_KIND_PIXEL_L = 7, 51515f2bd95SEwan Crawford RS_KIND_PIXEL_A, 51615f2bd95SEwan Crawford RS_KIND_PIXEL_LA, 51715f2bd95SEwan Crawford RS_KIND_PIXEL_RGB, 51815f2bd95SEwan Crawford RS_KIND_PIXEL_RGBA, 51915f2bd95SEwan Crawford RS_KIND_PIXEL_DEPTH, 52015f2bd95SEwan Crawford RS_KIND_PIXEL_YUV, 52115f2bd95SEwan Crawford RS_KIND_INVALID = 100 52215f2bd95SEwan Crawford }; 52378f339d1SEwan Crawford 52415f2bd95SEwan Crawford // Taken from rsDefines.h 525b9c1b51eSKate Stone enum DataType { 52615f2bd95SEwan Crawford RS_TYPE_NONE = 0, 52715f2bd95SEwan Crawford RS_TYPE_FLOAT_16, 52815f2bd95SEwan Crawford RS_TYPE_FLOAT_32, 52915f2bd95SEwan Crawford RS_TYPE_FLOAT_64, 53015f2bd95SEwan Crawford RS_TYPE_SIGNED_8, 53115f2bd95SEwan Crawford RS_TYPE_SIGNED_16, 53215f2bd95SEwan Crawford RS_TYPE_SIGNED_32, 53315f2bd95SEwan Crawford RS_TYPE_SIGNED_64, 53415f2bd95SEwan Crawford RS_TYPE_UNSIGNED_8, 53515f2bd95SEwan Crawford RS_TYPE_UNSIGNED_16, 53615f2bd95SEwan Crawford RS_TYPE_UNSIGNED_32, 53715f2bd95SEwan Crawford RS_TYPE_UNSIGNED_64, 5382e920715SEwan Crawford RS_TYPE_BOOLEAN, 5392e920715SEwan Crawford 5402e920715SEwan Crawford RS_TYPE_UNSIGNED_5_6_5, 5412e920715SEwan Crawford RS_TYPE_UNSIGNED_5_5_5_1, 5422e920715SEwan Crawford RS_TYPE_UNSIGNED_4_4_4_4, 5432e920715SEwan Crawford 5442e920715SEwan Crawford RS_TYPE_MATRIX_4X4, 5452e920715SEwan Crawford RS_TYPE_MATRIX_3X3, 5462e920715SEwan Crawford RS_TYPE_MATRIX_2X2, 5472e920715SEwan Crawford 5482e920715SEwan Crawford RS_TYPE_ELEMENT = 1000, 5492e920715SEwan Crawford RS_TYPE_TYPE, 5502e920715SEwan Crawford RS_TYPE_ALLOCATION, 5512e920715SEwan Crawford RS_TYPE_SAMPLER, 5522e920715SEwan Crawford RS_TYPE_SCRIPT, 5532e920715SEwan Crawford RS_TYPE_MESH, 5542e920715SEwan Crawford RS_TYPE_PROGRAM_FRAGMENT, 5552e920715SEwan Crawford RS_TYPE_PROGRAM_VERTEX, 5562e920715SEwan Crawford RS_TYPE_PROGRAM_RASTER, 5572e920715SEwan Crawford RS_TYPE_PROGRAM_STORE, 5582e920715SEwan Crawford RS_TYPE_FONT, 5592e920715SEwan Crawford 5602e920715SEwan Crawford RS_TYPE_INVALID = 10000 56178f339d1SEwan Crawford }; 56278f339d1SEwan Crawford 5638b244e21SEwan Crawford std::vector<Element> children; // Child Element fields for structs 564b9c1b51eSKate Stone empirical_type<lldb::addr_t> 565b9c1b51eSKate Stone element_ptr; // Pointer to the RS Element of the Type 566b9c1b51eSKate Stone empirical_type<DataType> 567b9c1b51eSKate Stone type; // Type of each data pointer stored by the allocation 568b9c1b51eSKate Stone empirical_type<DataKind> 569b9c1b51eSKate Stone type_kind; // Defines pixel type if Allocation is created from an image 570b9c1b51eSKate Stone empirical_type<uint32_t> 571b9c1b51eSKate Stone type_vec_size; // Vector size of each data point, e.g '4' for uchar4 5728b244e21SEwan Crawford empirical_type<uint32_t> field_count; // Number of Subelements 5738b244e21SEwan Crawford empirical_type<uint32_t> datum_size; // Size of a single Element with padding 5748b244e21SEwan Crawford empirical_type<uint32_t> padding; // Number of padding bytes 575b9c1b51eSKate Stone empirical_type<uint32_t> 5764ebdee0aSBruce Mitchener array_size; // Number of items in array, only needed for structs 5778b244e21SEwan Crawford ConstString type_name; // Name of type, only needed for structs 5788b244e21SEwan Crawford 5790e4c4821SAdrian Prantl static ConstString 580b3f7f69dSAidan Dodds GetFallbackStructName(); // Print this as the type name of a struct Element 5818b244e21SEwan Crawford // If we can't resolve the actual struct name 5828b59062aSEwan Crawford 58380af0b9eSLuke Drummond bool ShouldRefresh() const { 5848b59062aSEwan Crawford const bool valid_ptr = element_ptr.isValid() && *element_ptr.get() != 0x0; 585b9c1b51eSKate Stone const bool valid_type = 586b9c1b51eSKate Stone type.isValid() && type_vec_size.isValid() && type_kind.isValid(); 5878b59062aSEwan Crawford return !valid_ptr || !valid_type || !datum_size.isValid(); 5888b59062aSEwan Crawford } 5898b244e21SEwan Crawford }; 5908b244e21SEwan Crawford 5918b244e21SEwan Crawford // This AllocationDetails class collects data associated with a single 5928b244e21SEwan Crawford // allocation instance. 593b9c1b51eSKate Stone struct RenderScriptRuntime::AllocationDetails { 594b9c1b51eSKate Stone struct Dimension { 59515f2bd95SEwan Crawford uint32_t dim_1; 59615f2bd95SEwan Crawford uint32_t dim_2; 59715f2bd95SEwan Crawford uint32_t dim_3; 59880af0b9eSLuke Drummond uint32_t cube_map; 59915f2bd95SEwan Crawford 600b9c1b51eSKate Stone Dimension() { 60115f2bd95SEwan Crawford dim_1 = 0; 60215f2bd95SEwan Crawford dim_2 = 0; 60315f2bd95SEwan Crawford dim_3 = 0; 60480af0b9eSLuke Drummond cube_map = 0; 60515f2bd95SEwan Crawford } 60678f339d1SEwan Crawford }; 60778f339d1SEwan Crawford 608b9c1b51eSKate Stone // The FileHeader struct specifies the header we use for writing allocations 60980af0b9eSLuke Drummond // to a binary file. Our format begins with the ASCII characters "RSAD", 61080af0b9eSLuke Drummond // identifying the file as an allocation dump. Member variables dims and 61180af0b9eSLuke Drummond // hdr_size are then written consecutively, immediately followed by an 61280af0b9eSLuke Drummond // instance of the ElementHeader struct. Because Elements can contain 61380af0b9eSLuke Drummond // subelements, there may be more than one instance of the ElementHeader 61480af0b9eSLuke Drummond // struct. With this first instance being the root element, and the other 61580af0b9eSLuke Drummond // instances being the root's descendants. To identify which instances are an 61605097246SAdrian Prantl // ElementHeader's children, each struct is immediately followed by a 61705097246SAdrian Prantl // sequence of consecutive offsets to the start of its child structs. These 61805097246SAdrian Prantl // offsets are 61980af0b9eSLuke Drummond // 4 bytes in size, and the 0 offset signifies no more children. 620b9c1b51eSKate Stone struct FileHeader { 62155232f09SEwan Crawford uint8_t ident[4]; // ASCII 'RSAD' identifying the file 62226e52a70SEwan Crawford uint32_t dims[3]; // Dimensions 62326e52a70SEwan Crawford uint16_t hdr_size; // Header size in bytes, including all element headers 62426e52a70SEwan Crawford }; 62526e52a70SEwan Crawford 626b9c1b51eSKate Stone struct ElementHeader { 62755232f09SEwan Crawford uint16_t type; // DataType enum 62855232f09SEwan Crawford uint32_t kind; // DataKind enum 62955232f09SEwan Crawford uint32_t element_size; // Size of a single element, including padding 63026e52a70SEwan Crawford uint16_t vector_size; // Vector width 63126e52a70SEwan Crawford uint32_t array_size; // Number of elements in array 63255232f09SEwan Crawford }; 63355232f09SEwan Crawford 63415f2bd95SEwan Crawford // Monotonically increasing from 1 635b3f7f69dSAidan Dodds static uint32_t ID; 63615f2bd95SEwan Crawford 63705097246SAdrian Prantl // Maps Allocation DataType enum and vector size to printable strings using 63805097246SAdrian Prantl // mapping from RenderScript numerical types summary documentation 63915f2bd95SEwan Crawford static const char *RsDataTypeToString[][4]; 64015f2bd95SEwan Crawford 64115f2bd95SEwan Crawford // Maps Allocation DataKind enum to printable strings 64215f2bd95SEwan Crawford static const char *RsDataKindToString[]; 64315f2bd95SEwan Crawford 644a0f08674SEwan Crawford // Maps allocation types to format sizes for printing. 645b3f7f69dSAidan Dodds static const uint32_t RSTypeToFormat[][3]; 646a0f08674SEwan Crawford 64715f2bd95SEwan Crawford // Give each allocation an ID as a way 64815f2bd95SEwan Crawford // for commands to reference it. 649b3f7f69dSAidan Dodds const uint32_t id; 65015f2bd95SEwan Crawford 65180af0b9eSLuke Drummond // Allocation Element type 65280af0b9eSLuke Drummond RenderScriptRuntime::Element element; 65380af0b9eSLuke Drummond // Dimensions of the Allocation 65480af0b9eSLuke Drummond empirical_type<Dimension> dimension; 65580af0b9eSLuke Drummond // Pointer to address of the RS Allocation 65680af0b9eSLuke Drummond empirical_type<lldb::addr_t> address; 65780af0b9eSLuke Drummond // Pointer to the data held by the Allocation 65880af0b9eSLuke Drummond empirical_type<lldb::addr_t> data_ptr; 65980af0b9eSLuke Drummond // Pointer to the RS Type of the Allocation 66080af0b9eSLuke Drummond empirical_type<lldb::addr_t> type_ptr; 66180af0b9eSLuke Drummond // Pointer to the RS Context of the Allocation 66280af0b9eSLuke Drummond empirical_type<lldb::addr_t> context; 66380af0b9eSLuke Drummond // Size of the allocation 66480af0b9eSLuke Drummond empirical_type<uint32_t> size; 66580af0b9eSLuke Drummond // Stride between rows of the allocation 66680af0b9eSLuke Drummond empirical_type<uint32_t> stride; 66715f2bd95SEwan Crawford 66815f2bd95SEwan Crawford // Give each allocation an id, so we can reference it in user commands. 669b3f7f69dSAidan Dodds AllocationDetails() : id(ID++) {} 6708b59062aSEwan Crawford 67180af0b9eSLuke Drummond bool ShouldRefresh() const { 6728b59062aSEwan Crawford bool valid_ptrs = data_ptr.isValid() && *data_ptr.get() != 0x0; 6738b59062aSEwan Crawford valid_ptrs = valid_ptrs && type_ptr.isValid() && *type_ptr.get() != 0x0; 674b9c1b51eSKate Stone return !valid_ptrs || !dimension.isValid() || !size.isValid() || 67580af0b9eSLuke Drummond element.ShouldRefresh(); 6768b59062aSEwan Crawford } 67715f2bd95SEwan Crawford }; 67815f2bd95SEwan Crawford 6790e4c4821SAdrian Prantl ConstString RenderScriptRuntime::Element::GetFallbackStructName() { 680fe06b5adSAdrian McCarthy static const ConstString FallbackStructName("struct"); 681fe06b5adSAdrian McCarthy return FallbackStructName; 682fe06b5adSAdrian McCarthy } 6838b244e21SEwan Crawford 684b3f7f69dSAidan Dodds uint32_t RenderScriptRuntime::AllocationDetails::ID = 1; 68515f2bd95SEwan Crawford 686b3f7f69dSAidan Dodds const char *RenderScriptRuntime::AllocationDetails::RsDataKindToString[] = { 687b9c1b51eSKate Stone "User", "Undefined", "Undefined", "Undefined", 688b9c1b51eSKate Stone "Undefined", "Undefined", "Undefined", // Enum jumps from 0 to 7 689b3f7f69dSAidan Dodds "L Pixel", "A Pixel", "LA Pixel", "RGB Pixel", 690b3f7f69dSAidan Dodds "RGBA Pixel", "Pixel Depth", "YUV Pixel"}; 69115f2bd95SEwan Crawford 692b3f7f69dSAidan Dodds const char *RenderScriptRuntime::AllocationDetails::RsDataTypeToString[][4] = { 69315f2bd95SEwan Crawford {"None", "None", "None", "None"}, 69415f2bd95SEwan Crawford {"half", "half2", "half3", "half4"}, 69515f2bd95SEwan Crawford {"float", "float2", "float3", "float4"}, 69615f2bd95SEwan Crawford {"double", "double2", "double3", "double4"}, 69715f2bd95SEwan Crawford {"char", "char2", "char3", "char4"}, 69815f2bd95SEwan Crawford {"short", "short2", "short3", "short4"}, 69915f2bd95SEwan Crawford {"int", "int2", "int3", "int4"}, 70015f2bd95SEwan Crawford {"long", "long2", "long3", "long4"}, 70115f2bd95SEwan Crawford {"uchar", "uchar2", "uchar3", "uchar4"}, 70215f2bd95SEwan Crawford {"ushort", "ushort2", "ushort3", "ushort4"}, 70315f2bd95SEwan Crawford {"uint", "uint2", "uint3", "uint4"}, 70415f2bd95SEwan Crawford {"ulong", "ulong2", "ulong3", "ulong4"}, 7052e920715SEwan Crawford {"bool", "bool2", "bool3", "bool4"}, 7062e920715SEwan Crawford {"packed_565", "packed_565", "packed_565", "packed_565"}, 7072e920715SEwan Crawford {"packed_5551", "packed_5551", "packed_5551", "packed_5551"}, 7082e920715SEwan Crawford {"packed_4444", "packed_4444", "packed_4444", "packed_4444"}, 7092e920715SEwan Crawford {"rs_matrix4x4", "rs_matrix4x4", "rs_matrix4x4", "rs_matrix4x4"}, 7102e920715SEwan Crawford {"rs_matrix3x3", "rs_matrix3x3", "rs_matrix3x3", "rs_matrix3x3"}, 7112e920715SEwan Crawford {"rs_matrix2x2", "rs_matrix2x2", "rs_matrix2x2", "rs_matrix2x2"}, 7122e920715SEwan Crawford 7132e920715SEwan Crawford // Handlers 7142e920715SEwan Crawford {"RS Element", "RS Element", "RS Element", "RS Element"}, 7152e920715SEwan Crawford {"RS Type", "RS Type", "RS Type", "RS Type"}, 7162e920715SEwan Crawford {"RS Allocation", "RS Allocation", "RS Allocation", "RS Allocation"}, 7172e920715SEwan Crawford {"RS Sampler", "RS Sampler", "RS Sampler", "RS Sampler"}, 7182e920715SEwan Crawford {"RS Script", "RS Script", "RS Script", "RS Script"}, 7192e920715SEwan Crawford 7202e920715SEwan Crawford // Deprecated 7212e920715SEwan Crawford {"RS Mesh", "RS Mesh", "RS Mesh", "RS Mesh"}, 722b9c1b51eSKate Stone {"RS Program Fragment", "RS Program Fragment", "RS Program Fragment", 723b9c1b51eSKate Stone "RS Program Fragment"}, 724b9c1b51eSKate Stone {"RS Program Vertex", "RS Program Vertex", "RS Program Vertex", 725b9c1b51eSKate Stone "RS Program Vertex"}, 726b9c1b51eSKate Stone {"RS Program Raster", "RS Program Raster", "RS Program Raster", 727b9c1b51eSKate Stone "RS Program Raster"}, 728b9c1b51eSKate Stone {"RS Program Store", "RS Program Store", "RS Program Store", 729b9c1b51eSKate Stone "RS Program Store"}, 730b3f7f69dSAidan Dodds {"RS Font", "RS Font", "RS Font", "RS Font"}}; 73178f339d1SEwan Crawford 732a0f08674SEwan Crawford // Used as an index into the RSTypeToFormat array elements 733b9c1b51eSKate Stone enum TypeToFormatIndex { eFormatSingle = 0, eFormatVector, eElementSize }; 734a0f08674SEwan Crawford 735b9c1b51eSKate Stone // { format enum of single element, format enum of element vector, size of 736b9c1b51eSKate Stone // element} 737b3f7f69dSAidan Dodds const uint32_t RenderScriptRuntime::AllocationDetails::RSTypeToFormat[][3] = { 73880af0b9eSLuke Drummond // RS_TYPE_NONE 73980af0b9eSLuke Drummond {eFormatHex, eFormatHex, 1}, 74080af0b9eSLuke Drummond // RS_TYPE_FLOAT_16 74180af0b9eSLuke Drummond {eFormatFloat, eFormatVectorOfFloat16, 2}, 74280af0b9eSLuke Drummond // RS_TYPE_FLOAT_32 74380af0b9eSLuke Drummond {eFormatFloat, eFormatVectorOfFloat32, sizeof(float)}, 74480af0b9eSLuke Drummond // RS_TYPE_FLOAT_64 74580af0b9eSLuke Drummond {eFormatFloat, eFormatVectorOfFloat64, sizeof(double)}, 74680af0b9eSLuke Drummond // RS_TYPE_SIGNED_8 74780af0b9eSLuke Drummond {eFormatDecimal, eFormatVectorOfSInt8, sizeof(int8_t)}, 74880af0b9eSLuke Drummond // RS_TYPE_SIGNED_16 74980af0b9eSLuke Drummond {eFormatDecimal, eFormatVectorOfSInt16, sizeof(int16_t)}, 75080af0b9eSLuke Drummond // RS_TYPE_SIGNED_32 75180af0b9eSLuke Drummond {eFormatDecimal, eFormatVectorOfSInt32, sizeof(int32_t)}, 75280af0b9eSLuke Drummond // RS_TYPE_SIGNED_64 75380af0b9eSLuke Drummond {eFormatDecimal, eFormatVectorOfSInt64, sizeof(int64_t)}, 75480af0b9eSLuke Drummond // RS_TYPE_UNSIGNED_8 75580af0b9eSLuke Drummond {eFormatDecimal, eFormatVectorOfUInt8, sizeof(uint8_t)}, 75680af0b9eSLuke Drummond // RS_TYPE_UNSIGNED_16 75780af0b9eSLuke Drummond {eFormatDecimal, eFormatVectorOfUInt16, sizeof(uint16_t)}, 75880af0b9eSLuke Drummond // RS_TYPE_UNSIGNED_32 75980af0b9eSLuke Drummond {eFormatDecimal, eFormatVectorOfUInt32, sizeof(uint32_t)}, 76080af0b9eSLuke Drummond // RS_TYPE_UNSIGNED_64 76180af0b9eSLuke Drummond {eFormatDecimal, eFormatVectorOfUInt64, sizeof(uint64_t)}, 76280af0b9eSLuke Drummond // RS_TYPE_BOOL 76380af0b9eSLuke Drummond {eFormatBoolean, eFormatBoolean, 1}, 76480af0b9eSLuke Drummond // RS_TYPE_UNSIGNED_5_6_5 76580af0b9eSLuke Drummond {eFormatHex, eFormatHex, sizeof(uint16_t)}, 76680af0b9eSLuke Drummond // RS_TYPE_UNSIGNED_5_5_5_1 76780af0b9eSLuke Drummond {eFormatHex, eFormatHex, sizeof(uint16_t)}, 76880af0b9eSLuke Drummond // RS_TYPE_UNSIGNED_4_4_4_4 76980af0b9eSLuke Drummond {eFormatHex, eFormatHex, sizeof(uint16_t)}, 77080af0b9eSLuke Drummond // RS_TYPE_MATRIX_4X4 77180af0b9eSLuke Drummond {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 16}, 77280af0b9eSLuke Drummond // RS_TYPE_MATRIX_3X3 77380af0b9eSLuke Drummond {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 9}, 77480af0b9eSLuke Drummond // RS_TYPE_MATRIX_2X2 77580af0b9eSLuke Drummond {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 4}}; 776a0f08674SEwan Crawford 7775ec532a9SColin Riley // Static Functions 7785ec532a9SColin Riley LanguageRuntime * 779b9c1b51eSKate Stone RenderScriptRuntime::CreateInstance(Process *process, 780b9c1b51eSKate Stone lldb::LanguageType language) { 7815ec532a9SColin Riley 7825ec532a9SColin Riley if (language == eLanguageTypeExtRenderScript) 7835ec532a9SColin Riley return new RenderScriptRuntime(process); 7845ec532a9SColin Riley else 785b3f7f69dSAidan Dodds return nullptr; 7865ec532a9SColin Riley } 7875ec532a9SColin Riley 78880af0b9eSLuke Drummond // Callback with a module to search for matching symbols. We first check that 78980af0b9eSLuke Drummond // the module contains RS kernels. Then look for a symbol which matches our 79080af0b9eSLuke Drummond // kernel name. The breakpoint address is finally set using the address of this 79180af0b9eSLuke Drummond // symbol. 79298156583SEwan Crawford Searcher::CallbackReturn 793b9c1b51eSKate Stone RSBreakpointResolver::SearchCallback(SearchFilter &filter, 79495e264fcSRaphael Isemann SymbolContext &context, Address *) { 7956c17cc53STatyana Krasnukha BreakpointSP breakpoint_sp = GetBreakpoint(); 7966c17cc53STatyana Krasnukha assert(breakpoint_sp); 7976c17cc53STatyana Krasnukha 79898156583SEwan Crawford ModuleSP module = context.module_sp; 79998156583SEwan Crawford 800b3bbcb12SLuke Drummond if (!module || !IsRenderScriptScriptModule(module)) 80198156583SEwan Crawford return Searcher::eCallbackReturnContinue; 80298156583SEwan Crawford 803b9c1b51eSKate Stone // Attempt to set a breakpoint on the kernel name symbol within the module 80480af0b9eSLuke Drummond // library. If it's not found, it's likely debug info is unavailable - try to 80580af0b9eSLuke Drummond // set a breakpoint on <name>.expand. 806b9c1b51eSKate Stone const Symbol *kernel_sym = 807b9c1b51eSKate Stone module->FindFirstSymbolWithNameAndType(m_kernel_name, eSymbolTypeCode); 808b9c1b51eSKate Stone if (!kernel_sym) { 80998156583SEwan Crawford std::string kernel_name_expanded(m_kernel_name.AsCString()); 81098156583SEwan Crawford kernel_name_expanded.append(".expand"); 811b9c1b51eSKate Stone kernel_sym = module->FindFirstSymbolWithNameAndType( 812b9c1b51eSKate Stone ConstString(kernel_name_expanded.c_str()), eSymbolTypeCode); 81398156583SEwan Crawford } 81498156583SEwan Crawford 815b9c1b51eSKate Stone if (kernel_sym) { 81698156583SEwan Crawford Address bp_addr = kernel_sym->GetAddress(); 81798156583SEwan Crawford if (filter.AddressPasses(bp_addr)) 8186c17cc53STatyana Krasnukha breakpoint_sp->AddLocation(bp_addr); 81998156583SEwan Crawford } 82098156583SEwan Crawford 82198156583SEwan Crawford return Searcher::eCallbackReturnContinue; 82298156583SEwan Crawford } 82398156583SEwan Crawford 824b3bbcb12SLuke Drummond Searcher::CallbackReturn 825b3bbcb12SLuke Drummond RSReduceBreakpointResolver::SearchCallback(lldb_private::SearchFilter &filter, 826b3bbcb12SLuke Drummond lldb_private::SymbolContext &context, 82795e264fcSRaphael Isemann Address *) { 8286c17cc53STatyana Krasnukha BreakpointSP breakpoint_sp = GetBreakpoint(); 8296c17cc53STatyana Krasnukha assert(breakpoint_sp); 8306c17cc53STatyana Krasnukha 831b3bbcb12SLuke Drummond // We need to have access to the list of reductions currently parsed, as 83205097246SAdrian Prantl // reduce names don't actually exist as symbols in a module. They are only 83305097246SAdrian Prantl // identifiable by parsing the .rs.info packet, or finding the expand symbol. 83405097246SAdrian Prantl // We therefore need access to the list of parsed rs modules to properly 83505097246SAdrian Prantl // resolve reduction names. 836*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Breakpoints); 837b3bbcb12SLuke Drummond ModuleSP module = context.module_sp; 838b3bbcb12SLuke Drummond 839b3bbcb12SLuke Drummond if (!module || !IsRenderScriptScriptModule(module)) 840b3bbcb12SLuke Drummond return Searcher::eCallbackReturnContinue; 841b3bbcb12SLuke Drummond 842b3bbcb12SLuke Drummond if (!m_rsmodules) 843b3bbcb12SLuke Drummond return Searcher::eCallbackReturnContinue; 844b3bbcb12SLuke Drummond 845b3bbcb12SLuke Drummond for (const auto &module_desc : *m_rsmodules) { 846b3bbcb12SLuke Drummond if (module_desc->m_module != module) 847b3bbcb12SLuke Drummond continue; 848b3bbcb12SLuke Drummond 849b3bbcb12SLuke Drummond for (const auto &reduction : module_desc->m_reductions) { 850b3bbcb12SLuke Drummond if (reduction.m_reduce_name != m_reduce_name) 851b3bbcb12SLuke Drummond continue; 852b3bbcb12SLuke Drummond 853b3bbcb12SLuke Drummond std::array<std::pair<ConstString, int>, 5> funcs{ 854b3bbcb12SLuke Drummond {{reduction.m_init_name, eKernelTypeInit}, 855b3bbcb12SLuke Drummond {reduction.m_accum_name, eKernelTypeAccum}, 856b3bbcb12SLuke Drummond {reduction.m_comb_name, eKernelTypeComb}, 857b3bbcb12SLuke Drummond {reduction.m_outc_name, eKernelTypeOutC}, 858b3bbcb12SLuke Drummond {reduction.m_halter_name, eKernelTypeHalter}}}; 859b3bbcb12SLuke Drummond 860b3bbcb12SLuke Drummond for (const auto &kernel : funcs) { 861b3bbcb12SLuke Drummond // Skip constituent functions that don't match our spec 862b3bbcb12SLuke Drummond if (!(m_kernel_types & kernel.second)) 863b3bbcb12SLuke Drummond continue; 864b3bbcb12SLuke Drummond 865b3bbcb12SLuke Drummond const auto kernel_name = kernel.first; 866b3bbcb12SLuke Drummond const auto symbol = module->FindFirstSymbolWithNameAndType( 867b3bbcb12SLuke Drummond kernel_name, eSymbolTypeCode); 868b3bbcb12SLuke Drummond if (!symbol) 869b3bbcb12SLuke Drummond continue; 870b3bbcb12SLuke Drummond 871b3bbcb12SLuke Drummond auto address = symbol->GetAddress(); 872b3bbcb12SLuke Drummond if (filter.AddressPasses(address)) { 873b3bbcb12SLuke Drummond bool new_bp; 87481fc84faSLuke Drummond if (!SkipPrologue(module, address)) { 87563e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s: Error trying to skip prologue", __FUNCTION__); 87681fc84faSLuke Drummond } 8776c17cc53STatyana Krasnukha breakpoint_sp->AddLocation(address, &new_bp); 87863e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s: %s reduction breakpoint on %s in %s", 87963e5fb76SJonas Devlieghere __FUNCTION__, new_bp ? "new" : "existing", 88063e5fb76SJonas Devlieghere kernel_name.GetCString(), 881b3bbcb12SLuke Drummond address.GetModule()->GetFileSpec().GetCString()); 882b3bbcb12SLuke Drummond } 883b3bbcb12SLuke Drummond } 884b3bbcb12SLuke Drummond } 885b3bbcb12SLuke Drummond } 886b3bbcb12SLuke Drummond return eCallbackReturnContinue; 887b3bbcb12SLuke Drummond } 888b3bbcb12SLuke Drummond 88921fed052SAidan Dodds Searcher::CallbackReturn RSScriptGroupBreakpointResolver::SearchCallback( 89095e264fcSRaphael Isemann SearchFilter &filter, SymbolContext &context, Address *addr) { 89121fed052SAidan Dodds 8926c17cc53STatyana Krasnukha BreakpointSP breakpoint_sp = GetBreakpoint(); 8936c17cc53STatyana Krasnukha if (!breakpoint_sp) 89421fed052SAidan Dodds return eCallbackReturnContinue; 89521fed052SAidan Dodds 896*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Breakpoints); 89721fed052SAidan Dodds ModuleSP &module = context.module_sp; 89821fed052SAidan Dodds 89921fed052SAidan Dodds if (!module || !IsRenderScriptScriptModule(module)) 90021fed052SAidan Dodds return Searcher::eCallbackReturnContinue; 90121fed052SAidan Dodds 90221fed052SAidan Dodds std::vector<std::string> names; 9036c17cc53STatyana Krasnukha Breakpoint& breakpoint = *breakpoint_sp; 9046c17cc53STatyana Krasnukha breakpoint.GetNames(names); 90521fed052SAidan Dodds if (names.empty()) 90621fed052SAidan Dodds return eCallbackReturnContinue; 90721fed052SAidan Dodds 90821fed052SAidan Dodds for (auto &name : names) { 90921fed052SAidan Dodds const RSScriptGroupDescriptorSP sg = FindScriptGroup(ConstString(name)); 91021fed052SAidan Dodds if (!sg) { 91163e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s: could not find script group for %s", __FUNCTION__, 91221fed052SAidan Dodds name.c_str()); 91321fed052SAidan Dodds continue; 91421fed052SAidan Dodds } 91521fed052SAidan Dodds 91663e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s: Found ScriptGroup for %s", __FUNCTION__, name.c_str()); 91721fed052SAidan Dodds 91821fed052SAidan Dodds for (const RSScriptGroupDescriptor::Kernel &k : sg->m_kernels) { 91921fed052SAidan Dodds if (log) { 92063e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s: Adding breakpoint for %s", __FUNCTION__, 92121fed052SAidan Dodds k.m_name.AsCString()); 92263e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s: Kernel address 0x%" PRIx64, __FUNCTION__, k.m_addr); 92321fed052SAidan Dodds } 92421fed052SAidan Dodds 92521fed052SAidan Dodds const lldb_private::Symbol *sym = 92621fed052SAidan Dodds module->FindFirstSymbolWithNameAndType(k.m_name, eSymbolTypeCode); 92721fed052SAidan Dodds if (!sym) { 92863e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s: Unable to find symbol for %s", __FUNCTION__, 92921fed052SAidan Dodds k.m_name.AsCString()); 93021fed052SAidan Dodds continue; 93121fed052SAidan Dodds } 93221fed052SAidan Dodds 93321fed052SAidan Dodds if (log) { 93463e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s: Found symbol name is %s", __FUNCTION__, 93521fed052SAidan Dodds sym->GetName().AsCString()); 93621fed052SAidan Dodds } 93721fed052SAidan Dodds 93821fed052SAidan Dodds auto address = sym->GetAddress(); 93921fed052SAidan Dodds if (!SkipPrologue(module, address)) { 94063e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s: Error trying to skip prologue", __FUNCTION__); 94121fed052SAidan Dodds } 94221fed052SAidan Dodds 94321fed052SAidan Dodds bool new_bp; 9446c17cc53STatyana Krasnukha breakpoint.AddLocation(address, &new_bp); 94521fed052SAidan Dodds 94663e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s: Placed %sbreakpoint on %s", __FUNCTION__, 94721fed052SAidan Dodds new_bp ? "new " : "", k.m_name.AsCString()); 94821fed052SAidan Dodds 94905097246SAdrian Prantl // exit after placing the first breakpoint if we do not intend to stop on 95005097246SAdrian Prantl // all kernels making up this script group 95121fed052SAidan Dodds if (!m_stop_on_all) 95221fed052SAidan Dodds break; 95321fed052SAidan Dodds } 95421fed052SAidan Dodds } 95521fed052SAidan Dodds 95621fed052SAidan Dodds return eCallbackReturnContinue; 95721fed052SAidan Dodds } 95821fed052SAidan Dodds 959b9c1b51eSKate Stone void RenderScriptRuntime::Initialize() { 960b9c1b51eSKate Stone PluginManager::RegisterPlugin(GetPluginNameStatic(), 961b9c1b51eSKate Stone "RenderScript language support", CreateInstance, 962b3f7f69dSAidan Dodds GetCommandObject); 9635ec532a9SColin Riley } 9645ec532a9SColin Riley 965b9c1b51eSKate Stone void RenderScriptRuntime::Terminate() { 9665ec532a9SColin Riley PluginManager::UnregisterPlugin(CreateInstance); 9675ec532a9SColin Riley } 9685ec532a9SColin Riley 969ef20b08fSColin Riley RenderScriptRuntime::ModuleKind 970b9c1b51eSKate Stone RenderScriptRuntime::GetModuleKind(const lldb::ModuleSP &module_sp) { 971b9c1b51eSKate Stone if (module_sp) { 972b3bbcb12SLuke Drummond if (IsRenderScriptScriptModule(module_sp)) 973ef20b08fSColin Riley return eModuleKindKernelObj; 9744640cde1SColin Riley 9754640cde1SColin Riley // Is this the main RS runtime library 9764640cde1SColin Riley const ConstString rs_lib("libRS.so"); 977b9c1b51eSKate Stone if (module_sp->GetFileSpec().GetFilename() == rs_lib) { 9784640cde1SColin Riley return eModuleKindLibRS; 9794640cde1SColin Riley } 9804640cde1SColin Riley 9814640cde1SColin Riley const ConstString rs_driverlib("libRSDriver.so"); 982b9c1b51eSKate Stone if (module_sp->GetFileSpec().GetFilename() == rs_driverlib) { 9834640cde1SColin Riley return eModuleKindDriver; 9844640cde1SColin Riley } 9854640cde1SColin Riley 98615f2bd95SEwan Crawford const ConstString rs_cpureflib("libRSCpuRef.so"); 987b9c1b51eSKate Stone if (module_sp->GetFileSpec().GetFilename() == rs_cpureflib) { 9884640cde1SColin Riley return eModuleKindImpl; 9894640cde1SColin Riley } 990ef20b08fSColin Riley } 991ef20b08fSColin Riley return eModuleKindIgnored; 992ef20b08fSColin Riley } 993ef20b08fSColin Riley 994b9c1b51eSKate Stone bool RenderScriptRuntime::IsRenderScriptModule( 995b9c1b51eSKate Stone const lldb::ModuleSP &module_sp) { 996ef20b08fSColin Riley return GetModuleKind(module_sp) != eModuleKindIgnored; 997ef20b08fSColin Riley } 998ef20b08fSColin Riley 999b9c1b51eSKate Stone void RenderScriptRuntime::ModulesDidLoad(const ModuleList &module_list) { 1000bb19a13cSSaleem Abdulrasool std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex()); 1001ef20b08fSColin Riley 1002ef20b08fSColin Riley size_t num_modules = module_list.GetSize(); 1003b9c1b51eSKate Stone for (size_t i = 0; i < num_modules; i++) { 1004ef20b08fSColin Riley auto mod = module_list.GetModuleAtIndex(i); 1005b9c1b51eSKate Stone if (IsRenderScriptModule(mod)) { 1006ef20b08fSColin Riley LoadModule(mod); 1007ef20b08fSColin Riley } 1008ef20b08fSColin Riley } 1009ef20b08fSColin Riley } 1010ef20b08fSColin Riley 1011b9c1b51eSKate Stone bool RenderScriptRuntime::GetDynamicTypeAndAddress( 1012b9c1b51eSKate Stone ValueObject &in_value, lldb::DynamicValueType use_dynamic, 10135f57b6eeSEnrico Granata TypeAndOrName &class_type_or_name, Address &address, 1014b9c1b51eSKate Stone Value::ValueType &value_type) { 10155ec532a9SColin Riley return false; 10165ec532a9SColin Riley } 10175ec532a9SColin Riley 1018c74275bcSEnrico Granata TypeAndOrName 1019b9c1b51eSKate Stone RenderScriptRuntime::FixUpDynamicType(const TypeAndOrName &type_and_or_name, 1020b9c1b51eSKate Stone ValueObject &static_value) { 1021c74275bcSEnrico Granata return type_and_or_name; 1022c74275bcSEnrico Granata } 1023c74275bcSEnrico Granata 1024b9c1b51eSKate Stone bool RenderScriptRuntime::CouldHaveDynamicValue(ValueObject &in_value) { 10255ec532a9SColin Riley return false; 10265ec532a9SColin Riley } 10275ec532a9SColin Riley 10285ec532a9SColin Riley lldb::BreakpointResolverSP 10296c17cc53STatyana Krasnukha RenderScriptRuntime::CreateExceptionResolver(const lldb::BreakpointSP &bp, 10306c17cc53STatyana Krasnukha bool catch_bp, bool throw_bp) { 10315ec532a9SColin Riley BreakpointResolverSP resolver_sp; 10325ec532a9SColin Riley return resolver_sp; 10335ec532a9SColin Riley } 10345ec532a9SColin Riley 1035b9c1b51eSKate Stone const RenderScriptRuntime::HookDefn RenderScriptRuntime::s_runtimeHookDefns[] = 1036b9c1b51eSKate Stone { 10374640cde1SColin Riley // rsdScript 1038b9c1b51eSKate Stone {"rsdScriptInit", "_Z13rsdScriptInitPKN7android12renderscript7ContextEP" 1039b9c1b51eSKate Stone "NS0_7ScriptCEPKcS7_PKhjj", 1040b9c1b51eSKate Stone "_Z13rsdScriptInitPKN7android12renderscript7ContextEPNS0_" 1041b9c1b51eSKate Stone "7ScriptCEPKcS7_PKhmj", 1042b9c1b51eSKate Stone 0, RenderScriptRuntime::eModuleKindDriver, 1043b9c1b51eSKate Stone &lldb_private::RenderScriptRuntime::CaptureScriptInit}, 1044b9c1b51eSKate Stone {"rsdScriptInvokeForEachMulti", 1045b9c1b51eSKate Stone "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0" 1046b9c1b51eSKate Stone "_6ScriptEjPPKNS0_10AllocationEjPS6_PKvjPK12RsScriptCall", 1047b9c1b51eSKate Stone "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0" 1048b9c1b51eSKate Stone "_6ScriptEjPPKNS0_10AllocationEmPS6_PKvmPK12RsScriptCall", 1049b9c1b51eSKate Stone 0, RenderScriptRuntime::eModuleKindDriver, 1050b9c1b51eSKate Stone &lldb_private::RenderScriptRuntime::CaptureScriptInvokeForEachMulti}, 1051b9c1b51eSKate Stone {"rsdScriptSetGlobalVar", "_Z21rsdScriptSetGlobalVarPKN7android12render" 1052b9c1b51eSKate Stone "script7ContextEPKNS0_6ScriptEjPvj", 1053b9c1b51eSKate Stone "_Z21rsdScriptSetGlobalVarPKN7android12renderscript7ContextEPKNS0_" 1054b9c1b51eSKate Stone "6ScriptEjPvm", 1055b9c1b51eSKate Stone 0, RenderScriptRuntime::eModuleKindDriver, 1056b9c1b51eSKate Stone &lldb_private::RenderScriptRuntime::CaptureSetGlobalVar}, 10574640cde1SColin Riley 10584640cde1SColin Riley // rsdAllocation 1059b9c1b51eSKate Stone {"rsdAllocationInit", "_Z17rsdAllocationInitPKN7android12renderscript7C" 1060b9c1b51eSKate Stone "ontextEPNS0_10AllocationEb", 1061b9c1b51eSKate Stone "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_" 1062b9c1b51eSKate Stone "10AllocationEb", 1063b9c1b51eSKate Stone 0, RenderScriptRuntime::eModuleKindDriver, 1064b9c1b51eSKate Stone &lldb_private::RenderScriptRuntime::CaptureAllocationInit}, 1065b9c1b51eSKate Stone {"rsdAllocationRead2D", 1066b9c1b51eSKate Stone "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_" 1067b9c1b51eSKate Stone "10AllocationEjjj23RsAllocationCubemapFacejjPvjj", 1068b9c1b51eSKate Stone "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_" 1069b9c1b51eSKate Stone "10AllocationEjjj23RsAllocationCubemapFacejjPvmm", 1070b9c1b51eSKate Stone 0, RenderScriptRuntime::eModuleKindDriver, nullptr}, 1071b9c1b51eSKate Stone {"rsdAllocationDestroy", "_Z20rsdAllocationDestroyPKN7android12rendersc" 1072b9c1b51eSKate Stone "ript7ContextEPNS0_10AllocationE", 1073b9c1b51eSKate Stone "_Z20rsdAllocationDestroyPKN7android12renderscript7ContextEPNS0_" 1074b9c1b51eSKate Stone "10AllocationE", 1075b9c1b51eSKate Stone 0, RenderScriptRuntime::eModuleKindDriver, 1076b9c1b51eSKate Stone &lldb_private::RenderScriptRuntime::CaptureAllocationDestroy}, 107721fed052SAidan Dodds 107821fed052SAidan Dodds // renderscript script groups 107921fed052SAidan Dodds {"rsdDebugHintScriptGroup2", "_ZN7android12renderscript21debugHintScrip" 108021fed052SAidan Dodds "tGroup2EPKcjPKPFvPK24RsExpandKernelDriver" 108121fed052SAidan Dodds "InfojjjEj", 108221fed052SAidan Dodds "_ZN7android12renderscript21debugHintScriptGroup2EPKcjPKPFvPK24RsExpan" 108321fed052SAidan Dodds "dKernelDriverInfojjjEj", 108421fed052SAidan Dodds 0, RenderScriptRuntime::eModuleKindImpl, 108521fed052SAidan Dodds &lldb_private::RenderScriptRuntime::CaptureDebugHintScriptGroup2}}; 10864640cde1SColin Riley 1087b9c1b51eSKate Stone const size_t RenderScriptRuntime::s_runtimeHookCount = 1088b9c1b51eSKate Stone sizeof(s_runtimeHookDefns) / sizeof(s_runtimeHookDefns[0]); 10894640cde1SColin Riley 1090b9c1b51eSKate Stone bool RenderScriptRuntime::HookCallback(void *baton, 1091b9c1b51eSKate Stone StoppointCallbackContext *ctx, 1092b9c1b51eSKate Stone lldb::user_id_t break_id, 1093b9c1b51eSKate Stone lldb::user_id_t break_loc_id) { 109480af0b9eSLuke Drummond RuntimeHook *hook = (RuntimeHook *)baton; 109580af0b9eSLuke Drummond ExecutionContext exe_ctx(ctx->exe_ctx_ref); 10964640cde1SColin Riley 1097056f6f18SAlex Langford RenderScriptRuntime *lang_rt = llvm::cast<RenderScriptRuntime>( 1098056f6f18SAlex Langford exe_ctx.GetProcessPtr()->GetLanguageRuntime( 1099056f6f18SAlex Langford eLanguageTypeExtRenderScript)); 11004640cde1SColin Riley 110180af0b9eSLuke Drummond lang_rt->HookCallback(hook, exe_ctx); 11024640cde1SColin Riley 11034640cde1SColin Riley return false; 11044640cde1SColin Riley } 11054640cde1SColin Riley 110680af0b9eSLuke Drummond void RenderScriptRuntime::HookCallback(RuntimeHook *hook, 110780af0b9eSLuke Drummond ExecutionContext &exe_ctx) { 1108*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 11094640cde1SColin Riley 111063e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - '%s'", __FUNCTION__, hook->defn->name); 11114640cde1SColin Riley 111280af0b9eSLuke Drummond if (hook->defn->grabber) { 111380af0b9eSLuke Drummond (this->*(hook->defn->grabber))(hook, exe_ctx); 11144640cde1SColin Riley } 11154640cde1SColin Riley } 11164640cde1SColin Riley 111721fed052SAidan Dodds void RenderScriptRuntime::CaptureDebugHintScriptGroup2( 111821fed052SAidan Dodds RuntimeHook *hook_info, ExecutionContext &context) { 1119*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 112021fed052SAidan Dodds 112121fed052SAidan Dodds enum { 112221fed052SAidan Dodds eGroupName = 0, 112321fed052SAidan Dodds eGroupNameSize, 112421fed052SAidan Dodds eKernel, 112521fed052SAidan Dodds eKernelCount, 112621fed052SAidan Dodds }; 112721fed052SAidan Dodds 112821fed052SAidan Dodds std::array<ArgItem, 4> args{{ 112921fed052SAidan Dodds {ArgItem::ePointer, 0}, // const char *groupName 113021fed052SAidan Dodds {ArgItem::eInt32, 0}, // const uint32_t groupNameSize 113121fed052SAidan Dodds {ArgItem::ePointer, 0}, // const ExpandFuncTy *kernel 113221fed052SAidan Dodds {ArgItem::eInt32, 0}, // const uint32_t kernelCount 113321fed052SAidan Dodds }}; 113421fed052SAidan Dodds 113521fed052SAidan Dodds if (!GetArgs(context, args.data(), args.size())) { 113663e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - Error while reading the function parameters", 113721fed052SAidan Dodds __FUNCTION__); 113821fed052SAidan Dodds return; 113921fed052SAidan Dodds } else if (log) { 114063e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - groupName : 0x%" PRIx64, __FUNCTION__, 114121fed052SAidan Dodds addr_t(args[eGroupName])); 114263e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - groupNameSize: %" PRIu64, __FUNCTION__, 114321fed052SAidan Dodds uint64_t(args[eGroupNameSize])); 114463e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - kernel : 0x%" PRIx64, __FUNCTION__, 114521fed052SAidan Dodds addr_t(args[eKernel])); 114663e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - kernelCount : %" PRIu64, __FUNCTION__, 114721fed052SAidan Dodds uint64_t(args[eKernelCount])); 114821fed052SAidan Dodds } 114921fed052SAidan Dodds 115021fed052SAidan Dodds // parse script group name 115121fed052SAidan Dodds ConstString group_name; 115221fed052SAidan Dodds { 115397206d57SZachary Turner Status err; 115421fed052SAidan Dodds const uint64_t len = uint64_t(args[eGroupNameSize]); 115521fed052SAidan Dodds std::unique_ptr<char[]> buffer(new char[uint32_t(len + 1)]); 115621fed052SAidan Dodds m_process->ReadMemory(addr_t(args[eGroupName]), buffer.get(), len, err); 115721fed052SAidan Dodds buffer.get()[len] = '\0'; 115821fed052SAidan Dodds if (!err.Success()) { 115963e5fb76SJonas Devlieghere LLDB_LOGF(log, "Error reading scriptgroup name from target"); 116021fed052SAidan Dodds return; 116121fed052SAidan Dodds } else { 116263e5fb76SJonas Devlieghere LLDB_LOGF(log, "Extracted scriptgroup name %s", buffer.get()); 116321fed052SAidan Dodds } 116421fed052SAidan Dodds // write back the script group name 116521fed052SAidan Dodds group_name.SetCString(buffer.get()); 116621fed052SAidan Dodds } 116721fed052SAidan Dodds 116821fed052SAidan Dodds // create or access existing script group 116921fed052SAidan Dodds RSScriptGroupDescriptorSP group; 117021fed052SAidan Dodds { 117121fed052SAidan Dodds // search for existing script group 117221fed052SAidan Dodds for (auto sg : m_scriptGroups) { 117321fed052SAidan Dodds if (sg->m_name == group_name) { 117421fed052SAidan Dodds group = sg; 117521fed052SAidan Dodds break; 117621fed052SAidan Dodds } 117721fed052SAidan Dodds } 117821fed052SAidan Dodds if (!group) { 1179796ac80bSJonas Devlieghere group = std::make_shared<RSScriptGroupDescriptor>(); 118021fed052SAidan Dodds group->m_name = group_name; 118121fed052SAidan Dodds m_scriptGroups.push_back(group); 118221fed052SAidan Dodds } else { 118321fed052SAidan Dodds // already have this script group 118463e5fb76SJonas Devlieghere LLDB_LOGF(log, "Attempt to add duplicate script group %s", 118521fed052SAidan Dodds group_name.AsCString()); 118621fed052SAidan Dodds return; 118721fed052SAidan Dodds } 118821fed052SAidan Dodds } 118921fed052SAidan Dodds assert(group); 119021fed052SAidan Dodds 119121fed052SAidan Dodds const uint32_t target_ptr_size = m_process->GetAddressByteSize(); 119221fed052SAidan Dodds std::vector<addr_t> kernels; 119321fed052SAidan Dodds // parse kernel addresses in script group 119421fed052SAidan Dodds for (uint64_t i = 0; i < uint64_t(args[eKernelCount]); ++i) { 119521fed052SAidan Dodds RSScriptGroupDescriptor::Kernel kernel; 119621fed052SAidan Dodds // extract script group kernel addresses from the target 119721fed052SAidan Dodds const addr_t ptr_addr = addr_t(args[eKernel]) + i * target_ptr_size; 119821fed052SAidan Dodds uint64_t kernel_addr = 0; 119997206d57SZachary Turner Status err; 120021fed052SAidan Dodds size_t read = 120121fed052SAidan Dodds m_process->ReadMemory(ptr_addr, &kernel_addr, target_ptr_size, err); 120221fed052SAidan Dodds if (!err.Success() || read != target_ptr_size) { 120363e5fb76SJonas Devlieghere LLDB_LOGF(log, "Error parsing kernel address %" PRIu64 " in script group", 120421fed052SAidan Dodds i); 120521fed052SAidan Dodds return; 120621fed052SAidan Dodds } 120763e5fb76SJonas Devlieghere LLDB_LOGF(log, "Extracted scriptgroup kernel address - 0x%" PRIx64, 120821fed052SAidan Dodds kernel_addr); 120921fed052SAidan Dodds kernel.m_addr = kernel_addr; 121021fed052SAidan Dodds 121121fed052SAidan Dodds // try to resolve the associated kernel name 121221fed052SAidan Dodds if (!ResolveKernelName(kernel.m_addr, kernel.m_name)) { 121363e5fb76SJonas Devlieghere LLDB_LOGF(log, "Parsed scriptgroup kernel %" PRIu64 " - 0x%" PRIx64, i, 121421fed052SAidan Dodds kernel_addr); 121521fed052SAidan Dodds return; 121621fed052SAidan Dodds } 121721fed052SAidan Dodds 121821fed052SAidan Dodds // try to find the non '.expand' function 121921fed052SAidan Dodds { 122021fed052SAidan Dodds const llvm::StringRef expand(".expand"); 122121fed052SAidan Dodds const llvm::StringRef name_ref = kernel.m_name.GetStringRef(); 122221fed052SAidan Dodds if (name_ref.endswith(expand)) { 122321fed052SAidan Dodds const ConstString base_kernel(name_ref.drop_back(expand.size())); 122421fed052SAidan Dodds // verify this function is a valid kernel 122521fed052SAidan Dodds if (IsKnownKernel(base_kernel)) { 122621fed052SAidan Dodds kernel.m_name = base_kernel; 122763e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - found non expand version '%s'", __FUNCTION__, 122821fed052SAidan Dodds base_kernel.GetCString()); 122921fed052SAidan Dodds } 123021fed052SAidan Dodds } 123121fed052SAidan Dodds } 123221fed052SAidan Dodds // add to a list of script group kernels we know about 123321fed052SAidan Dodds group->m_kernels.push_back(kernel); 123421fed052SAidan Dodds } 123521fed052SAidan Dodds 123621fed052SAidan Dodds // Resolve any pending scriptgroup breakpoints 123721fed052SAidan Dodds { 123821fed052SAidan Dodds Target &target = m_process->GetTarget(); 123921fed052SAidan Dodds const BreakpointList &list = target.GetBreakpointList(); 124021fed052SAidan Dodds const size_t num_breakpoints = list.GetSize(); 124163e5fb76SJonas Devlieghere LLDB_LOGF(log, "Resolving %zu breakpoints", num_breakpoints); 124221fed052SAidan Dodds for (size_t i = 0; i < num_breakpoints; ++i) { 124321fed052SAidan Dodds const BreakpointSP bp = list.GetBreakpointAtIndex(i); 124421fed052SAidan Dodds if (bp) { 124521fed052SAidan Dodds if (bp->MatchesName(group_name.AsCString())) { 124663e5fb76SJonas Devlieghere LLDB_LOGF(log, "Found breakpoint with name %s", 124721fed052SAidan Dodds group_name.AsCString()); 124821fed052SAidan Dodds bp->ResolveBreakpoint(); 124921fed052SAidan Dodds } 125021fed052SAidan Dodds } 125121fed052SAidan Dodds } 125221fed052SAidan Dodds } 125321fed052SAidan Dodds } 125421fed052SAidan Dodds 1255b9c1b51eSKate Stone void RenderScriptRuntime::CaptureScriptInvokeForEachMulti( 125680af0b9eSLuke Drummond RuntimeHook *hook, ExecutionContext &exe_ctx) { 1257*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 1258e09c44b6SAidan Dodds 1259b9c1b51eSKate Stone enum { 1260f4786785SAidan Dodds eRsContext = 0, 1261f4786785SAidan Dodds eRsScript, 1262f4786785SAidan Dodds eRsSlot, 1263f4786785SAidan Dodds eRsAIns, 1264f4786785SAidan Dodds eRsInLen, 1265f4786785SAidan Dodds eRsAOut, 1266f4786785SAidan Dodds eRsUsr, 1267f4786785SAidan Dodds eRsUsrLen, 1268f4786785SAidan Dodds eRsSc, 1269f4786785SAidan Dodds }; 1270e09c44b6SAidan Dodds 12711ee07253SSaleem Abdulrasool std::array<ArgItem, 9> args{{ 1272f4786785SAidan Dodds ArgItem{ArgItem::ePointer, 0}, // const Context *rsc 1273f4786785SAidan Dodds ArgItem{ArgItem::ePointer, 0}, // Script *s 1274f4786785SAidan Dodds ArgItem{ArgItem::eInt32, 0}, // uint32_t slot 1275f4786785SAidan Dodds ArgItem{ArgItem::ePointer, 0}, // const Allocation **aIns 1276f4786785SAidan Dodds ArgItem{ArgItem::eInt32, 0}, // size_t inLen 1277f4786785SAidan Dodds ArgItem{ArgItem::ePointer, 0}, // Allocation *aout 1278f4786785SAidan Dodds ArgItem{ArgItem::ePointer, 0}, // const void *usr 1279f4786785SAidan Dodds ArgItem{ArgItem::eInt32, 0}, // size_t usrLen 1280f4786785SAidan Dodds ArgItem{ArgItem::ePointer, 0}, // const RsScriptCall *sc 12811ee07253SSaleem Abdulrasool }}; 1282e09c44b6SAidan Dodds 128380af0b9eSLuke Drummond bool success = GetArgs(exe_ctx, &args[0], args.size()); 1284b9c1b51eSKate Stone if (!success) { 128563e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - Error while reading the function parameters", 1286b9c1b51eSKate Stone __FUNCTION__); 1287e09c44b6SAidan Dodds return; 1288e09c44b6SAidan Dodds } 1289e09c44b6SAidan Dodds 1290e09c44b6SAidan Dodds const uint32_t target_ptr_size = m_process->GetAddressByteSize(); 129197206d57SZachary Turner Status err; 1292e09c44b6SAidan Dodds std::vector<uint64_t> allocs; 1293e09c44b6SAidan Dodds 1294e09c44b6SAidan Dodds // traverse allocation list 1295b9c1b51eSKate Stone for (uint64_t i = 0; i < uint64_t(args[eRsInLen]); ++i) { 1296e09c44b6SAidan Dodds // calculate offest to allocation pointer 1297f4786785SAidan Dodds const addr_t addr = addr_t(args[eRsAIns]) + i * target_ptr_size; 1298e09c44b6SAidan Dodds 129980af0b9eSLuke Drummond // Note: due to little endian layout, reading 32bits or 64bits into res 130080af0b9eSLuke Drummond // will give the correct results. 130180af0b9eSLuke Drummond uint64_t result = 0; 130280af0b9eSLuke Drummond size_t read = m_process->ReadMemory(addr, &result, target_ptr_size, err); 130380af0b9eSLuke Drummond if (read != target_ptr_size || !err.Success()) { 130463e5fb76SJonas Devlieghere LLDB_LOGF(log, 1305b9c1b51eSKate Stone "%s - Error while reading allocation list argument %" PRIu64, 1306b9c1b51eSKate Stone __FUNCTION__, i); 1307b9c1b51eSKate Stone } else { 130880af0b9eSLuke Drummond allocs.push_back(result); 1309e09c44b6SAidan Dodds } 1310e09c44b6SAidan Dodds } 1311e09c44b6SAidan Dodds 1312e09c44b6SAidan Dodds // if there is an output allocation track it 131380af0b9eSLuke Drummond if (uint64_t alloc_out = uint64_t(args[eRsAOut])) { 131480af0b9eSLuke Drummond allocs.push_back(alloc_out); 1315e09c44b6SAidan Dodds } 1316e09c44b6SAidan Dodds 1317e09c44b6SAidan Dodds // for all allocations we have found 1318b9c1b51eSKate Stone for (const uint64_t alloc_addr : allocs) { 13195d057637SLuke Drummond AllocationDetails *alloc = LookUpAllocation(alloc_addr); 13205d057637SLuke Drummond if (!alloc) 13215d057637SLuke Drummond alloc = CreateAllocation(alloc_addr); 13225d057637SLuke Drummond 1323b9c1b51eSKate Stone if (alloc) { 1324e09c44b6SAidan Dodds // save the allocation address 1325b9c1b51eSKate Stone if (alloc->address.isValid()) { 1326e09c44b6SAidan Dodds // check the allocation address we already have matches 1327e09c44b6SAidan Dodds assert(*alloc->address.get() == alloc_addr); 1328b9c1b51eSKate Stone } else { 1329e09c44b6SAidan Dodds alloc->address = alloc_addr; 1330e09c44b6SAidan Dodds } 1331e09c44b6SAidan Dodds 1332e09c44b6SAidan Dodds // save the context 1333b9c1b51eSKate Stone if (log) { 1334b9c1b51eSKate Stone if (alloc->context.isValid() && 1335b9c1b51eSKate Stone *alloc->context.get() != addr_t(args[eRsContext])) 133663e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - Allocation used by multiple contexts", 1337b9c1b51eSKate Stone __FUNCTION__); 1338e09c44b6SAidan Dodds } 1339f4786785SAidan Dodds alloc->context = addr_t(args[eRsContext]); 1340e09c44b6SAidan Dodds } 1341e09c44b6SAidan Dodds } 1342e09c44b6SAidan Dodds 1343e09c44b6SAidan Dodds // make sure we track this script object 1344b9c1b51eSKate Stone if (lldb_private::RenderScriptRuntime::ScriptDetails *script = 1345b9c1b51eSKate Stone LookUpScript(addr_t(args[eRsScript]), true)) { 1346b9c1b51eSKate Stone if (log) { 1347b9c1b51eSKate Stone if (script->context.isValid() && 1348b9c1b51eSKate Stone *script->context.get() != addr_t(args[eRsContext])) 134963e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - Script used by multiple contexts", __FUNCTION__); 1350e09c44b6SAidan Dodds } 1351f4786785SAidan Dodds script->context = addr_t(args[eRsContext]); 1352e09c44b6SAidan Dodds } 1353e09c44b6SAidan Dodds } 1354e09c44b6SAidan Dodds 135580af0b9eSLuke Drummond void RenderScriptRuntime::CaptureSetGlobalVar(RuntimeHook *hook, 1356b9c1b51eSKate Stone ExecutionContext &context) { 1357*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 13584640cde1SColin Riley 1359b9c1b51eSKate Stone enum { 1360f4786785SAidan Dodds eRsContext, 1361f4786785SAidan Dodds eRsScript, 1362f4786785SAidan Dodds eRsId, 1363f4786785SAidan Dodds eRsData, 1364f4786785SAidan Dodds eRsLength, 1365f4786785SAidan Dodds }; 13664640cde1SColin Riley 13671ee07253SSaleem Abdulrasool std::array<ArgItem, 5> args{{ 1368f4786785SAidan Dodds ArgItem{ArgItem::ePointer, 0}, // eRsContext 1369f4786785SAidan Dodds ArgItem{ArgItem::ePointer, 0}, // eRsScript 1370f4786785SAidan Dodds ArgItem{ArgItem::eInt32, 0}, // eRsId 1371f4786785SAidan Dodds ArgItem{ArgItem::ePointer, 0}, // eRsData 1372f4786785SAidan Dodds ArgItem{ArgItem::eInt32, 0}, // eRsLength 13731ee07253SSaleem Abdulrasool }}; 13744640cde1SColin Riley 1375f4786785SAidan Dodds bool success = GetArgs(context, &args[0], args.size()); 1376b9c1b51eSKate Stone if (!success) { 137763e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - error reading the function parameters.", __FUNCTION__); 137882780287SAidan Dodds return; 137982780287SAidan Dodds } 13804640cde1SColin Riley 1381b9c1b51eSKate Stone if (log) { 138263e5fb76SJonas Devlieghere LLDB_LOGF(log, 138363e5fb76SJonas Devlieghere "%s - 0x%" PRIx64 ",0x%" PRIx64 " slot %" PRIu64 " = 0x%" PRIx64 1384b9c1b51eSKate Stone ":%" PRIu64 "bytes.", 1385b9c1b51eSKate Stone __FUNCTION__, uint64_t(args[eRsContext]), 1386b9c1b51eSKate Stone uint64_t(args[eRsScript]), uint64_t(args[eRsId]), 1387f4786785SAidan Dodds uint64_t(args[eRsData]), uint64_t(args[eRsLength])); 13884640cde1SColin Riley 1389f4786785SAidan Dodds addr_t script_addr = addr_t(args[eRsScript]); 1390b9c1b51eSKate Stone if (m_scriptMappings.find(script_addr) != m_scriptMappings.end()) { 13914640cde1SColin Riley auto rsm = m_scriptMappings[script_addr]; 1392b9c1b51eSKate Stone if (uint64_t(args[eRsId]) < rsm->m_globals.size()) { 1393f4786785SAidan Dodds auto rsg = rsm->m_globals[uint64_t(args[eRsId])]; 139463e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - Setting of '%s' within '%s' inferred", 139563e5fb76SJonas Devlieghere __FUNCTION__, rsg.m_name.AsCString(), 1396f4786785SAidan Dodds rsm->m_module->GetFileSpec().GetFilename().AsCString()); 13974640cde1SColin Riley } 13984640cde1SColin Riley } 13994640cde1SColin Riley } 14004640cde1SColin Riley } 14014640cde1SColin Riley 140280af0b9eSLuke Drummond void RenderScriptRuntime::CaptureAllocationInit(RuntimeHook *hook, 140380af0b9eSLuke Drummond ExecutionContext &exe_ctx) { 1404*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 14054640cde1SColin Riley 1406b9c1b51eSKate Stone enum { eRsContext, eRsAlloc, eRsForceZero }; 14074640cde1SColin Riley 14081ee07253SSaleem Abdulrasool std::array<ArgItem, 3> args{{ 1409f4786785SAidan Dodds ArgItem{ArgItem::ePointer, 0}, // eRsContext 1410f4786785SAidan Dodds ArgItem{ArgItem::ePointer, 0}, // eRsAlloc 1411f4786785SAidan Dodds ArgItem{ArgItem::eBool, 0}, // eRsForceZero 14121ee07253SSaleem Abdulrasool }}; 14134640cde1SColin Riley 141480af0b9eSLuke Drummond bool success = GetArgs(exe_ctx, &args[0], args.size()); 141580af0b9eSLuke Drummond if (!success) { 141663e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - error while reading the function parameters", 1417b9c1b51eSKate Stone __FUNCTION__); 141880af0b9eSLuke Drummond return; 141982780287SAidan Dodds } 14204640cde1SColin Riley 142163e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - 0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 " .", 142263e5fb76SJonas Devlieghere __FUNCTION__, uint64_t(args[eRsContext]), uint64_t(args[eRsAlloc]), 142363e5fb76SJonas Devlieghere uint64_t(args[eRsForceZero])); 142478f339d1SEwan Crawford 14255d057637SLuke Drummond AllocationDetails *alloc = CreateAllocation(uint64_t(args[eRsAlloc])); 142678f339d1SEwan Crawford if (alloc) 1427f4786785SAidan Dodds alloc->context = uint64_t(args[eRsContext]); 14284640cde1SColin Riley } 14294640cde1SColin Riley 143080af0b9eSLuke Drummond void RenderScriptRuntime::CaptureAllocationDestroy(RuntimeHook *hook, 143180af0b9eSLuke Drummond ExecutionContext &exe_ctx) { 1432*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 1433e69df382SEwan Crawford 1434b9c1b51eSKate Stone enum { 1435f4786785SAidan Dodds eRsContext, 1436f4786785SAidan Dodds eRsAlloc, 1437f4786785SAidan Dodds }; 1438e69df382SEwan Crawford 14391ee07253SSaleem Abdulrasool std::array<ArgItem, 2> args{{ 1440f4786785SAidan Dodds ArgItem{ArgItem::ePointer, 0}, // eRsContext 1441f4786785SAidan Dodds ArgItem{ArgItem::ePointer, 0}, // eRsAlloc 14421ee07253SSaleem Abdulrasool }}; 1443f4786785SAidan Dodds 144480af0b9eSLuke Drummond bool success = GetArgs(exe_ctx, &args[0], args.size()); 1445b9c1b51eSKate Stone if (!success) { 144663e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - error while reading the function parameters.", 1447b9c1b51eSKate Stone __FUNCTION__); 1448b3f7f69dSAidan Dodds return; 1449e69df382SEwan Crawford } 1450e69df382SEwan Crawford 145163e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - 0x%" PRIx64 ", 0x%" PRIx64 ".", __FUNCTION__, 1452b9c1b51eSKate Stone uint64_t(args[eRsContext]), uint64_t(args[eRsAlloc])); 1453e69df382SEwan Crawford 1454b9c1b51eSKate Stone for (auto iter = m_allocations.begin(); iter != m_allocations.end(); ++iter) { 1455d5b44036SJonas Devlieghere auto &allocation_up = *iter; // get the unique pointer 1456d5b44036SJonas Devlieghere if (allocation_up->address.isValid() && 1457d5b44036SJonas Devlieghere *allocation_up->address.get() == addr_t(args[eRsAlloc])) { 1458e69df382SEwan Crawford m_allocations.erase(iter); 145963e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - deleted allocation entry.", __FUNCTION__); 1460e69df382SEwan Crawford return; 1461e69df382SEwan Crawford } 1462e69df382SEwan Crawford } 1463e69df382SEwan Crawford 146463e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - couldn't find destroyed allocation.", __FUNCTION__); 1465e69df382SEwan Crawford } 1466e69df382SEwan Crawford 146780af0b9eSLuke Drummond void RenderScriptRuntime::CaptureScriptInit(RuntimeHook *hook, 146880af0b9eSLuke Drummond ExecutionContext &exe_ctx) { 1469*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 14704640cde1SColin Riley 147197206d57SZachary Turner Status err; 147280af0b9eSLuke Drummond Process *process = exe_ctx.GetProcessPtr(); 14734640cde1SColin Riley 1474b9c1b51eSKate Stone enum { eRsContext, eRsScript, eRsResNamePtr, eRsCachedDirPtr }; 14754640cde1SColin Riley 1476b9c1b51eSKate Stone std::array<ArgItem, 4> args{ 1477b9c1b51eSKate Stone {ArgItem{ArgItem::ePointer, 0}, ArgItem{ArgItem::ePointer, 0}, 14781ee07253SSaleem Abdulrasool ArgItem{ArgItem::ePointer, 0}, ArgItem{ArgItem::ePointer, 0}}}; 147980af0b9eSLuke Drummond bool success = GetArgs(exe_ctx, &args[0], args.size()); 1480b9c1b51eSKate Stone if (!success) { 148163e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - error while reading the function parameters.", 1482b9c1b51eSKate Stone __FUNCTION__); 148382780287SAidan Dodds return; 148482780287SAidan Dodds } 148582780287SAidan Dodds 148680af0b9eSLuke Drummond std::string res_name; 148780af0b9eSLuke Drummond process->ReadCStringFromMemory(addr_t(args[eRsResNamePtr]), res_name, err); 148880af0b9eSLuke Drummond if (err.Fail()) { 148963e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - error reading res_name: %s.", __FUNCTION__, 149080af0b9eSLuke Drummond err.AsCString()); 14914640cde1SColin Riley } 14924640cde1SColin Riley 149380af0b9eSLuke Drummond std::string cache_dir; 149480af0b9eSLuke Drummond process->ReadCStringFromMemory(addr_t(args[eRsCachedDirPtr]), cache_dir, err); 149580af0b9eSLuke Drummond if (err.Fail()) { 149663e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - error reading cache_dir: %s.", __FUNCTION__, 149780af0b9eSLuke Drummond err.AsCString()); 14984640cde1SColin Riley } 14994640cde1SColin Riley 150063e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - 0x%" PRIx64 ",0x%" PRIx64 " => '%s' at '%s' .", 150163e5fb76SJonas Devlieghere __FUNCTION__, uint64_t(args[eRsContext]), uint64_t(args[eRsScript]), 150263e5fb76SJonas Devlieghere res_name.c_str(), cache_dir.c_str()); 15034640cde1SColin Riley 150480af0b9eSLuke Drummond if (res_name.size() > 0) { 15054640cde1SColin Riley StreamString strm; 150680af0b9eSLuke Drummond strm.Printf("librs.%s.so", res_name.c_str()); 15074640cde1SColin Riley 1508f4786785SAidan Dodds ScriptDetails *script = LookUpScript(addr_t(args[eRsScript]), true); 1509b9c1b51eSKate Stone if (script) { 151078f339d1SEwan Crawford script->type = ScriptDetails::eScriptC; 151180af0b9eSLuke Drummond script->cache_dir = cache_dir; 151280af0b9eSLuke Drummond script->res_name = res_name; 1513adcd0268SBenjamin Kramer script->shared_lib = std::string(strm.GetString()); 1514f4786785SAidan Dodds script->context = addr_t(args[eRsContext]); 151578f339d1SEwan Crawford } 15164640cde1SColin Riley 151763e5fb76SJonas Devlieghere LLDB_LOGF(log, 151863e5fb76SJonas Devlieghere "%s - '%s' tagged with context 0x%" PRIx64 1519b9c1b51eSKate Stone " and script 0x%" PRIx64 ".", 1520b9c1b51eSKate Stone __FUNCTION__, strm.GetData(), uint64_t(args[eRsContext]), 1521b9c1b51eSKate Stone uint64_t(args[eRsScript])); 1522b9c1b51eSKate Stone } else if (log) { 152363e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - resource name invalid, Script not tagged.", 152463e5fb76SJonas Devlieghere __FUNCTION__); 15254640cde1SColin Riley } 15264640cde1SColin Riley } 15274640cde1SColin Riley 1528b9c1b51eSKate Stone void RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module, 1529b9c1b51eSKate Stone ModuleKind kind) { 1530*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 15314640cde1SColin Riley 1532b9c1b51eSKate Stone if (!module) { 15334640cde1SColin Riley return; 15344640cde1SColin Riley } 15354640cde1SColin Riley 153682780287SAidan Dodds Target &target = GetProcess()->GetTarget(); 153721fed052SAidan Dodds const llvm::Triple::ArchType machine = target.GetArchitecture().GetMachine(); 153882780287SAidan Dodds 153980af0b9eSLuke Drummond if (machine != llvm::Triple::ArchType::x86 && 154080af0b9eSLuke Drummond machine != llvm::Triple::ArchType::arm && 154180af0b9eSLuke Drummond machine != llvm::Triple::ArchType::aarch64 && 154280af0b9eSLuke Drummond machine != llvm::Triple::ArchType::mipsel && 154380af0b9eSLuke Drummond machine != llvm::Triple::ArchType::mips64el && 154480af0b9eSLuke Drummond machine != llvm::Triple::ArchType::x86_64) { 154563e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - unable to hook runtime functions.", __FUNCTION__); 15464640cde1SColin Riley return; 15474640cde1SColin Riley } 15484640cde1SColin Riley 154921fed052SAidan Dodds const uint32_t target_ptr_size = 155021fed052SAidan Dodds target.GetArchitecture().GetAddressByteSize(); 155121fed052SAidan Dodds 155221fed052SAidan Dodds std::array<bool, s_runtimeHookCount> hook_placed; 155321fed052SAidan Dodds hook_placed.fill(false); 15544640cde1SColin Riley 1555b9c1b51eSKate Stone for (size_t idx = 0; idx < s_runtimeHookCount; idx++) { 15564640cde1SColin Riley const HookDefn *hook_defn = &s_runtimeHookDefns[idx]; 1557b9c1b51eSKate Stone if (hook_defn->kind != kind) { 15584640cde1SColin Riley continue; 15594640cde1SColin Riley } 15604640cde1SColin Riley 156180af0b9eSLuke Drummond const char *symbol_name = (target_ptr_size == 4) 156280af0b9eSLuke Drummond ? hook_defn->symbol_name_m32 1563b9c1b51eSKate Stone : hook_defn->symbol_name_m64; 156482780287SAidan Dodds 1565b9c1b51eSKate Stone const Symbol *sym = module->FindFirstSymbolWithNameAndType( 1566b9c1b51eSKate Stone ConstString(symbol_name), eSymbolTypeCode); 1567b9c1b51eSKate Stone if (!sym) { 1568b9c1b51eSKate Stone if (log) { 156963e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - symbol '%s' related to the function %s not found", 1570b3f7f69dSAidan Dodds __FUNCTION__, symbol_name, hook_defn->name); 157182780287SAidan Dodds } 157282780287SAidan Dodds continue; 157382780287SAidan Dodds } 15744640cde1SColin Riley 1575358cf1eaSGreg Clayton addr_t addr = sym->GetLoadAddress(&target); 1576b9c1b51eSKate Stone if (addr == LLDB_INVALID_ADDRESS) { 157763e5fb76SJonas Devlieghere LLDB_LOGF(log, 157863e5fb76SJonas Devlieghere "%s - unable to resolve the address of hook function '%s' " 1579b9c1b51eSKate Stone "with symbol '%s'.", 1580b3f7f69dSAidan Dodds __FUNCTION__, hook_defn->name, symbol_name); 15814640cde1SColin Riley continue; 1582b9c1b51eSKate Stone } else { 158363e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - function %s, address resolved at 0x%" PRIx64, 1584b3f7f69dSAidan Dodds __FUNCTION__, hook_defn->name, addr); 158582780287SAidan Dodds } 15864640cde1SColin Riley 15874640cde1SColin Riley RuntimeHookSP hook(new RuntimeHook()); 15884640cde1SColin Riley hook->address = addr; 15894640cde1SColin Riley hook->defn = hook_defn; 15904640cde1SColin Riley hook->bp_sp = target.CreateBreakpoint(addr, true, false); 15914640cde1SColin Riley hook->bp_sp->SetCallback(HookCallback, hook.get(), true); 15924640cde1SColin Riley m_runtimeHooks[addr] = hook; 1593b9c1b51eSKate Stone if (log) { 159463e5fb76SJonas Devlieghere LLDB_LOGF(log, 159563e5fb76SJonas Devlieghere "%s - successfully hooked '%s' in '%s' version %" PRIu64 1596b9c1b51eSKate Stone " at 0x%" PRIx64 ".", 1597b9c1b51eSKate Stone __FUNCTION__, hook_defn->name, 1598b9c1b51eSKate Stone module->GetFileSpec().GetFilename().AsCString(), 1599b3f7f69dSAidan Dodds (uint64_t)hook_defn->version, (uint64_t)addr); 16004640cde1SColin Riley } 160121fed052SAidan Dodds hook_placed[idx] = true; 160221fed052SAidan Dodds } 160321fed052SAidan Dodds 160421fed052SAidan Dodds // log any unhooked function 160521fed052SAidan Dodds if (log) { 160621fed052SAidan Dodds for (size_t i = 0; i < hook_placed.size(); ++i) { 160721fed052SAidan Dodds if (hook_placed[i]) 160821fed052SAidan Dodds continue; 160921fed052SAidan Dodds const HookDefn &hook_defn = s_runtimeHookDefns[i]; 161021fed052SAidan Dodds if (hook_defn.kind != kind) 161121fed052SAidan Dodds continue; 161263e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - function %s was not hooked", __FUNCTION__, 161321fed052SAidan Dodds hook_defn.name); 161421fed052SAidan Dodds } 16154640cde1SColin Riley } 16164640cde1SColin Riley } 16174640cde1SColin Riley 1618b9c1b51eSKate Stone void RenderScriptRuntime::FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp) { 16194640cde1SColin Riley if (!rsmodule_sp) 16204640cde1SColin Riley return; 16214640cde1SColin Riley 1622*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 16234640cde1SColin Riley 16244640cde1SColin Riley const ModuleSP module = rsmodule_sp->m_module; 16254640cde1SColin Riley const FileSpec &file = module->GetPlatformFileSpec(); 16264640cde1SColin Riley 162705097246SAdrian Prantl // Iterate over all of the scripts that we currently know of. Note: We cant 162805097246SAdrian Prantl // push or pop to m_scripts here or it may invalidate rs_script. 1629b9c1b51eSKate Stone for (const auto &rs_script : m_scripts) { 163078f339d1SEwan Crawford // Extract the expected .so file path for this script. 163180af0b9eSLuke Drummond std::string shared_lib; 163280af0b9eSLuke Drummond if (!rs_script->shared_lib.get(shared_lib)) 163378f339d1SEwan Crawford continue; 163478f339d1SEwan Crawford 163578f339d1SEwan Crawford // Only proceed if the module that has loaded corresponds to this script. 163680af0b9eSLuke Drummond if (file.GetFilename() != ConstString(shared_lib.c_str())) 163778f339d1SEwan Crawford continue; 163878f339d1SEwan Crawford 163978f339d1SEwan Crawford // Obtain the script address which we use as a key. 164078f339d1SEwan Crawford lldb::addr_t script; 164178f339d1SEwan Crawford if (!rs_script->script.get(script)) 164278f339d1SEwan Crawford continue; 164378f339d1SEwan Crawford 164478f339d1SEwan Crawford // If we have a script mapping for the current script. 1645b9c1b51eSKate Stone if (m_scriptMappings.find(script) != m_scriptMappings.end()) { 164678f339d1SEwan Crawford // if the module we have stored is different to the one we just received. 1647b9c1b51eSKate Stone if (m_scriptMappings[script] != rsmodule_sp) { 164863e5fb76SJonas Devlieghere LLDB_LOGF( 164963e5fb76SJonas Devlieghere log, 1650b9c1b51eSKate Stone "%s - script %" PRIx64 " wants reassigned to new rsmodule '%s'.", 1651b9c1b51eSKate Stone __FUNCTION__, (uint64_t)script, 1652b9c1b51eSKate Stone rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString()); 16534640cde1SColin Riley } 16544640cde1SColin Riley } 165578f339d1SEwan Crawford // We don't have a script mapping for the current script. 1656b9c1b51eSKate Stone else { 165778f339d1SEwan Crawford // Obtain the script resource name. 165880af0b9eSLuke Drummond std::string res_name; 165980af0b9eSLuke Drummond if (rs_script->res_name.get(res_name)) 166078f339d1SEwan Crawford // Set the modules resource name. 166180af0b9eSLuke Drummond rsmodule_sp->m_resname = res_name; 166278f339d1SEwan Crawford // Add Script/Module pair to map. 166378f339d1SEwan Crawford m_scriptMappings[script] = rsmodule_sp; 166463e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - script %" PRIx64 " associated with rsmodule '%s'.", 1665b9c1b51eSKate Stone __FUNCTION__, (uint64_t)script, 1666b9c1b51eSKate Stone rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString()); 16674640cde1SColin Riley } 16684640cde1SColin Riley } 16694640cde1SColin Riley } 16704640cde1SColin Riley 1671b9c1b51eSKate Stone // Uses the Target API to evaluate the expression passed as a parameter to the 167280af0b9eSLuke Drummond // function The result of that expression is returned an unsigned 64 bit int, 167380af0b9eSLuke Drummond // via the result* parameter. Function returns true on success, and false on 167480af0b9eSLuke Drummond // failure 167580af0b9eSLuke Drummond bool RenderScriptRuntime::EvalRSExpression(const char *expr, 1676b9c1b51eSKate Stone StackFrame *frame_ptr, 1677b9c1b51eSKate Stone uint64_t *result) { 1678*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 167963e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s(%s)", __FUNCTION__, expr); 168015f2bd95SEwan Crawford 168115f2bd95SEwan Crawford ValueObjectSP expr_result; 16828433fdbeSAidan Dodds EvaluateExpressionOptions options; 16838433fdbeSAidan Dodds options.SetLanguage(lldb::eLanguageTypeC_plus_plus); 168415f2bd95SEwan Crawford // Perform the actual expression evaluation 168580af0b9eSLuke Drummond auto &target = GetProcess()->GetTarget(); 168680af0b9eSLuke Drummond target.EvaluateExpression(expr, frame_ptr, expr_result, options); 168715f2bd95SEwan Crawford 1688b9c1b51eSKate Stone if (!expr_result) { 168963e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s: couldn't evaluate expression.", __FUNCTION__); 169015f2bd95SEwan Crawford return false; 169115f2bd95SEwan Crawford } 169215f2bd95SEwan Crawford 169315f2bd95SEwan Crawford // The result of the expression is invalid 1694b9c1b51eSKate Stone if (!expr_result->GetError().Success()) { 169597206d57SZachary Turner Status err = expr_result->GetError(); 169680af0b9eSLuke Drummond // Expression returned is void, so this is actually a success 1697a35912daSKrasimir Georgiev if (err.GetError() == UserExpression::kNoResult) { 169863e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - expression returned void.", __FUNCTION__); 169915f2bd95SEwan Crawford 170015f2bd95SEwan Crawford result = nullptr; 170115f2bd95SEwan Crawford return true; 170215f2bd95SEwan Crawford } 170315f2bd95SEwan Crawford 170463e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - error evaluating expression result: %s", __FUNCTION__, 1705b3f7f69dSAidan Dodds err.AsCString()); 170615f2bd95SEwan Crawford return false; 170715f2bd95SEwan Crawford } 170815f2bd95SEwan Crawford 170915f2bd95SEwan Crawford bool success = false; 171080af0b9eSLuke Drummond // We only read the result as an uint32_t. 171180af0b9eSLuke Drummond *result = expr_result->GetValueAsUnsigned(0, &success); 171215f2bd95SEwan Crawford 1713b9c1b51eSKate Stone if (!success) { 171463e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - couldn't convert expression result to uint32_t", 1715b9c1b51eSKate Stone __FUNCTION__); 171615f2bd95SEwan Crawford return false; 171715f2bd95SEwan Crawford } 171815f2bd95SEwan Crawford 171915f2bd95SEwan Crawford return true; 172015f2bd95SEwan Crawford } 172115f2bd95SEwan Crawford 1722b9c1b51eSKate Stone namespace { 1723836d9651SEwan Crawford // Used to index expression format strings 1724b9c1b51eSKate Stone enum ExpressionStrings { 1725836d9651SEwan Crawford eExprGetOffsetPtr = 0, 1726836d9651SEwan Crawford eExprAllocGetType, 1727836d9651SEwan Crawford eExprTypeDimX, 1728836d9651SEwan Crawford eExprTypeDimY, 1729836d9651SEwan Crawford eExprTypeDimZ, 1730836d9651SEwan Crawford eExprTypeElemPtr, 1731836d9651SEwan Crawford eExprElementType, 1732836d9651SEwan Crawford eExprElementKind, 1733836d9651SEwan Crawford eExprElementVec, 1734836d9651SEwan Crawford eExprElementFieldCount, 1735836d9651SEwan Crawford eExprSubelementsId, 1736836d9651SEwan Crawford eExprSubelementsName, 1737ea0636b5SEwan Crawford eExprSubelementsArrSize, 1738ea0636b5SEwan Crawford 173980af0b9eSLuke Drummond _eExprLast // keep at the end, implicit size of the array runtime_expressions 1740836d9651SEwan Crawford }; 174115f2bd95SEwan Crawford 1742ea0636b5SEwan Crawford // max length of an expanded expression 1743ea0636b5SEwan Crawford const int jit_max_expr_size = 512; 1744ea0636b5SEwan Crawford 1745ea0636b5SEwan Crawford // Retrieve the string to JIT for the given expression 174636d783ebSDavid Gross #define JIT_TEMPLATE_CONTEXT "void* ctxt = (void*)rsDebugGetContextWrapper(0x%" PRIx64 "); " 1747b9c1b51eSKate Stone const char *JITTemplate(ExpressionStrings e) { 1748ea0636b5SEwan Crawford // Format strings containing the expressions we may need to evaluate. 174980af0b9eSLuke Drummond static std::array<const char *, _eExprLast> runtime_expressions = { 1750b9c1b51eSKate Stone {// Mangled GetOffsetPointer(Allocation*, xoff, yoff, zoff, lod, cubemap) 1751b9c1b51eSKate Stone "(int*)_" 1752b9c1b51eSKate Stone "Z12GetOffsetPtrPKN7android12renderscript10AllocationEjjjj23RsAllocation" 1753b9c1b51eSKate Stone "CubemapFace" 175436d783ebSDavid Gross "(0x%" PRIx64 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", 0, 0)", // eExprGetOffsetPtr 175515f2bd95SEwan Crawford 175615f2bd95SEwan Crawford // Type* rsaAllocationGetType(Context*, Allocation*) 175736d783ebSDavid Gross JIT_TEMPLATE_CONTEXT "(void*)rsaAllocationGetType(ctxt, 0x%" PRIx64 ")", // eExprAllocGetType 175815f2bd95SEwan Crawford 175980af0b9eSLuke Drummond // rsaTypeGetNativeData(Context*, Type*, void* typeData, size) Pack the 176080af0b9eSLuke Drummond // data in the following way mHal.state.dimX; mHal.state.dimY; 176105097246SAdrian Prantl // mHal.state.dimZ; mHal.state.lodCount; mHal.state.faces; mElement; 176205097246SAdrian Prantl // into typeData Need to specify 32 or 64 bit for uint_t since this 176305097246SAdrian Prantl // differs between devices 176436d783ebSDavid Gross JIT_TEMPLATE_CONTEXT 176536d783ebSDavid Gross "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(ctxt" 176636d783ebSDavid Gross ", 0x%" PRIx64 ", data, 6); data[0]", // eExprTypeDimX 176736d783ebSDavid Gross JIT_TEMPLATE_CONTEXT 176836d783ebSDavid Gross "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(ctxt" 176936d783ebSDavid Gross ", 0x%" PRIx64 ", data, 6); data[1]", // eExprTypeDimY 177036d783ebSDavid Gross JIT_TEMPLATE_CONTEXT 177136d783ebSDavid Gross "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(ctxt" 177236d783ebSDavid Gross ", 0x%" PRIx64 ", data, 6); data[2]", // eExprTypeDimZ 177336d783ebSDavid Gross JIT_TEMPLATE_CONTEXT 177436d783ebSDavid Gross "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(ctxt" 177536d783ebSDavid Gross ", 0x%" PRIx64 ", data, 6); data[5]", // eExprTypeElemPtr 177615f2bd95SEwan Crawford 177715f2bd95SEwan Crawford // rsaElementGetNativeData(Context*, Element*, uint32_t* elemData,size) 1778b9c1b51eSKate Stone // Pack mType; mKind; mNormalized; mVectorSize; NumSubElements into 1779b9c1b51eSKate Stone // elemData 178036d783ebSDavid Gross JIT_TEMPLATE_CONTEXT 178136d783ebSDavid Gross "uint32_t data[5]; (void*)rsaElementGetNativeData(ctxt" 178236d783ebSDavid Gross ", 0x%" PRIx64 ", data, 5); data[0]", // eExprElementType 178336d783ebSDavid Gross JIT_TEMPLATE_CONTEXT 178436d783ebSDavid Gross "uint32_t data[5]; (void*)rsaElementGetNativeData(ctxt" 178536d783ebSDavid Gross ", 0x%" PRIx64 ", data, 5); data[1]", // eExprElementKind 178636d783ebSDavid Gross JIT_TEMPLATE_CONTEXT 178736d783ebSDavid Gross "uint32_t data[5]; (void*)rsaElementGetNativeData(ctxt" 178836d783ebSDavid Gross ", 0x%" PRIx64 ", data, 5); data[3]", // eExprElementVec 178936d783ebSDavid Gross JIT_TEMPLATE_CONTEXT 179036d783ebSDavid Gross "uint32_t data[5]; (void*)rsaElementGetNativeData(ctxt" 179136d783ebSDavid Gross ", 0x%" PRIx64 ", data, 5); data[4]", // eExprElementFieldCount 17928b244e21SEwan Crawford 1793b9c1b51eSKate Stone // rsaElementGetSubElements(RsContext con, RsElement elem, uintptr_t 179480af0b9eSLuke Drummond // *ids, const char **names, size_t *arraySizes, uint32_t dataSize) 1795b9c1b51eSKate Stone // Needed for Allocations of structs to gather details about 179680af0b9eSLuke Drummond // fields/Subelements Element* of field 179736d783ebSDavid Gross JIT_TEMPLATE_CONTEXT "void* ids[%" PRIu32 "]; const char* names[%" PRIu32 1798b9c1b51eSKate Stone "]; size_t arr_size[%" PRIu32 "];" 179936d783ebSDavid Gross "(void*)rsaElementGetSubElements(ctxt, 0x%" PRIx64 180036d783ebSDavid Gross ", ids, names, arr_size, %" PRIu32 "); ids[%" PRIu32 "]", // eExprSubelementsId 18018b244e21SEwan Crawford 1802577570b4SAidan Dodds // Name of field 180336d783ebSDavid Gross JIT_TEMPLATE_CONTEXT "void* ids[%" PRIu32 "]; const char* names[%" PRIu32 1804b9c1b51eSKate Stone "]; size_t arr_size[%" PRIu32 "];" 180536d783ebSDavid Gross "(void*)rsaElementGetSubElements(ctxt, 0x%" PRIx64 180636d783ebSDavid Gross ", ids, names, arr_size, %" PRIu32 "); names[%" PRIu32 "]", // eExprSubelementsName 18078b244e21SEwan Crawford 1808577570b4SAidan Dodds // Array size of field 180936d783ebSDavid Gross JIT_TEMPLATE_CONTEXT "void* ids[%" PRIu32 "]; const char* names[%" PRIu32 1810b9c1b51eSKate Stone "]; size_t arr_size[%" PRIu32 "];" 181136d783ebSDavid Gross "(void*)rsaElementGetSubElements(ctxt, 0x%" PRIx64 181236d783ebSDavid Gross ", ids, names, arr_size, %" PRIu32 "); arr_size[%" PRIu32 "]"}}; // eExprSubelementsArrSize 1813ea0636b5SEwan Crawford 181480af0b9eSLuke Drummond return runtime_expressions[e]; 1815ea0636b5SEwan Crawford } 1816ea0636b5SEwan Crawford } // end of the anonymous namespace 1817ea0636b5SEwan Crawford 181805097246SAdrian Prantl // JITs the RS runtime for the internal data pointer of an allocation. Is 181905097246SAdrian Prantl // passed x,y,z coordinates for the pointer to a specific element. Then sets 182005097246SAdrian Prantl // the data_ptr member in Allocation with the result. Returns true on success, 182105097246SAdrian Prantl // false otherwise 182280af0b9eSLuke Drummond bool RenderScriptRuntime::JITDataPointer(AllocationDetails *alloc, 1823b9c1b51eSKate Stone StackFrame *frame_ptr, uint32_t x, 1824b9c1b51eSKate Stone uint32_t y, uint32_t z) { 1825*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 182615f2bd95SEwan Crawford 182780af0b9eSLuke Drummond if (!alloc->address.isValid()) { 182863e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__); 182915f2bd95SEwan Crawford return false; 183015f2bd95SEwan Crawford } 183115f2bd95SEwan Crawford 183280af0b9eSLuke Drummond const char *fmt_str = JITTemplate(eExprGetOffsetPtr); 183380af0b9eSLuke Drummond char expr_buf[jit_max_expr_size]; 183415f2bd95SEwan Crawford 183580af0b9eSLuke Drummond int written = snprintf(expr_buf, jit_max_expr_size, fmt_str, 183680af0b9eSLuke Drummond *alloc->address.get(), x, y, z); 183780af0b9eSLuke Drummond if (written < 0) { 183863e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__); 183915f2bd95SEwan Crawford return false; 184080af0b9eSLuke Drummond } else if (written >= jit_max_expr_size) { 184163e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__); 184215f2bd95SEwan Crawford return false; 184315f2bd95SEwan Crawford } 184415f2bd95SEwan Crawford 184515f2bd95SEwan Crawford uint64_t result = 0; 184680af0b9eSLuke Drummond if (!EvalRSExpression(expr_buf, frame_ptr, &result)) 184715f2bd95SEwan Crawford return false; 184815f2bd95SEwan Crawford 184980af0b9eSLuke Drummond addr_t data_ptr = static_cast<lldb::addr_t>(result); 185080af0b9eSLuke Drummond alloc->data_ptr = data_ptr; 185115f2bd95SEwan Crawford 185215f2bd95SEwan Crawford return true; 185315f2bd95SEwan Crawford } 185415f2bd95SEwan Crawford 185515f2bd95SEwan Crawford // JITs the RS runtime for the internal pointer to the RS Type of an allocation 185680af0b9eSLuke Drummond // Then sets the type_ptr member in Allocation with the result. Returns true on 185780af0b9eSLuke Drummond // success, false otherwise 185880af0b9eSLuke Drummond bool RenderScriptRuntime::JITTypePointer(AllocationDetails *alloc, 1859b9c1b51eSKate Stone StackFrame *frame_ptr) { 1860*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 186115f2bd95SEwan Crawford 186280af0b9eSLuke Drummond if (!alloc->address.isValid() || !alloc->context.isValid()) { 186363e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__); 186415f2bd95SEwan Crawford return false; 186515f2bd95SEwan Crawford } 186615f2bd95SEwan Crawford 186780af0b9eSLuke Drummond const char *fmt_str = JITTemplate(eExprAllocGetType); 186880af0b9eSLuke Drummond char expr_buf[jit_max_expr_size]; 186915f2bd95SEwan Crawford 187080af0b9eSLuke Drummond int written = snprintf(expr_buf, jit_max_expr_size, fmt_str, 187180af0b9eSLuke Drummond *alloc->context.get(), *alloc->address.get()); 187280af0b9eSLuke Drummond if (written < 0) { 187363e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__); 187415f2bd95SEwan Crawford return false; 187580af0b9eSLuke Drummond } else if (written >= jit_max_expr_size) { 187663e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__); 187715f2bd95SEwan Crawford return false; 187815f2bd95SEwan Crawford } 187915f2bd95SEwan Crawford 188015f2bd95SEwan Crawford uint64_t result = 0; 188180af0b9eSLuke Drummond if (!EvalRSExpression(expr_buf, frame_ptr, &result)) 188215f2bd95SEwan Crawford return false; 188315f2bd95SEwan Crawford 188415f2bd95SEwan Crawford addr_t type_ptr = static_cast<lldb::addr_t>(result); 188580af0b9eSLuke Drummond alloc->type_ptr = type_ptr; 188615f2bd95SEwan Crawford 188715f2bd95SEwan Crawford return true; 188815f2bd95SEwan Crawford } 188915f2bd95SEwan Crawford 1890b9c1b51eSKate Stone // JITs the RS runtime for information about the dimensions and type of an 189105097246SAdrian Prantl // allocation Then sets dimension and element_ptr members in Allocation with 189205097246SAdrian Prantl // the result. Returns true on success, false otherwise 189380af0b9eSLuke Drummond bool RenderScriptRuntime::JITTypePacked(AllocationDetails *alloc, 1894b9c1b51eSKate Stone StackFrame *frame_ptr) { 1895*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 189615f2bd95SEwan Crawford 189780af0b9eSLuke Drummond if (!alloc->type_ptr.isValid() || !alloc->context.isValid()) { 189863e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - Failed to find allocation details.", __FUNCTION__); 189915f2bd95SEwan Crawford return false; 190015f2bd95SEwan Crawford } 190115f2bd95SEwan Crawford 190215f2bd95SEwan Crawford // Expression is different depending on if device is 32 or 64 bit 190380af0b9eSLuke Drummond uint32_t target_ptr_size = 1904b9c1b51eSKate Stone GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize(); 190580af0b9eSLuke Drummond const uint32_t bits = target_ptr_size == 4 ? 32 : 64; 190615f2bd95SEwan Crawford 190715f2bd95SEwan Crawford // We want 4 elements from packed data 1908b3f7f69dSAidan Dodds const uint32_t num_exprs = 4; 19094c1d6ee8SJonas Devlieghere static_assert(num_exprs == (eExprTypeElemPtr - eExprTypeDimX + 1), 1910b9c1b51eSKate Stone "Invalid number of expressions"); 191115f2bd95SEwan Crawford 191280af0b9eSLuke Drummond char expr_bufs[num_exprs][jit_max_expr_size]; 191315f2bd95SEwan Crawford uint64_t results[num_exprs]; 191415f2bd95SEwan Crawford 1915b9c1b51eSKate Stone for (uint32_t i = 0; i < num_exprs; ++i) { 191680af0b9eSLuke Drummond const char *fmt_str = JITTemplate(ExpressionStrings(eExprTypeDimX + i)); 191736d783ebSDavid Gross int written = snprintf(expr_bufs[i], jit_max_expr_size, fmt_str, 191836d783ebSDavid Gross *alloc->context.get(), bits, *alloc->type_ptr.get()); 191980af0b9eSLuke Drummond if (written < 0) { 192063e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__); 192115f2bd95SEwan Crawford return false; 192280af0b9eSLuke Drummond } else if (written >= jit_max_expr_size) { 192363e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__); 192415f2bd95SEwan Crawford return false; 192515f2bd95SEwan Crawford } 192615f2bd95SEwan Crawford 192715f2bd95SEwan Crawford // Perform expression evaluation 192880af0b9eSLuke Drummond if (!EvalRSExpression(expr_bufs[i], frame_ptr, &results[i])) 192915f2bd95SEwan Crawford return false; 193015f2bd95SEwan Crawford } 193115f2bd95SEwan Crawford 193215f2bd95SEwan Crawford // Assign results to allocation members 193315f2bd95SEwan Crawford AllocationDetails::Dimension dims; 193415f2bd95SEwan Crawford dims.dim_1 = static_cast<uint32_t>(results[0]); 193515f2bd95SEwan Crawford dims.dim_2 = static_cast<uint32_t>(results[1]); 193615f2bd95SEwan Crawford dims.dim_3 = static_cast<uint32_t>(results[2]); 193780af0b9eSLuke Drummond alloc->dimension = dims; 193815f2bd95SEwan Crawford 193980af0b9eSLuke Drummond addr_t element_ptr = static_cast<lldb::addr_t>(results[3]); 194080af0b9eSLuke Drummond alloc->element.element_ptr = element_ptr; 194115f2bd95SEwan Crawford 194263e5fb76SJonas Devlieghere LLDB_LOGF(log, 194363e5fb76SJonas Devlieghere "%s - dims (%" PRIu32 ", %" PRIu32 ", %" PRIu32 1944b9c1b51eSKate Stone ") Element*: 0x%" PRIx64 ".", 194580af0b9eSLuke Drummond __FUNCTION__, dims.dim_1, dims.dim_2, dims.dim_3, element_ptr); 194615f2bd95SEwan Crawford 194715f2bd95SEwan Crawford return true; 194815f2bd95SEwan Crawford } 194915f2bd95SEwan Crawford 195080af0b9eSLuke Drummond // JITs the RS runtime for information about the Element of an allocation Then 195180af0b9eSLuke Drummond // sets type, type_vec_size, field_count and type_kind members in Element with 195280af0b9eSLuke Drummond // the result. Returns true on success, false otherwise 1953b9c1b51eSKate Stone bool RenderScriptRuntime::JITElementPacked(Element &elem, 1954b9c1b51eSKate Stone const lldb::addr_t context, 1955b9c1b51eSKate Stone StackFrame *frame_ptr) { 1956*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 195715f2bd95SEwan Crawford 1958b9c1b51eSKate Stone if (!elem.element_ptr.isValid()) { 195963e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__); 196015f2bd95SEwan Crawford return false; 196115f2bd95SEwan Crawford } 196215f2bd95SEwan Crawford 19638b244e21SEwan Crawford // We want 4 elements from packed data 1964b3f7f69dSAidan Dodds const uint32_t num_exprs = 4; 19654c1d6ee8SJonas Devlieghere static_assert(num_exprs == (eExprElementFieldCount - eExprElementType + 1), 1966b9c1b51eSKate Stone "Invalid number of expressions"); 196715f2bd95SEwan Crawford 196880af0b9eSLuke Drummond char expr_bufs[num_exprs][jit_max_expr_size]; 196915f2bd95SEwan Crawford uint64_t results[num_exprs]; 197015f2bd95SEwan Crawford 1971b9c1b51eSKate Stone for (uint32_t i = 0; i < num_exprs; i++) { 197280af0b9eSLuke Drummond const char *fmt_str = JITTemplate(ExpressionStrings(eExprElementType + i)); 197380af0b9eSLuke Drummond int written = snprintf(expr_bufs[i], jit_max_expr_size, fmt_str, context, 197480af0b9eSLuke Drummond *elem.element_ptr.get()); 197580af0b9eSLuke Drummond if (written < 0) { 197663e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__); 197715f2bd95SEwan Crawford return false; 197880af0b9eSLuke Drummond } else if (written >= jit_max_expr_size) { 197963e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__); 198015f2bd95SEwan Crawford return false; 198115f2bd95SEwan Crawford } 198215f2bd95SEwan Crawford 198315f2bd95SEwan Crawford // Perform expression evaluation 198480af0b9eSLuke Drummond if (!EvalRSExpression(expr_bufs[i], frame_ptr, &results[i])) 198515f2bd95SEwan Crawford return false; 198615f2bd95SEwan Crawford } 198715f2bd95SEwan Crawford 198815f2bd95SEwan Crawford // Assign results to allocation members 19898b244e21SEwan Crawford elem.type = static_cast<RenderScriptRuntime::Element::DataType>(results[0]); 1990b9c1b51eSKate Stone elem.type_kind = 1991b9c1b51eSKate Stone static_cast<RenderScriptRuntime::Element::DataKind>(results[1]); 19928b244e21SEwan Crawford elem.type_vec_size = static_cast<uint32_t>(results[2]); 19938b244e21SEwan Crawford elem.field_count = static_cast<uint32_t>(results[3]); 199415f2bd95SEwan Crawford 199563e5fb76SJonas Devlieghere LLDB_LOGF(log, 199663e5fb76SJonas Devlieghere "%s - data type %" PRIu32 ", pixel type %" PRIu32 1997b9c1b51eSKate Stone ", vector size %" PRIu32 ", field count %" PRIu32, 1998b9c1b51eSKate Stone __FUNCTION__, *elem.type.get(), *elem.type_kind.get(), 1999b9c1b51eSKate Stone *elem.type_vec_size.get(), *elem.field_count.get()); 20008b244e21SEwan Crawford 2001b9c1b51eSKate Stone // If this Element has subelements then JIT rsaElementGetSubElements() for 2002b9c1b51eSKate Stone // details about its fields 2003a6682a41SJonas Devlieghere return !(*elem.field_count.get() > 0 && 2004a6682a41SJonas Devlieghere !JITSubelements(elem, context, frame_ptr)); 20058b244e21SEwan Crawford } 20068b244e21SEwan Crawford 2007b9c1b51eSKate Stone // JITs the RS runtime for information about the subelements/fields of a struct 200880af0b9eSLuke Drummond // allocation This is necessary for infering the struct type so we can pretty 200980af0b9eSLuke Drummond // print the allocation's contents. Returns true on success, false otherwise 2010b9c1b51eSKate Stone bool RenderScriptRuntime::JITSubelements(Element &elem, 2011b9c1b51eSKate Stone const lldb::addr_t context, 2012b9c1b51eSKate Stone StackFrame *frame_ptr) { 2013*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 20148b244e21SEwan Crawford 2015b9c1b51eSKate Stone if (!elem.element_ptr.isValid() || !elem.field_count.isValid()) { 201663e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__); 20178b244e21SEwan Crawford return false; 20188b244e21SEwan Crawford } 20198b244e21SEwan Crawford 20208b244e21SEwan Crawford const short num_exprs = 3; 20214c1d6ee8SJonas Devlieghere static_assert(num_exprs == (eExprSubelementsArrSize - eExprSubelementsId + 1), 2022b9c1b51eSKate Stone "Invalid number of expressions"); 20238b244e21SEwan Crawford 2024ea0636b5SEwan Crawford char expr_buffer[jit_max_expr_size]; 20258b244e21SEwan Crawford uint64_t results; 20268b244e21SEwan Crawford 20278b244e21SEwan Crawford // Iterate over struct fields. 20288b244e21SEwan Crawford const uint32_t field_count = *elem.field_count.get(); 2029b9c1b51eSKate Stone for (uint32_t field_index = 0; field_index < field_count; ++field_index) { 20308b244e21SEwan Crawford Element child; 2031b9c1b51eSKate Stone for (uint32_t expr_index = 0; expr_index < num_exprs; ++expr_index) { 203280af0b9eSLuke Drummond const char *fmt_str = 2033b9c1b51eSKate Stone JITTemplate(ExpressionStrings(eExprSubelementsId + expr_index)); 203480af0b9eSLuke Drummond int written = snprintf(expr_buffer, jit_max_expr_size, fmt_str, 203536d783ebSDavid Gross context, field_count, field_count, field_count, 203680af0b9eSLuke Drummond *elem.element_ptr.get(), field_count, field_index); 203780af0b9eSLuke Drummond if (written < 0) { 203863e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__); 20398b244e21SEwan Crawford return false; 204080af0b9eSLuke Drummond } else if (written >= jit_max_expr_size) { 204163e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__); 20428b244e21SEwan Crawford return false; 20438b244e21SEwan Crawford } 20448b244e21SEwan Crawford 20458b244e21SEwan Crawford // Perform expression evaluation 20468b244e21SEwan Crawford if (!EvalRSExpression(expr_buffer, frame_ptr, &results)) 20478b244e21SEwan Crawford return false; 20488b244e21SEwan Crawford 204963e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - expr result 0x%" PRIx64 ".", __FUNCTION__, results); 20508b244e21SEwan Crawford 2051b9c1b51eSKate Stone switch (expr_index) { 20528b244e21SEwan Crawford case 0: // Element* of child 20538b244e21SEwan Crawford child.element_ptr = static_cast<addr_t>(results); 20548b244e21SEwan Crawford break; 20558b244e21SEwan Crawford case 1: // Name of child 20568b244e21SEwan Crawford { 20578b244e21SEwan Crawford lldb::addr_t address = static_cast<addr_t>(results); 205897206d57SZachary Turner Status err; 20598b244e21SEwan Crawford std::string name; 20608b244e21SEwan Crawford GetProcess()->ReadCStringFromMemory(address, name, err); 20618b244e21SEwan Crawford if (!err.Fail()) 20628b244e21SEwan Crawford child.type_name = ConstString(name); 2063b9c1b51eSKate Stone else { 206463e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - warning: Couldn't read field name.", 2065b9c1b51eSKate Stone __FUNCTION__); 20668b244e21SEwan Crawford } 20678b244e21SEwan Crawford break; 20688b244e21SEwan Crawford } 20698b244e21SEwan Crawford case 2: // Array size of child 20708b244e21SEwan Crawford child.array_size = static_cast<uint32_t>(results); 20718b244e21SEwan Crawford break; 20728b244e21SEwan Crawford } 20738b244e21SEwan Crawford } 20748b244e21SEwan Crawford 20758b244e21SEwan Crawford // We need to recursively JIT each Element field of the struct since 20768b244e21SEwan Crawford // structs can be nested inside structs. 20778b244e21SEwan Crawford if (!JITElementPacked(child, context, frame_ptr)) 20788b244e21SEwan Crawford return false; 20798b244e21SEwan Crawford elem.children.push_back(child); 20808b244e21SEwan Crawford } 20818b244e21SEwan Crawford 2082b9c1b51eSKate Stone // Try to infer the name of the struct type so we can pretty print the 2083b9c1b51eSKate Stone // allocation contents. 20848b244e21SEwan Crawford FindStructTypeName(elem, frame_ptr); 208515f2bd95SEwan Crawford 208615f2bd95SEwan Crawford return true; 208715f2bd95SEwan Crawford } 208815f2bd95SEwan Crawford 2089a0f08674SEwan Crawford // JITs the RS runtime for the address of the last element in the allocation. 2090b9c1b51eSKate Stone // The `elem_size` parameter represents the size of a single element, including 209180af0b9eSLuke Drummond // padding. Which is needed as an offset from the last element pointer. Using 209280af0b9eSLuke Drummond // this offset minus the starting address we can calculate the size of the 209380af0b9eSLuke Drummond // allocation. Returns true on success, false otherwise 209480af0b9eSLuke Drummond bool RenderScriptRuntime::JITAllocationSize(AllocationDetails *alloc, 2095b9c1b51eSKate Stone StackFrame *frame_ptr) { 2096*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 2097a0f08674SEwan Crawford 209880af0b9eSLuke Drummond if (!alloc->address.isValid() || !alloc->dimension.isValid() || 209980af0b9eSLuke Drummond !alloc->data_ptr.isValid() || !alloc->element.datum_size.isValid()) { 210063e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__); 2101a0f08674SEwan Crawford return false; 2102a0f08674SEwan Crawford } 2103a0f08674SEwan Crawford 2104a0f08674SEwan Crawford // Find dimensions 210580af0b9eSLuke Drummond uint32_t dim_x = alloc->dimension.get()->dim_1; 210680af0b9eSLuke Drummond uint32_t dim_y = alloc->dimension.get()->dim_2; 210780af0b9eSLuke Drummond uint32_t dim_z = alloc->dimension.get()->dim_3; 2108a0f08674SEwan Crawford 2109b9c1b51eSKate Stone // Our plan of jitting the last element address doesn't seem to work for 211080af0b9eSLuke Drummond // struct Allocations` Instead try to infer the size ourselves without any 211180af0b9eSLuke Drummond // inter element padding. 211280af0b9eSLuke Drummond if (alloc->element.children.size() > 0) { 2113b9c1b51eSKate Stone if (dim_x == 0) 2114b9c1b51eSKate Stone dim_x = 1; 2115b9c1b51eSKate Stone if (dim_y == 0) 2116b9c1b51eSKate Stone dim_y = 1; 2117b9c1b51eSKate Stone if (dim_z == 0) 2118b9c1b51eSKate Stone dim_z = 1; 21198b244e21SEwan Crawford 212080af0b9eSLuke Drummond alloc->size = dim_x * dim_y * dim_z * *alloc->element.datum_size.get(); 21218b244e21SEwan Crawford 212263e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - inferred size of struct allocation %" PRIu32 ".", 212380af0b9eSLuke Drummond __FUNCTION__, *alloc->size.get()); 21248b244e21SEwan Crawford return true; 21258b244e21SEwan Crawford } 21268b244e21SEwan Crawford 212780af0b9eSLuke Drummond const char *fmt_str = JITTemplate(eExprGetOffsetPtr); 212880af0b9eSLuke Drummond char expr_buf[jit_max_expr_size]; 21298b244e21SEwan Crawford 2130a0f08674SEwan Crawford // Calculate last element 2131a0f08674SEwan Crawford dim_x = dim_x == 0 ? 0 : dim_x - 1; 2132a0f08674SEwan Crawford dim_y = dim_y == 0 ? 0 : dim_y - 1; 2133a0f08674SEwan Crawford dim_z = dim_z == 0 ? 0 : dim_z - 1; 2134a0f08674SEwan Crawford 213580af0b9eSLuke Drummond int written = snprintf(expr_buf, jit_max_expr_size, fmt_str, 213680af0b9eSLuke Drummond *alloc->address.get(), dim_x, dim_y, dim_z); 213780af0b9eSLuke Drummond if (written < 0) { 213863e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__); 2139a0f08674SEwan Crawford return false; 214080af0b9eSLuke Drummond } else if (written >= jit_max_expr_size) { 214163e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__); 2142a0f08674SEwan Crawford return false; 2143a0f08674SEwan Crawford } 2144a0f08674SEwan Crawford 2145a0f08674SEwan Crawford uint64_t result = 0; 214680af0b9eSLuke Drummond if (!EvalRSExpression(expr_buf, frame_ptr, &result)) 2147a0f08674SEwan Crawford return false; 2148a0f08674SEwan Crawford 2149a0f08674SEwan Crawford addr_t mem_ptr = static_cast<lldb::addr_t>(result); 2150a0f08674SEwan Crawford // Find pointer to last element and add on size of an element 215180af0b9eSLuke Drummond alloc->size = static_cast<uint32_t>(mem_ptr - *alloc->data_ptr.get()) + 215280af0b9eSLuke Drummond *alloc->element.datum_size.get(); 2153a0f08674SEwan Crawford 2154a0f08674SEwan Crawford return true; 2155a0f08674SEwan Crawford } 2156a0f08674SEwan Crawford 2157b9c1b51eSKate Stone // JITs the RS runtime for information about the stride between rows in the 215805097246SAdrian Prantl // allocation. This is done to detect padding, since allocated memory is 215905097246SAdrian Prantl // 16-byte aligned. Returns true on success, false otherwise 216080af0b9eSLuke Drummond bool RenderScriptRuntime::JITAllocationStride(AllocationDetails *alloc, 2161b9c1b51eSKate Stone StackFrame *frame_ptr) { 2162*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 2163a0f08674SEwan Crawford 216480af0b9eSLuke Drummond if (!alloc->address.isValid() || !alloc->data_ptr.isValid()) { 216563e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__); 2166a0f08674SEwan Crawford return false; 2167a0f08674SEwan Crawford } 2168a0f08674SEwan Crawford 216980af0b9eSLuke Drummond const char *fmt_str = JITTemplate(eExprGetOffsetPtr); 217080af0b9eSLuke Drummond char expr_buf[jit_max_expr_size]; 2171a0f08674SEwan Crawford 217280af0b9eSLuke Drummond int written = snprintf(expr_buf, jit_max_expr_size, fmt_str, 217380af0b9eSLuke Drummond *alloc->address.get(), 0, 1, 0); 217480af0b9eSLuke Drummond if (written < 0) { 217563e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__); 2176a0f08674SEwan Crawford return false; 217780af0b9eSLuke Drummond } else if (written >= jit_max_expr_size) { 217863e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__); 2179a0f08674SEwan Crawford return false; 2180a0f08674SEwan Crawford } 2181a0f08674SEwan Crawford 2182a0f08674SEwan Crawford uint64_t result = 0; 218380af0b9eSLuke Drummond if (!EvalRSExpression(expr_buf, frame_ptr, &result)) 2184a0f08674SEwan Crawford return false; 2185a0f08674SEwan Crawford 2186a0f08674SEwan Crawford addr_t mem_ptr = static_cast<lldb::addr_t>(result); 218780af0b9eSLuke Drummond alloc->stride = static_cast<uint32_t>(mem_ptr - *alloc->data_ptr.get()); 2188a0f08674SEwan Crawford 2189a0f08674SEwan Crawford return true; 2190a0f08674SEwan Crawford } 2191a0f08674SEwan Crawford 219215f2bd95SEwan Crawford // JIT all the current runtime info regarding an allocation 219380af0b9eSLuke Drummond bool RenderScriptRuntime::RefreshAllocation(AllocationDetails *alloc, 2194b9c1b51eSKate Stone StackFrame *frame_ptr) { 219515f2bd95SEwan Crawford // GetOffsetPointer() 219680af0b9eSLuke Drummond if (!JITDataPointer(alloc, frame_ptr)) 219715f2bd95SEwan Crawford return false; 219815f2bd95SEwan Crawford 219915f2bd95SEwan Crawford // rsaAllocationGetType() 220080af0b9eSLuke Drummond if (!JITTypePointer(alloc, frame_ptr)) 220115f2bd95SEwan Crawford return false; 220215f2bd95SEwan Crawford 220315f2bd95SEwan Crawford // rsaTypeGetNativeData() 220480af0b9eSLuke Drummond if (!JITTypePacked(alloc, frame_ptr)) 220515f2bd95SEwan Crawford return false; 220615f2bd95SEwan Crawford 220715f2bd95SEwan Crawford // rsaElementGetNativeData() 220880af0b9eSLuke Drummond if (!JITElementPacked(alloc->element, *alloc->context.get(), frame_ptr)) 220915f2bd95SEwan Crawford return false; 221015f2bd95SEwan Crawford 22118b244e21SEwan Crawford // Sets the datum_size member in Element 221280af0b9eSLuke Drummond SetElementSize(alloc->element); 22138b244e21SEwan Crawford 221455232f09SEwan Crawford // Use GetOffsetPointer() to infer size of the allocation 2215a6682a41SJonas Devlieghere return JITAllocationSize(alloc, frame_ptr); 221655232f09SEwan Crawford } 221755232f09SEwan Crawford 221836597e47SBruce Mitchener // Function attempts to set the type_name member of the parameterised Element 221905097246SAdrian Prantl // object. This string should be the name of the struct type the Element 222005097246SAdrian Prantl // represents. We need this string for pretty printing the Element to users. 2221b9c1b51eSKate Stone void RenderScriptRuntime::FindStructTypeName(Element &elem, 2222b9c1b51eSKate Stone StackFrame *frame_ptr) { 2223*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 22248b244e21SEwan Crawford 22258b244e21SEwan Crawford if (!elem.type_name.IsEmpty()) // Name already set 22268b244e21SEwan Crawford return; 22278b244e21SEwan Crawford else 2228b9c1b51eSKate Stone elem.type_name = Element::GetFallbackStructName(); // Default type name if 2229b9c1b51eSKate Stone // we don't succeed 22308b244e21SEwan Crawford 22318b244e21SEwan Crawford // Find all the global variables from the script rs modules 223280af0b9eSLuke Drummond VariableList var_list; 22338b244e21SEwan Crawford for (auto module_sp : m_rsmodules) 223495eae423SZachary Turner module_sp->m_module->FindGlobalVariables( 223534cda14bSPavel Labath RegularExpression(llvm::StringRef(".")), UINT32_MAX, var_list); 22368b244e21SEwan Crawford 2237b9c1b51eSKate Stone // Iterate over all the global variables looking for one with a matching type 223805097246SAdrian Prantl // to the Element. We make the assumption a match exists since there needs to 223905097246SAdrian Prantl // be a global variable to reflect the struct type back into java host code. 2240d1782133SRaphael Isemann for (const VariableSP &var_sp : var_list) { 22418b244e21SEwan Crawford if (!var_sp) 22428b244e21SEwan Crawford continue; 22438b244e21SEwan Crawford 22448b244e21SEwan Crawford ValueObjectSP valobj_sp = ValueObjectVariable::Create(frame_ptr, var_sp); 22458b244e21SEwan Crawford if (!valobj_sp) 22468b244e21SEwan Crawford continue; 22478b244e21SEwan Crawford 22488b244e21SEwan Crawford // Find the number of variable fields. 2249b9c1b51eSKate Stone // If it has no fields, or more fields than our Element, then it can't be 225005097246SAdrian Prantl // the struct we're looking for. Don't check for equality since RS can add 225105097246SAdrian Prantl // extra struct members for padding. 22528b244e21SEwan Crawford size_t num_children = valobj_sp->GetNumChildren(); 22538b244e21SEwan Crawford if (num_children > elem.children.size() || num_children == 0) 22548b244e21SEwan Crawford continue; 22558b244e21SEwan Crawford 225605097246SAdrian Prantl // Iterate over children looking for members with matching field names. If 225705097246SAdrian Prantl // all the field names match, this is likely the struct we want. 2258b9c1b51eSKate Stone // TODO: This could be made more robust by also checking children data 2259b9c1b51eSKate Stone // sizes, or array size 22608b244e21SEwan Crawford bool found = true; 226180af0b9eSLuke Drummond for (size_t i = 0; i < num_children; ++i) { 226280af0b9eSLuke Drummond ValueObjectSP child = valobj_sp->GetChildAtIndex(i, true); 226380af0b9eSLuke Drummond if (!child || (child->GetName() != elem.children[i].type_name)) { 22648b244e21SEwan Crawford found = false; 22658b244e21SEwan Crawford break; 22668b244e21SEwan Crawford } 22678b244e21SEwan Crawford } 22688b244e21SEwan Crawford 2269b9c1b51eSKate Stone // RS can add extra struct members for padding in the format 2270b9c1b51eSKate Stone // '#rs_padding_[0-9]+' 2271b9c1b51eSKate Stone if (found && num_children < elem.children.size()) { 2272b3f7f69dSAidan Dodds const uint32_t size_diff = elem.children.size() - num_children; 227363e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - %" PRIu32 " padding struct entries", __FUNCTION__, 2274b9c1b51eSKate Stone size_diff); 22758b244e21SEwan Crawford 227680af0b9eSLuke Drummond for (uint32_t i = 0; i < size_diff; ++i) { 22770e4c4821SAdrian Prantl ConstString name = elem.children[num_children + i].type_name; 22788b244e21SEwan Crawford if (strcmp(name.AsCString(), "#rs_padding") < 0) 22798b244e21SEwan Crawford found = false; 22808b244e21SEwan Crawford } 22818b244e21SEwan Crawford } 22828b244e21SEwan Crawford 228380af0b9eSLuke Drummond // We've found a global variable with matching type 2284b9c1b51eSKate Stone if (found) { 22858b244e21SEwan Crawford // Dereference since our Element type isn't a pointer. 2286b9c1b51eSKate Stone if (valobj_sp->IsPointerType()) { 228797206d57SZachary Turner Status err; 22888b244e21SEwan Crawford ValueObjectSP deref_valobj = valobj_sp->Dereference(err); 22898b244e21SEwan Crawford if (!err.Fail()) 22908b244e21SEwan Crawford valobj_sp = deref_valobj; 22918b244e21SEwan Crawford } 22928b244e21SEwan Crawford 22938b244e21SEwan Crawford // Save name of variable in Element. 22948b244e21SEwan Crawford elem.type_name = valobj_sp->GetTypeName(); 229563e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - element name set to %s", __FUNCTION__, 2296b9c1b51eSKate Stone elem.type_name.AsCString()); 22978b244e21SEwan Crawford 22988b244e21SEwan Crawford return; 22998b244e21SEwan Crawford } 23008b244e21SEwan Crawford } 23018b244e21SEwan Crawford } 23028b244e21SEwan Crawford 2303b9c1b51eSKate Stone // Function sets the datum_size member of Element. Representing the size of a 230405097246SAdrian Prantl // single instance including padding. Assumes the relevant allocation 230505097246SAdrian Prantl // information has already been jitted. 2306b9c1b51eSKate Stone void RenderScriptRuntime::SetElementSize(Element &elem) { 2307*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 23088b244e21SEwan Crawford const Element::DataType type = *elem.type.get(); 2309b9c1b51eSKate Stone assert(type >= Element::RS_TYPE_NONE && type <= Element::RS_TYPE_FONT && 2310b9c1b51eSKate Stone "Invalid allocation type"); 231155232f09SEwan Crawford 2312b3f7f69dSAidan Dodds const uint32_t vec_size = *elem.type_vec_size.get(); 2313b3f7f69dSAidan Dodds uint32_t data_size = 0; 2314b3f7f69dSAidan Dodds uint32_t padding = 0; 231555232f09SEwan Crawford 23168b244e21SEwan Crawford // Element is of a struct type, calculate size recursively. 2317b9c1b51eSKate Stone if ((type == Element::RS_TYPE_NONE) && (elem.children.size() > 0)) { 2318b9c1b51eSKate Stone for (Element &child : elem.children) { 23198b244e21SEwan Crawford SetElementSize(child); 2320b9c1b51eSKate Stone const uint32_t array_size = 2321b9c1b51eSKate Stone child.array_size.isValid() ? *child.array_size.get() : 1; 23228b244e21SEwan Crawford data_size += *child.datum_size.get() * array_size; 23238b244e21SEwan Crawford } 23248b244e21SEwan Crawford } 2325b3f7f69dSAidan Dodds // These have been packed already 2326b3f7f69dSAidan Dodds else if (type == Element::RS_TYPE_UNSIGNED_5_6_5 || 2327b3f7f69dSAidan Dodds type == Element::RS_TYPE_UNSIGNED_5_5_5_1 || 2328b9c1b51eSKate Stone type == Element::RS_TYPE_UNSIGNED_4_4_4_4) { 23292e920715SEwan Crawford data_size = AllocationDetails::RSTypeToFormat[type][eElementSize]; 2330b9c1b51eSKate Stone } else if (type < Element::RS_TYPE_ELEMENT) { 2331b9c1b51eSKate Stone data_size = 2332b9c1b51eSKate Stone vec_size * AllocationDetails::RSTypeToFormat[type][eElementSize]; 23332e920715SEwan Crawford if (vec_size == 3) 23342e920715SEwan Crawford padding = AllocationDetails::RSTypeToFormat[type][eElementSize]; 2335b9c1b51eSKate Stone } else 2336b9c1b51eSKate Stone data_size = 2337b9c1b51eSKate Stone GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize(); 23388b244e21SEwan Crawford 23398b244e21SEwan Crawford elem.padding = padding; 23408b244e21SEwan Crawford elem.datum_size = data_size + padding; 234163e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - element size set to %" PRIu32, __FUNCTION__, 2342b9c1b51eSKate Stone data_size + padding); 234355232f09SEwan Crawford } 234455232f09SEwan Crawford 234505097246SAdrian Prantl // Given an allocation, this function copies the allocation contents from 234605097246SAdrian Prantl // device into a buffer on the heap. Returning a shared pointer to the buffer 234705097246SAdrian Prantl // containing the data. 234855232f09SEwan Crawford std::shared_ptr<uint8_t> 234980af0b9eSLuke Drummond RenderScriptRuntime::GetAllocationData(AllocationDetails *alloc, 2350b9c1b51eSKate Stone StackFrame *frame_ptr) { 2351*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 235255232f09SEwan Crawford 235355232f09SEwan Crawford // JIT all the allocation details 235480af0b9eSLuke Drummond if (alloc->ShouldRefresh()) { 235563e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - allocation details not calculated yet, jitting info", 2356b9c1b51eSKate Stone __FUNCTION__); 235755232f09SEwan Crawford 235880af0b9eSLuke Drummond if (!RefreshAllocation(alloc, frame_ptr)) { 235963e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - couldn't JIT allocation details", __FUNCTION__); 236055232f09SEwan Crawford return nullptr; 236155232f09SEwan Crawford } 236255232f09SEwan Crawford } 236355232f09SEwan Crawford 236480af0b9eSLuke Drummond assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() && 236580af0b9eSLuke Drummond alloc->element.type_vec_size.isValid() && alloc->size.isValid() && 236680af0b9eSLuke Drummond "Allocation information not available"); 236755232f09SEwan Crawford 236855232f09SEwan Crawford // Allocate a buffer to copy data into 236980af0b9eSLuke Drummond const uint32_t size = *alloc->size.get(); 237055232f09SEwan Crawford std::shared_ptr<uint8_t> buffer(new uint8_t[size]); 2371b9c1b51eSKate Stone if (!buffer) { 237263e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - couldn't allocate a %" PRIu32 " byte buffer", 2373b9c1b51eSKate Stone __FUNCTION__, size); 237455232f09SEwan Crawford return nullptr; 237555232f09SEwan Crawford } 237655232f09SEwan Crawford 237755232f09SEwan Crawford // Read the inferior memory 237897206d57SZachary Turner Status err; 237980af0b9eSLuke Drummond lldb::addr_t data_ptr = *alloc->data_ptr.get(); 238080af0b9eSLuke Drummond GetProcess()->ReadMemory(data_ptr, buffer.get(), size, err); 238180af0b9eSLuke Drummond if (err.Fail()) { 238263e5fb76SJonas Devlieghere LLDB_LOGF(log, 238363e5fb76SJonas Devlieghere "%s - '%s' Couldn't read %" PRIu32 2384b9c1b51eSKate Stone " bytes of allocation data from 0x%" PRIx64, 238580af0b9eSLuke Drummond __FUNCTION__, err.AsCString(), size, data_ptr); 238655232f09SEwan Crawford return nullptr; 238755232f09SEwan Crawford } 238855232f09SEwan Crawford 238955232f09SEwan Crawford return buffer; 239055232f09SEwan Crawford } 239155232f09SEwan Crawford 239205097246SAdrian Prantl // Function copies data from a binary file into an allocation. There is a 239305097246SAdrian Prantl // header at the start of the file, FileHeader, before the data content itself. 2394b9c1b51eSKate Stone // Information from this header is used to display warnings to the user about 2395b9c1b51eSKate Stone // incompatibilities 2396b9c1b51eSKate Stone bool RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id, 239780af0b9eSLuke Drummond const char *path, 2398b9c1b51eSKate Stone StackFrame *frame_ptr) { 2399*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 240055232f09SEwan Crawford 240155232f09SEwan Crawford // Find allocation with the given id 240255232f09SEwan Crawford AllocationDetails *alloc = FindAllocByID(strm, alloc_id); 240355232f09SEwan Crawford if (!alloc) 240455232f09SEwan Crawford return false; 240555232f09SEwan Crawford 240663e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - found allocation 0x%" PRIx64, __FUNCTION__, 2407b9c1b51eSKate Stone *alloc->address.get()); 240855232f09SEwan Crawford 240955232f09SEwan Crawford // JIT all the allocation details 241080af0b9eSLuke Drummond if (alloc->ShouldRefresh()) { 241163e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - allocation details not calculated yet, jitting info.", 2412b9c1b51eSKate Stone __FUNCTION__); 241355232f09SEwan Crawford 2414b9c1b51eSKate Stone if (!RefreshAllocation(alloc, frame_ptr)) { 241563e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - couldn't JIT allocation details", __FUNCTION__); 24164cfc9198SSylvestre Ledru return false; 241755232f09SEwan Crawford } 241855232f09SEwan Crawford } 241955232f09SEwan Crawford 2420b9c1b51eSKate Stone assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() && 2421b9c1b51eSKate Stone alloc->element.type_vec_size.isValid() && alloc->size.isValid() && 2422b9c1b51eSKate Stone alloc->element.datum_size.isValid() && 2423b9c1b51eSKate Stone "Allocation information not available"); 242455232f09SEwan Crawford 242555232f09SEwan Crawford // Check we can read from file 24268f3be7a3SJonas Devlieghere FileSpec file(path); 24278f3be7a3SJonas Devlieghere FileSystem::Instance().Resolve(file); 2428dbd7fabaSJonas Devlieghere if (!FileSystem::Instance().Exists(file)) { 242980af0b9eSLuke Drummond strm.Printf("Error: File %s does not exist", path); 243055232f09SEwan Crawford strm.EOL(); 243155232f09SEwan Crawford return false; 243255232f09SEwan Crawford } 243355232f09SEwan Crawford 24347c5310bbSJonas Devlieghere if (!FileSystem::Instance().Readable(file)) { 243580af0b9eSLuke Drummond strm.Printf("Error: File %s does not have readable permissions", path); 243655232f09SEwan Crawford strm.EOL(); 243755232f09SEwan Crawford return false; 243855232f09SEwan Crawford } 243955232f09SEwan Crawford 244055232f09SEwan Crawford // Read file into data buffer 244187e403aaSJonas Devlieghere auto data_sp = FileSystem::Instance().CreateDataBuffer(file.GetPath()); 244255232f09SEwan Crawford 244355232f09SEwan Crawford // Cast start of buffer to FileHeader and use pointer to read metadata 244480af0b9eSLuke Drummond void *file_buf = data_sp->GetBytes(); 244580af0b9eSLuke Drummond if (file_buf == nullptr || 2446b9c1b51eSKate Stone data_sp->GetByteSize() < (sizeof(AllocationDetails::FileHeader) + 2447b9c1b51eSKate Stone sizeof(AllocationDetails::ElementHeader))) { 244880af0b9eSLuke Drummond strm.Printf("Error: File %s does not contain enough data for header", path); 244926e52a70SEwan Crawford strm.EOL(); 245026e52a70SEwan Crawford return false; 245126e52a70SEwan Crawford } 2452b9c1b51eSKate Stone const AllocationDetails::FileHeader *file_header = 245380af0b9eSLuke Drummond static_cast<AllocationDetails::FileHeader *>(file_buf); 245455232f09SEwan Crawford 245526e52a70SEwan Crawford // Check file starts with ascii characters "RSAD" 2456b9c1b51eSKate Stone if (memcmp(file_header->ident, "RSAD", 4)) { 2457b9c1b51eSKate Stone strm.Printf("Error: File doesn't contain identifier for an RS allocation " 2458b9c1b51eSKate Stone "dump. Are you sure this is the correct file?"); 245926e52a70SEwan Crawford strm.EOL(); 246026e52a70SEwan Crawford return false; 246126e52a70SEwan Crawford } 246226e52a70SEwan Crawford 246326e52a70SEwan Crawford // Look at the type of the root element in the header 246480af0b9eSLuke Drummond AllocationDetails::ElementHeader root_el_hdr; 246580af0b9eSLuke Drummond memcpy(&root_el_hdr, static_cast<uint8_t *>(file_buf) + 2466b9c1b51eSKate Stone sizeof(AllocationDetails::FileHeader), 246726e52a70SEwan Crawford sizeof(AllocationDetails::ElementHeader)); 246855232f09SEwan Crawford 246963e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - header type %" PRIu32 ", element size %" PRIu32, 247080af0b9eSLuke Drummond __FUNCTION__, root_el_hdr.type, root_el_hdr.element_size); 247155232f09SEwan Crawford 2472b9c1b51eSKate Stone // Check if the target allocation and file both have the same number of bytes 2473b9c1b51eSKate Stone // for an Element 247480af0b9eSLuke Drummond if (*alloc->element.datum_size.get() != root_el_hdr.element_size) { 2475b9c1b51eSKate Stone strm.Printf("Warning: Mismatched Element sizes - file %" PRIu32 2476b9c1b51eSKate Stone " bytes, allocation %" PRIu32 " bytes", 247780af0b9eSLuke Drummond root_el_hdr.element_size, *alloc->element.datum_size.get()); 247855232f09SEwan Crawford strm.EOL(); 247955232f09SEwan Crawford } 248055232f09SEwan Crawford 248126e52a70SEwan Crawford // Check if the target allocation and file both have the same type 2482b3f7f69dSAidan Dodds const uint32_t alloc_type = static_cast<uint32_t>(*alloc->element.type.get()); 248380af0b9eSLuke Drummond const uint32_t file_type = root_el_hdr.type; 248426e52a70SEwan Crawford 2485b9c1b51eSKate Stone if (file_type > Element::RS_TYPE_FONT) { 248626e52a70SEwan Crawford strm.Printf("Warning: File has unknown allocation type"); 248726e52a70SEwan Crawford strm.EOL(); 2488b9c1b51eSKate Stone } else if (alloc_type != file_type) { 2489b9c1b51eSKate Stone // Enum value isn't monotonous, so doesn't always index RsDataTypeToString 2490b9c1b51eSKate Stone // array 249180af0b9eSLuke Drummond uint32_t target_type_name_idx = alloc_type; 249280af0b9eSLuke Drummond uint32_t head_type_name_idx = file_type; 2493b9c1b51eSKate Stone if (alloc_type >= Element::RS_TYPE_ELEMENT && 2494b9c1b51eSKate Stone alloc_type <= Element::RS_TYPE_FONT) 249580af0b9eSLuke Drummond target_type_name_idx = static_cast<Element::DataType>( 2496b9c1b51eSKate Stone (alloc_type - Element::RS_TYPE_ELEMENT) + 2497b3f7f69dSAidan Dodds Element::RS_TYPE_MATRIX_2X2 + 1); 24982e920715SEwan Crawford 2499b9c1b51eSKate Stone if (file_type >= Element::RS_TYPE_ELEMENT && 2500b9c1b51eSKate Stone file_type <= Element::RS_TYPE_FONT) 250180af0b9eSLuke Drummond head_type_name_idx = static_cast<Element::DataType>( 2502b9c1b51eSKate Stone (file_type - Element::RS_TYPE_ELEMENT) + Element::RS_TYPE_MATRIX_2X2 + 2503b9c1b51eSKate Stone 1); 25042e920715SEwan Crawford 250580af0b9eSLuke Drummond const char *head_type_name = 250680af0b9eSLuke Drummond AllocationDetails::RsDataTypeToString[head_type_name_idx][0]; 250780af0b9eSLuke Drummond const char *target_type_name = 250880af0b9eSLuke Drummond AllocationDetails::RsDataTypeToString[target_type_name_idx][0]; 250955232f09SEwan Crawford 2510b9c1b51eSKate Stone strm.Printf( 2511b9c1b51eSKate Stone "Warning: Mismatched Types - file '%s' type, allocation '%s' type", 251280af0b9eSLuke Drummond head_type_name, target_type_name); 251355232f09SEwan Crawford strm.EOL(); 251455232f09SEwan Crawford } 251555232f09SEwan Crawford 251626e52a70SEwan Crawford // Advance buffer past header 251780af0b9eSLuke Drummond file_buf = static_cast<uint8_t *>(file_buf) + file_header->hdr_size; 251826e52a70SEwan Crawford 251955232f09SEwan Crawford // Calculate size of allocation data in file 252080af0b9eSLuke Drummond size_t size = data_sp->GetByteSize() - file_header->hdr_size; 252155232f09SEwan Crawford 252205097246SAdrian Prantl // Check if the target allocation and file both have the same total data 252305097246SAdrian Prantl // size. 2524b3f7f69dSAidan Dodds const uint32_t alloc_size = *alloc->size.get(); 252580af0b9eSLuke Drummond if (alloc_size != size) { 2526b9c1b51eSKate Stone strm.Printf("Warning: Mismatched allocation sizes - file 0x%" PRIx64 2527b9c1b51eSKate Stone " bytes, allocation 0x%" PRIx32 " bytes", 252880af0b9eSLuke Drummond (uint64_t)size, alloc_size); 252955232f09SEwan Crawford strm.EOL(); 253080af0b9eSLuke Drummond // Set length to copy to minimum 253180af0b9eSLuke Drummond size = alloc_size < size ? alloc_size : size; 253255232f09SEwan Crawford } 253355232f09SEwan Crawford 253455232f09SEwan Crawford // Copy file data from our buffer into the target allocation. 253555232f09SEwan Crawford lldb::addr_t alloc_data = *alloc->data_ptr.get(); 253697206d57SZachary Turner Status err; 253780af0b9eSLuke Drummond size_t written = GetProcess()->WriteMemory(alloc_data, file_buf, size, err); 253880af0b9eSLuke Drummond if (!err.Success() || written != size) { 253980af0b9eSLuke Drummond strm.Printf("Error: Couldn't write data to allocation %s", err.AsCString()); 254055232f09SEwan Crawford strm.EOL(); 254155232f09SEwan Crawford return false; 254255232f09SEwan Crawford } 254355232f09SEwan Crawford 254480af0b9eSLuke Drummond strm.Printf("Contents of file '%s' read into allocation %" PRIu32, path, 2545b9c1b51eSKate Stone alloc->id); 254655232f09SEwan Crawford strm.EOL(); 254755232f09SEwan Crawford 254855232f09SEwan Crawford return true; 254955232f09SEwan Crawford } 255055232f09SEwan Crawford 2551b9c1b51eSKate Stone // Function takes as parameters a byte buffer, which will eventually be written 255280af0b9eSLuke Drummond // to file as the element header, an offset into that buffer, and an Element 255305097246SAdrian Prantl // that will be saved into the buffer at the parametrised offset. Return value 255405097246SAdrian Prantl // is the new offset after writing the element into the buffer. Elements are 255505097246SAdrian Prantl // saved to the file as the ElementHeader struct followed by offsets to the 255605097246SAdrian Prantl // structs of all the element's children. 2557b9c1b51eSKate Stone size_t RenderScriptRuntime::PopulateElementHeaders( 2558b9c1b51eSKate Stone const std::shared_ptr<uint8_t> header_buffer, size_t offset, 2559b9c1b51eSKate Stone const Element &elem) { 256005097246SAdrian Prantl // File struct for an element header with all the relevant details copied 256105097246SAdrian Prantl // from elem. We assume members are valid already. 256226e52a70SEwan Crawford AllocationDetails::ElementHeader elem_header; 256326e52a70SEwan Crawford elem_header.type = *elem.type.get(); 256426e52a70SEwan Crawford elem_header.kind = *elem.type_kind.get(); 256526e52a70SEwan Crawford elem_header.element_size = *elem.datum_size.get(); 256626e52a70SEwan Crawford elem_header.vector_size = *elem.type_vec_size.get(); 2567b9c1b51eSKate Stone elem_header.array_size = 2568b9c1b51eSKate Stone elem.array_size.isValid() ? *elem.array_size.get() : 0; 256926e52a70SEwan Crawford const size_t elem_header_size = sizeof(AllocationDetails::ElementHeader); 257026e52a70SEwan Crawford 257105097246SAdrian Prantl // Copy struct into buffer and advance offset We assume that header_buffer 257205097246SAdrian Prantl // has been checked for nullptr before this method is called 257326e52a70SEwan Crawford memcpy(header_buffer.get() + offset, &elem_header, elem_header_size); 257426e52a70SEwan Crawford offset += elem_header_size; 257526e52a70SEwan Crawford 257626e52a70SEwan Crawford // Starting offset of child ElementHeader struct 2577b9c1b51eSKate Stone size_t child_offset = 2578b9c1b51eSKate Stone offset + ((elem.children.size() + 1) * sizeof(uint32_t)); 2579b9c1b51eSKate Stone for (const RenderScriptRuntime::Element &child : elem.children) { 2580b9c1b51eSKate Stone // Recursively populate the buffer with the element header structs of 258180af0b9eSLuke Drummond // children. Then save the offsets where they were set after the parent 258280af0b9eSLuke Drummond // element header. 258326e52a70SEwan Crawford memcpy(header_buffer.get() + offset, &child_offset, sizeof(uint32_t)); 258426e52a70SEwan Crawford offset += sizeof(uint32_t); 258526e52a70SEwan Crawford 258626e52a70SEwan Crawford child_offset = PopulateElementHeaders(header_buffer, child_offset, child); 258726e52a70SEwan Crawford } 258826e52a70SEwan Crawford 258926e52a70SEwan Crawford // Zero indicates no more children 259026e52a70SEwan Crawford memset(header_buffer.get() + offset, 0, sizeof(uint32_t)); 259126e52a70SEwan Crawford 259226e52a70SEwan Crawford return child_offset; 259326e52a70SEwan Crawford } 259426e52a70SEwan Crawford 2595b9c1b51eSKate Stone // Given an Element object this function returns the total size needed in the 259680af0b9eSLuke Drummond // file header to store the element's details. Taking into account the size of 259780af0b9eSLuke Drummond // the element header struct, plus the offsets to all the element's children. 2598b9c1b51eSKate Stone // Function is recursive so that the size of all ancestors is taken into 2599b9c1b51eSKate Stone // account. 2600b9c1b51eSKate Stone size_t RenderScriptRuntime::CalculateElementHeaderSize(const Element &elem) { 260180af0b9eSLuke Drummond // Offsets to children plus zero terminator 260280af0b9eSLuke Drummond size_t size = (elem.children.size() + 1) * sizeof(uint32_t); 260380af0b9eSLuke Drummond // Size of header struct with type details 260480af0b9eSLuke Drummond size += sizeof(AllocationDetails::ElementHeader); 260526e52a70SEwan Crawford 260626e52a70SEwan Crawford // Calculate recursively for all descendants 260726e52a70SEwan Crawford for (const Element &child : elem.children) 260826e52a70SEwan Crawford size += CalculateElementHeaderSize(child); 260926e52a70SEwan Crawford 261026e52a70SEwan Crawford return size; 261126e52a70SEwan Crawford } 261226e52a70SEwan Crawford 261305097246SAdrian Prantl // Function copies allocation contents into a binary file. This file can then 261405097246SAdrian Prantl // be loaded later into a different allocation. There is a header, FileHeader, 261580af0b9eSLuke Drummond // before the allocation data containing meta-data. 2616b9c1b51eSKate Stone bool RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id, 261780af0b9eSLuke Drummond const char *path, 2618b9c1b51eSKate Stone StackFrame *frame_ptr) { 2619*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 262055232f09SEwan Crawford 262155232f09SEwan Crawford // Find allocation with the given id 262255232f09SEwan Crawford AllocationDetails *alloc = FindAllocByID(strm, alloc_id); 262355232f09SEwan Crawford if (!alloc) 262455232f09SEwan Crawford return false; 262555232f09SEwan Crawford 262663e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - found allocation 0x%" PRIx64 ".", __FUNCTION__, 2627b9c1b51eSKate Stone *alloc->address.get()); 262855232f09SEwan Crawford 262955232f09SEwan Crawford // JIT all the allocation details 263080af0b9eSLuke Drummond if (alloc->ShouldRefresh()) { 263163e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - allocation details not calculated yet, jitting info.", 2632b9c1b51eSKate Stone __FUNCTION__); 263355232f09SEwan Crawford 2634b9c1b51eSKate Stone if (!RefreshAllocation(alloc, frame_ptr)) { 263563e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - couldn't JIT allocation details.", __FUNCTION__); 26364cfc9198SSylvestre Ledru return false; 263755232f09SEwan Crawford } 263855232f09SEwan Crawford } 263955232f09SEwan Crawford 2640b9c1b51eSKate Stone assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() && 2641b9c1b51eSKate Stone alloc->element.type_vec_size.isValid() && 2642b9c1b51eSKate Stone alloc->element.datum_size.get() && 2643b9c1b51eSKate Stone alloc->element.type_kind.isValid() && alloc->dimension.isValid() && 2644b3f7f69dSAidan Dodds "Allocation information not available"); 264555232f09SEwan Crawford 264655232f09SEwan Crawford // Check we can create writable file 26478f3be7a3SJonas Devlieghere FileSpec file_spec(path); 26488f3be7a3SJonas Devlieghere FileSystem::Instance().Resolve(file_spec); 26492fce1137SLawrence D'Anna auto file = FileSystem::Instance().Open( 265014735cabSMichał Górny file_spec, File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate | 2651b9c1b51eSKate Stone File::eOpenOptionTruncate); 265250bc1ed2SJonas Devlieghere 2653b9c1b51eSKate Stone if (!file) { 26542fce1137SLawrence D'Anna std::string error = llvm::toString(file.takeError()); 26552fce1137SLawrence D'Anna strm.Printf("Error: Failed to open '%s' for writing: %s", path, 26562fce1137SLawrence D'Anna error.c_str()); 265755232f09SEwan Crawford strm.EOL(); 265855232f09SEwan Crawford return false; 265955232f09SEwan Crawford } 266055232f09SEwan Crawford 266155232f09SEwan Crawford // Read allocation into buffer of heap memory 266255232f09SEwan Crawford const std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr); 2663b9c1b51eSKate Stone if (!buffer) { 266455232f09SEwan Crawford strm.Printf("Error: Couldn't read allocation data into buffer"); 266555232f09SEwan Crawford strm.EOL(); 266655232f09SEwan Crawford return false; 266755232f09SEwan Crawford } 266855232f09SEwan Crawford 266955232f09SEwan Crawford // Create the file header 267055232f09SEwan Crawford AllocationDetails::FileHeader head; 2671b3f7f69dSAidan Dodds memcpy(head.ident, "RSAD", 4); 26722d62328aSEwan Crawford head.dims[0] = static_cast<uint32_t>(alloc->dimension.get()->dim_1); 26732d62328aSEwan Crawford head.dims[1] = static_cast<uint32_t>(alloc->dimension.get()->dim_2); 26742d62328aSEwan Crawford head.dims[2] = static_cast<uint32_t>(alloc->dimension.get()->dim_3); 267526e52a70SEwan Crawford 267626e52a70SEwan Crawford const size_t element_header_size = CalculateElementHeaderSize(alloc->element); 2677b9c1b51eSKate Stone assert((sizeof(AllocationDetails::FileHeader) + element_header_size) < 2678b9c1b51eSKate Stone UINT16_MAX && 2679b9c1b51eSKate Stone "Element header too large"); 2680b9c1b51eSKate Stone head.hdr_size = static_cast<uint16_t>(sizeof(AllocationDetails::FileHeader) + 2681b9c1b51eSKate Stone element_header_size); 268255232f09SEwan Crawford 268355232f09SEwan Crawford // Write the file header 268455232f09SEwan Crawford size_t num_bytes = sizeof(AllocationDetails::FileHeader); 268563e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - writing File Header, 0x%" PRIx64 " bytes", __FUNCTION__, 2686b9c1b51eSKate Stone (uint64_t)num_bytes); 268726e52a70SEwan Crawford 26882fce1137SLawrence D'Anna Status err = file.get()->Write(&head, num_bytes); 2689b9c1b51eSKate Stone if (!err.Success()) { 269080af0b9eSLuke Drummond strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), path); 269126e52a70SEwan Crawford strm.EOL(); 269226e52a70SEwan Crawford return false; 269326e52a70SEwan Crawford } 269426e52a70SEwan Crawford 269526e52a70SEwan Crawford // Create the headers describing the element type of the allocation. 2696b9c1b51eSKate Stone std::shared_ptr<uint8_t> element_header_buffer( 2697b9c1b51eSKate Stone new uint8_t[element_header_size]); 2698b9c1b51eSKate Stone if (element_header_buffer == nullptr) { 2699b9c1b51eSKate Stone strm.Printf("Internal Error: Couldn't allocate %" PRIu64 2700b9c1b51eSKate Stone " bytes on the heap", 2701b9c1b51eSKate Stone (uint64_t)element_header_size); 270226e52a70SEwan Crawford strm.EOL(); 270326e52a70SEwan Crawford return false; 270426e52a70SEwan Crawford } 270526e52a70SEwan Crawford 270626e52a70SEwan Crawford PopulateElementHeaders(element_header_buffer, 0, alloc->element); 270726e52a70SEwan Crawford 270826e52a70SEwan Crawford // Write headers for allocation element type to file 270926e52a70SEwan Crawford num_bytes = element_header_size; 271063e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - writing element headers, 0x%" PRIx64 " bytes.", 2711b9c1b51eSKate Stone __FUNCTION__, (uint64_t)num_bytes); 271226e52a70SEwan Crawford 27132fce1137SLawrence D'Anna err = file.get()->Write(element_header_buffer.get(), num_bytes); 2714b9c1b51eSKate Stone if (!err.Success()) { 271580af0b9eSLuke Drummond strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), path); 271655232f09SEwan Crawford strm.EOL(); 271755232f09SEwan Crawford return false; 271855232f09SEwan Crawford } 271955232f09SEwan Crawford 272055232f09SEwan Crawford // Write allocation data to file 272155232f09SEwan Crawford num_bytes = static_cast<size_t>(*alloc->size.get()); 272263e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - writing 0x%" PRIx64 " bytes", __FUNCTION__, 2723b9c1b51eSKate Stone (uint64_t)num_bytes); 272455232f09SEwan Crawford 27252fce1137SLawrence D'Anna err = file.get()->Write(buffer.get(), num_bytes); 2726b9c1b51eSKate Stone if (!err.Success()) { 272780af0b9eSLuke Drummond strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), path); 272855232f09SEwan Crawford strm.EOL(); 272955232f09SEwan Crawford return false; 273055232f09SEwan Crawford } 273155232f09SEwan Crawford 273280af0b9eSLuke Drummond strm.Printf("Allocation written to file '%s'", path); 273355232f09SEwan Crawford strm.EOL(); 273415f2bd95SEwan Crawford return true; 273515f2bd95SEwan Crawford } 273615f2bd95SEwan Crawford 2737b9c1b51eSKate Stone bool RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp) { 2738*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 27394640cde1SColin Riley 2740b9c1b51eSKate Stone if (module_sp) { 2741b9c1b51eSKate Stone for (const auto &rs_module : m_rsmodules) { 2742b9c1b51eSKate Stone if (rs_module->m_module == module_sp) { 274305097246SAdrian Prantl // Check if the user has enabled automatically breaking on all RS 274405097246SAdrian Prantl // kernels. 27457dc7771cSEwan Crawford if (m_breakAllKernels) 27467dc7771cSEwan Crawford BreakOnModuleKernels(rs_module); 27477dc7771cSEwan Crawford 27485ec532a9SColin Riley return false; 27495ec532a9SColin Riley } 27507dc7771cSEwan Crawford } 2751ef20b08fSColin Riley bool module_loaded = false; 2752b9c1b51eSKate Stone switch (GetModuleKind(module_sp)) { 2753b9c1b51eSKate Stone case eModuleKindKernelObj: { 27544640cde1SColin Riley RSModuleDescriptorSP module_desc; 2755796ac80bSJonas Devlieghere module_desc = std::make_shared<RSModuleDescriptor>(module_sp); 2756b9c1b51eSKate Stone if (module_desc->ParseRSInfo()) { 27575ec532a9SColin Riley m_rsmodules.push_back(module_desc); 275847d64161SLuke Drummond module_desc->WarnIfVersionMismatch(GetProcess() 275947d64161SLuke Drummond ->GetTarget() 276047d64161SLuke Drummond .GetDebugger() 276147d64161SLuke Drummond .GetAsyncOutputStream() 276247d64161SLuke Drummond .get()); 2763ef20b08fSColin Riley module_loaded = true; 27645ec532a9SColin Riley } 2765b9c1b51eSKate Stone if (module_loaded) { 27664640cde1SColin Riley FixupScriptDetails(module_desc); 27674640cde1SColin Riley } 2768ef20b08fSColin Riley break; 2769ef20b08fSColin Riley } 2770b9c1b51eSKate Stone case eModuleKindDriver: { 2771b9c1b51eSKate Stone if (!m_libRSDriver) { 27724640cde1SColin Riley m_libRSDriver = module_sp; 27734640cde1SColin Riley LoadRuntimeHooks(m_libRSDriver, RenderScriptRuntime::eModuleKindDriver); 27744640cde1SColin Riley } 27754640cde1SColin Riley break; 27764640cde1SColin Riley } 2777b9c1b51eSKate Stone case eModuleKindImpl: { 277821fed052SAidan Dodds if (!m_libRSCpuRef) { 27794640cde1SColin Riley m_libRSCpuRef = module_sp; 278021fed052SAidan Dodds LoadRuntimeHooks(m_libRSCpuRef, RenderScriptRuntime::eModuleKindImpl); 278121fed052SAidan Dodds } 27824640cde1SColin Riley break; 27834640cde1SColin Riley } 2784b9c1b51eSKate Stone case eModuleKindLibRS: { 2785b9c1b51eSKate Stone if (!m_libRS) { 27864640cde1SColin Riley m_libRS = module_sp; 27874640cde1SColin Riley static ConstString gDbgPresentStr("gDebuggerPresent"); 2788b9c1b51eSKate Stone const Symbol *debug_present = m_libRS->FindFirstSymbolWithNameAndType( 2789b9c1b51eSKate Stone gDbgPresentStr, eSymbolTypeData); 2790b9c1b51eSKate Stone if (debug_present) { 279197206d57SZachary Turner Status err; 27924640cde1SColin Riley uint32_t flag = 0x00000001U; 27934640cde1SColin Riley Target &target = GetProcess()->GetTarget(); 2794358cf1eaSGreg Clayton addr_t addr = debug_present->GetLoadAddress(&target); 279580af0b9eSLuke Drummond GetProcess()->WriteMemory(addr, &flag, sizeof(flag), err); 279680af0b9eSLuke Drummond if (err.Success()) { 279763e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - debugger present flag set on debugee.", 2798b9c1b51eSKate Stone __FUNCTION__); 27994640cde1SColin Riley 28004640cde1SColin Riley m_debuggerPresentFlagged = true; 2801b9c1b51eSKate Stone } else if (log) { 280263e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - error writing debugger present flags '%s' ", 280380af0b9eSLuke Drummond __FUNCTION__, err.AsCString()); 28044640cde1SColin Riley } 2805b9c1b51eSKate Stone } else if (log) { 280663e5fb76SJonas Devlieghere LLDB_LOGF( 280763e5fb76SJonas Devlieghere log, 2808b9c1b51eSKate Stone "%s - error writing debugger present flags - symbol not found", 2809b9c1b51eSKate Stone __FUNCTION__); 28104640cde1SColin Riley } 28114640cde1SColin Riley } 28124640cde1SColin Riley break; 28134640cde1SColin Riley } 2814ef20b08fSColin Riley default: 2815ef20b08fSColin Riley break; 2816ef20b08fSColin Riley } 2817ef20b08fSColin Riley if (module_loaded) 2818ef20b08fSColin Riley Update(); 2819ef20b08fSColin Riley return module_loaded; 28205ec532a9SColin Riley } 28215ec532a9SColin Riley return false; 28225ec532a9SColin Riley } 28235ec532a9SColin Riley 2824b9c1b51eSKate Stone void RenderScriptRuntime::Update() { 2825b9c1b51eSKate Stone if (m_rsmodules.size() > 0) { 2826b9c1b51eSKate Stone if (!m_initiated) { 2827ef20b08fSColin Riley Initiate(); 2828ef20b08fSColin Riley } 2829ef20b08fSColin Riley } 2830ef20b08fSColin Riley } 2831ef20b08fSColin Riley 283247d64161SLuke Drummond void RSModuleDescriptor::WarnIfVersionMismatch(lldb_private::Stream *s) const { 283347d64161SLuke Drummond if (!s) 283447d64161SLuke Drummond return; 283547d64161SLuke Drummond 283647d64161SLuke Drummond if (m_slang_version.empty() || m_bcc_version.empty()) { 283747d64161SLuke Drummond s->PutCString("WARNING: Unknown bcc or slang (llvm-rs-cc) version; debug " 283847d64161SLuke Drummond "experience may be unreliable"); 283947d64161SLuke Drummond s->EOL(); 284047d64161SLuke Drummond } else if (m_slang_version != m_bcc_version) { 284147d64161SLuke Drummond s->Printf("WARNING: The debug info emitted by the slang frontend " 284247d64161SLuke Drummond "(llvm-rs-cc) used to build this module (%s) does not match the " 284347d64161SLuke Drummond "version of bcc used to generate the debug information (%s). " 284447d64161SLuke Drummond "This is an unsupported configuration and may result in a poor " 284547d64161SLuke Drummond "debugging experience; proceed with caution", 284647d64161SLuke Drummond m_slang_version.c_str(), m_bcc_version.c_str()); 284747d64161SLuke Drummond s->EOL(); 284847d64161SLuke Drummond } 284947d64161SLuke Drummond } 285047d64161SLuke Drummond 28517f193d69SLuke Drummond bool RSModuleDescriptor::ParsePragmaCount(llvm::StringRef *lines, 28527f193d69SLuke Drummond size_t n_lines) { 28537f193d69SLuke Drummond // Skip the pragma prototype line 28547f193d69SLuke Drummond ++lines; 28557f193d69SLuke Drummond for (; n_lines--; ++lines) { 28567f193d69SLuke Drummond const auto kv_pair = lines->split(" - "); 28577f193d69SLuke Drummond m_pragmas[kv_pair.first.trim().str()] = kv_pair.second.trim().str(); 28587f193d69SLuke Drummond } 28597f193d69SLuke Drummond return true; 28607f193d69SLuke Drummond } 28617f193d69SLuke Drummond 28627f193d69SLuke Drummond bool RSModuleDescriptor::ParseExportReduceCount(llvm::StringRef *lines, 28637f193d69SLuke Drummond size_t n_lines) { 28647f193d69SLuke Drummond // The list of reduction kernels in the `.rs.info` symbol is of the form 28657f193d69SLuke Drummond // "signature - accumulatordatasize - reduction_name - initializer_name - 286605097246SAdrian Prantl // accumulator_name - combiner_name - outconverter_name - halter_name" Where 286705097246SAdrian Prantl // a function is not explicitly named by the user, or is not generated by the 286805097246SAdrian Prantl // compiler, it is named "." so the dash separated list should always be 8 286905097246SAdrian Prantl // items long 2870*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 28717f193d69SLuke Drummond // Skip the exportReduceCount line 28727f193d69SLuke Drummond ++lines; 28737f193d69SLuke Drummond for (; n_lines--; ++lines) { 28747f193d69SLuke Drummond llvm::SmallVector<llvm::StringRef, 8> spec; 28757f193d69SLuke Drummond lines->split(spec, " - "); 28767f193d69SLuke Drummond if (spec.size() != 8) { 28777f193d69SLuke Drummond if (spec.size() < 8) { 28787f193d69SLuke Drummond if (log) 28797f193d69SLuke Drummond log->Error("Error parsing RenderScript reduction spec. wrong number " 28807f193d69SLuke Drummond "of fields"); 28817f193d69SLuke Drummond return false; 28827f193d69SLuke Drummond } else if (log) 28837f193d69SLuke Drummond log->Warning("Extraneous members in reduction spec: '%s'", 28847f193d69SLuke Drummond lines->str().c_str()); 28857f193d69SLuke Drummond } 28867f193d69SLuke Drummond 28877f193d69SLuke Drummond const auto sig_s = spec[0]; 28887f193d69SLuke Drummond uint32_t sig; 28897f193d69SLuke Drummond if (sig_s.getAsInteger(10, sig)) { 28907f193d69SLuke Drummond if (log) 28917f193d69SLuke Drummond log->Error("Error parsing Renderscript reduction spec: invalid kernel " 28927f193d69SLuke Drummond "signature: '%s'", 28937f193d69SLuke Drummond sig_s.str().c_str()); 28947f193d69SLuke Drummond return false; 28957f193d69SLuke Drummond } 28967f193d69SLuke Drummond 28977f193d69SLuke Drummond const auto accum_data_size_s = spec[1]; 28987f193d69SLuke Drummond uint32_t accum_data_size; 28997f193d69SLuke Drummond if (accum_data_size_s.getAsInteger(10, accum_data_size)) { 29007f193d69SLuke Drummond if (log) 29017f193d69SLuke Drummond log->Error("Error parsing Renderscript reduction spec: invalid " 29027f193d69SLuke Drummond "accumulator data size %s", 29037f193d69SLuke Drummond accum_data_size_s.str().c_str()); 29047f193d69SLuke Drummond return false; 29057f193d69SLuke Drummond } 29067f193d69SLuke Drummond 290763e5fb76SJonas Devlieghere LLDB_LOGF(log, "Found RenderScript reduction '%s'", spec[2].str().c_str()); 29087f193d69SLuke Drummond 29097f193d69SLuke Drummond m_reductions.push_back(RSReductionDescriptor(this, sig, accum_data_size, 29107f193d69SLuke Drummond spec[2], spec[3], spec[4], 29117f193d69SLuke Drummond spec[5], spec[6], spec[7])); 29127f193d69SLuke Drummond } 29137f193d69SLuke Drummond return true; 29147f193d69SLuke Drummond } 29157f193d69SLuke Drummond 291647d64161SLuke Drummond bool RSModuleDescriptor::ParseVersionInfo(llvm::StringRef *lines, 291747d64161SLuke Drummond size_t n_lines) { 291847d64161SLuke Drummond // Skip the versionInfo line 291947d64161SLuke Drummond ++lines; 292047d64161SLuke Drummond for (; n_lines--; ++lines) { 292147d64161SLuke Drummond // We're only interested in bcc and slang versions, and ignore all other 292247d64161SLuke Drummond // versionInfo lines 292347d64161SLuke Drummond const auto kv_pair = lines->split(" - "); 292447d64161SLuke Drummond if (kv_pair.first == "slang") 292547d64161SLuke Drummond m_slang_version = kv_pair.second.str(); 292647d64161SLuke Drummond else if (kv_pair.first == "bcc") 292747d64161SLuke Drummond m_bcc_version = kv_pair.second.str(); 292847d64161SLuke Drummond } 292947d64161SLuke Drummond return true; 293047d64161SLuke Drummond } 293147d64161SLuke Drummond 29327f193d69SLuke Drummond bool RSModuleDescriptor::ParseExportForeachCount(llvm::StringRef *lines, 29337f193d69SLuke Drummond size_t n_lines) { 29347f193d69SLuke Drummond // Skip the exportForeachCount line 29357f193d69SLuke Drummond ++lines; 29367f193d69SLuke Drummond for (; n_lines--; ++lines) { 29377f193d69SLuke Drummond uint32_t slot; 29387f193d69SLuke Drummond // `forEach` kernels are listed in the `.rs.info` packet as a "slot - name" 29397f193d69SLuke Drummond // pair per line 29407f193d69SLuke Drummond const auto kv_pair = lines->split(" - "); 29417f193d69SLuke Drummond if (kv_pair.first.getAsInteger(10, slot)) 29427f193d69SLuke Drummond return false; 29437f193d69SLuke Drummond m_kernels.push_back(RSKernelDescriptor(this, kv_pair.second, slot)); 29447f193d69SLuke Drummond } 29457f193d69SLuke Drummond return true; 29467f193d69SLuke Drummond } 29477f193d69SLuke Drummond 29487f193d69SLuke Drummond bool RSModuleDescriptor::ParseExportVarCount(llvm::StringRef *lines, 29497f193d69SLuke Drummond size_t n_lines) { 29507f193d69SLuke Drummond // Skip the ExportVarCount line 29517f193d69SLuke Drummond ++lines; 29527f193d69SLuke Drummond for (; n_lines--; ++lines) 29537f193d69SLuke Drummond m_globals.push_back(RSGlobalDescriptor(this, *lines)); 29547f193d69SLuke Drummond return true; 29557f193d69SLuke Drummond } 29565ec532a9SColin Riley 2957b9c1b51eSKate Stone // The .rs.info symbol in renderscript modules contains a string which needs to 295805097246SAdrian Prantl // be parsed. The string is basic and is parsed on a line by line basis. 2959b9c1b51eSKate Stone bool RSModuleDescriptor::ParseRSInfo() { 2960b0be30f7SAidan Dodds assert(m_module); 2961*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 2962b9c1b51eSKate Stone const Symbol *info_sym = m_module->FindFirstSymbolWithNameAndType( 2963b9c1b51eSKate Stone ConstString(".rs.info"), eSymbolTypeData); 2964b0be30f7SAidan Dodds if (!info_sym) 2965b0be30f7SAidan Dodds return false; 2966b0be30f7SAidan Dodds 2967358cf1eaSGreg Clayton const addr_t addr = info_sym->GetAddressRef().GetFileAddress(); 2968b0be30f7SAidan Dodds if (addr == LLDB_INVALID_ADDRESS) 2969b0be30f7SAidan Dodds return false; 2970b0be30f7SAidan Dodds 29715ec532a9SColin Riley const addr_t size = info_sym->GetByteSize(); 29725ec532a9SColin Riley const FileSpec fs = m_module->GetFileSpec(); 29735ec532a9SColin Riley 297487e403aaSJonas Devlieghere auto buffer = 297587e403aaSJonas Devlieghere FileSystem::Instance().CreateDataBuffer(fs.GetPath(), size, addr); 29765ec532a9SColin Riley if (!buffer) 29775ec532a9SColin Riley return false; 29785ec532a9SColin Riley 2979b0be30f7SAidan Dodds // split rs.info. contents into lines 29807f193d69SLuke Drummond llvm::SmallVector<llvm::StringRef, 128> info_lines; 29815ec532a9SColin Riley { 29827f193d69SLuke Drummond const llvm::StringRef raw_rs_info((const char *)buffer->GetBytes()); 29837f193d69SLuke Drummond raw_rs_info.split(info_lines, '\n'); 298463e5fb76SJonas Devlieghere LLDB_LOGF(log, "'.rs.info symbol for '%s':\n%s", 298563e5fb76SJonas Devlieghere m_module->GetFileSpec().GetCString(), raw_rs_info.str().c_str()); 2986b0be30f7SAidan Dodds } 2987b0be30f7SAidan Dodds 29887f193d69SLuke Drummond enum { 29897f193d69SLuke Drummond eExportVar, 29907f193d69SLuke Drummond eExportForEach, 29917f193d69SLuke Drummond eExportReduce, 29927f193d69SLuke Drummond ePragma, 29937f193d69SLuke Drummond eBuildChecksum, 299447d64161SLuke Drummond eObjectSlot, 299547d64161SLuke Drummond eVersionInfo, 29967f193d69SLuke Drummond }; 29977f193d69SLuke Drummond 2998b3bbcb12SLuke Drummond const auto rs_info_handler = [](llvm::StringRef name) -> int { 2999b3bbcb12SLuke Drummond return llvm::StringSwitch<int>(name) 3000b3bbcb12SLuke Drummond // The number of visible global variables in the script 3001b3bbcb12SLuke Drummond .Case("exportVarCount", eExportVar) 30027f193d69SLuke Drummond // The number of RenderScrip `forEach` kernels __attribute__((kernel)) 3003b3bbcb12SLuke Drummond .Case("exportForEachCount", eExportForEach) 3004b3bbcb12SLuke Drummond // The number of generalreductions: This marked in the script by 3005b3bbcb12SLuke Drummond // `#pragma reduce()` 3006b3bbcb12SLuke Drummond .Case("exportReduceCount", eExportReduce) 3007b3bbcb12SLuke Drummond // Total count of all RenderScript specific `#pragmas` used in the 3008b3bbcb12SLuke Drummond // script 3009b3bbcb12SLuke Drummond .Case("pragmaCount", ePragma) 3010b3bbcb12SLuke Drummond .Case("objectSlotCount", eObjectSlot) 301147d64161SLuke Drummond .Case("versionInfo", eVersionInfo) 3012b3bbcb12SLuke Drummond .Default(-1); 3013b3bbcb12SLuke Drummond }; 3014b0be30f7SAidan Dodds 3015b0be30f7SAidan Dodds // parse all text lines of .rs.info 3016b9c1b51eSKate Stone for (auto line = info_lines.begin(); line != info_lines.end(); ++line) { 30177f193d69SLuke Drummond const auto kv_pair = line->split(": "); 30187f193d69SLuke Drummond const auto key = kv_pair.first; 30197f193d69SLuke Drummond const auto val = kv_pair.second.trim(); 30205ec532a9SColin Riley 3021b3bbcb12SLuke Drummond const auto handler = rs_info_handler(key); 3022b3bbcb12SLuke Drummond if (handler == -1) 30237f193d69SLuke Drummond continue; 302405097246SAdrian Prantl // getAsInteger returns `true` on an error condition - we're only 302505097246SAdrian Prantl // interested in numeric fields at the moment 30267f193d69SLuke Drummond uint64_t n_lines; 30277f193d69SLuke Drummond if (val.getAsInteger(10, n_lines)) { 30286302bf6aSPavel Labath LLDB_LOGV(log, "Failed to parse non-numeric '.rs.info' section {0}", 30296302bf6aSPavel Labath line->str()); 30307f193d69SLuke Drummond continue; 30317f193d69SLuke Drummond } 30327f193d69SLuke Drummond if (info_lines.end() - (line + 1) < (ptrdiff_t)n_lines) 30337f193d69SLuke Drummond return false; 30347f193d69SLuke Drummond 30357f193d69SLuke Drummond bool success = false; 3036b3bbcb12SLuke Drummond switch (handler) { 30377f193d69SLuke Drummond case eExportVar: 30387f193d69SLuke Drummond success = ParseExportVarCount(line, n_lines); 30397f193d69SLuke Drummond break; 30407f193d69SLuke Drummond case eExportForEach: 30417f193d69SLuke Drummond success = ParseExportForeachCount(line, n_lines); 30427f193d69SLuke Drummond break; 30437f193d69SLuke Drummond case eExportReduce: 30447f193d69SLuke Drummond success = ParseExportReduceCount(line, n_lines); 30457f193d69SLuke Drummond break; 30467f193d69SLuke Drummond case ePragma: 30477f193d69SLuke Drummond success = ParsePragmaCount(line, n_lines); 30487f193d69SLuke Drummond break; 304947d64161SLuke Drummond case eVersionInfo: 305047d64161SLuke Drummond success = ParseVersionInfo(line, n_lines); 305147d64161SLuke Drummond break; 30527f193d69SLuke Drummond default: { 305363e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - skipping .rs.info field '%s'", __FUNCTION__, 30547f193d69SLuke Drummond line->str().c_str()); 30557f193d69SLuke Drummond continue; 30567f193d69SLuke Drummond } 30577f193d69SLuke Drummond } 30587f193d69SLuke Drummond if (!success) 30597f193d69SLuke Drummond return false; 30607f193d69SLuke Drummond line += n_lines; 30617f193d69SLuke Drummond } 30627f193d69SLuke Drummond return info_lines.size() > 0; 30635ec532a9SColin Riley } 30645ec532a9SColin Riley 306597206d57SZachary Turner void RenderScriptRuntime::DumpStatus(Stream &strm) const { 3066b9c1b51eSKate Stone if (m_libRS) { 30674640cde1SColin Riley strm.Printf("Runtime Library discovered."); 30684640cde1SColin Riley strm.EOL(); 30694640cde1SColin Riley } 3070b9c1b51eSKate Stone if (m_libRSDriver) { 30714640cde1SColin Riley strm.Printf("Runtime Driver discovered."); 30724640cde1SColin Riley strm.EOL(); 30734640cde1SColin Riley } 3074b9c1b51eSKate Stone if (m_libRSCpuRef) { 30754640cde1SColin Riley strm.Printf("CPU Reference Implementation discovered."); 30764640cde1SColin Riley strm.EOL(); 30774640cde1SColin Riley } 30784640cde1SColin Riley 3079b9c1b51eSKate Stone if (m_runtimeHooks.size()) { 30804640cde1SColin Riley strm.Printf("Runtime functions hooked:"); 30814640cde1SColin Riley strm.EOL(); 3082b9c1b51eSKate Stone for (auto b : m_runtimeHooks) { 30834640cde1SColin Riley strm.Indent(b.second->defn->name); 30844640cde1SColin Riley strm.EOL(); 30854640cde1SColin Riley } 3086b9c1b51eSKate Stone } else { 30874640cde1SColin Riley strm.Printf("Runtime is not hooked."); 30884640cde1SColin Riley strm.EOL(); 30894640cde1SColin Riley } 30904640cde1SColin Riley } 30914640cde1SColin Riley 3092b9c1b51eSKate Stone void RenderScriptRuntime::DumpContexts(Stream &strm) const { 30934640cde1SColin Riley strm.Printf("Inferred RenderScript Contexts:"); 30944640cde1SColin Riley strm.EOL(); 30954640cde1SColin Riley strm.IndentMore(); 30964640cde1SColin Riley 30974640cde1SColin Riley std::map<addr_t, uint64_t> contextReferences; 30984640cde1SColin Riley 309905097246SAdrian Prantl // Iterate over all of the currently discovered scripts. Note: We cant push 310005097246SAdrian Prantl // or pop from m_scripts inside this loop or it may invalidate script. 3101b9c1b51eSKate Stone for (const auto &script : m_scripts) { 310278f339d1SEwan Crawford if (!script->context.isValid()) 310378f339d1SEwan Crawford continue; 310478f339d1SEwan Crawford lldb::addr_t context = *script->context; 310578f339d1SEwan Crawford 3106b9c1b51eSKate Stone if (contextReferences.find(context) != contextReferences.end()) { 310778f339d1SEwan Crawford contextReferences[context]++; 3108b9c1b51eSKate Stone } else { 310978f339d1SEwan Crawford contextReferences[context] = 1; 31104640cde1SColin Riley } 31114640cde1SColin Riley } 31124640cde1SColin Riley 3113b9c1b51eSKate Stone for (const auto &cRef : contextReferences) { 3114b9c1b51eSKate Stone strm.Printf("Context 0x%" PRIx64 ": %" PRIu64 " script instances", 3115b9c1b51eSKate Stone cRef.first, cRef.second); 31164640cde1SColin Riley strm.EOL(); 31174640cde1SColin Riley } 31184640cde1SColin Riley strm.IndentLess(); 31194640cde1SColin Riley } 31204640cde1SColin Riley 3121b9c1b51eSKate Stone void RenderScriptRuntime::DumpKernels(Stream &strm) const { 31224640cde1SColin Riley strm.Printf("RenderScript Kernels:"); 31234640cde1SColin Riley strm.EOL(); 31244640cde1SColin Riley strm.IndentMore(); 3125b9c1b51eSKate Stone for (const auto &module : m_rsmodules) { 31264640cde1SColin Riley strm.Printf("Resource '%s':", module->m_resname.c_str()); 31274640cde1SColin Riley strm.EOL(); 3128b9c1b51eSKate Stone for (const auto &kernel : module->m_kernels) { 31299dfd4e26SRaphael Isemann strm.Indent(kernel.m_name.GetStringRef()); 31304640cde1SColin Riley strm.EOL(); 31314640cde1SColin Riley } 31324640cde1SColin Riley } 31334640cde1SColin Riley strm.IndentLess(); 31344640cde1SColin Riley } 31354640cde1SColin Riley 3136a0f08674SEwan Crawford RenderScriptRuntime::AllocationDetails * 3137b9c1b51eSKate Stone RenderScriptRuntime::FindAllocByID(Stream &strm, const uint32_t alloc_id) { 3138a0f08674SEwan Crawford AllocationDetails *alloc = nullptr; 3139a0f08674SEwan Crawford 3140a0f08674SEwan Crawford // See if we can find allocation using id as an index; 3141b9c1b51eSKate Stone if (alloc_id <= m_allocations.size() && alloc_id != 0 && 3142b9c1b51eSKate Stone m_allocations[alloc_id - 1]->id == alloc_id) { 3143a0f08674SEwan Crawford alloc = m_allocations[alloc_id - 1].get(); 3144a0f08674SEwan Crawford return alloc; 3145a0f08674SEwan Crawford } 3146a0f08674SEwan Crawford 3147a0f08674SEwan Crawford // Fallback to searching 3148b9c1b51eSKate Stone for (const auto &a : m_allocations) { 3149b9c1b51eSKate Stone if (a->id == alloc_id) { 3150a0f08674SEwan Crawford alloc = a.get(); 3151a0f08674SEwan Crawford break; 3152a0f08674SEwan Crawford } 3153a0f08674SEwan Crawford } 3154a0f08674SEwan Crawford 3155b9c1b51eSKate Stone if (alloc == nullptr) { 3156b9c1b51eSKate Stone strm.Printf("Error: Couldn't find allocation with id matching %" PRIu32, 3157b9c1b51eSKate Stone alloc_id); 3158a0f08674SEwan Crawford strm.EOL(); 3159a0f08674SEwan Crawford } 3160a0f08674SEwan Crawford 3161a0f08674SEwan Crawford return alloc; 3162a0f08674SEwan Crawford } 3163a0f08674SEwan Crawford 3164b9c1b51eSKate Stone // Prints the contents of an allocation to the output stream, which may be a 3165b9c1b51eSKate Stone // file 3166b9c1b51eSKate Stone bool RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame *frame_ptr, 3167b9c1b51eSKate Stone const uint32_t id) { 3168*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 3169a0f08674SEwan Crawford 3170a0f08674SEwan Crawford // Check we can find the desired allocation 3171a0f08674SEwan Crawford AllocationDetails *alloc = FindAllocByID(strm, id); 3172a0f08674SEwan Crawford if (!alloc) 3173a0f08674SEwan Crawford return false; // FindAllocByID() will print error message for us here 3174a0f08674SEwan Crawford 317563e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - found allocation 0x%" PRIx64, __FUNCTION__, 3176b9c1b51eSKate Stone *alloc->address.get()); 3177a0f08674SEwan Crawford 3178a0f08674SEwan Crawford // Check we have information about the allocation, if not calculate it 317980af0b9eSLuke Drummond if (alloc->ShouldRefresh()) { 318063e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - allocation details not calculated yet, jitting info.", 3181b9c1b51eSKate Stone __FUNCTION__); 3182a0f08674SEwan Crawford 3183a0f08674SEwan Crawford // JIT all the allocation information 3184b9c1b51eSKate Stone if (!RefreshAllocation(alloc, frame_ptr)) { 3185a0f08674SEwan Crawford strm.Printf("Error: Couldn't JIT allocation details"); 3186a0f08674SEwan Crawford strm.EOL(); 3187a0f08674SEwan Crawford return false; 3188a0f08674SEwan Crawford } 3189a0f08674SEwan Crawford } 3190a0f08674SEwan Crawford 3191a0f08674SEwan Crawford // Establish format and size of each data element 3192b3f7f69dSAidan Dodds const uint32_t vec_size = *alloc->element.type_vec_size.get(); 31938b244e21SEwan Crawford const Element::DataType type = *alloc->element.type.get(); 3194a0f08674SEwan Crawford 3195b9c1b51eSKate Stone assert(type >= Element::RS_TYPE_NONE && type <= Element::RS_TYPE_FONT && 3196b9c1b51eSKate Stone "Invalid allocation type"); 3197a0f08674SEwan Crawford 31982e920715SEwan Crawford lldb::Format format; 31992e920715SEwan Crawford if (type >= Element::RS_TYPE_ELEMENT) 32002e920715SEwan Crawford format = eFormatHex; 32012e920715SEwan Crawford else 3202b9c1b51eSKate Stone format = vec_size == 1 3203b9c1b51eSKate Stone ? static_cast<lldb::Format>( 3204b9c1b51eSKate Stone AllocationDetails::RSTypeToFormat[type][eFormatSingle]) 3205b9c1b51eSKate Stone : static_cast<lldb::Format>( 3206b9c1b51eSKate Stone AllocationDetails::RSTypeToFormat[type][eFormatVector]); 3207a0f08674SEwan Crawford 3208b3f7f69dSAidan Dodds const uint32_t data_size = *alloc->element.datum_size.get(); 3209a0f08674SEwan Crawford 321063e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - element size %" PRIu32 " bytes, including padding", 3211b9c1b51eSKate Stone __FUNCTION__, data_size); 3212a0f08674SEwan Crawford 321355232f09SEwan Crawford // Allocate a buffer to copy data into 321455232f09SEwan Crawford std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr); 3215b9c1b51eSKate Stone if (!buffer) { 32162e920715SEwan Crawford strm.Printf("Error: Couldn't read allocation data"); 321755232f09SEwan Crawford strm.EOL(); 321855232f09SEwan Crawford return false; 321955232f09SEwan Crawford } 322055232f09SEwan Crawford 3221a0f08674SEwan Crawford // Calculate stride between rows as there may be padding at end of rows since 3222a0f08674SEwan Crawford // allocated memory is 16-byte aligned 3223b9c1b51eSKate Stone if (!alloc->stride.isValid()) { 3224a0f08674SEwan Crawford if (alloc->dimension.get()->dim_2 == 0) // We only have one dimension 3225a0f08674SEwan Crawford alloc->stride = 0; 3226b9c1b51eSKate Stone else if (!JITAllocationStride(alloc, frame_ptr)) { 3227a0f08674SEwan Crawford strm.Printf("Error: Couldn't calculate allocation row stride"); 3228a0f08674SEwan Crawford strm.EOL(); 3229a0f08674SEwan Crawford return false; 3230a0f08674SEwan Crawford } 3231a0f08674SEwan Crawford } 3232b3f7f69dSAidan Dodds const uint32_t stride = *alloc->stride.get(); 3233b3f7f69dSAidan Dodds const uint32_t size = *alloc->size.get(); // Size of whole allocation 3234b9c1b51eSKate Stone const uint32_t padding = 3235b9c1b51eSKate Stone alloc->element.padding.isValid() ? *alloc->element.padding.get() : 0; 323663e5fb76SJonas Devlieghere LLDB_LOGF(log, 323763e5fb76SJonas Devlieghere "%s - stride %" PRIu32 " bytes, size %" PRIu32 3238b9c1b51eSKate Stone " bytes, padding %" PRIu32, 3239b3f7f69dSAidan Dodds __FUNCTION__, stride, size, padding); 3240a0f08674SEwan Crawford 3241a0f08674SEwan Crawford // Find dimensions used to index loops, so need to be non-zero 3242b3f7f69dSAidan Dodds uint32_t dim_x = alloc->dimension.get()->dim_1; 3243a0f08674SEwan Crawford dim_x = dim_x == 0 ? 1 : dim_x; 3244a0f08674SEwan Crawford 3245b3f7f69dSAidan Dodds uint32_t dim_y = alloc->dimension.get()->dim_2; 3246a0f08674SEwan Crawford dim_y = dim_y == 0 ? 1 : dim_y; 3247a0f08674SEwan Crawford 3248b3f7f69dSAidan Dodds uint32_t dim_z = alloc->dimension.get()->dim_3; 3249a0f08674SEwan Crawford dim_z = dim_z == 0 ? 1 : dim_z; 3250a0f08674SEwan Crawford 325155232f09SEwan Crawford // Use data extractor to format output 325280af0b9eSLuke Drummond const uint32_t target_ptr_size = 3253b9c1b51eSKate Stone GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize(); 3254b9c1b51eSKate Stone DataExtractor alloc_data(buffer.get(), size, GetProcess()->GetByteOrder(), 325580af0b9eSLuke Drummond target_ptr_size); 325655232f09SEwan Crawford 3257b3f7f69dSAidan Dodds uint32_t offset = 0; // Offset in buffer to next element to be printed 3258b3f7f69dSAidan Dodds uint32_t prev_row = 0; // Offset to the start of the previous row 3259a0f08674SEwan Crawford 3260a0f08674SEwan Crawford // Iterate over allocation dimensions, printing results to user 3261a0f08674SEwan Crawford strm.Printf("Data (X, Y, Z):"); 3262b9c1b51eSKate Stone for (uint32_t z = 0; z < dim_z; ++z) { 3263b9c1b51eSKate Stone for (uint32_t y = 0; y < dim_y; ++y) { 3264a0f08674SEwan Crawford // Use stride to index start of next row. 3265a0f08674SEwan Crawford if (!(y == 0 && z == 0)) 3266a0f08674SEwan Crawford offset = prev_row + stride; 3267a0f08674SEwan Crawford prev_row = offset; 3268a0f08674SEwan Crawford 3269a0f08674SEwan Crawford // Print each element in the row individually 3270b9c1b51eSKate Stone for (uint32_t x = 0; x < dim_x; ++x) { 3271b3f7f69dSAidan Dodds strm.Printf("\n(%" PRIu32 ", %" PRIu32 ", %" PRIu32 ") = ", x, y, z); 3272b9c1b51eSKate Stone if ((type == Element::RS_TYPE_NONE) && 3273b9c1b51eSKate Stone (alloc->element.children.size() > 0) && 3274b9c1b51eSKate Stone (alloc->element.type_name != Element::GetFallbackStructName())) { 327505097246SAdrian Prantl // Here we are dumping an Element of struct type. This is done using 327605097246SAdrian Prantl // expression evaluation with the name of the struct type and pointer 327705097246SAdrian Prantl // to element. Don't print the name of the resulting expression, 327805097246SAdrian Prantl // since this will be '$[0-9]+' 32798b244e21SEwan Crawford DumpValueObjectOptions expr_options; 32808b244e21SEwan Crawford expr_options.SetHideName(true); 32818b244e21SEwan Crawford 32824ebdee0aSBruce Mitchener // Setup expression as dereferencing a pointer cast to element 328305097246SAdrian Prantl // address. 3284ea0636b5SEwan Crawford char expr_char_buffer[jit_max_expr_size]; 328580af0b9eSLuke Drummond int written = 3286b9c1b51eSKate Stone snprintf(expr_char_buffer, jit_max_expr_size, "*(%s*) 0x%" PRIx64, 3287b9c1b51eSKate Stone alloc->element.type_name.AsCString(), 3288b9c1b51eSKate Stone *alloc->data_ptr.get() + offset); 32898b244e21SEwan Crawford 329080af0b9eSLuke Drummond if (written < 0 || written >= jit_max_expr_size) { 329163e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - error in snprintf().", __FUNCTION__); 32928b244e21SEwan Crawford continue; 32938b244e21SEwan Crawford } 32948b244e21SEwan Crawford 32958b244e21SEwan Crawford // Evaluate expression 32968b244e21SEwan Crawford ValueObjectSP expr_result; 3297b9c1b51eSKate Stone GetProcess()->GetTarget().EvaluateExpression(expr_char_buffer, 3298b9c1b51eSKate Stone frame_ptr, expr_result); 32998b244e21SEwan Crawford 33008b244e21SEwan Crawford // Print the results to our stream. 33018b244e21SEwan Crawford expr_result->Dump(strm, expr_options); 3302b9c1b51eSKate Stone } else { 330329cb868aSZachary Turner DumpDataExtractor(alloc_data, &strm, offset, format, 330429cb868aSZachary Turner data_size - padding, 1, 1, LLDB_INVALID_ADDRESS, 0, 330529cb868aSZachary Turner 0); 33068b244e21SEwan Crawford } 33078b244e21SEwan Crawford offset += data_size; 3308a0f08674SEwan Crawford } 3309a0f08674SEwan Crawford } 3310a0f08674SEwan Crawford } 3311a0f08674SEwan Crawford strm.EOL(); 3312a0f08674SEwan Crawford 3313a0f08674SEwan Crawford return true; 3314a0f08674SEwan Crawford } 3315a0f08674SEwan Crawford 331605097246SAdrian Prantl // Function recalculates all our cached information about allocations by 331705097246SAdrian Prantl // jitting the RS runtime regarding each allocation we know about. Returns true 331805097246SAdrian Prantl // if all allocations could be recomputed, false otherwise. 3319b9c1b51eSKate Stone bool RenderScriptRuntime::RecomputeAllAllocations(Stream &strm, 3320b9c1b51eSKate Stone StackFrame *frame_ptr) { 33210d2bfcfbSEwan Crawford bool success = true; 3322b9c1b51eSKate Stone for (auto &alloc : m_allocations) { 33230d2bfcfbSEwan Crawford // JIT current allocation information 3324b9c1b51eSKate Stone if (!RefreshAllocation(alloc.get(), frame_ptr)) { 3325b9c1b51eSKate Stone strm.Printf("Error: Couldn't evaluate details for allocation %" PRIu32 3326b9c1b51eSKate Stone "\n", 3327b9c1b51eSKate Stone alloc->id); 33280d2bfcfbSEwan Crawford success = false; 33290d2bfcfbSEwan Crawford } 33300d2bfcfbSEwan Crawford } 33310d2bfcfbSEwan Crawford 33320d2bfcfbSEwan Crawford if (success) 33330d2bfcfbSEwan Crawford strm.Printf("All allocations successfully recomputed"); 33340d2bfcfbSEwan Crawford strm.EOL(); 33350d2bfcfbSEwan Crawford 33360d2bfcfbSEwan Crawford return success; 33370d2bfcfbSEwan Crawford } 33380d2bfcfbSEwan Crawford 333980af0b9eSLuke Drummond // Prints information regarding currently loaded allocations. These details are 334080af0b9eSLuke Drummond // gathered by jitting the runtime, which has as latency. Index parameter 334180af0b9eSLuke Drummond // specifies a single allocation ID to print, or a zero value to print them all 3342b9c1b51eSKate Stone void RenderScriptRuntime::ListAllocations(Stream &strm, StackFrame *frame_ptr, 3343b9c1b51eSKate Stone const uint32_t index) { 334415f2bd95SEwan Crawford strm.Printf("RenderScript Allocations:"); 334515f2bd95SEwan Crawford strm.EOL(); 334615f2bd95SEwan Crawford strm.IndentMore(); 334715f2bd95SEwan Crawford 3348b9c1b51eSKate Stone for (auto &alloc : m_allocations) { 3349b649b005SEwan Crawford // index will only be zero if we want to print all allocations 3350b649b005SEwan Crawford if (index != 0 && index != alloc->id) 3351b649b005SEwan Crawford continue; 335215f2bd95SEwan Crawford 335315f2bd95SEwan Crawford // JIT current allocation information 335480af0b9eSLuke Drummond if (alloc->ShouldRefresh() && !RefreshAllocation(alloc.get(), frame_ptr)) { 3355b9c1b51eSKate Stone strm.Printf("Error: Couldn't evaluate details for allocation %" PRIu32, 3356b9c1b51eSKate Stone alloc->id); 3357b3f7f69dSAidan Dodds strm.EOL(); 335815f2bd95SEwan Crawford continue; 335915f2bd95SEwan Crawford } 336015f2bd95SEwan Crawford 3361b3f7f69dSAidan Dodds strm.Printf("%" PRIu32 ":", alloc->id); 3362b3f7f69dSAidan Dodds strm.EOL(); 336315f2bd95SEwan Crawford strm.IndentMore(); 336415f2bd95SEwan Crawford 336515f2bd95SEwan Crawford strm.Indent("Context: "); 336615f2bd95SEwan Crawford if (!alloc->context.isValid()) 336715f2bd95SEwan Crawford strm.Printf("unknown\n"); 336815f2bd95SEwan Crawford else 336915f2bd95SEwan Crawford strm.Printf("0x%" PRIx64 "\n", *alloc->context.get()); 337015f2bd95SEwan Crawford 337115f2bd95SEwan Crawford strm.Indent("Address: "); 337215f2bd95SEwan Crawford if (!alloc->address.isValid()) 337315f2bd95SEwan Crawford strm.Printf("unknown\n"); 337415f2bd95SEwan Crawford else 337515f2bd95SEwan Crawford strm.Printf("0x%" PRIx64 "\n", *alloc->address.get()); 337615f2bd95SEwan Crawford 337715f2bd95SEwan Crawford strm.Indent("Data pointer: "); 337815f2bd95SEwan Crawford if (!alloc->data_ptr.isValid()) 337915f2bd95SEwan Crawford strm.Printf("unknown\n"); 338015f2bd95SEwan Crawford else 338115f2bd95SEwan Crawford strm.Printf("0x%" PRIx64 "\n", *alloc->data_ptr.get()); 338215f2bd95SEwan Crawford 338315f2bd95SEwan Crawford strm.Indent("Dimensions: "); 338415f2bd95SEwan Crawford if (!alloc->dimension.isValid()) 338515f2bd95SEwan Crawford strm.Printf("unknown\n"); 338615f2bd95SEwan Crawford else 3387b3f7f69dSAidan Dodds strm.Printf("(%" PRId32 ", %" PRId32 ", %" PRId32 ")\n", 3388b9c1b51eSKate Stone alloc->dimension.get()->dim_1, alloc->dimension.get()->dim_2, 3389b9c1b51eSKate Stone alloc->dimension.get()->dim_3); 339015f2bd95SEwan Crawford 339115f2bd95SEwan Crawford strm.Indent("Data Type: "); 3392b9c1b51eSKate Stone if (!alloc->element.type.isValid() || 3393b9c1b51eSKate Stone !alloc->element.type_vec_size.isValid()) 339415f2bd95SEwan Crawford strm.Printf("unknown\n"); 3395b9c1b51eSKate Stone else { 33968b244e21SEwan Crawford const int vector_size = *alloc->element.type_vec_size.get(); 33972e920715SEwan Crawford Element::DataType type = *alloc->element.type.get(); 339815f2bd95SEwan Crawford 33998b244e21SEwan Crawford if (!alloc->element.type_name.IsEmpty()) 34008b244e21SEwan Crawford strm.Printf("%s\n", alloc->element.type_name.AsCString()); 3401b9c1b51eSKate Stone else { 3402b9c1b51eSKate Stone // Enum value isn't monotonous, so doesn't always index 3403b9c1b51eSKate Stone // RsDataTypeToString array 34042e920715SEwan Crawford if (type >= Element::RS_TYPE_ELEMENT && type <= Element::RS_TYPE_FONT) 3405b9c1b51eSKate Stone type = 3406b9c1b51eSKate Stone static_cast<Element::DataType>((type - Element::RS_TYPE_ELEMENT) + 3407b3f7f69dSAidan Dodds Element::RS_TYPE_MATRIX_2X2 + 1); 34082e920715SEwan Crawford 3409b3f7f69dSAidan Dodds if (type >= (sizeof(AllocationDetails::RsDataTypeToString) / 3410b3f7f69dSAidan Dodds sizeof(AllocationDetails::RsDataTypeToString[0])) || 3411b3f7f69dSAidan Dodds vector_size > 4 || vector_size < 1) 341215f2bd95SEwan Crawford strm.Printf("invalid type\n"); 341315f2bd95SEwan Crawford else 3414b9c1b51eSKate Stone strm.Printf( 3415b9c1b51eSKate Stone "%s\n", 3416b9c1b51eSKate Stone AllocationDetails::RsDataTypeToString[static_cast<uint32_t>(type)] 3417b3f7f69dSAidan Dodds [vector_size - 1]); 341815f2bd95SEwan Crawford } 34192e920715SEwan Crawford } 342015f2bd95SEwan Crawford 342115f2bd95SEwan Crawford strm.Indent("Data Kind: "); 34228b244e21SEwan Crawford if (!alloc->element.type_kind.isValid()) 342315f2bd95SEwan Crawford strm.Printf("unknown\n"); 3424b9c1b51eSKate Stone else { 34258b244e21SEwan Crawford const Element::DataKind kind = *alloc->element.type_kind.get(); 34268b244e21SEwan Crawford if (kind < Element::RS_KIND_USER || kind > Element::RS_KIND_PIXEL_YUV) 342715f2bd95SEwan Crawford strm.Printf("invalid kind\n"); 342815f2bd95SEwan Crawford else 3429b9c1b51eSKate Stone strm.Printf( 3430b9c1b51eSKate Stone "%s\n", 3431b9c1b51eSKate Stone AllocationDetails::RsDataKindToString[static_cast<uint32_t>(kind)]); 343215f2bd95SEwan Crawford } 343315f2bd95SEwan Crawford 343415f2bd95SEwan Crawford strm.EOL(); 343515f2bd95SEwan Crawford strm.IndentLess(); 343615f2bd95SEwan Crawford } 343715f2bd95SEwan Crawford strm.IndentLess(); 343815f2bd95SEwan Crawford } 343915f2bd95SEwan Crawford 34407dc7771cSEwan Crawford // Set breakpoints on every kernel found in RS module 3441b9c1b51eSKate Stone void RenderScriptRuntime::BreakOnModuleKernels( 3442b9c1b51eSKate Stone const RSModuleDescriptorSP rsmodule_sp) { 3443b9c1b51eSKate Stone for (const auto &kernel : rsmodule_sp->m_kernels) { 34447dc7771cSEwan Crawford // Don't set breakpoint on 'root' kernel 34457dc7771cSEwan Crawford if (strcmp(kernel.m_name.AsCString(), "root") == 0) 34467dc7771cSEwan Crawford continue; 34477dc7771cSEwan Crawford 34487dc7771cSEwan Crawford CreateKernelBreakpoint(kernel.m_name); 34497dc7771cSEwan Crawford } 34507dc7771cSEwan Crawford } 34517dc7771cSEwan Crawford 345280af0b9eSLuke Drummond // Method is internally called by the 'kernel breakpoint all' command to enable 345380af0b9eSLuke Drummond // or disable breaking on all kernels. When do_break is true we want to enable 345480af0b9eSLuke Drummond // this functionality. When do_break is false we want to disable it. 3455b9c1b51eSKate Stone void RenderScriptRuntime::SetBreakAllKernels(bool do_break, TargetSP target) { 3456*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language | LLDBLog::Breakpoints); 34577dc7771cSEwan Crawford 34587dc7771cSEwan Crawford InitSearchFilter(target); 34597dc7771cSEwan Crawford 34607dc7771cSEwan Crawford // Set breakpoints on all the kernels 3461b9c1b51eSKate Stone if (do_break && !m_breakAllKernels) { 34627dc7771cSEwan Crawford m_breakAllKernels = true; 34637dc7771cSEwan Crawford 34647dc7771cSEwan Crawford for (const auto &module : m_rsmodules) 34657dc7771cSEwan Crawford BreakOnModuleKernels(module); 34667dc7771cSEwan Crawford 346763e5fb76SJonas Devlieghere LLDB_LOGF(log, 346863e5fb76SJonas Devlieghere "%s(True) - breakpoints set on all currently loaded kernels.", 3469b9c1b51eSKate Stone __FUNCTION__); 3470b9c1b51eSKate Stone } else if (!do_break && 3471b9c1b51eSKate Stone m_breakAllKernels) // Breakpoints won't be set on any new kernels. 34727dc7771cSEwan Crawford { 34737dc7771cSEwan Crawford m_breakAllKernels = false; 34747dc7771cSEwan Crawford 347563e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s(False) - breakpoints no longer automatically set.", 3476b9c1b51eSKate Stone __FUNCTION__); 34777dc7771cSEwan Crawford } 34787dc7771cSEwan Crawford } 34797dc7771cSEwan Crawford 348005097246SAdrian Prantl // Given the name of a kernel this function creates a breakpoint using our own 348105097246SAdrian Prantl // breakpoint resolver, and returns the Breakpoint shared pointer. 34827dc7771cSEwan Crawford BreakpointSP 34830e4c4821SAdrian Prantl RenderScriptRuntime::CreateKernelBreakpoint(ConstString name) { 3484*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language | LLDBLog::Breakpoints); 34857dc7771cSEwan Crawford 3486b9c1b51eSKate Stone if (!m_filtersp) { 348763e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - error, no breakpoint search filter set.", 348863e5fb76SJonas Devlieghere __FUNCTION__); 34897dc7771cSEwan Crawford return nullptr; 34907dc7771cSEwan Crawford } 34917dc7771cSEwan Crawford 34927dc7771cSEwan Crawford BreakpointResolverSP resolver_sp(new RSBreakpointResolver(nullptr, name)); 3493b842f2ecSJim Ingham Target &target = GetProcess()->GetTarget(); 3494b842f2ecSJim Ingham BreakpointSP bp = target.CreateBreakpoint( 3495b9c1b51eSKate Stone m_filtersp, resolver_sp, false, false, false); 34967dc7771cSEwan Crawford 3497b9c1b51eSKate Stone // Give RS breakpoints a specific name, so the user can manipulate them as a 3498b9c1b51eSKate Stone // group. 349997206d57SZachary Turner Status err; 3500b842f2ecSJim Ingham target.AddNameToBreakpoint(bp, "RenderScriptKernel", err); 3501b842f2ecSJim Ingham if (err.Fail() && log) 350263e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - error setting break name, '%s'.", __FUNCTION__, 3503b3bbcb12SLuke Drummond err.AsCString()); 3504b3bbcb12SLuke Drummond 3505b3bbcb12SLuke Drummond return bp; 3506b3bbcb12SLuke Drummond } 3507b3bbcb12SLuke Drummond 3508b3bbcb12SLuke Drummond BreakpointSP 35090e4c4821SAdrian Prantl RenderScriptRuntime::CreateReductionBreakpoint(ConstString name, 3510b3bbcb12SLuke Drummond int kernel_types) { 3511*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language | LLDBLog::Breakpoints); 3512b3bbcb12SLuke Drummond 3513b3bbcb12SLuke Drummond if (!m_filtersp) { 351463e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - error, no breakpoint search filter set.", 351563e5fb76SJonas Devlieghere __FUNCTION__); 3516b3bbcb12SLuke Drummond return nullptr; 3517b3bbcb12SLuke Drummond } 3518b3bbcb12SLuke Drummond 3519b3bbcb12SLuke Drummond BreakpointResolverSP resolver_sp(new RSReduceBreakpointResolver( 3520b3bbcb12SLuke Drummond nullptr, name, &m_rsmodules, kernel_types)); 3521b842f2ecSJim Ingham Target &target = GetProcess()->GetTarget(); 3522b842f2ecSJim Ingham BreakpointSP bp = target.CreateBreakpoint( 3523b3bbcb12SLuke Drummond m_filtersp, resolver_sp, false, false, false); 3524b3bbcb12SLuke Drummond 3525b3bbcb12SLuke Drummond // Give RS breakpoints a specific name, so the user can manipulate them as a 3526b3bbcb12SLuke Drummond // group. 352797206d57SZachary Turner Status err; 3528b842f2ecSJim Ingham target.AddNameToBreakpoint(bp, "RenderScriptReduction", err); 3529b842f2ecSJim Ingham if (err.Fail() && log) 353063e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - error setting break name, '%s'.", __FUNCTION__, 3531b9c1b51eSKate Stone err.AsCString()); 353254782db7SEwan Crawford 35337dc7771cSEwan Crawford return bp; 35347dc7771cSEwan Crawford } 35357dc7771cSEwan Crawford 3536b9c1b51eSKate Stone // Given an expression for a variable this function tries to calculate the 353780af0b9eSLuke Drummond // variable's value. If this is possible it returns true and sets the uint64_t 353880af0b9eSLuke Drummond // parameter to the variables unsigned value. Otherwise function returns false. 3539b9c1b51eSKate Stone bool RenderScriptRuntime::GetFrameVarAsUnsigned(const StackFrameSP frame_sp, 3540b9c1b51eSKate Stone const char *var_name, 3541b9c1b51eSKate Stone uint64_t &val) { 3542*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 354397206d57SZachary Turner Status err; 3544018f5a7eSEwan Crawford VariableSP var_sp; 3545018f5a7eSEwan Crawford 3546018f5a7eSEwan Crawford // Find variable in stack frame 3547b3f7f69dSAidan Dodds ValueObjectSP value_sp(frame_sp->GetValueForVariableExpressionPath( 3548b3f7f69dSAidan Dodds var_name, eNoDynamicValues, 3549b9c1b51eSKate Stone StackFrame::eExpressionPathOptionCheckPtrVsMember | 3550b9c1b51eSKate Stone StackFrame::eExpressionPathOptionsAllowDirectIVarAccess, 355180af0b9eSLuke Drummond var_sp, err)); 355280af0b9eSLuke Drummond if (!err.Success()) { 355363e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - error, couldn't find '%s' in frame", __FUNCTION__, 3554b9c1b51eSKate Stone var_name); 3555018f5a7eSEwan Crawford return false; 3556018f5a7eSEwan Crawford } 3557018f5a7eSEwan Crawford 3558b3f7f69dSAidan Dodds // Find the uint32_t value for the variable 3559018f5a7eSEwan Crawford bool success = false; 3560018f5a7eSEwan Crawford val = value_sp->GetValueAsUnsigned(0, &success); 3561b9c1b51eSKate Stone if (!success) { 356263e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - error, couldn't parse '%s' as an uint32_t.", 3563b9c1b51eSKate Stone __FUNCTION__, var_name); 3564018f5a7eSEwan Crawford return false; 3565018f5a7eSEwan Crawford } 3566018f5a7eSEwan Crawford 3567018f5a7eSEwan Crawford return true; 3568018f5a7eSEwan Crawford } 3569018f5a7eSEwan Crawford 3570b9c1b51eSKate Stone // Function attempts to find the current coordinate of a kernel invocation by 357180af0b9eSLuke Drummond // investigating the values of frame variables in the .expand function. These 357280af0b9eSLuke Drummond // coordinates are returned via the coord array reference parameter. Returns 357380af0b9eSLuke Drummond // true if the coordinates could be found, and false otherwise. 3574b9c1b51eSKate Stone bool RenderScriptRuntime::GetKernelCoordinate(RSCoordinate &coord, 3575b9c1b51eSKate Stone Thread *thread_ptr) { 357600f56eebSLuke Drummond static const char *const x_expr = "rsIndex"; 357700f56eebSLuke Drummond static const char *const y_expr = "p->current.y"; 357800f56eebSLuke Drummond static const char *const z_expr = "p->current.z"; 35791e05c3bcSGreg Clayton 3580*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 35814f8817c2SEwan Crawford 3582b9c1b51eSKate Stone if (!thread_ptr) { 358363e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - Error, No thread pointer", __FUNCTION__); 35844f8817c2SEwan Crawford 35854f8817c2SEwan Crawford return false; 35864f8817c2SEwan Crawford } 35874f8817c2SEwan Crawford 3588b9c1b51eSKate Stone // Walk the call stack looking for a function whose name has the suffix 358980af0b9eSLuke Drummond // '.expand' and contains the variables we're looking for. 3590b9c1b51eSKate Stone for (uint32_t i = 0; i < thread_ptr->GetStackFrameCount(); ++i) { 35914f8817c2SEwan Crawford if (!thread_ptr->SetSelectedFrameByIndex(i)) 35924f8817c2SEwan Crawford continue; 35934f8817c2SEwan Crawford 35944f8817c2SEwan Crawford StackFrameSP frame_sp = thread_ptr->GetSelectedFrame(); 35954f8817c2SEwan Crawford if (!frame_sp) 35964f8817c2SEwan Crawford continue; 35974f8817c2SEwan Crawford 35984f8817c2SEwan Crawford // Find the function name 3599991e4453SZachary Turner const SymbolContext sym_ctx = 3600991e4453SZachary Turner frame_sp->GetSymbolContext(eSymbolContextFunction); 360100f56eebSLuke Drummond const ConstString func_name = sym_ctx.GetFunctionName(); 360200f56eebSLuke Drummond if (!func_name) 36034f8817c2SEwan Crawford continue; 36044f8817c2SEwan Crawford 360563e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - Inspecting function '%s'", __FUNCTION__, 360600f56eebSLuke Drummond func_name.GetCString()); 36074f8817c2SEwan Crawford 36084f8817c2SEwan Crawford // Check if function name has .expand suffix 360900f56eebSLuke Drummond if (!func_name.GetStringRef().endswith(".expand")) 36104f8817c2SEwan Crawford continue; 36114f8817c2SEwan Crawford 361263e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - Found .expand function '%s'", __FUNCTION__, 361300f56eebSLuke Drummond func_name.GetCString()); 36144f8817c2SEwan Crawford 361505097246SAdrian Prantl // Get values for variables in .expand frame that tell us the current 361605097246SAdrian Prantl // kernel invocation 361700f56eebSLuke Drummond uint64_t x, y, z; 361800f56eebSLuke Drummond bool found = GetFrameVarAsUnsigned(frame_sp, x_expr, x) && 361900f56eebSLuke Drummond GetFrameVarAsUnsigned(frame_sp, y_expr, y) && 362000f56eebSLuke Drummond GetFrameVarAsUnsigned(frame_sp, z_expr, z); 36214f8817c2SEwan Crawford 362200f56eebSLuke Drummond if (found) { 362300f56eebSLuke Drummond // The RenderScript runtime uses uint32_t for these vars. If they're not 362400f56eebSLuke Drummond // within bounds, our frame parsing is garbage 362500f56eebSLuke Drummond assert(x <= UINT32_MAX && y <= UINT32_MAX && z <= UINT32_MAX); 362600f56eebSLuke Drummond coord.x = (uint32_t)x; 362700f56eebSLuke Drummond coord.y = (uint32_t)y; 362800f56eebSLuke Drummond coord.z = (uint32_t)z; 36294f8817c2SEwan Crawford return true; 36304f8817c2SEwan Crawford } 363100f56eebSLuke Drummond } 36324f8817c2SEwan Crawford return false; 36334f8817c2SEwan Crawford } 36344f8817c2SEwan Crawford 3635b9c1b51eSKate Stone // Callback when a kernel breakpoint hits and we're looking for a specific 363680af0b9eSLuke Drummond // coordinate. Baton parameter contains a pointer to the target coordinate we 363705097246SAdrian Prantl // want to break on. Function then checks the .expand frame for the current 363805097246SAdrian Prantl // coordinate and breaks to user if it matches. Parameter 'break_id' is the id 363905097246SAdrian Prantl // of the Breakpoint which made the callback. Parameter 'break_loc_id' is the 364005097246SAdrian Prantl // id for the BreakpointLocation which was hit, a single logical breakpoint can 364105097246SAdrian Prantl // have multiple addresses. 3642b9c1b51eSKate Stone bool RenderScriptRuntime::KernelBreakpointHit(void *baton, 3643b9c1b51eSKate Stone StoppointCallbackContext *ctx, 3644b9c1b51eSKate Stone user_id_t break_id, 3645b9c1b51eSKate Stone user_id_t break_loc_id) { 3646*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language | LLDBLog::Breakpoints); 3647018f5a7eSEwan Crawford 3648b9c1b51eSKate Stone assert(baton && 3649b9c1b51eSKate Stone "Error: null baton in conditional kernel breakpoint callback"); 3650018f5a7eSEwan Crawford 3651018f5a7eSEwan Crawford // Coordinate we want to stop on 365200f56eebSLuke Drummond RSCoordinate target_coord = *static_cast<RSCoordinate *>(baton); 3653018f5a7eSEwan Crawford 365463e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - Break ID %" PRIu64 ", " FMT_COORD, __FUNCTION__, 365563e5fb76SJonas Devlieghere break_id, target_coord.x, target_coord.y, target_coord.z); 3656018f5a7eSEwan Crawford 36574f8817c2SEwan Crawford // Select current thread 3658018f5a7eSEwan Crawford ExecutionContext context(ctx->exe_ctx_ref); 36594f8817c2SEwan Crawford Thread *thread_ptr = context.GetThreadPtr(); 36604f8817c2SEwan Crawford assert(thread_ptr && "Null thread pointer"); 36614f8817c2SEwan Crawford 36624f8817c2SEwan Crawford // Find current kernel invocation from .expand frame variables 366300f56eebSLuke Drummond RSCoordinate current_coord{}; 3664b9c1b51eSKate Stone if (!GetKernelCoordinate(current_coord, thread_ptr)) { 366563e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - Error, couldn't select .expand stack frame", 3666b9c1b51eSKate Stone __FUNCTION__); 3667018f5a7eSEwan Crawford return false; 3668018f5a7eSEwan Crawford } 3669018f5a7eSEwan Crawford 367063e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - " FMT_COORD, __FUNCTION__, current_coord.x, 367100f56eebSLuke Drummond current_coord.y, current_coord.z); 3672018f5a7eSEwan Crawford 3673b9c1b51eSKate Stone // Check if the current kernel invocation coordinate matches our target 3674b9c1b51eSKate Stone // coordinate 367500f56eebSLuke Drummond if (target_coord == current_coord) { 367663e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s, BREAKING " FMT_COORD, __FUNCTION__, current_coord.x, 367700f56eebSLuke Drummond current_coord.y, current_coord.z); 3678018f5a7eSEwan Crawford 3679b9c1b51eSKate Stone BreakpointSP breakpoint_sp = 3680b9c1b51eSKate Stone context.GetTargetPtr()->GetBreakpointByID(break_id); 3681b9c1b51eSKate Stone assert(breakpoint_sp != nullptr && 3682b9c1b51eSKate Stone "Error: Couldn't find breakpoint matching break id for callback"); 3683b9c1b51eSKate Stone breakpoint_sp->SetEnabled(false); // Optimise since conditional breakpoint 3684b9c1b51eSKate Stone // should only be hit once. 3685018f5a7eSEwan Crawford return true; 3686018f5a7eSEwan Crawford } 3687018f5a7eSEwan Crawford 3688018f5a7eSEwan Crawford // No match on coordinate 3689018f5a7eSEwan Crawford return false; 3690018f5a7eSEwan Crawford } 3691018f5a7eSEwan Crawford 369200f56eebSLuke Drummond void RenderScriptRuntime::SetConditional(BreakpointSP bp, Stream &messages, 369300f56eebSLuke Drummond const RSCoordinate &coord) { 369400f56eebSLuke Drummond messages.Printf("Conditional kernel breakpoint on coordinate " FMT_COORD, 369500f56eebSLuke Drummond coord.x, coord.y, coord.z); 369600f56eebSLuke Drummond messages.EOL(); 369700f56eebSLuke Drummond 369800f56eebSLuke Drummond // Allocate memory for the baton, and copy over coordinate 369900f56eebSLuke Drummond RSCoordinate *baton = new RSCoordinate(coord); 370000f56eebSLuke Drummond 370100f56eebSLuke Drummond // Create a callback that will be invoked every time the breakpoint is hit. 370200f56eebSLuke Drummond // The baton object passed to the handler is the target coordinate we want to 370300f56eebSLuke Drummond // break on. 370400f56eebSLuke Drummond bp->SetCallback(KernelBreakpointHit, baton, true); 370500f56eebSLuke Drummond 370600f56eebSLuke Drummond // Store a shared pointer to the baton, so the memory will eventually be 370700f56eebSLuke Drummond // cleaned up after destruction 370800f56eebSLuke Drummond m_conditional_breaks[bp->GetID()] = std::unique_ptr<RSCoordinate>(baton); 370900f56eebSLuke Drummond } 371000f56eebSLuke Drummond 371105097246SAdrian Prantl // Tries to set a breakpoint on the start of a kernel, resolved using the 371205097246SAdrian Prantl // kernel name. Argument 'coords', represents a three dimensional coordinate 371305097246SAdrian Prantl // which can be used to specify a single kernel instance to break on. If this 371405097246SAdrian Prantl // is set then we add a callback to the breakpoint. 371500f56eebSLuke Drummond bool RenderScriptRuntime::PlaceBreakpointOnKernel(TargetSP target, 371600f56eebSLuke Drummond Stream &messages, 371700f56eebSLuke Drummond const char *name, 371800f56eebSLuke Drummond const RSCoordinate *coord) { 371900f56eebSLuke Drummond if (!name) 372000f56eebSLuke Drummond return false; 37214640cde1SColin Riley 37227dc7771cSEwan Crawford InitSearchFilter(target); 372398156583SEwan Crawford 37244640cde1SColin Riley ConstString kernel_name(name); 37257dc7771cSEwan Crawford BreakpointSP bp = CreateKernelBreakpoint(kernel_name); 372600f56eebSLuke Drummond if (!bp) 372700f56eebSLuke Drummond return false; 3728018f5a7eSEwan Crawford 3729018f5a7eSEwan Crawford // We have a conditional breakpoint on a specific coordinate 373000f56eebSLuke Drummond if (coord) 373100f56eebSLuke Drummond SetConditional(bp, messages, *coord); 3732018f5a7eSEwan Crawford 373300f56eebSLuke Drummond bp->GetDescription(&messages, lldb::eDescriptionLevelInitial, false); 3734018f5a7eSEwan Crawford 373500f56eebSLuke Drummond return true; 37364640cde1SColin Riley } 37374640cde1SColin Riley 373821fed052SAidan Dodds BreakpointSP 37390e4c4821SAdrian Prantl RenderScriptRuntime::CreateScriptGroupBreakpoint(ConstString name, 374021fed052SAidan Dodds bool stop_on_all) { 3741*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language | LLDBLog::Breakpoints); 374221fed052SAidan Dodds 374321fed052SAidan Dodds if (!m_filtersp) { 374463e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - error, no breakpoint search filter set.", 374563e5fb76SJonas Devlieghere __FUNCTION__); 374621fed052SAidan Dodds return nullptr; 374721fed052SAidan Dodds } 374821fed052SAidan Dodds 374921fed052SAidan Dodds BreakpointResolverSP resolver_sp(new RSScriptGroupBreakpointResolver( 375021fed052SAidan Dodds nullptr, name, m_scriptGroups, stop_on_all)); 3751b842f2ecSJim Ingham Target &target = GetProcess()->GetTarget(); 3752b842f2ecSJim Ingham BreakpointSP bp = target.CreateBreakpoint( 375321fed052SAidan Dodds m_filtersp, resolver_sp, false, false, false); 375421fed052SAidan Dodds // Give RS breakpoints a specific name, so the user can manipulate them as a 375521fed052SAidan Dodds // group. 375697206d57SZachary Turner Status err; 3757b842f2ecSJim Ingham target.AddNameToBreakpoint(bp, name.GetCString(), err); 3758b842f2ecSJim Ingham if (err.Fail() && log) 375963e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - error setting break name, '%s'.", __FUNCTION__, 376021fed052SAidan Dodds err.AsCString()); 376121fed052SAidan Dodds // ask the breakpoint to resolve itself 376221fed052SAidan Dodds bp->ResolveBreakpoint(); 376321fed052SAidan Dodds return bp; 376421fed052SAidan Dodds } 376521fed052SAidan Dodds 376621fed052SAidan Dodds bool RenderScriptRuntime::PlaceBreakpointOnScriptGroup(TargetSP target, 376721fed052SAidan Dodds Stream &strm, 37680e4c4821SAdrian Prantl ConstString name, 376921fed052SAidan Dodds bool multi) { 377021fed052SAidan Dodds InitSearchFilter(target); 377121fed052SAidan Dodds BreakpointSP bp = CreateScriptGroupBreakpoint(name, multi); 377221fed052SAidan Dodds if (bp) 377321fed052SAidan Dodds bp->GetDescription(&strm, lldb::eDescriptionLevelInitial, false); 377421fed052SAidan Dodds return bool(bp); 377521fed052SAidan Dodds } 377621fed052SAidan Dodds 3777b3bbcb12SLuke Drummond bool RenderScriptRuntime::PlaceBreakpointOnReduction(TargetSP target, 3778b3bbcb12SLuke Drummond Stream &messages, 3779b3bbcb12SLuke Drummond const char *reduce_name, 3780b3bbcb12SLuke Drummond const RSCoordinate *coord, 3781b3bbcb12SLuke Drummond int kernel_types) { 3782b3bbcb12SLuke Drummond if (!reduce_name) 3783b3bbcb12SLuke Drummond return false; 3784b3bbcb12SLuke Drummond 3785b3bbcb12SLuke Drummond InitSearchFilter(target); 3786b3bbcb12SLuke Drummond BreakpointSP bp = 3787b3bbcb12SLuke Drummond CreateReductionBreakpoint(ConstString(reduce_name), kernel_types); 3788b3bbcb12SLuke Drummond if (!bp) 3789b3bbcb12SLuke Drummond return false; 3790b3bbcb12SLuke Drummond 3791b3bbcb12SLuke Drummond if (coord) 3792b3bbcb12SLuke Drummond SetConditional(bp, messages, *coord); 3793b3bbcb12SLuke Drummond 3794b3bbcb12SLuke Drummond bp->GetDescription(&messages, lldb::eDescriptionLevelInitial, false); 3795b3bbcb12SLuke Drummond 3796b3bbcb12SLuke Drummond return true; 3797b3bbcb12SLuke Drummond } 3798b3bbcb12SLuke Drummond 3799b9c1b51eSKate Stone void RenderScriptRuntime::DumpModules(Stream &strm) const { 38005ec532a9SColin Riley strm.Printf("RenderScript Modules:"); 38015ec532a9SColin Riley strm.EOL(); 38025ec532a9SColin Riley strm.IndentMore(); 3803b9c1b51eSKate Stone for (const auto &module : m_rsmodules) { 38044640cde1SColin Riley module->Dump(strm); 38055ec532a9SColin Riley } 38065ec532a9SColin Riley strm.IndentLess(); 38075ec532a9SColin Riley } 38085ec532a9SColin Riley 380978f339d1SEwan Crawford RenderScriptRuntime::ScriptDetails * 3810b9c1b51eSKate Stone RenderScriptRuntime::LookUpScript(addr_t address, bool create) { 3811b9c1b51eSKate Stone for (const auto &s : m_scripts) { 381278f339d1SEwan Crawford if (s->script.isValid()) 381378f339d1SEwan Crawford if (*s->script == address) 381478f339d1SEwan Crawford return s.get(); 381578f339d1SEwan Crawford } 3816b9c1b51eSKate Stone if (create) { 381778f339d1SEwan Crawford std::unique_ptr<ScriptDetails> s(new ScriptDetails); 381878f339d1SEwan Crawford s->script = address; 381978f339d1SEwan Crawford m_scripts.push_back(std::move(s)); 3820d10ca9deSEwan Crawford return m_scripts.back().get(); 382178f339d1SEwan Crawford } 382278f339d1SEwan Crawford return nullptr; 382378f339d1SEwan Crawford } 382478f339d1SEwan Crawford 382578f339d1SEwan Crawford RenderScriptRuntime::AllocationDetails * 3826b9c1b51eSKate Stone RenderScriptRuntime::LookUpAllocation(addr_t address) { 3827b9c1b51eSKate Stone for (const auto &a : m_allocations) { 382878f339d1SEwan Crawford if (a->address.isValid()) 382978f339d1SEwan Crawford if (*a->address == address) 383078f339d1SEwan Crawford return a.get(); 383178f339d1SEwan Crawford } 38325d057637SLuke Drummond return nullptr; 38335d057637SLuke Drummond } 38345d057637SLuke Drummond 38355d057637SLuke Drummond RenderScriptRuntime::AllocationDetails * 3836b9c1b51eSKate Stone RenderScriptRuntime::CreateAllocation(addr_t address) { 3837*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Language); 38385d057637SLuke Drummond 38395d057637SLuke Drummond // Remove any previous allocation which contains the same address 38405d057637SLuke Drummond auto it = m_allocations.begin(); 3841b9c1b51eSKate Stone while (it != m_allocations.end()) { 3842b9c1b51eSKate Stone if (*((*it)->address) == address) { 384363e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s - Removing allocation id: %d, address: 0x%" PRIx64, 3844b9c1b51eSKate Stone __FUNCTION__, (*it)->id, address); 38455d057637SLuke Drummond 38465d057637SLuke Drummond it = m_allocations.erase(it); 3847b9c1b51eSKate Stone } else { 38485d057637SLuke Drummond it++; 38495d057637SLuke Drummond } 38505d057637SLuke Drummond } 38515d057637SLuke Drummond 385278f339d1SEwan Crawford std::unique_ptr<AllocationDetails> a(new AllocationDetails); 385378f339d1SEwan Crawford a->address = address; 385478f339d1SEwan Crawford m_allocations.push_back(std::move(a)); 3855d10ca9deSEwan Crawford return m_allocations.back().get(); 385678f339d1SEwan Crawford } 385778f339d1SEwan Crawford 385821fed052SAidan Dodds bool RenderScriptRuntime::ResolveKernelName(lldb::addr_t kernel_addr, 385921fed052SAidan Dodds ConstString &name) { 3860*a007a6d8SPavel Labath Log *log = GetLog(LLDBLog::Symbols); 386121fed052SAidan Dodds 386221fed052SAidan Dodds Target &target = GetProcess()->GetTarget(); 386321fed052SAidan Dodds Address resolved; 386421fed052SAidan Dodds // RenderScript module 386521fed052SAidan Dodds if (!target.GetSectionLoadList().ResolveLoadAddress(kernel_addr, resolved)) { 386663e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s: unable to resolve 0x%" PRIx64 " to a loaded symbol", 386721fed052SAidan Dodds __FUNCTION__, kernel_addr); 386821fed052SAidan Dodds return false; 386921fed052SAidan Dodds } 387021fed052SAidan Dodds 387121fed052SAidan Dodds Symbol *sym = resolved.CalculateSymbolContextSymbol(); 387221fed052SAidan Dodds if (!sym) 387321fed052SAidan Dodds return false; 387421fed052SAidan Dodds 387521fed052SAidan Dodds name = sym->GetName(); 387621fed052SAidan Dodds assert(IsRenderScriptModule(resolved.CalculateSymbolContextModule())); 387763e5fb76SJonas Devlieghere LLDB_LOGF(log, "%s: 0x%" PRIx64 " resolved to the symbol '%s'", __FUNCTION__, 387821fed052SAidan Dodds kernel_addr, name.GetCString()); 387921fed052SAidan Dodds return true; 388021fed052SAidan Dodds } 388121fed052SAidan Dodds 3882b9c1b51eSKate Stone void RSModuleDescriptor::Dump(Stream &strm) const { 38837f193d69SLuke Drummond int indent = strm.GetIndentLevel(); 38847f193d69SLuke Drummond 38855ec532a9SColin Riley strm.Indent(); 38864dac97ebSRaphael Isemann m_module->GetFileSpec().Dump(strm.AsRawOstream()); 38877f193d69SLuke Drummond strm.Indent(m_module->GetNumCompileUnits() ? "Debug info loaded." 38887f193d69SLuke Drummond : "Debug info does not exist."); 38895ec532a9SColin Riley strm.EOL(); 38905ec532a9SColin Riley strm.IndentMore(); 38917f193d69SLuke Drummond 38925ec532a9SColin Riley strm.Indent(); 3893189598edSColin Riley strm.Printf("Globals: %" PRIu64, static_cast<uint64_t>(m_globals.size())); 38945ec532a9SColin Riley strm.EOL(); 38955ec532a9SColin Riley strm.IndentMore(); 3896b9c1b51eSKate Stone for (const auto &global : m_globals) { 38975ec532a9SColin Riley global.Dump(strm); 38985ec532a9SColin Riley } 38995ec532a9SColin Riley strm.IndentLess(); 39007f193d69SLuke Drummond 39015ec532a9SColin Riley strm.Indent(); 3902189598edSColin Riley strm.Printf("Kernels: %" PRIu64, static_cast<uint64_t>(m_kernels.size())); 39035ec532a9SColin Riley strm.EOL(); 39045ec532a9SColin Riley strm.IndentMore(); 3905b9c1b51eSKate Stone for (const auto &kernel : m_kernels) { 39065ec532a9SColin Riley kernel.Dump(strm); 39075ec532a9SColin Riley } 39087f193d69SLuke Drummond strm.IndentLess(); 39097f193d69SLuke Drummond 39107f193d69SLuke Drummond strm.Indent(); 39114640cde1SColin Riley strm.Printf("Pragmas: %" PRIu64, static_cast<uint64_t>(m_pragmas.size())); 39124640cde1SColin Riley strm.EOL(); 39134640cde1SColin Riley strm.IndentMore(); 3914b9c1b51eSKate Stone for (const auto &key_val : m_pragmas) { 39157f193d69SLuke Drummond strm.Indent(); 39164640cde1SColin Riley strm.Printf("%s: %s", key_val.first.c_str(), key_val.second.c_str()); 39174640cde1SColin Riley strm.EOL(); 39184640cde1SColin Riley } 39197f193d69SLuke Drummond strm.IndentLess(); 39207f193d69SLuke Drummond 39217f193d69SLuke Drummond strm.Indent(); 39227f193d69SLuke Drummond strm.Printf("Reductions: %" PRIu64, 39237f193d69SLuke Drummond static_cast<uint64_t>(m_reductions.size())); 39247f193d69SLuke Drummond strm.EOL(); 39257f193d69SLuke Drummond strm.IndentMore(); 39267f193d69SLuke Drummond for (const auto &reduction : m_reductions) { 39277f193d69SLuke Drummond reduction.Dump(strm); 39287f193d69SLuke Drummond } 39297f193d69SLuke Drummond 39307f193d69SLuke Drummond strm.SetIndentLevel(indent); 39315ec532a9SColin Riley } 39325ec532a9SColin Riley 3933b9c1b51eSKate Stone void RSGlobalDescriptor::Dump(Stream &strm) const { 39349dfd4e26SRaphael Isemann strm.Indent(m_name.GetStringRef()); 39354640cde1SColin Riley VariableList var_list; 3936f9568a95SRaphael Isemann m_module->m_module->FindGlobalVariables(m_name, CompilerDeclContext(), 1U, 3937f9568a95SRaphael Isemann var_list); 3938b9c1b51eSKate Stone if (var_list.GetSize() == 1) { 39394640cde1SColin Riley auto var = var_list.GetVariableAtIndex(0); 39404640cde1SColin Riley auto type = var->GetType(); 3941b9c1b51eSKate Stone if (type) { 39424640cde1SColin Riley strm.Printf(" - "); 39434640cde1SColin Riley type->DumpTypeName(&strm); 3944b9c1b51eSKate Stone } else { 39454640cde1SColin Riley strm.Printf(" - Unknown Type"); 39464640cde1SColin Riley } 3947b9c1b51eSKate Stone } else { 39484640cde1SColin Riley strm.Printf(" - variable identified, but not found in binary"); 3949b9c1b51eSKate Stone const Symbol *s = m_module->m_module->FindFirstSymbolWithNameAndType( 3950b9c1b51eSKate Stone m_name, eSymbolTypeData); 3951b9c1b51eSKate Stone if (s) { 39524640cde1SColin Riley strm.Printf(" (symbol exists) "); 39534640cde1SColin Riley } 39544640cde1SColin Riley } 39554640cde1SColin Riley 39565ec532a9SColin Riley strm.EOL(); 39575ec532a9SColin Riley } 39585ec532a9SColin Riley 3959b9c1b51eSKate Stone void RSKernelDescriptor::Dump(Stream &strm) const { 39609dfd4e26SRaphael Isemann strm.Indent(m_name.GetStringRef()); 39615ec532a9SColin Riley strm.EOL(); 39625ec532a9SColin Riley } 39635ec532a9SColin Riley 39647f193d69SLuke Drummond void RSReductionDescriptor::Dump(lldb_private::Stream &stream) const { 39659dfd4e26SRaphael Isemann stream.Indent(m_reduce_name.GetStringRef()); 39667f193d69SLuke Drummond stream.IndentMore(); 39677f193d69SLuke Drummond stream.EOL(); 39687f193d69SLuke Drummond stream.Indent(); 39697f193d69SLuke Drummond stream.Printf("accumulator: %s", m_accum_name.AsCString()); 39707f193d69SLuke Drummond stream.EOL(); 39717f193d69SLuke Drummond stream.Indent(); 39727f193d69SLuke Drummond stream.Printf("initializer: %s", m_init_name.AsCString()); 39737f193d69SLuke Drummond stream.EOL(); 39747f193d69SLuke Drummond stream.Indent(); 39757f193d69SLuke Drummond stream.Printf("combiner: %s", m_comb_name.AsCString()); 39767f193d69SLuke Drummond stream.EOL(); 39777f193d69SLuke Drummond stream.Indent(); 39787f193d69SLuke Drummond stream.Printf("outconverter: %s", m_outc_name.AsCString()); 39797f193d69SLuke Drummond stream.EOL(); 39807f193d69SLuke Drummond // XXX This is currently unspecified by RenderScript, and unused 39817f193d69SLuke Drummond // stream.Indent(); 39827f193d69SLuke Drummond // stream.Printf("halter: '%s'", m_init_name.AsCString()); 39837f193d69SLuke Drummond // stream.EOL(); 39847f193d69SLuke Drummond stream.IndentLess(); 39857f193d69SLuke Drummond } 39867f193d69SLuke Drummond 3987b9c1b51eSKate Stone class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed { 39885ec532a9SColin Riley public: 39895ec532a9SColin Riley CommandObjectRenderScriptRuntimeModuleDump(CommandInterpreter &interpreter) 3990b9c1b51eSKate Stone : CommandObjectParsed( 3991b9c1b51eSKate Stone interpreter, "renderscript module dump", 3992b9c1b51eSKate Stone "Dumps renderscript specific information for all modules.", 3993b9c1b51eSKate Stone "renderscript module dump", 3994b9c1b51eSKate Stone eCommandRequiresProcess | eCommandProcessMustBeLaunched) {} 39955ec532a9SColin Riley 3996222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeModuleDump() override = default; 39975ec532a9SColin Riley 3998b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 3999056f6f18SAlex Langford RenderScriptRuntime *runtime = llvm::cast<RenderScriptRuntime>( 4000056f6f18SAlex Langford m_exe_ctx.GetProcessPtr()->GetLanguageRuntime( 4001056f6f18SAlex Langford eLanguageTypeExtRenderScript)); 40025ec532a9SColin Riley runtime->DumpModules(result.GetOutputStream()); 40035ec532a9SColin Riley result.SetStatus(eReturnStatusSuccessFinishResult); 40045ec532a9SColin Riley return true; 40055ec532a9SColin Riley } 40065ec532a9SColin Riley }; 40075ec532a9SColin Riley 4008b9c1b51eSKate Stone class CommandObjectRenderScriptRuntimeModule : public CommandObjectMultiword { 40095ec532a9SColin Riley public: 40105ec532a9SColin Riley CommandObjectRenderScriptRuntimeModule(CommandInterpreter &interpreter) 4011b9c1b51eSKate Stone : CommandObjectMultiword(interpreter, "renderscript module", 4012b9c1b51eSKate Stone "Commands that deal with RenderScript modules.", 4013b9c1b51eSKate Stone nullptr) { 4014b9c1b51eSKate Stone LoadSubCommand( 4015b9c1b51eSKate Stone "dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleDump( 4016b9c1b51eSKate Stone interpreter))); 40175ec532a9SColin Riley } 40185ec532a9SColin Riley 4019222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeModule() override = default; 40205ec532a9SColin Riley }; 40215ec532a9SColin Riley 4022b9c1b51eSKate Stone class CommandObjectRenderScriptRuntimeKernelList : public CommandObjectParsed { 40234640cde1SColin Riley public: 40244640cde1SColin Riley CommandObjectRenderScriptRuntimeKernelList(CommandInterpreter &interpreter) 4025b9c1b51eSKate Stone : CommandObjectParsed( 4026b9c1b51eSKate Stone interpreter, "renderscript kernel list", 4027b3f7f69dSAidan Dodds "Lists renderscript kernel names and associated script resources.", 4028b9c1b51eSKate Stone "renderscript kernel list", 4029b9c1b51eSKate Stone eCommandRequiresProcess | eCommandProcessMustBeLaunched) {} 40304640cde1SColin Riley 4031222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeKernelList() override = default; 40324640cde1SColin Riley 4033b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 4034056f6f18SAlex Langford RenderScriptRuntime *runtime = llvm::cast<RenderScriptRuntime>( 4035056f6f18SAlex Langford m_exe_ctx.GetProcessPtr()->GetLanguageRuntime( 4036056f6f18SAlex Langford eLanguageTypeExtRenderScript)); 40374640cde1SColin Riley runtime->DumpKernels(result.GetOutputStream()); 40384640cde1SColin Riley result.SetStatus(eReturnStatusSuccessFinishResult); 40394640cde1SColin Riley return true; 40404640cde1SColin Riley } 40414640cde1SColin Riley }; 40424640cde1SColin Riley 40438fe53c49STatyana Krasnukha static constexpr OptionDefinition g_renderscript_reduction_bp_set_options[] = { 4044b3bbcb12SLuke Drummond {LLDB_OPT_SET_1, false, "function-role", 't', 40458fe53c49STatyana Krasnukha OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOneLiner, 4046b3bbcb12SLuke Drummond "Break on a comma separated set of reduction kernel types " 4047b3bbcb12SLuke Drummond "(accumulator,outcoverter,combiner,initializer"}, 4048b3bbcb12SLuke Drummond {LLDB_OPT_SET_1, false, "coordinate", 'c', OptionParser::eRequiredArgument, 40498fe53c49STatyana Krasnukha nullptr, {}, 0, eArgTypeValue, 4050b3bbcb12SLuke Drummond "Set a breakpoint on a single invocation of the kernel with specified " 4051b3bbcb12SLuke Drummond "coordinate.\n" 4052b3bbcb12SLuke Drummond "Coordinate takes the form 'x[,y][,z] where x,y,z are positive " 4053b3bbcb12SLuke Drummond "integers representing kernel dimensions. " 4054b3bbcb12SLuke Drummond "Any unset dimensions will be defaulted to zero."}}; 4055b3bbcb12SLuke Drummond 4056b3bbcb12SLuke Drummond class CommandObjectRenderScriptRuntimeReductionBreakpointSet 4057b3bbcb12SLuke Drummond : public CommandObjectParsed { 4058b3bbcb12SLuke Drummond public: 4059b3bbcb12SLuke Drummond CommandObjectRenderScriptRuntimeReductionBreakpointSet( 4060b3bbcb12SLuke Drummond CommandInterpreter &interpreter) 4061b3bbcb12SLuke Drummond : CommandObjectParsed( 4062b3bbcb12SLuke Drummond interpreter, "renderscript reduction breakpoint set", 4063b3bbcb12SLuke Drummond "Set a breakpoint on named RenderScript general reductions", 4064b3bbcb12SLuke Drummond "renderscript reduction breakpoint set <kernel_name> [-t " 4065b3bbcb12SLuke Drummond "<reduction_kernel_type,...>]", 4066b3bbcb12SLuke Drummond eCommandRequiresProcess | eCommandProcessMustBeLaunched | 4067b3bbcb12SLuke Drummond eCommandProcessMustBePaused), 4068b3bbcb12SLuke Drummond m_options(){}; 4069b3bbcb12SLuke Drummond 4070b3bbcb12SLuke Drummond class CommandOptions : public Options { 4071b3bbcb12SLuke Drummond public: 40729494c510SJonas Devlieghere CommandOptions() : Options() {} 4073b3bbcb12SLuke Drummond 4074b3bbcb12SLuke Drummond ~CommandOptions() override = default; 4075b3bbcb12SLuke Drummond 407697206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 4077b3bbcb12SLuke Drummond ExecutionContext *exe_ctx) override { 407897206d57SZachary Turner Status err; 4079b3bbcb12SLuke Drummond StreamString err_str; 4080b3bbcb12SLuke Drummond const int short_option = m_getopt_table[option_idx].val; 4081b3bbcb12SLuke Drummond switch (short_option) { 4082b3bbcb12SLuke Drummond case 't': 4083fe11483bSZachary Turner if (!ParseReductionTypes(option_arg, err_str)) 4084b3bbcb12SLuke Drummond err.SetErrorStringWithFormat( 4085fe11483bSZachary Turner "Unable to deduce reduction types for %s: %s", 4086fe11483bSZachary Turner option_arg.str().c_str(), err_str.GetData()); 4087b3bbcb12SLuke Drummond break; 4088b3bbcb12SLuke Drummond case 'c': { 4089b3bbcb12SLuke Drummond auto coord = RSCoordinate{}; 4090fe11483bSZachary Turner if (!ParseCoordinate(option_arg, coord)) 4091b3bbcb12SLuke Drummond err.SetErrorStringWithFormat("unable to parse coordinate for %s", 4092fe11483bSZachary Turner option_arg.str().c_str()); 4093b3bbcb12SLuke Drummond else { 4094b3bbcb12SLuke Drummond m_have_coord = true; 4095b3bbcb12SLuke Drummond m_coord = coord; 4096b3bbcb12SLuke Drummond } 4097b3bbcb12SLuke Drummond break; 4098b3bbcb12SLuke Drummond } 4099b3bbcb12SLuke Drummond default: 4100b3bbcb12SLuke Drummond err.SetErrorStringWithFormat("Invalid option '-%c'", short_option); 4101b3bbcb12SLuke Drummond } 4102b3bbcb12SLuke Drummond return err; 4103b3bbcb12SLuke Drummond } 4104b3bbcb12SLuke Drummond 4105b3bbcb12SLuke Drummond void OptionParsingStarting(ExecutionContext *exe_ctx) override { 4106b3bbcb12SLuke Drummond m_have_coord = false; 4107b3bbcb12SLuke Drummond } 4108b3bbcb12SLuke Drummond 4109b3bbcb12SLuke Drummond llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 4110b3bbcb12SLuke Drummond return llvm::makeArrayRef(g_renderscript_reduction_bp_set_options); 4111b3bbcb12SLuke Drummond } 4112b3bbcb12SLuke Drummond 4113fe11483bSZachary Turner bool ParseReductionTypes(llvm::StringRef option_val, 4114fe11483bSZachary Turner StreamString &err_str) { 4115b3bbcb12SLuke Drummond m_kernel_types = RSReduceBreakpointResolver::eKernelTypeNone; 4116b3bbcb12SLuke Drummond const auto reduce_name_to_type = [](llvm::StringRef name) -> int { 4117b3bbcb12SLuke Drummond return llvm::StringSwitch<int>(name) 4118b3bbcb12SLuke Drummond .Case("accumulator", RSReduceBreakpointResolver::eKernelTypeAccum) 4119b3bbcb12SLuke Drummond .Case("initializer", RSReduceBreakpointResolver::eKernelTypeInit) 4120b3bbcb12SLuke Drummond .Case("outconverter", RSReduceBreakpointResolver::eKernelTypeOutC) 4121b3bbcb12SLuke Drummond .Case("combiner", RSReduceBreakpointResolver::eKernelTypeComb) 4122b3bbcb12SLuke Drummond .Case("all", RSReduceBreakpointResolver::eKernelTypeAll) 4123b3bbcb12SLuke Drummond // Currently not exposed by the runtime 4124b3bbcb12SLuke Drummond // .Case("halter", RSReduceBreakpointResolver::eKernelTypeHalter) 4125b3bbcb12SLuke Drummond .Default(0); 4126b3bbcb12SLuke Drummond }; 4127b3bbcb12SLuke Drummond 4128b3bbcb12SLuke Drummond // Matching a comma separated list of known words is fairly 412905097246SAdrian Prantl // straightforward with PCRE, but we're using ERE, so we end up with a 413005097246SAdrian Prantl // little ugliness... 4131b3bbcb12SLuke Drummond RegularExpression match_type_list( 4132b3bbcb12SLuke Drummond llvm::StringRef("^([[:alpha:]]+)(,[[:alpha:]]+){0,4}$")); 4133b3bbcb12SLuke Drummond 4134b3bbcb12SLuke Drummond assert(match_type_list.IsValid()); 4135b3bbcb12SLuke Drummond 41363af3f1e8SJonas Devlieghere if (!match_type_list.Execute(option_val)) { 4137b3bbcb12SLuke Drummond err_str.PutCString( 4138b3bbcb12SLuke Drummond "a comma-separated list of kernel types is required"); 4139b3bbcb12SLuke Drummond return false; 4140b3bbcb12SLuke Drummond } 4141b3bbcb12SLuke Drummond 4142b3bbcb12SLuke Drummond // splitting on commas is much easier with llvm::StringRef than regex 4143b3bbcb12SLuke Drummond llvm::SmallVector<llvm::StringRef, 5> type_names; 4144b3bbcb12SLuke Drummond llvm::StringRef(option_val).split(type_names, ','); 4145b3bbcb12SLuke Drummond 4146b3bbcb12SLuke Drummond for (const auto &name : type_names) { 4147b3bbcb12SLuke Drummond const int type = reduce_name_to_type(name); 4148b3bbcb12SLuke Drummond if (!type) { 4149b3bbcb12SLuke Drummond err_str.Printf("unknown kernel type name %s", name.str().c_str()); 4150b3bbcb12SLuke Drummond return false; 4151b3bbcb12SLuke Drummond } 4152b3bbcb12SLuke Drummond m_kernel_types |= type; 4153b3bbcb12SLuke Drummond } 4154b3bbcb12SLuke Drummond 4155b3bbcb12SLuke Drummond return true; 4156b3bbcb12SLuke Drummond } 4157b3bbcb12SLuke Drummond 41589494c510SJonas Devlieghere int m_kernel_types = RSReduceBreakpointResolver::eKernelTypeAll; 4159b3bbcb12SLuke Drummond llvm::StringRef m_reduce_name; 4160b3bbcb12SLuke Drummond RSCoordinate m_coord; 4161b3bbcb12SLuke Drummond bool m_have_coord; 4162b3bbcb12SLuke Drummond }; 4163b3bbcb12SLuke Drummond 4164b3bbcb12SLuke Drummond Options *GetOptions() override { return &m_options; } 4165b3bbcb12SLuke Drummond 4166b3bbcb12SLuke Drummond bool DoExecute(Args &command, CommandReturnObject &result) override { 4167b3bbcb12SLuke Drummond const size_t argc = command.GetArgumentCount(); 4168b3bbcb12SLuke Drummond if (argc < 1) { 4169b3bbcb12SLuke Drummond result.AppendErrorWithFormat("'%s' takes 1 argument of reduction name, " 4170b3bbcb12SLuke Drummond "and an optional kernel type list", 4171b3bbcb12SLuke Drummond m_cmd_name.c_str()); 4172b3bbcb12SLuke Drummond return false; 4173b3bbcb12SLuke Drummond } 4174b3bbcb12SLuke Drummond 4175b3bbcb12SLuke Drummond RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>( 4176b3bbcb12SLuke Drummond m_exe_ctx.GetProcessPtr()->GetLanguageRuntime( 4177b3bbcb12SLuke Drummond eLanguageTypeExtRenderScript)); 4178b3bbcb12SLuke Drummond 4179b3bbcb12SLuke Drummond auto &outstream = result.GetOutputStream(); 4180b3bbcb12SLuke Drummond auto name = command.GetArgumentAtIndex(0); 4181b3bbcb12SLuke Drummond auto &target = m_exe_ctx.GetTargetSP(); 4182b3bbcb12SLuke Drummond auto coord = m_options.m_have_coord ? &m_options.m_coord : nullptr; 4183b3bbcb12SLuke Drummond if (!runtime->PlaceBreakpointOnReduction(target, outstream, name, coord, 4184b3bbcb12SLuke Drummond m_options.m_kernel_types)) { 4185b3bbcb12SLuke Drummond result.AppendError("Error: unable to place breakpoint on reduction"); 4186b3bbcb12SLuke Drummond return false; 4187b3bbcb12SLuke Drummond } 4188b3bbcb12SLuke Drummond result.AppendMessage("Breakpoint(s) created"); 4189b3bbcb12SLuke Drummond result.SetStatus(eReturnStatusSuccessFinishResult); 4190b3bbcb12SLuke Drummond return true; 4191b3bbcb12SLuke Drummond } 4192b3bbcb12SLuke Drummond 4193b3bbcb12SLuke Drummond private: 4194b3bbcb12SLuke Drummond CommandOptions m_options; 4195b3bbcb12SLuke Drummond }; 4196b3bbcb12SLuke Drummond 41978fe53c49STatyana Krasnukha static constexpr OptionDefinition g_renderscript_kernel_bp_set_options[] = { 41981f0f5b5bSZachary Turner {LLDB_OPT_SET_1, false, "coordinate", 'c', OptionParser::eRequiredArgument, 41998fe53c49STatyana Krasnukha nullptr, {}, 0, eArgTypeValue, 42001f0f5b5bSZachary Turner "Set a breakpoint on a single invocation of the kernel with specified " 42011f0f5b5bSZachary Turner "coordinate.\n" 42021f0f5b5bSZachary Turner "Coordinate takes the form 'x[,y][,z] where x,y,z are positive " 42031f0f5b5bSZachary Turner "integers representing kernel dimensions. " 42041f0f5b5bSZachary Turner "Any unset dimensions will be defaulted to zero."}}; 42051f0f5b5bSZachary Turner 4206b9c1b51eSKate Stone class CommandObjectRenderScriptRuntimeKernelBreakpointSet 4207b9c1b51eSKate Stone : public CommandObjectParsed { 42084640cde1SColin Riley public: 4209b9c1b51eSKate Stone CommandObjectRenderScriptRuntimeKernelBreakpointSet( 4210b9c1b51eSKate Stone CommandInterpreter &interpreter) 4211b9c1b51eSKate Stone : CommandObjectParsed( 4212b9c1b51eSKate Stone interpreter, "renderscript kernel breakpoint set", 4213b3f7f69dSAidan Dodds "Sets a breakpoint on a renderscript kernel.", 4214b3f7f69dSAidan Dodds "renderscript kernel breakpoint set <kernel_name> [-c x,y,z]", 4215b9c1b51eSKate Stone eCommandRequiresProcess | eCommandProcessMustBeLaunched | 4216b9c1b51eSKate Stone eCommandProcessMustBePaused), 4217b9c1b51eSKate Stone m_options() {} 42184640cde1SColin Riley 4219222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeKernelBreakpointSet() override = default; 4220222b937cSEugene Zelenko 4221b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 4222018f5a7eSEwan Crawford 4223b9c1b51eSKate Stone class CommandOptions : public Options { 4224018f5a7eSEwan Crawford public: 4225e1cfbc79STodd Fiala CommandOptions() : Options() {} 4226018f5a7eSEwan Crawford 4227222b937cSEugene Zelenko ~CommandOptions() override = default; 4228018f5a7eSEwan Crawford 422997206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 4230b3bbcb12SLuke Drummond ExecutionContext *exe_ctx) override { 423197206d57SZachary Turner Status err; 4232018f5a7eSEwan Crawford const int short_option = m_getopt_table[option_idx].val; 4233018f5a7eSEwan Crawford 4234b9c1b51eSKate Stone switch (short_option) { 423500f56eebSLuke Drummond case 'c': { 423600f56eebSLuke Drummond auto coord = RSCoordinate{}; 423700f56eebSLuke Drummond if (!ParseCoordinate(option_arg, coord)) 423880af0b9eSLuke Drummond err.SetErrorStringWithFormat( 4239b9c1b51eSKate Stone "Couldn't parse coordinate '%s', should be in format 'x,y,z'.", 4240fe11483bSZachary Turner option_arg.str().c_str()); 424100f56eebSLuke Drummond else { 424200f56eebSLuke Drummond m_have_coord = true; 424300f56eebSLuke Drummond m_coord = coord; 424400f56eebSLuke Drummond } 4245018f5a7eSEwan Crawford break; 424600f56eebSLuke Drummond } 4247018f5a7eSEwan Crawford default: 424880af0b9eSLuke Drummond err.SetErrorStringWithFormat("unrecognized option '%c'", short_option); 4249018f5a7eSEwan Crawford break; 4250018f5a7eSEwan Crawford } 425180af0b9eSLuke Drummond return err; 4252018f5a7eSEwan Crawford } 4253018f5a7eSEwan Crawford 4254b3bbcb12SLuke Drummond void OptionParsingStarting(ExecutionContext *exe_ctx) override { 425500f56eebSLuke Drummond m_have_coord = false; 4256018f5a7eSEwan Crawford } 4257018f5a7eSEwan Crawford 42581f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 425970602439SZachary Turner return llvm::makeArrayRef(g_renderscript_kernel_bp_set_options); 42601f0f5b5bSZachary Turner } 4261018f5a7eSEwan Crawford 426200f56eebSLuke Drummond RSCoordinate m_coord; 426300f56eebSLuke Drummond bool m_have_coord; 4264018f5a7eSEwan Crawford }; 4265018f5a7eSEwan Crawford 4266b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 42674640cde1SColin Riley const size_t argc = command.GetArgumentCount(); 4268b9c1b51eSKate Stone if (argc < 1) { 4269b9c1b51eSKate Stone result.AppendErrorWithFormat( 4270b9c1b51eSKate Stone "'%s' takes 1 argument of kernel name, and an optional coordinate.", 4271b3f7f69dSAidan Dodds m_cmd_name.c_str()); 4272018f5a7eSEwan Crawford return false; 4273018f5a7eSEwan Crawford } 4274018f5a7eSEwan Crawford 4275056f6f18SAlex Langford RenderScriptRuntime *runtime = llvm::cast<RenderScriptRuntime>( 4276056f6f18SAlex Langford m_exe_ctx.GetProcessPtr()->GetLanguageRuntime( 4277056f6f18SAlex Langford eLanguageTypeExtRenderScript)); 42784640cde1SColin Riley 427900f56eebSLuke Drummond auto &outstream = result.GetOutputStream(); 428000f56eebSLuke Drummond auto &target = m_exe_ctx.GetTargetSP(); 428100f56eebSLuke Drummond auto name = command.GetArgumentAtIndex(0); 428200f56eebSLuke Drummond auto coord = m_options.m_have_coord ? &m_options.m_coord : nullptr; 428300f56eebSLuke Drummond if (!runtime->PlaceBreakpointOnKernel(target, outstream, name, coord)) { 428400f56eebSLuke Drummond result.AppendErrorWithFormat( 428500f56eebSLuke Drummond "Error: unable to set breakpoint on kernel '%s'", name); 428600f56eebSLuke Drummond return false; 428700f56eebSLuke Drummond } 42884640cde1SColin Riley 42894640cde1SColin Riley result.AppendMessage("Breakpoint(s) created"); 42904640cde1SColin Riley result.SetStatus(eReturnStatusSuccessFinishResult); 42914640cde1SColin Riley return true; 42924640cde1SColin Riley } 42934640cde1SColin Riley 4294018f5a7eSEwan Crawford private: 4295018f5a7eSEwan Crawford CommandOptions m_options; 42964640cde1SColin Riley }; 42974640cde1SColin Riley 4298b9c1b51eSKate Stone class CommandObjectRenderScriptRuntimeKernelBreakpointAll 4299b9c1b51eSKate Stone : public CommandObjectParsed { 43007dc7771cSEwan Crawford public: 4301b9c1b51eSKate Stone CommandObjectRenderScriptRuntimeKernelBreakpointAll( 4302b9c1b51eSKate Stone CommandInterpreter &interpreter) 4303b3f7f69dSAidan Dodds : CommandObjectParsed( 4304b3f7f69dSAidan Dodds interpreter, "renderscript kernel breakpoint all", 4305b9c1b51eSKate Stone "Automatically sets a breakpoint on all renderscript kernels that " 4306b9c1b51eSKate Stone "are or will be loaded.\n" 4307b9c1b51eSKate Stone "Disabling option means breakpoints will no longer be set on any " 4308b9c1b51eSKate Stone "kernels loaded in the future, " 43097dc7771cSEwan Crawford "but does not remove currently set breakpoints.", 43107dc7771cSEwan Crawford "renderscript kernel breakpoint all <enable/disable>", 4311b9c1b51eSKate Stone eCommandRequiresProcess | eCommandProcessMustBeLaunched | 4312b9c1b51eSKate Stone eCommandProcessMustBePaused) {} 43137dc7771cSEwan Crawford 4314222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeKernelBreakpointAll() override = default; 43157dc7771cSEwan Crawford 4316b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 43177dc7771cSEwan Crawford const size_t argc = command.GetArgumentCount(); 4318b9c1b51eSKate Stone if (argc != 1) { 4319b9c1b51eSKate Stone result.AppendErrorWithFormat( 4320b9c1b51eSKate Stone "'%s' takes 1 argument of 'enable' or 'disable'", m_cmd_name.c_str()); 43217dc7771cSEwan Crawford return false; 43227dc7771cSEwan Crawford } 43237dc7771cSEwan Crawford 4324b3f7f69dSAidan Dodds RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>( 4325b9c1b51eSKate Stone m_exe_ctx.GetProcessPtr()->GetLanguageRuntime( 4326b9c1b51eSKate Stone eLanguageTypeExtRenderScript)); 43277dc7771cSEwan Crawford 43287dc7771cSEwan Crawford bool do_break = false; 43297dc7771cSEwan Crawford const char *argument = command.GetArgumentAtIndex(0); 4330b9c1b51eSKate Stone if (strcmp(argument, "enable") == 0) { 43317dc7771cSEwan Crawford do_break = true; 43327dc7771cSEwan Crawford result.AppendMessage("Breakpoints will be set on all kernels."); 4333b9c1b51eSKate Stone } else if (strcmp(argument, "disable") == 0) { 43347dc7771cSEwan Crawford do_break = false; 43357dc7771cSEwan Crawford result.AppendMessage("Breakpoints will not be set on any new kernels."); 4336b9c1b51eSKate Stone } else { 4337b9c1b51eSKate Stone result.AppendErrorWithFormat( 4338b9c1b51eSKate Stone "Argument must be either 'enable' or 'disable'"); 43397dc7771cSEwan Crawford return false; 43407dc7771cSEwan Crawford } 43417dc7771cSEwan Crawford 43427dc7771cSEwan Crawford runtime->SetBreakAllKernels(do_break, m_exe_ctx.GetTargetSP()); 43437dc7771cSEwan Crawford 43447dc7771cSEwan Crawford result.SetStatus(eReturnStatusSuccessFinishResult); 43457dc7771cSEwan Crawford return true; 43467dc7771cSEwan Crawford } 43477dc7771cSEwan Crawford }; 43487dc7771cSEwan Crawford 4349b3bbcb12SLuke Drummond class CommandObjectRenderScriptRuntimeReductionBreakpoint 4350b3bbcb12SLuke Drummond : public CommandObjectMultiword { 4351b3bbcb12SLuke Drummond public: 4352b3bbcb12SLuke Drummond CommandObjectRenderScriptRuntimeReductionBreakpoint( 4353b3bbcb12SLuke Drummond CommandInterpreter &interpreter) 4354b3bbcb12SLuke Drummond : CommandObjectMultiword(interpreter, "renderscript reduction breakpoint", 4355b3bbcb12SLuke Drummond "Commands that manipulate breakpoints on " 4356b3bbcb12SLuke Drummond "renderscript general reductions.", 4357b3bbcb12SLuke Drummond nullptr) { 4358b3bbcb12SLuke Drummond LoadSubCommand( 4359b3bbcb12SLuke Drummond "set", CommandObjectSP( 4360b3bbcb12SLuke Drummond new CommandObjectRenderScriptRuntimeReductionBreakpointSet( 4361b3bbcb12SLuke Drummond interpreter))); 4362b3bbcb12SLuke Drummond } 4363b3bbcb12SLuke Drummond 4364b3bbcb12SLuke Drummond ~CommandObjectRenderScriptRuntimeReductionBreakpoint() override = default; 4365b3bbcb12SLuke Drummond }; 4366b3bbcb12SLuke Drummond 4367b9c1b51eSKate Stone class CommandObjectRenderScriptRuntimeKernelCoordinate 4368b9c1b51eSKate Stone : public CommandObjectParsed { 43694f8817c2SEwan Crawford public: 4370b9c1b51eSKate Stone CommandObjectRenderScriptRuntimeKernelCoordinate( 4371b9c1b51eSKate Stone CommandInterpreter &interpreter) 4372b9c1b51eSKate Stone : CommandObjectParsed( 4373b9c1b51eSKate Stone interpreter, "renderscript kernel coordinate", 43744f8817c2SEwan Crawford "Shows the (x,y,z) coordinate of the current kernel invocation.", 43754f8817c2SEwan Crawford "renderscript kernel coordinate", 4376b9c1b51eSKate Stone eCommandRequiresProcess | eCommandProcessMustBeLaunched | 4377b9c1b51eSKate Stone eCommandProcessMustBePaused) {} 43784f8817c2SEwan Crawford 43794f8817c2SEwan Crawford ~CommandObjectRenderScriptRuntimeKernelCoordinate() override = default; 43804f8817c2SEwan Crawford 4381b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 438200f56eebSLuke Drummond RSCoordinate coord{}; 4383b9c1b51eSKate Stone bool success = RenderScriptRuntime::GetKernelCoordinate( 4384b9c1b51eSKate Stone coord, m_exe_ctx.GetThreadPtr()); 43854f8817c2SEwan Crawford Stream &stream = result.GetOutputStream(); 43864f8817c2SEwan Crawford 4387b9c1b51eSKate Stone if (success) { 438800f56eebSLuke Drummond stream.Printf("Coordinate: " FMT_COORD, coord.x, coord.y, coord.z); 43894f8817c2SEwan Crawford stream.EOL(); 43904f8817c2SEwan Crawford result.SetStatus(eReturnStatusSuccessFinishResult); 4391b9c1b51eSKate Stone } else { 43924f8817c2SEwan Crawford stream.Printf("Error: Coordinate could not be found."); 43934f8817c2SEwan Crawford stream.EOL(); 43944f8817c2SEwan Crawford result.SetStatus(eReturnStatusFailed); 43954f8817c2SEwan Crawford } 43964f8817c2SEwan Crawford return true; 43974f8817c2SEwan Crawford } 43984f8817c2SEwan Crawford }; 43994f8817c2SEwan Crawford 4400b9c1b51eSKate Stone class CommandObjectRenderScriptRuntimeKernelBreakpoint 4401b9c1b51eSKate Stone : public CommandObjectMultiword { 44027dc7771cSEwan Crawford public: 4403b9c1b51eSKate Stone CommandObjectRenderScriptRuntimeKernelBreakpoint( 4404b9c1b51eSKate Stone CommandInterpreter &interpreter) 4405b9c1b51eSKate Stone : CommandObjectMultiword( 4406b9c1b51eSKate Stone interpreter, "renderscript kernel", 4407b9c1b51eSKate Stone "Commands that generate breakpoints on renderscript kernels.", 4408b9c1b51eSKate Stone nullptr) { 4409b9c1b51eSKate Stone LoadSubCommand( 4410b9c1b51eSKate Stone "set", 4411b9c1b51eSKate Stone CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointSet( 4412b9c1b51eSKate Stone interpreter))); 4413b9c1b51eSKate Stone LoadSubCommand( 4414b9c1b51eSKate Stone "all", 4415b9c1b51eSKate Stone CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointAll( 4416b9c1b51eSKate Stone interpreter))); 44177dc7771cSEwan Crawford } 44187dc7771cSEwan Crawford 4419222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeKernelBreakpoint() override = default; 44207dc7771cSEwan Crawford }; 44217dc7771cSEwan Crawford 4422b9c1b51eSKate Stone class CommandObjectRenderScriptRuntimeKernel : public CommandObjectMultiword { 44234640cde1SColin Riley public: 44244640cde1SColin Riley CommandObjectRenderScriptRuntimeKernel(CommandInterpreter &interpreter) 4425b9c1b51eSKate Stone : CommandObjectMultiword(interpreter, "renderscript kernel", 4426b9c1b51eSKate Stone "Commands that deal with RenderScript kernels.", 4427b9c1b51eSKate Stone nullptr) { 4428b9c1b51eSKate Stone LoadSubCommand( 4429b9c1b51eSKate Stone "list", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelList( 4430b9c1b51eSKate Stone interpreter))); 4431b9c1b51eSKate Stone LoadSubCommand( 4432b9c1b51eSKate Stone "coordinate", 4433b9c1b51eSKate Stone CommandObjectSP( 4434b9c1b51eSKate Stone new CommandObjectRenderScriptRuntimeKernelCoordinate(interpreter))); 4435b9c1b51eSKate Stone LoadSubCommand( 4436b9c1b51eSKate Stone "breakpoint", 4437b9c1b51eSKate Stone CommandObjectSP( 4438b9c1b51eSKate Stone new CommandObjectRenderScriptRuntimeKernelBreakpoint(interpreter))); 44394640cde1SColin Riley } 44404640cde1SColin Riley 4441222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeKernel() override = default; 44424640cde1SColin Riley }; 44434640cde1SColin Riley 4444b9c1b51eSKate Stone class CommandObjectRenderScriptRuntimeContextDump : public CommandObjectParsed { 44454640cde1SColin Riley public: 44464640cde1SColin Riley CommandObjectRenderScriptRuntimeContextDump(CommandInterpreter &interpreter) 4447b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "renderscript context dump", 4448b9c1b51eSKate Stone "Dumps renderscript context information.", 4449b9c1b51eSKate Stone "renderscript context dump", 4450b9c1b51eSKate Stone eCommandRequiresProcess | 4451b9c1b51eSKate Stone eCommandProcessMustBeLaunched) {} 44524640cde1SColin Riley 4453222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeContextDump() override = default; 44544640cde1SColin Riley 4455b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 4456056f6f18SAlex Langford RenderScriptRuntime *runtime = llvm::cast<RenderScriptRuntime>( 4457056f6f18SAlex Langford m_exe_ctx.GetProcessPtr()->GetLanguageRuntime( 4458056f6f18SAlex Langford eLanguageTypeExtRenderScript)); 44594640cde1SColin Riley runtime->DumpContexts(result.GetOutputStream()); 44604640cde1SColin Riley result.SetStatus(eReturnStatusSuccessFinishResult); 44614640cde1SColin Riley return true; 44624640cde1SColin Riley } 44634640cde1SColin Riley }; 44644640cde1SColin Riley 44658fe53c49STatyana Krasnukha static constexpr OptionDefinition g_renderscript_runtime_alloc_dump_options[] = { 44661f0f5b5bSZachary Turner {LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, 44678fe53c49STatyana Krasnukha nullptr, {}, 0, eArgTypeFilename, 44681f0f5b5bSZachary Turner "Print results to specified file instead of command line."}}; 44691f0f5b5bSZachary Turner 4470b9c1b51eSKate Stone class CommandObjectRenderScriptRuntimeContext : public CommandObjectMultiword { 44714640cde1SColin Riley public: 44724640cde1SColin Riley CommandObjectRenderScriptRuntimeContext(CommandInterpreter &interpreter) 4473b9c1b51eSKate Stone : CommandObjectMultiword(interpreter, "renderscript context", 4474b9c1b51eSKate Stone "Commands that deal with RenderScript contexts.", 4475b9c1b51eSKate Stone nullptr) { 4476b9c1b51eSKate Stone LoadSubCommand( 4477b9c1b51eSKate Stone "dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeContextDump( 4478b9c1b51eSKate Stone interpreter))); 44794640cde1SColin Riley } 44804640cde1SColin Riley 4481222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeContext() override = default; 44824640cde1SColin Riley }; 44834640cde1SColin Riley 4484b9c1b51eSKate Stone class CommandObjectRenderScriptRuntimeAllocationDump 4485b9c1b51eSKate Stone : public CommandObjectParsed { 4486a0f08674SEwan Crawford public: 4487b9c1b51eSKate Stone CommandObjectRenderScriptRuntimeAllocationDump( 4488b9c1b51eSKate Stone CommandInterpreter &interpreter) 4489a0f08674SEwan Crawford : CommandObjectParsed(interpreter, "renderscript allocation dump", 4490b9c1b51eSKate Stone "Displays the contents of a particular allocation", 4491b9c1b51eSKate Stone "renderscript allocation dump <ID>", 4492b9c1b51eSKate Stone eCommandRequiresProcess | 4493b9c1b51eSKate Stone eCommandProcessMustBeLaunched), 4494b9c1b51eSKate Stone m_options() {} 4495a0f08674SEwan Crawford 4496222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeAllocationDump() override = default; 4497222b937cSEugene Zelenko 4498b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 4499a0f08674SEwan Crawford 4500b9c1b51eSKate Stone class CommandOptions : public Options { 4501a0f08674SEwan Crawford public: 4502e1cfbc79STodd Fiala CommandOptions() : Options() {} 4503a0f08674SEwan Crawford 4504222b937cSEugene Zelenko ~CommandOptions() override = default; 4505a0f08674SEwan Crawford 450697206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 4507b3bbcb12SLuke Drummond ExecutionContext *exe_ctx) override { 450897206d57SZachary Turner Status err; 4509a0f08674SEwan Crawford const int short_option = m_getopt_table[option_idx].val; 4510a0f08674SEwan Crawford 4511b9c1b51eSKate Stone switch (short_option) { 4512a0f08674SEwan Crawford case 'f': 45138f3be7a3SJonas Devlieghere m_outfile.SetFile(option_arg, FileSpec::Style::native); 45148f3be7a3SJonas Devlieghere FileSystem::Instance().Resolve(m_outfile); 4515dbd7fabaSJonas Devlieghere if (FileSystem::Instance().Exists(m_outfile)) { 4516a0f08674SEwan Crawford m_outfile.Clear(); 4517fe11483bSZachary Turner err.SetErrorStringWithFormat("file already exists: '%s'", 4518fe11483bSZachary Turner option_arg.str().c_str()); 4519a0f08674SEwan Crawford } 4520a0f08674SEwan Crawford break; 4521a0f08674SEwan Crawford default: 452280af0b9eSLuke Drummond err.SetErrorStringWithFormat("unrecognized option '%c'", short_option); 4523a0f08674SEwan Crawford break; 4524a0f08674SEwan Crawford } 452580af0b9eSLuke Drummond return err; 4526a0f08674SEwan Crawford } 4527a0f08674SEwan Crawford 4528b3bbcb12SLuke Drummond void OptionParsingStarting(ExecutionContext *exe_ctx) override { 4529a0f08674SEwan Crawford m_outfile.Clear(); 4530a0f08674SEwan Crawford } 4531a0f08674SEwan Crawford 45321f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 453370602439SZachary Turner return llvm::makeArrayRef(g_renderscript_runtime_alloc_dump_options); 45341f0f5b5bSZachary Turner } 4535a0f08674SEwan Crawford 4536a0f08674SEwan Crawford FileSpec m_outfile; 4537a0f08674SEwan Crawford }; 4538a0f08674SEwan Crawford 4539b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 4540a0f08674SEwan Crawford const size_t argc = command.GetArgumentCount(); 4541b9c1b51eSKate Stone if (argc < 1) { 4542b9c1b51eSKate Stone result.AppendErrorWithFormat("'%s' takes 1 argument, an allocation ID. " 4543b9c1b51eSKate Stone "As well as an optional -f argument", 4544a0f08674SEwan Crawford m_cmd_name.c_str()); 4545a0f08674SEwan Crawford return false; 4546a0f08674SEwan Crawford } 4547a0f08674SEwan Crawford 4548b3f7f69dSAidan Dodds RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>( 4549b9c1b51eSKate Stone m_exe_ctx.GetProcessPtr()->GetLanguageRuntime( 4550b9c1b51eSKate Stone eLanguageTypeExtRenderScript)); 4551a0f08674SEwan Crawford 4552a0f08674SEwan Crawford const char *id_cstr = command.GetArgumentAtIndex(0); 45533a6ba367SMichał Górny uint32_t id; 45543a6ba367SMichał Górny if (!llvm::to_integer(id_cstr, id)) { 4555b9c1b51eSKate Stone result.AppendErrorWithFormat("invalid allocation id argument '%s'", 4556b9c1b51eSKate Stone id_cstr); 4557a0f08674SEwan Crawford return false; 4558a0f08674SEwan Crawford } 4559a0f08674SEwan Crawford 45602fce1137SLawrence D'Anna Stream *output_stream_p = nullptr; 45612fce1137SLawrence D'Anna std::unique_ptr<Stream> output_stream_storage; 45622fce1137SLawrence D'Anna 4563b9c1b51eSKate Stone const FileSpec &outfile_spec = 4564b9c1b51eSKate Stone m_options.m_outfile; // Dump allocation to file instead 4565b9c1b51eSKate Stone if (outfile_spec) { 4566a0f08674SEwan Crawford // Open output file 456750bc1ed2SJonas Devlieghere std::string path = outfile_spec.GetPath(); 456814735cabSMichał Górny auto file = FileSystem::Instance().Open(outfile_spec, 456914735cabSMichał Górny File::eOpenOptionWriteOnly | 457014735cabSMichał Górny File::eOpenOptionCanCreate); 45712fce1137SLawrence D'Anna if (file) { 45722fce1137SLawrence D'Anna output_stream_storage = 45732fce1137SLawrence D'Anna std::make_unique<StreamFile>(std::move(file.get())); 45742fce1137SLawrence D'Anna output_stream_p = output_stream_storage.get(); 457550bc1ed2SJonas Devlieghere result.GetOutputStream().Printf("Results written to '%s'", 457650bc1ed2SJonas Devlieghere path.c_str()); 4577a0f08674SEwan Crawford result.GetOutputStream().EOL(); 4578b9c1b51eSKate Stone } else { 45792fce1137SLawrence D'Anna std::string error = llvm::toString(file.takeError()); 45802fce1137SLawrence D'Anna result.AppendErrorWithFormat("Couldn't open file '%s': %s", 45812fce1137SLawrence D'Anna path.c_str(), error.c_str()); 4582a0f08674SEwan Crawford return false; 4583a0f08674SEwan Crawford } 4584b9c1b51eSKate Stone } else 45852fce1137SLawrence D'Anna output_stream_p = &result.GetOutputStream(); 4586a0f08674SEwan Crawford 45872fce1137SLawrence D'Anna assert(output_stream_p != nullptr); 458880af0b9eSLuke Drummond bool dumped = 45892fce1137SLawrence D'Anna runtime->DumpAllocation(*output_stream_p, m_exe_ctx.GetFramePtr(), id); 4590a0f08674SEwan Crawford 459180af0b9eSLuke Drummond if (dumped) 4592a0f08674SEwan Crawford result.SetStatus(eReturnStatusSuccessFinishResult); 4593a0f08674SEwan Crawford else 4594a0f08674SEwan Crawford result.SetStatus(eReturnStatusFailed); 4595a0f08674SEwan Crawford 4596a0f08674SEwan Crawford return true; 4597a0f08674SEwan Crawford } 4598a0f08674SEwan Crawford 4599a0f08674SEwan Crawford private: 4600a0f08674SEwan Crawford CommandOptions m_options; 4601a0f08674SEwan Crawford }; 4602a0f08674SEwan Crawford 46038fe53c49STatyana Krasnukha static constexpr OptionDefinition g_renderscript_runtime_alloc_list_options[] = { 46041f0f5b5bSZachary Turner {LLDB_OPT_SET_1, false, "id", 'i', OptionParser::eRequiredArgument, nullptr, 46058fe53c49STatyana Krasnukha {}, 0, eArgTypeIndex, 46061f0f5b5bSZachary Turner "Only show details of a single allocation with specified id."}}; 4607a0f08674SEwan Crawford 4608b9c1b51eSKate Stone class CommandObjectRenderScriptRuntimeAllocationList 4609b9c1b51eSKate Stone : public CommandObjectParsed { 461015f2bd95SEwan Crawford public: 4611b9c1b51eSKate Stone CommandObjectRenderScriptRuntimeAllocationList( 4612b9c1b51eSKate Stone CommandInterpreter &interpreter) 4613b9c1b51eSKate Stone : CommandObjectParsed( 4614b9c1b51eSKate Stone interpreter, "renderscript allocation list", 4615b9c1b51eSKate Stone "List renderscript allocations and their information.", 4616b9c1b51eSKate Stone "renderscript allocation list", 4617b3f7f69dSAidan Dodds eCommandRequiresProcess | eCommandProcessMustBeLaunched), 4618b9c1b51eSKate Stone m_options() {} 461915f2bd95SEwan Crawford 4620222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeAllocationList() override = default; 4621222b937cSEugene Zelenko 4622b9c1b51eSKate Stone Options *GetOptions() override { return &m_options; } 462315f2bd95SEwan Crawford 4624b9c1b51eSKate Stone class CommandOptions : public Options { 462515f2bd95SEwan Crawford public: 46269494c510SJonas Devlieghere CommandOptions() : Options() {} 462715f2bd95SEwan Crawford 4628222b937cSEugene Zelenko ~CommandOptions() override = default; 462915f2bd95SEwan Crawford 463097206d57SZachary Turner Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 4631b3bbcb12SLuke Drummond ExecutionContext *exe_ctx) override { 463297206d57SZachary Turner Status err; 463315f2bd95SEwan Crawford const int short_option = m_getopt_table[option_idx].val; 463415f2bd95SEwan Crawford 4635b9c1b51eSKate Stone switch (short_option) { 4636b649b005SEwan Crawford case 'i': 4637fe11483bSZachary Turner if (option_arg.getAsInteger(0, m_id)) 463880af0b9eSLuke Drummond err.SetErrorStringWithFormat("invalid integer value for option '%c'", 4639b9c1b51eSKate Stone short_option); 464015f2bd95SEwan Crawford break; 464180af0b9eSLuke Drummond default: 464280af0b9eSLuke Drummond err.SetErrorStringWithFormat("unrecognized option '%c'", short_option); 464380af0b9eSLuke Drummond break; 464415f2bd95SEwan Crawford } 464580af0b9eSLuke Drummond return err; 464615f2bd95SEwan Crawford } 464715f2bd95SEwan Crawford 4648b3bbcb12SLuke Drummond void OptionParsingStarting(ExecutionContext *exe_ctx) override { m_id = 0; } 464915f2bd95SEwan Crawford 46501f0f5b5bSZachary Turner llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 465170602439SZachary Turner return llvm::makeArrayRef(g_renderscript_runtime_alloc_list_options); 46521f0f5b5bSZachary Turner } 465315f2bd95SEwan Crawford 46549494c510SJonas Devlieghere uint32_t m_id = 0; 465515f2bd95SEwan Crawford }; 465615f2bd95SEwan Crawford 4657b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 4658b3f7f69dSAidan Dodds RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>( 4659b9c1b51eSKate Stone m_exe_ctx.GetProcessPtr()->GetLanguageRuntime( 4660b9c1b51eSKate Stone eLanguageTypeExtRenderScript)); 4661b9c1b51eSKate Stone runtime->ListAllocations(result.GetOutputStream(), m_exe_ctx.GetFramePtr(), 4662b9c1b51eSKate Stone m_options.m_id); 466315f2bd95SEwan Crawford result.SetStatus(eReturnStatusSuccessFinishResult); 466415f2bd95SEwan Crawford return true; 466515f2bd95SEwan Crawford } 466615f2bd95SEwan Crawford 466715f2bd95SEwan Crawford private: 466815f2bd95SEwan Crawford CommandOptions m_options; 466915f2bd95SEwan Crawford }; 467015f2bd95SEwan Crawford 4671b9c1b51eSKate Stone class CommandObjectRenderScriptRuntimeAllocationLoad 4672b9c1b51eSKate Stone : public CommandObjectParsed { 467355232f09SEwan Crawford public: 4674b9c1b51eSKate Stone CommandObjectRenderScriptRuntimeAllocationLoad( 4675b9c1b51eSKate Stone CommandInterpreter &interpreter) 4676b3f7f69dSAidan Dodds : CommandObjectParsed( 4677b9c1b51eSKate Stone interpreter, "renderscript allocation load", 4678b9c1b51eSKate Stone "Loads renderscript allocation contents from a file.", 4679b9c1b51eSKate Stone "renderscript allocation load <ID> <filename>", 4680b9c1b51eSKate Stone eCommandRequiresProcess | eCommandProcessMustBeLaunched) {} 468155232f09SEwan Crawford 4682222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeAllocationLoad() override = default; 468355232f09SEwan Crawford 4684b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 468555232f09SEwan Crawford const size_t argc = command.GetArgumentCount(); 4686b9c1b51eSKate Stone if (argc != 2) { 4687b9c1b51eSKate Stone result.AppendErrorWithFormat( 4688b9c1b51eSKate Stone "'%s' takes 2 arguments, an allocation ID and filename to read from.", 4689b3f7f69dSAidan Dodds m_cmd_name.c_str()); 469055232f09SEwan Crawford return false; 469155232f09SEwan Crawford } 469255232f09SEwan Crawford 4693b3f7f69dSAidan Dodds RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>( 4694b9c1b51eSKate Stone m_exe_ctx.GetProcessPtr()->GetLanguageRuntime( 4695b9c1b51eSKate Stone eLanguageTypeExtRenderScript)); 469655232f09SEwan Crawford 469755232f09SEwan Crawford const char *id_cstr = command.GetArgumentAtIndex(0); 46983a6ba367SMichał Górny uint32_t id; 46993a6ba367SMichał Górny if (!llvm::to_integer(id_cstr, id)) { 4700b9c1b51eSKate Stone result.AppendErrorWithFormat("invalid allocation id argument '%s'", 4701b9c1b51eSKate Stone id_cstr); 470255232f09SEwan Crawford return false; 470355232f09SEwan Crawford } 470455232f09SEwan Crawford 470580af0b9eSLuke Drummond const char *path = command.GetArgumentAtIndex(1); 470680af0b9eSLuke Drummond bool loaded = runtime->LoadAllocation(result.GetOutputStream(), id, path, 470780af0b9eSLuke Drummond m_exe_ctx.GetFramePtr()); 470855232f09SEwan Crawford 470980af0b9eSLuke Drummond if (loaded) 471055232f09SEwan Crawford result.SetStatus(eReturnStatusSuccessFinishResult); 471155232f09SEwan Crawford else 471255232f09SEwan Crawford result.SetStatus(eReturnStatusFailed); 471355232f09SEwan Crawford 471455232f09SEwan Crawford return true; 471555232f09SEwan Crawford } 471655232f09SEwan Crawford }; 471755232f09SEwan Crawford 4718b9c1b51eSKate Stone class CommandObjectRenderScriptRuntimeAllocationSave 4719b9c1b51eSKate Stone : public CommandObjectParsed { 472055232f09SEwan Crawford public: 4721b9c1b51eSKate Stone CommandObjectRenderScriptRuntimeAllocationSave( 4722b9c1b51eSKate Stone CommandInterpreter &interpreter) 4723b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "renderscript allocation save", 4724b9c1b51eSKate Stone "Write renderscript allocation contents to a file.", 4725b9c1b51eSKate Stone "renderscript allocation save <ID> <filename>", 4726b9c1b51eSKate Stone eCommandRequiresProcess | 4727b9c1b51eSKate Stone eCommandProcessMustBeLaunched) {} 472855232f09SEwan Crawford 4729222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeAllocationSave() override = default; 473055232f09SEwan Crawford 4731b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 473255232f09SEwan Crawford const size_t argc = command.GetArgumentCount(); 4733b9c1b51eSKate Stone if (argc != 2) { 4734b9c1b51eSKate Stone result.AppendErrorWithFormat( 4735b9c1b51eSKate Stone "'%s' takes 2 arguments, an allocation ID and filename to read from.", 4736b3f7f69dSAidan Dodds m_cmd_name.c_str()); 473755232f09SEwan Crawford return false; 473855232f09SEwan Crawford } 473955232f09SEwan Crawford 4740b3f7f69dSAidan Dodds RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>( 4741b9c1b51eSKate Stone m_exe_ctx.GetProcessPtr()->GetLanguageRuntime( 4742b9c1b51eSKate Stone eLanguageTypeExtRenderScript)); 474355232f09SEwan Crawford 474455232f09SEwan Crawford const char *id_cstr = command.GetArgumentAtIndex(0); 47453a6ba367SMichał Górny uint32_t id; 47463a6ba367SMichał Górny if (!llvm::to_integer(id_cstr, id)) { 4747b9c1b51eSKate Stone result.AppendErrorWithFormat("invalid allocation id argument '%s'", 4748b9c1b51eSKate Stone id_cstr); 474955232f09SEwan Crawford return false; 475055232f09SEwan Crawford } 475155232f09SEwan Crawford 475280af0b9eSLuke Drummond const char *path = command.GetArgumentAtIndex(1); 475380af0b9eSLuke Drummond bool saved = runtime->SaveAllocation(result.GetOutputStream(), id, path, 475480af0b9eSLuke Drummond m_exe_ctx.GetFramePtr()); 475555232f09SEwan Crawford 475680af0b9eSLuke Drummond if (saved) 475755232f09SEwan Crawford result.SetStatus(eReturnStatusSuccessFinishResult); 475855232f09SEwan Crawford else 475955232f09SEwan Crawford result.SetStatus(eReturnStatusFailed); 476055232f09SEwan Crawford 476155232f09SEwan Crawford return true; 476255232f09SEwan Crawford } 476355232f09SEwan Crawford }; 476455232f09SEwan Crawford 4765b9c1b51eSKate Stone class CommandObjectRenderScriptRuntimeAllocationRefresh 4766b9c1b51eSKate Stone : public CommandObjectParsed { 47670d2bfcfbSEwan Crawford public: 4768b9c1b51eSKate Stone CommandObjectRenderScriptRuntimeAllocationRefresh( 4769b9c1b51eSKate Stone CommandInterpreter &interpreter) 47700d2bfcfbSEwan Crawford : CommandObjectParsed(interpreter, "renderscript allocation refresh", 4771b9c1b51eSKate Stone "Recomputes the details of all allocations.", 4772b9c1b51eSKate Stone "renderscript allocation refresh", 4773b9c1b51eSKate Stone eCommandRequiresProcess | 4774b9c1b51eSKate Stone eCommandProcessMustBeLaunched) {} 47750d2bfcfbSEwan Crawford 47760d2bfcfbSEwan Crawford ~CommandObjectRenderScriptRuntimeAllocationRefresh() override = default; 47770d2bfcfbSEwan Crawford 4778b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 47790d2bfcfbSEwan Crawford RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>( 4780b9c1b51eSKate Stone m_exe_ctx.GetProcessPtr()->GetLanguageRuntime( 4781b9c1b51eSKate Stone eLanguageTypeExtRenderScript)); 47820d2bfcfbSEwan Crawford 4783b9c1b51eSKate Stone bool success = runtime->RecomputeAllAllocations(result.GetOutputStream(), 4784b9c1b51eSKate Stone m_exe_ctx.GetFramePtr()); 47850d2bfcfbSEwan Crawford 4786b9c1b51eSKate Stone if (success) { 47870d2bfcfbSEwan Crawford result.SetStatus(eReturnStatusSuccessFinishResult); 47880d2bfcfbSEwan Crawford return true; 4789b9c1b51eSKate Stone } else { 47900d2bfcfbSEwan Crawford result.SetStatus(eReturnStatusFailed); 47910d2bfcfbSEwan Crawford return false; 47920d2bfcfbSEwan Crawford } 47930d2bfcfbSEwan Crawford } 47940d2bfcfbSEwan Crawford }; 47950d2bfcfbSEwan Crawford 4796b9c1b51eSKate Stone class CommandObjectRenderScriptRuntimeAllocation 4797b9c1b51eSKate Stone : public CommandObjectMultiword { 479815f2bd95SEwan Crawford public: 479915f2bd95SEwan Crawford CommandObjectRenderScriptRuntimeAllocation(CommandInterpreter &interpreter) 4800b9c1b51eSKate Stone : CommandObjectMultiword( 4801b9c1b51eSKate Stone interpreter, "renderscript allocation", 4802b9c1b51eSKate Stone "Commands that deal with RenderScript allocations.", nullptr) { 4803b9c1b51eSKate Stone LoadSubCommand( 4804b9c1b51eSKate Stone "list", 4805b9c1b51eSKate Stone CommandObjectSP( 4806b9c1b51eSKate Stone new CommandObjectRenderScriptRuntimeAllocationList(interpreter))); 4807b9c1b51eSKate Stone LoadSubCommand( 4808b9c1b51eSKate Stone "dump", 4809b9c1b51eSKate Stone CommandObjectSP( 4810b9c1b51eSKate Stone new CommandObjectRenderScriptRuntimeAllocationDump(interpreter))); 4811b9c1b51eSKate Stone LoadSubCommand( 4812b9c1b51eSKate Stone "save", 4813b9c1b51eSKate Stone CommandObjectSP( 4814b9c1b51eSKate Stone new CommandObjectRenderScriptRuntimeAllocationSave(interpreter))); 4815b9c1b51eSKate Stone LoadSubCommand( 4816b9c1b51eSKate Stone "load", 4817b9c1b51eSKate Stone CommandObjectSP( 4818b9c1b51eSKate Stone new CommandObjectRenderScriptRuntimeAllocationLoad(interpreter))); 4819b9c1b51eSKate Stone LoadSubCommand( 4820b9c1b51eSKate Stone "refresh", 4821b9c1b51eSKate Stone CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationRefresh( 4822b9c1b51eSKate Stone interpreter))); 482315f2bd95SEwan Crawford } 482415f2bd95SEwan Crawford 4825222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeAllocation() override = default; 482615f2bd95SEwan Crawford }; 482715f2bd95SEwan Crawford 4828b9c1b51eSKate Stone class CommandObjectRenderScriptRuntimeStatus : public CommandObjectParsed { 48294640cde1SColin Riley public: 48304640cde1SColin Riley CommandObjectRenderScriptRuntimeStatus(CommandInterpreter &interpreter) 4831b9c1b51eSKate Stone : CommandObjectParsed(interpreter, "renderscript status", 4832b9c1b51eSKate Stone "Displays current RenderScript runtime status.", 4833b9c1b51eSKate Stone "renderscript status", 4834b9c1b51eSKate Stone eCommandRequiresProcess | 4835b9c1b51eSKate Stone eCommandProcessMustBeLaunched) {} 48364640cde1SColin Riley 4837222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntimeStatus() override = default; 48384640cde1SColin Riley 4839b9c1b51eSKate Stone bool DoExecute(Args &command, CommandReturnObject &result) override { 4840056f6f18SAlex Langford RenderScriptRuntime *runtime = llvm::cast<RenderScriptRuntime>( 4841056f6f18SAlex Langford m_exe_ctx.GetProcessPtr()->GetLanguageRuntime( 4842056f6f18SAlex Langford eLanguageTypeExtRenderScript)); 484397206d57SZachary Turner runtime->DumpStatus(result.GetOutputStream()); 48444640cde1SColin Riley result.SetStatus(eReturnStatusSuccessFinishResult); 48454640cde1SColin Riley return true; 48464640cde1SColin Riley } 48474640cde1SColin Riley }; 48484640cde1SColin Riley 4849b3bbcb12SLuke Drummond class CommandObjectRenderScriptRuntimeReduction 4850b3bbcb12SLuke Drummond : public CommandObjectMultiword { 4851b3bbcb12SLuke Drummond public: 4852b3bbcb12SLuke Drummond CommandObjectRenderScriptRuntimeReduction(CommandInterpreter &interpreter) 4853b3bbcb12SLuke Drummond : CommandObjectMultiword(interpreter, "renderscript reduction", 4854b3bbcb12SLuke Drummond "Commands that handle general reduction kernels", 4855b3bbcb12SLuke Drummond nullptr) { 4856b3bbcb12SLuke Drummond LoadSubCommand( 4857b3bbcb12SLuke Drummond "breakpoint", 4858b3bbcb12SLuke Drummond CommandObjectSP(new CommandObjectRenderScriptRuntimeReductionBreakpoint( 4859b3bbcb12SLuke Drummond interpreter))); 4860b3bbcb12SLuke Drummond } 4861b3bbcb12SLuke Drummond ~CommandObjectRenderScriptRuntimeReduction() override = default; 4862b3bbcb12SLuke Drummond }; 4863b3bbcb12SLuke Drummond 4864b9c1b51eSKate Stone class CommandObjectRenderScriptRuntime : public CommandObjectMultiword { 48655ec532a9SColin Riley public: 48665ec532a9SColin Riley CommandObjectRenderScriptRuntime(CommandInterpreter &interpreter) 4867b9c1b51eSKate Stone : CommandObjectMultiword( 4868b9c1b51eSKate Stone interpreter, "renderscript", 4869b9c1b51eSKate Stone "Commands for operating on the RenderScript runtime.", 4870b9c1b51eSKate Stone "renderscript <subcommand> [<subcommand-options>]") { 4871b9c1b51eSKate Stone LoadSubCommand( 4872b9c1b51eSKate Stone "module", CommandObjectSP( 4873b9c1b51eSKate Stone new CommandObjectRenderScriptRuntimeModule(interpreter))); 4874b9c1b51eSKate Stone LoadSubCommand( 4875b9c1b51eSKate Stone "status", CommandObjectSP( 4876b9c1b51eSKate Stone new CommandObjectRenderScriptRuntimeStatus(interpreter))); 4877b9c1b51eSKate Stone LoadSubCommand( 4878b9c1b51eSKate Stone "kernel", CommandObjectSP( 4879b9c1b51eSKate Stone new CommandObjectRenderScriptRuntimeKernel(interpreter))); 4880b9c1b51eSKate Stone LoadSubCommand("context", 4881b9c1b51eSKate Stone CommandObjectSP(new CommandObjectRenderScriptRuntimeContext( 4882b9c1b51eSKate Stone interpreter))); 4883b9c1b51eSKate Stone LoadSubCommand( 4884b9c1b51eSKate Stone "allocation", 4885b9c1b51eSKate Stone CommandObjectSP( 4886b9c1b51eSKate Stone new CommandObjectRenderScriptRuntimeAllocation(interpreter))); 488721fed052SAidan Dodds LoadSubCommand("scriptgroup", 488821fed052SAidan Dodds NewCommandObjectRenderScriptScriptGroup(interpreter)); 4889b3bbcb12SLuke Drummond LoadSubCommand( 4890b3bbcb12SLuke Drummond "reduction", 4891b3bbcb12SLuke Drummond CommandObjectSP( 4892b3bbcb12SLuke Drummond new CommandObjectRenderScriptRuntimeReduction(interpreter))); 48935ec532a9SColin Riley } 48945ec532a9SColin Riley 4895222b937cSEugene Zelenko ~CommandObjectRenderScriptRuntime() override = default; 48965ec532a9SColin Riley }; 4897ef20b08fSColin Riley 4898b9c1b51eSKate Stone void RenderScriptRuntime::Initiate() { assert(!m_initiated); } 4899ef20b08fSColin Riley 4900ef20b08fSColin Riley RenderScriptRuntime::RenderScriptRuntime(Process *process) 4901b9c1b51eSKate Stone : lldb_private::CPPLanguageRuntime(process), m_initiated(false), 4902b9c1b51eSKate Stone m_debuggerPresentFlagged(false), m_breakAllKernels(false), 4903b9c1b51eSKate Stone m_ir_passes(nullptr) { 49044640cde1SColin Riley ModulesDidLoad(process->GetTarget().GetImages()); 4905ef20b08fSColin Riley } 49064640cde1SColin Riley 4907b9c1b51eSKate Stone lldb::CommandObjectSP RenderScriptRuntime::GetCommandObject( 4908b9c1b51eSKate Stone lldb_private::CommandInterpreter &interpreter) { 49090a66e2f1SEnrico Granata return CommandObjectSP(new CommandObjectRenderScriptRuntime(interpreter)); 49104640cde1SColin Riley } 49114640cde1SColin Riley 491278f339d1SEwan Crawford RenderScriptRuntime::~RenderScriptRuntime() = default; 4913