[lldb] [ABI/AArch64] Add pseudo-regs if missing
Create pseudo-registers on the AArch64 target if they are not provided by the remote server. This is the case for gdbserver. The created registers are: - 32-bit wN partials for 64-bit xN registers - double precision floating-point dN registers (overlapping with vN) - single precision floating-point sN registers (overlapping with vN) Differential Revision: https://reviews.llvm.org/D109876
This commit is contained in:
parent
1afda54f19
commit
583f67cb4e
@ -13,6 +13,8 @@
|
||||
#include "lldb/Core/PluginManager.h"
|
||||
#include "lldb/Target/Process.h"
|
||||
|
||||
#include <bitset>
|
||||
|
||||
LLDB_PLUGIN_DEFINE(ABIAArch64)
|
||||
|
||||
void ABIAArch64::Initialize() {
|
||||
@ -71,14 +73,81 @@ uint32_t ABIAArch64::GetGenericNum(llvm::StringRef name) {
|
||||
.Default(LLDB_INVALID_REGNUM);
|
||||
}
|
||||
|
||||
static void addPartialRegisters(
|
||||
std::vector<lldb_private::DynamicRegisterInfo::Register> ®s,
|
||||
llvm::ArrayRef<llvm::Optional<uint32_t>> full_reg_indices,
|
||||
uint32_t full_reg_size, const char *partial_reg_format,
|
||||
uint32_t partial_reg_size, lldb::Encoding encoding, lldb::Format format) {
|
||||
for (auto it : llvm::enumerate(full_reg_indices)) {
|
||||
llvm::Optional<uint32_t> full_reg_index = it.value();
|
||||
if (!full_reg_index ||
|
||||
regs[full_reg_index.getValue()].byte_size != full_reg_size)
|
||||
return;
|
||||
|
||||
lldb_private::DynamicRegisterInfo::Register partial_reg{
|
||||
lldb_private::ConstString(
|
||||
llvm::formatv(partial_reg_format, it.index()).str()),
|
||||
lldb_private::ConstString(),
|
||||
lldb_private::ConstString("supplementary registers"),
|
||||
partial_reg_size,
|
||||
LLDB_INVALID_INDEX32,
|
||||
encoding,
|
||||
format,
|
||||
LLDB_INVALID_REGNUM,
|
||||
LLDB_INVALID_REGNUM,
|
||||
LLDB_INVALID_REGNUM,
|
||||
LLDB_INVALID_REGNUM,
|
||||
{full_reg_index.getValue()},
|
||||
{}};
|
||||
addSupplementaryRegister(regs, partial_reg);
|
||||
}
|
||||
}
|
||||
|
||||
void ABIAArch64::AugmentRegisterInfo(
|
||||
std::vector<lldb_private::DynamicRegisterInfo::Register> ®s) {
|
||||
lldb_private::MCBasedABI::AugmentRegisterInfo(regs);
|
||||
|
||||
lldb_private::ConstString sp_string{"sp"};
|
||||
for (lldb_private::DynamicRegisterInfo::Register &info : regs) {
|
||||
|
||||
std::array<llvm::Optional<uint32_t>, 32> x_regs;
|
||||
std::array<llvm::Optional<uint32_t>, 32> v_regs;
|
||||
std::bitset<32> have_w_regs;
|
||||
std::bitset<32> have_s_regs;
|
||||
std::bitset<32> have_d_regs;
|
||||
|
||||
for (auto it : llvm::enumerate(regs)) {
|
||||
lldb_private::DynamicRegisterInfo::Register &info = it.value();
|
||||
// GDB sends x31 as "sp". Add the "x31" alt_name for convenience.
|
||||
if (info.name == sp_string && !info.alt_name)
|
||||
info.alt_name.SetCString("x31");
|
||||
|
||||
unsigned int reg_num;
|
||||
auto get_reg = [&info, ®_num](const char *prefix) {
|
||||
llvm::StringRef reg_name = info.name.GetStringRef();
|
||||
llvm::StringRef alt_name = info.alt_name.GetStringRef();
|
||||
return (reg_name.consume_front(prefix) &&
|
||||
llvm::to_integer(reg_name, reg_num, 10) && reg_num < 32) ||
|
||||
(alt_name.consume_front(prefix) &&
|
||||
llvm::to_integer(alt_name, reg_num, 10) && reg_num < 32);
|
||||
};
|
||||
|
||||
if (get_reg("x"))
|
||||
x_regs[reg_num] = it.index();
|
||||
if (get_reg("v"))
|
||||
v_regs[reg_num] = it.index();
|
||||
if (get_reg("w"))
|
||||
have_w_regs[reg_num] = true;
|
||||
if (get_reg("s"))
|
||||
have_s_regs[reg_num] = true;
|
||||
if (get_reg("d"))
|
||||
have_d_regs[reg_num] = true;
|
||||
}
|
||||
|
||||
// Create aliases for partial registers: wN for xN, and sN/dN for vN.
|
||||
addPartialRegisters(regs, x_regs, 8, "w{0}", 4, lldb::eEncodingUint,
|
||||
lldb::eFormatHex);
|
||||
addPartialRegisters(regs, v_regs, 16, "s{0}", 4, lldb::eEncodingIEEE754,
|
||||
lldb::eFormatFloat);
|
||||
addPartialRegisters(regs, v_regs, 16, "d{0}", 8, lldb::eEncodingIEEE754,
|
||||
lldb::eFormatFloat);
|
||||
}
|
||||
|
||||
@ -270,27 +270,27 @@ class TestGDBServerTargetXML(GDBRemoteTestBase):
|
||||
@skipIfLLVMTargetMissing("AArch64")
|
||||
def test_aarch64_regs(self):
|
||||
"""Test grabbing various aarch64 registers from gdbserver."""
|
||||
reg_data = [
|
||||
"0102030405060708", # x0
|
||||
"1112131415161718", # x1
|
||||
] + 27 * [
|
||||
"2122232425262728", # x2..x28
|
||||
] + [
|
||||
"3132333435363738", # x29 (fp)
|
||||
"4142434445464748", # x30 (lr)
|
||||
"5152535455565758", # x31 (sp)
|
||||
"6162636465666768", # pc
|
||||
"71727374", # cpsr
|
||||
"8182838485868788898a8b8c8d8e8f90", # v0
|
||||
"9192939495969798999a9b9c9d9e9fa0", # v1
|
||||
] + 30 * [
|
||||
"a1a2a3a4a5a6a7a8a9aaabacadaeafb0", # v2..v31
|
||||
] + [
|
||||
"00000000", # fpsr
|
||||
"00000000", # fpcr
|
||||
]
|
||||
|
||||
class MyResponder(MockGDBServerResponder):
|
||||
reg_data = (
|
||||
"0102030405060708" # x0
|
||||
"1112131415161718" # x1
|
||||
) + 27 * (
|
||||
"2122232425262728" # x2..x28
|
||||
) + (
|
||||
"3132333435363738" # x29 (fp)
|
||||
"4142434445464748" # x30 (lr)
|
||||
"5152535455565758" # x31 (sp)
|
||||
"6162636465666768" # pc
|
||||
"71727374" # cpsr
|
||||
"8182838485868788898a8b8c8d8e8f90" # v0
|
||||
"9192939495969798999a9b9c9d9e9fa0" # v1
|
||||
) + 30 * (
|
||||
"a1a2a3a4a5a6a7a8a9aaabacadaeafb0" # v2..v31
|
||||
) + (
|
||||
"00000000" # fpsr
|
||||
"00000000" # fpcr
|
||||
)
|
||||
|
||||
def qXferRead(self, obj, annex, offset, length):
|
||||
if annex == "target.xml":
|
||||
return """<?xml version="1.0"?>
|
||||
@ -377,9 +377,10 @@ class TestGDBServerTargetXML(GDBRemoteTestBase):
|
||||
return ""
|
||||
|
||||
def readRegisters(self):
|
||||
return "".join(reg_data)
|
||||
return self.reg_data
|
||||
|
||||
def writeRegisters(self, reg_hex):
|
||||
self.reg_data = reg_hex
|
||||
return "OK"
|
||||
|
||||
def haltReason(self):
|
||||
@ -429,3 +430,43 @@ class TestGDBServerTargetXML(GDBRemoteTestBase):
|
||||
["v0 = {0x81 0x82 0x83 0x84 0x85 0x86 0x87 0x88 0x89 0x8a 0x8b 0x8c 0x8d 0x8e 0x8f 0x90}"])
|
||||
self.match("register read v31",
|
||||
["v31 = {0xa1 0xa2 0xa3 0xa4 0xa5 0xa6 0xa7 0xa8 0xa9 0xaa 0xab 0xac 0xad 0xae 0xaf 0xb0}"])
|
||||
|
||||
# test partial registers
|
||||
self.match("register read w0",
|
||||
["w0 = 0x04030201"])
|
||||
self.runCmd("register write w0 0xfffefdfc")
|
||||
self.match("register read x0",
|
||||
["x0 = 0x08070605fffefdfc"])
|
||||
|
||||
self.match("register read w1",
|
||||
["w1 = 0x14131211"])
|
||||
self.runCmd("register write w1 0xefeeedec")
|
||||
self.match("register read x1",
|
||||
["x1 = 0x18171615efeeedec"])
|
||||
|
||||
self.match("register read w30",
|
||||
["w30 = 0x44434241"])
|
||||
self.runCmd("register write w30 0xdfdedddc")
|
||||
self.match("register read x30",
|
||||
["x30 = 0x48474645dfdedddc"])
|
||||
|
||||
self.match("register read w31",
|
||||
["w31 = 0x54535251"])
|
||||
self.runCmd("register write w31 0xcfcecdcc")
|
||||
self.match("register read x31",
|
||||
["sp = 0x58575655cfcecdcc"])
|
||||
|
||||
# test FPU registers (overlapping with vector registers)
|
||||
self.runCmd("register write d0 16")
|
||||
self.match("register read v0",
|
||||
["v0 = {0x00 0x00 0x00 0x00 0x00 0x00 0x30 0x40 0x89 0x8a 0x8b 0x8c 0x8d 0x8e 0x8f 0x90}"])
|
||||
self.runCmd("register write v31 '{0x00 0x00 0x00 0x00 0x00 0x00 0x50 0x40 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff}'")
|
||||
self.match("register read d31",
|
||||
["d31 = 64"])
|
||||
|
||||
self.runCmd("register write s0 32")
|
||||
self.match("register read v0",
|
||||
["v0 = {0x00 0x00 0x00 0x42 0x00 0x00 0x30 0x40 0x89 0x8a 0x8b 0x8c 0x8d 0x8e 0x8f 0x90}"])
|
||||
self.runCmd("register write v31 '{0x00 0x00 0x00 0x43 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff 0xff}'")
|
||||
self.match("register read s31",
|
||||
["s31 = 128"])
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user