| """ |
| Test that LLDB ignores notification packets (those beginning with '%') |
| when waiting for a response to a '$' packet. |
| |
| OpenOCD is one debug server that uses notification packets to reset |
| the connection timeout if a memory read takes too long. So that's what |
| we test here, but it should apply to any exchange. |
| """ |
| |
| import lldb |
| from lldbsuite.test.lldbtest import * |
| from lldbsuite.test.decorators import * |
| from lldbsuite.test.gdbclientutils import * |
| from lldbsuite.test.lldbgdbclient import GDBRemoteTestBase |
| |
| |
| class NotifyingServerResponder(MockGDBServerResponder): |
| def readMemory(self, addr, length): |
| return "01" * length |
| |
| |
| class NotifyingServer(MockGDBServer): |
| def __init__(self, socket): |
| self._socket = socket |
| self.responder = NotifyingServerResponder() |
| self.sent_notification = False |
| |
| def _sendPacket(self, packet: str, prefix="$"): |
| # In theory we could add notifies before all packets, but it always |
| # goes through the same code and just makes the test take longer. |
| if packet == "01010101": |
| # Send more than one to make sure we clear them all to find |
| # the real response. |
| super()._sendPacket("this_is_a_notification", prefix="%") |
| super()._sendPacket("this_is_a_2nd_notification", prefix="%") |
| self.sent_notification = True |
| |
| super()._sendPacket(packet) |
| |
| if packet == "01010101": |
| super()._sendPacket("this_is_a_3rd_notification", prefix="%") |
| |
| |
| class TestIgnoringNotifications(GDBRemoteTestBase): |
| def setUp(self): |
| TestBase.setUp(self) |
| self.server = NotifyingServer(self.server_socket_class()) |
| self.server.start() |
| |
| @skipIfLLVMTargetMissing("AArch64") |
| def test(self): |
| target = self.createTarget("basic_eh_frame-aarch64.yaml") |
| |
| if self.TraceOn(): |
| self.runCmd("log enable gdb-remote packets") |
| self.runCmd("log enable gdb-remote comm") |
| 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] |
| ) |
| |
| # Disabling cache is not required but makes debugging this test easier. |
| self.runCmd("settings set target.process.disable-memory-cache true") |
| |
| # Should succeed despite getting a notification before the real result. |
| self.expect("memory read --format hex 0x1234 0x1238", substrs=["0x01010101"]) |
| |
| # Check we didn't succeed because lldb got memory in some other way. |
| self.assertTrue(self.server.sent_notification) |