Author: Muhammad Omair Javaid Date: 2020-12-02T03:19:43+05:00 New Revision: 78cb4562faa7315fff030593bc6bca4dc033f803
URL: https://github.com/llvm/llvm-project/commit/78cb4562faa7315fff030593bc6bca4dc033f803 DIFF: https://github.com/llvm/llvm-project/commit/78cb4562faa7315fff030593bc6bca4dc033f803.diff LOG: Make offset field optional in RegisterInfo packet for Arm64 This patch carries forward our aim to remove offset field from qRegisterInfo packets and XML register description. I have created a new function which returns if offset fields are dynamic meaning client can calculate offset on its own based on register number sequence and register size. For now this function only returns true for NativeRegisterContextLinux_arm64 but we can test this for other architectures and make it standard later. As a consequence we do not send offset field from lldb-server (arm64 for now) while other stubs dont have an offset field so it wont effect them for now. On the client side we have replaced previous offset calculation algorithm with a new scheme, where we sort all primary registers in increasing order of remote regnum and then calculate offset incrementally. This committ also includes a test to verify all of above functionality on Arm64. Reviewed By: labath Differential Revision: https://reviews.llvm.org/D91241 Added: lldb/test/API/functionalities/gdb_remote_client/TestAArch64XMLRegOffsets.py Modified: lldb/include/lldb/Host/common/NativeRegisterContext.h lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h lldb/test/API/tools/lldb-server/registers-target-xml-reading/TestGdbRemoteTargetXmlPacket.py lldb/unittests/tools/lldb-server/tests/MessageObjects.cpp lldb/unittests/tools/lldb-server/tests/TestClient.cpp Removed: ################################################################################ diff --git a/lldb/include/lldb/Host/common/NativeRegisterContext.h b/lldb/include/lldb/Host/common/NativeRegisterContext.h index a8c74358c718..f7568fe31b80 100644 --- a/lldb/include/lldb/Host/common/NativeRegisterContext.h +++ b/lldb/include/lldb/Host/common/NativeRegisterContext.h @@ -121,6 +121,8 @@ class NativeRegisterContext virtual std::vector<uint32_t> GetExpeditedRegisters(ExpeditedRegs expType) const; + virtual bool RegisterOffsetIsDynamic() const { return false; } + const RegisterInfo *GetRegisterInfoByName(llvm::StringRef reg_name, uint32_t start_idx = 0); diff --git a/lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py b/lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py index a1c420d1fa03..2f278289988c 100644 --- a/lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py +++ b/lldb/packages/Python/lldbsuite/test/tools/lldb-server/gdbremote_testcase.py @@ -664,7 +664,10 @@ def assert_valid_reg_info(self, reg_info): # Check the bare-minimum expected set of register info keys. self.assertTrue("name" in reg_info) self.assertTrue("bitsize" in reg_info) - self.assertTrue("offset" in reg_info) + + if not self.getArchitecture() == 'aarch64': + self.assertTrue("offset" in reg_info) + self.assertTrue("encoding" in reg_info) self.assertTrue("format" in reg_info) diff --git a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h index 9ba8c7699a56..344eae247e91 100644 --- a/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h +++ b/lldb/source/Plugins/Process/Linux/NativeRegisterContextLinux_arm64.h @@ -47,6 +47,8 @@ class NativeRegisterContextLinux_arm64 : public NativeRegisterContextLinux { std::vector<uint32_t> GetExpeditedRegisters(ExpeditedRegs expType) const override; + bool RegisterOffsetIsDynamic() const override { return true; } + // Hardware breakpoints/watchpoint management functions uint32_t NumSupportedHardwareBreakpoints() override; diff --git a/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp b/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp index fd9e1923104d..71e9b5ea4b2a 100644 --- a/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp +++ b/lldb/source/Plugins/Process/Utility/DynamicRegisterInfo.cpp @@ -428,9 +428,6 @@ void DynamicRegisterInfo::AddRegister(RegisterInfo ®_info, assert(set < m_set_reg_nums.size()); assert(set < m_set_names.size()); m_set_reg_nums[set].push_back(reg_num); - size_t end_reg_offset = reg_info.byte_offset + reg_info.byte_size; - if (m_reg_data_byte_size < end_reg_offset) - m_reg_data_byte_size = end_reg_offset; } void DynamicRegisterInfo::Finalize(const ArchSpec &arch) { @@ -445,6 +442,28 @@ void DynamicRegisterInfo::Finalize(const ArchSpec &arch) { m_sets[set].registers = m_set_reg_nums[set].data(); } + // We are going to create a map between remote (eRegisterKindProcessPlugin) + // and local (eRegisterKindLLDB) register numbers. This map will give us + // remote register numbers in increasing order for offset calculation. + std::map<uint32_t, uint32_t> remote_to_local_regnum_map; + for (const auto ® : m_regs) + remote_to_local_regnum_map[reg.kinds[eRegisterKindProcessPlugin]] = + reg.kinds[eRegisterKindLLDB]; + + // At this stage we manually calculate g/G packet offsets of all primary + // registers, only if target XML or qRegisterInfo packet did not send + // an offset explicitly. + uint32_t reg_offset = 0; + for (auto const ®num_pair : remote_to_local_regnum_map) { + if (m_regs[regnum_pair.second].byte_offset == LLDB_INVALID_INDEX32 && + m_regs[regnum_pair.second].value_regs == nullptr) { + m_regs[regnum_pair.second].byte_offset = reg_offset; + + reg_offset = m_regs[regnum_pair.second].byte_offset + + m_regs[regnum_pair.second].byte_size; + } + } + // sort and unique all value registers and make sure each is terminated with // LLDB_INVALID_REGNUM @@ -466,10 +485,24 @@ void DynamicRegisterInfo::Finalize(const ArchSpec &arch) { // Now update all value_regs with each register info as needed const size_t num_regs = m_regs.size(); for (size_t i = 0; i < num_regs; ++i) { - if (m_value_regs_map.find(i) != m_value_regs_map.end()) + if (m_value_regs_map.find(i) != m_value_regs_map.end()) { m_regs[i].value_regs = m_value_regs_map[i].data(); - else + // Assign a valid offset to all pseudo registers if not assigned by stub. + // Pseudo registers with value_regs list populated will share same offset + // as that of their corresponding primary register in value_regs list. + if (m_regs[i].byte_offset == LLDB_INVALID_INDEX32) { + uint32_t value_regnum = m_regs[i].value_regs[0]; + if (value_regnum != LLDB_INVALID_INDEX32) + m_regs[i].byte_offset = + GetRegisterInfoAtIndex(remote_to_local_regnum_map[value_regnum]) + ->byte_offset; + } + } else m_regs[i].value_regs = nullptr; + + reg_offset = m_regs[i].byte_offset + m_regs[i].byte_size; + if (m_reg_data_byte_size < reg_offset) + m_reg_data_byte_size = reg_offset; } // Expand all invalidation dependencies diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index 694c88c49eba..c202fc9d339f 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -1788,8 +1788,10 @@ GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo( response.PutChar(';'); } - response.Printf("bitsize:%" PRIu32 ";offset:%" PRIu32 ";", - reg_info->byte_size * 8, reg_info->byte_offset); + response.Printf("bitsize:%" PRIu32 ";", reg_info->byte_size * 8); + + if (!reg_context.RegisterOffsetIsDynamic()) + response.Printf("offset:%" PRIu32 ";", reg_info->byte_offset); llvm::StringRef encoding = GetEncodingNameOrEmpty(*reg_info); if (!encoding.empty()) @@ -2861,10 +2863,11 @@ GDBRemoteCommunicationServerLLGS::BuildTargetXml() { continue; } - response.Printf("<reg name=\"%s\" bitsize=\"%" PRIu32 "\" offset=\"%" PRIu32 - "\" regnum=\"%d\" ", - reg_info->name, reg_info->byte_size * 8, - reg_info->byte_offset, reg_index); + response.Printf("<reg name=\"%s\" bitsize=\"%" PRIu32 "\" regnum=\"%d\" ", + reg_info->name, reg_info->byte_size * 8, reg_index); + + if (!reg_context.RegisterOffsetIsDynamic()) + response.Printf("offset=\"%" PRIu32 "\" ", reg_info->byte_offset); if (reg_info->alt_name && reg_info->alt_name[0]) response.Printf("altname=\"%s\" ", reg_info->alt_name); diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 4c00e9a4c673..0d02acf1b12a 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -451,7 +451,7 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) { return; char packet[128]; - uint32_t reg_offset = 0; + uint32_t reg_offset = LLDB_INVALID_INDEX32; uint32_t reg_num = 0; for (StringExtractorGDBRemote::ResponseType response_type = StringExtractorGDBRemote::eResponse; @@ -564,7 +564,7 @@ void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) { reg_info.byte_offset = reg_offset; assert(reg_info.byte_size != 0); - reg_offset += reg_info.byte_size; + reg_offset = LLDB_INVALID_INDEX32; if (!value_regs.empty()) { value_regs.push_back(LLDB_INVALID_REGNUM); reg_info.value_regs = value_regs.data(); @@ -4276,14 +4276,14 @@ struct GdbServerTargetInfo { bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemoteDynamicRegisterInfo &dyn_reg_info, ABISP abi_sp, - uint32_t &cur_reg_num, uint32_t ®_offset) { + uint32_t ®_num_remote, uint32_t ®_num_local) { if (!feature_node) return false; + uint32_t reg_offset = LLDB_INVALID_INDEX32; feature_node.ForEachChildElementWithName( - "reg", - [&target_info, &dyn_reg_info, &cur_reg_num, ®_offset, - &abi_sp](const XMLNode ®_node) -> bool { + "reg", [&target_info, &dyn_reg_info, ®_num_remote, ®_num_local, + ®_offset, &abi_sp](const XMLNode ®_node) -> bool { std::string gdb_group; std::string gdb_type; ConstString reg_name; @@ -4305,8 +4305,8 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info, LLDB_INVALID_REGNUM, // eh_frame reg num LLDB_INVALID_REGNUM, // DWARF reg num LLDB_INVALID_REGNUM, // generic reg num - cur_reg_num, // process plugin reg num - cur_reg_num // native register number + reg_num_remote, // process plugin reg num + reg_num_local // native register number }, nullptr, nullptr, @@ -4433,7 +4433,7 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info, reg_info.byte_offset = reg_offset; assert(reg_info.byte_size != 0); - reg_offset += reg_info.byte_size; + reg_offset = LLDB_INVALID_INDEX32; if (!value_regs.empty()) { value_regs.push_back(LLDB_INVALID_REGNUM); reg_info.value_regs = value_regs.data(); @@ -4443,7 +4443,8 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info, reg_info.invalidate_regs = invalidate_regs.data(); } - ++cur_reg_num; + reg_num_remote = reg_info.kinds[eRegisterKindProcessPlugin] + 1; + ++reg_num_local; reg_info.name = reg_name.AsCString(); if (abi_sp) abi_sp->AugmentRegisterInfo(reg_info); @@ -4462,8 +4463,8 @@ bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info, // for nested register definition files. It returns true if it was able // to fetch and parse an xml file. bool ProcessGDBRemote::GetGDBServerRegisterInfoXMLAndProcess( - ArchSpec &arch_to_use, std::string xml_filename, uint32_t &cur_reg_num, - uint32_t ®_offset) { + ArchSpec &arch_to_use, std::string xml_filename, uint32_t ®_num_remote, + uint32_t ®_num_local) { // request the target xml file std::string raw; lldb_private::Status lldberr; @@ -4567,12 +4568,12 @@ bool ProcessGDBRemote::GetGDBServerRegisterInfoXMLAndProcess( ABISP abi_to_use_sp = ABI::FindPlugin(shared_from_this(), arch_to_use); for (auto &feature_node : feature_nodes) { ParseRegisters(feature_node, target_info, this->m_register_info, - abi_to_use_sp, cur_reg_num, reg_offset); + abi_to_use_sp, reg_num_remote, reg_num_local); } for (const auto &include : target_info.includes) { - GetGDBServerRegisterInfoXMLAndProcess(arch_to_use, include, cur_reg_num, - reg_offset); + GetGDBServerRegisterInfoXMLAndProcess(arch_to_use, include, + reg_num_remote, reg_num_local); } } } else { @@ -4592,9 +4593,10 @@ bool ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) { if (!m_gdb_comm.GetQXferFeaturesReadSupported()) return false; - uint32_t cur_reg_num = 0; - uint32_t reg_offset = 0; - if (GetGDBServerRegisterInfoXMLAndProcess (arch_to_use, "target.xml", cur_reg_num, reg_offset)) + uint32_t reg_num_remote = 0; + uint32_t reg_num_local = 0; + if (GetGDBServerRegisterInfoXMLAndProcess(arch_to_use, "target.xml", + reg_num_remote, reg_num_local)) this->m_register_info.Finalize(arch_to_use); return m_register_info.GetNumRegisters() > 0; diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index 5efe8b757af8..8e0a04f04eb0 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -391,8 +391,8 @@ class ProcessGDBRemote : public Process, bool GetGDBServerRegisterInfoXMLAndProcess(ArchSpec &arch_to_use, std::string xml_filename, - uint32_t &cur_reg_num, - uint32_t ®_offset); + uint32_t &cur_reg_remote, + uint32_t &cur_reg_local); // Query remote GDBServer for register information bool GetGDBServerRegisterInfo(ArchSpec &arch); diff --git a/lldb/test/API/functionalities/gdb_remote_client/TestAArch64XMLRegOffsets.py b/lldb/test/API/functionalities/gdb_remote_client/TestAArch64XMLRegOffsets.py new file mode 100644 index 000000000000..8026abc7fc18 --- /dev/null +++ b/lldb/test/API/functionalities/gdb_remote_client/TestAArch64XMLRegOffsets.py @@ -0,0 +1,151 @@ +from __future__ import print_function +from textwrap import dedent +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * +from gdbclientutils import * + + +class MyResponder(MockGDBServerResponder): + def qXferRead(self, obj, annex, offset, length): + if annex == "target.xml": + return dedent("""\ + <?xml version="1.0"?> + <target version="1.0"> + <architecture>aarch64</architecture> + <feature name="org.gnu.gdb.aarch64.core"> + <reg name="cpsr" regnum="33" bitsize="32"/> + <reg name="x0" regnum="0" bitsize="64"/> + <reg name="x1" bitsize="64"/> + <reg name="x2" bitsize="64"/> + <reg name="x3" bitsize="64"/> + <reg name="x4" bitsize="64"/> + <reg name="x5" bitsize="64"/> + <reg name="x6" bitsize="64"/> + <reg name="x7" bitsize="64"/> + <reg name="x8" bitsize="64"/> + <reg name="x9" bitsize="64"/> + <reg name="x10" bitsize="64"/> + <reg name="x11" bitsize="64"/> + <reg name="x12" bitsize="64"/> + <reg name="x13" bitsize="64"/> + <reg name="x14" bitsize="64"/> + <reg name="x15" bitsize="64"/> + <reg name="x16" bitsize="64"/> + <reg name="x17" bitsize="64"/> + <reg name="x18" bitsize="64"/> + <reg name="x19" bitsize="64"/> + <reg name="x20" bitsize="64"/> + <reg name="x21" bitsize="64"/> + <reg name="x22" bitsize="64"/> + <reg name="x23" bitsize="64"/> + <reg name="x24" bitsize="64"/> + <reg name="x25" bitsize="64"/> + <reg name="x26" bitsize="64"/> + <reg name="x27" bitsize="64"/> + <reg name="x28" bitsize="64"/> + <reg name="x29" bitsize="64"/> + <reg name="x30" bitsize="64"/> + <reg name="sp" bitsize="64"/> + <reg name="pc" bitsize="64"/> + <reg name="w0" bitsize="32" value_regnums="0" invalidate_regnums="0" regnum="34"/> + <reg name="w1" bitsize="32" value_regnums="1" invalidate_regnums="1"/> + <reg name="w2" bitsize="32" value_regnums="2" invalidate_regnums="2"/> + <reg name="w3" bitsize="32" value_regnums="3" invalidate_regnums="3"/> + <reg name="w4" bitsize="32" value_regnums="4" invalidate_regnums="4"/> + <reg name="w5" bitsize="32" value_regnums="5" invalidate_regnums="5"/> + <reg name="w6" bitsize="32" value_regnums="6" invalidate_regnums="6"/> + <reg name="w7" bitsize="32" value_regnums="7" invalidate_regnums="7"/> + <reg name="w8" bitsize="32" value_regnums="8" invalidate_regnums="8"/> + <reg name="w9" bitsize="32" value_regnums="9" invalidate_regnums="9"/> + <reg name="w10" bitsize="32" value_regnums="10" invalidate_regnums="10"/> + <reg name="w11" bitsize="32" value_regnums="11" invalidate_regnums="11"/> + <reg name="w12" bitsize="32" value_regnums="12" invalidate_regnums="12"/> + <reg name="w13" bitsize="32" value_regnums="13" invalidate_regnums="13"/> + <reg name="w14" bitsize="32" value_regnums="14" invalidate_regnums="14"/> + <reg name="w15" bitsize="32" value_regnums="15" invalidate_regnums="15"/> + <reg name="w16" bitsize="32" value_regnums="16" invalidate_regnums="16"/> + <reg name="w17" bitsize="32" value_regnums="17" invalidate_regnums="17"/> + <reg name="w18" bitsize="32" value_regnums="18" invalidate_regnums="18"/> + <reg name="w19" bitsize="32" value_regnums="19" invalidate_regnums="19"/> + <reg name="w20" bitsize="32" value_regnums="20" invalidate_regnums="20"/> + <reg name="w21" bitsize="32" value_regnums="21" invalidate_regnums="21"/> + <reg name="w22" bitsize="32" value_regnums="22" invalidate_regnums="22"/> + <reg name="w23" bitsize="32" value_regnums="23" invalidate_regnums="23"/> + <reg name="w24" bitsize="32" value_regnums="24" invalidate_regnums="24"/> + <reg name="w25" bitsize="32" value_regnums="25" invalidate_regnums="25"/> + <reg name="w26" bitsize="32" value_regnums="26" invalidate_regnums="26"/> + <reg name="w27" bitsize="32" value_regnums="27" invalidate_regnums="27"/> + <reg name="w28" bitsize="32" value_regnums="28" invalidate_regnums="28"/> + </feature> + </target> + """), False + else: + return None, + + def readRegister(self, regnum): + return "E01" + + def readRegisters(self): + return "20000000000000002000000000000000f0c154bfffff00005daa985a8fea0b48f0b954bfffff0000ad13cce570150b48380000000000000070456abfffff0000a700000000000000000000000000000001010101010101010000000000000000f0c154bfffff00000f2700000000000008e355bfffff0000080e55bfffff0000281041000000000010de61bfffff00005c05000000000000f0c154bfffff000090fcffffffff00008efcffffffff00008ffcffffffff00000000000000000000001000000000000090fcffffffff000000d06cbfffff0000f0c154bfffff00000100000000000000d0b954bfffff0000e407400000000000d0b954bfffff0000e40740000000000000100000" + + +class TestAArch64XMLRegOffsets(GDBRemoteTestBase): + + @skipIfXmlSupportMissing + @skipIfRemote + @skipIfLLVMTargetMissing("AArch64") + def test_register_gpacket_offsets(self): + """ + Test that we correctly associate the register info with the eh_frame + register numbers. + """ + + target = self.createTarget("basic_eh_frame-aarch64.yaml") + self.server.responder = MyResponder() + + if self.TraceOn(): + self.runCmd("log enable gdb-remote packets") + self.addTearDownHook( + lambda: self.runCmd("log disable gdb-remote packets")) + + process = self.connect(target) + lldbutil.expect_state_changes(self, self.dbg.GetListener(), process, + [lldb.eStateStopped]) + + registerSet = process.GetThreadAtIndex( + 0).GetFrameAtIndex(0).GetRegisters().GetValueAtIndex(0) + + reg_val_dict = { + "x0": 0x0000000000000020, "x1": 0x0000000000000020, + "x2": 0x0000ffffbf54c1f0, "x3": 0x480bea8f5a98aa5d, + "x4": 0x0000ffffbf54b9f0, "x5": 0x480b1570e5cc13ad, + "x6": 0x0000000000000038, "x7": 0x0000ffffbf6a4570, + "x8": 0x00000000000000a7, "x9": 0x0000000000000000, + "x10": 0x0101010101010101, "x11": 0x0000000000000000, + "x12": 0x0000ffffbf54c1f0, "x13": 0x000000000000270f, + "x14": 0x0000ffffbf55e308, "x15": 0x0000ffffbf550e08, + "x16": 0x0000000000411028, "x17": 0x0000ffffbf61de10, + "x18": 0x000000000000055c, "x19": 0x0000ffffbf54c1f0, + "x20": 0x0000fffffffffc90, "x21": 0x0000fffffffffc8e, + "x22": 0x0000fffffffffc8f, "x23": 0x0000000000000000, + "x24": 0x0000000000001000, "x25": 0x0000fffffffffc90, + "x26": 0x0000ffffbf6cd000, "x27": 0x0000ffffbf54c1f0, + "x28": 0x0000000000000001, "x29": 0x0000ffffbf54b9d0, + "x30": 0x00000000004007e4, "sp": 0x0000ffffbf54b9d0, + "pc": 0x00000000004007e4, "cpsr": 0x00001000, "w0": 0x00000020, + "w1": 0x00000020, "w2": 0xbf54c1f0, "w3": 0x5a98aa5d, + "w4": 0xbf54b9f0, "w5": 0xe5cc13ad, "w6": 0x00000038, + "w7": 0xbf6a4570, "w8": 0x000000a7, "w9": 0x00000000, + "w10": 0x01010101, "w11": 0x00000000, "w12": 0xbf54c1f0, + "w13": 0x0000270f, "w14": 0xbf55e308, "w15": 0xbf550e08, + "w16": 0x00411028, "w17": 0xbf61de10, "w18": 0x0000055c, + "w19": 0xbf54c1f0, "w20": 0xfffffc90, "w21": 0xfffffc8e, + "w22": 0xfffffc8f, "w23": 0x00000000, "w24": 0x00001000, + "w25": 0xfffffc90, "w26": 0xbf6cd000, "w27": 0xbf54c1f0, + "w28": 0x00000001 + } + + for reg in registerSet: + self.assertEqual(reg.GetValueAsUnsigned(), + reg_val_dict[reg.GetName()]) diff --git a/lldb/test/API/tools/lldb-server/registers-target-xml-reading/TestGdbRemoteTargetXmlPacket.py b/lldb/test/API/tools/lldb-server/registers-target-xml-reading/TestGdbRemoteTargetXmlPacket.py index 5ef074c1802c..cd14fcf8125c 100644 --- a/lldb/test/API/tools/lldb-server/registers-target-xml-reading/TestGdbRemoteTargetXmlPacket.py +++ b/lldb/test/API/tools/lldb-server/registers-target-xml-reading/TestGdbRemoteTargetXmlPacket.py @@ -65,5 +65,8 @@ def test_g_target_xml_returns_correct_data(self): self.assertEqual(q_info_reg["set"], xml_info_reg.get("group")) self.assertEqual(q_info_reg["format"], xml_info_reg.get("format")) self.assertEqual(q_info_reg["bitsize"], xml_info_reg.get("bitsize")) - self.assertEqual(q_info_reg["offset"], xml_info_reg.get("offset")) + + if not self.getArchitecture() == 'aarch64': + self.assertEqual(q_info_reg["offset"], xml_info_reg.get("offset")) + self.assertEqual(q_info_reg["encoding"], xml_info_reg.get("encoding")) diff --git a/lldb/unittests/tools/lldb-server/tests/MessageObjects.cpp b/lldb/unittests/tools/lldb-server/tests/MessageObjects.cpp index 3d1a153d2894..77bc3a5e6eef 100644 --- a/lldb/unittests/tools/lldb-server/tests/MessageObjects.cpp +++ b/lldb/unittests/tools/lldb-server/tests/MessageObjects.cpp @@ -171,7 +171,7 @@ Expected<RegisterInfo> RegisterInfoParser::create(StringRef Response) { Info.byte_size /= CHAR_BIT; if (!to_integer(Elements["offset"], Info.byte_offset, 10)) - return make_parsing_error("qRegisterInfo: offset"); + Info.byte_offset = LLDB_INVALID_INDEX32; Info.encoding = Args::StringToEncoding(Elements["encoding"]); if (Info.encoding == eEncodingInvalid) diff --git a/lldb/unittests/tools/lldb-server/tests/TestClient.cpp b/lldb/unittests/tools/lldb-server/tests/TestClient.cpp index 52428e4afc8a..752b0bb2600b 100644 --- a/lldb/unittests/tools/lldb-server/tests/TestClient.cpp +++ b/lldb/unittests/tools/lldb-server/tests/TestClient.cpp @@ -219,6 +219,7 @@ Error TestClient::qProcessInfo() { } Error TestClient::qRegisterInfos() { + uint32_t reg_offset = 0; for (unsigned int Reg = 0;; ++Reg) { std::string Message = formatv("qRegisterInfo{0:x-}", Reg).str(); Expected<RegisterInfo> InfoOr = SendMessage<RegisterInfoParser>(Message); @@ -227,6 +228,12 @@ Error TestClient::qRegisterInfos() { break; } m_register_infos.emplace_back(std::move(*InfoOr)); + + if (m_register_infos[Reg].byte_offset == LLDB_INVALID_INDEX32) + m_register_infos[Reg].byte_offset = reg_offset; + + reg_offset = + m_register_infos[Reg].byte_offset + m_register_infos[Reg].byte_size; if (m_register_infos[Reg].kinds[eRegisterKindGeneric] == LLDB_REGNUM_GENERIC_PC) m_pc_register = Reg; _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits