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 "Utility/StringExtractorGDBRemote.h" 23 24 using namespace lldb; 25 using namespace lldb_private; 26 using namespace lldb_private::process_gdb_remote; 27 28 GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(const char *comm_name, 29 const char *listener_name) : 30 GDBRemoteCommunication (comm_name, listener_name), 31 m_exit_now (false) 32 { 33 } 34 35 GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer() 36 { 37 } 38 39 void GDBRemoteCommunicationServer::RegisterPacketHandler( 40 StringExtractorGDBRemote::ServerPacketType packet_type, 41 PacketHandler handler) 42 { 43 m_packet_handlers[packet_type] = std::move(handler); 44 } 45 46 GDBRemoteCommunication::PacketResult 47 GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec, 48 Error &error, 49 bool &interrupt, 50 bool &quit) 51 { 52 StringExtractorGDBRemote packet; 53 54 PacketResult packet_result = WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec); 55 if (packet_result == PacketResult::Success) 56 { 57 const StringExtractorGDBRemote::ServerPacketType packet_type = packet.GetServerPacketType (); 58 switch (packet_type) 59 { 60 case StringExtractorGDBRemote::eServerPacketType_nack: 61 case StringExtractorGDBRemote::eServerPacketType_ack: 62 break; 63 64 case StringExtractorGDBRemote::eServerPacketType_invalid: 65 error.SetErrorString("invalid packet"); 66 quit = true; 67 break; 68 69 case StringExtractorGDBRemote::eServerPacketType_unimplemented: 70 packet_result = SendUnimplementedResponse (packet.GetStringRef().c_str()); 71 break; 72 73 default: 74 auto handler_it = m_packet_handlers.find(packet_type); 75 if (handler_it == m_packet_handlers.end()) 76 packet_result = SendUnimplementedResponse (packet.GetStringRef().c_str()); 77 else 78 packet_result = handler_it->second (packet, error, interrupt, quit); 79 break; 80 } 81 } 82 else 83 { 84 if (!IsConnected()) 85 { 86 error.SetErrorString("lost connection"); 87 quit = true; 88 } 89 else 90 { 91 error.SetErrorString("timeout"); 92 } 93 } 94 95 // Check if anything occurred that would force us to want to exit. 96 if (m_exit_now) 97 quit = true; 98 99 return packet_result; 100 } 101 102 GDBRemoteCommunication::PacketResult 103 GDBRemoteCommunicationServer::SendUnimplementedResponse (const char *) 104 { 105 // TODO: Log the packet we aren't handling... 106 return SendPacketNoLock ("", 0); 107 } 108 109 110 GDBRemoteCommunication::PacketResult 111 GDBRemoteCommunicationServer::SendErrorResponse (uint8_t err) 112 { 113 char packet[16]; 114 int packet_len = ::snprintf (packet, sizeof(packet), "E%2.2x", err); 115 assert (packet_len < (int)sizeof(packet)); 116 return SendPacketNoLock (packet, packet_len); 117 } 118 119 GDBRemoteCommunication::PacketResult 120 GDBRemoteCommunicationServer::SendIllFormedResponse (const StringExtractorGDBRemote &failed_packet, const char *message) 121 { 122 Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS)); 123 if (log) 124 log->Printf ("GDBRemoteCommunicationServer::%s: ILLFORMED: '%s' (%s)", __FUNCTION__, failed_packet.GetStringRef ().c_str (), message ? message : ""); 125 return SendErrorResponse (0x03); 126 } 127 128 GDBRemoteCommunication::PacketResult 129 GDBRemoteCommunicationServer::SendOKResponse () 130 { 131 return SendPacketNoLock ("OK", 2); 132 } 133 134 bool 135 GDBRemoteCommunicationServer::HandshakeWithClient(Error *error_ptr) 136 { 137 return GetAck() == PacketResult::Success; 138 } 139