This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG536783170f08: Support GDB remote g packet partial read
(authored by omjavaid).
Herald added a project: LLDB.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D97498/new/
https://reviews.llvm.org/D97498
Files:
lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
lldb/test/API/functionalities/gdb_remote_client/TestPartialGPacket.py
Index: lldb/test/API/functionalities/gdb_remote_client/TestPartialGPacket.py
===================================================================
--- /dev/null
+++ lldb/test/API/functionalities/gdb_remote_client/TestPartialGPacket.py
@@ -0,0 +1,106 @@
+from __future__ import print_function
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+from gdbclientutils import *
+
+
+class TestPartialGPacket(GDBRemoteTestBase):
+
+ @skipIfXmlSupportMissing
+ @skipIfRemote
+ def test(self):
+ """
+ Test GDB remote fallback to 'p' packet when 'g' packet does not include all registers.
+ """
+ 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>arm</architecture>
+ <feature name="org.gnu.gdb.arm.m-profile">
+ <reg name="r0" bitsize="32" type="uint32" group="general"/>
+ <reg name="r1" bitsize="32" type="uint32" group="general"/>
+ <reg name="r2" bitsize="32" type="uint32" group="general"/>
+ <reg name="r3" bitsize="32" type="uint32" group="general"/>
+ <reg name="r4" bitsize="32" type="uint32" group="general"/>
+ <reg name="r5" bitsize="32" type="uint32" group="general"/>
+ <reg name="r6" bitsize="32" type="uint32" group="general"/>
+ <reg name="r7" bitsize="32" type="uint32" group="general"/>
+ <reg name="r8" bitsize="32" type="uint32" group="general"/>
+ <reg name="r9" bitsize="32" type="uint32" group="general"/>
+ <reg name="r10" bitsize="32" type="uint32" group="general"/>
+ <reg name="r11" bitsize="32" type="uint32" group="general"/>
+ <reg name="r12" bitsize="32" type="uint32" group="general"/>
+ <reg name="sp" bitsize="32" type="data_ptr" group="general"/>
+ <reg name="lr" bitsize="32" type="uint32" group="general"/>
+ <reg name="pc" bitsize="32" type="code_ptr" group="general"/>
+ <reg name="xpsr" bitsize="32" regnum="25" type="uint32" group="general"/>
+ <reg name="MSP" bitsize="32" regnum="26" type="uint32" group="general"/>
+ <reg name="PSP" bitsize="32" regnum="27" type="uint32" group="general"/>
+ <reg name="PRIMASK" bitsize="32" regnum="28" type="uint32" group="general"/>
+ <reg name="BASEPRI" bitsize="32" regnum="29" type="uint32" group="general"/>
+ <reg name="FAULTMASK" bitsize="32" regnum="30" type="uint32" group="general"/>
+ <reg name="CONTROL" bitsize="32" regnum="31" type="uint32" group="general"/>
+ </feature>
+ </target>""", False
+ else:
+ return None, False
+
+ def readRegister(self, regnum):
+ if regnum == 31:
+ return "cdcc8c3f00000000"
+ return "E01"
+
+ def readRegisters(self):
+ return "20000000f8360020001000002fcb0008f8360020a0360020200c0020000000000000000000000000000000000000000000000000b87f0120b7d100082ed2000800000001"
+
+ def haltReason(self):
+ return "S05"
+
+ def qfThreadInfo(self):
+ return "mdead"
+
+ def qC(self):
+ return ""
+
+ def qSupported(self, client_supported):
+ return "PacketSize=4000;qXfer:memory-map:read-;QStartNoAckMode+;qXfer:threads:read+;hwbreak+;qXfer:features:read+"
+
+ def QThreadSuffixSupported(self):
+ return "OK"
+
+ def QListThreadsInStopReply(self):
+ return "OK"
+
+ self.server.responder = MyResponder()
+ if self.TraceOn():
+ self.runCmd("log enable gdb-remote packets")
+ self.addTearDownHook(
+ lambda: self.runCmd("log disable gdb-remote packets"))
+
+ self.dbg.SetDefaultArchitecture("armv7em")
+ target = self.dbg.CreateTargetWithFileAndArch(None, None)
+
+ process = self.connect(target)
+
+ if self.TraceOn():
+ interp = self.dbg.GetCommandInterpreter()
+ result = lldb.SBCommandReturnObject()
+ interp.HandleCommand("target list", result)
+ print(result.GetOutput())
+
+ r0_valobj = process.GetThreadAtIndex(
+ 0).GetFrameAtIndex(0).FindRegister("r0")
+ self.assertEqual(r0_valobj.GetValueAsUnsigned(), 0x20)
+
+ pc_valobj = process.GetThreadAtIndex(
+ 0).GetFrameAtIndex(0).FindRegister("pc")
+ self.assertEqual(pc_valobj.GetValueAsUnsigned(), 0x0800d22e)
+
+ pc_valobj = process.GetThreadAtIndex(
+ 0).GetFrameAtIndex(0).FindRegister("CONTROL")
+ self.assertEqual(pc_valobj.GetValueAsUnsigned(), 0x3f8ccccd)
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
@@ -118,6 +118,7 @@
DataExtractor m_reg_data;
bool m_read_all_at_once;
bool m_write_all_at_once;
+ bool m_gpacket_cached;
private:
// Helper function for ReadRegisterBytes().
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
@@ -36,7 +36,7 @@
: RegisterContext(thread, concrete_frame_idx),
m_reg_info_sp(std::move(reg_info_sp)), m_reg_valid(), m_reg_data(),
m_read_all_at_once(read_all_at_once),
- m_write_all_at_once(write_all_at_once) {
+ m_write_all_at_once(write_all_at_once), m_gpacket_cached(false) {
// Resize our vector of bools to contain one bool for every register. We will
// use these boolean values to know when a register value is valid in
// m_reg_data.
@@ -57,6 +57,7 @@
}
void GDBRemoteRegisterContext::SetAllRegisterValid(bool b) {
+ m_gpacket_cached = b;
std::vector<bool>::iterator pos, end = m_reg_valid.end();
for (pos = m_reg_valid.begin(); pos != end; ++pos)
*pos = b;
@@ -200,7 +201,7 @@
const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
if (!GetRegisterIsValid(reg)) {
- if (m_read_all_at_once) {
+ if (m_read_all_at_once && !m_gpacket_cached) {
if (DataBufferSP buffer_sp =
gdb_comm.ReadAllRegisters(m_thread.GetProtocolID())) {
memcpy(const_cast<uint8_t *>(m_reg_data.GetDataStart()),
@@ -221,7 +222,10 @@
m_reg_valid[i] = false;
}
}
- return true;
+
+ m_gpacket_cached = true;
+ if (GetRegisterIsValid(reg))
+ return true;
} else {
Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_THREAD |
GDBR_LOG_PACKETS));
@@ -233,9 +237,9 @@
" bytes "
"but only got %" PRId64 " bytes.",
m_reg_data.GetByteSize(), buffer_sp->GetByteSize());
+ return false;
}
}
- return false;
}
if (reg_info->value_regs) {
// Process this composite register request by delegating to the
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits