//===-- RenderScriptRuntime.cpp -------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "RenderScriptRuntime.h"
#include "RenderScriptScriptGroup.h"

#include "lldb/Breakpoint/StoppointCallbackContext.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/DumpDataExtractor.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/DataFormatters/DumpValueObjectOptions.h"
#include "lldb/Expression/UserExpression.h"
#include "lldb/Host/OptionParser.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Interpreter/Options.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/SectionLoadList.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/Args.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/Status.h"

#include "llvm/ADT/StringSwitch.h"

#include <memory>

using namespace lldb;
using namespace lldb_private;
using namespace lldb_renderscript;

LLDB_PLUGIN_DEFINE(RenderScriptRuntime)

#define FMT_COORD "(%" PRIu32 ", %" PRIu32 ", %" PRIu32 ")"

char RenderScriptRuntime::ID = 0;

namespace {

// The empirical_type adds a basic level of validation to arbitrary data
// allowing us to track if data has been discovered and stored or not. An
// empirical_type will be marked as valid only if it has been explicitly
// assigned to.
template <typename type_t> class empirical_type {
public:
  // Ctor. Contents is invalid when constructed.
  empirical_type() = default;

  // Return true and copy contents to out if valid, else return false.
  bool get(type_t &out) const {
    if (valid)
      out = data;
    return valid;
  }

  // Return a pointer to the contents or nullptr if it was not valid.
  const type_t *get() const { return valid ? &data : nullptr; }

  // Assign data explicitly.
  void set(const type_t in) {
    data = in;
    valid = true;
  }

  // Mark contents as invalid.
  void invalidate() { valid = false; }

  // Returns true if this type contains valid data.
  bool isValid() const { return valid; }

  // Assignment operator.
  empirical_type<type_t> &operator=(const type_t in) {
    set(in);
    return *this;
  }

  // Dereference operator returns contents.
  // Warning: Will assert if not valid so use only when you know data is valid.
  const type_t &operator*() const {
    assert(valid);
    return data;
  }

protected:
  bool valid = false;
  type_t data;
};

// ArgItem is used by the GetArgs() function when reading function arguments
// from the target.
struct ArgItem {
  enum { ePointer, eInt32, eInt64, eLong, eBool } type;

  uint64_t value;

  explicit operator uint64_t() const { return value; }
};

// Context structure to be passed into GetArgsXXX(), argument reading functions
// below.
struct GetArgsCtx {
  RegisterContext *reg_ctx;
  Process *process;
};

bool GetArgsX86(const GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) {
  Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);

  Status err;

  // get the current stack pointer
  uint64_t sp = ctx.reg_ctx->GetSP();

  for (size_t i = 0; i < num_args; ++i) {
    ArgItem &arg = arg_list[i];
    // advance up the stack by one argument
    sp += sizeof(uint32_t);
    // get the argument type size
    size_t arg_size = sizeof(uint32_t);
    // read the argument from memory
    arg.value = 0;
    Status err;
    size_t read =
        ctx.process->ReadMemory(sp, &arg.value, sizeof(uint32_t), err);
    if (read != arg_size || !err.Success()) {
      LLDB_LOGF(log, "%s - error reading argument: %" PRIu64 " '%s'",
                __FUNCTION__, uint64_t(i), err.AsCString());
      return false;
    }
  }
  return true;
}

bool GetArgsX86_64(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) {
  Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);

  // number of arguments passed in registers
  static const uint32_t args_in_reg = 6;
  // register passing order
  static const std::array<const char *, args_in_reg> reg_names{
      {"rdi", "rsi", "rdx", "rcx", "r8", "r9"}};
  // argument type to size mapping
  static const std::array<size_t, 5> arg_size{{
      8, // ePointer,
      4, // eInt32,
      8, // eInt64,
      8, // eLong,
      4, // eBool,
  }};

  Status err;

  // get the current stack pointer
  uint64_t sp = ctx.reg_ctx->GetSP();
  // step over the return address
  sp += sizeof(uint64_t);

  // check the stack alignment was correct (16 byte aligned)
  if ((sp & 0xf) != 0x0) {
    LLDB_LOGF(log, "%s - stack misaligned", __FUNCTION__);
    return false;
  }

  // find the start of arguments on the stack
  uint64_t sp_offset = 0;
  for (uint32_t i = args_in_reg; i < num_args; ++i) {
    sp_offset += arg_size[arg_list[i].type];
  }
  // round up to multiple of 16
  sp_offset = (sp_offset + 0xf) & 0xf;
  sp += sp_offset;

  for (size_t i = 0; i < num_args; ++i) {
    bool success = false;
    ArgItem &arg = arg_list[i];
    // arguments passed in registers
    if (i < args_in_reg) {
      const RegisterInfo *reg =
          ctx.reg_ctx->GetRegisterInfoByName(reg_names[i]);
      RegisterValue reg_val;
      if (ctx.reg_ctx->ReadRegister(reg, reg_val))
        arg.value = reg_val.GetAsUInt64(0, &success);
    }
    // arguments passed on the stack
    else {
      // get the argument type size
      const size_t size = arg_size[arg_list[i].type];
      // read the argument from memory
      arg.value = 0;
      // note: due to little endian layout reading 4 or 8 bytes will give the
      // correct value.
      size_t read = ctx.process->ReadMemory(sp, &arg.value, size, err);
      success = (err.Success() && read == size);
      // advance past this argument
      sp -= size;
    }
    // fail if we couldn't read this argument
    if (!success) {
      LLDB_LOGF(log, "%s - error reading argument: %" PRIu64 ", reason: %s",
                __FUNCTION__, uint64_t(i), err.AsCString("n/a"));
      return false;
    }
  }
  return true;
}

bool GetArgsArm(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) {
  // number of arguments passed in registers
  static const uint32_t args_in_reg = 4;

  Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);

  Status err;

  // get the current stack pointer
  uint64_t sp = ctx.reg_ctx->GetSP();

  for (size_t i = 0; i < num_args; ++i) {
    bool success = false;
    ArgItem &arg = arg_list[i];
    // arguments passed in registers
    if (i < args_in_reg) {
      const RegisterInfo *reg = ctx.reg_ctx->GetRegisterInfoAtIndex(i);
      RegisterValue reg_val;
      if (ctx.reg_ctx->ReadRegister(reg, reg_val))
        arg.value = reg_val.GetAsUInt32(0, &success);
    }
    // arguments passed on the stack
    else {
      // get the argument type size
      const size_t arg_size = sizeof(uint32_t);
      // clear all 64bits
      arg.value = 0;
      // read this argument from memory
      size_t bytes_read =
          ctx.process->ReadMemory(sp, &arg.value, arg_size, err);
      success = (err.Success() && bytes_read == arg_size);
      // advance the stack pointer
      sp += sizeof(uint32_t);
    }
    // fail if we couldn't read this argument
    if (!success) {
      LLDB_LOGF(log, "%s - error reading argument: %" PRIu64 ", reason: %s",
                __FUNCTION__, uint64_t(i), err.AsCString("n/a"));
      return false;
    }
  }
  return true;
}

bool GetArgsAarch64(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) {
  // number of arguments passed in registers
  static const uint32_t args_in_reg = 8;

  Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);

  for (size_t i = 0; i < num_args; ++i) {
    bool success = false;
    ArgItem &arg = arg_list[i];
    // arguments passed in registers
    if (i < args_in_reg) {
      const RegisterInfo *reg = ctx.reg_ctx->GetRegisterInfoAtIndex(i);
      RegisterValue reg_val;
      if (ctx.reg_ctx->ReadRegister(reg, reg_val))
        arg.value = reg_val.GetAsUInt64(0, &success);
    }
    // arguments passed on the stack
    else {
      LLDB_LOGF(log, "%s - reading arguments spilled to stack not implemented",
                __FUNCTION__);
    }
    // fail if we couldn't read this argument
    if (!success) {
      LLDB_LOGF(log, "%s - error reading argument: %" PRIu64, __FUNCTION__,
                uint64_t(i));
      return false;
    }
  }
  return true;
}

bool GetArgsMipsel(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) {
  // number of arguments passed in registers
  static const uint32_t args_in_reg = 4;
  // register file offset to first argument
  static const uint32_t reg_offset = 4;

  Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);

  Status err;

  // find offset to arguments on the stack (+16 to skip over a0-a3 shadow
  // space)
  uint64_t sp = ctx.reg_ctx->GetSP() + 16;

  for (size_t i = 0; i < num_args; ++i) {
    bool success = false;
    ArgItem &arg = arg_list[i];
    // arguments passed in registers
    if (i < args_in_reg) {
      const RegisterInfo *reg =
          ctx.reg_ctx->GetRegisterInfoAtIndex(i + reg_offset);
      RegisterValue reg_val;
      if (ctx.reg_ctx->ReadRegister(reg, reg_val))
        arg.value = reg_val.GetAsUInt64(0, &success);
    }
    // arguments passed on the stack
    else {
      const size_t arg_size = sizeof(uint32_t);
      arg.value = 0;
      size_t bytes_read =
          ctx.process->ReadMemory(sp, &arg.value, arg_size, err);
      success = (err.Success() && bytes_read == arg_size);
      // advance the stack pointer
      sp += arg_size;
    }
    // fail if we couldn't read this argument
    if (!success) {
      LLDB_LOGF(log, "%s - error reading argument: %" PRIu64 ", reason: %s",
                __FUNCTION__, uint64_t(i), err.AsCString("n/a"));
      return false;
    }
  }
  return true;
}

bool GetArgsMips64el(GetArgsCtx &ctx, ArgItem *arg_list, size_t num_args) {
  // number of arguments passed in registers
  static const uint32_t args_in_reg = 8;
  // register file offset to first argument
  static const uint32_t reg_offset = 4;

  Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);

  Status err;

  // get the current stack pointer
  uint64_t sp = ctx.reg_ctx->GetSP();

  for (size_t i = 0; i < num_args; ++i) {
    bool success = false;
    ArgItem &arg = arg_list[i];
    // arguments passed in registers
    if (i < args_in_reg) {
      const RegisterInfo *reg =
          ctx.reg_ctx->GetRegisterInfoAtIndex(i + reg_offset);
      RegisterValue reg_val;
      if (ctx.reg_ctx->ReadRegister(reg, reg_val))
        arg.value = reg_val.GetAsUInt64(0, &success);
    }
    // arguments passed on the stack
    else {
      // get the argument type size
      const size_t arg_size = sizeof(uint64_t);
      // clear all 64bits
      arg.value = 0;
      // read this argument from memory
      size_t bytes_read =
          ctx.process->ReadMemory(sp, &arg.value, arg_size, err);
      success = (err.Success() && bytes_read == arg_size);
      // advance the stack pointer
      sp += arg_size;
    }
    // fail if we couldn't read this argument
    if (!success) {
      LLDB_LOGF(log, "%s - error reading argument: %" PRIu64 ", reason: %s",
                __FUNCTION__, uint64_t(i), err.AsCString("n/a"));
      return false;
    }
  }
  return true;
}

bool GetArgs(ExecutionContext &exe_ctx, ArgItem *arg_list, size_t num_args) {
  Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);

  // verify that we have a target
  if (!exe_ctx.GetTargetPtr()) {
    LLDB_LOGF(log, "%s - invalid target", __FUNCTION__);
    return false;
  }

  GetArgsCtx ctx = {exe_ctx.GetRegisterContext(), exe_ctx.GetProcessPtr()};
  assert(ctx.reg_ctx && ctx.process);

  // dispatch based on architecture
  switch (exe_ctx.GetTargetPtr()->GetArchitecture().GetMachine()) {
  case llvm::Triple::ArchType::x86:
    return GetArgsX86(ctx, arg_list, num_args);

  case llvm::Triple::ArchType::x86_64:
    return GetArgsX86_64(ctx, arg_list, num_args);

  case llvm::Triple::ArchType::arm:
    return GetArgsArm(ctx, arg_list, num_args);

  case llvm::Triple::ArchType::aarch64:
    return GetArgsAarch64(ctx, arg_list, num_args);

  case llvm::Triple::ArchType::mipsel:
    return GetArgsMipsel(ctx, arg_list, num_args);

  case llvm::Triple::ArchType::mips64el:
    return GetArgsMips64el(ctx, arg_list, num_args);

  default:
    // unsupported architecture
    if (log) {
      LLDB_LOGF(log, "%s - architecture not supported: '%s'", __FUNCTION__,
                exe_ctx.GetTargetRef().GetArchitecture().GetArchitectureName());
    }
    return false;
  }
}

bool IsRenderScriptScriptModule(ModuleSP module) {
  if (!module)
    return false;
  return module->FindFirstSymbolWithNameAndType(ConstString(".rs.info"),
                                                eSymbolTypeData) != nullptr;
}

bool ParseCoordinate(llvm::StringRef coord_s, RSCoordinate &coord) {
  // takes an argument of the form 'num[,num][,num]'. Where 'coord_s' is a
  // comma separated 1,2 or 3-dimensional coordinate with the whitespace
  // trimmed. Missing coordinates are defaulted to zero. If parsing of any
  // elements fails the contents of &coord are undefined and `false` is
  // returned, `true` otherwise

  llvm::SmallVector<llvm::StringRef, 4> matches;

  if (!RegularExpression("^([0-9]+),([0-9]+),([0-9]+)$")
           .Execute(coord_s, &matches) &&
      !RegularExpression("^([0-9]+),([0-9]+)$").Execute(coord_s, &matches) &&
      !RegularExpression("^([0-9]+)$").Execute(coord_s, &matches))
    return false;

  auto get_index = [&](size_t idx, uint32_t &i) -> bool {
    std::string group;
    errno = 0;
    if (idx + 1 < matches.size()) {
      return !llvm::StringRef(matches[idx + 1]).getAsInteger<uint32_t>(10, i);
    }
    return true;
  };

  return get_index(0, coord.x) && get_index(1, coord.y) &&
         get_index(2, coord.z);
}

bool SkipPrologue(lldb::ModuleSP &module, Address &addr) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
  SymbolContext sc;
  uint32_t resolved_flags =
      module->ResolveSymbolContextForAddress(addr, eSymbolContextFunction, sc);
  if (resolved_flags & eSymbolContextFunction) {
    if (sc.function) {
      const uint32_t offset = sc.function->GetPrologueByteSize();
      ConstString name = sc.GetFunctionName();
      if (offset)
        addr.Slide(offset);
      LLDB_LOGF(log, "%s: Prologue offset for %s is %" PRIu32, __FUNCTION__,
                name.AsCString(), offset);
    }
    return true;
  } else
    return false;
}
} // anonymous namespace

// The ScriptDetails class collects data associated with a single script
// instance.
struct RenderScriptRuntime::ScriptDetails {
  ~ScriptDetails() = default;

  enum ScriptType { eScript, eScriptC };

  // The derived type of the script.
  empirical_type<ScriptType> type;
  // The name of the original source file.
  empirical_type<std::string> res_name;
  // Path to script .so file on the device.
  empirical_type<std::string> shared_lib;
  // Directory where kernel objects are cached on device.
  empirical_type<std::string> cache_dir;
  // Pointer to the context which owns this script.
  empirical_type<lldb::addr_t> context;
  // Pointer to the script object itself.
  empirical_type<lldb::addr_t> script;
};

// This Element class represents the Element object in RS, defining the type
// associated with an Allocation.
struct RenderScriptRuntime::Element {
  // Taken from rsDefines.h
  enum DataKind {
    RS_KIND_USER,
    RS_KIND_PIXEL_L = 7,
    RS_KIND_PIXEL_A,
    RS_KIND_PIXEL_LA,
    RS_KIND_PIXEL_RGB,
    RS_KIND_PIXEL_RGBA,
    RS_KIND_PIXEL_DEPTH,
    RS_KIND_PIXEL_YUV,
    RS_KIND_INVALID = 100
  };

  // Taken from rsDefines.h
  enum DataType {
    RS_TYPE_NONE = 0,
    RS_TYPE_FLOAT_16,
    RS_TYPE_FLOAT_32,
    RS_TYPE_FLOAT_64,
    RS_TYPE_SIGNED_8,
    RS_TYPE_SIGNED_16,
    RS_TYPE_SIGNED_32,
    RS_TYPE_SIGNED_64,
    RS_TYPE_UNSIGNED_8,
    RS_TYPE_UNSIGNED_16,
    RS_TYPE_UNSIGNED_32,
    RS_TYPE_UNSIGNED_64,
    RS_TYPE_BOOLEAN,

    RS_TYPE_UNSIGNED_5_6_5,
    RS_TYPE_UNSIGNED_5_5_5_1,
    RS_TYPE_UNSIGNED_4_4_4_4,

    RS_TYPE_MATRIX_4X4,
    RS_TYPE_MATRIX_3X3,
    RS_TYPE_MATRIX_2X2,

    RS_TYPE_ELEMENT = 1000,
    RS_TYPE_TYPE,
    RS_TYPE_ALLOCATION,
    RS_TYPE_SAMPLER,
    RS_TYPE_SCRIPT,
    RS_TYPE_MESH,
    RS_TYPE_PROGRAM_FRAGMENT,
    RS_TYPE_PROGRAM_VERTEX,
    RS_TYPE_PROGRAM_RASTER,
    RS_TYPE_PROGRAM_STORE,
    RS_TYPE_FONT,

    RS_TYPE_INVALID = 10000
  };

  std::vector<Element> children; // Child Element fields for structs
  empirical_type<lldb::addr_t>
      element_ptr; // Pointer to the RS Element of the Type
  empirical_type<DataType>
      type; // Type of each data pointer stored by the allocation
  empirical_type<DataKind>
      type_kind; // Defines pixel type if Allocation is created from an image
  empirical_type<uint32_t>
      type_vec_size; // Vector size of each data point, e.g '4' for uchar4
  empirical_type<uint32_t> field_count; // Number of Subelements
  empirical_type<uint32_t> datum_size;  // Size of a single Element with padding
  empirical_type<uint32_t> padding;     // Number of padding bytes
  empirical_type<uint32_t>
      array_size;        // Number of items in array, only needed for structs
  ConstString type_name; // Name of type, only needed for structs

  static ConstString 
  GetFallbackStructName(); // Print this as the type name of a struct Element
                           // If we can't resolve the actual struct name

  bool ShouldRefresh() const {
    const bool valid_ptr = element_ptr.isValid() && *element_ptr.get() != 0x0;
    const bool valid_type =
        type.isValid() && type_vec_size.isValid() && type_kind.isValid();
    return !valid_ptr || !valid_type || !datum_size.isValid();
  }
};

// This AllocationDetails class collects data associated with a single
// allocation instance.
struct RenderScriptRuntime::AllocationDetails {
  struct Dimension {
    uint32_t dim_1;
    uint32_t dim_2;
    uint32_t dim_3;
    uint32_t cube_map;

    Dimension() {
      dim_1 = 0;
      dim_2 = 0;
      dim_3 = 0;
      cube_map = 0;
    }
  };

  // The FileHeader struct specifies the header we use for writing allocations
  // to a binary file. Our format begins with the ASCII characters "RSAD",
  // identifying the file as an allocation dump. Member variables dims and
  // hdr_size are then written consecutively, immediately followed by an
  // instance of the ElementHeader struct. Because Elements can contain
  // subelements, there may be more than one instance of the ElementHeader
  // struct. With this first instance being the root element, and the other
  // instances being the root's descendants. To identify which instances are an
  // ElementHeader's children, each struct is immediately followed by a
  // sequence of consecutive offsets to the start of its child structs. These
  // offsets are
  // 4 bytes in size, and the 0 offset signifies no more children.
  struct FileHeader {
    uint8_t ident[4];  // ASCII 'RSAD' identifying the file
    uint32_t dims[3];  // Dimensions
    uint16_t hdr_size; // Header size in bytes, including all element headers
  };

  struct ElementHeader {
    uint16_t type;         // DataType enum
    uint32_t kind;         // DataKind enum
    uint32_t element_size; // Size of a single element, including padding
    uint16_t vector_size;  // Vector width
    uint32_t array_size;   // Number of elements in array
  };

  // Monotonically increasing from 1
  static uint32_t ID;

  // Maps Allocation DataType enum and vector size to printable strings using
  // mapping from RenderScript numerical types summary documentation
  static const char *RsDataTypeToString[][4];

  // Maps Allocation DataKind enum to printable strings
  static const char *RsDataKindToString[];

  // Maps allocation types to format sizes for printing.
  static const uint32_t RSTypeToFormat[][3];

  // Give each allocation an ID as a way
  // for commands to reference it.
  const uint32_t id;

  // Allocation Element type
  RenderScriptRuntime::Element element;
  // Dimensions of the Allocation
  empirical_type<Dimension> dimension;
  // Pointer to address of the RS Allocation
  empirical_type<lldb::addr_t> address;
  // Pointer to the data held by the Allocation
  empirical_type<lldb::addr_t> data_ptr;
  // Pointer to the RS Type of the Allocation
  empirical_type<lldb::addr_t> type_ptr;
  // Pointer to the RS Context of the Allocation
  empirical_type<lldb::addr_t> context;
  // Size of the allocation
  empirical_type<uint32_t> size;
  // Stride between rows of the allocation
  empirical_type<uint32_t> stride;

  // Give each allocation an id, so we can reference it in user commands.
  AllocationDetails() : id(ID++) {}

  bool ShouldRefresh() const {
    bool valid_ptrs = data_ptr.isValid() && *data_ptr.get() != 0x0;
    valid_ptrs = valid_ptrs && type_ptr.isValid() && *type_ptr.get() != 0x0;
    return !valid_ptrs || !dimension.isValid() || !size.isValid() ||
           element.ShouldRefresh();
  }
};

ConstString RenderScriptRuntime::Element::GetFallbackStructName() {
  static const ConstString FallbackStructName("struct");
  return FallbackStructName;
}

uint32_t RenderScriptRuntime::AllocationDetails::ID = 1;

const char *RenderScriptRuntime::AllocationDetails::RsDataKindToString[] = {
    "User",       "Undefined",   "Undefined", "Undefined",
    "Undefined",  "Undefined",   "Undefined", // Enum jumps from 0 to 7
    "L Pixel",    "A Pixel",     "LA Pixel",  "RGB Pixel",
    "RGBA Pixel", "Pixel Depth", "YUV Pixel"};

const char *RenderScriptRuntime::AllocationDetails::RsDataTypeToString[][4] = {
    {"None", "None", "None", "None"},
    {"half", "half2", "half3", "half4"},
    {"float", "float2", "float3", "float4"},
    {"double", "double2", "double3", "double4"},
    {"char", "char2", "char3", "char4"},
    {"short", "short2", "short3", "short4"},
    {"int", "int2", "int3", "int4"},
    {"long", "long2", "long3", "long4"},
    {"uchar", "uchar2", "uchar3", "uchar4"},
    {"ushort", "ushort2", "ushort3", "ushort4"},
    {"uint", "uint2", "uint3", "uint4"},
    {"ulong", "ulong2", "ulong3", "ulong4"},
    {"bool", "bool2", "bool3", "bool4"},
    {"packed_565", "packed_565", "packed_565", "packed_565"},
    {"packed_5551", "packed_5551", "packed_5551", "packed_5551"},
    {"packed_4444", "packed_4444", "packed_4444", "packed_4444"},
    {"rs_matrix4x4", "rs_matrix4x4", "rs_matrix4x4", "rs_matrix4x4"},
    {"rs_matrix3x3", "rs_matrix3x3", "rs_matrix3x3", "rs_matrix3x3"},
    {"rs_matrix2x2", "rs_matrix2x2", "rs_matrix2x2", "rs_matrix2x2"},

    // Handlers
    {"RS Element", "RS Element", "RS Element", "RS Element"},
    {"RS Type", "RS Type", "RS Type", "RS Type"},
    {"RS Allocation", "RS Allocation", "RS Allocation", "RS Allocation"},
    {"RS Sampler", "RS Sampler", "RS Sampler", "RS Sampler"},
    {"RS Script", "RS Script", "RS Script", "RS Script"},

    // Deprecated
    {"RS Mesh", "RS Mesh", "RS Mesh", "RS Mesh"},
    {"RS Program Fragment", "RS Program Fragment", "RS Program Fragment",
     "RS Program Fragment"},
    {"RS Program Vertex", "RS Program Vertex", "RS Program Vertex",
     "RS Program Vertex"},
    {"RS Program Raster", "RS Program Raster", "RS Program Raster",
     "RS Program Raster"},
    {"RS Program Store", "RS Program Store", "RS Program Store",
     "RS Program Store"},
    {"RS Font", "RS Font", "RS Font", "RS Font"}};

// Used as an index into the RSTypeToFormat array elements
enum TypeToFormatIndex { eFormatSingle = 0, eFormatVector, eElementSize };

// { format enum of single element, format enum of element vector, size of
// element}
const uint32_t RenderScriptRuntime::AllocationDetails::RSTypeToFormat[][3] = {
    // RS_TYPE_NONE
    {eFormatHex, eFormatHex, 1},
    // RS_TYPE_FLOAT_16
    {eFormatFloat, eFormatVectorOfFloat16, 2},
    // RS_TYPE_FLOAT_32
    {eFormatFloat, eFormatVectorOfFloat32, sizeof(float)},
    // RS_TYPE_FLOAT_64
    {eFormatFloat, eFormatVectorOfFloat64, sizeof(double)},
    // RS_TYPE_SIGNED_8
    {eFormatDecimal, eFormatVectorOfSInt8, sizeof(int8_t)},
    // RS_TYPE_SIGNED_16
    {eFormatDecimal, eFormatVectorOfSInt16, sizeof(int16_t)},
    // RS_TYPE_SIGNED_32
    {eFormatDecimal, eFormatVectorOfSInt32, sizeof(int32_t)},
    // RS_TYPE_SIGNED_64
    {eFormatDecimal, eFormatVectorOfSInt64, sizeof(int64_t)},
    // RS_TYPE_UNSIGNED_8
    {eFormatDecimal, eFormatVectorOfUInt8, sizeof(uint8_t)},
    // RS_TYPE_UNSIGNED_16
    {eFormatDecimal, eFormatVectorOfUInt16, sizeof(uint16_t)},
    // RS_TYPE_UNSIGNED_32
    {eFormatDecimal, eFormatVectorOfUInt32, sizeof(uint32_t)},
    // RS_TYPE_UNSIGNED_64
    {eFormatDecimal, eFormatVectorOfUInt64, sizeof(uint64_t)},
    // RS_TYPE_BOOL
    {eFormatBoolean, eFormatBoolean, 1},
    // RS_TYPE_UNSIGNED_5_6_5
    {eFormatHex, eFormatHex, sizeof(uint16_t)},
    // RS_TYPE_UNSIGNED_5_5_5_1
    {eFormatHex, eFormatHex, sizeof(uint16_t)},
    // RS_TYPE_UNSIGNED_4_4_4_4
    {eFormatHex, eFormatHex, sizeof(uint16_t)},
    // RS_TYPE_MATRIX_4X4
    {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 16},
    // RS_TYPE_MATRIX_3X3
    {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 9},
    // RS_TYPE_MATRIX_2X2
    {eFormatVectorOfFloat32, eFormatVectorOfFloat32, sizeof(float) * 4}};

// Static Functions
LanguageRuntime *
RenderScriptRuntime::CreateInstance(Process *process,
                                    lldb::LanguageType language) {

  if (language == eLanguageTypeExtRenderScript)
    return new RenderScriptRuntime(process);
  else
    return nullptr;
}

// Callback with a module to search for matching symbols. We first check that
// the module contains RS kernels. Then look for a symbol which matches our
// kernel name. The breakpoint address is finally set using the address of this
// symbol.
Searcher::CallbackReturn
RSBreakpointResolver::SearchCallback(SearchFilter &filter,
                                     SymbolContext &context, Address *) {
  BreakpointSP breakpoint_sp = GetBreakpoint();
  assert(breakpoint_sp);

  ModuleSP module = context.module_sp;

  if (!module || !IsRenderScriptScriptModule(module))
    return Searcher::eCallbackReturnContinue;

  // Attempt to set a breakpoint on the kernel name symbol within the module
  // library. If it's not found, it's likely debug info is unavailable - try to
  // set a breakpoint on <name>.expand.
  const Symbol *kernel_sym =
      module->FindFirstSymbolWithNameAndType(m_kernel_name, eSymbolTypeCode);
  if (!kernel_sym) {
    std::string kernel_name_expanded(m_kernel_name.AsCString());
    kernel_name_expanded.append(".expand");
    kernel_sym = module->FindFirstSymbolWithNameAndType(
        ConstString(kernel_name_expanded.c_str()), eSymbolTypeCode);
  }

  if (kernel_sym) {
    Address bp_addr = kernel_sym->GetAddress();
    if (filter.AddressPasses(bp_addr))
      breakpoint_sp->AddLocation(bp_addr);
  }

  return Searcher::eCallbackReturnContinue;
}

Searcher::CallbackReturn
RSReduceBreakpointResolver::SearchCallback(lldb_private::SearchFilter &filter,
                                           lldb_private::SymbolContext &context,
                                           Address *) {
  BreakpointSP breakpoint_sp = GetBreakpoint();
  assert(breakpoint_sp);

  // We need to have access to the list of reductions currently parsed, as
  // reduce names don't actually exist as symbols in a module. They are only
  // identifiable by parsing the .rs.info packet, or finding the expand symbol.
  // We therefore need access to the list of parsed rs modules to properly
  // resolve reduction names.
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
  ModuleSP module = context.module_sp;

  if (!module || !IsRenderScriptScriptModule(module))
    return Searcher::eCallbackReturnContinue;

  if (!m_rsmodules)
    return Searcher::eCallbackReturnContinue;

  for (const auto &module_desc : *m_rsmodules) {
    if (module_desc->m_module != module)
      continue;

    for (const auto &reduction : module_desc->m_reductions) {
      if (reduction.m_reduce_name != m_reduce_name)
        continue;

      std::array<std::pair<ConstString, int>, 5> funcs{
          {{reduction.m_init_name, eKernelTypeInit},
           {reduction.m_accum_name, eKernelTypeAccum},
           {reduction.m_comb_name, eKernelTypeComb},
           {reduction.m_outc_name, eKernelTypeOutC},
           {reduction.m_halter_name, eKernelTypeHalter}}};

      for (const auto &kernel : funcs) {
        // Skip constituent functions that don't match our spec
        if (!(m_kernel_types & kernel.second))
          continue;

        const auto kernel_name = kernel.first;
        const auto symbol = module->FindFirstSymbolWithNameAndType(
            kernel_name, eSymbolTypeCode);
        if (!symbol)
          continue;

        auto address = symbol->GetAddress();
        if (filter.AddressPasses(address)) {
          bool new_bp;
          if (!SkipPrologue(module, address)) {
            LLDB_LOGF(log, "%s: Error trying to skip prologue", __FUNCTION__);
          }
          breakpoint_sp->AddLocation(address, &new_bp);
          LLDB_LOGF(log, "%s: %s reduction breakpoint on %s in %s",
                    __FUNCTION__, new_bp ? "new" : "existing",
                    kernel_name.GetCString(),
                    address.GetModule()->GetFileSpec().GetCString());
        }
      }
    }
  }
  return eCallbackReturnContinue;
}

Searcher::CallbackReturn RSScriptGroupBreakpointResolver::SearchCallback(
    SearchFilter &filter, SymbolContext &context, Address *addr) {

  BreakpointSP breakpoint_sp = GetBreakpoint();
  if (!breakpoint_sp)
    return eCallbackReturnContinue;

  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
  ModuleSP &module = context.module_sp;

  if (!module || !IsRenderScriptScriptModule(module))
    return Searcher::eCallbackReturnContinue;

  std::vector<std::string> names;
  Breakpoint& breakpoint = *breakpoint_sp;
  breakpoint.GetNames(names);
  if (names.empty())
    return eCallbackReturnContinue;

  for (auto &name : names) {
    const RSScriptGroupDescriptorSP sg = FindScriptGroup(ConstString(name));
    if (!sg) {
      LLDB_LOGF(log, "%s: could not find script group for %s", __FUNCTION__,
                name.c_str());
      continue;
    }

    LLDB_LOGF(log, "%s: Found ScriptGroup for %s", __FUNCTION__, name.c_str());

    for (const RSScriptGroupDescriptor::Kernel &k : sg->m_kernels) {
      if (log) {
        LLDB_LOGF(log, "%s: Adding breakpoint for %s", __FUNCTION__,
                  k.m_name.AsCString());
        LLDB_LOGF(log, "%s: Kernel address 0x%" PRIx64, __FUNCTION__, k.m_addr);
      }

      const lldb_private::Symbol *sym =
          module->FindFirstSymbolWithNameAndType(k.m_name, eSymbolTypeCode);
      if (!sym) {
        LLDB_LOGF(log, "%s: Unable to find symbol for %s", __FUNCTION__,
                  k.m_name.AsCString());
        continue;
      }

      if (log) {
        LLDB_LOGF(log, "%s: Found symbol name is %s", __FUNCTION__,
                  sym->GetName().AsCString());
      }

      auto address = sym->GetAddress();
      if (!SkipPrologue(module, address)) {
        LLDB_LOGF(log, "%s: Error trying to skip prologue", __FUNCTION__);
      }

      bool new_bp;
      breakpoint.AddLocation(address, &new_bp);

      LLDB_LOGF(log, "%s: Placed %sbreakpoint on %s", __FUNCTION__,
                new_bp ? "new " : "", k.m_name.AsCString());

      // exit after placing the first breakpoint if we do not intend to stop on
      // all kernels making up this script group
      if (!m_stop_on_all)
        break;
    }
  }

  return eCallbackReturnContinue;
}

void RenderScriptRuntime::Initialize() {
  PluginManager::RegisterPlugin(GetPluginNameStatic(),
                                "RenderScript language support", CreateInstance,
                                GetCommandObject);
}

void RenderScriptRuntime::Terminate() {
  PluginManager::UnregisterPlugin(CreateInstance);
}

RenderScriptRuntime::ModuleKind
RenderScriptRuntime::GetModuleKind(const lldb::ModuleSP &module_sp) {
  if (module_sp) {
    if (IsRenderScriptScriptModule(module_sp))
      return eModuleKindKernelObj;

    // Is this the main RS runtime library
    const ConstString rs_lib("libRS.so");
    if (module_sp->GetFileSpec().GetFilename() == rs_lib) {
      return eModuleKindLibRS;
    }

    const ConstString rs_driverlib("libRSDriver.so");
    if (module_sp->GetFileSpec().GetFilename() == rs_driverlib) {
      return eModuleKindDriver;
    }

    const ConstString rs_cpureflib("libRSCpuRef.so");
    if (module_sp->GetFileSpec().GetFilename() == rs_cpureflib) {
      return eModuleKindImpl;
    }
  }
  return eModuleKindIgnored;
}

bool RenderScriptRuntime::IsRenderScriptModule(
    const lldb::ModuleSP &module_sp) {
  return GetModuleKind(module_sp) != eModuleKindIgnored;
}

void RenderScriptRuntime::ModulesDidLoad(const ModuleList &module_list) {
  std::lock_guard<std::recursive_mutex> guard(module_list.GetMutex());

  size_t num_modules = module_list.GetSize();
  for (size_t i = 0; i < num_modules; i++) {
    auto mod = module_list.GetModuleAtIndex(i);
    if (IsRenderScriptModule(mod)) {
      LoadModule(mod);
    }
  }
}

bool RenderScriptRuntime::GetDynamicTypeAndAddress(
    ValueObject &in_value, lldb::DynamicValueType use_dynamic,
    TypeAndOrName &class_type_or_name, Address &address,
    Value::ValueType &value_type) {
  return false;
}

TypeAndOrName
RenderScriptRuntime::FixUpDynamicType(const TypeAndOrName &type_and_or_name,
                                      ValueObject &static_value) {
  return type_and_or_name;
}

bool RenderScriptRuntime::CouldHaveDynamicValue(ValueObject &in_value) {
  return false;
}

lldb::BreakpointResolverSP
RenderScriptRuntime::CreateExceptionResolver(const lldb::BreakpointSP &bp,
                                             bool catch_bp, bool throw_bp) {
  BreakpointResolverSP resolver_sp;
  return resolver_sp;
}

const RenderScriptRuntime::HookDefn RenderScriptRuntime::s_runtimeHookDefns[] =
    {
        // rsdScript
        {"rsdScriptInit", "_Z13rsdScriptInitPKN7android12renderscript7ContextEP"
                          "NS0_7ScriptCEPKcS7_PKhjj",
         "_Z13rsdScriptInitPKN7android12renderscript7ContextEPNS0_"
         "7ScriptCEPKcS7_PKhmj",
         0, RenderScriptRuntime::eModuleKindDriver,
         &lldb_private::RenderScriptRuntime::CaptureScriptInit},
        {"rsdScriptInvokeForEachMulti",
         "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0"
         "_6ScriptEjPPKNS0_10AllocationEjPS6_PKvjPK12RsScriptCall",
         "_Z27rsdScriptInvokeForEachMultiPKN7android12renderscript7ContextEPNS0"
         "_6ScriptEjPPKNS0_10AllocationEmPS6_PKvmPK12RsScriptCall",
         0, RenderScriptRuntime::eModuleKindDriver,
         &lldb_private::RenderScriptRuntime::CaptureScriptInvokeForEachMulti},
        {"rsdScriptSetGlobalVar", "_Z21rsdScriptSetGlobalVarPKN7android12render"
                                  "script7ContextEPKNS0_6ScriptEjPvj",
         "_Z21rsdScriptSetGlobalVarPKN7android12renderscript7ContextEPKNS0_"
         "6ScriptEjPvm",
         0, RenderScriptRuntime::eModuleKindDriver,
         &lldb_private::RenderScriptRuntime::CaptureSetGlobalVar},

        // rsdAllocation
        {"rsdAllocationInit", "_Z17rsdAllocationInitPKN7android12renderscript7C"
                              "ontextEPNS0_10AllocationEb",
         "_Z17rsdAllocationInitPKN7android12renderscript7ContextEPNS0_"
         "10AllocationEb",
         0, RenderScriptRuntime::eModuleKindDriver,
         &lldb_private::RenderScriptRuntime::CaptureAllocationInit},
        {"rsdAllocationRead2D",
         "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_"
         "10AllocationEjjj23RsAllocationCubemapFacejjPvjj",
         "_Z19rsdAllocationRead2DPKN7android12renderscript7ContextEPKNS0_"
         "10AllocationEjjj23RsAllocationCubemapFacejjPvmm",
         0, RenderScriptRuntime::eModuleKindDriver, nullptr},
        {"rsdAllocationDestroy", "_Z20rsdAllocationDestroyPKN7android12rendersc"
                                 "ript7ContextEPNS0_10AllocationE",
         "_Z20rsdAllocationDestroyPKN7android12renderscript7ContextEPNS0_"
         "10AllocationE",
         0, RenderScriptRuntime::eModuleKindDriver,
         &lldb_private::RenderScriptRuntime::CaptureAllocationDestroy},

        // renderscript script groups
        {"rsdDebugHintScriptGroup2", "_ZN7android12renderscript21debugHintScrip"
                                     "tGroup2EPKcjPKPFvPK24RsExpandKernelDriver"
                                     "InfojjjEj",
         "_ZN7android12renderscript21debugHintScriptGroup2EPKcjPKPFvPK24RsExpan"
         "dKernelDriverInfojjjEj",
         0, RenderScriptRuntime::eModuleKindImpl,
         &lldb_private::RenderScriptRuntime::CaptureDebugHintScriptGroup2}};

const size_t RenderScriptRuntime::s_runtimeHookCount =
    sizeof(s_runtimeHookDefns) / sizeof(s_runtimeHookDefns[0]);

bool RenderScriptRuntime::HookCallback(void *baton,
                                       StoppointCallbackContext *ctx,
                                       lldb::user_id_t break_id,
                                       lldb::user_id_t break_loc_id) {
  RuntimeHook *hook = (RuntimeHook *)baton;
  ExecutionContext exe_ctx(ctx->exe_ctx_ref);

  RenderScriptRuntime *lang_rt = llvm::cast<RenderScriptRuntime>(
      exe_ctx.GetProcessPtr()->GetLanguageRuntime(
          eLanguageTypeExtRenderScript));

  lang_rt->HookCallback(hook, exe_ctx);

  return false;
}

void RenderScriptRuntime::HookCallback(RuntimeHook *hook,
                                       ExecutionContext &exe_ctx) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));

  LLDB_LOGF(log, "%s - '%s'", __FUNCTION__, hook->defn->name);

  if (hook->defn->grabber) {
    (this->*(hook->defn->grabber))(hook, exe_ctx);
  }
}

void RenderScriptRuntime::CaptureDebugHintScriptGroup2(
    RuntimeHook *hook_info, ExecutionContext &context) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));

  enum {
    eGroupName = 0,
    eGroupNameSize,
    eKernel,
    eKernelCount,
  };

  std::array<ArgItem, 4> args{{
      {ArgItem::ePointer, 0}, // const char         *groupName
      {ArgItem::eInt32, 0},   // const uint32_t      groupNameSize
      {ArgItem::ePointer, 0}, // const ExpandFuncTy *kernel
      {ArgItem::eInt32, 0},   // const uint32_t      kernelCount
  }};

  if (!GetArgs(context, args.data(), args.size())) {
    LLDB_LOGF(log, "%s - Error while reading the function parameters",
              __FUNCTION__);
    return;
  } else if (log) {
    LLDB_LOGF(log, "%s - groupName    : 0x%" PRIx64, __FUNCTION__,
              addr_t(args[eGroupName]));
    LLDB_LOGF(log, "%s - groupNameSize: %" PRIu64, __FUNCTION__,
              uint64_t(args[eGroupNameSize]));
    LLDB_LOGF(log, "%s - kernel       : 0x%" PRIx64, __FUNCTION__,
              addr_t(args[eKernel]));
    LLDB_LOGF(log, "%s - kernelCount  : %" PRIu64, __FUNCTION__,
              uint64_t(args[eKernelCount]));
  }

  // parse script group name
  ConstString group_name;
  {
    Status err;
    const uint64_t len = uint64_t(args[eGroupNameSize]);
    std::unique_ptr<char[]> buffer(new char[uint32_t(len + 1)]);
    m_process->ReadMemory(addr_t(args[eGroupName]), buffer.get(), len, err);
    buffer.get()[len] = '\0';
    if (!err.Success()) {
      LLDB_LOGF(log, "Error reading scriptgroup name from target");
      return;
    } else {
      LLDB_LOGF(log, "Extracted scriptgroup name %s", buffer.get());
    }
    // write back the script group name
    group_name.SetCString(buffer.get());
  }

  // create or access existing script group
  RSScriptGroupDescriptorSP group;
  {
    // search for existing script group
    for (auto sg : m_scriptGroups) {
      if (sg->m_name == group_name) {
        group = sg;
        break;
      }
    }
    if (!group) {
      group = std::make_shared<RSScriptGroupDescriptor>();
      group->m_name = group_name;
      m_scriptGroups.push_back(group);
    } else {
      // already have this script group
      LLDB_LOGF(log, "Attempt to add duplicate script group %s",
                group_name.AsCString());
      return;
    }
  }
  assert(group);

  const uint32_t target_ptr_size = m_process->GetAddressByteSize();
  std::vector<addr_t> kernels;
  // parse kernel addresses in script group
  for (uint64_t i = 0; i < uint64_t(args[eKernelCount]); ++i) {
    RSScriptGroupDescriptor::Kernel kernel;
    // extract script group kernel addresses from the target
    const addr_t ptr_addr = addr_t(args[eKernel]) + i * target_ptr_size;
    uint64_t kernel_addr = 0;
    Status err;
    size_t read =
        m_process->ReadMemory(ptr_addr, &kernel_addr, target_ptr_size, err);
    if (!err.Success() || read != target_ptr_size) {
      LLDB_LOGF(log, "Error parsing kernel address %" PRIu64 " in script group",
                i);
      return;
    }
    LLDB_LOGF(log, "Extracted scriptgroup kernel address - 0x%" PRIx64,
              kernel_addr);
    kernel.m_addr = kernel_addr;

    // try to resolve the associated kernel name
    if (!ResolveKernelName(kernel.m_addr, kernel.m_name)) {
      LLDB_LOGF(log, "Parsed scriptgroup kernel %" PRIu64 " - 0x%" PRIx64, i,
                kernel_addr);
      return;
    }

    // try to find the non '.expand' function
    {
      const llvm::StringRef expand(".expand");
      const llvm::StringRef name_ref = kernel.m_name.GetStringRef();
      if (name_ref.endswith(expand)) {
        const ConstString base_kernel(name_ref.drop_back(expand.size()));
        // verify this function is a valid kernel
        if (IsKnownKernel(base_kernel)) {
          kernel.m_name = base_kernel;
          LLDB_LOGF(log, "%s - found non expand version '%s'", __FUNCTION__,
                    base_kernel.GetCString());
        }
      }
    }
    // add to a list of script group kernels we know about
    group->m_kernels.push_back(kernel);
  }

  // Resolve any pending scriptgroup breakpoints
  {
    Target &target = m_process->GetTarget();
    const BreakpointList &list = target.GetBreakpointList();
    const size_t num_breakpoints = list.GetSize();
    LLDB_LOGF(log, "Resolving %zu breakpoints", num_breakpoints);
    for (size_t i = 0; i < num_breakpoints; ++i) {
      const BreakpointSP bp = list.GetBreakpointAtIndex(i);
      if (bp) {
        if (bp->MatchesName(group_name.AsCString())) {
          LLDB_LOGF(log, "Found breakpoint with name %s",
                    group_name.AsCString());
          bp->ResolveBreakpoint();
        }
      }
    }
  }
}

void RenderScriptRuntime::CaptureScriptInvokeForEachMulti(
    RuntimeHook *hook, ExecutionContext &exe_ctx) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));

  enum {
    eRsContext = 0,
    eRsScript,
    eRsSlot,
    eRsAIns,
    eRsInLen,
    eRsAOut,
    eRsUsr,
    eRsUsrLen,
    eRsSc,
  };

  std::array<ArgItem, 9> args{{
      ArgItem{ArgItem::ePointer, 0}, // const Context       *rsc
      ArgItem{ArgItem::ePointer, 0}, // Script              *s
      ArgItem{ArgItem::eInt32, 0},   // uint32_t             slot
      ArgItem{ArgItem::ePointer, 0}, // const Allocation   **aIns
      ArgItem{ArgItem::eInt32, 0},   // size_t               inLen
      ArgItem{ArgItem::ePointer, 0}, // Allocation          *aout
      ArgItem{ArgItem::ePointer, 0}, // const void          *usr
      ArgItem{ArgItem::eInt32, 0},   // size_t               usrLen
      ArgItem{ArgItem::ePointer, 0}, // const RsScriptCall  *sc
  }};

  bool success = GetArgs(exe_ctx, &args[0], args.size());
  if (!success) {
    LLDB_LOGF(log, "%s - Error while reading the function parameters",
              __FUNCTION__);
    return;
  }

  const uint32_t target_ptr_size = m_process->GetAddressByteSize();
  Status err;
  std::vector<uint64_t> allocs;

  // traverse allocation list
  for (uint64_t i = 0; i < uint64_t(args[eRsInLen]); ++i) {
    // calculate offest to allocation pointer
    const addr_t addr = addr_t(args[eRsAIns]) + i * target_ptr_size;

    // Note: due to little endian layout, reading 32bits or 64bits into res
    // will give the correct results.
    uint64_t result = 0;
    size_t read = m_process->ReadMemory(addr, &result, target_ptr_size, err);
    if (read != target_ptr_size || !err.Success()) {
      LLDB_LOGF(log,
                "%s - Error while reading allocation list argument %" PRIu64,
                __FUNCTION__, i);
    } else {
      allocs.push_back(result);
    }
  }

  // if there is an output allocation track it
  if (uint64_t alloc_out = uint64_t(args[eRsAOut])) {
    allocs.push_back(alloc_out);
  }

  // for all allocations we have found
  for (const uint64_t alloc_addr : allocs) {
    AllocationDetails *alloc = LookUpAllocation(alloc_addr);
    if (!alloc)
      alloc = CreateAllocation(alloc_addr);

    if (alloc) {
      // save the allocation address
      if (alloc->address.isValid()) {
        // check the allocation address we already have matches
        assert(*alloc->address.get() == alloc_addr);
      } else {
        alloc->address = alloc_addr;
      }

      // save the context
      if (log) {
        if (alloc->context.isValid() &&
            *alloc->context.get() != addr_t(args[eRsContext]))
          LLDB_LOGF(log, "%s - Allocation used by multiple contexts",
                    __FUNCTION__);
      }
      alloc->context = addr_t(args[eRsContext]);
    }
  }

  // make sure we track this script object
  if (lldb_private::RenderScriptRuntime::ScriptDetails *script =
          LookUpScript(addr_t(args[eRsScript]), true)) {
    if (log) {
      if (script->context.isValid() &&
          *script->context.get() != addr_t(args[eRsContext]))
        LLDB_LOGF(log, "%s - Script used by multiple contexts", __FUNCTION__);
    }
    script->context = addr_t(args[eRsContext]);
  }
}

void RenderScriptRuntime::CaptureSetGlobalVar(RuntimeHook *hook,
                                              ExecutionContext &context) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));

  enum {
    eRsContext,
    eRsScript,
    eRsId,
    eRsData,
    eRsLength,
  };

  std::array<ArgItem, 5> args{{
      ArgItem{ArgItem::ePointer, 0}, // eRsContext
      ArgItem{ArgItem::ePointer, 0}, // eRsScript
      ArgItem{ArgItem::eInt32, 0},   // eRsId
      ArgItem{ArgItem::ePointer, 0}, // eRsData
      ArgItem{ArgItem::eInt32, 0},   // eRsLength
  }};

  bool success = GetArgs(context, &args[0], args.size());
  if (!success) {
    LLDB_LOGF(log, "%s - error reading the function parameters.", __FUNCTION__);
    return;
  }

  if (log) {
    LLDB_LOGF(log,
              "%s - 0x%" PRIx64 ",0x%" PRIx64 " slot %" PRIu64 " = 0x%" PRIx64
              ":%" PRIu64 "bytes.",
              __FUNCTION__, uint64_t(args[eRsContext]),
              uint64_t(args[eRsScript]), uint64_t(args[eRsId]),
              uint64_t(args[eRsData]), uint64_t(args[eRsLength]));

    addr_t script_addr = addr_t(args[eRsScript]);
    if (m_scriptMappings.find(script_addr) != m_scriptMappings.end()) {
      auto rsm = m_scriptMappings[script_addr];
      if (uint64_t(args[eRsId]) < rsm->m_globals.size()) {
        auto rsg = rsm->m_globals[uint64_t(args[eRsId])];
        LLDB_LOGF(log, "%s - Setting of '%s' within '%s' inferred",
                  __FUNCTION__, rsg.m_name.AsCString(),
                  rsm->m_module->GetFileSpec().GetFilename().AsCString());
      }
    }
  }
}

void RenderScriptRuntime::CaptureAllocationInit(RuntimeHook *hook,
                                                ExecutionContext &exe_ctx) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));

  enum { eRsContext, eRsAlloc, eRsForceZero };

  std::array<ArgItem, 3> args{{
      ArgItem{ArgItem::ePointer, 0}, // eRsContext
      ArgItem{ArgItem::ePointer, 0}, // eRsAlloc
      ArgItem{ArgItem::eBool, 0},    // eRsForceZero
  }};

  bool success = GetArgs(exe_ctx, &args[0], args.size());
  if (!success) {
    LLDB_LOGF(log, "%s - error while reading the function parameters",
              __FUNCTION__);
    return;
  }

  LLDB_LOGF(log, "%s - 0x%" PRIx64 ",0x%" PRIx64 ",0x%" PRIx64 " .",
            __FUNCTION__, uint64_t(args[eRsContext]), uint64_t(args[eRsAlloc]),
            uint64_t(args[eRsForceZero]));

  AllocationDetails *alloc = CreateAllocation(uint64_t(args[eRsAlloc]));
  if (alloc)
    alloc->context = uint64_t(args[eRsContext]);
}

void RenderScriptRuntime::CaptureAllocationDestroy(RuntimeHook *hook,
                                                   ExecutionContext &exe_ctx) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));

  enum {
    eRsContext,
    eRsAlloc,
  };

  std::array<ArgItem, 2> args{{
      ArgItem{ArgItem::ePointer, 0}, // eRsContext
      ArgItem{ArgItem::ePointer, 0}, // eRsAlloc
  }};

  bool success = GetArgs(exe_ctx, &args[0], args.size());
  if (!success) {
    LLDB_LOGF(log, "%s - error while reading the function parameters.",
              __FUNCTION__);
    return;
  }

  LLDB_LOGF(log, "%s - 0x%" PRIx64 ", 0x%" PRIx64 ".", __FUNCTION__,
            uint64_t(args[eRsContext]), uint64_t(args[eRsAlloc]));

  for (auto iter = m_allocations.begin(); iter != m_allocations.end(); ++iter) {
    auto &allocation_up = *iter; // get the unique pointer
    if (allocation_up->address.isValid() &&
        *allocation_up->address.get() == addr_t(args[eRsAlloc])) {
      m_allocations.erase(iter);
      LLDB_LOGF(log, "%s - deleted allocation entry.", __FUNCTION__);
      return;
    }
  }

  LLDB_LOGF(log, "%s - couldn't find destroyed allocation.", __FUNCTION__);
}

void RenderScriptRuntime::CaptureScriptInit(RuntimeHook *hook,
                                            ExecutionContext &exe_ctx) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));

  Status err;
  Process *process = exe_ctx.GetProcessPtr();

  enum { eRsContext, eRsScript, eRsResNamePtr, eRsCachedDirPtr };

  std::array<ArgItem, 4> args{
      {ArgItem{ArgItem::ePointer, 0}, ArgItem{ArgItem::ePointer, 0},
       ArgItem{ArgItem::ePointer, 0}, ArgItem{ArgItem::ePointer, 0}}};
  bool success = GetArgs(exe_ctx, &args[0], args.size());
  if (!success) {
    LLDB_LOGF(log, "%s - error while reading the function parameters.",
              __FUNCTION__);
    return;
  }

  std::string res_name;
  process->ReadCStringFromMemory(addr_t(args[eRsResNamePtr]), res_name, err);
  if (err.Fail()) {
    LLDB_LOGF(log, "%s - error reading res_name: %s.", __FUNCTION__,
              err.AsCString());
  }

  std::string cache_dir;
  process->ReadCStringFromMemory(addr_t(args[eRsCachedDirPtr]), cache_dir, err);
  if (err.Fail()) {
    LLDB_LOGF(log, "%s - error reading cache_dir: %s.", __FUNCTION__,
              err.AsCString());
  }

  LLDB_LOGF(log, "%s - 0x%" PRIx64 ",0x%" PRIx64 " => '%s' at '%s' .",
            __FUNCTION__, uint64_t(args[eRsContext]), uint64_t(args[eRsScript]),
            res_name.c_str(), cache_dir.c_str());

  if (res_name.size() > 0) {
    StreamString strm;
    strm.Printf("librs.%s.so", res_name.c_str());

    ScriptDetails *script = LookUpScript(addr_t(args[eRsScript]), true);
    if (script) {
      script->type = ScriptDetails::eScriptC;
      script->cache_dir = cache_dir;
      script->res_name = res_name;
      script->shared_lib = std::string(strm.GetString());
      script->context = addr_t(args[eRsContext]);
    }

    LLDB_LOGF(log,
              "%s - '%s' tagged with context 0x%" PRIx64
              " and script 0x%" PRIx64 ".",
              __FUNCTION__, strm.GetData(), uint64_t(args[eRsContext]),
              uint64_t(args[eRsScript]));
  } else if (log) {
    LLDB_LOGF(log, "%s - resource name invalid, Script not tagged.",
              __FUNCTION__);
  }
}

void RenderScriptRuntime::LoadRuntimeHooks(lldb::ModuleSP module,
                                           ModuleKind kind) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));

  if (!module) {
    return;
  }

  Target &target = GetProcess()->GetTarget();
  const llvm::Triple::ArchType machine = target.GetArchitecture().GetMachine();

  if (machine != llvm::Triple::ArchType::x86 &&
      machine != llvm::Triple::ArchType::arm &&
      machine != llvm::Triple::ArchType::aarch64 &&
      machine != llvm::Triple::ArchType::mipsel &&
      machine != llvm::Triple::ArchType::mips64el &&
      machine != llvm::Triple::ArchType::x86_64) {
    LLDB_LOGF(log, "%s - unable to hook runtime functions.", __FUNCTION__);
    return;
  }

  const uint32_t target_ptr_size =
      target.GetArchitecture().GetAddressByteSize();

  std::array<bool, s_runtimeHookCount> hook_placed;
  hook_placed.fill(false);

  for (size_t idx = 0; idx < s_runtimeHookCount; idx++) {
    const HookDefn *hook_defn = &s_runtimeHookDefns[idx];
    if (hook_defn->kind != kind) {
      continue;
    }

    const char *symbol_name = (target_ptr_size == 4)
                                  ? hook_defn->symbol_name_m32
                                  : hook_defn->symbol_name_m64;

    const Symbol *sym = module->FindFirstSymbolWithNameAndType(
        ConstString(symbol_name), eSymbolTypeCode);
    if (!sym) {
      if (log) {
        LLDB_LOGF(log, "%s - symbol '%s' related to the function %s not found",
                  __FUNCTION__, symbol_name, hook_defn->name);
      }
      continue;
    }

    addr_t addr = sym->GetLoadAddress(&target);
    if (addr == LLDB_INVALID_ADDRESS) {
      LLDB_LOGF(log,
                "%s - unable to resolve the address of hook function '%s' "
                "with symbol '%s'.",
                __FUNCTION__, hook_defn->name, symbol_name);
      continue;
    } else {
      LLDB_LOGF(log, "%s - function %s, address resolved at 0x%" PRIx64,
                __FUNCTION__, hook_defn->name, addr);
    }

    RuntimeHookSP hook(new RuntimeHook());
    hook->address = addr;
    hook->defn = hook_defn;
    hook->bp_sp = target.CreateBreakpoint(addr, true, false);
    hook->bp_sp->SetCallback(HookCallback, hook.get(), true);
    m_runtimeHooks[addr] = hook;
    if (log) {
      LLDB_LOGF(log,
                "%s - successfully hooked '%s' in '%s' version %" PRIu64
                " at 0x%" PRIx64 ".",
                __FUNCTION__, hook_defn->name,
                module->GetFileSpec().GetFilename().AsCString(),
                (uint64_t)hook_defn->version, (uint64_t)addr);
    }
    hook_placed[idx] = true;
  }

  // log any unhooked function
  if (log) {
    for (size_t i = 0; i < hook_placed.size(); ++i) {
      if (hook_placed[i])
        continue;
      const HookDefn &hook_defn = s_runtimeHookDefns[i];
      if (hook_defn.kind != kind)
        continue;
      LLDB_LOGF(log, "%s - function %s was not hooked", __FUNCTION__,
                hook_defn.name);
    }
  }
}

void RenderScriptRuntime::FixupScriptDetails(RSModuleDescriptorSP rsmodule_sp) {
  if (!rsmodule_sp)
    return;

  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));

  const ModuleSP module = rsmodule_sp->m_module;
  const FileSpec &file = module->GetPlatformFileSpec();

  // Iterate over all of the scripts that we currently know of. Note: We cant
  // push or pop to m_scripts here or it may invalidate rs_script.
  for (const auto &rs_script : m_scripts) {
    // Extract the expected .so file path for this script.
    std::string shared_lib;
    if (!rs_script->shared_lib.get(shared_lib))
      continue;

    // Only proceed if the module that has loaded corresponds to this script.
    if (file.GetFilename() != ConstString(shared_lib.c_str()))
      continue;

    // Obtain the script address which we use as a key.
    lldb::addr_t script;
    if (!rs_script->script.get(script))
      continue;

    // If we have a script mapping for the current script.
    if (m_scriptMappings.find(script) != m_scriptMappings.end()) {
      // if the module we have stored is different to the one we just received.
      if (m_scriptMappings[script] != rsmodule_sp) {
        LLDB_LOGF(
            log,
            "%s - script %" PRIx64 " wants reassigned to new rsmodule '%s'.",
            __FUNCTION__, (uint64_t)script,
            rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
      }
    }
    // We don't have a script mapping for the current script.
    else {
      // Obtain the script resource name.
      std::string res_name;
      if (rs_script->res_name.get(res_name))
        // Set the modules resource name.
        rsmodule_sp->m_resname = res_name;
      // Add Script/Module pair to map.
      m_scriptMappings[script] = rsmodule_sp;
      LLDB_LOGF(log, "%s - script %" PRIx64 " associated with rsmodule '%s'.",
                __FUNCTION__, (uint64_t)script,
                rsmodule_sp->m_module->GetFileSpec().GetFilename().AsCString());
    }
  }
}

// Uses the Target API to evaluate the expression passed as a parameter to the
// function The result of that expression is returned an unsigned 64 bit int,
// via the result* parameter. Function returns true on success, and false on
// failure
bool RenderScriptRuntime::EvalRSExpression(const char *expr,
                                           StackFrame *frame_ptr,
                                           uint64_t *result) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
  LLDB_LOGF(log, "%s(%s)", __FUNCTION__, expr);

  ValueObjectSP expr_result;
  EvaluateExpressionOptions options;
  options.SetLanguage(lldb::eLanguageTypeC_plus_plus);
  // Perform the actual expression evaluation
  auto &target = GetProcess()->GetTarget();
  target.EvaluateExpression(expr, frame_ptr, expr_result, options);

  if (!expr_result) {
    LLDB_LOGF(log, "%s: couldn't evaluate expression.", __FUNCTION__);
    return false;
  }

  // The result of the expression is invalid
  if (!expr_result->GetError().Success()) {
    Status err = expr_result->GetError();
    // Expression returned is void, so this is actually a success
    if (err.GetError() == UserExpression::kNoResult) {
      LLDB_LOGF(log, "%s - expression returned void.", __FUNCTION__);

      result = nullptr;
      return true;
    }

    LLDB_LOGF(log, "%s - error evaluating expression result: %s", __FUNCTION__,
              err.AsCString());
    return false;
  }

  bool success = false;
  // We only read the result as an uint32_t.
  *result = expr_result->GetValueAsUnsigned(0, &success);

  if (!success) {
    LLDB_LOGF(log, "%s - couldn't convert expression result to uint32_t",
              __FUNCTION__);
    return false;
  }

  return true;
}

namespace {
// Used to index expression format strings
enum ExpressionStrings {
  eExprGetOffsetPtr = 0,
  eExprAllocGetType,
  eExprTypeDimX,
  eExprTypeDimY,
  eExprTypeDimZ,
  eExprTypeElemPtr,
  eExprElementType,
  eExprElementKind,
  eExprElementVec,
  eExprElementFieldCount,
  eExprSubelementsId,
  eExprSubelementsName,
  eExprSubelementsArrSize,

  _eExprLast // keep at the end, implicit size of the array runtime_expressions
};

// max length of an expanded expression
const int jit_max_expr_size = 512;

// Retrieve the string to JIT for the given expression
#define JIT_TEMPLATE_CONTEXT "void* ctxt = (void*)rsDebugGetContextWrapper(0x%" PRIx64 "); "
const char *JITTemplate(ExpressionStrings e) {
  // Format strings containing the expressions we may need to evaluate.
  static std::array<const char *, _eExprLast> runtime_expressions = {
      {// Mangled GetOffsetPointer(Allocation*, xoff, yoff, zoff, lod, cubemap)
       "(int*)_"
       "Z12GetOffsetPtrPKN7android12renderscript10AllocationEjjjj23RsAllocation"
       "CubemapFace"
       "(0x%" PRIx64 ", %" PRIu32 ", %" PRIu32 ", %" PRIu32 ", 0, 0)", // eExprGetOffsetPtr

       // Type* rsaAllocationGetType(Context*, Allocation*)
       JIT_TEMPLATE_CONTEXT "(void*)rsaAllocationGetType(ctxt, 0x%" PRIx64 ")", // eExprAllocGetType

       // rsaTypeGetNativeData(Context*, Type*, void* typeData, size) Pack the
       // data in the following way mHal.state.dimX; mHal.state.dimY;
       // mHal.state.dimZ; mHal.state.lodCount; mHal.state.faces; mElement;
       // into typeData Need to specify 32 or 64 bit for uint_t since this
       // differs between devices
       JIT_TEMPLATE_CONTEXT
       "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(ctxt"
       ", 0x%" PRIx64 ", data, 6); data[0]", // eExprTypeDimX
       JIT_TEMPLATE_CONTEXT
       "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(ctxt"
       ", 0x%" PRIx64 ", data, 6); data[1]", // eExprTypeDimY
       JIT_TEMPLATE_CONTEXT
       "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(ctxt"
       ", 0x%" PRIx64 ", data, 6); data[2]", // eExprTypeDimZ
       JIT_TEMPLATE_CONTEXT
       "uint%" PRIu32 "_t data[6]; (void*)rsaTypeGetNativeData(ctxt"
       ", 0x%" PRIx64 ", data, 6); data[5]", // eExprTypeElemPtr

       // rsaElementGetNativeData(Context*, Element*, uint32_t* elemData,size)
       // Pack mType; mKind; mNormalized; mVectorSize; NumSubElements into
       // elemData
       JIT_TEMPLATE_CONTEXT
       "uint32_t data[5]; (void*)rsaElementGetNativeData(ctxt"
       ", 0x%" PRIx64 ", data, 5); data[0]", // eExprElementType
       JIT_TEMPLATE_CONTEXT
       "uint32_t data[5]; (void*)rsaElementGetNativeData(ctxt"
       ", 0x%" PRIx64 ", data, 5); data[1]", // eExprElementKind
       JIT_TEMPLATE_CONTEXT
       "uint32_t data[5]; (void*)rsaElementGetNativeData(ctxt"
       ", 0x%" PRIx64 ", data, 5); data[3]", // eExprElementVec
       JIT_TEMPLATE_CONTEXT
       "uint32_t data[5]; (void*)rsaElementGetNativeData(ctxt"
       ", 0x%" PRIx64 ", data, 5); data[4]", // eExprElementFieldCount

       // rsaElementGetSubElements(RsContext con, RsElement elem, uintptr_t
       // *ids, const char **names, size_t *arraySizes, uint32_t dataSize)
       // Needed for Allocations of structs to gather details about
       // fields/Subelements Element* of field
       JIT_TEMPLATE_CONTEXT "void* ids[%" PRIu32 "]; const char* names[%" PRIu32
       "]; size_t arr_size[%" PRIu32 "];"
       "(void*)rsaElementGetSubElements(ctxt, 0x%" PRIx64
       ", ids, names, arr_size, %" PRIu32 "); ids[%" PRIu32 "]", // eExprSubelementsId

       // Name of field
       JIT_TEMPLATE_CONTEXT "void* ids[%" PRIu32 "]; const char* names[%" PRIu32
       "]; size_t arr_size[%" PRIu32 "];"
       "(void*)rsaElementGetSubElements(ctxt, 0x%" PRIx64
       ", ids, names, arr_size, %" PRIu32 "); names[%" PRIu32 "]", // eExprSubelementsName

       // Array size of field
       JIT_TEMPLATE_CONTEXT "void* ids[%" PRIu32 "]; const char* names[%" PRIu32
       "]; size_t arr_size[%" PRIu32 "];"
       "(void*)rsaElementGetSubElements(ctxt, 0x%" PRIx64
       ", ids, names, arr_size, %" PRIu32 "); arr_size[%" PRIu32 "]"}}; // eExprSubelementsArrSize

  return runtime_expressions[e];
}
} // end of the anonymous namespace

// JITs the RS runtime for the internal data pointer of an allocation. Is
// passed x,y,z coordinates for the pointer to a specific element. Then sets
// the data_ptr member in Allocation with the result. Returns true on success,
// false otherwise
bool RenderScriptRuntime::JITDataPointer(AllocationDetails *alloc,
                                         StackFrame *frame_ptr, uint32_t x,
                                         uint32_t y, uint32_t z) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));

  if (!alloc->address.isValid()) {
    LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__);
    return false;
  }

  const char *fmt_str = JITTemplate(eExprGetOffsetPtr);
  char expr_buf[jit_max_expr_size];

  int written = snprintf(expr_buf, jit_max_expr_size, fmt_str,
                         *alloc->address.get(), x, y, z);
  if (written < 0) {
    LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__);
    return false;
  } else if (written >= jit_max_expr_size) {
    LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__);
    return false;
  }

  uint64_t result = 0;
  if (!EvalRSExpression(expr_buf, frame_ptr, &result))
    return false;

  addr_t data_ptr = static_cast<lldb::addr_t>(result);
  alloc->data_ptr = data_ptr;

  return true;
}

// JITs the RS runtime for the internal pointer to the RS Type of an allocation
// Then sets the type_ptr member in Allocation with the result. Returns true on
// success, false otherwise
bool RenderScriptRuntime::JITTypePointer(AllocationDetails *alloc,
                                         StackFrame *frame_ptr) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));

  if (!alloc->address.isValid() || !alloc->context.isValid()) {
    LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__);
    return false;
  }

  const char *fmt_str = JITTemplate(eExprAllocGetType);
  char expr_buf[jit_max_expr_size];

  int written = snprintf(expr_buf, jit_max_expr_size, fmt_str,
                         *alloc->context.get(), *alloc->address.get());
  if (written < 0) {
    LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__);
    return false;
  } else if (written >= jit_max_expr_size) {
    LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__);
    return false;
  }

  uint64_t result = 0;
  if (!EvalRSExpression(expr_buf, frame_ptr, &result))
    return false;

  addr_t type_ptr = static_cast<lldb::addr_t>(result);
  alloc->type_ptr = type_ptr;

  return true;
}

// JITs the RS runtime for information about the dimensions and type of an
// allocation Then sets dimension and element_ptr members in Allocation with
// the result. Returns true on success, false otherwise
bool RenderScriptRuntime::JITTypePacked(AllocationDetails *alloc,
                                        StackFrame *frame_ptr) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));

  if (!alloc->type_ptr.isValid() || !alloc->context.isValid()) {
    LLDB_LOGF(log, "%s - Failed to find allocation details.", __FUNCTION__);
    return false;
  }

  // Expression is different depending on if device is 32 or 64 bit
  uint32_t target_ptr_size =
      GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
  const uint32_t bits = target_ptr_size == 4 ? 32 : 64;

  // We want 4 elements from packed data
  const uint32_t num_exprs = 4;
  static_assert(num_exprs == (eExprTypeElemPtr - eExprTypeDimX + 1),
                "Invalid number of expressions");

  char expr_bufs[num_exprs][jit_max_expr_size];
  uint64_t results[num_exprs];

  for (uint32_t i = 0; i < num_exprs; ++i) {
    const char *fmt_str = JITTemplate(ExpressionStrings(eExprTypeDimX + i));
    int written = snprintf(expr_bufs[i], jit_max_expr_size, fmt_str,
                           *alloc->context.get(), bits, *alloc->type_ptr.get());
    if (written < 0) {
      LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__);
      return false;
    } else if (written >= jit_max_expr_size) {
      LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__);
      return false;
    }

    // Perform expression evaluation
    if (!EvalRSExpression(expr_bufs[i], frame_ptr, &results[i]))
      return false;
  }

  // Assign results to allocation members
  AllocationDetails::Dimension dims;
  dims.dim_1 = static_cast<uint32_t>(results[0]);
  dims.dim_2 = static_cast<uint32_t>(results[1]);
  dims.dim_3 = static_cast<uint32_t>(results[2]);
  alloc->dimension = dims;

  addr_t element_ptr = static_cast<lldb::addr_t>(results[3]);
  alloc->element.element_ptr = element_ptr;

  LLDB_LOGF(log,
            "%s - dims (%" PRIu32 ", %" PRIu32 ", %" PRIu32
            ") Element*: 0x%" PRIx64 ".",
            __FUNCTION__, dims.dim_1, dims.dim_2, dims.dim_3, element_ptr);

  return true;
}

// JITs the RS runtime for information about the Element of an allocation Then
// sets type, type_vec_size, field_count and type_kind members in Element with
// the result. Returns true on success, false otherwise
bool RenderScriptRuntime::JITElementPacked(Element &elem,
                                           const lldb::addr_t context,
                                           StackFrame *frame_ptr) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));

  if (!elem.element_ptr.isValid()) {
    LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__);
    return false;
  }

  // We want 4 elements from packed data
  const uint32_t num_exprs = 4;
  static_assert(num_exprs == (eExprElementFieldCount - eExprElementType + 1),
                "Invalid number of expressions");

  char expr_bufs[num_exprs][jit_max_expr_size];
  uint64_t results[num_exprs];

  for (uint32_t i = 0; i < num_exprs; i++) {
    const char *fmt_str = JITTemplate(ExpressionStrings(eExprElementType + i));
    int written = snprintf(expr_bufs[i], jit_max_expr_size, fmt_str, context,
                           *elem.element_ptr.get());
    if (written < 0) {
      LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__);
      return false;
    } else if (written >= jit_max_expr_size) {
      LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__);
      return false;
    }

    // Perform expression evaluation
    if (!EvalRSExpression(expr_bufs[i], frame_ptr, &results[i]))
      return false;
  }

  // Assign results to allocation members
  elem.type = static_cast<RenderScriptRuntime::Element::DataType>(results[0]);
  elem.type_kind =
      static_cast<RenderScriptRuntime::Element::DataKind>(results[1]);
  elem.type_vec_size = static_cast<uint32_t>(results[2]);
  elem.field_count = static_cast<uint32_t>(results[3]);

  LLDB_LOGF(log,
            "%s - data type %" PRIu32 ", pixel type %" PRIu32
            ", vector size %" PRIu32 ", field count %" PRIu32,
            __FUNCTION__, *elem.type.get(), *elem.type_kind.get(),
            *elem.type_vec_size.get(), *elem.field_count.get());

  // If this Element has subelements then JIT rsaElementGetSubElements() for
  // details about its fields
  return !(*elem.field_count.get() > 0 &&
           !JITSubelements(elem, context, frame_ptr));
}

// JITs the RS runtime for information about the subelements/fields of a struct
// allocation This is necessary for infering the struct type so we can pretty
// print the allocation's contents. Returns true on success, false otherwise
bool RenderScriptRuntime::JITSubelements(Element &elem,
                                         const lldb::addr_t context,
                                         StackFrame *frame_ptr) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));

  if (!elem.element_ptr.isValid() || !elem.field_count.isValid()) {
    LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__);
    return false;
  }

  const short num_exprs = 3;
  static_assert(num_exprs == (eExprSubelementsArrSize - eExprSubelementsId + 1),
                "Invalid number of expressions");

  char expr_buffer[jit_max_expr_size];
  uint64_t results;

  // Iterate over struct fields.
  const uint32_t field_count = *elem.field_count.get();
  for (uint32_t field_index = 0; field_index < field_count; ++field_index) {
    Element child;
    for (uint32_t expr_index = 0; expr_index < num_exprs; ++expr_index) {
      const char *fmt_str =
          JITTemplate(ExpressionStrings(eExprSubelementsId + expr_index));
      int written = snprintf(expr_buffer, jit_max_expr_size, fmt_str,
                             context, field_count, field_count, field_count,
                             *elem.element_ptr.get(), field_count, field_index);
      if (written < 0) {
        LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__);
        return false;
      } else if (written >= jit_max_expr_size) {
        LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__);
        return false;
      }

      // Perform expression evaluation
      if (!EvalRSExpression(expr_buffer, frame_ptr, &results))
        return false;

      LLDB_LOGF(log, "%s - expr result 0x%" PRIx64 ".", __FUNCTION__, results);

      switch (expr_index) {
      case 0: // Element* of child
        child.element_ptr = static_cast<addr_t>(results);
        break;
      case 1: // Name of child
      {
        lldb::addr_t address = static_cast<addr_t>(results);
        Status err;
        std::string name;
        GetProcess()->ReadCStringFromMemory(address, name, err);
        if (!err.Fail())
          child.type_name = ConstString(name);
        else {
          LLDB_LOGF(log, "%s - warning: Couldn't read field name.",
                    __FUNCTION__);
        }
        break;
      }
      case 2: // Array size of child
        child.array_size = static_cast<uint32_t>(results);
        break;
      }
    }

    // We need to recursively JIT each Element field of the struct since
    // structs can be nested inside structs.
    if (!JITElementPacked(child, context, frame_ptr))
      return false;
    elem.children.push_back(child);
  }

  // Try to infer the name of the struct type so we can pretty print the
  // allocation contents.
  FindStructTypeName(elem, frame_ptr);

  return true;
}

// JITs the RS runtime for the address of the last element in the allocation.
// The `elem_size` parameter represents the size of a single element, including
// padding. Which is needed as an offset from the last element pointer. Using
// this offset minus the starting address we can calculate the size of the
// allocation. Returns true on success, false otherwise
bool RenderScriptRuntime::JITAllocationSize(AllocationDetails *alloc,
                                            StackFrame *frame_ptr) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));

  if (!alloc->address.isValid() || !alloc->dimension.isValid() ||
      !alloc->data_ptr.isValid() || !alloc->element.datum_size.isValid()) {
    LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__);
    return false;
  }

  // Find dimensions
  uint32_t dim_x = alloc->dimension.get()->dim_1;
  uint32_t dim_y = alloc->dimension.get()->dim_2;
  uint32_t dim_z = alloc->dimension.get()->dim_3;

  // Our plan of jitting the last element address doesn't seem to work for
  // struct Allocations` Instead try to infer the size ourselves without any
  // inter element padding.
  if (alloc->element.children.size() > 0) {
    if (dim_x == 0)
      dim_x = 1;
    if (dim_y == 0)
      dim_y = 1;
    if (dim_z == 0)
      dim_z = 1;

    alloc->size = dim_x * dim_y * dim_z * *alloc->element.datum_size.get();

    LLDB_LOGF(log, "%s - inferred size of struct allocation %" PRIu32 ".",
              __FUNCTION__, *alloc->size.get());
    return true;
  }

  const char *fmt_str = JITTemplate(eExprGetOffsetPtr);
  char expr_buf[jit_max_expr_size];

  // Calculate last element
  dim_x = dim_x == 0 ? 0 : dim_x - 1;
  dim_y = dim_y == 0 ? 0 : dim_y - 1;
  dim_z = dim_z == 0 ? 0 : dim_z - 1;

  int written = snprintf(expr_buf, jit_max_expr_size, fmt_str,
                         *alloc->address.get(), dim_x, dim_y, dim_z);
  if (written < 0) {
    LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__);
    return false;
  } else if (written >= jit_max_expr_size) {
    LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__);
    return false;
  }

  uint64_t result = 0;
  if (!EvalRSExpression(expr_buf, frame_ptr, &result))
    return false;

  addr_t mem_ptr = static_cast<lldb::addr_t>(result);
  // Find pointer to last element and add on size of an element
  alloc->size = static_cast<uint32_t>(mem_ptr - *alloc->data_ptr.get()) +
                *alloc->element.datum_size.get();

  return true;
}

// JITs the RS runtime for information about the stride between rows in the
// allocation. This is done to detect padding, since allocated memory is
// 16-byte aligned. Returns true on success, false otherwise
bool RenderScriptRuntime::JITAllocationStride(AllocationDetails *alloc,
                                              StackFrame *frame_ptr) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));

  if (!alloc->address.isValid() || !alloc->data_ptr.isValid()) {
    LLDB_LOGF(log, "%s - failed to find allocation details.", __FUNCTION__);
    return false;
  }

  const char *fmt_str = JITTemplate(eExprGetOffsetPtr);
  char expr_buf[jit_max_expr_size];

  int written = snprintf(expr_buf, jit_max_expr_size, fmt_str,
                         *alloc->address.get(), 0, 1, 0);
  if (written < 0) {
    LLDB_LOGF(log, "%s - encoding error in snprintf().", __FUNCTION__);
    return false;
  } else if (written >= jit_max_expr_size) {
    LLDB_LOGF(log, "%s - expression too long.", __FUNCTION__);
    return false;
  }

  uint64_t result = 0;
  if (!EvalRSExpression(expr_buf, frame_ptr, &result))
    return false;

  addr_t mem_ptr = static_cast<lldb::addr_t>(result);
  alloc->stride = static_cast<uint32_t>(mem_ptr - *alloc->data_ptr.get());

  return true;
}

// JIT all the current runtime info regarding an allocation
bool RenderScriptRuntime::RefreshAllocation(AllocationDetails *alloc,
                                            StackFrame *frame_ptr) {
  // GetOffsetPointer()
  if (!JITDataPointer(alloc, frame_ptr))
    return false;

  // rsaAllocationGetType()
  if (!JITTypePointer(alloc, frame_ptr))
    return false;

  // rsaTypeGetNativeData()
  if (!JITTypePacked(alloc, frame_ptr))
    return false;

  // rsaElementGetNativeData()
  if (!JITElementPacked(alloc->element, *alloc->context.get(), frame_ptr))
    return false;

  // Sets the datum_size member in Element
  SetElementSize(alloc->element);

  // Use GetOffsetPointer() to infer size of the allocation
  return JITAllocationSize(alloc, frame_ptr);
}

// Function attempts to set the type_name member of the parameterised Element
// object. This string should be the name of the struct type the Element
// represents. We need this string for pretty printing the Element to users.
void RenderScriptRuntime::FindStructTypeName(Element &elem,
                                             StackFrame *frame_ptr) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));

  if (!elem.type_name.IsEmpty()) // Name already set
    return;
  else
    elem.type_name = Element::GetFallbackStructName(); // Default type name if
                                                       // we don't succeed

  // Find all the global variables from the script rs modules
  VariableList var_list;
  for (auto module_sp : m_rsmodules)
    module_sp->m_module->FindGlobalVariables(
        RegularExpression(llvm::StringRef(".")), UINT32_MAX, var_list);

  // Iterate over all the global variables looking for one with a matching type
  // to the Element. We make the assumption a match exists since there needs to
  // be a global variable to reflect the struct type back into java host code.
  for (const VariableSP &var_sp : var_list) {
    if (!var_sp)
      continue;

    ValueObjectSP valobj_sp = ValueObjectVariable::Create(frame_ptr, var_sp);
    if (!valobj_sp)
      continue;

    // Find the number of variable fields.
    // If it has no fields, or more fields than our Element, then it can't be
    // the struct we're looking for. Don't check for equality since RS can add
    // extra struct members for padding.
    size_t num_children = valobj_sp->GetNumChildren();
    if (num_children > elem.children.size() || num_children == 0)
      continue;

    // Iterate over children looking for members with matching field names. If
    // all the field names match, this is likely the struct we want.
    //   TODO: This could be made more robust by also checking children data
    //   sizes, or array size
    bool found = true;
    for (size_t i = 0; i < num_children; ++i) {
      ValueObjectSP child = valobj_sp->GetChildAtIndex(i, true);
      if (!child || (child->GetName() != elem.children[i].type_name)) {
        found = false;
        break;
      }
    }

    // RS can add extra struct members for padding in the format
    // '#rs_padding_[0-9]+'
    if (found && num_children < elem.children.size()) {
      const uint32_t size_diff = elem.children.size() - num_children;
      LLDB_LOGF(log, "%s - %" PRIu32 " padding struct entries", __FUNCTION__,
                size_diff);

      for (uint32_t i = 0; i < size_diff; ++i) {
        ConstString name = elem.children[num_children + i].type_name;
        if (strcmp(name.AsCString(), "#rs_padding") < 0)
          found = false;
      }
    }

    // We've found a global variable with matching type
    if (found) {
      // Dereference since our Element type isn't a pointer.
      if (valobj_sp->IsPointerType()) {
        Status err;
        ValueObjectSP deref_valobj = valobj_sp->Dereference(err);
        if (!err.Fail())
          valobj_sp = deref_valobj;
      }

      // Save name of variable in Element.
      elem.type_name = valobj_sp->GetTypeName();
      LLDB_LOGF(log, "%s - element name set to %s", __FUNCTION__,
                elem.type_name.AsCString());

      return;
    }
  }
}

// Function sets the datum_size member of Element. Representing the size of a
// single instance including padding. Assumes the relevant allocation
// information has already been jitted.
void RenderScriptRuntime::SetElementSize(Element &elem) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
  const Element::DataType type = *elem.type.get();
  assert(type >= Element::RS_TYPE_NONE && type <= Element::RS_TYPE_FONT &&
         "Invalid allocation type");

  const uint32_t vec_size = *elem.type_vec_size.get();
  uint32_t data_size = 0;
  uint32_t padding = 0;

  // Element is of a struct type, calculate size recursively.
  if ((type == Element::RS_TYPE_NONE) && (elem.children.size() > 0)) {
    for (Element &child : elem.children) {
      SetElementSize(child);
      const uint32_t array_size =
          child.array_size.isValid() ? *child.array_size.get() : 1;
      data_size += *child.datum_size.get() * array_size;
    }
  }
  // These have been packed already
  else if (type == Element::RS_TYPE_UNSIGNED_5_6_5 ||
           type == Element::RS_TYPE_UNSIGNED_5_5_5_1 ||
           type == Element::RS_TYPE_UNSIGNED_4_4_4_4) {
    data_size = AllocationDetails::RSTypeToFormat[type][eElementSize];
  } else if (type < Element::RS_TYPE_ELEMENT) {
    data_size =
        vec_size * AllocationDetails::RSTypeToFormat[type][eElementSize];
    if (vec_size == 3)
      padding = AllocationDetails::RSTypeToFormat[type][eElementSize];
  } else
    data_size =
        GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();

  elem.padding = padding;
  elem.datum_size = data_size + padding;
  LLDB_LOGF(log, "%s - element size set to %" PRIu32, __FUNCTION__,
            data_size + padding);
}

// Given an allocation, this function copies the allocation contents from
// device into a buffer on the heap. Returning a shared pointer to the buffer
// containing the data.
std::shared_ptr<uint8_t>
RenderScriptRuntime::GetAllocationData(AllocationDetails *alloc,
                                       StackFrame *frame_ptr) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));

  // JIT all the allocation details
  if (alloc->ShouldRefresh()) {
    LLDB_LOGF(log, "%s - allocation details not calculated yet, jitting info",
              __FUNCTION__);

    if (!RefreshAllocation(alloc, frame_ptr)) {
      LLDB_LOGF(log, "%s - couldn't JIT allocation details", __FUNCTION__);
      return nullptr;
    }
  }

  assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() &&
         alloc->element.type_vec_size.isValid() && alloc->size.isValid() &&
         "Allocation information not available");

  // Allocate a buffer to copy data into
  const uint32_t size = *alloc->size.get();
  std::shared_ptr<uint8_t> buffer(new uint8_t[size]);
  if (!buffer) {
    LLDB_LOGF(log, "%s - couldn't allocate a %" PRIu32 " byte buffer",
              __FUNCTION__, size);
    return nullptr;
  }

  // Read the inferior memory
  Status err;
  lldb::addr_t data_ptr = *alloc->data_ptr.get();
  GetProcess()->ReadMemory(data_ptr, buffer.get(), size, err);
  if (err.Fail()) {
    LLDB_LOGF(log,
              "%s - '%s' Couldn't read %" PRIu32
              " bytes of allocation data from 0x%" PRIx64,
              __FUNCTION__, err.AsCString(), size, data_ptr);
    return nullptr;
  }

  return buffer;
}

// Function copies data from a binary file into an allocation. There is a
// header at the start of the file, FileHeader, before the data content itself.
// Information from this header is used to display warnings to the user about
// incompatibilities
bool RenderScriptRuntime::LoadAllocation(Stream &strm, const uint32_t alloc_id,
                                         const char *path,
                                         StackFrame *frame_ptr) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));

  // Find allocation with the given id
  AllocationDetails *alloc = FindAllocByID(strm, alloc_id);
  if (!alloc)
    return false;

  LLDB_LOGF(log, "%s - found allocation 0x%" PRIx64, __FUNCTION__,
            *alloc->address.get());

  // JIT all the allocation details
  if (alloc->ShouldRefresh()) {
    LLDB_LOGF(log, "%s - allocation details not calculated yet, jitting info.",
              __FUNCTION__);

    if (!RefreshAllocation(alloc, frame_ptr)) {
      LLDB_LOGF(log, "%s - couldn't JIT allocation details", __FUNCTION__);
      return false;
    }
  }

  assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() &&
         alloc->element.type_vec_size.isValid() && alloc->size.isValid() &&
         alloc->element.datum_size.isValid() &&
         "Allocation information not available");

  // Check we can read from file
  FileSpec file(path);
  FileSystem::Instance().Resolve(file);
  if (!FileSystem::Instance().Exists(file)) {
    strm.Printf("Error: File %s does not exist", path);
    strm.EOL();
    return false;
  }

  if (!FileSystem::Instance().Readable(file)) {
    strm.Printf("Error: File %s does not have readable permissions", path);
    strm.EOL();
    return false;
  }

  // Read file into data buffer
  auto data_sp = FileSystem::Instance().CreateDataBuffer(file.GetPath());

  // Cast start of buffer to FileHeader and use pointer to read metadata
  void *file_buf = data_sp->GetBytes();
  if (file_buf == nullptr ||
      data_sp->GetByteSize() < (sizeof(AllocationDetails::FileHeader) +
                                sizeof(AllocationDetails::ElementHeader))) {
    strm.Printf("Error: File %s does not contain enough data for header", path);
    strm.EOL();
    return false;
  }
  const AllocationDetails::FileHeader *file_header =
      static_cast<AllocationDetails::FileHeader *>(file_buf);

  // Check file starts with ascii characters "RSAD"
  if (memcmp(file_header->ident, "RSAD", 4)) {
    strm.Printf("Error: File doesn't contain identifier for an RS allocation "
                "dump. Are you sure this is the correct file?");
    strm.EOL();
    return false;
  }

  // Look at the type of the root element in the header
  AllocationDetails::ElementHeader root_el_hdr;
  memcpy(&root_el_hdr, static_cast<uint8_t *>(file_buf) +
                           sizeof(AllocationDetails::FileHeader),
         sizeof(AllocationDetails::ElementHeader));

  LLDB_LOGF(log, "%s - header type %" PRIu32 ", element size %" PRIu32,
            __FUNCTION__, root_el_hdr.type, root_el_hdr.element_size);

  // Check if the target allocation and file both have the same number of bytes
  // for an Element
  if (*alloc->element.datum_size.get() != root_el_hdr.element_size) {
    strm.Printf("Warning: Mismatched Element sizes - file %" PRIu32
                " bytes, allocation %" PRIu32 " bytes",
                root_el_hdr.element_size, *alloc->element.datum_size.get());
    strm.EOL();
  }

  // Check if the target allocation and file both have the same type
  const uint32_t alloc_type = static_cast<uint32_t>(*alloc->element.type.get());
  const uint32_t file_type = root_el_hdr.type;

  if (file_type > Element::RS_TYPE_FONT) {
    strm.Printf("Warning: File has unknown allocation type");
    strm.EOL();
  } else if (alloc_type != file_type) {
    // Enum value isn't monotonous, so doesn't always index RsDataTypeToString
    // array
    uint32_t target_type_name_idx = alloc_type;
    uint32_t head_type_name_idx = file_type;
    if (alloc_type >= Element::RS_TYPE_ELEMENT &&
        alloc_type <= Element::RS_TYPE_FONT)
      target_type_name_idx = static_cast<Element::DataType>(
          (alloc_type - Element::RS_TYPE_ELEMENT) +
          Element::RS_TYPE_MATRIX_2X2 + 1);

    if (file_type >= Element::RS_TYPE_ELEMENT &&
        file_type <= Element::RS_TYPE_FONT)
      head_type_name_idx = static_cast<Element::DataType>(
          (file_type - Element::RS_TYPE_ELEMENT) + Element::RS_TYPE_MATRIX_2X2 +
          1);

    const char *head_type_name =
        AllocationDetails::RsDataTypeToString[head_type_name_idx][0];
    const char *target_type_name =
        AllocationDetails::RsDataTypeToString[target_type_name_idx][0];

    strm.Printf(
        "Warning: Mismatched Types - file '%s' type, allocation '%s' type",
        head_type_name, target_type_name);
    strm.EOL();
  }

  // Advance buffer past header
  file_buf = static_cast<uint8_t *>(file_buf) + file_header->hdr_size;

  // Calculate size of allocation data in file
  size_t size = data_sp->GetByteSize() - file_header->hdr_size;

  // Check if the target allocation and file both have the same total data
  // size.
  const uint32_t alloc_size = *alloc->size.get();
  if (alloc_size != size) {
    strm.Printf("Warning: Mismatched allocation sizes - file 0x%" PRIx64
                " bytes, allocation 0x%" PRIx32 " bytes",
                (uint64_t)size, alloc_size);
    strm.EOL();
    // Set length to copy to minimum
    size = alloc_size < size ? alloc_size : size;
  }

  // Copy file data from our buffer into the target allocation.
  lldb::addr_t alloc_data = *alloc->data_ptr.get();
  Status err;
  size_t written = GetProcess()->WriteMemory(alloc_data, file_buf, size, err);
  if (!err.Success() || written != size) {
    strm.Printf("Error: Couldn't write data to allocation %s", err.AsCString());
    strm.EOL();
    return false;
  }

  strm.Printf("Contents of file '%s' read into allocation %" PRIu32, path,
              alloc->id);
  strm.EOL();

  return true;
}

// Function takes as parameters a byte buffer, which will eventually be written
// to file as the element header, an offset into that buffer, and an Element
// that will be saved into the buffer at the parametrised offset. Return value
// is the new offset after writing the element into the buffer. Elements are
// saved to the file as the ElementHeader struct followed by offsets to the
// structs of all the element's children.
size_t RenderScriptRuntime::PopulateElementHeaders(
    const std::shared_ptr<uint8_t> header_buffer, size_t offset,
    const Element &elem) {
  // File struct for an element header with all the relevant details copied
  // from elem. We assume members are valid already.
  AllocationDetails::ElementHeader elem_header;
  elem_header.type = *elem.type.get();
  elem_header.kind = *elem.type_kind.get();
  elem_header.element_size = *elem.datum_size.get();
  elem_header.vector_size = *elem.type_vec_size.get();
  elem_header.array_size =
      elem.array_size.isValid() ? *elem.array_size.get() : 0;
  const size_t elem_header_size = sizeof(AllocationDetails::ElementHeader);

  // Copy struct into buffer and advance offset We assume that header_buffer
  // has been checked for nullptr before this method is called
  memcpy(header_buffer.get() + offset, &elem_header, elem_header_size);
  offset += elem_header_size;

  // Starting offset of child ElementHeader struct
  size_t child_offset =
      offset + ((elem.children.size() + 1) * sizeof(uint32_t));
  for (const RenderScriptRuntime::Element &child : elem.children) {
    // Recursively populate the buffer with the element header structs of
    // children. Then save the offsets where they were set after the parent
    // element header.
    memcpy(header_buffer.get() + offset, &child_offset, sizeof(uint32_t));
    offset += sizeof(uint32_t);

    child_offset = PopulateElementHeaders(header_buffer, child_offset, child);
  }

  // Zero indicates no more children
  memset(header_buffer.get() + offset, 0, sizeof(uint32_t));

  return child_offset;
}

// Given an Element object this function returns the total size needed in the
// file header to store the element's details. Taking into account the size of
// the element header struct, plus the offsets to all the element's children.
// Function is recursive so that the size of all ancestors is taken into
// account.
size_t RenderScriptRuntime::CalculateElementHeaderSize(const Element &elem) {
  // Offsets to children plus zero terminator
  size_t size = (elem.children.size() + 1) * sizeof(uint32_t);
  // Size of header struct with type details
  size += sizeof(AllocationDetails::ElementHeader);

  // Calculate recursively for all descendants
  for (const Element &child : elem.children)
    size += CalculateElementHeaderSize(child);

  return size;
}

// Function copies allocation contents into a binary file. This file can then
// be loaded later into a different allocation. There is a header, FileHeader,
// before the allocation data containing meta-data.
bool RenderScriptRuntime::SaveAllocation(Stream &strm, const uint32_t alloc_id,
                                         const char *path,
                                         StackFrame *frame_ptr) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));

  // Find allocation with the given id
  AllocationDetails *alloc = FindAllocByID(strm, alloc_id);
  if (!alloc)
    return false;

  LLDB_LOGF(log, "%s - found allocation 0x%" PRIx64 ".", __FUNCTION__,
            *alloc->address.get());

  // JIT all the allocation details
  if (alloc->ShouldRefresh()) {
    LLDB_LOGF(log, "%s - allocation details not calculated yet, jitting info.",
              __FUNCTION__);

    if (!RefreshAllocation(alloc, frame_ptr)) {
      LLDB_LOGF(log, "%s - couldn't JIT allocation details.", __FUNCTION__);
      return false;
    }
  }

  assert(alloc->data_ptr.isValid() && alloc->element.type.isValid() &&
         alloc->element.type_vec_size.isValid() &&
         alloc->element.datum_size.get() &&
         alloc->element.type_kind.isValid() && alloc->dimension.isValid() &&
         "Allocation information not available");

  // Check we can create writable file
  FileSpec file_spec(path);
  FileSystem::Instance().Resolve(file_spec);
  auto file = FileSystem::Instance().Open(
      file_spec, File::eOpenOptionWriteOnly | File::eOpenOptionCanCreate |
                     File::eOpenOptionTruncate);

  if (!file) {
    std::string error = llvm::toString(file.takeError());
    strm.Printf("Error: Failed to open '%s' for writing: %s", path,
                error.c_str());
    strm.EOL();
    return false;
  }

  // Read allocation into buffer of heap memory
  const std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr);
  if (!buffer) {
    strm.Printf("Error: Couldn't read allocation data into buffer");
    strm.EOL();
    return false;
  }

  // Create the file header
  AllocationDetails::FileHeader head;
  memcpy(head.ident, "RSAD", 4);
  head.dims[0] = static_cast<uint32_t>(alloc->dimension.get()->dim_1);
  head.dims[1] = static_cast<uint32_t>(alloc->dimension.get()->dim_2);
  head.dims[2] = static_cast<uint32_t>(alloc->dimension.get()->dim_3);

  const size_t element_header_size = CalculateElementHeaderSize(alloc->element);
  assert((sizeof(AllocationDetails::FileHeader) + element_header_size) <
             UINT16_MAX &&
         "Element header too large");
  head.hdr_size = static_cast<uint16_t>(sizeof(AllocationDetails::FileHeader) +
                                        element_header_size);

  // Write the file header
  size_t num_bytes = sizeof(AllocationDetails::FileHeader);
  LLDB_LOGF(log, "%s - writing File Header, 0x%" PRIx64 " bytes", __FUNCTION__,
            (uint64_t)num_bytes);

  Status err = file.get()->Write(&head, num_bytes);
  if (!err.Success()) {
    strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), path);
    strm.EOL();
    return false;
  }

  // Create the headers describing the element type of the allocation.
  std::shared_ptr<uint8_t> element_header_buffer(
      new uint8_t[element_header_size]);
  if (element_header_buffer == nullptr) {
    strm.Printf("Internal Error: Couldn't allocate %" PRIu64
                " bytes on the heap",
                (uint64_t)element_header_size);
    strm.EOL();
    return false;
  }

  PopulateElementHeaders(element_header_buffer, 0, alloc->element);

  // Write headers for allocation element type to file
  num_bytes = element_header_size;
  LLDB_LOGF(log, "%s - writing element headers, 0x%" PRIx64 " bytes.",
            __FUNCTION__, (uint64_t)num_bytes);

  err = file.get()->Write(element_header_buffer.get(), num_bytes);
  if (!err.Success()) {
    strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), path);
    strm.EOL();
    return false;
  }

  // Write allocation data to file
  num_bytes = static_cast<size_t>(*alloc->size.get());
  LLDB_LOGF(log, "%s - writing 0x%" PRIx64 " bytes", __FUNCTION__,
            (uint64_t)num_bytes);

  err = file.get()->Write(buffer.get(), num_bytes);
  if (!err.Success()) {
    strm.Printf("Error: '%s' when writing to file '%s'", err.AsCString(), path);
    strm.EOL();
    return false;
  }

  strm.Printf("Allocation written to file '%s'", path);
  strm.EOL();
  return true;
}

bool RenderScriptRuntime::LoadModule(const lldb::ModuleSP &module_sp) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));

  if (module_sp) {
    for (const auto &rs_module : m_rsmodules) {
      if (rs_module->m_module == module_sp) {
        // Check if the user has enabled automatically breaking on all RS
        // kernels.
        if (m_breakAllKernels)
          BreakOnModuleKernels(rs_module);

        return false;
      }
    }
    bool module_loaded = false;
    switch (GetModuleKind(module_sp)) {
    case eModuleKindKernelObj: {
      RSModuleDescriptorSP module_desc;
      module_desc = std::make_shared<RSModuleDescriptor>(module_sp);
      if (module_desc->ParseRSInfo()) {
        m_rsmodules.push_back(module_desc);
        module_desc->WarnIfVersionMismatch(GetProcess()
                                               ->GetTarget()
                                               .GetDebugger()
                                               .GetAsyncOutputStream()
                                               .get());
        module_loaded = true;
      }
      if (module_loaded) {
        FixupScriptDetails(module_desc);
      }
      break;
    }
    case eModuleKindDriver: {
      if (!m_libRSDriver) {
        m_libRSDriver = module_sp;
        LoadRuntimeHooks(m_libRSDriver, RenderScriptRuntime::eModuleKindDriver);
      }
      break;
    }
    case eModuleKindImpl: {
      if (!m_libRSCpuRef) {
        m_libRSCpuRef = module_sp;
        LoadRuntimeHooks(m_libRSCpuRef, RenderScriptRuntime::eModuleKindImpl);
      }
      break;
    }
    case eModuleKindLibRS: {
      if (!m_libRS) {
        m_libRS = module_sp;
        static ConstString gDbgPresentStr("gDebuggerPresent");
        const Symbol *debug_present = m_libRS->FindFirstSymbolWithNameAndType(
            gDbgPresentStr, eSymbolTypeData);
        if (debug_present) {
          Status err;
          uint32_t flag = 0x00000001U;
          Target &target = GetProcess()->GetTarget();
          addr_t addr = debug_present->GetLoadAddress(&target);
          GetProcess()->WriteMemory(addr, &flag, sizeof(flag), err);
          if (err.Success()) {
            LLDB_LOGF(log, "%s - debugger present flag set on debugee.",
                      __FUNCTION__);

            m_debuggerPresentFlagged = true;
          } else if (log) {
            LLDB_LOGF(log, "%s - error writing debugger present flags '%s' ",
                      __FUNCTION__, err.AsCString());
          }
        } else if (log) {
          LLDB_LOGF(
              log,
              "%s - error writing debugger present flags - symbol not found",
              __FUNCTION__);
        }
      }
      break;
    }
    default:
      break;
    }
    if (module_loaded)
      Update();
    return module_loaded;
  }
  return false;
}

void RenderScriptRuntime::Update() {
  if (m_rsmodules.size() > 0) {
    if (!m_initiated) {
      Initiate();
    }
  }
}

void RSModuleDescriptor::WarnIfVersionMismatch(lldb_private::Stream *s) const {
  if (!s)
    return;

  if (m_slang_version.empty() || m_bcc_version.empty()) {
    s->PutCString("WARNING: Unknown bcc or slang (llvm-rs-cc) version; debug "
                  "experience may be unreliable");
    s->EOL();
  } else if (m_slang_version != m_bcc_version) {
    s->Printf("WARNING: The debug info emitted by the slang frontend "
              "(llvm-rs-cc) used to build this module (%s) does not match the "
              "version of bcc used to generate the debug information (%s). "
              "This is an unsupported configuration and may result in a poor "
              "debugging experience; proceed with caution",
              m_slang_version.c_str(), m_bcc_version.c_str());
    s->EOL();
  }
}

bool RSModuleDescriptor::ParsePragmaCount(llvm::StringRef *lines,
                                          size_t n_lines) {
  // Skip the pragma prototype line
  ++lines;
  for (; n_lines--; ++lines) {
    const auto kv_pair = lines->split(" - ");
    m_pragmas[kv_pair.first.trim().str()] = kv_pair.second.trim().str();
  }
  return true;
}

bool RSModuleDescriptor::ParseExportReduceCount(llvm::StringRef *lines,
                                                size_t n_lines) {
  // The list of reduction kernels in the `.rs.info` symbol is of the form
  // "signature - accumulatordatasize - reduction_name - initializer_name -
  // accumulator_name - combiner_name - outconverter_name - halter_name" Where
  // a function is not explicitly named by the user, or is not generated by the
  // compiler, it is named "." so the dash separated list should always be 8
  // items long
  Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);
  // Skip the exportReduceCount line
  ++lines;
  for (; n_lines--; ++lines) {
    llvm::SmallVector<llvm::StringRef, 8> spec;
    lines->split(spec, " - ");
    if (spec.size() != 8) {
      if (spec.size() < 8) {
        if (log)
          log->Error("Error parsing RenderScript reduction spec. wrong number "
                     "of fields");
        return false;
      } else if (log)
        log->Warning("Extraneous members in reduction spec: '%s'",
                     lines->str().c_str());
    }

    const auto sig_s = spec[0];
    uint32_t sig;
    if (sig_s.getAsInteger(10, sig)) {
      if (log)
        log->Error("Error parsing Renderscript reduction spec: invalid kernel "
                   "signature: '%s'",
                   sig_s.str().c_str());
      return false;
    }

    const auto accum_data_size_s = spec[1];
    uint32_t accum_data_size;
    if (accum_data_size_s.getAsInteger(10, accum_data_size)) {
      if (log)
        log->Error("Error parsing Renderscript reduction spec: invalid "
                   "accumulator data size %s",
                   accum_data_size_s.str().c_str());
      return false;
    }

    LLDB_LOGF(log, "Found RenderScript reduction '%s'", spec[2].str().c_str());

    m_reductions.push_back(RSReductionDescriptor(this, sig, accum_data_size,
                                                 spec[2], spec[3], spec[4],
                                                 spec[5], spec[6], spec[7]));
  }
  return true;
}

bool RSModuleDescriptor::ParseVersionInfo(llvm::StringRef *lines,
                                          size_t n_lines) {
  // Skip the versionInfo line
  ++lines;
  for (; n_lines--; ++lines) {
    // We're only interested in bcc and slang versions, and ignore all other
    // versionInfo lines
    const auto kv_pair = lines->split(" - ");
    if (kv_pair.first == "slang")
      m_slang_version = kv_pair.second.str();
    else if (kv_pair.first == "bcc")
      m_bcc_version = kv_pair.second.str();
  }
  return true;
}

bool RSModuleDescriptor::ParseExportForeachCount(llvm::StringRef *lines,
                                                 size_t n_lines) {
  // Skip the exportForeachCount line
  ++lines;
  for (; n_lines--; ++lines) {
    uint32_t slot;
    // `forEach` kernels are listed in the `.rs.info` packet as a "slot - name"
    // pair per line
    const auto kv_pair = lines->split(" - ");
    if (kv_pair.first.getAsInteger(10, slot))
      return false;
    m_kernels.push_back(RSKernelDescriptor(this, kv_pair.second, slot));
  }
  return true;
}

bool RSModuleDescriptor::ParseExportVarCount(llvm::StringRef *lines,
                                             size_t n_lines) {
  // Skip the ExportVarCount line
  ++lines;
  for (; n_lines--; ++lines)
    m_globals.push_back(RSGlobalDescriptor(this, *lines));
  return true;
}

// The .rs.info symbol in renderscript modules contains a string which needs to
// be parsed. The string is basic and is parsed on a line by line basis.
bool RSModuleDescriptor::ParseRSInfo() {
  assert(m_module);
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));
  const Symbol *info_sym = m_module->FindFirstSymbolWithNameAndType(
      ConstString(".rs.info"), eSymbolTypeData);
  if (!info_sym)
    return false;

  const addr_t addr = info_sym->GetAddressRef().GetFileAddress();
  if (addr == LLDB_INVALID_ADDRESS)
    return false;

  const addr_t size = info_sym->GetByteSize();
  const FileSpec fs = m_module->GetFileSpec();

  auto buffer =
      FileSystem::Instance().CreateDataBuffer(fs.GetPath(), size, addr);
  if (!buffer)
    return false;

  // split rs.info. contents into lines
  llvm::SmallVector<llvm::StringRef, 128> info_lines;
  {
    const llvm::StringRef raw_rs_info((const char *)buffer->GetBytes());
    raw_rs_info.split(info_lines, '\n');
    LLDB_LOGF(log, "'.rs.info symbol for '%s':\n%s",
              m_module->GetFileSpec().GetCString(), raw_rs_info.str().c_str());
  }

  enum {
    eExportVar,
    eExportForEach,
    eExportReduce,
    ePragma,
    eBuildChecksum,
    eObjectSlot,
    eVersionInfo,
  };

  const auto rs_info_handler = [](llvm::StringRef name) -> int {
    return llvm::StringSwitch<int>(name)
        // The number of visible global variables in the script
        .Case("exportVarCount", eExportVar)
        // The number of RenderScrip `forEach` kernels __attribute__((kernel))
        .Case("exportForEachCount", eExportForEach)
        // The number of generalreductions: This marked in the script by
        // `#pragma reduce()`
        .Case("exportReduceCount", eExportReduce)
        // Total count of all RenderScript specific `#pragmas` used in the
        // script
        .Case("pragmaCount", ePragma)
        .Case("objectSlotCount", eObjectSlot)
        .Case("versionInfo", eVersionInfo)
        .Default(-1);
  };

  // parse all text lines of .rs.info
  for (auto line = info_lines.begin(); line != info_lines.end(); ++line) {
    const auto kv_pair = line->split(": ");
    const auto key = kv_pair.first;
    const auto val = kv_pair.second.trim();

    const auto handler = rs_info_handler(key);
    if (handler == -1)
      continue;
    // getAsInteger returns `true` on an error condition - we're only
    // interested in numeric fields at the moment
    uint64_t n_lines;
    if (val.getAsInteger(10, n_lines)) {
      LLDB_LOGV(log, "Failed to parse non-numeric '.rs.info' section {0}",
                line->str());
      continue;
    }
    if (info_lines.end() - (line + 1) < (ptrdiff_t)n_lines)
      return false;

    bool success = false;
    switch (handler) {
    case eExportVar:
      success = ParseExportVarCount(line, n_lines);
      break;
    case eExportForEach:
      success = ParseExportForeachCount(line, n_lines);
      break;
    case eExportReduce:
      success = ParseExportReduceCount(line, n_lines);
      break;
    case ePragma:
      success = ParsePragmaCount(line, n_lines);
      break;
    case eVersionInfo:
      success = ParseVersionInfo(line, n_lines);
      break;
    default: {
      LLDB_LOGF(log, "%s - skipping .rs.info field '%s'", __FUNCTION__,
                line->str().c_str());
      continue;
    }
    }
    if (!success)
      return false;
    line += n_lines;
  }
  return info_lines.size() > 0;
}

void RenderScriptRuntime::DumpStatus(Stream &strm) const {
  if (m_libRS) {
    strm.Printf("Runtime Library discovered.");
    strm.EOL();
  }
  if (m_libRSDriver) {
    strm.Printf("Runtime Driver discovered.");
    strm.EOL();
  }
  if (m_libRSCpuRef) {
    strm.Printf("CPU Reference Implementation discovered.");
    strm.EOL();
  }

  if (m_runtimeHooks.size()) {
    strm.Printf("Runtime functions hooked:");
    strm.EOL();
    for (auto b : m_runtimeHooks) {
      strm.Indent(b.second->defn->name);
      strm.EOL();
    }
  } else {
    strm.Printf("Runtime is not hooked.");
    strm.EOL();
  }
}

void RenderScriptRuntime::DumpContexts(Stream &strm) const {
  strm.Printf("Inferred RenderScript Contexts:");
  strm.EOL();
  strm.IndentMore();

  std::map<addr_t, uint64_t> contextReferences;

  // Iterate over all of the currently discovered scripts. Note: We cant push
  // or pop from m_scripts inside this loop or it may invalidate script.
  for (const auto &script : m_scripts) {
    if (!script->context.isValid())
      continue;
    lldb::addr_t context = *script->context;

    if (contextReferences.find(context) != contextReferences.end()) {
      contextReferences[context]++;
    } else {
      contextReferences[context] = 1;
    }
  }

  for (const auto &cRef : contextReferences) {
    strm.Printf("Context 0x%" PRIx64 ": %" PRIu64 " script instances",
                cRef.first, cRef.second);
    strm.EOL();
  }
  strm.IndentLess();
}

void RenderScriptRuntime::DumpKernels(Stream &strm) const {
  strm.Printf("RenderScript Kernels:");
  strm.EOL();
  strm.IndentMore();
  for (const auto &module : m_rsmodules) {
    strm.Printf("Resource '%s':", module->m_resname.c_str());
    strm.EOL();
    for (const auto &kernel : module->m_kernels) {
      strm.Indent(kernel.m_name.GetStringRef());
      strm.EOL();
    }
  }
  strm.IndentLess();
}

RenderScriptRuntime::AllocationDetails *
RenderScriptRuntime::FindAllocByID(Stream &strm, const uint32_t alloc_id) {
  AllocationDetails *alloc = nullptr;

  // See if we can find allocation using id as an index;
  if (alloc_id <= m_allocations.size() && alloc_id != 0 &&
      m_allocations[alloc_id - 1]->id == alloc_id) {
    alloc = m_allocations[alloc_id - 1].get();
    return alloc;
  }

  // Fallback to searching
  for (const auto &a : m_allocations) {
    if (a->id == alloc_id) {
      alloc = a.get();
      break;
    }
  }

  if (alloc == nullptr) {
    strm.Printf("Error: Couldn't find allocation with id matching %" PRIu32,
                alloc_id);
    strm.EOL();
  }

  return alloc;
}

// Prints the contents of an allocation to the output stream, which may be a
// file
bool RenderScriptRuntime::DumpAllocation(Stream &strm, StackFrame *frame_ptr,
                                         const uint32_t id) {
  Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE));

  // Check we can find the desired allocation
  AllocationDetails *alloc = FindAllocByID(strm, id);
  if (!alloc)
    return false; // FindAllocByID() will print error message for us here

  LLDB_LOGF(log, "%s - found allocation 0x%" PRIx64, __FUNCTION__,
            *alloc->address.get());

  // Check we have information about the allocation, if not calculate it
  if (alloc->ShouldRefresh()) {
    LLDB_LOGF(log, "%s - allocation details not calculated yet, jitting info.",
              __FUNCTION__);

    // JIT all the allocation information
    if (!RefreshAllocation(alloc, frame_ptr)) {
      strm.Printf("Error: Couldn't JIT allocation details");
      strm.EOL();
      return false;
    }
  }

  // Establish format and size of each data element
  const uint32_t vec_size = *alloc->element.type_vec_size.get();
  const Element::DataType type = *alloc->element.type.get();

  assert(type >= Element::RS_TYPE_NONE && type <= Element::RS_TYPE_FONT &&
         "Invalid allocation type");

  lldb::Format format;
  if (type >= Element::RS_TYPE_ELEMENT)
    format = eFormatHex;
  else
    format = vec_size == 1
                 ? static_cast<lldb::Format>(
                       AllocationDetails::RSTypeToFormat[type][eFormatSingle])
                 : static_cast<lldb::Format>(
                       AllocationDetails::RSTypeToFormat[type][eFormatVector]);

  const uint32_t data_size = *alloc->element.datum_size.get();

  LLDB_LOGF(log, "%s - element size %" PRIu32 " bytes, including padding",
            __FUNCTION__, data_size);

  // Allocate a buffer to copy data into
  std::shared_ptr<uint8_t> buffer = GetAllocationData(alloc, frame_ptr);
  if (!buffer) {
    strm.Printf("Error: Couldn't read allocation data");
    strm.EOL();
    return false;
  }

  // Calculate stride between rows as there may be padding at end of rows since
  // allocated memory is 16-byte aligned
  if (!alloc->stride.isValid()) {
    if (alloc->dimension.get()->dim_2 == 0) // We only have one dimension
      alloc->stride = 0;
    else if (!JITAllocationStride(alloc, frame_ptr)) {
      strm.Printf("Error: Couldn't calculate allocation row stride");
      strm.EOL();
      return false;
    }
  }
  const uint32_t stride = *alloc->stride.get();
  const uint32_t size = *alloc->size.get(); // Size of whole allocation
  const uint32_t padding =
      alloc->element.padding.isValid() ? *alloc->element.padding.get() : 0;
  LLDB_LOGF(log,
            "%s - stride %" PRIu32 " bytes, size %" PRIu32
            " bytes, padding %" PRIu32,
            __FUNCTION__, stride, size, padding);

  // Find dimensions used to index loops, so need to be non-zero
  uint32_t dim_x = alloc->dimension.get()->dim_1;
  dim_x = dim_x == 0 ? 1 : dim_x;

  uint32_t dim_y = alloc->dimension.get()->dim_2;
  dim_y = dim_y == 0 ? 1 : dim_y;

  uint32_t dim_z = alloc->dimension.get()->dim_3;
  dim_z = dim_z == 0 ? 1 : dim_z;

  // Use data extractor to format output
  const uint32_t target_ptr_size =
      GetProcess()->GetTarget().GetArchitecture().GetAddressByteSize();
  DataExtractor alloc_data(buffer.get(), size, GetProcess()->GetByteOrder(),
                           target_ptr_size);

  uint32_t offset = 0;   // Offset in buffer to next element to be printed
  uint32_t prev_row = 0; // Offset to the start of the previous row

  // Iterate over allocation dimensions, printing results to user
  strm.Printf("Data (X, Y, Z):");
  for (uint32_t z = 0; z < dim_z; ++z) {
    for (uint32_t y = 0; y < dim_y; ++y) {
      // Use stride to index start of next row.
      if (!(y == 0 && z == 0))
        offset = prev_row + stride;
      prev_row = offset;

      // Print each element in the row individually
      for (uint32_t x = 0; x < dim_x; ++x) {
        strm.Printf("\n(%" PRIu32 ", %" PRIu32 ", %" PRIu32 ") = ", x, y, z);
        if ((type == Element::RS_TYPE_NONE) &&
            (alloc->element.children.size() > 0) &&
            (alloc->element.type_name != Element::GetFallbackStructName())) {
          // Here we are dumping an Element of struct type. This is done using
          // expression evaluation with the name of the struct type and pointer
          // to element. Don't print the name of the resulting expression,
          // since this will be '$[0-9]+'
          DumpValueObjectOptions expr_options;
          expr_options.SetHideName(true);

          // Setup expression as dereferencing a pointer cast to element
          // address.
          char expr_char_buffer[jit_max_expr_size];
          int written =
              snprintf(expr_char_buffer, jit_max_expr_size, "*(%s*) 0x%" PRIx64,
                       alloc->element.type_name.AsCString(),
                       *alloc->data_ptr.get() + offset);

          if (written < 0 || written >= jit_max_expr_size) {
            LLDB_LOGF(log, "%s - error in snprintf().", __FUNCTION__);
            continue;
          }

          // Evaluate expression
          ValueObjectSP expr_result;
          GetProcess()->GetTarget().EvaluateExpression(expr_char_buffer,
                                                       frame_ptr, expr_result);

          // Print the results to our stream.
          expr_result->Dump(strm, expr_options);
        } else {
          DumpDataExtractor(alloc_data, &strm, offset, format,
                            data_size - padding, 1, 1, LLDB_INVALID_ADDRESS, 0,
                            0);
        }
        offset += data_size;
      }
    }
  }
  strm.EOL();

  return true;
}

// Function recalculates all our cached information about allocations by
// jitting the RS runtime regarding each allocation we know about. Returns true
// if all allocations could be recomputed, false otherwise.
bool RenderScriptRuntime::RecomputeAllAllocations(Stream &strm,
                                                  StackFrame *frame_ptr) {
  bool success = true;
  for (auto &alloc : m_allocations) {
    // JIT current allocation information
    if (!RefreshAllocation(alloc.get(), frame_ptr)) {
      strm.Printf("Error: Couldn't evaluate details for allocation %" PRIu32
                  "\n",
                  alloc->id);
      success = false;
    }
  }

  if (success)
    strm.Printf("All allocations successfully recomputed");
  strm.EOL();

  return success;
}

// Prints information regarding currently loaded allocations. These details are
// gathered by jitting the runtime, which has as latency. Index parameter
// specifies a single allocation ID to print, or a zero value to print them all
void RenderScriptRuntime::ListAllocations(Stream &strm, StackFrame *frame_ptr,
                                          const uint32_t index) {
  strm.Printf("RenderScript Allocations:");
  strm.EOL();
  strm.IndentMore();

  for (auto &alloc : m_allocations) {
    // index will only be zero if we want to print all allocations
    if (index != 0 && index != alloc->id)
      continue;

    // JIT current allocation information
    if (alloc->ShouldRefresh() && !RefreshAllocation(alloc.get(), frame_ptr)) {
      strm.Printf("Error: Couldn't evaluate details for allocation %" PRIu32,
                  alloc->id);
      strm.EOL();
      continue;
    }

    strm.Printf("%" PRIu32 ":", alloc->id);
    strm.EOL();
    strm.IndentMore();

    strm.Indent("Context: ");
    if (!alloc->context.isValid())
      strm.Printf("unknown\n");
    else
      strm.Printf("0x%" PRIx64 "\n", *alloc->context.get());

    strm.Indent("Address: ");
    if (!alloc->address.isValid())
      strm.Printf("unknown\n");
    else
      strm.Printf("0x%" PRIx64 "\n", *alloc->address.get());

    strm.Indent("Data pointer: ");
    if (!alloc->data_ptr.isValid())
      strm.Printf("unknown\n");
    else
      strm.Printf("0x%" PRIx64 "\n", *alloc->data_ptr.get());

    strm.Indent("Dimensions: ");
    if (!alloc->dimension.isValid())
      strm.Printf("unknown\n");
    else
      strm.Printf("(%" PRId32 ", %" PRId32 ", %" PRId32 ")\n",
                  alloc->dimension.get()->dim_1, alloc->dimension.get()->dim_2,
                  alloc->dimension.get()->dim_3);

    strm.Indent("Data Type: ");
    if (!alloc->element.type.isValid() ||
        !alloc->element.type_vec_size.isValid())
      strm.Printf("unknown\n");
    else {
      const int vector_size = *alloc->element.type_vec_size.get();
      Element::DataType type = *alloc->element.type.get();

      if (!alloc->element.type_name.IsEmpty())
        strm.Printf("%s\n", alloc->element.type_name.AsCString());
      else {
        // Enum value isn't monotonous, so doesn't always index
        // RsDataTypeToString array
        if (type >= Element::RS_TYPE_ELEMENT && type <= Element::RS_TYPE_FONT)
          type =
              static_cast<Element::DataType>((type - Element::RS_TYPE_ELEMENT) +
                                             Element::RS_TYPE_MATRIX_2X2 + 1);

        if (type >= (sizeof(AllocationDetails::RsDataTypeToString) /
                     sizeof(AllocationDetails::RsDataTypeToString[0])) ||
            vector_size > 4 || vector_size < 1)
          strm.Printf("invalid type\n");
        else
          strm.Printf(
              "%s\n",
              AllocationDetails::RsDataTypeToString[static_cast<uint32_t>(type)]
                                                   [vector_size - 1]);
      }
    }

    strm.Indent("Data Kind: ");
    if (!alloc->element.type_kind.isValid())
      strm.Printf("unknown\n");
    else {
      const Element::DataKind kind = *alloc->element.type_kind.get();
      if (kind < Element::RS_KIND_USER || kind > Element::RS_KIND_PIXEL_YUV)
        strm.Printf("invalid kind\n");
      else
        strm.Printf(
            "%s\n",
            AllocationDetails::RsDataKindToString[static_cast<uint32_t>(kind)]);
    }

    strm.EOL();
    strm.IndentLess();
  }
  strm.IndentLess();
}

// Set breakpoints on every kernel found in RS module
void RenderScriptRuntime::BreakOnModuleKernels(
    const RSModuleDescriptorSP rsmodule_sp) {
  for (const auto &kernel : rsmodule_sp->m_kernels) {
    // Don't set breakpoint on 'root' kernel
    if (strcmp(kernel.m_name.AsCString(), "root") == 0)
      continue;

    CreateKernelBreakpoint(kernel.m_name);
  }
}

// Method is internally called by the 'kernel breakpoint all' command to enable
// or disable breaking on all kernels. When do_break is true we want to enable
// this functionality. When do_break is false we want to disable it.
void RenderScriptRuntime::SetBreakAllKernels(bool do_break, TargetSP target) {
  Log *log(
      GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));

  InitSearchFilter(target);

  // Set breakpoints on all the kernels
  if (do_break && !m_breakAllKernels) {
    m_breakAllKernels = true;

    for (const auto &module : m_rsmodules)
      BreakOnModuleKernels(module);

    LLDB_LOGF(log,
              "%s(True) - breakpoints set on all currently loaded kernels.",
              __FUNCTION__);
  } else if (!do_break &&
             m_breakAllKernels) // Breakpoints won't be set on any new kernels.
  {
    m_breakAllKernels = false;

    LLDB_LOGF(log, "%s(False) - breakpoints no longer automatically set.",
              __FUNCTION__);
  }
}

// Given the name of a kernel this function creates a breakpoint using our own
// breakpoint resolver, and returns the Breakpoint shared pointer.
BreakpointSP
RenderScriptRuntime::CreateKernelBreakpoint(ConstString name) {
  Log *log(
      GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));

  if (!m_filtersp) {
    LLDB_LOGF(log, "%s - error, no breakpoint search filter set.",
              __FUNCTION__);
    return nullptr;
  }

  BreakpointResolverSP resolver_sp(new RSBreakpointResolver(nullptr, name));
  Target &target = GetProcess()->GetTarget();
  BreakpointSP bp = target.CreateBreakpoint(
      m_filtersp, resolver_sp, false, false, false);

  // Give RS breakpoints a specific name, so the user can manipulate them as a
  // group.
  Status err;
  target.AddNameToBreakpoint(bp, "RenderScriptKernel", err);
  if (err.Fail() && log)
    LLDB_LOGF(log, "%s - error setting break name, '%s'.", __FUNCTION__,
              err.AsCString());

  return bp;
}

BreakpointSP
RenderScriptRuntime::CreateReductionBreakpoint(ConstString name,
                                               int kernel_types) {
  Log *log(
      GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));

  if (!m_filtersp) {
    LLDB_LOGF(log, "%s - error, no breakpoint search filter set.",
              __FUNCTION__);
    return nullptr;
  }

  BreakpointResolverSP resolver_sp(new RSReduceBreakpointResolver(
      nullptr, name, &m_rsmodules, kernel_types));
  Target &target = GetProcess()->GetTarget();
  BreakpointSP bp = target.CreateBreakpoint(
      m_filtersp, resolver_sp, false, false, false);

  // Give RS breakpoints a specific name, so the user can manipulate them as a
  // group.
  Status err;
  target.AddNameToBreakpoint(bp, "RenderScriptReduction", err);
  if (err.Fail() && log)
    LLDB_LOGF(log, "%s - error setting break name, '%s'.", __FUNCTION__,
              err.AsCString());

  return bp;
}

// Given an expression for a variable this function tries to calculate the
// variable's value. If this is possible it returns true and sets the uint64_t
// parameter to the variables unsigned value. Otherwise function returns false.
bool RenderScriptRuntime::GetFrameVarAsUnsigned(const StackFrameSP frame_sp,
                                                const char *var_name,
                                                uint64_t &val) {
  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE));
  Status err;
  VariableSP var_sp;

  // Find variable in stack frame
  ValueObjectSP value_sp(frame_sp->GetValueForVariableExpressionPath(
      var_name, eNoDynamicValues,
      StackFrame::eExpressionPathOptionCheckPtrVsMember |
          StackFrame::eExpressionPathOptionsAllowDirectIVarAccess,
      var_sp, err));
  if (!err.Success()) {
    LLDB_LOGF(log, "%s - error, couldn't find '%s' in frame", __FUNCTION__,
              var_name);
    return false;
  }

  // Find the uint32_t value for the variable
  bool success = false;
  val = value_sp->GetValueAsUnsigned(0, &success);
  if (!success) {
    LLDB_LOGF(log, "%s - error, couldn't parse '%s' as an uint32_t.",
              __FUNCTION__, var_name);
    return false;
  }

  return true;
}

// Function attempts to find the current coordinate of a kernel invocation by
// investigating the values of frame variables in the .expand function. These
// coordinates are returned via the coord array reference parameter. Returns
// true if the coordinates could be found, and false otherwise.
bool RenderScriptRuntime::GetKernelCoordinate(RSCoordinate &coord,
                                              Thread *thread_ptr) {
  static const char *const x_expr = "rsIndex";
  static const char *const y_expr = "p->current.y";
  static const char *const z_expr = "p->current.z";

  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE));

  if (!thread_ptr) {
    LLDB_LOGF(log, "%s - Error, No thread pointer", __FUNCTION__);

    return false;
  }

  // Walk the call stack looking for a function whose name has the suffix
  // '.expand' and contains the variables we're looking for.
  for (uint32_t i = 0; i < thread_ptr->GetStackFrameCount(); ++i) {
    if (!thread_ptr->SetSelectedFrameByIndex(i))
      continue;

    StackFrameSP frame_sp = thread_ptr->GetSelectedFrame();
    if (!frame_sp)
      continue;

    // Find the function name
    const SymbolContext sym_ctx =
        frame_sp->GetSymbolContext(eSymbolContextFunction);
    const ConstString func_name = sym_ctx.GetFunctionName();
    if (!func_name)
      continue;

    LLDB_LOGF(log, "%s - Inspecting function '%s'", __FUNCTION__,
              func_name.GetCString());

    // Check if function name has .expand suffix
    if (!func_name.GetStringRef().endswith(".expand"))
      continue;

    LLDB_LOGF(log, "%s - Found .expand function '%s'", __FUNCTION__,
              func_name.GetCString());

    // Get values for variables in .expand frame that tell us the current
    // kernel invocation
    uint64_t x, y, z;
    bool found = GetFrameVarAsUnsigned(frame_sp, x_expr, x) &&
                 GetFrameVarAsUnsigned(frame_sp, y_expr, y) &&
                 GetFrameVarAsUnsigned(frame_sp, z_expr, z);

    if (found) {
      // The RenderScript runtime uses uint32_t for these vars. If they're not
      // within bounds, our frame parsing is garbage
      assert(x <= UINT32_MAX && y <= UINT32_MAX && z <= UINT32_MAX);
      coord.x = (uint32_t)x;
      coord.y = (uint32_t)y;
      coord.z = (uint32_t)z;
      return true;
    }
  }
  return false;
}

// Callback when a kernel breakpoint hits and we're looking for a specific
// coordinate. Baton parameter contains a pointer to the target coordinate we
// want to break on. Function then checks the .expand frame for the current
// coordinate and breaks to user if it matches. Parameter 'break_id' is the id
// of the Breakpoint which made the callback. Parameter 'break_loc_id' is the
// id for the BreakpointLocation which was hit, a single logical breakpoint can
// have multiple addresses.
bool RenderScriptRuntime::KernelBreakpointHit(void *baton,
                                              StoppointCallbackContext *ctx,
                                              user_id_t break_id,
                                              user_id_t break_loc_id) {
  Log *log(
      GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));

  assert(baton &&
         "Error: null baton in conditional kernel breakpoint callback");

  // Coordinate we want to stop on
  RSCoordinate target_coord = *static_cast<RSCoordinate *>(baton);

  LLDB_LOGF(log, "%s - Break ID %" PRIu64 ", " FMT_COORD, __FUNCTION__,
            break_id, target_coord.x, target_coord.y, target_coord.z);

  // Select current thread
  ExecutionContext context(ctx->exe_ctx_ref);
  Thread *thread_ptr = context.GetThreadPtr();
  assert(thread_ptr && "Null thread pointer");

  // Find current kernel invocation from .expand frame variables
  RSCoordinate current_coord{};
  if (!GetKernelCoordinate(current_coord, thread_ptr)) {
    LLDB_LOGF(log, "%s - Error, couldn't select .expand stack frame",
              __FUNCTION__);
    return false;
  }

  LLDB_LOGF(log, "%s - " FMT_COORD, __FUNCTION__, current_coord.x,
            current_coord.y, current_coord.z);

  // Check if the current kernel invocation coordinate matches our target
  // coordinate
  if (target_coord == current_coord) {
    LLDB_LOGF(log, "%s, BREAKING " FMT_COORD, __FUNCTION__, current_coord.x,
              current_coord.y, current_coord.z);

    BreakpointSP breakpoint_sp =
        context.GetTargetPtr()->GetBreakpointByID(break_id);
    assert(breakpoint_sp != nullptr &&
           "Error: Couldn't find breakpoint matching break id for callback");
    breakpoint_sp->SetEnabled(false); // Optimise since conditional breakpoint
                                      // should only be hit once.
    return true;
  }

  // No match on coordinate
  return false;
}

void RenderScriptRuntime::SetConditional(BreakpointSP bp, Stream &messages,
                                         const RSCoordinate &coord) {
  messages.Printf("Conditional kernel breakpoint on coordinate " FMT_COORD,
                  coord.x, coord.y, coord.z);
  messages.EOL();

  // Allocate memory for the baton, and copy over coordinate
  RSCoordinate *baton = new RSCoordinate(coord);

  // Create a callback that will be invoked every time the breakpoint is hit.
  // The baton object passed to the handler is the target coordinate we want to
  // break on.
  bp->SetCallback(KernelBreakpointHit, baton, true);

  // Store a shared pointer to the baton, so the memory will eventually be
  // cleaned up after destruction
  m_conditional_breaks[bp->GetID()] = std::unique_ptr<RSCoordinate>(baton);
}

// Tries to set a breakpoint on the start of a kernel, resolved using the
// kernel name. Argument 'coords', represents a three dimensional coordinate
// which can be used to specify a single kernel instance to break on. If this
// is set then we add a callback to the breakpoint.
bool RenderScriptRuntime::PlaceBreakpointOnKernel(TargetSP target,
                                                  Stream &messages,
                                                  const char *name,
                                                  const RSCoordinate *coord) {
  if (!name)
    return false;

  InitSearchFilter(target);

  ConstString kernel_name(name);
  BreakpointSP bp = CreateKernelBreakpoint(kernel_name);
  if (!bp)
    return false;

  // We have a conditional breakpoint on a specific coordinate
  if (coord)
    SetConditional(bp, messages, *coord);

  bp->GetDescription(&messages, lldb::eDescriptionLevelInitial, false);

  return true;
}

BreakpointSP
RenderScriptRuntime::CreateScriptGroupBreakpoint(ConstString name,
                                                 bool stop_on_all) {
  Log *log(
      GetLogIfAnyCategoriesSet(LIBLLDB_LOG_LANGUAGE | LIBLLDB_LOG_BREAKPOINTS));

  if (!m_filtersp) {
    LLDB_LOGF(log, "%s - error, no breakpoint search filter set.",
              __FUNCTION__);
    return nullptr;
  }

  BreakpointResolverSP resolver_sp(new RSScriptGroupBreakpointResolver(
      nullptr, name, m_scriptGroups, stop_on_all));
  Target &target = GetProcess()->GetTarget();
  BreakpointSP bp = target.CreateBreakpoint(
      m_filtersp, resolver_sp, false, false, false);
  // Give RS breakpoints a specific name, so the user can manipulate them as a
  // group.
  Status err;
  target.AddNameToBreakpoint(bp, name.GetCString(), err);
  if (err.Fail() && log)
    LLDB_LOGF(log, "%s - error setting break name, '%s'.", __FUNCTION__,
              err.AsCString());
  // ask the breakpoint to resolve itself
  bp->ResolveBreakpoint();
  return bp;
}

bool RenderScriptRuntime::PlaceBreakpointOnScriptGroup(TargetSP target,
                                                       Stream &strm,
                                                       ConstString name,
                                                       bool multi) {
  InitSearchFilter(target);
  BreakpointSP bp = CreateScriptGroupBreakpoint(name, multi);
  if (bp)
    bp->GetDescription(&strm, lldb::eDescriptionLevelInitial, false);
  return bool(bp);
}

bool RenderScriptRuntime::PlaceBreakpointOnReduction(TargetSP target,
                                                     Stream &messages,
                                                     const char *reduce_name,
                                                     const RSCoordinate *coord,
                                                     int kernel_types) {
  if (!reduce_name)
    return false;

  InitSearchFilter(target);
  BreakpointSP bp =
      CreateReductionBreakpoint(ConstString(reduce_name), kernel_types);
  if (!bp)
    return false;

  if (coord)
    SetConditional(bp, messages, *coord);

  bp->GetDescription(&messages, lldb::eDescriptionLevelInitial, false);

  return true;
}

void RenderScriptRuntime::DumpModules(Stream &strm) const {
  strm.Printf("RenderScript Modules:");
  strm.EOL();
  strm.IndentMore();
  for (const auto &module : m_rsmodules) {
    module->Dump(strm);
  }
  strm.IndentLess();
}

RenderScriptRuntime::ScriptDetails *
RenderScriptRuntime::LookUpScript(addr_t address, bool create) {
  for (const auto &s : m_scripts) {
    if (s->script.isValid())
      if (*s->script == address)
        return s.get();
  }
  if (create) {
    std::unique_ptr<ScriptDetails> s(new ScriptDetails);
    s->script = address;
    m_scripts.push_back(std::move(s));
    return m_scripts.back().get();
  }
  return nullptr;
}

RenderScriptRuntime::AllocationDetails *
RenderScriptRuntime::LookUpAllocation(addr_t address) {
  for (const auto &a : m_allocations) {
    if (a->address.isValid())
      if (*a->address == address)
        return a.get();
  }
  return nullptr;
}

RenderScriptRuntime::AllocationDetails *
RenderScriptRuntime::CreateAllocation(addr_t address) {
  Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_LANGUAGE);

  // Remove any previous allocation which contains the same address
  auto it = m_allocations.begin();
  while (it != m_allocations.end()) {
    if (*((*it)->address) == address) {
      LLDB_LOGF(log, "%s - Removing allocation id: %d, address: 0x%" PRIx64,
                __FUNCTION__, (*it)->id, address);

      it = m_allocations.erase(it);
    } else {
      it++;
    }
  }

  std::unique_ptr<AllocationDetails> a(new AllocationDetails);
  a->address = address;
  m_allocations.push_back(std::move(a));
  return m_allocations.back().get();
}

bool RenderScriptRuntime::ResolveKernelName(lldb::addr_t kernel_addr,
                                            ConstString &name) {
  Log *log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYMBOLS);

  Target &target = GetProcess()->GetTarget();
  Address resolved;
  // RenderScript module
  if (!target.GetSectionLoadList().ResolveLoadAddress(kernel_addr, resolved)) {
    LLDB_LOGF(log, "%s: unable to resolve 0x%" PRIx64 " to a loaded symbol",
              __FUNCTION__, kernel_addr);
    return false;
  }

  Symbol *sym = resolved.CalculateSymbolContextSymbol();
  if (!sym)
    return false;

  name = sym->GetName();
  assert(IsRenderScriptModule(resolved.CalculateSymbolContextModule()));
  LLDB_LOGF(log, "%s: 0x%" PRIx64 " resolved to the symbol '%s'", __FUNCTION__,
            kernel_addr, name.GetCString());
  return true;
}

void RSModuleDescriptor::Dump(Stream &strm) const {
  int indent = strm.GetIndentLevel();

  strm.Indent();
  m_module->GetFileSpec().Dump(strm.AsRawOstream());
  strm.Indent(m_module->GetNumCompileUnits() ? "Debug info loaded."
                                             : "Debug info does not exist.");
  strm.EOL();
  strm.IndentMore();

  strm.Indent();
  strm.Printf("Globals: %" PRIu64, static_cast<uint64_t>(m_globals.size()));
  strm.EOL();
  strm.IndentMore();
  for (const auto &global : m_globals) {
    global.Dump(strm);
  }
  strm.IndentLess();

  strm.Indent();
  strm.Printf("Kernels: %" PRIu64, static_cast<uint64_t>(m_kernels.size()));
  strm.EOL();
  strm.IndentMore();
  for (const auto &kernel : m_kernels) {
    kernel.Dump(strm);
  }
  strm.IndentLess();

  strm.Indent();
  strm.Printf("Pragmas: %" PRIu64, static_cast<uint64_t>(m_pragmas.size()));
  strm.EOL();
  strm.IndentMore();
  for (const auto &key_val : m_pragmas) {
    strm.Indent();
    strm.Printf("%s: %s", key_val.first.c_str(), key_val.second.c_str());
    strm.EOL();
  }
  strm.IndentLess();

  strm.Indent();
  strm.Printf("Reductions: %" PRIu64,
              static_cast<uint64_t>(m_reductions.size()));
  strm.EOL();
  strm.IndentMore();
  for (const auto &reduction : m_reductions) {
    reduction.Dump(strm);
  }

  strm.SetIndentLevel(indent);
}

void RSGlobalDescriptor::Dump(Stream &strm) const {
  strm.Indent(m_name.GetStringRef());
  VariableList var_list;
  m_module->m_module->FindGlobalVariables(m_name, CompilerDeclContext(), 1U,
                                          var_list);
  if (var_list.GetSize() == 1) {
    auto var = var_list.GetVariableAtIndex(0);
    auto type = var->GetType();
    if (type) {
      strm.Printf(" - ");
      type->DumpTypeName(&strm);
    } else {
      strm.Printf(" - Unknown Type");
    }
  } else {
    strm.Printf(" - variable identified, but not found in binary");
    const Symbol *s = m_module->m_module->FindFirstSymbolWithNameAndType(
        m_name, eSymbolTypeData);
    if (s) {
      strm.Printf(" (symbol exists) ");
    }
  }

  strm.EOL();
}

void RSKernelDescriptor::Dump(Stream &strm) const {
  strm.Indent(m_name.GetStringRef());
  strm.EOL();
}

void RSReductionDescriptor::Dump(lldb_private::Stream &stream) const {
  stream.Indent(m_reduce_name.GetStringRef());
  stream.IndentMore();
  stream.EOL();
  stream.Indent();
  stream.Printf("accumulator: %s", m_accum_name.AsCString());
  stream.EOL();
  stream.Indent();
  stream.Printf("initializer: %s", m_init_name.AsCString());
  stream.EOL();
  stream.Indent();
  stream.Printf("combiner: %s", m_comb_name.AsCString());
  stream.EOL();
  stream.Indent();
  stream.Printf("outconverter: %s", m_outc_name.AsCString());
  stream.EOL();
  // XXX This is currently unspecified by RenderScript, and unused
  // stream.Indent();
  // stream.Printf("halter: '%s'", m_init_name.AsCString());
  // stream.EOL();
  stream.IndentLess();
}

class CommandObjectRenderScriptRuntimeModuleDump : public CommandObjectParsed {
public:
  CommandObjectRenderScriptRuntimeModuleDump(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "renderscript module dump",
            "Dumps renderscript specific information for all modules.",
            "renderscript module dump",
            eCommandRequiresProcess | eCommandProcessMustBeLaunched) {}

  ~CommandObjectRenderScriptRuntimeModuleDump() override = default;

  bool DoExecute(Args &command, CommandReturnObject &result) override {
    RenderScriptRuntime *runtime = llvm::cast<RenderScriptRuntime>(
        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
            eLanguageTypeExtRenderScript));
    runtime->DumpModules(result.GetOutputStream());
    result.SetStatus(eReturnStatusSuccessFinishResult);
    return true;
  }
};

class CommandObjectRenderScriptRuntimeModule : public CommandObjectMultiword {
public:
  CommandObjectRenderScriptRuntimeModule(CommandInterpreter &interpreter)
      : CommandObjectMultiword(interpreter, "renderscript module",
                               "Commands that deal with RenderScript modules.",
                               nullptr) {
    LoadSubCommand(
        "dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeModuleDump(
                    interpreter)));
  }

  ~CommandObjectRenderScriptRuntimeModule() override = default;
};

class CommandObjectRenderScriptRuntimeKernelList : public CommandObjectParsed {
public:
  CommandObjectRenderScriptRuntimeKernelList(CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "renderscript kernel list",
            "Lists renderscript kernel names and associated script resources.",
            "renderscript kernel list",
            eCommandRequiresProcess | eCommandProcessMustBeLaunched) {}

  ~CommandObjectRenderScriptRuntimeKernelList() override = default;

  bool DoExecute(Args &command, CommandReturnObject &result) override {
    RenderScriptRuntime *runtime = llvm::cast<RenderScriptRuntime>(
        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
            eLanguageTypeExtRenderScript));
    runtime->DumpKernels(result.GetOutputStream());
    result.SetStatus(eReturnStatusSuccessFinishResult);
    return true;
  }
};

static constexpr OptionDefinition g_renderscript_reduction_bp_set_options[] = {
    {LLDB_OPT_SET_1, false, "function-role", 't',
     OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOneLiner,
     "Break on a comma separated set of reduction kernel types "
     "(accumulator,outcoverter,combiner,initializer"},
    {LLDB_OPT_SET_1, false, "coordinate", 'c', OptionParser::eRequiredArgument,
     nullptr, {}, 0, eArgTypeValue,
     "Set a breakpoint on a single invocation of the kernel with specified "
     "coordinate.\n"
     "Coordinate takes the form 'x[,y][,z] where x,y,z are positive "
     "integers representing kernel dimensions. "
     "Any unset dimensions will be defaulted to zero."}};

class CommandObjectRenderScriptRuntimeReductionBreakpointSet
    : public CommandObjectParsed {
public:
  CommandObjectRenderScriptRuntimeReductionBreakpointSet(
      CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "renderscript reduction breakpoint set",
            "Set a breakpoint on named RenderScript general reductions",
            "renderscript reduction breakpoint set  <kernel_name> [-t "
            "<reduction_kernel_type,...>]",
            eCommandRequiresProcess | eCommandProcessMustBeLaunched |
                eCommandProcessMustBePaused),
        m_options(){};

  class CommandOptions : public Options {
  public:
    CommandOptions() : Options() {}

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *exe_ctx) override {
      Status err;
      StreamString err_str;
      const int short_option = m_getopt_table[option_idx].val;
      switch (short_option) {
      case 't':
        if (!ParseReductionTypes(option_arg, err_str))
          err.SetErrorStringWithFormat(
              "Unable to deduce reduction types for %s: %s",
              option_arg.str().c_str(), err_str.GetData());
        break;
      case 'c': {
        auto coord = RSCoordinate{};
        if (!ParseCoordinate(option_arg, coord))
          err.SetErrorStringWithFormat("unable to parse coordinate for %s",
                                       option_arg.str().c_str());
        else {
          m_have_coord = true;
          m_coord = coord;
        }
        break;
      }
      default:
        err.SetErrorStringWithFormat("Invalid option '-%c'", short_option);
      }
      return err;
    }

    void OptionParsingStarting(ExecutionContext *exe_ctx) override {
      m_have_coord = false;
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::makeArrayRef(g_renderscript_reduction_bp_set_options);
    }

    bool ParseReductionTypes(llvm::StringRef option_val,
                             StreamString &err_str) {
      m_kernel_types = RSReduceBreakpointResolver::eKernelTypeNone;
      const auto reduce_name_to_type = [](llvm::StringRef name) -> int {
        return llvm::StringSwitch<int>(name)
            .Case("accumulator", RSReduceBreakpointResolver::eKernelTypeAccum)
            .Case("initializer", RSReduceBreakpointResolver::eKernelTypeInit)
            .Case("outconverter", RSReduceBreakpointResolver::eKernelTypeOutC)
            .Case("combiner", RSReduceBreakpointResolver::eKernelTypeComb)
            .Case("all", RSReduceBreakpointResolver::eKernelTypeAll)
            // Currently not exposed by the runtime
            // .Case("halter", RSReduceBreakpointResolver::eKernelTypeHalter)
            .Default(0);
      };

      // Matching a comma separated list of known words is fairly
      // straightforward with PCRE, but we're using ERE, so we end up with a
      // little ugliness...
      RegularExpression match_type_list(
          llvm::StringRef("^([[:alpha:]]+)(,[[:alpha:]]+){0,4}$"));

      assert(match_type_list.IsValid());

      if (!match_type_list.Execute(option_val)) {
        err_str.PutCString(
            "a comma-separated list of kernel types is required");
        return false;
      }

      // splitting on commas is much easier with llvm::StringRef than regex
      llvm::SmallVector<llvm::StringRef, 5> type_names;
      llvm::StringRef(option_val).split(type_names, ',');

      for (const auto &name : type_names) {
        const int type = reduce_name_to_type(name);
        if (!type) {
          err_str.Printf("unknown kernel type name %s", name.str().c_str());
          return false;
        }
        m_kernel_types |= type;
      }

      return true;
    }

    int m_kernel_types = RSReduceBreakpointResolver::eKernelTypeAll;
    llvm::StringRef m_reduce_name;
    RSCoordinate m_coord;
    bool m_have_coord;
  };

  Options *GetOptions() override { return &m_options; }

  bool DoExecute(Args &command, CommandReturnObject &result) override {
    const size_t argc = command.GetArgumentCount();
    if (argc < 1) {
      result.AppendErrorWithFormat("'%s' takes 1 argument of reduction name, "
                                   "and an optional kernel type list",
                                   m_cmd_name.c_str());
      return false;
    }

    RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
            eLanguageTypeExtRenderScript));

    auto &outstream = result.GetOutputStream();
    auto name = command.GetArgumentAtIndex(0);
    auto &target = m_exe_ctx.GetTargetSP();
    auto coord = m_options.m_have_coord ? &m_options.m_coord : nullptr;
    if (!runtime->PlaceBreakpointOnReduction(target, outstream, name, coord,
                                             m_options.m_kernel_types)) {
      result.AppendError("Error: unable to place breakpoint on reduction");
      return false;
    }
    result.AppendMessage("Breakpoint(s) created");
    result.SetStatus(eReturnStatusSuccessFinishResult);
    return true;
  }

private:
  CommandOptions m_options;
};

static constexpr OptionDefinition g_renderscript_kernel_bp_set_options[] = {
    {LLDB_OPT_SET_1, false, "coordinate", 'c', OptionParser::eRequiredArgument,
     nullptr, {}, 0, eArgTypeValue,
     "Set a breakpoint on a single invocation of the kernel with specified "
     "coordinate.\n"
     "Coordinate takes the form 'x[,y][,z] where x,y,z are positive "
     "integers representing kernel dimensions. "
     "Any unset dimensions will be defaulted to zero."}};

class CommandObjectRenderScriptRuntimeKernelBreakpointSet
    : public CommandObjectParsed {
public:
  CommandObjectRenderScriptRuntimeKernelBreakpointSet(
      CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "renderscript kernel breakpoint set",
            "Sets a breakpoint on a renderscript kernel.",
            "renderscript kernel breakpoint set <kernel_name> [-c x,y,z]",
            eCommandRequiresProcess | eCommandProcessMustBeLaunched |
                eCommandProcessMustBePaused),
        m_options() {}

  ~CommandObjectRenderScriptRuntimeKernelBreakpointSet() override = default;

  Options *GetOptions() override { return &m_options; }

  class CommandOptions : public Options {
  public:
    CommandOptions() : Options() {}

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *exe_ctx) override {
      Status err;
      const int short_option = m_getopt_table[option_idx].val;

      switch (short_option) {
      case 'c': {
        auto coord = RSCoordinate{};
        if (!ParseCoordinate(option_arg, coord))
          err.SetErrorStringWithFormat(
              "Couldn't parse coordinate '%s', should be in format 'x,y,z'.",
              option_arg.str().c_str());
        else {
          m_have_coord = true;
          m_coord = coord;
        }
        break;
      }
      default:
        err.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
        break;
      }
      return err;
    }

    void OptionParsingStarting(ExecutionContext *exe_ctx) override {
      m_have_coord = false;
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::makeArrayRef(g_renderscript_kernel_bp_set_options);
    }

    RSCoordinate m_coord;
    bool m_have_coord;
  };

  bool DoExecute(Args &command, CommandReturnObject &result) override {
    const size_t argc = command.GetArgumentCount();
    if (argc < 1) {
      result.AppendErrorWithFormat(
          "'%s' takes 1 argument of kernel name, and an optional coordinate.",
          m_cmd_name.c_str());
      return false;
    }

    RenderScriptRuntime *runtime = llvm::cast<RenderScriptRuntime>(
        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
            eLanguageTypeExtRenderScript));

    auto &outstream = result.GetOutputStream();
    auto &target = m_exe_ctx.GetTargetSP();
    auto name = command.GetArgumentAtIndex(0);
    auto coord = m_options.m_have_coord ? &m_options.m_coord : nullptr;
    if (!runtime->PlaceBreakpointOnKernel(target, outstream, name, coord)) {
      result.AppendErrorWithFormat(
          "Error: unable to set breakpoint on kernel '%s'", name);
      return false;
    }

    result.AppendMessage("Breakpoint(s) created");
    result.SetStatus(eReturnStatusSuccessFinishResult);
    return true;
  }

private:
  CommandOptions m_options;
};

class CommandObjectRenderScriptRuntimeKernelBreakpointAll
    : public CommandObjectParsed {
public:
  CommandObjectRenderScriptRuntimeKernelBreakpointAll(
      CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "renderscript kernel breakpoint all",
            "Automatically sets a breakpoint on all renderscript kernels that "
            "are or will be loaded.\n"
            "Disabling option means breakpoints will no longer be set on any "
            "kernels loaded in the future, "
            "but does not remove currently set breakpoints.",
            "renderscript kernel breakpoint all <enable/disable>",
            eCommandRequiresProcess | eCommandProcessMustBeLaunched |
                eCommandProcessMustBePaused) {}

  ~CommandObjectRenderScriptRuntimeKernelBreakpointAll() override = default;

  bool DoExecute(Args &command, CommandReturnObject &result) override {
    const size_t argc = command.GetArgumentCount();
    if (argc != 1) {
      result.AppendErrorWithFormat(
          "'%s' takes 1 argument of 'enable' or 'disable'", m_cmd_name.c_str());
      return false;
    }

    RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
            eLanguageTypeExtRenderScript));

    bool do_break = false;
    const char *argument = command.GetArgumentAtIndex(0);
    if (strcmp(argument, "enable") == 0) {
      do_break = true;
      result.AppendMessage("Breakpoints will be set on all kernels.");
    } else if (strcmp(argument, "disable") == 0) {
      do_break = false;
      result.AppendMessage("Breakpoints will not be set on any new kernels.");
    } else {
      result.AppendErrorWithFormat(
          "Argument must be either 'enable' or 'disable'");
      return false;
    }

    runtime->SetBreakAllKernels(do_break, m_exe_ctx.GetTargetSP());

    result.SetStatus(eReturnStatusSuccessFinishResult);
    return true;
  }
};

class CommandObjectRenderScriptRuntimeReductionBreakpoint
    : public CommandObjectMultiword {
public:
  CommandObjectRenderScriptRuntimeReductionBreakpoint(
      CommandInterpreter &interpreter)
      : CommandObjectMultiword(interpreter, "renderscript reduction breakpoint",
                               "Commands that manipulate breakpoints on "
                               "renderscript general reductions.",
                               nullptr) {
    LoadSubCommand(
        "set", CommandObjectSP(
                   new CommandObjectRenderScriptRuntimeReductionBreakpointSet(
                       interpreter)));
  }

  ~CommandObjectRenderScriptRuntimeReductionBreakpoint() override = default;
};

class CommandObjectRenderScriptRuntimeKernelCoordinate
    : public CommandObjectParsed {
public:
  CommandObjectRenderScriptRuntimeKernelCoordinate(
      CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "renderscript kernel coordinate",
            "Shows the (x,y,z) coordinate of the current kernel invocation.",
            "renderscript kernel coordinate",
            eCommandRequiresProcess | eCommandProcessMustBeLaunched |
                eCommandProcessMustBePaused) {}

  ~CommandObjectRenderScriptRuntimeKernelCoordinate() override = default;

  bool DoExecute(Args &command, CommandReturnObject &result) override {
    RSCoordinate coord{};
    bool success = RenderScriptRuntime::GetKernelCoordinate(
        coord, m_exe_ctx.GetThreadPtr());
    Stream &stream = result.GetOutputStream();

    if (success) {
      stream.Printf("Coordinate: " FMT_COORD, coord.x, coord.y, coord.z);
      stream.EOL();
      result.SetStatus(eReturnStatusSuccessFinishResult);
    } else {
      stream.Printf("Error: Coordinate could not be found.");
      stream.EOL();
      result.SetStatus(eReturnStatusFailed);
    }
    return true;
  }
};

class CommandObjectRenderScriptRuntimeKernelBreakpoint
    : public CommandObjectMultiword {
public:
  CommandObjectRenderScriptRuntimeKernelBreakpoint(
      CommandInterpreter &interpreter)
      : CommandObjectMultiword(
            interpreter, "renderscript kernel",
            "Commands that generate breakpoints on renderscript kernels.",
            nullptr) {
    LoadSubCommand(
        "set",
        CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointSet(
            interpreter)));
    LoadSubCommand(
        "all",
        CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelBreakpointAll(
            interpreter)));
  }

  ~CommandObjectRenderScriptRuntimeKernelBreakpoint() override = default;
};

class CommandObjectRenderScriptRuntimeKernel : public CommandObjectMultiword {
public:
  CommandObjectRenderScriptRuntimeKernel(CommandInterpreter &interpreter)
      : CommandObjectMultiword(interpreter, "renderscript kernel",
                               "Commands that deal with RenderScript kernels.",
                               nullptr) {
    LoadSubCommand(
        "list", CommandObjectSP(new CommandObjectRenderScriptRuntimeKernelList(
                    interpreter)));
    LoadSubCommand(
        "coordinate",
        CommandObjectSP(
            new CommandObjectRenderScriptRuntimeKernelCoordinate(interpreter)));
    LoadSubCommand(
        "breakpoint",
        CommandObjectSP(
            new CommandObjectRenderScriptRuntimeKernelBreakpoint(interpreter)));
  }

  ~CommandObjectRenderScriptRuntimeKernel() override = default;
};

class CommandObjectRenderScriptRuntimeContextDump : public CommandObjectParsed {
public:
  CommandObjectRenderScriptRuntimeContextDump(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "renderscript context dump",
                            "Dumps renderscript context information.",
                            "renderscript context dump",
                            eCommandRequiresProcess |
                                eCommandProcessMustBeLaunched) {}

  ~CommandObjectRenderScriptRuntimeContextDump() override = default;

  bool DoExecute(Args &command, CommandReturnObject &result) override {
    RenderScriptRuntime *runtime = llvm::cast<RenderScriptRuntime>(
        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
            eLanguageTypeExtRenderScript));
    runtime->DumpContexts(result.GetOutputStream());
    result.SetStatus(eReturnStatusSuccessFinishResult);
    return true;
  }
};

static constexpr OptionDefinition g_renderscript_runtime_alloc_dump_options[] = {
    {LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument,
     nullptr, {}, 0, eArgTypeFilename,
     "Print results to specified file instead of command line."}};

class CommandObjectRenderScriptRuntimeContext : public CommandObjectMultiword {
public:
  CommandObjectRenderScriptRuntimeContext(CommandInterpreter &interpreter)
      : CommandObjectMultiword(interpreter, "renderscript context",
                               "Commands that deal with RenderScript contexts.",
                               nullptr) {
    LoadSubCommand(
        "dump", CommandObjectSP(new CommandObjectRenderScriptRuntimeContextDump(
                    interpreter)));
  }

  ~CommandObjectRenderScriptRuntimeContext() override = default;
};

class CommandObjectRenderScriptRuntimeAllocationDump
    : public CommandObjectParsed {
public:
  CommandObjectRenderScriptRuntimeAllocationDump(
      CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "renderscript allocation dump",
                            "Displays the contents of a particular allocation",
                            "renderscript allocation dump <ID>",
                            eCommandRequiresProcess |
                                eCommandProcessMustBeLaunched),
        m_options() {}

  ~CommandObjectRenderScriptRuntimeAllocationDump() override = default;

  Options *GetOptions() override { return &m_options; }

  class CommandOptions : public Options {
  public:
    CommandOptions() : Options() {}

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *exe_ctx) override {
      Status err;
      const int short_option = m_getopt_table[option_idx].val;

      switch (short_option) {
      case 'f':
        m_outfile.SetFile(option_arg, FileSpec::Style::native);
        FileSystem::Instance().Resolve(m_outfile);
        if (FileSystem::Instance().Exists(m_outfile)) {
          m_outfile.Clear();
          err.SetErrorStringWithFormat("file already exists: '%s'",
                                       option_arg.str().c_str());
        }
        break;
      default:
        err.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
        break;
      }
      return err;
    }

    void OptionParsingStarting(ExecutionContext *exe_ctx) override {
      m_outfile.Clear();
    }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::makeArrayRef(g_renderscript_runtime_alloc_dump_options);
    }

    FileSpec m_outfile;
  };

  bool DoExecute(Args &command, CommandReturnObject &result) override {
    const size_t argc = command.GetArgumentCount();
    if (argc < 1) {
      result.AppendErrorWithFormat("'%s' takes 1 argument, an allocation ID. "
                                   "As well as an optional -f argument",
                                   m_cmd_name.c_str());
      return false;
    }

    RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
            eLanguageTypeExtRenderScript));

    const char *id_cstr = command.GetArgumentAtIndex(0);
    uint32_t id;
    if (!llvm::to_integer(id_cstr, id)) {
      result.AppendErrorWithFormat("invalid allocation id argument '%s'",
                                   id_cstr);
      return false;
    }

    Stream *output_stream_p = nullptr;
    std::unique_ptr<Stream> output_stream_storage;

    const FileSpec &outfile_spec =
        m_options.m_outfile; // Dump allocation to file instead
    if (outfile_spec) {
      // Open output file
      std::string path = outfile_spec.GetPath();
      auto file = FileSystem::Instance().Open(outfile_spec,
                                              File::eOpenOptionWriteOnly |
                                                  File::eOpenOptionCanCreate);
      if (file) {
        output_stream_storage =
            std::make_unique<StreamFile>(std::move(file.get()));
        output_stream_p = output_stream_storage.get();
        result.GetOutputStream().Printf("Results written to '%s'",
                                        path.c_str());
        result.GetOutputStream().EOL();
      } else {
        std::string error = llvm::toString(file.takeError());
        result.AppendErrorWithFormat("Couldn't open file '%s': %s",
                                     path.c_str(), error.c_str());
        return false;
      }
    } else
      output_stream_p = &result.GetOutputStream();

    assert(output_stream_p != nullptr);
    bool dumped =
        runtime->DumpAllocation(*output_stream_p, m_exe_ctx.GetFramePtr(), id);

    if (dumped)
      result.SetStatus(eReturnStatusSuccessFinishResult);
    else
      result.SetStatus(eReturnStatusFailed);

    return true;
  }

private:
  CommandOptions m_options;
};

static constexpr OptionDefinition g_renderscript_runtime_alloc_list_options[] = {
    {LLDB_OPT_SET_1, false, "id", 'i', OptionParser::eRequiredArgument, nullptr,
     {}, 0, eArgTypeIndex,
     "Only show details of a single allocation with specified id."}};

class CommandObjectRenderScriptRuntimeAllocationList
    : public CommandObjectParsed {
public:
  CommandObjectRenderScriptRuntimeAllocationList(
      CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "renderscript allocation list",
            "List renderscript allocations and their information.",
            "renderscript allocation list",
            eCommandRequiresProcess | eCommandProcessMustBeLaunched),
        m_options() {}

  ~CommandObjectRenderScriptRuntimeAllocationList() override = default;

  Options *GetOptions() override { return &m_options; }

  class CommandOptions : public Options {
  public:
    CommandOptions() : Options() {}

    ~CommandOptions() override = default;

    Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
                          ExecutionContext *exe_ctx) override {
      Status err;
      const int short_option = m_getopt_table[option_idx].val;

      switch (short_option) {
      case 'i':
        if (option_arg.getAsInteger(0, m_id))
          err.SetErrorStringWithFormat("invalid integer value for option '%c'",
                                       short_option);
        break;
      default:
        err.SetErrorStringWithFormat("unrecognized option '%c'", short_option);
        break;
      }
      return err;
    }

    void OptionParsingStarting(ExecutionContext *exe_ctx) override { m_id = 0; }

    llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
      return llvm::makeArrayRef(g_renderscript_runtime_alloc_list_options);
    }

    uint32_t m_id = 0;
  };

  bool DoExecute(Args &command, CommandReturnObject &result) override {
    RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
            eLanguageTypeExtRenderScript));
    runtime->ListAllocations(result.GetOutputStream(), m_exe_ctx.GetFramePtr(),
                             m_options.m_id);
    result.SetStatus(eReturnStatusSuccessFinishResult);
    return true;
  }

private:
  CommandOptions m_options;
};

class CommandObjectRenderScriptRuntimeAllocationLoad
    : public CommandObjectParsed {
public:
  CommandObjectRenderScriptRuntimeAllocationLoad(
      CommandInterpreter &interpreter)
      : CommandObjectParsed(
            interpreter, "renderscript allocation load",
            "Loads renderscript allocation contents from a file.",
            "renderscript allocation load <ID> <filename>",
            eCommandRequiresProcess | eCommandProcessMustBeLaunched) {}

  ~CommandObjectRenderScriptRuntimeAllocationLoad() override = default;

  bool DoExecute(Args &command, CommandReturnObject &result) override {
    const size_t argc = command.GetArgumentCount();
    if (argc != 2) {
      result.AppendErrorWithFormat(
          "'%s' takes 2 arguments, an allocation ID and filename to read from.",
          m_cmd_name.c_str());
      return false;
    }

    RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
            eLanguageTypeExtRenderScript));

    const char *id_cstr = command.GetArgumentAtIndex(0);
    uint32_t id;
    if (!llvm::to_integer(id_cstr, id)) {
      result.AppendErrorWithFormat("invalid allocation id argument '%s'",
                                   id_cstr);
      return false;
    }

    const char *path = command.GetArgumentAtIndex(1);
    bool loaded = runtime->LoadAllocation(result.GetOutputStream(), id, path,
                                          m_exe_ctx.GetFramePtr());

    if (loaded)
      result.SetStatus(eReturnStatusSuccessFinishResult);
    else
      result.SetStatus(eReturnStatusFailed);

    return true;
  }
};

class CommandObjectRenderScriptRuntimeAllocationSave
    : public CommandObjectParsed {
public:
  CommandObjectRenderScriptRuntimeAllocationSave(
      CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "renderscript allocation save",
                            "Write renderscript allocation contents to a file.",
                            "renderscript allocation save <ID> <filename>",
                            eCommandRequiresProcess |
                                eCommandProcessMustBeLaunched) {}

  ~CommandObjectRenderScriptRuntimeAllocationSave() override = default;

  bool DoExecute(Args &command, CommandReturnObject &result) override {
    const size_t argc = command.GetArgumentCount();
    if (argc != 2) {
      result.AppendErrorWithFormat(
          "'%s' takes 2 arguments, an allocation ID and filename to read from.",
          m_cmd_name.c_str());
      return false;
    }

    RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
            eLanguageTypeExtRenderScript));

    const char *id_cstr = command.GetArgumentAtIndex(0);
    uint32_t id;
    if (!llvm::to_integer(id_cstr, id)) {
      result.AppendErrorWithFormat("invalid allocation id argument '%s'",
                                   id_cstr);
      return false;
    }

    const char *path = command.GetArgumentAtIndex(1);
    bool saved = runtime->SaveAllocation(result.GetOutputStream(), id, path,
                                         m_exe_ctx.GetFramePtr());

    if (saved)
      result.SetStatus(eReturnStatusSuccessFinishResult);
    else
      result.SetStatus(eReturnStatusFailed);

    return true;
  }
};

class CommandObjectRenderScriptRuntimeAllocationRefresh
    : public CommandObjectParsed {
public:
  CommandObjectRenderScriptRuntimeAllocationRefresh(
      CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "renderscript allocation refresh",
                            "Recomputes the details of all allocations.",
                            "renderscript allocation refresh",
                            eCommandRequiresProcess |
                                eCommandProcessMustBeLaunched) {}

  ~CommandObjectRenderScriptRuntimeAllocationRefresh() override = default;

  bool DoExecute(Args &command, CommandReturnObject &result) override {
    RenderScriptRuntime *runtime = static_cast<RenderScriptRuntime *>(
        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
            eLanguageTypeExtRenderScript));

    bool success = runtime->RecomputeAllAllocations(result.GetOutputStream(),
                                                    m_exe_ctx.GetFramePtr());

    if (success) {
      result.SetStatus(eReturnStatusSuccessFinishResult);
      return true;
    } else {
      result.SetStatus(eReturnStatusFailed);
      return false;
    }
  }
};

class CommandObjectRenderScriptRuntimeAllocation
    : public CommandObjectMultiword {
public:
  CommandObjectRenderScriptRuntimeAllocation(CommandInterpreter &interpreter)
      : CommandObjectMultiword(
            interpreter, "renderscript allocation",
            "Commands that deal with RenderScript allocations.", nullptr) {
    LoadSubCommand(
        "list",
        CommandObjectSP(
            new CommandObjectRenderScriptRuntimeAllocationList(interpreter)));
    LoadSubCommand(
        "dump",
        CommandObjectSP(
            new CommandObjectRenderScriptRuntimeAllocationDump(interpreter)));
    LoadSubCommand(
        "save",
        CommandObjectSP(
            new CommandObjectRenderScriptRuntimeAllocationSave(interpreter)));
    LoadSubCommand(
        "load",
        CommandObjectSP(
            new CommandObjectRenderScriptRuntimeAllocationLoad(interpreter)));
    LoadSubCommand(
        "refresh",
        CommandObjectSP(new CommandObjectRenderScriptRuntimeAllocationRefresh(
            interpreter)));
  }

  ~CommandObjectRenderScriptRuntimeAllocation() override = default;
};

class CommandObjectRenderScriptRuntimeStatus : public CommandObjectParsed {
public:
  CommandObjectRenderScriptRuntimeStatus(CommandInterpreter &interpreter)
      : CommandObjectParsed(interpreter, "renderscript status",
                            "Displays current RenderScript runtime status.",
                            "renderscript status",
                            eCommandRequiresProcess |
                                eCommandProcessMustBeLaunched) {}

  ~CommandObjectRenderScriptRuntimeStatus() override = default;

  bool DoExecute(Args &command, CommandReturnObject &result) override {
    RenderScriptRuntime *runtime = llvm::cast<RenderScriptRuntime>(
        m_exe_ctx.GetProcessPtr()->GetLanguageRuntime(
            eLanguageTypeExtRenderScript));
    runtime->DumpStatus(result.GetOutputStream());
    result.SetStatus(eReturnStatusSuccessFinishResult);
    return true;
  }
};

class CommandObjectRenderScriptRuntimeReduction
    : public CommandObjectMultiword {
public:
  CommandObjectRenderScriptRuntimeReduction(CommandInterpreter &interpreter)
      : CommandObjectMultiword(interpreter, "renderscript reduction",
                               "Commands that handle general reduction kernels",
                               nullptr) {
    LoadSubCommand(
        "breakpoint",
        CommandObjectSP(new CommandObjectRenderScriptRuntimeReductionBreakpoint(
            interpreter)));
  }
  ~CommandObjectRenderScriptRuntimeReduction() override = default;
};

class CommandObjectRenderScriptRuntime : public CommandObjectMultiword {
public:
  CommandObjectRenderScriptRuntime(CommandInterpreter &interpreter)
      : CommandObjectMultiword(
            interpreter, "renderscript",
            "Commands for operating on the RenderScript runtime.",
            "renderscript <subcommand> [<subcommand-options>]") {
    LoadSubCommand(
        "module", CommandObjectSP(
                      new CommandObjectRenderScriptRuntimeModule(interpreter)));
    LoadSubCommand(
        "status", CommandObjectSP(
                      new CommandObjectRenderScriptRuntimeStatus(interpreter)));
    LoadSubCommand(
        "kernel", CommandObjectSP(
                      new CommandObjectRenderScriptRuntimeKernel(interpreter)));
    LoadSubCommand("context",
                   CommandObjectSP(new CommandObjectRenderScriptRuntimeContext(
                       interpreter)));
    LoadSubCommand(
        "allocation",
        CommandObjectSP(
            new CommandObjectRenderScriptRuntimeAllocation(interpreter)));
    LoadSubCommand("scriptgroup",
                   NewCommandObjectRenderScriptScriptGroup(interpreter));
    LoadSubCommand(
        "reduction",
        CommandObjectSP(
            new CommandObjectRenderScriptRuntimeReduction(interpreter)));
  }

  ~CommandObjectRenderScriptRuntime() override = default;
};

void RenderScriptRuntime::Initiate() { assert(!m_initiated); }

RenderScriptRuntime::RenderScriptRuntime(Process *process)
    : lldb_private::CPPLanguageRuntime(process), m_initiated(false),
      m_debuggerPresentFlagged(false), m_breakAllKernels(false),
      m_ir_passes(nullptr) {
  ModulesDidLoad(process->GetTarget().GetImages());
}

lldb::CommandObjectSP RenderScriptRuntime::GetCommandObject(
    lldb_private::CommandInterpreter &interpreter) {
  return CommandObjectSP(new CommandObjectRenderScriptRuntime(interpreter));
}

RenderScriptRuntime::~RenderScriptRuntime() = default;
