Skip to content

Commit

Permalink
[lldb] [ABI/X86] Add pseudo-registers if missing
Browse files Browse the repository at this point in the history
Differential Revision: https://reviews.llvm.org/D108831
  • Loading branch information
mgorny committed Oct 15, 2021
1 parent 0d1705a commit 2712d18
Show file tree
Hide file tree
Showing 4 changed files with 271 additions and 2 deletions.
145 changes: 144 additions & 1 deletion lldb/source/Plugins/ABI/X86/ABIX86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,16 @@
//
//===----------------------------------------------------------------------===//

#include "ABIX86.h"
#include "ABIMacOSX_i386.h"
#include "ABISysV_i386.h"
#include "ABISysV_x86_64.h"
#include "ABIWindows_x86_64.h"
#include "ABIX86.h"
#include "lldb/Core/PluginManager.h"
#include "lldb/Target/Process.h"

using namespace lldb;
using namespace lldb_private;

LLDB_PLUGIN_DEFINE(ABIX86)

Expand All @@ -28,3 +32,142 @@ void ABIX86::Terminate() {
ABISysV_x86_64::Terminate();
ABIWindows_x86_64::Terminate();
}

enum class RegKind {
GPR32 = 0,
GPR16,
GPR8h,
GPR8,

MM = 0,
};

typedef llvm::SmallDenseMap<llvm::StringRef,
llvm::SmallVector<llvm::StringRef, 4>, 16>
RegisterMap;

static void addPartialRegisters(
std::vector<DynamicRegisterInfo::Register> &regs,
llvm::ArrayRef<uint32_t> base_reg_indices, const RegisterMap &reg_names,
uint32_t base_size, RegKind name_index, lldb::Encoding encoding,
lldb::Format format, uint32_t subreg_size, uint32_t subreg_offset = 0) {
for (uint32_t base_index : base_reg_indices) {
if (base_index == LLDB_INVALID_REGNUM)
break;
assert(base_index < regs.size());
DynamicRegisterInfo::Register &full_reg = regs[base_index];
llvm::StringRef subreg_name = reg_names.lookup(
full_reg.name.GetStringRef())[static_cast<int>(name_index)];
if (subreg_name.empty() || full_reg.byte_size != base_size)
continue;

lldb_private::DynamicRegisterInfo::Register subreg{
lldb_private::ConstString(subreg_name),
lldb_private::ConstString(),
lldb_private::ConstString("supplementary registers"),
subreg_size,
LLDB_INVALID_INDEX32,
encoding,
format,
LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM,
LLDB_INVALID_REGNUM,
{base_index},
{},
subreg_offset};

addSupplementaryRegister(regs, subreg);
}
}

void ABIX86::AugmentRegisterInfo(
std::vector<DynamicRegisterInfo::Register> &regs) {
MCBasedABI::AugmentRegisterInfo(regs);

ProcessSP process_sp = GetProcessSP();
if (!process_sp)
return;

uint32_t gpr_base_size =
process_sp->GetTarget().GetArchitecture().GetAddressByteSize();
bool is64bit = gpr_base_size == 8;

typedef RegisterMap::value_type RegPair;
#define GPR_BASE(basename) (is64bit ? "r" basename : "e" basename)
RegisterMap gpr_regs{{
RegPair(GPR_BASE("ax"), {"eax", "ax", "ah", "al"}),
RegPair(GPR_BASE("bx"), {"ebx", "bx", "bh", "bl"}),
RegPair(GPR_BASE("cx"), {"ecx", "cx", "ch", "cl"}),
RegPair(GPR_BASE("dx"), {"edx", "dx", "dh", "dl"}),
RegPair(GPR_BASE("si"), {"esi", "si", "", "sil"}),
RegPair(GPR_BASE("di"), {"edi", "di", "", "dil"}),
RegPair(GPR_BASE("bp"), {"ebp", "bp", "", "bpl"}),
RegPair(GPR_BASE("sp"), {"esp", "sp", "", "spl"}),
}};
#undef GPR_BASE
if (is64bit) {
#define R(base) RegPair(base, {base "d", base "w", "", base "l"})
RegisterMap amd64_regs{{
R("r8"),
R("r9"),
R("r10"),
R("r11"),
R("r12"),
R("r13"),
R("r14"),
R("r15"),
}};
#undef R
gpr_regs.insert(amd64_regs.begin(), amd64_regs.end());
}

RegisterMap st_regs{{
RegPair("st0", {"mm0"}),
RegPair("st1", {"mm1"}),
RegPair("st2", {"mm2"}),
RegPair("st3", {"mm3"}),
RegPair("st4", {"mm4"}),
RegPair("st5", {"mm5"}),
RegPair("st6", {"mm6"}),
RegPair("st7", {"mm7"}),
}};

// regs from gpr_basenames, in list order
std::vector<uint32_t> gpr_base_reg_indices;
// st0..st7, in list order
std::vector<uint32_t> st_reg_indices;
// map used for fast register lookups
llvm::SmallDenseSet<llvm::StringRef, 64> subreg_name_set;

// put all subreg names into the lookup set
for (const RegisterMap &regset : {gpr_regs, st_regs}) {
for (const RegPair &kv : regset)
subreg_name_set.insert(kv.second.begin(), kv.second.end());
}

for (const auto &x : llvm::enumerate(regs)) {
llvm::StringRef reg_name = x.value().name.GetStringRef();
// find expected base registers
if (gpr_regs.find(reg_name) != gpr_regs.end())
gpr_base_reg_indices.push_back(x.index());
else if (st_regs.find(reg_name) != st_regs.end())
st_reg_indices.push_back(x.index());
// abort if at least one sub-register is already present
else if (llvm::is_contained(subreg_name_set, reg_name))
return;
}

if (is64bit)
addPartialRegisters(regs, gpr_base_reg_indices, gpr_regs, gpr_base_size,
RegKind::GPR32, eEncodingUint, eFormatHex, 4);
addPartialRegisters(regs, gpr_base_reg_indices, gpr_regs, gpr_base_size,
RegKind::GPR16, eEncodingUint, eFormatHex, 2);
addPartialRegisters(regs, gpr_base_reg_indices, gpr_regs, gpr_base_size,
RegKind::GPR8h, eEncodingUint, eFormatHex, 1, 1);
addPartialRegisters(regs, gpr_base_reg_indices, gpr_regs, gpr_base_size,
RegKind::GPR8, eEncodingUint, eFormatHex, 1);

addPartialRegisters(regs, st_reg_indices, st_regs, 10, RegKind::MM,
eEncodingUint, eFormatHex, 8);
}
4 changes: 4 additions & 0 deletions lldb/source/Plugins/ABI/X86/ABIX86.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ class ABIX86 : public lldb_private::MCBasedABI {
static void Initialize();
static void Terminate();

protected:
void AugmentRegisterInfo(
std::vector<lldb_private::DynamicRegisterInfo::Register> &regs) override;

private:
using lldb_private::MCBasedABI::MCBasedABI;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@


class TestGDBServerTargetXML(GDBRemoteTestBase):

@skipIfXmlSupportMissing
@skipIfRemote
@skipIfLLVMTargetMissing("X86")
Expand Down Expand Up @@ -163,6 +162,52 @@ def haltReason(self):
["xmm1 = {0x91 0x92 0x93 0x94 0x95 0x96 0x97 0x98 "
"0x99 0x9a 0x9b 0x9c 0x9d 0x9e 0x9f 0xa0}"])

# test pseudo-registers
self.filecheck("register read --all",
os.path.join(os.path.dirname(__file__),
"amd64-partial-regs.FileCheck"))

# test writing into pseudo-registers
self.runCmd("register write ecx 0xfffefdfc")
reg_data[0] = "fcfdfeff05060708"
self.assertPacketLogContains(["G" + "".join(reg_data)])
self.match("register read rcx",
["rcx = 0x08070605fffefdfc"])

self.runCmd("register write cx 0xfbfa")
reg_data[0] = "fafbfeff05060708"
self.assertPacketLogContains(["G" + "".join(reg_data)])
self.match("register read ecx",
["ecx = 0xfffefbfa"])
self.match("register read rcx",
["rcx = 0x08070605fffefbfa"])

self.runCmd("register write ch 0xf9")
reg_data[0] = "faf9feff05060708"
self.assertPacketLogContains(["G" + "".join(reg_data)])
self.match("register read cx",
["cx = 0xf9fa"])
self.match("register read ecx",
["ecx = 0xfffef9fa"])
self.match("register read rcx",
["rcx = 0x08070605fffef9fa"])

self.runCmd("register write cl 0xf8")
reg_data[0] = "f8f9feff05060708"
self.assertPacketLogContains(["G" + "".join(reg_data)])
self.match("register read cx",
["cx = 0xf9f8"])
self.match("register read ecx",
["ecx = 0xfffef9f8"])
self.match("register read rcx",
["rcx = 0x08070605fffef9f8"])

self.runCmd("register write mm0 0xfffefdfcfbfaf9f8")
reg_data[10] = "f8f9fafbfcfdfeff090a"
self.assertPacketLogContains(["G" + "".join(reg_data)])
self.match("register read st0",
["st0 = {0xf8 0xf9 0xfa 0xfb 0xfc 0xfd 0xfe 0xff 0x09 0x0a}"])

@skipIfXmlSupportMissing
@skipIfRemote
@skipIfLLVMTargetMissing("X86")
Expand Down Expand Up @@ -272,11 +317,25 @@ def haltReason(self):
# test generic aliases
self.match("register read fp",
["ebp = 0x54535251"])
self.match("register read sp",
["esp = 0x44434241"])
self.match("register read pc",
["eip = 0x84838281"])
self.match("register read flags",
["eflags = 0x94939291"])

# test pseudo-registers
self.match("register read cx",
["cx = 0x1211"])
self.match("register read ch",
["ch = 0x12"])
self.match("register read cl",
["cl = 0x11"])
self.match("register read mm0",
["mm0 = 0x0807060504030201"])
self.match("register read mm1",
["mm1 = 0x1817161514131211"])

# both stX and xmmX should be displayed as vectors
self.match("register read st0",
["st0 = {0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a}"])
Expand All @@ -289,6 +348,35 @@ def haltReason(self):
["xmm1 = {0x91 0x92 0x93 0x94 0x95 0x96 0x97 0x98 "
"0x99 0x9a 0x9b 0x9c 0x9d 0x9e 0x9f 0xa0}"])

# test writing into pseudo-registers
self.runCmd("register write cx 0xfbfa")
reg_data[1] = "fafb1314"
self.assertPacketLogContains(["G" + "".join(reg_data)])
self.match("register read ecx",
["ecx = 0x1413fbfa"])

self.runCmd("register write ch 0xf9")
reg_data[1] = "faf91314"
self.assertPacketLogContains(["G" + "".join(reg_data)])
self.match("register read cx",
["cx = 0xf9fa"])
self.match("register read ecx",
["ecx = 0x1413f9fa"])

self.runCmd("register write cl 0xf8")
reg_data[1] = "f8f91314"
self.assertPacketLogContains(["G" + "".join(reg_data)])
self.match("register read cx",
["cx = 0xf9f8"])
self.match("register read ecx",
["ecx = 0x1413f9f8"])

self.runCmd("register write mm0 0xfffefdfcfbfaf9f8")
reg_data[10] = "f8f9fafbfcfdfeff090a"
self.assertPacketLogContains(["G" + "".join(reg_data)])
self.match("register read st0",
["st0 = {0xf8 0xf9 0xfa 0xfb 0xfc 0xfd 0xfe 0xff 0x09 0x0a}"])

@skipIfXmlSupportMissing
@skipIfRemote
@skipIfLLVMTargetMissing("AArch64")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
CHECK-DAG: ecx = 0x04030201
CHECK-DAG: edx = 0x14131211
CHECK-DAG: esi = 0x24232221
CHECK-DAG: edi = 0x34333231
CHECK-DAG: ebp = 0x44434241
CHECK-DAG: esp = 0x54535251
CHECK-DAG: r8d = 0x64636261
CHECK-DAG: r9d = 0x74737271
CHECK-DAG: cx = 0x0201
CHECK-DAG: dx = 0x1211
CHECK-DAG: si = 0x2221
CHECK-DAG: di = 0x3231
CHECK-DAG: bp = 0x4241
CHECK-DAG: sp = 0x5251
CHECK-DAG: r8w = 0x6261
CHECK-DAG: r9w = 0x7271
CHECK-DAG: ch = 0x02
CHECK-DAG: dh = 0x12
CHECK-DAG: cl = 0x01
CHECK-DAG: dl = 0x11
CHECK-DAG: sil = 0x21
CHECK-DAG: dil = 0x31
CHECK-DAG: bpl = 0x41
CHECK-DAG: spl = 0x51
CHECK-DAG: r8l = 0x61
CHECK-DAG: r9l = 0x71
CHECK-DAG: mm0 = 0x0807060504030201
CHECK-DAG: mm1 = 0x1817161514131211
CHECK-DAG: mm2 = 0x2827262524232221
CHECK-DAG: mm3 = 0x2827262524232221
CHECK-DAG: mm4 = 0x2827262524232221
CHECK-DAG: mm5 = 0x2827262524232221
CHECK-DAG: mm6 = 0x2827262524232221
CHECK-DAG: mm7 = 0x2827262524232221

0 comments on commit 2712d18

Please sign in to comment.