Path: blob/main/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
39642 views
//===-- GDBRemoteCommunicationServer.cpp ----------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include <cerrno>910#include "lldb/Host/Config.h"1112#include "GDBRemoteCommunicationServer.h"1314#include "ProcessGDBRemoteLog.h"15#include "lldb/Utility/StreamString.h"16#include "lldb/Utility/StringExtractorGDBRemote.h"17#include "lldb/Utility/UnimplementedError.h"18#include "llvm/Support/JSON.h"19#include <cstring>2021using namespace lldb;22using namespace lldb_private;23using namespace lldb_private::process_gdb_remote;24using namespace llvm;2526GDBRemoteCommunicationServer::GDBRemoteCommunicationServer()27: GDBRemoteCommunication(), m_exit_now(false) {28RegisterPacketHandler(29StringExtractorGDBRemote::eServerPacketType_QEnableErrorStrings,30[this](StringExtractorGDBRemote packet, Status &error, bool &interrupt,31bool &quit) { return this->Handle_QErrorStringEnable(packet); });32}3334GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer() = default;3536void GDBRemoteCommunicationServer::RegisterPacketHandler(37StringExtractorGDBRemote::ServerPacketType packet_type,38PacketHandler handler) {39m_packet_handlers[packet_type] = std::move(handler);40}4142GDBRemoteCommunication::PacketResult43GDBRemoteCommunicationServer::GetPacketAndSendResponse(44Timeout<std::micro> timeout, Status &error, bool &interrupt, bool &quit) {45StringExtractorGDBRemote packet;4647PacketResult packet_result = ReadPacket(packet, timeout, false);48if (packet_result == PacketResult::Success) {49const StringExtractorGDBRemote::ServerPacketType packet_type =50packet.GetServerPacketType();51switch (packet_type) {52case StringExtractorGDBRemote::eServerPacketType_nack:53case StringExtractorGDBRemote::eServerPacketType_ack:54break;5556case StringExtractorGDBRemote::eServerPacketType_invalid:57error.SetErrorString("invalid packet");58quit = true;59break;6061case StringExtractorGDBRemote::eServerPacketType_unimplemented:62packet_result = SendUnimplementedResponse(packet.GetStringRef().data());63break;6465default:66auto handler_it = m_packet_handlers.find(packet_type);67if (handler_it == m_packet_handlers.end())68packet_result = SendUnimplementedResponse(packet.GetStringRef().data());69else70packet_result = handler_it->second(packet, error, interrupt, quit);71break;72}73} else {74if (!IsConnected()) {75error.SetErrorString("lost connection");76quit = true;77} else {78error.SetErrorString("timeout");79}80}8182// Check if anything occurred that would force us to want to exit.83if (m_exit_now)84quit = true;8586return packet_result;87}8889GDBRemoteCommunication::PacketResult90GDBRemoteCommunicationServer::SendUnimplementedResponse(const char *) {91// TODO: Log the packet we aren't handling...92return SendPacketNoLock("");93}9495GDBRemoteCommunication::PacketResult96GDBRemoteCommunicationServer::SendErrorResponse(uint8_t err) {97char packet[16];98int packet_len = ::snprintf(packet, sizeof(packet), "E%2.2x", err);99assert(packet_len < (int)sizeof(packet));100return SendPacketNoLock(llvm::StringRef(packet, packet_len));101}102103GDBRemoteCommunication::PacketResult104GDBRemoteCommunicationServer::SendErrorResponse(const Status &error) {105if (m_send_error_strings) {106lldb_private::StreamString packet;107packet.Printf("E%2.2x;", static_cast<uint8_t>(error.GetError()));108packet.PutStringAsRawHex8(error.AsCString());109return SendPacketNoLock(packet.GetString());110} else111return SendErrorResponse(error.GetError());112}113114GDBRemoteCommunication::PacketResult115GDBRemoteCommunicationServer::SendErrorResponse(llvm::Error error) {116assert(error);117std::unique_ptr<llvm::ErrorInfoBase> EIB;118std::unique_ptr<UnimplementedError> UE;119llvm::handleAllErrors(120std::move(error),121[&](std::unique_ptr<UnimplementedError> E) { UE = std::move(E); },122[&](std::unique_ptr<llvm::ErrorInfoBase> E) { EIB = std::move(E); });123124if (EIB)125return SendErrorResponse(Status(llvm::Error(std::move(EIB))));126return SendUnimplementedResponse("");127}128129GDBRemoteCommunication::PacketResult130GDBRemoteCommunicationServer::Handle_QErrorStringEnable(131StringExtractorGDBRemote &packet) {132m_send_error_strings = true;133return SendOKResponse();134}135136GDBRemoteCommunication::PacketResult137GDBRemoteCommunicationServer::SendIllFormedResponse(138const StringExtractorGDBRemote &failed_packet, const char *message) {139Log *log = GetLog(GDBRLog::Packets);140LLDB_LOGF(log, "GDBRemoteCommunicationServer::%s: ILLFORMED: '%s' (%s)",141__FUNCTION__, failed_packet.GetStringRef().data(),142message ? message : "");143return SendErrorResponse(0x03);144}145146GDBRemoteCommunication::PacketResult147GDBRemoteCommunicationServer::SendOKResponse() {148return SendPacketNoLock("OK");149}150151GDBRemoteCommunication::PacketResult152GDBRemoteCommunicationServer::SendJSONResponse(const json::Value &value) {153std::string json_string;154raw_string_ostream os(json_string);155os << value;156os.flush();157StreamGDBRemote escaped_response;158escaped_response.PutEscapedBytes(json_string.c_str(), json_string.size());159return SendPacketNoLock(escaped_response.GetString());160}161162GDBRemoteCommunication::PacketResult163GDBRemoteCommunicationServer::SendJSONResponse(Expected<json::Value> value) {164if (!value)165return SendErrorResponse(value.takeError());166return SendJSONResponse(*value);167}168169170