brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.6 KiB · 5bd29ae Raw
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