GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServer::Handle_vFile_MD5 (StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("vFile:MD5:")); std::string path; packet.GetHexByteString(path); if (!path.empty()) { uint64_t a,b; StreamGDBRemote response; if (Host::CalculateMD5(FileSpec(path.c_str(),false),a,b) == false) { response.PutCString("F,"); response.PutCString("x"); } else { response.PutCString("F,"); response.PutHex64(a); response.PutHex64(b); } return SendPacketNoLock(response.GetData(), response.GetSize()); } return SendErrorResponse(25); }
GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet) { #ifdef _WIN32 return SendErrorResponse(9); #else // Spawn a local debugserver as a platform so we can then attach or launch // a process... Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); if (log) log->Printf ("GDBRemoteCommunicationServerPlatform::%s() called", __FUNCTION__); ConnectionFileDescriptor file_conn; std::string hostname; packet.SetFilePos(::strlen ("qLaunchGDBServer;")); std::string name; std::string value; uint16_t port = UINT16_MAX; while (packet.GetNameColonValue(name, value)) { if (name.compare ("host") == 0) hostname.swap(value); else if (name.compare ("port") == 0) port = StringConvert::ToUInt32(value.c_str(), 0, 0); } lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID; std::string socket_name; Error error = LaunchGDBServer(Args(), hostname, debugserver_pid, port, socket_name); if (error.Fail()) { if (log) log->Printf("GDBRemoteCommunicationServerPlatform::%s() debugserver launch failed: %s", __FUNCTION__, error.AsCString ()); return SendErrorResponse(9); } if (log) log->Printf ("GDBRemoteCommunicationServerPlatform::%s() debugserver launched successfully as pid %" PRIu64, __FUNCTION__, debugserver_pid); StreamGDBRemote response; response.Printf("pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset); if (!socket_name.empty()) { response.PutCString("socket_name:"); response.PutCStringAsRawHex8(socket_name.c_str()); response.PutChar(';'); } PacketResult packet_result = SendPacketNoLock(response.GetData(), response.GetSize()); if (packet_result != PacketResult::Success) { if (debugserver_pid != LLDB_INVALID_PROCESS_ID) ::kill (debugserver_pid, SIGINT); } return packet_result; #endif }
GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_qSupported (StringExtractorGDBRemote &packet) { StreamGDBRemote response; // Features common to lldb-platform and llgs. uint32_t max_packet_size = 128 * 1024; // 128KBytes is a reasonable max packet size--debugger can always use less response.Printf ("PacketSize=%x", max_packet_size); response.PutCString (";QStartNoAckMode+"); response.PutCString (";QThreadSuffixSupported+"); response.PutCString (";QListThreadsInStopReply+"); response.PutCString (";qEcho+"); #if defined(__linux__) response.PutCString (";qXfer:auxv:read+"); #endif return SendPacketNoLock(response.GetData(), response.GetSize()); }
GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServer::Handle_qPlatform_shell (StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("qPlatform_shell:")); std::string path; std::string working_dir; packet.GetHexByteStringTerminatedBy(path,','); if (!path.empty()) { if (packet.GetChar() == ',') { // FIXME: add timeout to qPlatform_shell packet // uint32_t timeout = packet.GetHexMaxU32(false, 32); uint32_t timeout = 10; if (packet.GetChar() == ',') packet.GetHexByteString(working_dir); int status, signo; std::string output; Error err = Host::RunShellCommand(path.c_str(), working_dir.empty() ? NULL : working_dir.c_str(), &status, &signo, &output, timeout); StreamGDBRemote response; if (err.Fail()) { response.PutCString("F,"); response.PutHex32(UINT32_MAX); } else { response.PutCString("F,"); response.PutHex32(status); response.PutChar(','); response.PutHex32(signo); response.PutChar(','); response.PutEscapedBytes(output.c_str(), output.size()); } return SendPacketNoLock(response.GetData(), response.GetSize()); } } return SendErrorResponse(24); }
GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_qModuleInfo( StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("qModuleInfo:")); std::string module_path; packet.GetHexByteStringTerminatedBy(module_path, ';'); if (module_path.empty()) return SendErrorResponse(1); if (packet.GetChar() != ';') return SendErrorResponse(2); std::string triple; packet.GetHexByteString(triple); ModuleSpec matched_module_spec = GetModuleInfo(module_path, triple); if (!matched_module_spec.GetFileSpec()) return SendErrorResponse(3); const auto file_offset = matched_module_spec.GetObjectOffset(); const auto file_size = matched_module_spec.GetObjectSize(); const auto uuid_str = matched_module_spec.GetUUID().GetAsString(""); StreamGDBRemote response; if (uuid_str.empty()) { std::string md5_hash; if (!FileSystem::CalculateMD5AsString(matched_module_spec.GetFileSpec(), file_offset, file_size, md5_hash)) return SendErrorResponse(5); response.PutCString("md5:"); response.PutCStringAsRawHex8(md5_hash.c_str()); } else { response.PutCString("uuid:"); response.PutCStringAsRawHex8(uuid_str.c_str()); } response.PutChar(';'); const auto &module_arch = matched_module_spec.GetArchitecture(); response.PutCString("triple:"); response.PutCStringAsRawHex8(module_arch.GetTriple().getTriple().c_str()); response.PutChar(';'); response.PutCString("file_path:"); response.PutCStringAsRawHex8(matched_module_spec.GetFileSpec().GetCString()); response.PutChar(';'); response.PutCString("file_offset:"); response.PutHex64(file_offset); response.PutChar(';'); response.PutCString("file_size:"); response.PutHex64(file_size); response.PutChar(';'); return SendPacketNoLock(response.GetString()); }