LLDB mainline
GDBRemoteCommunicationServer.cpp
Go to the documentation of this file.
1//===-- GDBRemoteCommunicationServer.cpp ----------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include <cerrno>
10
11#include "lldb/Host/Config.h"
12
14
15#include "ProcessGDBRemoteLog.h"
19#include "llvm/Support/JSON.h"
20#include <cstring>
21
22using namespace lldb;
23using namespace lldb_private;
25using namespace llvm;
26
28 : GDBRemoteCommunication(), m_exit_now(false) {
31 [this](StringExtractorGDBRemote packet, Status &error, bool &interrupt,
32 bool &quit) { return this->Handle_QErrorStringEnable(packet); });
33}
34
36
39 PacketHandler handler) {
40 m_packet_handlers[packet_type] = std::move(handler);
41}
42
45 Timeout<std::micro> timeout, Status &error, bool &interrupt, bool &quit) {
47
48 PacketResult packet_result = ReadPacket(packet, timeout, false);
49 if (packet_result == PacketResult::Success) {
51 packet.GetServerPacketType();
52 switch (packet_type) {
55 break;
56
58 error = Status::FromErrorString("invalid packet");
59 quit = true;
60 break;
61
63 packet_result = SendUnimplementedResponse(packet.GetStringRef().data());
64 break;
65
66 default:
67 auto handler_it = m_packet_handlers.find(packet_type);
68 if (handler_it == m_packet_handlers.end())
69 packet_result = SendUnimplementedResponse(packet.GetStringRef().data());
70 else
71 packet_result = handler_it->second(packet, error, interrupt, quit);
72 break;
73 }
74 } else {
75 if (!IsConnected()) {
76 error = Status::FromErrorString("lost connection");
77 quit = true;
78 } else {
79 error = Status::FromErrorString("timeout");
80 }
81 }
82
83 // Check if anything occurred that would force us to want to exit.
84 if (m_exit_now)
85 quit = true;
86
87 return packet_result;
88}
89
92 // TODO: Log the packet we aren't handling...
93 return SendPacketNoLock("");
94}
95
98 char packet[16];
99 int packet_len = ::snprintf(packet, sizeof(packet), "E%2.2x", err);
100 assert(packet_len < (int)sizeof(packet));
101 return SendPacketNoLock(llvm::StringRef(packet, packet_len));
102}
103
106 uint8_t code = error.GetType() == eErrorTypePOSIX ? error.GetError() : 0xff;
109 packet.Printf("E%2.2x;", code);
110 packet.PutStringAsRawHex8(error.AsCString());
111 return SendPacketNoLock(packet.GetString());
112 }
113 return SendErrorResponse(code);
114}
115
118 assert(error);
119 std::unique_ptr<llvm::ErrorInfoBase> EIB;
120 std::unique_ptr<UnimplementedError> UE;
121 llvm::handleAllErrors(
122 std::move(error),
123 [&](std::unique_ptr<UnimplementedError> E) { UE = std::move(E); },
124 [&](std::unique_ptr<llvm::ErrorInfoBase> E) { EIB = std::move(E); });
125
126 if (EIB)
127 return SendErrorResponse(Status::FromError(llvm::Error(std::move(EIB))));
128 return SendUnimplementedResponse("");
129}
130
133 StringExtractorGDBRemote &packet) {
135 return SendOKResponse();
136}
137
140 const StringExtractorGDBRemote &failed_packet, const char *message) {
142 LLDB_LOGF(log, "GDBRemoteCommunicationServer::%s: ILLFORMED: '%s' (%s)",
143 __FUNCTION__, failed_packet.GetStringRef().data(),
144 message ? message : "");
145 return SendErrorResponse(0x03);
146}
147
150 return SendPacketNoLock("OK");
151}
152
154GDBRemoteCommunicationServer::SendJSONResponse(const json::Value &value) {
155 std::string json_string;
156 raw_string_ostream os(json_string);
157 os << value;
158 StreamGDBRemote escaped_response;
159 escaped_response.PutEscapedBytes(json_string.c_str(), json_string.size());
160 return SendPacketNoLock(escaped_response.GetString());
161}
162
164GDBRemoteCommunicationServer::SendJSONResponse(Expected<json::Value> value) {
165 if (!value)
166 return SendErrorResponse(value.takeError());
167 return SendJSONResponse(*value);
168}
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOGF(log,...)
Definition: Log.h:376
ServerPacketType GetServerPacketType() const
llvm::StringRef GetStringRef() const
bool IsConnected() const
Check if the connection is valid.
An error handling class.
Definition: Status.h:115
static Status FromErrorString(const char *str)
Definition: Status.h:138
static Status FromError(llvm::Error error)
Avoid using this in new code. Migrate APIs to llvm::Expected instead.
Definition: Status.cpp:137
int PutEscapedBytes(const void *s, size_t src_len)
Output a block of data to the stream performing GDB-remote escaping.
Definition: GDBRemote.cpp:28
llvm::StringRef GetString() const
size_t PutStringAsRawHex8(llvm::StringRef s)
Definition: Stream.cpp:410
size_t Printf(const char *format,...) __attribute__((format(printf
Output printf formatted output to the stream.
Definition: Stream.cpp:134
std::function< PacketResult(StringExtractorGDBRemote &packet, Status &error, bool &interrupt, bool &quit)> PacketHandler
void RegisterPacketHandler(StringExtractorGDBRemote::ServerPacketType packet_type, PacketHandler handler)
std::map< StringExtractorGDBRemote::ServerPacketType, PacketHandler > m_packet_handlers
PacketResult Handle_QErrorStringEnable(StringExtractorGDBRemote &packet)
PacketResult SendIllFormedResponse(const StringExtractorGDBRemote &packet, const char *error_message)
PacketResult GetPacketAndSendResponse(Timeout< std::micro > timeout, Status &error, bool &interrupt, bool &quit)
PacketResult SendJSONResponse(const llvm::json::Value &value)
Serialize and send a JSON object response.
PacketResult ReadPacket(StringExtractorGDBRemote &response, Timeout< std::micro > timeout, bool sync_on_timeout)
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition: Log.h:332
Definition: SBAddress.h:15
@ eErrorTypePOSIX
POSIX error codes.
Definition: Debugger.h:54