mgorny updated this revision to Diff 372261. mgorny added a comment. Rename the file to `_x86.cpp` to future-proof it. Replace`assert()s` with explicit skipping, we don't really want to crash on unexpected data in `target.xml`.
CHANGES SINCE LAST ACTION https://reviews.llvm.org/D108831/new/ https://reviews.llvm.org/D108831 Files: lldb/source/Plugins/Process/gdb-remote/CMakeLists.txt lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext_x86.cpp 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 @@ -151,6 +151,26 @@ self.match("register read flags", ["eflags = 0x94939291"]) + # 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"]) + # 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}"]) @@ -162,3 +182,44 @@ self.match("register read xmm1", ["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 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}"]) Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext_x86.cpp =================================================================== --- /dev/null +++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext_x86.cpp @@ -0,0 +1,189 @@ +//===-- GDBRemoteRegisterContext_x86.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 "GDBRemoteRegisterContext.h" + +using namespace lldb; +using namespace lldb_private; +using namespace lldb_private::process_gdb_remote; + +enum PartialGPRRegKind { + eRegKind32, + eRegKind16, + eRegKind8h, + eRegKind8l, + + eRegKindCount +}; + +struct PartialGPRReg { + const char *name; + + // extra storage used for pointers + uint32_t value_regs[2]; + uint32_t invalidate_regs[eRegKindCount]; +}; + +struct PartialGPRRegSet { + const char *reg64; + PartialGPRReg r[eRegKindCount]; +}; + +static std::array<PartialGPRRegSet, 16> partial_gpr_regs = {{ + {"rax", {{"eax"}, {"ax"}, {"ah"}, {"al"}}}, + {"rbx", {{"ebx"}, {"bx"}, {"bh"}, {"bl"}}}, + {"rcx", {{"ecx"}, {"cx"}, {"ch"}, {"cl"}}}, + {"rdx", {{"edx"}, {"dx"}, {"dh"}, {"dl"}}}, + {"rdi", {{"edi"}, {"di"}, {nullptr}, {"dil"}}}, + {"rsi", {{"esi"}, {"si"}, {nullptr}, {"sil"}}}, + {"rbp", {{"ebp"}, {"bp"}, {nullptr}, {"bpl"}}}, + {"rsp", {{"esp"}, {"sp"}, {nullptr}, {"spl"}}}, + {"r8", {{"r8d"}, {"r8w"}, {nullptr}, {"r8l"}}}, + {"r9", {{"r9d"}, {"r9w"}, {nullptr}, {"r9l"}}}, + {"r10", {{"r10d"}, {"r10w"}, {nullptr}, {"r10l"}}}, + {"r11", {{"r11d"}, {"r11w"}, {nullptr}, {"r11l"}}}, + {"r12", {{"r12d"}, {"r12w"}, {nullptr}, {"r12l"}}}, + {"r13", {{"r13d"}, {"r13w"}, {nullptr}, {"r13l"}}}, + {"r14", {{"r14d"}, {"r14w"}, {nullptr}, {"r14l"}}}, + {"r15", {{"r15d"}, {"r15w"}, {nullptr}, {"r15l"}}}, +}}; + +static uint32_t partial_gpr_sizes[eRegKindCount] = {4, 2, 1, 1}; + +struct MMReg { + const char *streg; + const char *name; + + // extra storage used for pointers + uint32_t value_regs[2]; +}; + +static std::array<MMReg, 16> mm_regs = {{ + {"st0", "mm0"}, + {"st1", "mm1"}, + {"st2", "mm2"}, + {"st3", "mm3"}, + {"st4", "mm4"}, + {"st5", "mm5"}, + {"st6", "mm6"}, + {"st7", "mm7"}, +}}; + +void GDBRemoteDynamicRegisterInfo::PreFinalize_x86_64() { + uint32_t max_regnum = 0; + uint32_t next_regindex = m_regs.size(); + for (const RegisterInfo ® : m_regs) + max_regnum = std::max(max_regnum, reg.kinds[eRegisterKindProcessPlugin]); + + ConstString group; + group.SetCString("partial registers"); + + for (PartialGPRRegSet &partial_regset : partial_gpr_regs) { + const RegisterInfo *reg64 = GetRegisterInfo(partial_regset.reg64); + if (!reg64 || reg64->byte_size != 8) + continue; + + const RegisterInfo *reginfo[eRegKindCount]; + uint32_t regno[eRegKindCount]; + + for (int i = 0; i < eRegKindCount; i++) { + if (!partial_regset.r[i].name) + continue; + + reginfo[i] = GetRegisterInfo(partial_regset.r[i].name); + if (reginfo[i]) + regno[i] = reginfo[i]->kinds[eRegisterKindProcessPlugin]; + else + regno[i] = ++max_regnum; + } + + for (int i = 0; i < eRegKindCount; i++) { + if (!partial_regset.r[i].name) + continue; + + partial_regset.r[i].value_regs[0] = + reg64->kinds[eRegisterKindProcessPlugin]; + partial_regset.r[i].value_regs[1] = LLDB_INVALID_REGNUM; + + int k = 0; + for (int j = 0; j < eRegKindCount; j++) { + if (i != j && partial_regset.r[j].name) + partial_regset.r[i].invalidate_regs[k++] = regno[j]; + } + partial_regset.r[i].invalidate_regs[k] = LLDB_INVALID_REGNUM; + + struct RegisterInfo new_reg { + partial_regset.r[i].name, nullptr, partial_gpr_sizes[i], + LLDB_INVALID_INDEX32, reg64->encoding, reg64->format, + { + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + LLDB_INVALID_REGNUM, regno[i], + next_regindex++, + }, + partial_regset.r[i].value_regs, partial_regset.r[i].invalidate_regs, + nullptr, 0 + }; + + ConstString name; + ConstString alt_name; + name.SetCString(new_reg.name); + AddRegister(new_reg, name, alt_name, group); + } + } + + for (MMReg &mmreg : mm_regs) { + const RegisterInfo *streg = GetRegisterInfo(mmreg.streg); + if (!streg || streg->byte_size != 10) + continue; + + if (GetRegisterInfo(mmreg.name)) + continue; + + mmreg.value_regs[0] = streg->kinds[eRegisterKindProcessPlugin]; + mmreg.value_regs[1] = LLDB_INVALID_REGNUM; + + struct RegisterInfo new_reg { + mmreg.name, nullptr, 8, LLDB_INVALID_INDEX32, eEncodingUint, eFormatHex, + { + LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, + ++max_regnum, next_regindex++, + }, + mmreg.value_regs, nullptr, nullptr, 0 + }; + + ConstString name; + ConstString alt_name; + name.SetCString(new_reg.name); + AddRegister(new_reg, name, alt_name, group); + } +} + +void GDBRemoteDynamicRegisterInfo::PostFinalize_x86_64() { + for (PartialGPRRegSet &partial_regset : partial_gpr_regs) { + if (!partial_regset.r[eRegKind8h].name) + continue; + + llvm::StringRef reg8h_name = partial_regset.r[eRegKind8h].name; + const RegisterInfo *reg8h = GetRegisterInfo(reg8h_name); + const RegisterInfo *reg8l = + GetRegisterInfo(partial_regset.r[eRegKind8l].name); + if (!reg8h || !reg8l || reg8h->byte_size != 1 || reg8l->byte_size != 1) + continue; + + // we currently have no way of indicating offset via value_regs, so we + // instead increment it after Finalize() assigns byte offsets + if (reg8h->byte_offset == reg8l->byte_offset) { + for (auto ®_info : m_regs) { + if (reg_info.name == reg8h_name) { + reg_info.byte_offset++; + break; + } + } + } + } +} Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h =================================================================== --- lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h +++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h @@ -40,6 +40,10 @@ void HardcodeARMRegisters(bool from_scratch); bool UpdateARM64SVERegistersInfos(uint64_t vg); + void Finalize(const lldb_private::ArchSpec &arch); + + void PreFinalize_x86_64(); + void PostFinalize_x86_64(); }; class GDBRemoteRegisterContext : public RegisterContext { Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp =================================================================== --- lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp +++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp @@ -1064,3 +1064,28 @@ } } } + +void GDBRemoteDynamicRegisterInfo::Finalize(const ArchSpec &arch) { + if (m_finalized) + return; + + switch (arch.GetMachine()) { + case llvm::Triple::x86_64: + PreFinalize_x86_64(); + break; + + default: + break; + } + + DynamicRegisterInfo::Finalize(arch); + + switch (arch.GetMachine()) { + case llvm::Triple::x86_64: + PostFinalize_x86_64(); + break; + + default: + break; + } +} Index: lldb/source/Plugins/Process/gdb-remote/CMakeLists.txt =================================================================== --- lldb/source/Plugins/Process/gdb-remote/CMakeLists.txt +++ lldb/source/Plugins/Process/gdb-remote/CMakeLists.txt @@ -26,6 +26,7 @@ GDBRemoteCommunicationServerLLGS.cpp GDBRemoteCommunicationServerPlatform.cpp GDBRemoteRegisterContext.cpp + GDBRemoteRegisterContext_x86.cpp ProcessGDBRemote.cpp ProcessGDBRemoteLog.cpp ThreadGDBRemote.cpp
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits