169 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include <cerrno>10 11#include "lldb/Host/Config.h"12 13#include "GDBRemoteCommunicationServer.h"14 15#include "ProcessGDBRemoteLog.h"16#include "lldb/Utility/StreamString.h"17#include "lldb/Utility/StringExtractorGDBRemote.h"18#include "lldb/Utility/UnimplementedError.h"19#include "llvm/Support/JSON.h"20#include <cstring>21 22using namespace lldb;23using namespace lldb_private;24using namespace lldb_private::process_gdb_remote;25using namespace llvm;26 27GDBRemoteCommunicationServer::GDBRemoteCommunicationServer()28 : GDBRemoteCommunication(), m_exit_now(false) {29 RegisterPacketHandler(30 StringExtractorGDBRemote::eServerPacketType_QEnableErrorStrings,31 [this](StringExtractorGDBRemote packet, Status &error, bool &interrupt,32 bool &quit) { return this->Handle_QErrorStringEnable(packet); });33}34 35GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer() = default;36 37void GDBRemoteCommunicationServer::RegisterPacketHandler(38 StringExtractorGDBRemote::ServerPacketType packet_type,39 PacketHandler handler) {40 m_packet_handlers[packet_type] = std::move(handler);41}42 43GDBRemoteCommunication::PacketResult44GDBRemoteCommunicationServer::GetPacketAndSendResponse(45 Timeout<std::micro> timeout, Status &error, bool &interrupt, bool &quit) {46 StringExtractorGDBRemote packet;47 48 PacketResult packet_result = ReadPacket(packet, timeout, false);49 if (packet_result == PacketResult::Success) {50 const StringExtractorGDBRemote::ServerPacketType packet_type =51 packet.GetServerPacketType();52 switch (packet_type) {53 case StringExtractorGDBRemote::eServerPacketType_nack:54 case StringExtractorGDBRemote::eServerPacketType_ack:55 break;56 57 case StringExtractorGDBRemote::eServerPacketType_invalid:58 error = Status::FromErrorString("invalid packet");59 quit = true;60 break;61 62 case StringExtractorGDBRemote::eServerPacketType_unimplemented: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 else71 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 90GDBRemoteCommunication::PacketResult91GDBRemoteCommunicationServer::SendUnimplementedResponse(const char *) {92 // TODO: Log the packet we aren't handling...93 return SendPacketNoLock("");94}95 96GDBRemoteCommunication::PacketResult97GDBRemoteCommunicationServer::SendErrorResponse(uint8_t err) {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 104GDBRemoteCommunication::PacketResult105GDBRemoteCommunicationServer::SendErrorResponse(const Status &error) {106 uint8_t code = error.GetType() == eErrorTypePOSIX ? error.GetError() : 0xff;107 if (m_send_error_strings) {108 lldb_private::StreamString packet;109 packet.Printf("E%2.2x;", code);110 packet.PutStringAsRawHex8(error.AsCString());111 return SendPacketNoLock(packet.GetString());112 }113 return SendErrorResponse(code);114}115 116GDBRemoteCommunication::PacketResult117GDBRemoteCommunicationServer::SendErrorResponse(llvm::Error error) {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 131GDBRemoteCommunication::PacketResult132GDBRemoteCommunicationServer::Handle_QErrorStringEnable(133 StringExtractorGDBRemote &packet) {134 m_send_error_strings = true;135 return SendOKResponse();136}137 138GDBRemoteCommunication::PacketResult139GDBRemoteCommunicationServer::SendIllFormedResponse(140 const StringExtractorGDBRemote &failed_packet, const char *message) {141 Log *log = GetLog(GDBRLog::Packets);142 LLDB_LOGF(log, "GDBRemoteCommunicationServer::%s: ILLFORMED: '%s' (%s)",143 __FUNCTION__, failed_packet.GetStringRef().data(),144 message ? message : "");145 return SendErrorResponse(0x03);146}147 148GDBRemoteCommunication::PacketResult149GDBRemoteCommunicationServer::SendOKResponse() {150 return SendPacketNoLock("OK");151}152 153GDBRemoteCommunication::PacketResult154GDBRemoteCommunicationServer::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 163GDBRemoteCommunication::PacketResult164GDBRemoteCommunicationServer::SendJSONResponse(Expected<json::Value> value) {165 if (!value)166 return SendErrorResponse(value.takeError());167 return SendJSONResponse(*value);168}169