mgorny updated this revision to Diff 379652.
mgorny added a comment.
Use `ArchSpec` instead of passing hardcoded 64bit. Abort the whole process if
at least one subreg is present, eliminating all the `have*` bools.
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D108831/new/
https://reviews.llvm.org/D108831
Files:
lldb/source/Plugins/ABI/X86/ABIX86.cpp
lldb/source/Plugins/ABI/X86/ABIX86.h
lldb/test/API/functionalities/gdb_remote_client/TestGDBServerTargetXML.py
Index: lldb/test/API/functionalities/gdb_remote_client/TestGDBServerTargetXML.py
===================================================================
--- lldb/test/API/functionalities/gdb_remote_client/TestGDBServerTargetXML.py
+++ lldb/test/API/functionalities/gdb_remote_client/TestGDBServerTargetXML.py
@@ -163,6 +163,67 @@
["xmm1 = {0x91 0x92 0x93 0x94 0x95 0x96 0x97 0x98 "
"0x99 0x9a 0x9b 0x9c 0x9d 0x9e 0x9f 0xa0}"])
+ # test pseudo-registers
+ self.match("register read ecx",
+ ["ecx = 0x04030201"])
+ self.match("register read cx",
+ ["cx = 0x0201"])
+ self.match("register read ch",
+ ["ch = 0x02"])
+ self.match("register read cl",
+ ["cl = 0x01"])
+ self.match("register read r8d",
+ ["r8d = 0x64636261"])
+ self.match("register read r8w",
+ ["r8w = 0x6261"])
+ self.match("register read r8l",
+ ["r8l = 0x61"])
+ self.match("register read mm0",
+ ["mm0 = 0x0807060504030201"])
+ self.match("register read mm1",
+ ["mm1 = 0x1817161514131211"])
+
+ # 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")
@@ -272,11 +333,25 @@
# 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}"])
@@ -289,6 +364,35 @@
["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")
Index: lldb/source/Plugins/ABI/X86/ABIX86.h
===================================================================
--- lldb/source/Plugins/ABI/X86/ABIX86.h
+++ lldb/source/Plugins/ABI/X86/ABIX86.h
@@ -17,6 +17,10 @@
static void Initialize();
static void Terminate();
+protected:
+ void AugmentRegisterInfo(
+ std::vector<lldb_private::DynamicRegisterInfo::Register> ®s) override;
+
private:
using lldb_private::MCBasedABI::MCBasedABI;
};
Index: lldb/source/Plugins/ABI/X86/ABIX86.cpp
===================================================================
--- lldb/source/Plugins/ABI/X86/ABIX86.cpp
+++ lldb/source/Plugins/ABI/X86/ABIX86.cpp
@@ -6,12 +6,18 @@
//
//===----------------------------------------------------------------------===//
-#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"
+
+#include <unordered_set>
+
+using namespace lldb;
+using namespace lldb_private;
LLDB_PLUGIN_DEFINE(ABIX86)
@@ -28,3 +34,236 @@
ABISysV_x86_64::Terminate();
ABIWindows_x86_64::Terminate();
}
+
+static void addPartialRegister(std::vector<DynamicRegisterInfo::Register> ®s,
+ uint32_t full_reg_index, uint32_t full_reg_size,
+ const std::string &partial_reg_name,
+ uint32_t partial_reg_size,
+ uint32_t offset = 0,
+ lldb::Encoding encoding = eEncodingInvalid, lldb::Format format = eFormatInvalid) {
+ DynamicRegisterInfo::Register &full_reg = regs[full_reg_index];
+ if (full_reg.byte_size != full_reg_size)
+ return;
+
+ lldb_private::DynamicRegisterInfo::Register partial_reg{
+ lldb_private::ConstString(partial_reg_name),
+ lldb_private::ConstString(),
+ lldb_private::ConstString("supplementary registers"),
+ partial_reg_size,
+ LLDB_INVALID_INDEX32,
+ encoding != eEncodingInvalid ? encoding : full_reg.encoding,
+ format != eFormatInvalid ? format : full_reg.format,
+ LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM,
+ {full_reg_index},
+ {},
+ offset};
+
+ addSupplementaryRegister(regs, partial_reg);
+}
+
+struct GPRReg {
+ uint32_t base_index = LLDB_INVALID_REGNUM;
+ std::string name32;
+ std::string name16;
+ std::string name8h;
+ std::string name8;
+};
+
+struct STReg {
+ uint32_t base_index = LLDB_INVALID_REGNUM;
+ std::string name_mm;
+};
+
+void ABIX86::AugmentRegisterInfo(
+ std::vector<DynamicRegisterInfo::Register> ®s) {
+ MCBasedABI::AugmentRegisterInfo(regs);
+
+ ProcessSP process_sp = GetProcessSP();
+ if (!process_sp)
+ return;
+
+ ArchSpec arch = process_sp->GetTarget().GetArchitecture();
+ bool is64bit;
+ switch (arch.GetMachine()) {
+ case llvm::Triple::x86:
+ is64bit = false;
+ break;
+ case llvm::Triple::x86_64:
+ is64bit = true;
+ break;
+ default:
+ llvm_unreachable("unexpected arch");
+ }
+
+ std::unordered_set<std::string> gpr_basenames{
+ {"ax", "bx", "cx", "dx", "si", "di", "bp", "sp"}};
+ char gpr_base_reg_prefix = is64bit ? 'r' : 'e';
+ uint32_t gpr_base_size = is64bit ? 8 : 4;
+ // regs from gpr_basenames, in list order
+ std::array<GPRReg, 8> gpr_base_reg_indices;
+ assert(gpr_base_reg_indices.size() == gpr_basenames.size());
+ // r8..r15, sorted
+ std::array<GPRReg, 8> gpr_extra_reg_indices;
+ // st0..st7, sorted
+ std::array<STReg, 8> st_reg_indices;
+ // map used for fast register lookups
+ std::unordered_set<std::string> subreg_name_set;
+
+ // find base registers and store their indices
+ // (note that with incorrect input we could get less than 8 regs)
+ size_t new_index = 0;
+ for (const auto &x : llvm::enumerate(regs)) {
+ const char *reg_name = x.value().name.AsCString();
+ if (reg_name[0] == gpr_base_reg_prefix) {
+ // handle regs from gpr_basenames
+ auto in_basenames = gpr_basenames.find(reg_name + 1);
+ if (in_basenames != gpr_basenames.end() &&
+ new_index < gpr_base_reg_indices.size()) {
+ GPRReg ®_rec = gpr_base_reg_indices[new_index++];
+ reg_rec.base_index = x.index();
+
+ // construct derived register names
+ std::string new_regname{reg_name};
+ if (is64bit) {
+ // 32-bit e* registers
+ new_regname[0] = 'e';
+ reg_rec.name32 = new_regname;
+ subreg_name_set.insert(new_regname);
+ }
+
+ // 16-bit * registers
+ new_regname.erase(new_regname.begin());
+ reg_rec.name16 = new_regname;
+ subreg_name_set.insert(new_regname);
+
+ if (new_regname[1] == 'x') {
+ // 8-bit [a-d]h registers
+ new_regname[1] = 'h';
+ reg_rec.name8h = new_regname;
+ subreg_name_set.insert(new_regname);
+
+ // 8-bit [a-d]l registers
+ new_regname[1] = 'l';
+ reg_rec.name8 = new_regname;
+ subreg_name_set.insert(new_regname);
+ } else {
+ // 8-bit sil/dil/spl/bpl registers
+ new_regname += 'l';
+ reg_rec.name8 = new_regname;
+ subreg_name_set.insert(new_regname);
+ }
+
+ continue;
+ }
+
+ // handle r8..r15 regs
+ unsigned int suffix;
+ if (is64bit && llvm::to_integer(reg_name + 1, suffix, 10) &&
+ suffix >= 8 && suffix < 16) {
+ GPRReg ®_rec = gpr_extra_reg_indices[suffix - 8];
+ reg_rec.base_index = x.index();
+
+ // construct derived register names
+ std::string new_regname{reg_name};
+ // 32-bit r*d registers
+ new_regname += 'd';
+ reg_rec.name32 = new_regname;
+ subreg_name_set.insert(new_regname);
+
+ // 16-bit r*w registers
+ new_regname.back() = 'w';
+ reg_rec.name16 = new_regname;
+ subreg_name_set.insert(new_regname);
+
+ // 8-bit r*l registers
+ new_regname.back() = 'l';
+ reg_rec.name8 = new_regname;
+ subreg_name_set.insert(new_regname);
+
+ continue;
+ }
+ }
+
+ // st0..st7 regs
+ if (llvm::StringRef(reg_name).startswith("st")) {
+ unsigned int suffix;
+ if (llvm::to_integer(reg_name + 2, suffix, 10) && suffix < 8) {
+ STReg ®_rec = st_reg_indices[suffix];
+ reg_rec.base_index = x.index();
+
+ std::string new_regname{"mm"};
+ new_regname += llvm::utostr(suffix);
+ reg_rec.name_mm = new_regname;
+ subreg_name_set.insert(new_regname);
+
+ continue;
+ }
+ }
+ }
+
+ // abort if we have at least one existing subregister
+ for (const DynamicRegisterInfo::Register &x : regs) {
+ const char *reg_name = x.name.AsCString();
+ auto found = subreg_name_set.find(reg_name);
+ if (found != subreg_name_set.end())
+ return;
+ }
+
+ if (is64bit) {
+ // on amd64, add 32-bit e* registers
+ for (const GPRReg ® : gpr_base_reg_indices) {
+ if (reg.base_index != LLDB_INVALID_REGNUM)
+ addPartialRegister(regs, reg.base_index, gpr_base_size, reg.name32, 4);
+ }
+
+ // add 32-bit r*d registers
+ for (const GPRReg ® : gpr_extra_reg_indices) {
+ if (reg.base_index != LLDB_INVALID_REGNUM)
+ addPartialRegister(regs, reg.base_index, gpr_base_size, reg.name32, 4);
+ }
+ }
+
+ // add 16-bit * registers
+ for (const GPRReg ® : gpr_base_reg_indices) {
+ if (reg.base_index != LLDB_INVALID_REGNUM)
+ addPartialRegister(regs, reg.base_index, gpr_base_size, reg.name16, 2);
+ }
+
+ if (is64bit) {
+ // add 16-bit r*w registers
+ for (const GPRReg ® : gpr_extra_reg_indices) {
+ if (reg.base_index != LLDB_INVALID_REGNUM)
+ addPartialRegister(regs, reg.base_index, gpr_base_size, reg.name16, 2);
+ }
+ }
+
+ // add 8-bit *h registers
+ for (const GPRReg ® : gpr_base_reg_indices) {
+ if (reg.base_index != LLDB_INVALID_REGNUM && !reg.name8h.empty())
+ addPartialRegister(regs, reg.base_index, gpr_base_size, reg.name8h, 1, 1);
+ }
+
+ // add 8-bit *l registers
+ for (const GPRReg ® : gpr_base_reg_indices) {
+ if (reg.base_index != LLDB_INVALID_REGNUM)
+ addPartialRegister(regs, reg.base_index, gpr_base_size, reg.name8, 1);
+ }
+
+ if (is64bit) {
+ // add 8-bit r*l registers
+ for (const GPRReg ® : gpr_extra_reg_indices) {
+ if (reg.base_index != LLDB_INVALID_REGNUM)
+ addPartialRegister(regs, reg.base_index, gpr_base_size, reg.name8, 1);
+ }
+ }
+
+ // add mm registers
+ for (const STReg ® : st_reg_indices) {
+ if (reg.base_index != LLDB_INVALID_REGNUM)
+ addPartialRegister(regs, reg.base_index, 10, reg.name_mm, 8, 0,
+ eEncodingUint, eFormatHex);
+ }
+}
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits