forked from OSchip/llvm-project
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
This commit is contained in:
parent
26b8ea2e37
commit
78cb4562fa
|
@ -121,6 +121,8 @@ public:
|
|||
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);
|
||||
|
||||
|
|
|
@ -664,7 +664,10 @@ class GdbRemoteTestCaseBase(TestBase):
|
|||
# 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)
|
||||
|
||||
|
|
|
@ -47,6 +47,8 @@ public:
|
|||
std::vector<uint32_t>
|
||||
GetExpeditedRegisters(ExpeditedRegs expType) const override;
|
||||
|
||||
bool RegisterOffsetIsDynamic() const override { return true; }
|
||||
|
||||
// Hardware breakpoints/watchpoint management functions
|
||||
|
||||
uint32_t NumSupportedHardwareBreakpoints() override;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -391,8 +391,8 @@ protected:
|
|||
|
||||
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);
|
||||
|
|
|
@ -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()])
|
|
@ -65,5 +65,8 @@ class TestGdbRemoteTargetXmlPacket(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
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"))
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue