diff options
author | Jonas Devlieghere <jonas@devlieghere.com> | 2019-06-27 02:03:34 +0000 |
---|---|---|
committer | Jonas Devlieghere <jonas@devlieghere.com> | 2019-06-27 02:03:34 +0000 |
commit | d661a06bed4e383a8fa2ddca5849880e27d77fa8 (patch) | |
tree | ccf36a2e1f494cf985cd033d04df84365a70333d /lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp | |
parent | 55afdeada47ec87688ecde3f81e8487e3928b9e1 (diff) | |
download | bcm5719-llvm-d661a06bed4e383a8fa2ddca5849880e27d77fa8.tar.gz bcm5719-llvm-d661a06bed4e383a8fa2ddca5849880e27d77fa8.zip |
[Reproducers] Fix flakiness and off-by-one during replay.
This fixes two replay issues that caused the tests to behave
erratically:
1. It fixes an off-by-one error, where all replies where shifted by 1
because of a `+` packet that should've been ignored.
2. It fixes another off-by-one-error, where an asynchronous ^C was
offsetting all subsequent packets. The reason is that we
'synchronize' requests and replies. In reality, a stop reply is only
sent when the process halt. During replay however, we instantly
report the stop, as the reply to packets like continue (vCont).
Both packets should be ignored, and indeed, checking the gdb-remote log,
no unexpected packets are received anymore.
Additionally, be more pedantic when it comes to unexpected packets and
return an failure form the replay server. This way we should be able to
catch these things faster in the future.
llvm-svn: 364494
Diffstat (limited to 'lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp')
-rw-r--r-- | lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp | 31 |
1 files changed, 25 insertions, 6 deletions
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp index 7d60ff50fa9..5cdf572bd5a 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationReplayServer.cpp @@ -30,6 +30,7 @@ using namespace lldb; using namespace lldb_private; using namespace lldb_private::process_gdb_remote; +/// Check if the given expected packet matches the actual packet. static bool unexpected(llvm::StringRef expected, llvm::StringRef actual) { // The 'expected' string contains the raw data, including the leading $ and // trailing checksum. The 'actual' string contains only the packet's content. @@ -48,6 +49,25 @@ static bool unexpected(llvm::StringRef expected, llvm::StringRef actual) { return true; } +/// Check if we should reply to the given packet. +static bool skip(llvm::StringRef data) { + assert(!data.empty() && "Empty packet?"); + + // We've already acknowledge the '+' packet so we're done here. + if (data == "+") + return true; + + /// Don't 't reply to ^C. We need this because of stop reply packets, which + /// are only returned when the target halts. Reproducers synchronize these + /// 'asynchronous' replies, by recording them as a regular replies to the + /// previous packet (e.g. vCont). As a result, we should ignore real + /// asynchronous requests. + if (data.data()[0] == 0x03) + return true; + + return false; +} + GDBRemoteCommunicationReplayServer::GDBRemoteCommunicationReplayServer() : GDBRemoteCommunication("gdb-replay", "gdb-replay.rx_packet"), m_async_broadcaster(nullptr, "lldb.gdb-replay.async-broadcaster"), @@ -89,9 +109,8 @@ GDBRemoteCommunicationReplayServer::GetPacketAndSendResponse( m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncContinue); - // If m_send_acks is true, we're before the handshake phase. We've already - // acknowledge the '+' packet so we're done here. - if (m_send_acks && packet.GetStringRef() == "+") + // Check if we should reply to this packet. + if (skip(packet.GetStringRef())) return PacketResult::Success; // This completes the handshake. Since m_send_acks was true, we can unset it @@ -102,9 +121,8 @@ GDBRemoteCommunicationReplayServer::GetPacketAndSendResponse( // A QEnvironment packet is sent for every environment variable. If the // number of environment variables is different during replay, the replies // become out of sync. - if (packet.GetStringRef().find("QEnvironment") == 0) { + if (packet.GetStringRef().find("QEnvironment") == 0) return SendRawPacketNoLock("$OK#9a"); - } Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); while (!m_packet_history.empty()) { @@ -112,7 +130,7 @@ GDBRemoteCommunicationReplayServer::GetPacketAndSendResponse( GDBRemoteCommunicationHistory::Entry entry = m_packet_history.back(); m_packet_history.pop_back(); - // We're handled the handshake implicitly before. Skip the packet and move + // We've handled the handshake implicitly before. Skip the packet and move // on. if (entry.packet.data == "+") continue; @@ -124,6 +142,7 @@ GDBRemoteCommunicationReplayServer::GetPacketAndSendResponse( entry.packet.data); LLDB_LOG(log, "GDBRemoteCommunicationReplayServer actual packet: '{0}'", packet.GetStringRef()); + return PacketResult::ErrorSendFailed; } // Ignore QEnvironment packets as they're handled earlier. |