The gdb-protocol spec says > Recipients should silently ignore corrupted notifications and notifications they do not understand. This changes `WaitForPacketNoLock` so that it ignores all notifications (I'm not sure about corrupted ones). An example of a notification that causes issues without this change is that OpenOCD sends `%ookeepalive:00` notifications during memory accesses. Fixes #197944
72 lines
2.6 KiB
Python
72 lines
2.6 KiB
Python
"""
|
|
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)
|