Author: Michał Górny Date: 2021-09-13T13:05:06+02:00 New Revision: 8567f4d4b9a79f041406026011fb8151b24b8c99
URL: https://github.com/llvm/llvm-project/commit/8567f4d4b9a79f041406026011fb8151b24b8c99 DIFF: https://github.com/llvm/llvm-project/commit/8567f4d4b9a79f041406026011fb8151b24b8c99.diff LOG: [lldb] Support querying registers via generic names without alt_names Update GetRegisterInfoByName() methods to support getting registers by a generic name independently of alt_name entries in the register context. This makes it possible to use generic names when interacting with gdbserver (that does not supply alt_names). It also makes it possible to remove some of the duplicated information from register context declarations and/or use alt_names for another purpose. Differential Revision: https://reviews.llvm.org/D108554 Added: lldb/test/API/functionalities/gdb_remote_client/TestGDBServerTargetXML.py Modified: lldb/include/lldb/Core/ValueObjectRegister.h lldb/source/API/SBFrame.cpp lldb/source/Core/ValueObjectRegister.cpp lldb/source/Host/common/NativeRegisterContext.cpp lldb/source/Target/RegisterContext.cpp Removed: ################################################################################ diff --git a/lldb/include/lldb/Core/ValueObjectRegister.h b/lldb/include/lldb/Core/ValueObjectRegister.h index e210b36d2a45b..20a7411b6fdee 100644 --- a/lldb/include/lldb/Core/ValueObjectRegister.h +++ b/lldb/include/lldb/Core/ValueObjectRegister.h @@ -84,7 +84,7 @@ class ValueObjectRegister : public ValueObject { static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope, lldb::RegisterContextSP ®_ctx_sp, - uint32_t reg_num); + const RegisterInfo *reg_info); llvm::Optional<uint64_t> GetByteSize() override; @@ -119,15 +119,16 @@ class ValueObjectRegister : public ValueObject { CompilerType m_compiler_type; private: - void ConstructObject(uint32_t reg_num); + void ConstructObject(const RegisterInfo *reg_info); friend class ValueObjectRegisterSet; ValueObjectRegister(ValueObject &parent, lldb::RegisterContextSP ®_ctx_sp, - uint32_t reg_num); + const RegisterInfo *reg_info); ValueObjectRegister(ExecutionContextScope *exe_scope, ValueObjectManager &manager, - lldb::RegisterContextSP ®_ctx_sp, uint32_t reg_num); + lldb::RegisterContextSP ®_ctx_sp, + const RegisterInfo *reg_info); // For ValueObject only ValueObjectRegister(const ValueObjectRegister &) = delete; diff --git a/lldb/source/API/SBFrame.cpp b/lldb/source/API/SBFrame.cpp index 8f9e426e066e7..7107768ba884b 100644 --- a/lldb/source/API/SBFrame.cpp +++ b/lldb/source/API/SBFrame.cpp @@ -633,18 +633,10 @@ SBValue SBFrame::FindValue(const char *name, ValueType value_type, { RegisterContextSP reg_ctx(frame->GetRegisterContext()); if (reg_ctx) { - const uint32_t num_regs = reg_ctx->GetRegisterCount(); - for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) { - const RegisterInfo *reg_info = - reg_ctx->GetRegisterInfoAtIndex(reg_idx); - if (reg_info && - ((reg_info->name && strcasecmp(reg_info->name, name) == 0) || - (reg_info->alt_name && - strcasecmp(reg_info->alt_name, name) == 0))) { - value_sp = ValueObjectRegister::Create(frame, reg_ctx, reg_idx); - sb_value.SetSP(value_sp); - break; - } + if (const RegisterInfo *reg_info = + reg_ctx->GetRegisterInfoByName(name)) { + value_sp = ValueObjectRegister::Create(frame, reg_ctx, reg_info); + sb_value.SetSP(value_sp); } } } break; @@ -953,18 +945,10 @@ SBValue SBFrame::FindRegister(const char *name) { if (frame) { RegisterContextSP reg_ctx(frame->GetRegisterContext()); if (reg_ctx) { - const uint32_t num_regs = reg_ctx->GetRegisterCount(); - for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx) { - const RegisterInfo *reg_info = - reg_ctx->GetRegisterInfoAtIndex(reg_idx); - if (reg_info && - ((reg_info->name && strcasecmp(reg_info->name, name) == 0) || - (reg_info->alt_name && - strcasecmp(reg_info->alt_name, name) == 0))) { - value_sp = ValueObjectRegister::Create(frame, reg_ctx, reg_idx); - result.SetSP(value_sp); - break; - } + if (const RegisterInfo *reg_info = + reg_ctx->GetRegisterInfoByName(name)) { + value_sp = ValueObjectRegister::Create(frame, reg_ctx, reg_info); + result.SetSP(value_sp); } } } diff --git a/lldb/source/Core/ValueObjectRegister.cpp b/lldb/source/Core/ValueObjectRegister.cpp index 089fd76670801..743083a2d1eda 100644 --- a/lldb/source/Core/ValueObjectRegister.cpp +++ b/lldb/source/Core/ValueObjectRegister.cpp @@ -118,8 +118,9 @@ ValueObject *ValueObjectRegisterSet::CreateChildAtIndex( if (m_reg_ctx_sp && m_reg_set) { const size_t num_children = GetNumChildren(); if (idx < num_children) - valobj = new ValueObjectRegister(*this, m_reg_ctx_sp, - m_reg_set->registers[idx]); + valobj = new ValueObjectRegister( + *this, m_reg_ctx_sp, + m_reg_ctx_sp->GetRegisterInfoAtIndex(m_reg_set->registers[idx])); } return valobj; } @@ -132,8 +133,7 @@ ValueObjectRegisterSet::GetChildMemberWithName(ConstString name, const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoByName(name.GetStringRef()); if (reg_info != nullptr) - valobj = new ValueObjectRegister(*this, m_reg_ctx_sp, - reg_info->kinds[eRegisterKindLLDB]); + valobj = new ValueObjectRegister(*this, m_reg_ctx_sp, reg_info); } if (valobj) return valobj->GetSP(); @@ -155,8 +155,7 @@ ValueObjectRegisterSet::GetIndexOfChildWithName(ConstString name) { #pragma mark - #pragma mark ValueObjectRegister -void ValueObjectRegister::ConstructObject(uint32_t reg_num) { - const RegisterInfo *reg_info = m_reg_ctx_sp->GetRegisterInfoAtIndex(reg_num); +void ValueObjectRegister::ConstructObject(const RegisterInfo *reg_info) { if (reg_info) { m_reg_info = *reg_info; if (reg_info->name) @@ -168,29 +167,29 @@ void ValueObjectRegister::ConstructObject(uint32_t reg_num) { ValueObjectRegister::ValueObjectRegister(ValueObject &parent, lldb::RegisterContextSP ®_ctx_sp, - uint32_t reg_num) + const RegisterInfo *reg_info) : ValueObject(parent), m_reg_ctx_sp(reg_ctx_sp), m_reg_info(), m_reg_value(), m_type_name(), m_compiler_type() { assert(reg_ctx_sp.get()); - ConstructObject(reg_num); + ConstructObject(reg_info); } ValueObjectSP ValueObjectRegister::Create(ExecutionContextScope *exe_scope, lldb::RegisterContextSP ®_ctx_sp, - uint32_t reg_num) { + const RegisterInfo *reg_info) { auto manager_sp = ValueObjectManager::Create(); - return (new ValueObjectRegister(exe_scope, *manager_sp, reg_ctx_sp, reg_num)) + return (new ValueObjectRegister(exe_scope, *manager_sp, reg_ctx_sp, reg_info)) ->GetSP(); } ValueObjectRegister::ValueObjectRegister(ExecutionContextScope *exe_scope, ValueObjectManager &manager, lldb::RegisterContextSP ®_ctx, - uint32_t reg_num) + const RegisterInfo *reg_info) : ValueObject(exe_scope, manager), m_reg_ctx_sp(reg_ctx), m_reg_info(), m_reg_value(), m_type_name(), m_compiler_type() { assert(reg_ctx); - ConstructObject(reg_num); + ConstructObject(reg_info); } ValueObjectRegister::~ValueObjectRegister() = default; diff --git a/lldb/source/Host/common/NativeRegisterContext.cpp b/lldb/source/Host/common/NativeRegisterContext.cpp index 04d10aba4e63a..d0afc2b47dac3 100644 --- a/lldb/source/Host/common/NativeRegisterContext.cpp +++ b/lldb/source/Host/common/NativeRegisterContext.cpp @@ -56,6 +56,17 @@ NativeRegisterContext::GetRegisterInfoByName(llvm::StringRef reg_name, if (reg_name.empty()) return nullptr; + // Generic register names take precedence over specific register names. + // For example, on x86 we want "sp" to refer to the complete RSP/ESP register + // rather than the 16-bit SP pseudo-register. + uint32_t generic_reg = Args::StringToGenericRegister(reg_name); + if (generic_reg != LLDB_INVALID_REGNUM) { + const RegisterInfo *reg_info = + GetRegisterInfo(eRegisterKindGeneric, generic_reg); + if (reg_info) + return reg_info; + } + const uint32_t num_registers = GetRegisterCount(); for (uint32_t reg = start_idx; reg < num_registers; ++reg) { const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg); @@ -64,6 +75,7 @@ NativeRegisterContext::GetRegisterInfoByName(llvm::StringRef reg_name, reg_name.equals_insensitive(reg_info->alt_name)) return reg_info; } + return nullptr; } diff --git a/lldb/source/Target/RegisterContext.cpp b/lldb/source/Target/RegisterContext.cpp index bd50a9486ef3e..0e50e650dd235 100644 --- a/lldb/source/Target/RegisterContext.cpp +++ b/lldb/source/Target/RegisterContext.cpp @@ -54,6 +54,17 @@ RegisterContext::GetRegisterInfoByName(llvm::StringRef reg_name, if (reg_name.empty()) return nullptr; + // Generic register names take precedence over specific register names. + // For example, on x86 we want "sp" to refer to the complete RSP/ESP register + // rather than the 16-bit SP pseudo-register. + uint32_t generic_reg = Args::StringToGenericRegister(reg_name); + if (generic_reg != LLDB_INVALID_REGNUM) { + const RegisterInfo *reg_info = + GetRegisterInfo(eRegisterKindGeneric, generic_reg); + if (reg_info) + return reg_info; + } + const uint32_t num_registers = GetRegisterCount(); for (uint32_t reg = start_idx; reg < num_registers; ++reg) { const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg); @@ -62,6 +73,7 @@ RegisterContext::GetRegisterInfoByName(llvm::StringRef reg_name, reg_name.equals_insensitive(reg_info->alt_name)) return reg_info; } + return nullptr; } diff --git a/lldb/test/API/functionalities/gdb_remote_client/TestGDBServerTargetXML.py b/lldb/test/API/functionalities/gdb_remote_client/TestGDBServerTargetXML.py new file mode 100644 index 0000000000000..255e36a3104a8 --- /dev/null +++ b/lldb/test/API/functionalities/gdb_remote_client/TestGDBServerTargetXML.py @@ -0,0 +1,152 @@ +from __future__ import print_function +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +from gdbclientutils import * + + +class TestGDBServerTargetXML(GDBRemoteTestBase): + + @skipIfXmlSupportMissing + @skipIfRemote + @skipIfLLVMTargetMissing("X86") + def test_x86_64_regs(self): + """Test grabbing various x86_64 registers from gdbserver.""" + reg_data = [ + "0102030405060708", # rcx + "1112131415161718", # rdx + "2122232425262728", # rsi + "3132333435363738", # rdi + "4142434445464748", # rbp + "5152535455565758", # rsp + "6162636465666768", # r8 + "7172737475767778", # r9 + "8182838485868788", # rip + "91929394", # eflags + "0102030405060708090a", # st0 + "1112131415161718191a", # st1 + ] + 6 * [ + "2122232425262728292a" # st2..st7 + ] + [ + "8182838485868788898a8b8c8d8e8f90", # xmm0 + "9192939495969798999a9b9c9d9e9fa0", # xmm1 + ] + 14 * [ + "a1a2a3a4a5a6a7a8a9aaabacadaeafb0", # xmm2..xmm15 + ] + [ + "00000000", # mxcsr + ] + [ + "b1b2b3b4b5b6b7b8b9babbbcbdbebfc0", # ymm0h + "c1c2c3c4c5c6c7c8c9cacbcccdcecfd0", # ymm1h + ] + 14 * [ + "d1d2d3d4d5d6d7d8d9dadbdcdddedfe0", # ymm2h..ymm15h + ] + + class MyResponder(MockGDBServerResponder): + def qXferRead(self, obj, annex, offset, length): + if annex == "target.xml": + return """<?xml version="1.0"?> + <!DOCTYPE feature SYSTEM "gdb-target.dtd"> + <target> + <architecture>i386:x86-64</architecture> + <osabi>GNU/Linux</osabi> + <feature name="org.gnu.gdb.i386.core"> + <reg name="rcx" bitsize="64" type="int64" regnum="2"/> + <reg name="rdx" bitsize="64" type="int64" regnum="3"/> + <reg name="rsi" bitsize="64" type="int64" regnum="4"/> + <reg name="rdi" bitsize="64" type="int64" regnum="5"/> + <reg name="rbp" bitsize="64" type="data_ptr" regnum="6"/> + <reg name="rsp" bitsize="64" type="data_ptr" regnum="7"/> + <reg name="r8" bitsize="64" type="int64" regnum="8"/> + <reg name="r9" bitsize="64" type="int64" regnum="9"/> + <reg name="rip" bitsize="64" type="code_ptr" regnum="16"/> + <reg name="eflags" bitsize="32" type="i386_eflags" regnum="17"/> + <reg name="st0" bitsize="80" type="i387_ext" regnum="24"/> + <reg name="st1" bitsize="80" type="i387_ext" regnum="25"/> + <reg name="st2" bitsize="80" type="i387_ext" regnum="26"/> + <reg name="st3" bitsize="80" type="i387_ext" regnum="27"/> + <reg name="st4" bitsize="80" type="i387_ext" regnum="28"/> + <reg name="st5" bitsize="80" type="i387_ext" regnum="29"/> + <reg name="st6" bitsize="80" type="i387_ext" regnum="30"/> + <reg name="st7" bitsize="80" type="i387_ext" regnum="31"/> + </feature> + <feature name="org.gnu.gdb.i386.sse"> + <reg name="xmm0" bitsize="128" type="vec128" regnum="40"/> + <reg name="xmm1" bitsize="128" type="vec128" regnum="41"/> + <reg name="xmm2" bitsize="128" type="vec128" regnum="42"/> + <reg name="xmm3" bitsize="128" type="vec128" regnum="43"/> + <reg name="xmm4" bitsize="128" type="vec128" regnum="44"/> + <reg name="xmm5" bitsize="128" type="vec128" regnum="45"/> + <reg name="xmm6" bitsize="128" type="vec128" regnum="46"/> + <reg name="xmm7" bitsize="128" type="vec128" regnum="47"/> + <reg name="xmm8" bitsize="128" type="vec128" regnum="48"/> + <reg name="xmm9" bitsize="128" type="vec128" regnum="49"/> + <reg name="xmm10" bitsize="128" type="vec128" regnum="50"/> + <reg name="xmm11" bitsize="128" type="vec128" regnum="51"/> + <reg name="xmm12" bitsize="128" type="vec128" regnum="52"/> + <reg name="xmm13" bitsize="128" type="vec128" regnum="53"/> + <reg name="xmm14" bitsize="128" type="vec128" regnum="54"/> + <reg name="xmm15" bitsize="128" type="vec128" regnum="55"/> + <reg name="mxcsr" bitsize="32" type="i386_mxcsr" regnum="56" group="vector"/> + </feature> + <feature name="org.gnu.gdb.i386.avx"> + <reg name="ymm0h" bitsize="128" type="uint128" regnum="60"/> + <reg name="ymm1h" bitsize="128" type="uint128" regnum="61"/> + <reg name="ymm2h" bitsize="128" type="uint128" regnum="62"/> + <reg name="ymm3h" bitsize="128" type="uint128" regnum="63"/> + <reg name="ymm4h" bitsize="128" type="uint128" regnum="64"/> + <reg name="ymm5h" bitsize="128" type="uint128" regnum="65"/> + <reg name="ymm6h" bitsize="128" type="uint128" regnum="66"/> + <reg name="ymm7h" bitsize="128" type="uint128" regnum="67"/> + <reg name="ymm8h" bitsize="128" type="uint128" regnum="68"/> + <reg name="ymm9h" bitsize="128" type="uint128" regnum="69"/> + <reg name="ymm10h" bitsize="128" type="uint128" regnum="70"/> + <reg name="ymm11h" bitsize="128" type="uint128" regnum="71"/> + <reg name="ymm12h" bitsize="128" type="uint128" regnum="72"/> + <reg name="ymm13h" bitsize="128" type="uint128" regnum="73"/> + <reg name="ymm14h" bitsize="128" type="uint128" regnum="74"/> + <reg name="ymm15h" bitsize="128" type="uint128" regnum="75"/> + </feature> + </target>""", False + else: + return None, False + + def readRegister(self, regnum): + return "" + + def readRegisters(self): + return "".join(reg_data) + + def writeRegisters(self, reg_hex): + return "OK" + + def haltReason(self): + return "T02thread:1ff0d;threads:1ff0d;thread-pcs:000000010001bc00;07:0102030405060708;10:1112131415161718;" + + self.server.responder = MyResponder() + + target = self.createTarget("basic_eh_frame.yaml") + process = self.connect(target) + lldbutil.expect_state_changes(self, self.dbg.GetListener(), process, + [lldb.eStateStopped]) + + # test generic aliases + self.match("register read arg4", + ["rcx = 0x0807060504030201"]) + self.match("register read arg3", + ["rdx = 0x1817161514131211"]) + self.match("register read arg2", + ["rsi = 0x2827262524232221"]) + self.match("register read arg1", + ["rdi = 0x3837363534333231"]) + self.match("register read fp", + ["rbp = 0x4847464544434241"]) + self.match("register read sp", + ["rsp = 0x5857565554535251"]) + self.match("register read arg5", + ["r8 = 0x6867666564636261"]) + self.match("register read arg6", + ["r9 = 0x7877767574737271"]) + self.match("register read pc", + ["rip = 0x8887868584838281"]) + self.match("register read flags", + ["eflags = 0x94939291"]) _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits