llvm-capstone/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
Jonas Devlieghere d35b42f20a [NFC] Return llvm::StringRef from StringExtractor::GetStringRef.
This patch removes the two variant of StringExtractor::GetStringRef that
return (non-)const references to std::string. The non-const one was
being abused to reinitialize the StringExtractor and its uses are
replaced by calls to the copy asignment operator. The const variant was
refactored to return an actual llvm::StringRef.

llvm-svn: 369493
2019-08-21 04:55:56 +00:00

157 lines
5.2 KiB
C++

//===-- GDBRemoteCommunicationServer.cpp ------------------------*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
#include <errno.h>
#include "lldb/Host/Config.h"
#include "GDBRemoteCommunicationServer.h"
#include <cstring>
#include "ProcessGDBRemoteLog.h"
#include "lldb/Utility/StreamString.h"
#include "lldb/Utility/StringExtractorGDBRemote.h"
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::process_gdb_remote;
GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(
const char *comm_name, const char *listener_name)
: GDBRemoteCommunication(comm_name, listener_name), m_exit_now(false) {
RegisterPacketHandler(
StringExtractorGDBRemote::eServerPacketType_QEnableErrorStrings,
[this](StringExtractorGDBRemote packet, Status &error, bool &interrupt,
bool &quit) { return this->Handle_QErrorStringEnable(packet); });
}
GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer() {}
void GDBRemoteCommunicationServer::RegisterPacketHandler(
StringExtractorGDBRemote::ServerPacketType packet_type,
PacketHandler handler) {
m_packet_handlers[packet_type] = std::move(handler);
}
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::GetPacketAndSendResponse(
Timeout<std::micro> timeout, Status &error, bool &interrupt, bool &quit) {
StringExtractorGDBRemote packet;
PacketResult packet_result = WaitForPacketNoLock(packet, timeout, false);
if (packet_result == PacketResult::Success) {
const StringExtractorGDBRemote::ServerPacketType packet_type =
packet.GetServerPacketType();
switch (packet_type) {
case StringExtractorGDBRemote::eServerPacketType_nack:
case StringExtractorGDBRemote::eServerPacketType_ack:
break;
case StringExtractorGDBRemote::eServerPacketType_invalid:
error.SetErrorString("invalid packet");
quit = true;
break;
case StringExtractorGDBRemote::eServerPacketType_unimplemented:
packet_result = SendUnimplementedResponse(packet.GetStringRef().data());
break;
default:
auto handler_it = m_packet_handlers.find(packet_type);
if (handler_it == m_packet_handlers.end())
packet_result = SendUnimplementedResponse(packet.GetStringRef().data());
else
packet_result = handler_it->second(packet, error, interrupt, quit);
break;
}
} else {
if (!IsConnected()) {
error.SetErrorString("lost connection");
quit = true;
} else {
error.SetErrorString("timeout");
}
}
// Check if anything occurred that would force us to want to exit.
if (m_exit_now)
quit = true;
return packet_result;
}
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::SendUnimplementedResponse(const char *) {
// TODO: Log the packet we aren't handling...
return SendPacketNoLock("");
}
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::SendErrorResponse(uint8_t err) {
char packet[16];
int packet_len = ::snprintf(packet, sizeof(packet), "E%2.2x", err);
assert(packet_len < (int)sizeof(packet));
return SendPacketNoLock(llvm::StringRef(packet, packet_len));
}
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::SendErrorResponse(const Status &error) {
if (m_send_error_strings) {
lldb_private::StreamString packet;
packet.Printf("E%2.2x;", static_cast<uint8_t>(error.GetError()));
packet.PutStringAsRawHex8(error.AsCString());
return SendPacketNoLock(packet.GetString());
} else
return SendErrorResponse(error.GetError());
}
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::SendErrorResponse(llvm::Error error) {
std::unique_ptr<llvm::ErrorInfoBase> EIB;
std::unique_ptr<PacketUnimplementedError> PUE;
llvm::handleAllErrors(
std::move(error),
[&](std::unique_ptr<PacketUnimplementedError> E) { PUE = std::move(E); },
[&](std::unique_ptr<llvm::ErrorInfoBase> E) { EIB = std::move(E); });
if (EIB)
return SendErrorResponse(Status(llvm::Error(std::move(EIB))));
if (PUE)
return SendUnimplementedResponse(PUE->message().c_str());
return SendErrorResponse(Status("Unknown Error"));
}
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::Handle_QErrorStringEnable(
StringExtractorGDBRemote &packet) {
m_send_error_strings = true;
return SendOKResponse();
}
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::SendIllFormedResponse(
const StringExtractorGDBRemote &failed_packet, const char *message) {
Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS));
LLDB_LOGF(log, "GDBRemoteCommunicationServer::%s: ILLFORMED: '%s' (%s)",
__FUNCTION__, failed_packet.GetStringRef().data(),
message ? message : "");
return SendErrorResponse(0x03);
}
GDBRemoteCommunication::PacketResult
GDBRemoteCommunicationServer::SendOKResponse() {
return SendPacketNoLock("OK");
}
bool GDBRemoteCommunicationServer::HandshakeWithClient() {
return GetAck() == PacketResult::Success;
}
char PacketUnimplementedError::ID;