Skip to content

Commit 2712d18

Browse files
committed
[lldb] [ABI/X86] Add pseudo-registers if missing
Differential Revision: https://reviews.llvm.org/D108831
1 parent 0d1705a commit 2712d18

File tree

4 files changed

+271
-2
lines changed

4 files changed

+271
-2
lines changed

lldb/source/Plugins/ABI/X86/ABIX86.cpp

Lines changed: 144 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,16 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9-
#include "ABIX86.h"
109
#include "ABIMacOSX_i386.h"
1110
#include "ABISysV_i386.h"
1211
#include "ABISysV_x86_64.h"
1312
#include "ABIWindows_x86_64.h"
13+
#include "ABIX86.h"
1414
#include "lldb/Core/PluginManager.h"
15+
#include "lldb/Target/Process.h"
16+
17+
using namespace lldb;
18+
using namespace lldb_private;
1519

1620
LLDB_PLUGIN_DEFINE(ABIX86)
1721

@@ -28,3 +32,142 @@ void ABIX86::Terminate() {
2832
ABISysV_x86_64::Terminate();
2933
ABIWindows_x86_64::Terminate();
3034
}
35+
36+
enum class RegKind {
37+
GPR32 = 0,
38+
GPR16,
39+
GPR8h,
40+
GPR8,
41+
42+
MM = 0,
43+
};
44+
45+
typedef llvm::SmallDenseMap<llvm::StringRef,
46+
llvm::SmallVector<llvm::StringRef, 4>, 16>
47+
RegisterMap;
48+
49+
static void addPartialRegisters(
50+
std::vector<DynamicRegisterInfo::Register> &regs,
51+
llvm::ArrayRef<uint32_t> base_reg_indices, const RegisterMap &reg_names,
52+
uint32_t base_size, RegKind name_index, lldb::Encoding encoding,
53+
lldb::Format format, uint32_t subreg_size, uint32_t subreg_offset = 0) {
54+
for (uint32_t base_index : base_reg_indices) {
55+
if (base_index == LLDB_INVALID_REGNUM)
56+
break;
57+
assert(base_index < regs.size());
58+
DynamicRegisterInfo::Register &full_reg = regs[base_index];
59+
llvm::StringRef subreg_name = reg_names.lookup(
60+
full_reg.name.GetStringRef())[static_cast<int>(name_index)];
61+
if (subreg_name.empty() || full_reg.byte_size != base_size)
62+
continue;
63+
64+
lldb_private::DynamicRegisterInfo::Register subreg{
65+
lldb_private::ConstString(subreg_name),
66+
lldb_private::ConstString(),
67+
lldb_private::ConstString("supplementary registers"),
68+
subreg_size,
69+
LLDB_INVALID_INDEX32,
70+
encoding,
71+
format,
72+
LLDB_INVALID_REGNUM,
73+
LLDB_INVALID_REGNUM,
74+
LLDB_INVALID_REGNUM,
75+
LLDB_INVALID_REGNUM,
76+
{base_index},
77+
{},
78+
subreg_offset};
79+
80+
addSupplementaryRegister(regs, subreg);
81+
}
82+
}
83+
84+
void ABIX86::AugmentRegisterInfo(
85+
std::vector<DynamicRegisterInfo::Register> &regs) {
86+
MCBasedABI::AugmentRegisterInfo(regs);
87+
88+
ProcessSP process_sp = GetProcessSP();
89+
if (!process_sp)
90+
return;
91+
92+
uint32_t gpr_base_size =
93+
process_sp->GetTarget().GetArchitecture().GetAddressByteSize();
94+
bool is64bit = gpr_base_size == 8;
95+
96+
typedef RegisterMap::value_type RegPair;
97+
#define GPR_BASE(basename) (is64bit ? "r" basename : "e" basename)
98+
RegisterMap gpr_regs{{
99+
RegPair(GPR_BASE("ax"), {"eax", "ax", "ah", "al"}),
100+
RegPair(GPR_BASE("bx"), {"ebx", "bx", "bh", "bl"}),
101+
RegPair(GPR_BASE("cx"), {"ecx", "cx", "ch", "cl"}),
102+
RegPair(GPR_BASE("dx"), {"edx", "dx", "dh", "dl"}),
103+
RegPair(GPR_BASE("si"), {"esi", "si", "", "sil"}),
104+
RegPair(GPR_BASE("di"), {"edi", "di", "", "dil"}),
105+
RegPair(GPR_BASE("bp"), {"ebp", "bp", "", "bpl"}),
106+
RegPair(GPR_BASE("sp"), {"esp", "sp", "", "spl"}),
107+
}};
108+
#undef GPR_BASE
109+
if (is64bit) {
110+
#define R(base) RegPair(base, {base "d", base "w", "", base "l"})
111+
RegisterMap amd64_regs{{
112+
R("r8"),
113+
R("r9"),
114+
R("r10"),
115+
R("r11"),
116+
R("r12"),
117+
R("r13"),
118+
R("r14"),
119+
R("r15"),
120+
}};
121+
#undef R
122+
gpr_regs.insert(amd64_regs.begin(), amd64_regs.end());
123+
}
124+
125+
RegisterMap st_regs{{
126+
RegPair("st0", {"mm0"}),
127+
RegPair("st1", {"mm1"}),
128+
RegPair("st2", {"mm2"}),
129+
RegPair("st3", {"mm3"}),
130+
RegPair("st4", {"mm4"}),
131+
RegPair("st5", {"mm5"}),
132+
RegPair("st6", {"mm6"}),
133+
RegPair("st7", {"mm7"}),
134+
}};
135+
136+
// regs from gpr_basenames, in list order
137+
std::vector<uint32_t> gpr_base_reg_indices;
138+
// st0..st7, in list order
139+
std::vector<uint32_t> st_reg_indices;
140+
// map used for fast register lookups
141+
llvm::SmallDenseSet<llvm::StringRef, 64> subreg_name_set;
142+
143+
// put all subreg names into the lookup set
144+
for (const RegisterMap &regset : {gpr_regs, st_regs}) {
145+
for (const RegPair &kv : regset)
146+
subreg_name_set.insert(kv.second.begin(), kv.second.end());
147+
}
148+
149+
for (const auto &x : llvm::enumerate(regs)) {
150+
llvm::StringRef reg_name = x.value().name.GetStringRef();
151+
// find expected base registers
152+
if (gpr_regs.find(reg_name) != gpr_regs.end())
153+
gpr_base_reg_indices.push_back(x.index());
154+
else if (st_regs.find(reg_name) != st_regs.end())
155+
st_reg_indices.push_back(x.index());
156+
// abort if at least one sub-register is already present
157+
else if (llvm::is_contained(subreg_name_set, reg_name))
158+
return;
159+
}
160+
161+
if (is64bit)
162+
addPartialRegisters(regs, gpr_base_reg_indices, gpr_regs, gpr_base_size,
163+
RegKind::GPR32, eEncodingUint, eFormatHex, 4);
164+
addPartialRegisters(regs, gpr_base_reg_indices, gpr_regs, gpr_base_size,
165+
RegKind::GPR16, eEncodingUint, eFormatHex, 2);
166+
addPartialRegisters(regs, gpr_base_reg_indices, gpr_regs, gpr_base_size,
167+
RegKind::GPR8h, eEncodingUint, eFormatHex, 1, 1);
168+
addPartialRegisters(regs, gpr_base_reg_indices, gpr_regs, gpr_base_size,
169+
RegKind::GPR8, eEncodingUint, eFormatHex, 1);
170+
171+
addPartialRegisters(regs, st_reg_indices, st_regs, 10, RegKind::MM,
172+
eEncodingUint, eFormatHex, 8);
173+
}

lldb/source/Plugins/ABI/X86/ABIX86.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ class ABIX86 : public lldb_private::MCBasedABI {
1717
static void Initialize();
1818
static void Terminate();
1919

20+
protected:
21+
void AugmentRegisterInfo(
22+
std::vector<lldb_private::DynamicRegisterInfo::Register> &regs) override;
23+
2024
private:
2125
using lldb_private::MCBasedABI::MCBasedABI;
2226
};

lldb/test/API/functionalities/gdb_remote_client/TestGDBServerTargetXML.py

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77

88
class TestGDBServerTargetXML(GDBRemoteTestBase):
9-
109
@skipIfXmlSupportMissing
1110
@skipIfRemote
1211
@skipIfLLVMTargetMissing("X86")
@@ -163,6 +162,52 @@ def haltReason(self):
163162
["xmm1 = {0x91 0x92 0x93 0x94 0x95 0x96 0x97 0x98 "
164163
"0x99 0x9a 0x9b 0x9c 0x9d 0x9e 0x9f 0xa0}"])
165164

165+
# test pseudo-registers
166+
self.filecheck("register read --all",
167+
os.path.join(os.path.dirname(__file__),
168+
"amd64-partial-regs.FileCheck"))
169+
170+
# test writing into pseudo-registers
171+
self.runCmd("register write ecx 0xfffefdfc")
172+
reg_data[0] = "fcfdfeff05060708"
173+
self.assertPacketLogContains(["G" + "".join(reg_data)])
174+
self.match("register read rcx",
175+
["rcx = 0x08070605fffefdfc"])
176+
177+
self.runCmd("register write cx 0xfbfa")
178+
reg_data[0] = "fafbfeff05060708"
179+
self.assertPacketLogContains(["G" + "".join(reg_data)])
180+
self.match("register read ecx",
181+
["ecx = 0xfffefbfa"])
182+
self.match("register read rcx",
183+
["rcx = 0x08070605fffefbfa"])
184+
185+
self.runCmd("register write ch 0xf9")
186+
reg_data[0] = "faf9feff05060708"
187+
self.assertPacketLogContains(["G" + "".join(reg_data)])
188+
self.match("register read cx",
189+
["cx = 0xf9fa"])
190+
self.match("register read ecx",
191+
["ecx = 0xfffef9fa"])
192+
self.match("register read rcx",
193+
["rcx = 0x08070605fffef9fa"])
194+
195+
self.runCmd("register write cl 0xf8")
196+
reg_data[0] = "f8f9feff05060708"
197+
self.assertPacketLogContains(["G" + "".join(reg_data)])
198+
self.match("register read cx",
199+
["cx = 0xf9f8"])
200+
self.match("register read ecx",
201+
["ecx = 0xfffef9f8"])
202+
self.match("register read rcx",
203+
["rcx = 0x08070605fffef9f8"])
204+
205+
self.runCmd("register write mm0 0xfffefdfcfbfaf9f8")
206+
reg_data[10] = "f8f9fafbfcfdfeff090a"
207+
self.assertPacketLogContains(["G" + "".join(reg_data)])
208+
self.match("register read st0",
209+
["st0 = {0xf8 0xf9 0xfa 0xfb 0xfc 0xfd 0xfe 0xff 0x09 0x0a}"])
210+
166211
@skipIfXmlSupportMissing
167212
@skipIfRemote
168213
@skipIfLLVMTargetMissing("X86")
@@ -272,11 +317,25 @@ def haltReason(self):
272317
# test generic aliases
273318
self.match("register read fp",
274319
["ebp = 0x54535251"])
320+
self.match("register read sp",
321+
["esp = 0x44434241"])
275322
self.match("register read pc",
276323
["eip = 0x84838281"])
277324
self.match("register read flags",
278325
["eflags = 0x94939291"])
279326

327+
# test pseudo-registers
328+
self.match("register read cx",
329+
["cx = 0x1211"])
330+
self.match("register read ch",
331+
["ch = 0x12"])
332+
self.match("register read cl",
333+
["cl = 0x11"])
334+
self.match("register read mm0",
335+
["mm0 = 0x0807060504030201"])
336+
self.match("register read mm1",
337+
["mm1 = 0x1817161514131211"])
338+
280339
# both stX and xmmX should be displayed as vectors
281340
self.match("register read st0",
282341
["st0 = {0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a}"])
@@ -289,6 +348,35 @@ def haltReason(self):
289348
["xmm1 = {0x91 0x92 0x93 0x94 0x95 0x96 0x97 0x98 "
290349
"0x99 0x9a 0x9b 0x9c 0x9d 0x9e 0x9f 0xa0}"])
291350

351+
# test writing into pseudo-registers
352+
self.runCmd("register write cx 0xfbfa")
353+
reg_data[1] = "fafb1314"
354+
self.assertPacketLogContains(["G" + "".join(reg_data)])
355+
self.match("register read ecx",
356+
["ecx = 0x1413fbfa"])
357+
358+
self.runCmd("register write ch 0xf9")
359+
reg_data[1] = "faf91314"
360+
self.assertPacketLogContains(["G" + "".join(reg_data)])
361+
self.match("register read cx",
362+
["cx = 0xf9fa"])
363+
self.match("register read ecx",
364+
["ecx = 0x1413f9fa"])
365+
366+
self.runCmd("register write cl 0xf8")
367+
reg_data[1] = "f8f91314"
368+
self.assertPacketLogContains(["G" + "".join(reg_data)])
369+
self.match("register read cx",
370+
["cx = 0xf9f8"])
371+
self.match("register read ecx",
372+
["ecx = 0x1413f9f8"])
373+
374+
self.runCmd("register write mm0 0xfffefdfcfbfaf9f8")
375+
reg_data[10] = "f8f9fafbfcfdfeff090a"
376+
self.assertPacketLogContains(["G" + "".join(reg_data)])
377+
self.match("register read st0",
378+
["st0 = {0xf8 0xf9 0xfa 0xfb 0xfc 0xfd 0xfe 0xff 0x09 0x0a}"])
379+
292380
@skipIfXmlSupportMissing
293381
@skipIfRemote
294382
@skipIfLLVMTargetMissing("AArch64")
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
CHECK-DAG: ecx = 0x04030201
2+
CHECK-DAG: edx = 0x14131211
3+
CHECK-DAG: esi = 0x24232221
4+
CHECK-DAG: edi = 0x34333231
5+
CHECK-DAG: ebp = 0x44434241
6+
CHECK-DAG: esp = 0x54535251
7+
CHECK-DAG: r8d = 0x64636261
8+
CHECK-DAG: r9d = 0x74737271
9+
CHECK-DAG: cx = 0x0201
10+
CHECK-DAG: dx = 0x1211
11+
CHECK-DAG: si = 0x2221
12+
CHECK-DAG: di = 0x3231
13+
CHECK-DAG: bp = 0x4241
14+
CHECK-DAG: sp = 0x5251
15+
CHECK-DAG: r8w = 0x6261
16+
CHECK-DAG: r9w = 0x7271
17+
CHECK-DAG: ch = 0x02
18+
CHECK-DAG: dh = 0x12
19+
CHECK-DAG: cl = 0x01
20+
CHECK-DAG: dl = 0x11
21+
CHECK-DAG: sil = 0x21
22+
CHECK-DAG: dil = 0x31
23+
CHECK-DAG: bpl = 0x41
24+
CHECK-DAG: spl = 0x51
25+
CHECK-DAG: r8l = 0x61
26+
CHECK-DAG: r9l = 0x71
27+
CHECK-DAG: mm0 = 0x0807060504030201
28+
CHECK-DAG: mm1 = 0x1817161514131211
29+
CHECK-DAG: mm2 = 0x2827262524232221
30+
CHECK-DAG: mm3 = 0x2827262524232221
31+
CHECK-DAG: mm4 = 0x2827262524232221
32+
CHECK-DAG: mm5 = 0x2827262524232221
33+
CHECK-DAG: mm6 = 0x2827262524232221
34+
CHECK-DAG: mm7 = 0x2827262524232221

0 commit comments

Comments
 (0)