180814287SRaphael Isemann //===-- GDBRemoteCommunicationServer.cpp ----------------------------------===//
2576d8834SGreg Clayton //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6576d8834SGreg Clayton //
7576d8834SGreg Clayton //===----------------------------------------------------------------------===//
8576d8834SGreg Clayton
976e47d48SRaphael Isemann #include <cerrno>
10576d8834SGreg Clayton
110ec7baa9SZachary Turner #include "lldb/Host/Config.h"
120ec7baa9SZachary Turner
13576d8834SGreg Clayton #include "GDBRemoteCommunicationServer.h"
14576d8834SGreg Clayton
15576d8834SGreg Clayton #include "ProcessGDBRemoteLog.h"
16dab1d5f3SRavitheja Addepally #include "lldb/Utility/StreamString.h"
179af71b38SPavel Labath #include "lldb/Utility/StringExtractorGDBRemote.h"
18e2f1fe36SPavel Labath #include "lldb/Utility/UnimplementedError.h"
190b697561SWalter Erquinigo #include "llvm/Support/JSON.h"
20e2f1fe36SPavel Labath #include <cstring>
21576d8834SGreg Clayton
22576d8834SGreg Clayton using namespace lldb;
23576d8834SGreg Clayton using namespace lldb_private;
24db264a6dSTamas Berghammer using namespace lldb_private::process_gdb_remote;
250b697561SWalter Erquinigo using namespace llvm;
26576d8834SGreg Clayton
GDBRemoteCommunicationServer(const char * comm_name,const char * listener_name)27b9c1b51eSKate Stone GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(
28b9c1b51eSKate Stone const char *comm_name, const char *listener_name)
29dab1d5f3SRavitheja Addepally : GDBRemoteCommunication(comm_name, listener_name), m_exit_now(false) {
30dab1d5f3SRavitheja Addepally RegisterPacketHandler(
31dab1d5f3SRavitheja Addepally StringExtractorGDBRemote::eServerPacketType_QEnableErrorStrings,
32dab1d5f3SRavitheja Addepally [this](StringExtractorGDBRemote packet, Status &error, bool &interrupt,
33dab1d5f3SRavitheja Addepally bool &quit) { return this->Handle_QErrorStringEnable(packet); });
34dab1d5f3SRavitheja Addepally }
35af245d11STodd Fiala
36fd2433e1SJonas Devlieghere GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer() = default;
37576d8834SGreg Clayton
RegisterPacketHandler(StringExtractorGDBRemote::ServerPacketType packet_type,PacketHandler handler)38e13c2731STamas Berghammer void GDBRemoteCommunicationServer::RegisterPacketHandler(
39e13c2731STamas Berghammer StringExtractorGDBRemote::ServerPacketType packet_type,
40b9c1b51eSKate Stone PacketHandler handler) {
41e13c2731STamas Berghammer m_packet_handlers[packet_type] = std::move(handler);
42e13c2731STamas Berghammer }
43e13c2731STamas Berghammer
44af245d11STodd Fiala GDBRemoteCommunication::PacketResult
GetPacketAndSendResponse(Timeout<std::micro> timeout,Status & error,bool & interrupt,bool & quit)451eff73c3SPavel Labath GDBRemoteCommunicationServer::GetPacketAndSendResponse(
4697206d57SZachary Turner Timeout<std::micro> timeout, Status &error, bool &interrupt, bool &quit) {
47576d8834SGreg Clayton StringExtractorGDBRemote packet;
48af245d11STodd Fiala
49165545c7SPavel Labath PacketResult packet_result = ReadPacket(packet, timeout, false);
50b9c1b51eSKate Stone if (packet_result == PacketResult::Success) {
51b9c1b51eSKate Stone const StringExtractorGDBRemote::ServerPacketType packet_type =
52b9c1b51eSKate Stone packet.GetServerPacketType();
53b9c1b51eSKate Stone switch (packet_type) {
54576d8834SGreg Clayton case StringExtractorGDBRemote::eServerPacketType_nack:
55576d8834SGreg Clayton case StringExtractorGDBRemote::eServerPacketType_ack:
56576d8834SGreg Clayton break;
57576d8834SGreg Clayton
58576d8834SGreg Clayton case StringExtractorGDBRemote::eServerPacketType_invalid:
591cb6496eSGreg Clayton error.SetErrorString("invalid packet");
60d314e810SGreg Clayton quit = true;
61d314e810SGreg Clayton break;
62d314e810SGreg Clayton
63576d8834SGreg Clayton case StringExtractorGDBRemote::eServerPacketType_unimplemented:
64d35b42f2SJonas Devlieghere packet_result = SendUnimplementedResponse(packet.GetStringRef().data());
653dedae12SGreg Clayton break;
66576d8834SGreg Clayton
67e13c2731STamas Berghammer default:
68e13c2731STamas Berghammer auto handler_it = m_packet_handlers.find(packet_type);
69e13c2731STamas Berghammer if (handler_it == m_packet_handlers.end())
70d35b42f2SJonas Devlieghere packet_result = SendUnimplementedResponse(packet.GetStringRef().data());
71af245d11STodd Fiala else
72e13c2731STamas Berghammer packet_result = handler_it->second(packet, error, interrupt, quit);
731109ed42STodd Fiala break;
74576d8834SGreg Clayton }
75b9c1b51eSKate Stone } else {
76b9c1b51eSKate Stone if (!IsConnected()) {
771cb6496eSGreg Clayton error.SetErrorString("lost connection");
783dedae12SGreg Clayton quit = true;
79b9c1b51eSKate Stone } else {
801cb6496eSGreg Clayton error.SetErrorString("timeout");
811cb6496eSGreg Clayton }
823dedae12SGreg Clayton }
83af245d11STodd Fiala
84af245d11STodd Fiala // Check if anything occurred that would force us to want to exit.
85af245d11STodd Fiala if (m_exit_now)
86af245d11STodd Fiala quit = true;
87af245d11STodd Fiala
88af245d11STodd Fiala return packet_result;
89576d8834SGreg Clayton }
90576d8834SGreg Clayton
913dedae12SGreg Clayton GDBRemoteCommunication::PacketResult
SendUnimplementedResponse(const char *)92b9c1b51eSKate Stone GDBRemoteCommunicationServer::SendUnimplementedResponse(const char *) {
9332e0a750SGreg Clayton // TODO: Log the packet we aren't handling...
9426709df8SZachary Turner return SendPacketNoLock("");
95576d8834SGreg Clayton }
96576d8834SGreg Clayton
973dedae12SGreg Clayton GDBRemoteCommunication::PacketResult
SendErrorResponse(uint8_t err)98b9c1b51eSKate Stone GDBRemoteCommunicationServer::SendErrorResponse(uint8_t err) {
9932e0a750SGreg Clayton char packet[16];
10032e0a750SGreg Clayton int packet_len = ::snprintf(packet, sizeof(packet), "E%2.2x", err);
101a297a97eSAndy Gibbs assert(packet_len < (int)sizeof(packet));
10226709df8SZachary Turner return SendPacketNoLock(llvm::StringRef(packet, packet_len));
10332e0a750SGreg Clayton }
10432e0a750SGreg Clayton
105af245d11STodd Fiala GDBRemoteCommunication::PacketResult
SendErrorResponse(const Status & error)106dab1d5f3SRavitheja Addepally GDBRemoteCommunicationServer::SendErrorResponse(const Status &error) {
107dab1d5f3SRavitheja Addepally if (m_send_error_strings) {
108dab1d5f3SRavitheja Addepally lldb_private::StreamString packet;
109dab1d5f3SRavitheja Addepally packet.Printf("E%2.2x;", static_cast<uint8_t>(error.GetError()));
1107f815a9aSPavel Labath packet.PutStringAsRawHex8(error.AsCString());
111dab1d5f3SRavitheja Addepally return SendPacketNoLock(packet.GetString());
112dab1d5f3SRavitheja Addepally } else
113dab1d5f3SRavitheja Addepally return SendErrorResponse(error.GetError());
114dab1d5f3SRavitheja Addepally }
115dab1d5f3SRavitheja Addepally
116dab1d5f3SRavitheja Addepally GDBRemoteCommunication::PacketResult
SendErrorResponse(llvm::Error error)11757e2da4fSAntonio Afonso GDBRemoteCommunicationServer::SendErrorResponse(llvm::Error error) {
118e2f1fe36SPavel Labath assert(error);
11957e2da4fSAntonio Afonso std::unique_ptr<llvm::ErrorInfoBase> EIB;
120e2f1fe36SPavel Labath std::unique_ptr<UnimplementedError> UE;
12157e2da4fSAntonio Afonso llvm::handleAllErrors(
12257e2da4fSAntonio Afonso std::move(error),
123e2f1fe36SPavel Labath [&](std::unique_ptr<UnimplementedError> E) { UE = std::move(E); },
12457e2da4fSAntonio Afonso [&](std::unique_ptr<llvm::ErrorInfoBase> E) { EIB = std::move(E); });
12557e2da4fSAntonio Afonso
12657e2da4fSAntonio Afonso if (EIB)
12757e2da4fSAntonio Afonso return SendErrorResponse(Status(llvm::Error(std::move(EIB))));
128e2f1fe36SPavel Labath return SendUnimplementedResponse("");
12957e2da4fSAntonio Afonso }
13057e2da4fSAntonio Afonso
13157e2da4fSAntonio Afonso GDBRemoteCommunication::PacketResult
Handle_QErrorStringEnable(StringExtractorGDBRemote & packet)132dab1d5f3SRavitheja Addepally GDBRemoteCommunicationServer::Handle_QErrorStringEnable(
133dab1d5f3SRavitheja Addepally StringExtractorGDBRemote &packet) {
134dab1d5f3SRavitheja Addepally m_send_error_strings = true;
135dab1d5f3SRavitheja Addepally return SendOKResponse();
136dab1d5f3SRavitheja Addepally }
137dab1d5f3SRavitheja Addepally
138dab1d5f3SRavitheja Addepally GDBRemoteCommunication::PacketResult
SendIllFormedResponse(const StringExtractorGDBRemote & failed_packet,const char * message)139b9c1b51eSKate Stone GDBRemoteCommunicationServer::SendIllFormedResponse(
140b9c1b51eSKate Stone const StringExtractorGDBRemote &failed_packet, const char *message) {
141*b1127753SPavel Labath Log *log = GetLog(GDBRLog::Packets);
14263e5fb76SJonas Devlieghere LLDB_LOGF(log, "GDBRemoteCommunicationServer::%s: ILLFORMED: '%s' (%s)",
143d35b42f2SJonas Devlieghere __FUNCTION__, failed_packet.GetStringRef().data(),
144b9c1b51eSKate Stone message ? message : "");
145af245d11STodd Fiala return SendErrorResponse(0x03);
146af245d11STodd Fiala }
14732e0a750SGreg Clayton
1483dedae12SGreg Clayton GDBRemoteCommunication::PacketResult
SendOKResponse()149b9c1b51eSKate Stone GDBRemoteCommunicationServer::SendOKResponse() {
15026709df8SZachary Turner return SendPacketNoLock("OK");
1511cb6496eSGreg Clayton }
1521cb6496eSGreg Clayton
1530b697561SWalter Erquinigo GDBRemoteCommunication::PacketResult
SendJSONResponse(const json::Value & value)1540b697561SWalter Erquinigo GDBRemoteCommunicationServer::SendJSONResponse(const json::Value &value) {
1550b697561SWalter Erquinigo std::string json_string;
1560b697561SWalter Erquinigo raw_string_ostream os(json_string);
1570b697561SWalter Erquinigo os << value;
1580b697561SWalter Erquinigo os.flush();
1590b697561SWalter Erquinigo StreamGDBRemote escaped_response;
1600b697561SWalter Erquinigo escaped_response.PutEscapedBytes(json_string.c_str(), json_string.size());
1610b697561SWalter Erquinigo return SendPacketNoLock(escaped_response.GetString());
1620b697561SWalter Erquinigo }
1630b697561SWalter Erquinigo
1640b697561SWalter Erquinigo GDBRemoteCommunication::PacketResult
SendJSONResponse(Expected<json::Value> value)1650b697561SWalter Erquinigo GDBRemoteCommunicationServer::SendJSONResponse(Expected<json::Value> value) {
1660b697561SWalter Erquinigo if (!value)
1670b697561SWalter Erquinigo return SendErrorResponse(value.takeError());
1680b697561SWalter Erquinigo return SendJSONResponse(*value);
1690b697561SWalter Erquinigo }
170