llvm-project/lldb/source/Plugins/ABI/Mips/ABISysV_mips.cpp

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

1067 lines
28 KiB
C++
Raw Normal View History

//===-- ABISysV_mips.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_mips.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Triple.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(ABISysV_mips);
Clean up register naming conventions inside lldb. "gcc" register numbers are now correctly referred to as "ehframe" register numbers. In almost all cases, ehframe and dwarf register numbers are identical (the one exception is i386 darwin where ehframe regnums were incorrect). The old "gdb" register numbers, which I incorrectly thought were stabs register numbers, are now referred to as "Process Plugin" register numbers. This is the register numbering scheme that the remote process controller stub (lldb-server, gdbserver, core file support, kdp server, remote jtag devices, etc) uses to refer to the registers. The process plugin register numbers may not be contiguous - there are remote jtag devices that have gaps in their register numbering schemes. I removed all of the enums for "gdb" register numbers that we had in lldb - these were meaningless - and I put LLDB_INVALID_REGNUM in all of the register tables for the Process Plugin regnum slot. This change is almost entirely mechnical; the one actual change in here is to ProcessGDBRemote.cpp's ParseRegisters() which parses the qXfer:features:read:target.xml response. As it parses register definitions from the xml, it will assign sequential numbers as the eRegisterKindLLDB numbers (the lldb register numberings must be sequential, without any gaps) and if the xml file specifies register numbers, those will be used as the eRegisterKindProcessPlugin register numbers (and those may have gaps). A J-Link jtag device's target.xml does contain a gap in register numbers, and it only specifies the register numbers for the registers after that gap. The device supports many different ARM boards and probably selects different part of its register file as appropriate. http://reviews.llvm.org/D12791 <rdar://problem/22623262> llvm-svn: 247741
2015-09-16 07:20:34 +08:00
enum dwarf_regnums {
dwarf_r0 = 0,
dwarf_r1,
dwarf_r2,
dwarf_r3,
dwarf_r4,
dwarf_r5,
dwarf_r6,
dwarf_r7,
dwarf_r8,
dwarf_r9,
dwarf_r10,
dwarf_r11,
dwarf_r12,
dwarf_r13,
dwarf_r14,
dwarf_r15,
dwarf_r16,
dwarf_r17,
dwarf_r18,
dwarf_r19,
dwarf_r20,
dwarf_r21,
dwarf_r22,
dwarf_r23,
dwarf_r24,
dwarf_r25,
dwarf_r26,
dwarf_r27,
dwarf_r28,
dwarf_r29,
dwarf_r30,
dwarf_r31,
dwarf_sr,
dwarf_lo,
dwarf_hi,
dwarf_bad,
dwarf_cause,
dwarf_pc
};
static const RegisterInfo g_register_infos[] = {
Clean up register naming conventions inside lldb. "gcc" register numbers are now correctly referred to as "ehframe" register numbers. In almost all cases, ehframe and dwarf register numbers are identical (the one exception is i386 darwin where ehframe regnums were incorrect). The old "gdb" register numbers, which I incorrectly thought were stabs register numbers, are now referred to as "Process Plugin" register numbers. This is the register numbering scheme that the remote process controller stub (lldb-server, gdbserver, core file support, kdp server, remote jtag devices, etc) uses to refer to the registers. The process plugin register numbers may not be contiguous - there are remote jtag devices that have gaps in their register numbering schemes. I removed all of the enums for "gdb" register numbers that we had in lldb - these were meaningless - and I put LLDB_INVALID_REGNUM in all of the register tables for the Process Plugin regnum slot. This change is almost entirely mechnical; the one actual change in here is to ProcessGDBRemote.cpp's ParseRegisters() which parses the qXfer:features:read:target.xml response. As it parses register definitions from the xml, it will assign sequential numbers as the eRegisterKindLLDB numbers (the lldb register numberings must be sequential, without any gaps) and if the xml file specifies register numbers, those will be used as the eRegisterKindProcessPlugin register numbers (and those may have gaps). A J-Link jtag device's target.xml does contain a gap in register numbers, and it only specifies the register numbers for the registers after that gap. The device supports many different ARM boards and probably selects different part of its register file as appropriate. http://reviews.llvm.org/D12791 <rdar://problem/22623262> llvm-svn: 247741
2015-09-16 07:20:34 +08:00
// NAME ALT SZ OFF ENCODING FORMAT EH_FRAME
// DWARF GENERIC PROCESS PLUGINS
// LLDB NATIVE VALUE REGS INVALIDATE REGS
// ======== ====== == === ============= =========== ============
// ============== ============ =================
// =================== ========== =================
{"r0",
"zero",
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_r0, dwarf_r0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"r1",
"AT",
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_r1, dwarf_r1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"r2",
"v0",
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_r2, dwarf_r2, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"r3",
"v1",
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_r3, dwarf_r3, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"r4",
"arg1",
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_r4, dwarf_r4, LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"r5",
"arg2",
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_r5, dwarf_r5, LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"r6",
"arg3",
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_r6, dwarf_r6, LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"r7",
"arg4",
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_r7, dwarf_r7, LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"r8",
"arg5",
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_r8, dwarf_r8, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"r9",
"arg6",
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_r9, dwarf_r9, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"r10",
"arg7",
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_r10, dwarf_r10, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"r11",
"arg8",
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_r11, dwarf_r11, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"r12",
nullptr,
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_r12, dwarf_r12, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"r13",
nullptr,
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_r13, dwarf_r13, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"r14",
nullptr,
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_r14, dwarf_r14, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"r15",
nullptr,
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_r15, dwarf_r15, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"r16",
nullptr,
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_r16, dwarf_r16, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"r17",
nullptr,
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_r17, dwarf_r17, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"r18",
nullptr,
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_r18, dwarf_r18, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"r19",
nullptr,
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_r19, dwarf_r19, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"r20",
nullptr,
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_r20, dwarf_r20, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"r21",
nullptr,
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_r21, dwarf_r21, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"r22",
nullptr,
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_r22, dwarf_r22, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"r23",
nullptr,
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_r23, dwarf_r23, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"r24",
nullptr,
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_r24, dwarf_r24, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"r25",
nullptr,
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_r25, dwarf_r25, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"r26",
nullptr,
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_r26, dwarf_r26, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"r27",
nullptr,
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_r27, dwarf_r27, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"r28",
"gp",
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_r28, dwarf_r28, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"r29",
"sp",
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_r29, dwarf_r29, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"r30",
"fp",
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_r30, dwarf_r30, LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"r31",
"ra",
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_r31, dwarf_r31, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"sr",
nullptr,
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_sr, dwarf_sr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"lo",
nullptr,
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_lo, dwarf_lo, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"hi",
nullptr,
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_hi, dwarf_hi, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"bad",
nullptr,
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_bad, dwarf_bad, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"cause",
nullptr,
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_cause, dwarf_cause, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
{"pc",
nullptr,
4,
0,
eEncodingUint,
eFormatHex,
{dwarf_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM},
nullptr,
nullptr,
nullptr,
0},
};
static const uint32_t k_num_register_infos =
llvm::array_lengthof(g_register_infos);
const lldb_private::RegisterInfo *
ABISysV_mips::GetRegisterInfoArray(uint32_t &count) {
count = k_num_register_infos;
return g_register_infos;
}
size_t ABISysV_mips::GetRedZoneSize() const { return 0; }
// Static Functions
ABISP
ABISysV_mips::CreateInstance(lldb::ProcessSP process_sp, const ArchSpec &arch) {
const llvm::Triple::ArchType arch_type = arch.GetTriple().getArch();
if ((arch_type == llvm::Triple::mips) ||
(arch_type == llvm::Triple::mipsel)) {
Have ABI plugins vend llvm MCRegisterInfo data Summary: I was recently surprised to learn that there is a total of 2 (two) users of the register info definitions contained in the ABI plugins. Yet, the defitions themselves span nearly 10kLOC. The two users are: - dwarf expression pretty printer - the mechanism for augmenting the register info definitions obtained over gdb-remote protocol (AugmentRegisterInfoViaABI) Both of these uses need the DWARF an EH register numbers, which is information that is already available in LLVM. This patch makes it possible to do so. It adds a GetMCRegisterInfo method to the ABI class, which every class is expected to implement. Normally, it should be sufficient to obtain the definitions from the appropriate llvm::Target object (for which I provide a utility function), but the subclasses are free to construct it in any way they deem fit. We should be able to always get the MCRegisterInfo object from llvm, with one important exception: if the relevant llvm target was disabled at compile time. To handle this, I add a mechanism to disable the compilation of ABI plugins based on the value of LLVM_TARGETS_TO_BUILD cmake setting. This ensures all our existing are able to create their MCRegisterInfo objects. The new MCRegisterInfo api is not used yet, but the intention is to make use of it in follow-up patches. Reviewers: jasonmolenda, aprantl, JDevlieghere, tatyana-krasnukha Subscribers: wuzish, nemanjai, mgorny, kbarton, atanasyan, lldb-commits Differential Revision: https://reviews.llvm.org/D67965 llvm-svn: 372862
2019-09-25 21:03:04 +08:00
return ABISP(
new ABISysV_mips(std::move(process_sp), MakeMCRegisterInfo(arch)));
}
return ABISP();
}
bool ABISysV_mips::PrepareTrivialCall(Thread &thread, addr_t sp,
addr_t func_addr, addr_t return_addr,
llvm::ArrayRef<addr_t> args) const {
Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS));
if (log) {
StreamString s;
s.Printf("ABISysV_mips::PrepareTrivialCall (tid = 0x%" PRIx64
", sp = 0x%" PRIx64 ", func_addr = 0x%" PRIx64
", return_addr = 0x%" PRIx64,
thread.GetID(), (uint64_t)sp, (uint64_t)func_addr,
(uint64_t)return_addr);
for (size_t i = 0; i < args.size(); ++i)
s.Printf(", arg%zd = 0x%" PRIx64, i + 1, args[i]);
s.PutCString(")");
log->PutString(s.GetString());
}
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
if (!reg_ctx)
return false;
const RegisterInfo *reg_info = nullptr;
RegisterValue reg_value;
// Argument registers
const char *reg_names[] = {"r4", "r5", "r6", "r7"};
llvm::ArrayRef<addr_t>::iterator ai = args.begin(), ae = args.end();
// Write arguments to registers
for (size_t i = 0; i < llvm::array_lengthof(reg_names); ++i) {
if (ai == ae)
break;
reg_info = reg_ctx->GetRegisterInfo(eRegisterKindGeneric,
LLDB_REGNUM_GENERIC_ARG1 + i);
LLDB_LOGF(log, "About to write arg%zd (0x%" PRIx64 ") into %s", i + 1,
args[i], reg_info->name);
if (!reg_ctx->WriteRegisterFromUnsigned(reg_info, args[i]))
return false;
++ai;
}
// If we have more than 4 arguments --Spill onto the stack
if (ai != ae) {
// No of arguments to go on stack
size_t num_stack_regs = args.size();
// Allocate needed space for args on the stack
sp -= (num_stack_regs * 4);
// Keep the stack 8 byte aligned
sp &= ~(8ull - 1ull);
// just using arg1 to get the right size
const RegisterInfo *reg_info = reg_ctx->GetRegisterInfo(
eRegisterKindGeneric, LLDB_REGNUM_GENERIC_ARG1);
addr_t arg_pos = sp + 16;
size_t i = 4;
for (; ai != ae; ++ai) {
reg_value.SetUInt32(*ai);
LLDB_LOGF(log, "About to write arg%zd (0x%" PRIx64 ") at 0x%" PRIx64 "",
i + 1, args[i], arg_pos);
if (reg_ctx
->WriteRegisterValueToMemory(reg_info, arg_pos,
reg_info->byte_size, reg_value)
.Fail())
return false;
arg_pos += reg_info->byte_size;
i++;
}
}
Status error;
const RegisterInfo *pc_reg_info =
reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
const RegisterInfo *sp_reg_info =
reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
const RegisterInfo *ra_reg_info =
reg_ctx->GetRegisterInfo(eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
const RegisterInfo *r25_info = reg_ctx->GetRegisterInfoByName("r25", 0);
const RegisterInfo *r0_info = reg_ctx->GetRegisterInfoByName("zero", 0);
LLDB_LOGF(log, "Writing R0: 0x%" PRIx64, (uint64_t)0);
/* Write r0 with 0, in case we are stopped in syscall,
* such setting prevents automatic decrement of the PC.
* This clears the bug 23659 for MIPS.
*/
if (!reg_ctx->WriteRegisterFromUnsigned(r0_info, (uint64_t)0))
return false;
LLDB_LOGF(log, "Writing SP: 0x%" PRIx64, (uint64_t)sp);
// Set "sp" to the requested value
if (!reg_ctx->WriteRegisterFromUnsigned(sp_reg_info, sp))
return false;
LLDB_LOGF(log, "Writing RA: 0x%" PRIx64, (uint64_t)return_addr);
// Set "ra" to the return address
if (!reg_ctx->WriteRegisterFromUnsigned(ra_reg_info, return_addr))
return false;
LLDB_LOGF(log, "Writing PC: 0x%" PRIx64, (uint64_t)func_addr);
// Set pc to the address of the called function.
if (!reg_ctx->WriteRegisterFromUnsigned(pc_reg_info, func_addr))
return false;
LLDB_LOGF(log, "Writing r25: 0x%" PRIx64, (uint64_t)func_addr);
// All callers of position independent functions must place the address of
// the called function in t9 (r25)
if (!reg_ctx->WriteRegisterFromUnsigned(r25_info, func_addr))
return false;
return true;
}
bool ABISysV_mips::GetArgumentValues(Thread &thread, ValueList &values) const {
return false;
}
Status ABISysV_mips::SetReturnValueObject(lldb::StackFrameSP &frame_sp,
lldb::ValueObjectSP &new_value_sp) {
Status error;
if (!new_value_sp) {
error.SetErrorString("Empty value object for return value.");
return error;
}
CompilerType compiler_type = new_value_sp->GetCompilerType();
if (!compiler_type) {
error.SetErrorString("Null clang type for return value.");
return error;
}
Thread *thread = frame_sp->GetThread().get();
bool is_signed;
uint32_t count;
bool is_complex;
RegisterContext *reg_ctx = thread->GetRegisterContext().get();
bool set_it_simple = false;
if (compiler_type.IsIntegerOrEnumerationType(is_signed) ||
compiler_type.IsPointerType()) {
DataExtractor data;
Status data_error;
size_t num_bytes = new_value_sp->GetData(data, data_error);
if (data_error.Fail()) {
error.SetErrorStringWithFormat(
"Couldn't convert return value to raw data: %s",
data_error.AsCString());
return error;
}
lldb::offset_t offset = 0;
if (num_bytes <= 8) {
const RegisterInfo *r2_info = reg_ctx->GetRegisterInfoByName("r2", 0);
if (num_bytes <= 4) {
uint32_t raw_value = data.GetMaxU32(&offset, num_bytes);
if (reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value))
set_it_simple = true;
} else {
uint32_t raw_value = data.GetMaxU32(&offset, 4);
if (reg_ctx->WriteRegisterFromUnsigned(r2_info, raw_value)) {
const RegisterInfo *r3_info = reg_ctx->GetRegisterInfoByName("r3", 0);
uint32_t raw_value = data.GetMaxU32(&offset, num_bytes - offset);
if (reg_ctx->WriteRegisterFromUnsigned(r3_info, raw_value))
set_it_simple = true;
}
}
} else {
error.SetErrorString("We don't support returning longer than 64 bit "
"integer values at present.");
}
} else if (compiler_type.IsFloatingPointType(count, is_complex)) {
if (is_complex)
error.SetErrorString(
"We don't support returning complex values at present");
else
error.SetErrorString(
"We don't support returning float values at present");
}
if (!set_it_simple)
error.SetErrorString(
"We only support setting simple integer return types at present.");
return error;
}
ValueObjectSP ABISysV_mips::GetReturnValueObjectSimple(
Thread &thread, CompilerType &return_compiler_type) const {
ValueObjectSP return_valobj_sp;
return return_valobj_sp;
}
ValueObjectSP ABISysV_mips::GetReturnValueObjectImpl(
Thread &thread, CompilerType &return_compiler_type) const {
ValueObjectSP return_valobj_sp;
Value value;
if (!return_compiler_type)
return return_valobj_sp;
ExecutionContext exe_ctx(thread.shared_from_this());
if (exe_ctx.GetTargetPtr() == nullptr || exe_ctx.GetProcessPtr() == nullptr)
return return_valobj_sp;
Target *target = exe_ctx.GetTargetPtr();
const ArchSpec target_arch = target->GetArchitecture();
ByteOrder target_byte_order = target_arch.GetByteOrder();
value.SetCompilerType(return_compiler_type);
uint32_t fp_flag =
target_arch.GetFlags() & lldb_private::ArchSpec::eMIPS_ABI_FP_mask;
RegisterContext *reg_ctx = thread.GetRegisterContext().get();
if (!reg_ctx)
return return_valobj_sp;
bool is_signed = false;
bool is_complex = false;
uint32_t count = 0;
// In MIPS register "r2" (v0) holds the integer function return values
const RegisterInfo *r2_reg_info = reg_ctx->GetRegisterInfoByName("r2", 0);
llvm::Optional<uint64_t> bit_width = return_compiler_type.GetBitSize(&thread);
if (!bit_width)
return return_valobj_sp;
if (return_compiler_type.IsIntegerOrEnumerationType(is_signed)) {
switch (*bit_width) {
default:
return return_valobj_sp;
case 64: {
const RegisterInfo *r3_reg_info = reg_ctx->GetRegisterInfoByName("r3", 0);
uint64_t raw_value;
raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX;
raw_value |= ((uint64_t)(reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0) &
UINT32_MAX))
<< 32;
if (is_signed)
value.GetScalar() = (int64_t)raw_value;
else
value.GetScalar() = (uint64_t)raw_value;
} break;
case 32:
if (is_signed)
value.GetScalar() = (int32_t)(
reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX);
else
value.GetScalar() = (uint32_t)(
reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT32_MAX);
break;
case 16:
if (is_signed)
value.GetScalar() = (int16_t)(
reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX);
else
value.GetScalar() = (uint16_t)(
reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT16_MAX);
break;
case 8:
if (is_signed)
value.GetScalar() = (int8_t)(
reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX);
else
value.GetScalar() = (uint8_t)(
reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0) & UINT8_MAX);
break;
}
} else if (return_compiler_type.IsPointerType()) {
uint32_t ptr =
thread.GetRegisterContext()->ReadRegisterAsUnsigned(r2_reg_info, 0) &
UINT32_MAX;
value.GetScalar() = ptr;
} else if (return_compiler_type.IsAggregateType()) {
// Structure/Vector is always passed in memory and pointer to that memory
// is passed in r2.
uint64_t mem_address = reg_ctx->ReadRegisterAsUnsigned(
reg_ctx->GetRegisterInfoByName("r2", 0), 0);
// We have got the address. Create a memory object out of it
return_valobj_sp = ValueObjectMemory::Create(
&thread, "", Address(mem_address, nullptr), return_compiler_type);
return return_valobj_sp;
} else if (return_compiler_type.IsFloatingPointType(count, is_complex)) {
if (IsSoftFloat(fp_flag)) {
uint64_t raw_value = reg_ctx->ReadRegisterAsUnsigned(r2_reg_info, 0);
if (count != 1 && is_complex)
return return_valobj_sp;
switch (*bit_width) {
default:
return return_valobj_sp;
case 32:
static_assert(sizeof(float) == sizeof(uint32_t), "");
value.GetScalar() = *((float *)(&raw_value));
break;
case 64:
static_assert(sizeof(double) == sizeof(uint64_t), "");
const RegisterInfo *r3_reg_info =
reg_ctx->GetRegisterInfoByName("r3", 0);
if (target_byte_order == eByteOrderLittle)
raw_value =
((reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0)) << 32) |
raw_value;
else
raw_value = (raw_value << 32) |
reg_ctx->ReadRegisterAsUnsigned(r3_reg_info, 0);
value.GetScalar() = *((double *)(&raw_value));
break;
}
}
else {
const RegisterInfo *f0_info = reg_ctx->GetRegisterInfoByName("f0", 0);
RegisterValue f0_value;
DataExtractor f0_data;
reg_ctx->ReadRegister(f0_info, f0_value);
f0_value.GetData(f0_data);
lldb::offset_t offset = 0;
if (count == 1 && !is_complex) {
switch (*bit_width) {
default:
return return_valobj_sp;
case 64: {
static_assert(sizeof(double) == sizeof(uint64_t), "");
const RegisterInfo *f1_info = reg_ctx->GetRegisterInfoByName("f1", 0);
RegisterValue f1_value;
DataExtractor f1_data;
reg_ctx->ReadRegister(f1_info, f1_value);
DataExtractor *copy_from_extractor = nullptr;
DataBufferSP data_sp(new DataBufferHeap(8, 0));
DataExtractor return_ext(
data_sp, target_byte_order,
target->GetArchitecture().GetAddressByteSize());
if (target_byte_order == eByteOrderLittle) {
copy_from_extractor = &f0_data;
copy_from_extractor->CopyByteOrderedData(
offset, 4, data_sp->GetBytes(), 4, target_byte_order);
f1_value.GetData(f1_data);
copy_from_extractor = &f1_data;
copy_from_extractor->CopyByteOrderedData(
offset, 4, data_sp->GetBytes() + 4, 4, target_byte_order);
} else {
copy_from_extractor = &f0_data;
copy_from_extractor->CopyByteOrderedData(
offset, 4, data_sp->GetBytes() + 4, 4, target_byte_order);
f1_value.GetData(f1_data);
copy_from_extractor = &f1_data;
copy_from_extractor->CopyByteOrderedData(
offset, 4, data_sp->GetBytes(), 4, target_byte_order);
}
value.GetScalar() = (double)return_ext.GetDouble(&offset);
break;
}
case 32: {
static_assert(sizeof(float) == sizeof(uint32_t), "");
value.GetScalar() = (float)f0_data.GetFloat(&offset);
break;
}
}
} else {
// not handled yet
return return_valobj_sp;
}
}
} else {
// not handled yet
return return_valobj_sp;
}
// If we get here, we have a valid Value, so make our ValueObject out of it:
return_valobj_sp = ValueObjectConstResult::Create(
thread.GetStackFrameAtIndex(0).get(), value, ConstString(""));
return return_valobj_sp;
}
bool ABISysV_mips::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) {
unwind_plan.Clear();
unwind_plan.SetRegisterKind(eRegisterKindDWARF);
UnwindPlan::RowSP row(new UnwindPlan::Row);
// Our Call Frame Address is the stack pointer value
Clean up register naming conventions inside lldb. "gcc" register numbers are now correctly referred to as "ehframe" register numbers. In almost all cases, ehframe and dwarf register numbers are identical (the one exception is i386 darwin where ehframe regnums were incorrect). The old "gdb" register numbers, which I incorrectly thought were stabs register numbers, are now referred to as "Process Plugin" register numbers. This is the register numbering scheme that the remote process controller stub (lldb-server, gdbserver, core file support, kdp server, remote jtag devices, etc) uses to refer to the registers. The process plugin register numbers may not be contiguous - there are remote jtag devices that have gaps in their register numbering schemes. I removed all of the enums for "gdb" register numbers that we had in lldb - these were meaningless - and I put LLDB_INVALID_REGNUM in all of the register tables for the Process Plugin regnum slot. This change is almost entirely mechnical; the one actual change in here is to ProcessGDBRemote.cpp's ParseRegisters() which parses the qXfer:features:read:target.xml response. As it parses register definitions from the xml, it will assign sequential numbers as the eRegisterKindLLDB numbers (the lldb register numberings must be sequential, without any gaps) and if the xml file specifies register numbers, those will be used as the eRegisterKindProcessPlugin register numbers (and those may have gaps). A J-Link jtag device's target.xml does contain a gap in register numbers, and it only specifies the register numbers for the registers after that gap. The device supports many different ARM boards and probably selects different part of its register file as appropriate. http://reviews.llvm.org/D12791 <rdar://problem/22623262> llvm-svn: 247741
2015-09-16 07:20:34 +08:00
row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
// The previous PC is in the RA
Clean up register naming conventions inside lldb. "gcc" register numbers are now correctly referred to as "ehframe" register numbers. In almost all cases, ehframe and dwarf register numbers are identical (the one exception is i386 darwin where ehframe regnums were incorrect). The old "gdb" register numbers, which I incorrectly thought were stabs register numbers, are now referred to as "Process Plugin" register numbers. This is the register numbering scheme that the remote process controller stub (lldb-server, gdbserver, core file support, kdp server, remote jtag devices, etc) uses to refer to the registers. The process plugin register numbers may not be contiguous - there are remote jtag devices that have gaps in their register numbering schemes. I removed all of the enums for "gdb" register numbers that we had in lldb - these were meaningless - and I put LLDB_INVALID_REGNUM in all of the register tables for the Process Plugin regnum slot. This change is almost entirely mechnical; the one actual change in here is to ProcessGDBRemote.cpp's ParseRegisters() which parses the qXfer:features:read:target.xml response. As it parses register definitions from the xml, it will assign sequential numbers as the eRegisterKindLLDB numbers (the lldb register numberings must be sequential, without any gaps) and if the xml file specifies register numbers, those will be used as the eRegisterKindProcessPlugin register numbers (and those may have gaps). A J-Link jtag device's target.xml does contain a gap in register numbers, and it only specifies the register numbers for the registers after that gap. The device supports many different ARM boards and probably selects different part of its register file as appropriate. http://reviews.llvm.org/D12791 <rdar://problem/22623262> llvm-svn: 247741
2015-09-16 07:20:34 +08:00
row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
unwind_plan.AppendRow(row);
// All other registers are the same.
unwind_plan.SetSourceName("mips at-func-entry default");
unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
Clean up register naming conventions inside lldb. "gcc" register numbers are now correctly referred to as "ehframe" register numbers. In almost all cases, ehframe and dwarf register numbers are identical (the one exception is i386 darwin where ehframe regnums were incorrect). The old "gdb" register numbers, which I incorrectly thought were stabs register numbers, are now referred to as "Process Plugin" register numbers. This is the register numbering scheme that the remote process controller stub (lldb-server, gdbserver, core file support, kdp server, remote jtag devices, etc) uses to refer to the registers. The process plugin register numbers may not be contiguous - there are remote jtag devices that have gaps in their register numbering schemes. I removed all of the enums for "gdb" register numbers that we had in lldb - these were meaningless - and I put LLDB_INVALID_REGNUM in all of the register tables for the Process Plugin regnum slot. This change is almost entirely mechnical; the one actual change in here is to ProcessGDBRemote.cpp's ParseRegisters() which parses the qXfer:features:read:target.xml response. As it parses register definitions from the xml, it will assign sequential numbers as the eRegisterKindLLDB numbers (the lldb register numberings must be sequential, without any gaps) and if the xml file specifies register numbers, those will be used as the eRegisterKindProcessPlugin register numbers (and those may have gaps). A J-Link jtag device's target.xml does contain a gap in register numbers, and it only specifies the register numbers for the registers after that gap. The device supports many different ARM boards and probably selects different part of its register file as appropriate. http://reviews.llvm.org/D12791 <rdar://problem/22623262> llvm-svn: 247741
2015-09-16 07:20:34 +08:00
unwind_plan.SetReturnAddressRegister(dwarf_r31);
return true;
}
bool ABISysV_mips::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) {
unwind_plan.Clear();
unwind_plan.SetRegisterKind(eRegisterKindDWARF);
UnwindPlan::RowSP row(new UnwindPlan::Row);
Clean up register naming conventions inside lldb. "gcc" register numbers are now correctly referred to as "ehframe" register numbers. In almost all cases, ehframe and dwarf register numbers are identical (the one exception is i386 darwin where ehframe regnums were incorrect). The old "gdb" register numbers, which I incorrectly thought were stabs register numbers, are now referred to as "Process Plugin" register numbers. This is the register numbering scheme that the remote process controller stub (lldb-server, gdbserver, core file support, kdp server, remote jtag devices, etc) uses to refer to the registers. The process plugin register numbers may not be contiguous - there are remote jtag devices that have gaps in their register numbering schemes. I removed all of the enums for "gdb" register numbers that we had in lldb - these were meaningless - and I put LLDB_INVALID_REGNUM in all of the register tables for the Process Plugin regnum slot. This change is almost entirely mechnical; the one actual change in here is to ProcessGDBRemote.cpp's ParseRegisters() which parses the qXfer:features:read:target.xml response. As it parses register definitions from the xml, it will assign sequential numbers as the eRegisterKindLLDB numbers (the lldb register numberings must be sequential, without any gaps) and if the xml file specifies register numbers, those will be used as the eRegisterKindProcessPlugin register numbers (and those may have gaps). A J-Link jtag device's target.xml does contain a gap in register numbers, and it only specifies the register numbers for the registers after that gap. The device supports many different ARM boards and probably selects different part of its register file as appropriate. http://reviews.llvm.org/D12791 <rdar://problem/22623262> llvm-svn: 247741
2015-09-16 07:20:34 +08:00
row->GetCFAValue().SetIsRegisterPlusOffset(dwarf_r29, 0);
Clean up register naming conventions inside lldb. "gcc" register numbers are now correctly referred to as "ehframe" register numbers. In almost all cases, ehframe and dwarf register numbers are identical (the one exception is i386 darwin where ehframe regnums were incorrect). The old "gdb" register numbers, which I incorrectly thought were stabs register numbers, are now referred to as "Process Plugin" register numbers. This is the register numbering scheme that the remote process controller stub (lldb-server, gdbserver, core file support, kdp server, remote jtag devices, etc) uses to refer to the registers. The process plugin register numbers may not be contiguous - there are remote jtag devices that have gaps in their register numbering schemes. I removed all of the enums for "gdb" register numbers that we had in lldb - these were meaningless - and I put LLDB_INVALID_REGNUM in all of the register tables for the Process Plugin regnum slot. This change is almost entirely mechnical; the one actual change in here is to ProcessGDBRemote.cpp's ParseRegisters() which parses the qXfer:features:read:target.xml response. As it parses register definitions from the xml, it will assign sequential numbers as the eRegisterKindLLDB numbers (the lldb register numberings must be sequential, without any gaps) and if the xml file specifies register numbers, those will be used as the eRegisterKindProcessPlugin register numbers (and those may have gaps). A J-Link jtag device's target.xml does contain a gap in register numbers, and it only specifies the register numbers for the registers after that gap. The device supports many different ARM boards and probably selects different part of its register file as appropriate. http://reviews.llvm.org/D12791 <rdar://problem/22623262> llvm-svn: 247741
2015-09-16 07:20:34 +08:00
row->SetRegisterLocationToRegister(dwarf_pc, dwarf_r31, true);
unwind_plan.AppendRow(row);
unwind_plan.SetSourceName("mips default unwind plan");
unwind_plan.SetSourcedFromCompiler(eLazyBoolNo);
unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
unwind_plan.SetUnwindPlanForSignalTrap(eLazyBoolNo);
return true;
}
bool ABISysV_mips::RegisterIsVolatile(const RegisterInfo *reg_info) {
return !RegisterIsCalleeSaved(reg_info);
}
bool ABISysV_mips::IsSoftFloat(uint32_t fp_flags) const {
return (fp_flags == lldb_private::ArchSpec::eMIPS_ABI_FP_SOFT);
}
bool ABISysV_mips::RegisterIsCalleeSaved(const RegisterInfo *reg_info) {
if (reg_info) {
// Preserved registers are :
// r16-r23, r28, r29, r30, r31
const char *name = reg_info->name;
if (name[0] == 'r') {
switch (name[1]) {
case '1':
if (name[2] == '6' || name[2] == '7' || name[2] == '8' ||
name[2] == '9') // r16-r19
return name[3] == '\0';
break;
case '2':
if (name[2] == '0' || name[2] == '1' || name[2] == '2' ||
name[2] == '3' // r20-r23
|| name[2] == '8' || name[2] == '9') // r28 and r29
return name[3] == '\0';
break;
case '3':
if (name[2] == '0' || name[2] == '1') // r30 and r31
return name[3] == '\0';
break;
}
if (name[0] == 'g' && name[1] == 'p' && name[2] == '\0') // gp (r28)
return true;
if (name[0] == 's' && name[1] == 'p' && name[2] == '\0') // sp (r29)
return true;
if (name[0] == 'f' && name[1] == 'p' && name[2] == '\0') // fp (r30)
return true;
if (name[0] == 'r' && name[1] == 'a' && name[2] == '\0') // ra (r31)
return true;
}
}
return false;
}
void ABISysV_mips::Initialize() {
PluginManager::RegisterPlugin(
GetPluginNameStatic(), "System V ABI for mips targets", CreateInstance);
}
void ABISysV_mips::Terminate() {
PluginManager::UnregisterPlugin(CreateInstance);
}
lldb_private::ConstString ABISysV_mips::GetPluginNameStatic() {
static ConstString g_name("sysv-mips");
return g_name;
}
// PluginInterface protocol
lldb_private::ConstString ABISysV_mips::GetPluginName() {
return GetPluginNameStatic();
}
uint32_t ABISysV_mips::GetPluginVersion() { return 1; }