GDBRemoteCommunicationServer.cpp revision 360784
1//===-- GDBRemoteCommunicationServer.cpp ------------------------*- C++ -*-===// 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-exception 6// 7//===----------------------------------------------------------------------===// 8 9#include <errno.h> 10 11#include "lldb/Host/Config.h" 12 13#include "GDBRemoteCommunicationServer.h" 14 15#include <cstring> 16 17#include "ProcessGDBRemoteLog.h" 18#include "lldb/Utility/StreamString.h" 19#include "lldb/Utility/StringExtractorGDBRemote.h" 20 21using namespace lldb; 22using namespace lldb_private; 23using namespace lldb_private::process_gdb_remote; 24 25GDBRemoteCommunicationServer::GDBRemoteCommunicationServer( 26 const char *comm_name, const char *listener_name) 27 : GDBRemoteCommunication(comm_name, listener_name), m_exit_now(false) { 28 RegisterPacketHandler( 29 StringExtractorGDBRemote::eServerPacketType_QEnableErrorStrings, 30 [this](StringExtractorGDBRemote packet, Status &error, bool &interrupt, 31 bool &quit) { return this->Handle_QErrorStringEnable(packet); }); 32} 33 34GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer() {} 35 36void GDBRemoteCommunicationServer::RegisterPacketHandler( 37 StringExtractorGDBRemote::ServerPacketType packet_type, 38 PacketHandler handler) { 39 m_packet_handlers[packet_type] = std::move(handler); 40} 41 42GDBRemoteCommunication::PacketResult 43GDBRemoteCommunicationServer::GetPacketAndSendResponse( 44 Timeout<std::micro> timeout, Status &error, bool &interrupt, bool &quit) { 45 StringExtractorGDBRemote packet; 46 47 PacketResult packet_result = WaitForPacketNoLock(packet, timeout, false); 48 if (packet_result == PacketResult::Success) { 49 const StringExtractorGDBRemote::ServerPacketType packet_type = 50 packet.GetServerPacketType(); 51 switch (packet_type) { 52 case StringExtractorGDBRemote::eServerPacketType_nack: 53 case StringExtractorGDBRemote::eServerPacketType_ack: 54 break; 55 56 case StringExtractorGDBRemote::eServerPacketType_invalid: 57 error.SetErrorString("invalid packet"); 58 quit = true; 59 break; 60 61 case StringExtractorGDBRemote::eServerPacketType_unimplemented: 62 packet_result = SendUnimplementedResponse(packet.GetStringRef().data()); 63 break; 64 65 default: 66 auto handler_it = m_packet_handlers.find(packet_type); 67 if (handler_it == m_packet_handlers.end()) 68 packet_result = SendUnimplementedResponse(packet.GetStringRef().data()); 69 else 70 packet_result = handler_it->second(packet, error, interrupt, quit); 71 break; 72 } 73 } else { 74 if (!IsConnected()) { 75 error.SetErrorString("lost connection"); 76 quit = true; 77 } else { 78 error.SetErrorString("timeout"); 79 } 80 } 81 82 // Check if anything occurred that would force us to want to exit. 83 if (m_exit_now) 84 quit = true; 85 86 return packet_result; 87} 88 89GDBRemoteCommunication::PacketResult 90GDBRemoteCommunicationServer::SendUnimplementedResponse(const char *) { 91 // TODO: Log the packet we aren't handling... 92 return SendPacketNoLock(""); 93} 94 95GDBRemoteCommunication::PacketResult 96GDBRemoteCommunicationServer::SendErrorResponse(uint8_t err) { 97 char packet[16]; 98 int packet_len = ::snprintf(packet, sizeof(packet), "E%2.2x", err); 99 assert(packet_len < (int)sizeof(packet)); 100 return SendPacketNoLock(llvm::StringRef(packet, packet_len)); 101} 102 103GDBRemoteCommunication::PacketResult 104GDBRemoteCommunicationServer::SendErrorResponse(const Status &error) { 105 if (m_send_error_strings) { 106 lldb_private::StreamString packet; 107 packet.Printf("E%2.2x;", static_cast<uint8_t>(error.GetError())); 108 packet.PutStringAsRawHex8(error.AsCString()); 109 return SendPacketNoLock(packet.GetString()); 110 } else 111 return SendErrorResponse(error.GetError()); 112} 113 114GDBRemoteCommunication::PacketResult 115GDBRemoteCommunicationServer::SendErrorResponse(llvm::Error error) { 116 std::unique_ptr<llvm::ErrorInfoBase> EIB; 117 std::unique_ptr<PacketUnimplementedError> PUE; 118 llvm::handleAllErrors( 119 std::move(error), 120 [&](std::unique_ptr<PacketUnimplementedError> E) { PUE = std::move(E); }, 121 [&](std::unique_ptr<llvm::ErrorInfoBase> E) { EIB = std::move(E); }); 122 123 if (EIB) 124 return SendErrorResponse(Status(llvm::Error(std::move(EIB)))); 125 if (PUE) 126 return SendUnimplementedResponse(PUE->message().c_str()); 127 return SendErrorResponse(Status("Unknown Error")); 128} 129 130GDBRemoteCommunication::PacketResult 131GDBRemoteCommunicationServer::Handle_QErrorStringEnable( 132 StringExtractorGDBRemote &packet) { 133 m_send_error_strings = true; 134 return SendOKResponse(); 135} 136 137GDBRemoteCommunication::PacketResult 138GDBRemoteCommunicationServer::SendIllFormedResponse( 139 const StringExtractorGDBRemote &failed_packet, const char *message) { 140 Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS)); 141 LLDB_LOGF(log, "GDBRemoteCommunicationServer::%s: ILLFORMED: '%s' (%s)", 142 __FUNCTION__, failed_packet.GetStringRef().data(), 143 message ? message : ""); 144 return SendErrorResponse(0x03); 145} 146 147GDBRemoteCommunication::PacketResult 148GDBRemoteCommunicationServer::SendOKResponse() { 149 return SendPacketNoLock("OK"); 150} 151 152bool GDBRemoteCommunicationServer::HandshakeWithClient() { 153 return GetAck() == PacketResult::Success; 154} 155 156char PacketUnimplementedError::ID; 157