diff options
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp')
-rw-r--r-- | contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp | 696 |
1 files changed, 418 insertions, 278 deletions
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp index df036cd..7cc3a05 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp @@ -47,27 +47,9 @@ GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform) : m_spawned_pids_mutex (Mutex::eMutexTypeRecursive), m_proc_infos (), m_proc_infos_index (0), - m_lo_port_num (0), - m_hi_port_num (0), - m_next_port (0), - m_use_port_range (false) + m_port_map (), + m_port_offset(0) { - // We seldom need to override the port number that the debugserver process - // starts with. We just pass in 0 to let the system choose a random port. - // In rare situation where the need arises, use two environment variables - // to override. - uint16_t lo_port_num = 0; - uint16_t hi_port_num = 0; - const char *lo_port_c_str = getenv("LLDB_PLATFORM_START_DEBUG_SERVER_LO_PORT"); - if (lo_port_c_str) - lo_port_num = ::atoi(lo_port_c_str); - const char *hi_port_c_str = getenv("LLDB_PLATFORM_START_DEBUG_SERVER_HI_PORT"); - if (hi_port_c_str) - hi_port_num = ::atoi(hi_port_c_str); - if (lo_port_num && hi_port_num && lo_port_num < hi_port_num) - { - SetPortRange(lo_port_num, hi_port_num); - } } //---------------------------------------------------------------------- @@ -166,6 +148,9 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec, case StringExtractorGDBRemote::eServerPacketType_qUserName: return Handle_qUserName (packet); + case StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir: + return Handle_qGetWorkingDir(packet); + case StringExtractorGDBRemote::eServerPacketType_QEnvironment: return Handle_QEnvironment (packet); @@ -190,38 +175,47 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec, case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode: return Handle_QStartNoAckMode (packet); - case StringExtractorGDBRemote::eServerPacketType_qPlatform_IO_MkDir: - return Handle_qPlatform_IO_MkDir (packet); + case StringExtractorGDBRemote::eServerPacketType_qPlatform_mkdir: + return Handle_qPlatform_mkdir (packet); - case StringExtractorGDBRemote::eServerPacketType_qPlatform_RunCommand: - return Handle_qPlatform_RunCommand (packet); + case StringExtractorGDBRemote::eServerPacketType_qPlatform_chmod: + return Handle_qPlatform_chmod (packet); - case StringExtractorGDBRemote::eServerPacketType_vFile_Open: + case StringExtractorGDBRemote::eServerPacketType_qPlatform_shell: + return Handle_qPlatform_shell (packet); + + case StringExtractorGDBRemote::eServerPacketType_vFile_open: return Handle_vFile_Open (packet); - case StringExtractorGDBRemote::eServerPacketType_vFile_Close: + case StringExtractorGDBRemote::eServerPacketType_vFile_close: return Handle_vFile_Close (packet); - case StringExtractorGDBRemote::eServerPacketType_vFile_pRead: + case StringExtractorGDBRemote::eServerPacketType_vFile_pread: return Handle_vFile_pRead (packet); - case StringExtractorGDBRemote::eServerPacketType_vFile_pWrite: + case StringExtractorGDBRemote::eServerPacketType_vFile_pwrite: return Handle_vFile_pWrite (packet); - case StringExtractorGDBRemote::eServerPacketType_vFile_Size: + case StringExtractorGDBRemote::eServerPacketType_vFile_size: return Handle_vFile_Size (packet); - case StringExtractorGDBRemote::eServerPacketType_vFile_Mode: + case StringExtractorGDBRemote::eServerPacketType_vFile_mode: return Handle_vFile_Mode (packet); - case StringExtractorGDBRemote::eServerPacketType_vFile_Exists: + case StringExtractorGDBRemote::eServerPacketType_vFile_exists: return Handle_vFile_Exists (packet); - case StringExtractorGDBRemote::eServerPacketType_vFile_Stat: + case StringExtractorGDBRemote::eServerPacketType_vFile_stat: return Handle_vFile_Stat (packet); - case StringExtractorGDBRemote::eServerPacketType_vFile_MD5: + case StringExtractorGDBRemote::eServerPacketType_vFile_md5: return Handle_vFile_MD5 (packet); + + case StringExtractorGDBRemote::eServerPacketType_vFile_symlink: + return Handle_vFile_symlink (packet); + + case StringExtractorGDBRemote::eServerPacketType_vFile_unlink: + return Handle_vFile_unlink (packet); } return true; } @@ -329,12 +323,33 @@ GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet response.PutCStringAsRawHex8(s.c_str()); response.PutChar(';'); } +#if defined(__APPLE__) + +#if defined(__arm__) + // For iOS devices, we are connected through a USB Mux so we never pretend + // to actually have a hostname as far as the remote lldb that is connecting + // to this lldb-platform is concerned + response.PutCString ("hostname:"); + response.PutCStringAsRawHex8("localhost"); + response.PutChar(';'); +#else // #if defined(__arm__) + if (Host::GetHostname (s)) + { + response.PutCString ("hostname:"); + response.PutCStringAsRawHex8(s.c_str()); + response.PutChar(';'); + } + +#endif // #if defined(__arm__) + +#else // #if defined(__APPLE__) if (Host::GetHostname (s)) { response.PutCString ("hostname:"); response.PutCStringAsRawHex8(s.c_str()); response.PutChar(';'); } +#endif // #if defined(__APPLE__) return SendPacketNoLock (response.GetData(), response.GetSize()) > 0; } @@ -731,6 +746,7 @@ bool GDBRemoteCommunicationServer::DebugserverProcessReaped (lldb::pid_t pid) { Mutex::Locker locker (m_spawned_pids_mutex); + FreePortForProcess(pid); return m_spawned_pids.erase(pid) > 0; } bool @@ -764,105 +780,119 @@ GDBRemoteCommunicationServer::Handle_qLaunchGDBServer (StringExtractorGDBRemote std::string hostname; // TODO: /tmp/ should not be hardcoded. User might want to override /tmp // with the TMPDIR environnement variable - char unix_socket_name[PATH_MAX] = "/tmp/XXXXXX"; - if (::mkstemp (unix_socket_name) == -1) + packet.SetFilePos(::strlen ("qLaunchGDBServer;")); + std::string name; + std::string value; + uint16_t port = UINT16_MAX; + while (packet.GetNameColonValue(name, value)) { - error.SetErrorStringWithFormat("failed to make temporary path for a unix socket: %s", strerror(errno)); + if (name.compare ("host") == 0) + hostname.swap(value); + else if (name.compare ("port") == 0) + port = Args::StringToUInt32(value.c_str(), 0, 0); } - else - { - 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 = Args::StringToUInt32(value.c_str(), 0, 0); - } - if (port == UINT16_MAX) - port = GetAndUpdateNextPort(); + if (port == UINT16_MAX) + port = GetNextAvailablePort(); - ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name); - // Spawn a new thread to accept the port that gets bound after - // binding to port 0 (zero). - lldb::thread_t accept_thread = LLDB_INVALID_HOST_THREAD; + // Spawn a new thread to accept the port that gets bound after + // binding to port 0 (zero). + lldb::thread_t accept_thread = LLDB_INVALID_HOST_THREAD; + const char *unix_socket_name = NULL; + char unix_socket_name_buf[PATH_MAX] = "/tmp/XXXXXXXXX"; - if (port == 0) + if (port == 0) + { + if (::mkstemp (unix_socket_name_buf) == 0) { + unix_socket_name = unix_socket_name_buf; + ::snprintf (connect_url, sizeof(connect_url), "unix-accept://%s", unix_socket_name); accept_thread = Host::ThreadCreate (unix_socket_name, AcceptPortFromInferior, connect_url, &error); } + else + { + error.SetErrorStringWithFormat("failed to make temporary path for a unix socket: %s", strerror(errno)); + } + } - if (IS_VALID_LLDB_HOST_THREAD(accept_thread)) + if (error.Success()) + { + // Spawn a debugserver and try to get the port it listens to. + ProcessLaunchInfo debugserver_launch_info; + StreamString host_and_port; + if (hostname.empty()) + hostname = "localhost"; + host_and_port.Printf("%s:%u", hostname.c_str(), port); + const char *host_and_port_cstr = host_and_port.GetString().c_str(); + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); + if (log) + log->Printf("Launching debugserver with: %s...\n", host_and_port_cstr); + + debugserver_launch_info.SetMonitorProcessCallback(ReapDebugserverProcess, this, false); + + error = StartDebugserverProcess (host_and_port_cstr, + unix_socket_name, + debugserver_launch_info); + + lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID(); + + + if (debugserver_pid != LLDB_INVALID_PROCESS_ID) { - // Spawn a debugserver and try to get the port it listens to. - ProcessLaunchInfo debugserver_launch_info; - StreamString host_and_port; - if (hostname.empty()) - hostname = "localhost"; - host_and_port.Printf("%s:%u", hostname.c_str(), port); - const char *host_and_port_cstr = host_and_port.GetString().c_str(); - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); - if (log) - log->Printf("Launching debugserver with: %s...\n", host_and_port_cstr); - error = StartDebugserverProcess (host_and_port_cstr, - unix_socket_name, - debugserver_launch_info); - - lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID(); - - if (debugserver_pid != LLDB_INVALID_PROCESS_ID) - { - { - Mutex::Locker locker (m_spawned_pids_mutex); - m_spawned_pids.insert(debugserver_pid); - } - Host::StartMonitoringChildProcess (ReapDebugserverProcess, this, debugserver_pid, false); - } + Mutex::Locker locker (m_spawned_pids_mutex); + m_spawned_pids.insert(debugserver_pid); + if (port > 0) + AssociatePortWithProcess(port, debugserver_pid); + } + else + { + if (port > 0) + FreePort (port); + } - if (error.Success()) - { - bool success = false; + if (error.Success()) + { + bool success = false; - if (accept_thread) + if (IS_VALID_LLDB_HOST_THREAD(accept_thread)) + { + thread_result_t accept_thread_result = NULL; + if (Host::ThreadJoin (accept_thread, &accept_thread_result, &error)) { - thread_result_t accept_thread_result = NULL; - if (Host::ThreadJoin (accept_thread, &accept_thread_result, &error)) + if (accept_thread_result) { - if (accept_thread_result) - { - port = (intptr_t)accept_thread_result; - char response[256]; - const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port); - assert (response_len < sizeof(response)); - //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID(); - success = SendPacketNoLock (response, response_len) > 0; - } + port = (intptr_t)accept_thread_result; + char response[256]; + const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset); + assert (response_len < sizeof(response)); + //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID(); + success = SendPacketNoLock (response, response_len) > 0; } } - else - { - char response[256]; - const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port); - assert (response_len < sizeof(response)); - //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID(); - success = SendPacketNoLock (response, response_len) > 0; + } + else + { + char response[256]; + const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset); + assert (response_len < sizeof(response)); + //m_port_to_pid_map[port] = debugserver_launch_info.GetProcessID(); + success = SendPacketNoLock (response, response_len) > 0; - } - ::unlink (unix_socket_name); + } + Host::Unlink (unix_socket_name); - if (!success) - { - if (debugserver_pid != LLDB_INVALID_PROCESS_ID) - ::kill (debugserver_pid, SIGINT); - } - return success; + if (!success) + { + if (debugserver_pid != LLDB_INVALID_PROCESS_ID) + ::kill (debugserver_pid, SIGINT); } + return success; + } + else if (accept_thread) + { + Host::Unlink (unix_socket_name); } } } @@ -896,7 +926,7 @@ GDBRemoteCommunicationServer::Handle_qKillSpawnedProcess (StringExtractorGDBRemo { Mutex::Locker locker (m_spawned_pids_mutex); if (m_spawned_pids.find(pid) == m_spawned_pids.end()) - return true; + return SendOKResponse(); } usleep (10000); } @@ -905,7 +935,7 @@ GDBRemoteCommunicationServer::Handle_qKillSpawnedProcess (StringExtractorGDBRemo { Mutex::Locker locker (m_spawned_pids_mutex); if (m_spawned_pids.find(pid) == m_spawned_pids.end()) - return true; + return SendOKResponse(); } Host::Kill (pid, SIGKILL); @@ -915,12 +945,12 @@ GDBRemoteCommunicationServer::Handle_qKillSpawnedProcess (StringExtractorGDBRemo { Mutex::Locker locker (m_spawned_pids_mutex); if (m_spawned_pids.find(pid) == m_spawned_pids.end()) - return true; + return SendOKResponse(); } usleep (10000); } } - return SendErrorResponse (10); + return SendErrorResponse (11); } bool @@ -944,7 +974,7 @@ GDBRemoteCommunicationServer::Handle_QEnvironment (StringExtractorGDBRemote &pa m_process_launch_info.GetEnvironmentEntries ().AppendArgument (packet.Peek()); return SendOKResponse (); } - return SendErrorResponse (11); + return SendErrorResponse (12); } bool @@ -959,7 +989,7 @@ GDBRemoteCommunicationServer::Handle_QLaunchArch (StringExtractorGDBRemote &pack m_process_launch_info.SetArchitecture(arch_spec); return SendOKResponse(); } - return SendErrorResponse(12); + return SendErrorResponse(13); } bool @@ -979,11 +1009,61 @@ GDBRemoteCommunicationServer::Handle_QSetWorkingDir (StringExtractorGDBRemote &p packet.SetFilePos(::strlen ("QSetWorkingDir:")); std::string path; packet.GetHexByteString(path); - m_process_launch_info.SwapWorkingDirectory (path); + if (m_is_platform) + { +#ifdef _WIN32 + // Not implemented on Windows + return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_QSetWorkingDir unimplemented"); +#else + // If this packet is sent to a platform, then change the current working directory + if (::chdir(path.c_str()) != 0) + return SendErrorResponse(errno); +#endif + } + else + { + m_process_launch_info.SwapWorkingDirectory (path); + } return SendOKResponse (); } bool +GDBRemoteCommunicationServer::Handle_qGetWorkingDir (StringExtractorGDBRemote &packet) +{ + StreamString response; + + if (m_is_platform) + { + // If this packet is sent to a platform, then change the current working directory + char cwd[PATH_MAX]; + if (getcwd(cwd, sizeof(cwd)) == NULL) + { + return SendErrorResponse(errno); + } + else + { + response.PutBytesAsRawHex8(cwd, strlen(cwd)); + SendPacketNoLock(response.GetData(), response.GetSize()); + return true; + } + } + else + { + const char *working_dir = m_process_launch_info.GetWorkingDirectory(); + if (working_dir && working_dir[0]) + { + response.PutBytesAsRawHex8(working_dir, strlen(working_dir)); + SendPacketNoLock(response.GetData(), response.GetSize()); + return true; + } + else + { + return SendErrorResponse(14); + } + } +} + +bool GDBRemoteCommunicationServer::Handle_QSetSTDIN (StringExtractorGDBRemote &packet) { packet.SetFilePos(::strlen ("QSetSTDIN:")); @@ -997,7 +1077,7 @@ GDBRemoteCommunicationServer::Handle_QSetSTDIN (StringExtractorGDBRemote &packet m_process_launch_info.AppendFileAction(file_action); return SendOKResponse (); } - return SendErrorResponse (13); + return SendErrorResponse (15); } bool @@ -1014,7 +1094,7 @@ GDBRemoteCommunicationServer::Handle_QSetSTDOUT (StringExtractorGDBRemote &packe m_process_launch_info.AppendFileAction(file_action); return SendOKResponse (); } - return SendErrorResponse (14); + return SendErrorResponse (16); } bool @@ -1031,7 +1111,7 @@ GDBRemoteCommunicationServer::Handle_QSetSTDERR (StringExtractorGDBRemote &packe m_process_launch_info.AppendFileAction(file_action); return SendOKResponse (); } - return SendErrorResponse (15); + return SendErrorResponse (17); } bool @@ -1044,19 +1124,40 @@ GDBRemoteCommunicationServer::Handle_QStartNoAckMode (StringExtractorGDBRemote & } bool -GDBRemoteCommunicationServer::Handle_qPlatform_IO_MkDir (StringExtractorGDBRemote &packet) +GDBRemoteCommunicationServer::Handle_qPlatform_mkdir (StringExtractorGDBRemote &packet) { - packet.SetFilePos(::strlen("qPlatform_IO_MkDir:")); + packet.SetFilePos(::strlen("qPlatform_mkdir:")); mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX); - if (packet.GetChar() != ',') - return false; - std::string path; - packet.GetHexByteString(path); - uint32_t retcode = Host::MakeDirectory(path.c_str(),mode); - StreamString response; - response.PutHex32(retcode); - SendPacketNoLock(response.GetData(), response.GetSize()); - return true; + if (packet.GetChar() == ',') + { + std::string path; + packet.GetHexByteString(path); + Error error = Host::MakeDirectory(path.c_str(),mode); + if (error.Success()) + return SendPacketNoLock ("OK", 2); + else + return SendErrorResponse(error.GetError()); + } + return SendErrorResponse(20); +} + +bool +GDBRemoteCommunicationServer::Handle_qPlatform_chmod (StringExtractorGDBRemote &packet) +{ + packet.SetFilePos(::strlen("qPlatform_chmod:")); + + mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX); + if (packet.GetChar() == ',') + { + std::string path; + packet.GetHexByteString(path); + Error error = Host::SetFilePermissions (path.c_str(), mode); + if (error.Success()) + return SendPacketNoLock ("OK", 2); + else + return SendErrorResponse(error.GetError()); + } + return SendErrorResponse(19); } bool @@ -1065,24 +1166,28 @@ GDBRemoteCommunicationServer::Handle_vFile_Open (StringExtractorGDBRemote &packe packet.SetFilePos(::strlen("vFile:open:")); std::string path; packet.GetHexByteStringTerminatedBy(path,','); - if (path.size() == 0) - return false; - if (packet.GetChar() != ',') - return false; - uint32_t flags = packet.GetHexMaxU32(false, UINT32_MAX); - if (packet.GetChar() != ',') - return false; - mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX); - Error error; - int fd = ::open (path.c_str(), flags, mode); - const int save_errno = fd == -1 ? errno : 0; - StreamString response; - response.PutChar('F'); - response.Printf("%i", fd); - if (save_errno) - response.Printf(",%i", save_errno); - SendPacketNoLock(response.GetData(), response.GetSize()); - return true; + if (!path.empty()) + { + if (packet.GetChar() == ',') + { + uint32_t flags = packet.GetHexMaxU32(false, 0); + if (packet.GetChar() == ',') + { + mode_t mode = packet.GetHexMaxU32(false, 0600); + Error error; + int fd = ::open (path.c_str(), flags, mode); + printf ("open('%s', flags=0x%x, mode=%o) fd = %i (%s)\n", path.c_str(), flags, mode, fd, fd == -1 ? strerror(errno) : "<success>"); + const int save_errno = fd == -1 ? errno : 0; + StreamString response; + response.PutChar('F'); + response.Printf("%i", fd); + if (save_errno) + response.Printf(",%i", save_errno); + return SendPacketNoLock(response.GetData(), response.GetSize()); + } + } + } + return SendErrorResponse(18); } bool @@ -1107,8 +1212,7 @@ GDBRemoteCommunicationServer::Handle_vFile_Close (StringExtractorGDBRemote &pack response.Printf("%i", err); if (save_errno) response.Printf(",%i", save_errno); - SendPacketNoLock(response.GetData(), response.GetSize()); - return true; + return SendPacketNoLock(response.GetData(), response.GetSize()); } bool @@ -1116,37 +1220,40 @@ GDBRemoteCommunicationServer::Handle_vFile_pRead (StringExtractorGDBRemote &pack { #ifdef _WIN32 // Not implemented on Windows - return false; + return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_vFile_pRead() unimplemented"); #else StreamGDBRemote response; packet.SetFilePos(::strlen("vFile:pread:")); int fd = packet.GetS32(-1); - if (packet.GetChar() != ',') - return false; - uint64_t count = packet.GetU64(UINT64_MAX); - if (packet.GetChar() != ',') - return false; - uint64_t offset = packet.GetU64(UINT32_MAX); - if (count == UINT64_MAX) - { - response.Printf("F-1:%i", EINVAL); - SendPacketNoLock(response.GetData(), response.GetSize()); - return true; - } - 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 + if (packet.GetChar() == ',') { - response.PutChar(';'); - response.PutEscapedBytes(&buffer[0], bytes_read); + 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.GetData(), response.GetSize()); + } + + 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.GetData(), response.GetSize()); + } } - SendPacketNoLock(response.GetData(), response.GetSize()); - return true; + return SendErrorResponse(21); + #endif } @@ -1154,8 +1261,7 @@ bool GDBRemoteCommunicationServer::Handle_vFile_pWrite (StringExtractorGDBRemote &packet) { #ifdef _WIN32 - // Not implemented on Windows - return false; + return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_vFile_pWrite() unimplemented"); #else packet.SetFilePos(::strlen("vFile:pwrite:")); @@ -1163,27 +1269,28 @@ GDBRemoteCommunicationServer::Handle_vFile_pWrite (StringExtractorGDBRemote &pac response.PutChar('F'); int fd = packet.GetU32(UINT32_MAX); - if (packet.GetChar() != ',') - return false; - off_t offset = packet.GetU64(UINT32_MAX); - if (packet.GetChar() != ',') - return false; - 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 + if (packet.GetChar() == ',') { - response.Printf ("-1,%i", EINVAL); + 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.GetData(), response.GetSize()); + } } - - SendPacketNoLock(response.GetData(), response.GetSize()); - return true; + return SendErrorResponse(27); #endif } @@ -1193,19 +1300,20 @@ GDBRemoteCommunicationServer::Handle_vFile_Size (StringExtractorGDBRemote &packe packet.SetFilePos(::strlen("vFile:size:")); std::string path; packet.GetHexByteString(path); - if (path.empty()) - return false; - lldb::user_id_t retcode = Host::GetFileSize(FileSpec(path.c_str(), false)); - StreamString response; - response.PutChar('F'); - response.PutHex64(retcode); - if (retcode == UINT64_MAX) + if (!path.empty()) { - response.PutChar(','); - response.PutHex64(retcode); // TODO: replace with Host::GetSyswideErrorCode() + lldb::user_id_t retcode = Host::GetFileSize(FileSpec(path.c_str(), false)); + StreamString response; + response.PutChar('F'); + response.PutHex64(retcode); + if (retcode == UINT64_MAX) + { + response.PutChar(','); + response.PutHex64(retcode); // TODO: replace with Host::GetSyswideErrorCode() + } + return SendPacketNoLock(response.GetData(), response.GetSize()); } - SendPacketNoLock(response.GetData(), response.GetSize()); - return true; + return SendErrorResponse(22); } bool @@ -1214,16 +1322,17 @@ GDBRemoteCommunicationServer::Handle_vFile_Mode (StringExtractorGDBRemote &packe packet.SetFilePos(::strlen("vFile:mode:")); std::string path; packet.GetHexByteString(path); - if (path.empty()) - return false; - Error error; - const uint32_t mode = File::GetPermissions(path.c_str(), error); - StreamString response; - response.Printf("F%u", mode); - if (mode == 0 || error.Fail()) - response.Printf(",%i", (int)error.GetError()); - SendPacketNoLock(response.GetData(), response.GetSize()); - return true; + if (!path.empty()) + { + Error error; + const uint32_t mode = File::GetPermissions(path.c_str(), error); + StreamString response; + response.Printf("F%u", mode); + if (mode == 0 || error.Fail()) + response.Printf(",%i", (int)error.GetError()); + return SendPacketNoLock(response.GetData(), response.GetSize()); + } + return SendErrorResponse(23); } bool @@ -1232,87 +1341,118 @@ GDBRemoteCommunicationServer::Handle_vFile_Exists (StringExtractorGDBRemote &pac packet.SetFilePos(::strlen("vFile:exists:")); std::string path; packet.GetHexByteString(path); - if (path.empty()) - return false; - bool retcode = Host::GetFileExists(FileSpec(path.c_str(), false)); + if (!path.empty()) + { + bool retcode = Host::GetFileExists(FileSpec(path.c_str(), false)); + StreamString response; + response.PutChar('F'); + response.PutChar(','); + if (retcode) + response.PutChar('1'); + else + response.PutChar('0'); + return SendPacketNoLock(response.GetData(), response.GetSize()); + } + return SendErrorResponse(24); +} + +bool +GDBRemoteCommunicationServer::Handle_vFile_symlink (StringExtractorGDBRemote &packet) +{ + packet.SetFilePos(::strlen("vFile:symlink:")); + std::string dst, src; + packet.GetHexByteStringTerminatedBy(dst, ','); + packet.GetChar(); // Skip ',' char + packet.GetHexByteString(src); + Error error = Host::Symlink(src.c_str(), dst.c_str()); StreamString response; - response.PutChar('F'); - response.PutChar(','); - if (retcode) - response.PutChar('1'); - else - response.PutChar('0'); - SendPacketNoLock(response.GetData(), response.GetSize()); - return true; + response.Printf("F%u,%u", error.GetError(), error.GetError()); + return SendPacketNoLock(response.GetData(), response.GetSize()); } bool -GDBRemoteCommunicationServer::Handle_qPlatform_RunCommand (StringExtractorGDBRemote &packet) +GDBRemoteCommunicationServer::Handle_vFile_unlink (StringExtractorGDBRemote &packet) { - packet.SetFilePos(::strlen("qPlatform_RunCommand:")); + packet.SetFilePos(::strlen("vFile:unlink:")); + std::string path; + packet.GetHexByteString(path); + Error error = Host::Unlink(path.c_str()); + StreamString response; + response.Printf("F%u,%u", error.GetError(), error.GetError()); + return SendPacketNoLock(response.GetData(), response.GetSize()); +} + +bool +GDBRemoteCommunicationServer::Handle_qPlatform_shell (StringExtractorGDBRemote &packet) +{ + packet.SetFilePos(::strlen("qPlatform_shell:")); std::string path; std::string working_dir; packet.GetHexByteStringTerminatedBy(path,','); - if (path.size() == 0) - return false; - if (packet.GetChar() != ',') - return false; - // FIXME: add timeout to qPlatform_RunCommand 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()) + if (!path.empty()) { - 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()); + 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()); + } } - SendPacketNoLock(response.GetData(), response.GetSize()); - return true; + return SendErrorResponse(24); } bool GDBRemoteCommunicationServer::Handle_vFile_Stat (StringExtractorGDBRemote &packet) { - return false; + return SendUnimplementedResponse("GDBRemoteCommunicationServer::Handle_vFile_Stat() unimplemented"); } bool GDBRemoteCommunicationServer::Handle_vFile_MD5 (StringExtractorGDBRemote &packet) { - packet.SetFilePos(::strlen("vFile:exists:")); + packet.SetFilePos(::strlen("vFile:MD5:")); std::string path; packet.GetHexByteString(path); - if (path.size() == 0) - return false; - uint64_t a,b; - StreamGDBRemote response; - if (Host::CalculateMD5(FileSpec(path.c_str(),false),a,b) == false) + if (!path.empty()) { - response.PutCString("F,"); - response.PutCString("x"); - } - else - { - response.PutCString("F,"); - response.PutHex64(a); - response.PutHex64(b); + 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()); } - SendPacketNoLock(response.GetData(), response.GetSize()); - return true; + return SendErrorResponse(25); } + |