
Although I cannot find any mention of this in the specification, both gdb and lldb agree on sending an initial + packet after establishing the connection. OTOH, gdbserver and lldb-server behavior is subtly different. While lldb-server *expects* the initial ack, and drops the connection if it is not received, gdbserver will just ignore a spurious ack at _any_ point in the connection. This patch changes lldb's behavior to match that of gdb. An ACK packet is ignored at any point in the connection (except when expecting an ACK packet, of course). This is inline with the "be strict in what you generate, and lenient in what you accept" philosophy, and also enables us to remove some special cases from the server code. I've extended the same handling to NAK (-) packets, mainly because I don't see a reason to treat them differently here. (The background here is that we had a stub which was sending spurious + packets. This bug has since been fixed, but I think this change makes sense nonetheless.) Differential Revision: https://reviews.llvm.org/D114520
88 lines
3.0 KiB
C++
88 lines
3.0 KiB
C++
//===-- GDBRemoteCommunicationServer.h --------------------------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
#ifndef LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONSERVER_H
|
|
#define LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONSERVER_H
|
|
|
|
#include <functional>
|
|
#include <map>
|
|
|
|
#include "GDBRemoteCommunication.h"
|
|
#include "lldb/lldb-private-forward.h"
|
|
|
|
#include "llvm/Support/Errc.h"
|
|
#include "llvm/Support/Error.h"
|
|
|
|
class StringExtractorGDBRemote;
|
|
|
|
namespace lldb_private {
|
|
namespace process_gdb_remote {
|
|
|
|
class ProcessGDBRemote;
|
|
|
|
class GDBRemoteCommunicationServer : public GDBRemoteCommunication {
|
|
public:
|
|
using PacketHandler =
|
|
std::function<PacketResult(StringExtractorGDBRemote &packet,
|
|
Status &error, bool &interrupt, bool &quit)>;
|
|
|
|
GDBRemoteCommunicationServer(const char *comm_name,
|
|
const char *listener_name);
|
|
|
|
~GDBRemoteCommunicationServer() override;
|
|
|
|
void
|
|
RegisterPacketHandler(StringExtractorGDBRemote::ServerPacketType packet_type,
|
|
PacketHandler handler);
|
|
|
|
PacketResult GetPacketAndSendResponse(Timeout<std::micro> timeout,
|
|
Status &error, bool &interrupt,
|
|
bool &quit);
|
|
|
|
protected:
|
|
std::map<StringExtractorGDBRemote::ServerPacketType, PacketHandler>
|
|
m_packet_handlers;
|
|
bool m_exit_now; // use in asynchronous handling to indicate process should
|
|
// exit.
|
|
|
|
bool m_send_error_strings = false; // If the client enables this then
|
|
// we will send error strings as well.
|
|
|
|
PacketResult Handle_QErrorStringEnable(StringExtractorGDBRemote &packet);
|
|
|
|
PacketResult SendErrorResponse(const Status &error);
|
|
|
|
PacketResult SendErrorResponse(llvm::Error error);
|
|
|
|
PacketResult SendUnimplementedResponse(const char *packet);
|
|
|
|
PacketResult SendErrorResponse(uint8_t error);
|
|
|
|
PacketResult SendIllFormedResponse(const StringExtractorGDBRemote &packet,
|
|
const char *error_message);
|
|
|
|
PacketResult SendOKResponse();
|
|
|
|
/// Serialize and send a JSON object response.
|
|
PacketResult SendJSONResponse(const llvm::json::Value &value);
|
|
|
|
/// Serialize and send a JSON object response, or respond with an error if the
|
|
/// input object is an \a llvm::Error.
|
|
PacketResult SendJSONResponse(llvm::Expected<llvm::json::Value> value);
|
|
|
|
private:
|
|
GDBRemoteCommunicationServer(const GDBRemoteCommunicationServer &) = delete;
|
|
const GDBRemoteCommunicationServer &
|
|
operator=(const GDBRemoteCommunicationServer &) = delete;
|
|
};
|
|
|
|
} // namespace process_gdb_remote
|
|
} // namespace lldb_private
|
|
|
|
#endif // LLDB_SOURCE_PLUGINS_PROCESS_GDB_REMOTE_GDBREMOTECOMMUNICATIONSERVER_H
|