Files
clang-p2996/lldb/source/Plugins/ABI/Hexagon/ABISysV_hexagon.cpp
Raphael Isemann 24e07570cc [lldb] Remove all the RegisterInfo name constification code
RegisterInfo's `reg_name`/`reg_alt_name` fields are C-Strings and are supposed
to only be generated from a ConstString. The reason for that is that
`DynamicRegisterInfo::GetRegisterInfo` and
`RegInfoBasedABI::GetRegisterInfoByName` try to optimise finding registers by
name by only comparing the C string pointer values instead of the underlying
strings. This only works if both C strings involved in the comparison come from
a ConstString. If one of the two C strings doesn't come from a ConstString the
comparison won't work (and most likely will silently fail).

I added an assert in b0060c3a78 which checks that
both strings come from a ConstString. Apparently not all ABI plugins are
generating their register names via ConstString, so this code is now not just
silently failing but also asserting.

In D88375 we did a shady fix for the MIPS plugins by just copying the
ConstString setup code to that plugin, but we still need to fix ABISysV_arc,
ABISysV_ppc and ABISysV_ppc64 plugins.

I would say we just fix the remaining plugins by removing the whole requirement
to have the register names coming from ConstStrings. I really doubt that we
actually save any time with the whole ConstString search trick (searching ~50
strings that have <4 characters doesn't sound more expensive than calling the
really expensive ConstString constructor + comparing the same amount of pointer
values). Also whatever small percentage of LLDB's runtime is actually spend in
this function is anyway not worth the complexity of this approach.

This patch just removes all this and just does a normal string comparison.

Reviewed By: JDevlieghere, labath

Differential Revision: https://reviews.llvm.org/D88490
2020-10-13 17:10:29 +02:00

1343 lines
27 KiB
C++

//===-- ABISysV_hexagon.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 "ABISysV_hexagon.h"
#include "llvm/ADT/Triple.h"
#include "llvm/IR/DerivedTypes.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectMemory.h"
#include "lldb/Core/ValueObjectRegister.h"
#include "lldb/Symbol/UnwindPlan.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/ConstString.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Log.h"
#include "lldb/Utility/RegisterValue.h"
#include "lldb/Utility/Status.h"
using namespace lldb;
using namespace lldb_private;
LLDB_PLUGIN_DEFINE_ADV(ABISysV_hexagon, ABIHexagon)
static const RegisterInfo g_register_infos[] = {
// hexagon-core.xml
{"r00",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{0, 0, LLDB_INVALID_REGNUM, 0, 0},
nullptr,
nullptr,
nullptr,
0},
{"r01",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{1, 1, LLDB_INVALID_REGNUM, 1, 1},
nullptr,
nullptr,
nullptr,
0},
{"r02",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{2, 2, LLDB_INVALID_REGNUM, 2, 2},
nullptr,
nullptr,
nullptr,
0},
{"r03",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{3, 3, LLDB_INVALID_REGNUM, 3, 3},
nullptr,
nullptr,
nullptr,
0},
{"r04",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{4, 4, LLDB_INVALID_REGNUM, 4, 4},
nullptr,
nullptr,
nullptr,
0},
{"r05",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{5, 5, LLDB_INVALID_REGNUM, 5, 5},
nullptr,
nullptr,
nullptr,
0},
{"r06",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{6, 6, LLDB_INVALID_REGNUM, 6, 6},
nullptr,
nullptr,
nullptr,
0},
{"r07",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{7, 7, LLDB_INVALID_REGNUM, 7, 7},
nullptr,
nullptr,
nullptr,
0},
{"r08",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{8, 8, LLDB_INVALID_REGNUM, 8, 8},
nullptr,
nullptr,
nullptr,
0},
{"r09",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{9, 9, LLDB_INVALID_REGNUM, 9, 9},
nullptr,
nullptr,
nullptr,
0},
{"r10",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{10, 10, LLDB_INVALID_REGNUM, 10, 10},
nullptr,
nullptr,
nullptr,
0},
{"r11",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{11, 11, LLDB_INVALID_REGNUM, 11, 11},
nullptr,
nullptr,
nullptr,
0},
{"r12",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{12, 12, LLDB_INVALID_REGNUM, 12, 12},
nullptr,
nullptr,
nullptr,
0},
{"r13",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{13, 13, LLDB_INVALID_REGNUM, 13, 13},
nullptr,
nullptr,
nullptr,
0},
{"r14",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{14, 14, LLDB_INVALID_REGNUM, 14, 14},
nullptr,
nullptr,
nullptr,
0},
{"r15",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{15, 15, LLDB_INVALID_REGNUM, 15, 15},
nullptr,
nullptr,
nullptr,
0},
{"r16",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{16, 16, LLDB_INVALID_REGNUM, 16, 16},
nullptr,
nullptr,
nullptr,
0},
{"r17",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{17, 17, LLDB_INVALID_REGNUM, 17, 17},
nullptr,
nullptr,
nullptr,
0},
{"r18",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{18, 18, LLDB_INVALID_REGNUM, 18, 18},
nullptr,
nullptr,
nullptr,
0},
{"r19",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{19, 19, LLDB_INVALID_REGNUM, 19, 19},
nullptr,
nullptr,
nullptr,
0},
{"r20",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{20, 20, LLDB_INVALID_REGNUM, 20, 20},
nullptr,
nullptr,
nullptr,
0},
{"r21",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{21, 21, LLDB_INVALID_REGNUM, 21, 21},
nullptr,
nullptr,
nullptr,
0},
{"r22",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{22, 22, LLDB_INVALID_REGNUM, 22, 22},
nullptr,
nullptr,
nullptr,
0},
{"r23",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{23, 23, LLDB_INVALID_REGNUM, 23, 23},
nullptr,
nullptr,
nullptr,
0},
{"r24",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{24, 24, LLDB_INVALID_REGNUM, 24, 24},
nullptr,
nullptr,
nullptr,
0},
{"r25",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{25, 25, LLDB_INVALID_REGNUM, 25, 25},
nullptr,
nullptr,
nullptr,
0},
{"r26",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{26, 26, LLDB_INVALID_REGNUM, 26, 26},
nullptr,
nullptr,
nullptr,
0},
{"r27",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{27, 27, LLDB_INVALID_REGNUM, 27, 27},
nullptr,
nullptr,
nullptr,
0},
{"r28",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{28, 28, LLDB_INVALID_REGNUM, 28, 28},
nullptr,
nullptr,
nullptr,
0},
{"sp",
"r29",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{29, 29, LLDB_REGNUM_GENERIC_SP, 29, 29},
nullptr,
nullptr,
nullptr,
0},
{"fp",
"r30",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{30, 30, LLDB_REGNUM_GENERIC_FP, 30, 30},
nullptr,
nullptr,
nullptr,
0},
{"lr",
"r31",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{31, 31, LLDB_REGNUM_GENERIC_RA, 31, 31},
nullptr,
nullptr,
nullptr,
0},
{"sa0",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{32, 32, LLDB_INVALID_REGNUM, 32, 32},
nullptr,
nullptr,
nullptr,
0},
{"lc0",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{33, 33, LLDB_INVALID_REGNUM, 33, 33},
nullptr,
nullptr,
nullptr,
0},
{"sa1",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{34, 34, LLDB_INVALID_REGNUM, 34, 34},
nullptr,
nullptr,
nullptr,
0},
{"lc1",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{35, 35, LLDB_INVALID_REGNUM, 35, 35},
nullptr,
nullptr,
nullptr,
0},
// --> hexagon-v4/5/55/56-sim.xml
{"p3_0",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{36, 36, LLDB_INVALID_REGNUM, 36, 36},
nullptr,
nullptr,
nullptr,
0},
// PADDING {
{"p00",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{37, 37, LLDB_INVALID_REGNUM, 37, 37},
nullptr,
nullptr,
nullptr,
0},
// }
{"m0",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{38, 38, LLDB_INVALID_REGNUM, 38, 38},
nullptr,
nullptr,
nullptr,
0},
{"m1",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{39, 39, LLDB_INVALID_REGNUM, 39, 39},
nullptr,
nullptr,
nullptr,
0},
{"usr",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{40, 40, LLDB_INVALID_REGNUM, 40, 40},
nullptr,
nullptr,
nullptr,
0},
{"pc",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{41, 41, LLDB_REGNUM_GENERIC_PC, 41, 41},
nullptr,
nullptr,
nullptr,
0},
{"ugp",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{42, 42, LLDB_INVALID_REGNUM, 42, 42},
nullptr,
nullptr,
nullptr,
0},
{"gp",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{43, 43, LLDB_INVALID_REGNUM, 43, 43},
nullptr,
nullptr,
nullptr,
0},
{"cs0",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{44, 44, LLDB_INVALID_REGNUM, 44, 44},
nullptr,
nullptr,
nullptr,
0},
{"cs1",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{45, 45, LLDB_INVALID_REGNUM, 45, 45},
nullptr,
nullptr,
nullptr,
0},
// PADDING {
{"p01",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{46, 46, LLDB_INVALID_REGNUM, 46, 46},
nullptr,
nullptr,
nullptr,
0},
{"p02",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{47, 47, LLDB_INVALID_REGNUM, 47, 47},
nullptr,
nullptr,
nullptr,
0},
{"p03",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{48, 48, LLDB_INVALID_REGNUM, 48, 48},
nullptr,
nullptr,
nullptr,
0},
{"p04",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{49, 49, LLDB_INVALID_REGNUM, 49, 49},
nullptr,
nullptr,
nullptr,
0},
{"p05",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{50, 50, LLDB_INVALID_REGNUM, 50, 50},
nullptr,
nullptr,
nullptr,
0},
{"p06",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{51, 51, LLDB_INVALID_REGNUM, 51, 51},
nullptr,
nullptr,
nullptr,
0},
{"p07",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{52, 52, LLDB_INVALID_REGNUM, 52, 52},
nullptr,
nullptr,
nullptr,
0},
{"p08",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{53, 53, LLDB_INVALID_REGNUM, 53, 53},
nullptr,
nullptr,
nullptr,
0},
{"p09",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{54, 54, LLDB_INVALID_REGNUM, 54, 54},
nullptr,
nullptr,
nullptr,
0},
{"p10",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{55, 55, LLDB_INVALID_REGNUM, 55, 55},
nullptr,
nullptr,
nullptr,
0},
{"p11",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{56, 56, LLDB_INVALID_REGNUM, 56, 56},
nullptr,
nullptr,
nullptr,
0},
{"p12",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{57, 57, LLDB_INVALID_REGNUM, 57, 57},
nullptr,
nullptr,
nullptr,
0},
{"p13",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{58, 58, LLDB_INVALID_REGNUM, 58, 58},
nullptr,
nullptr,
nullptr,
0},
{"p14",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{59, 59, LLDB_INVALID_REGNUM, 59, 59},
nullptr,
nullptr,
nullptr,
0},
{"p15",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{60, 60, LLDB_INVALID_REGNUM, 60, 60},
nullptr,
nullptr,
nullptr,
0},
{"p16",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{61, 61, LLDB_INVALID_REGNUM, 61, 61},
nullptr,
nullptr,
nullptr,
0},
{"p17",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{62, 62, LLDB_INVALID_REGNUM, 62, 62},
nullptr,
nullptr,
nullptr,
0},
{"p18",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{63, 63, LLDB_INVALID_REGNUM, 63, 63},
nullptr,
nullptr,
nullptr,
0},
// }
{"sgp0",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{64, 64, LLDB_INVALID_REGNUM, 64, 64},
nullptr,
nullptr,
nullptr,
0},
// PADDING {
{"p19",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{65, 65, LLDB_INVALID_REGNUM, 65, 65},
nullptr,
nullptr,
nullptr,
0},
// }
{"stid",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{66, 66, LLDB_INVALID_REGNUM, 66, 66},
nullptr,
nullptr,
nullptr,
0},
{"elr",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{67, 67, LLDB_INVALID_REGNUM, 67, 67},
nullptr,
nullptr,
nullptr,
0},
{"badva0",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{68, 68, LLDB_INVALID_REGNUM, 68, 68},
nullptr,
nullptr,
nullptr,
0},
{"badva1",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{69, 69, LLDB_INVALID_REGNUM, 69, 69},
nullptr,
nullptr,
nullptr,
0},
{"ssr",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{70, 70, LLDB_INVALID_REGNUM, 70, 70},
nullptr,
nullptr,
nullptr,
0},
{"ccr",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{71, 71, LLDB_INVALID_REGNUM, 71, 71},
nullptr,
nullptr,
nullptr,
0},
{"htid",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{72, 72, LLDB_INVALID_REGNUM, 72, 72},
nullptr,
nullptr,
nullptr,
0},
// PADDING {
{"p20",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{73, 73, LLDB_INVALID_REGNUM, 73, 73},
nullptr,
nullptr,
nullptr,
0},
// }
{"imask",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{74, 74, LLDB_INVALID_REGNUM, 74, 74},
nullptr,
nullptr,
nullptr,
0},
// PADDING {
{"p21",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{75, 75, LLDB_INVALID_REGNUM, 75, 75},
nullptr,
nullptr,
nullptr,
0},
{"p22",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{76, 76, LLDB_INVALID_REGNUM, 76, 76},
nullptr,
nullptr,
nullptr,
0},
{"p23",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{77, 77, LLDB_INVALID_REGNUM, 77, 77},
nullptr,
nullptr,
nullptr,
0},
{"p24",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{78, 78, LLDB_INVALID_REGNUM, 78, 78},
nullptr,
nullptr,
nullptr,
0},
{"p25",
"",
4,
0,
eEncodingInvalid,
eFormatInvalid,
{79, 79, LLDB_INVALID_REGNUM, 79, 79},
nullptr,
nullptr,
nullptr,
0},
// }
{"g0",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{80, 80, LLDB_INVALID_REGNUM, 80, 80},
nullptr,
nullptr,
nullptr,
0},
{"g1",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{81, 81, LLDB_INVALID_REGNUM, 81, 81},
nullptr,
nullptr,
nullptr,
0},
{"g2",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{82, 82, LLDB_INVALID_REGNUM, 82, 82},
nullptr,
nullptr,
nullptr,
0},
{"g3",
"",
4,
0,
eEncodingUint,
eFormatAddressInfo,
{83, 83, LLDB_INVALID_REGNUM, 83, 83},
nullptr,
nullptr,
nullptr,
0}};
static const uint32_t k_num_register_infos =
sizeof(g_register_infos) / sizeof(RegisterInfo);
const lldb_private::RegisterInfo *
ABISysV_hexagon::GetRegisterInfoArray(uint32_t &count) {
count = k_num_register_infos;
return g_register_infos;
}
/*
http://en.wikipedia.org/wiki/Red_zone_%28computing%29
In computing, a red zone is a fixed size area in memory beyond the stack
pointer that has not been
"allocated". This region of memory is not to be modified by
interrupt/exception/signal handlers.
This allows the space to be used for temporary data without the extra
overhead of modifying the
stack pointer. The x86-64 ABI mandates a 128 byte red zone.[1] The OpenRISC
toolchain assumes a
128 byte red zone though it is not documented.
*/
size_t ABISysV_hexagon::GetRedZoneSize() const { return 0; }
// Static Functions
ABISP
ABISysV_hexagon::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
if (arch.GetTriple().getArch() == llvm::Triple::hexagon) {
return ABISP(
new ABISysV_hexagon(std::move(process_sp), MakeMCRegisterInfo(arch)));
}
return ABISP();
}
bool ABISysV_hexagon::PrepareTrivialCall(Thread &thread, lldb::addr_t sp,
lldb::addr_t pc, lldb::addr_t ra,
llvm::ArrayRef<addr_t> args) const {
// we don't use the traditional trivial call specialized for jit
return false;
}
/*
// AD:
// . safeguard the current stack
// . how can we know that the called function will create its own frame
properly?
// . we could manually make a new stack first:
// 2. push RA
// 3. push FP
// 4. FP = SP
// 5. SP = SP ( since no locals in our temp frame )
// AD 6/05/2014
// . variable argument list parameters are not passed via registers, they are
passed on
// the stack. This presents us with a problem, since we need to know when
the valist
// starts. Currently I can find out if a function is varg, but not how many
// real parameters it takes. Thus I don't know when to start spilling the
vargs. For
// the time being, to progress, I will assume that it takes on real parameter
before
// the vargs list starts.
// AD 06/05/2014
// . how do we adhere to the stack alignment requirements
// AD 06/05/2014
// . handle 64bit values and their register / stack requirements
*/
#define HEX_ABI_DEBUG 0
bool ABISysV_hexagon::PrepareTrivialCall(
Thread &thread, lldb::addr_t sp, lldb::addr_t pc, lldb::addr_t ra,
llvm::Type &prototype, llvm::ArrayRef<ABI::CallArgument> args) const {
// default number of register passed arguments for varg functions
const int nVArgRegParams = 1;
Status error;
// grab the process so we have access to the memory for spilling
lldb::ProcessSP proc = thread.GetProcess();
// get the register context for modifying all of the registers
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
if (!reg_ctx)
return false;
uint32_t pc_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
if (pc_reg == LLDB_INVALID_REGNUM)
return false;
uint32_t ra_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
if (ra_reg == LLDB_INVALID_REGNUM)
return false;
uint32_t sp_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
if (sp_reg == LLDB_INVALID_REGNUM)
return false;
// push host data onto target
for (size_t i = 0; i < args.size(); i++) {
const ABI::CallArgument &arg = args[i];
// skip over target values
if (arg.type == ABI::CallArgument::TargetValue)
continue;
// round up to 8 byte multiple
size_t argSize = (arg.size | 0x7) + 1;
// create space on the stack for this data
sp -= argSize;
// write this argument onto the stack of the host process
proc->WriteMemory(sp, arg.data_up.get(), arg.size, error);
if (error.Fail())
return false;
// update the argument with the target pointer
// XXX: This is a gross hack for getting around the const
*const_cast<lldb::addr_t *>(&arg.value) = sp;
}
#if HEX_ABI_DEBUG
// print the original stack pointer
printf("sp : %04" PRIx64 " \n", sp);
#endif
// make sure number of parameters matches prototype
assert(prototype.getFunctionNumParams() == args.size());
// check if this is a variable argument function
bool isVArg = prototype.isFunctionVarArg();
// number of arguments passed by register
int nRegArgs = nVArgRegParams;
if (!isVArg) {
// number of arguments is limited by [R0 : R5] space
nRegArgs = args.size();
if (nRegArgs > 6)
nRegArgs = 6;
}
// pass arguments that are passed via registers
for (int i = 0; i < nRegArgs; i++) {
// get the parameter as a u32
uint32_t param = (uint32_t)args[i].value;
// write argument into register
if (!reg_ctx->WriteRegisterFromUnsigned(i, param))
return false;
}
// number of arguments to spill onto stack
int nSpillArgs = args.size() - nRegArgs;
// make space on the stack for arguments
sp -= 4 * nSpillArgs;
// align stack on an 8 byte boundary
if (sp & 7)
sp -= 4;
// arguments that are passed on the stack
for (size_t i = nRegArgs, offs = 0; i < args.size(); i++) {
// get the parameter as a u32
uint32_t param = (uint32_t)args[i].value;
// write argument to stack
proc->WriteMemory(sp + offs, (void *)&param, sizeof(param), error);
if (!error.Success())
return false;
//
offs += 4;
}
// update registers with current function call state
reg_ctx->WriteRegisterFromUnsigned(pc_reg, pc);
reg_ctx->WriteRegisterFromUnsigned(ra_reg, ra);
reg_ctx->WriteRegisterFromUnsigned(sp_reg, sp);
#if HEX_ABI_DEBUG
// quick and dirty stack dumper for debugging
for (int i = -8; i < 8; i++) {
uint32_t data = 0;
lldb::addr_t addr = sp + i * 4;
proc->ReadMemory(addr, (void *)&data, sizeof(data), error);
printf("\n0x%04" PRIx64 " 0x%08x ", addr, data);
if (i == 0)
printf("<<-- sp");
}
printf("\n");
#endif
return true;
}
bool ABISysV_hexagon::GetArgumentValues(Thread &thread,
ValueList &values) const {
return false;
}
Status
ABISysV_hexagon::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
lldb::ValueObjectSP &new_value_sp) {
Status error;
return error;
}
ValueObjectSP ABISysV_hexagon::GetReturnValueObjectSimple(
Thread &thread, CompilerType &return_compiler_type) const {
ValueObjectSP return_valobj_sp;
return return_valobj_sp;
}
ValueObjectSP ABISysV_hexagon::GetReturnValueObjectImpl(
Thread &thread, CompilerType &return_compiler_type) const {
ValueObjectSP return_valobj_sp;
return return_valobj_sp;
}
// called when we are on the first instruction of a new function for hexagon
// the return address is in RA (R31)
bool ABISysV_hexagon::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
unwind_plan.Clear();
unwind_plan.SetRegisterKind(eRegisterKindGeneric);
unwind_plan.SetReturnAddressRegister(LLDB_REGNUM_GENERIC_RA);
UnwindPlan::RowSP row(new UnwindPlan::Row);
// Our Call Frame Address is the stack pointer value
row->GetCFAValue().SetIsRegisterPlusOffset(LLDB_REGNUM_GENERIC_SP, 4);
row->SetOffset(0);
// The previous PC is in the LR
row->SetRegisterLocationToRegister(LLDB_REGNUM_GENERIC_PC,
LLDB_REGNUM_GENERIC_RA, true);
unwind_plan.AppendRow(row);
unwind_plan.SetSourceName("hexagon at-func-entry default");
unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
return true;
}
bool ABISysV_hexagon::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
unwind_plan.Clear();
unwind_plan.SetRegisterKind(eRegisterKindGeneric);
uint32_t fp_reg_num = LLDB_REGNUM_GENERIC_FP;
uint32_t sp_reg_num = LLDB_REGNUM_GENERIC_SP;
uint32_t pc_reg_num = LLDB_REGNUM_GENERIC_PC;
UnwindPlan::RowSP row(new UnwindPlan::Row);
row->GetCFAValue().SetIsRegisterPlusOffset(LLDB_REGNUM_GENERIC_FP, 8);
row->SetRegisterLocationToAtCFAPlusOffset(fp_reg_num, -8, true);
row->SetRegisterLocationToAtCFAPlusOffset(pc_reg_num, -4, true);
row->SetRegisterLocationToIsCFAPlusOffset(sp_reg_num, 0, true);
unwind_plan.AppendRow(row);
unwind_plan.SetSourceName("hexagon default unwind plan");
unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
return true;
}
/*
Register Usage Saved By
R0 - R5 parameters(a) -
R6 - R15 Scratch(b) Caller
R16 - R27 Scratch Callee
R28 Scratch(b) Caller
R29 - R31 Stack Frames Callee(c)
P3:0 Processor State Caller
a = the caller can change parameter values
b = R14 - R15 and R28 are used by the procedure linkage table
c = R29 - R31 are saved and restored by allocframe() and deallocframe()
*/
bool ABISysV_hexagon::RegisterIsVolatile(const RegisterInfo *reg_info) {
return !RegisterIsCalleeSaved(reg_info);
}
bool ABISysV_hexagon::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
int reg = ((reg_info->byte_offset) / 4);
bool save = (reg >= 16) && (reg <= 27);
save |= (reg >= 29) && (reg <= 32);
return save;
}
void ABISysV_hexagon::Initialize() {
PluginManager::RegisterPlugin(GetPluginNameStatic(),
"System V ABI for hexagon targets",
CreateInstance);
}
void ABISysV_hexagon::Terminate() {
PluginManager::UnregisterPlugin(CreateInstance);
}
lldb_private::ConstString ABISysV_hexagon::GetPluginNameStatic() {
static ConstString g_name("sysv-hexagon");
return g_name;
}
// PluginInterface protocol
lldb_private::ConstString ABISysV_hexagon::GetPluginName() {
return GetPluginNameStatic();
}
uint32_t ABISysV_hexagon::GetPluginVersion() { return 1; }
// get value object specialized to work with llvm IR types
lldb::ValueObjectSP
ABISysV_hexagon::GetReturnValueObjectImpl(lldb_private::Thread &thread,
llvm::Type &retType) const {
Value value;
ValueObjectSP vObjSP;
// get the current register context
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
if (!reg_ctx)
return vObjSP;
// for now just pop R0 to find the return value
const lldb_private::RegisterInfo *r0_info =
reg_ctx->GetRegisterInfoAtIndex(0);
if (r0_info == nullptr)
return vObjSP;
// void return type
if (retType.isVoidTy()) {
value.GetScalar() = 0;
}
// integer / pointer return type
else if (retType.isIntegerTy() || retType.isPointerTy()) {
// read r0 register value
lldb_private::RegisterValue r0_value;
if (!reg_ctx->ReadRegister(r0_info, r0_value))
return vObjSP;
// push r0 into value
uint32_t r0_u32 = r0_value.GetAsUInt32();
// account for integer size
if (retType.isIntegerTy() && retType.isSized()) {
uint64_t size = retType.getScalarSizeInBits();
uint64_t mask = (1ull << size) - 1;
// mask out higher order bits then the type we expect
r0_u32 &= mask;
}
value.GetScalar() = r0_u32;
}
// unsupported return type
else
return vObjSP;
// pack the value into a ValueObjectSP
vObjSP = ValueObjectConstResult::Create(thread.GetStackFrameAtIndex(0).get(),
value, ConstString(""));
return vObjSP;
}