GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_vFile_pWrite( StringExtractorGDBRemote &packet) { #ifdef _WIN32 return SendUnimplementedResponse("GDBRemoteCommunicationServerCommon::Handle_" "vFile_pWrite() unimplemented"); #else packet.SetFilePos(::strlen("vFile:pwrite:")); StreamGDBRemote response; response.PutChar('F'); int fd = packet.GetU32(UINT32_MAX); if (packet.GetChar() == ',') { off_t offset = packet.GetU64(UINT32_MAX); if (packet.GetChar() == ',') { std::string buffer; if (packet.GetEscapedBinaryData(buffer)) { const ssize_t bytes_written = ::pwrite(fd, buffer.data(), buffer.size(), offset); const int save_errno = bytes_written == -1 ? errno : 0; response.Printf("%zi", bytes_written); if (save_errno) response.Printf(",%i", save_errno); } else { response.Printf("-1,%i", EINVAL); } return SendPacketNoLock(response.GetString()); } } return SendErrorResponse(27); #endif }
GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer( StringExtractorGDBRemote &packet) { if (m_pending_gdb_server.pid == LLDB_INVALID_PROCESS_ID) return SendErrorResponse(4); JSONObject::SP server_sp = std::make_shared<JSONObject>(); server_sp->SetObject("port", std::make_shared<JSONNumber>(m_pending_gdb_server.port)); if (!m_pending_gdb_server.socket_name.empty()) server_sp->SetObject( "socket_name", std::make_shared<JSONString>(m_pending_gdb_server.socket_name.c_str())); JSONArray server_list; server_list.AppendObject(server_sp); StreamGDBRemote response; server_list.Write(response); StreamGDBRemote escaped_response; escaped_response.PutEscapedBytes(response.GetString().data(), response.GetSize()); return SendPacketNoLock(escaped_response.GetString()); }
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()); }
GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_vFile_pRead( StringExtractorGDBRemote &packet) { #ifdef _WIN32 // Not implemented on Windows return SendUnimplementedResponse( "GDBRemoteCommunicationServerCommon::Handle_vFile_pRead() unimplemented"); #else StreamGDBRemote response; packet.SetFilePos(::strlen("vFile:pread:")); int fd = packet.GetS32(-1); if (packet.GetChar() == ',') { uint64_t count = packet.GetU64(UINT64_MAX); if (packet.GetChar() == ',') { uint64_t offset = packet.GetU64(UINT32_MAX); if (count == UINT64_MAX) { response.Printf("F-1:%i", EINVAL); return SendPacketNoLock(response.GetString()); } std::string buffer(count, 0); const ssize_t bytes_read = ::pread(fd, &buffer[0], buffer.size(), offset); const int save_errno = bytes_read == -1 ? errno : 0; response.PutChar('F'); response.Printf("%zi", bytes_read); if (save_errno) response.Printf(",%i", save_errno); else { response.PutChar(';'); response.PutEscapedBytes(&buffer[0], bytes_read); } return SendPacketNoLock(response.GetString()); } } return SendErrorResponse(21); #endif }
GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::Handle_qPlatform_mkdir( StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen("qPlatform_mkdir:")); mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX); if (packet.GetChar() == ',') { std::string path; packet.GetHexByteString(path); Error error = FileSystem::MakeDirectory(FileSpec{path, false}, mode); StreamGDBRemote response; response.Printf("F%u", error.GetError()); return SendPacketNoLock(response.GetString()); } return SendErrorResponse(20); }
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.GetString()); }
GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::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 (!FileSystem::CalculateMD5(FileSpec(path.c_str(), false), a, b)) { response.PutCString("F,"); response.PutCString("x"); } else { response.PutCString("F,"); response.PutHex64(a); response.PutHex64(b); } return SendPacketNoLock(response.GetString()); } return SendErrorResponse(25); }
GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerCommon::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(), FileSpec{working_dir, true}, &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.GetString()); } } return SendErrorResponse(24); }
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;")); llvm::StringRef name; llvm::StringRef value; uint16_t port = UINT16_MAX; while (packet.GetNameColonValue(name, value)) { if (name.equals("host")) hostname = value; else if (name.equals("port")) value.getAsInteger(0, port); } lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID; std::string socket_name; Status 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.GetString()); if (packet_result != PacketResult::Success) { if (debugserver_pid != LLDB_INVALID_PROCESS_ID) ::kill(debugserver_pid, SIGINT); } return packet_result; #endif }