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