diff options
Diffstat (limited to 'source/Plugins/Process/gdb-remote')
7 files changed, 456 insertions, 213 deletions
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp index 1f4dd93..919fa54 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -17,15 +17,16 @@ // C++ Includes // Other libraries and framework includes -#include "lldb/Core/ConnectionFileDescriptor.h" #include "lldb/Core/Log.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/StreamString.h" +#include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/FileSpec.h" -#include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" +#include "lldb/Host/Pipe.h" #include "lldb/Host/Socket.h" +#include "lldb/Host/ThreadLauncher.h" #include "lldb/Host/TimeValue.h" #include "lldb/Target/Process.h" @@ -153,7 +154,6 @@ GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name, m_history (512), m_send_acks (true), m_is_platform (is_platform), - m_listen_thread (LLDB_INVALID_HOST_THREAD), m_listen_url () { } @@ -227,9 +227,23 @@ GDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_le Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS)); ConnectionStatus status = eConnectionStatusSuccess; - size_t bytes_written = Write (packet.GetData(), packet.GetSize(), status, NULL); + const char *packet_data = packet.GetData(); + const size_t packet_length = packet.GetSize(); + size_t bytes_written = Write (packet_data, packet_length, status, NULL); if (log) { + size_t binary_start_offset = 0; + if (strncmp(packet_data, "$vFile:pwrite:", strlen("$vFile:pwrite:")) == 0) + { + const char *first_comma = strchr(packet_data, ','); + if (first_comma) + { + const char *second_comma = strchr(first_comma + 1, ','); + if (second_comma) + binary_start_offset = second_comma - packet_data + 1; + } + } + // If logging was just enabled and we have history, then dump out what // we have to the log so we get the historical context. The Dump() call that // logs all of the packet will set a boolean so that we don't dump this more @@ -237,13 +251,27 @@ GDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_le if (!m_history.DidDumpToLog ()) m_history.Dump (log); - log->Printf("<%4" PRIu64 "> send packet: %.*s", (uint64_t)bytes_written, (int)packet.GetSize(), packet.GetData()); + if (binary_start_offset) + { + StreamString strm; + // Print non binary data header + strm.Printf("<%4" PRIu64 "> send packet: %.*s", (uint64_t)bytes_written, (int)binary_start_offset, packet_data); + const uint8_t *p; + // Print binary data exactly as sent + for (p = (uint8_t*)packet_data + binary_start_offset; *p != '#'; ++p) + strm.Printf("\\x%2.2x", *p); + // Print the checksum + strm.Printf("%*s", (int)3, p); + log->PutCString(strm.GetString().c_str()); + } + else + log->Printf("<%4" PRIu64 "> send packet: %.*s", (uint64_t)bytes_written, (int)packet_length, packet_data); } - m_history.AddPacket (packet.GetString(), packet.GetSize(), History::ePacketTypeSend, bytes_written); + m_history.AddPacket (packet.GetString(), packet_length, History::ePacketTypeSend, bytes_written); - if (bytes_written == packet.GetSize()) + if (bytes_written == packet_length) { if (GetSendAcks ()) return GetAck (); @@ -253,7 +281,7 @@ GDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_le else { if (log) - log->Printf ("error: failed to send packet: %.*s", (int)packet.GetSize(), packet.GetData()); + log->Printf ("error: failed to send packet: %.*s", (int)packet_length, packet_data); } } return PacketResult::ErrorSendFailed; @@ -447,8 +475,8 @@ GDBRemoteCommunication::CheckForPacket (const uint8_t *src, size_t src_len, Stri } if (log) log->Printf ("GDBRemoteCommunication::%s tossing %u junk bytes: '%.*s'", - __FUNCTION__, idx, idx, m_bytes.c_str()); - m_bytes.erase(0, idx); + __FUNCTION__, idx - 1, idx - 1, m_bytes.c_str()); + m_bytes.erase(0, idx - 1); } break; } @@ -606,7 +634,7 @@ Error GDBRemoteCommunication::StartListenThread (const char *hostname, uint16_t port) { Error error; - if (IS_VALID_LLDB_HOST_THREAD(m_listen_thread)) + if (m_listen_thread.IsJoinable()) { error.SetErrorString("listen thread already running"); } @@ -619,7 +647,7 @@ GDBRemoteCommunication::StartListenThread (const char *hostname, uint16_t port) snprintf(listen_url, sizeof(listen_url), "listen://%i", port); m_listen_url = listen_url; SetConnection(new ConnectionFileDescriptor()); - m_listen_thread = Host::ThreadCreate (listen_url, GDBRemoteCommunication::ListenThread, this, &error); + m_listen_thread = ThreadLauncher::LaunchThread(listen_url, GDBRemoteCommunication::ListenThread, this, &error); } return error; } @@ -627,11 +655,8 @@ GDBRemoteCommunication::StartListenThread (const char *hostname, uint16_t port) bool GDBRemoteCommunication::JoinListenThread () { - if (IS_VALID_LLDB_HOST_THREAD(m_listen_thread)) - { - Host::ThreadJoin(m_listen_thread, NULL, NULL); - m_listen_thread = LLDB_INVALID_HOST_THREAD; - } + if (m_listen_thread.IsJoinable()) + m_listen_thread.Join(nullptr); return true; } @@ -738,6 +763,7 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, char named_pipe_path[PATH_MAX]; named_pipe_path[0] = '\0'; + Pipe port_named_pipe; bool listen = false; if (host_and_port[0]) @@ -763,15 +789,11 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, if (::mktemp (named_pipe_path)) { -#if defined(_WIN32) - if ( false ) -#else - if (::mkfifo(named_pipe_path, 0600) == 0) -#endif - { - debugserver_args.AppendArgument("--named-pipe"); - debugserver_args.AppendArgument(named_pipe_path); - } + error = port_named_pipe.CreateNew(named_pipe_path, false); + if (error.Fail()) + return error; + debugserver_args.AppendArgument("--named-pipe"); + debugserver_args.AppendArgument(named_pipe_path); } } else @@ -838,11 +860,15 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, } } while (has_env_var); - // Close STDIN, STDOUT and STDERR. We might need to redirect them - // to "/dev/null" if we run into any problems. + // Close STDIN, STDOUT and STDERR. launch_info.AppendCloseFileAction (STDIN_FILENO); launch_info.AppendCloseFileAction (STDOUT_FILENO); launch_info.AppendCloseFileAction (STDERR_FILENO); + + // Redirect STDIN, STDOUT and STDERR to "/dev/null". + launch_info.AppendSuppressFileAction (STDIN_FILENO, true, false); + launch_info.AppendSuppressFileAction (STDOUT_FILENO, false, true); + launch_info.AppendSuppressFileAction (STDERR_FILENO, false, true); error = Host::LaunchProcess(launch_info); @@ -850,20 +876,40 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, { if (named_pipe_path[0]) { - File name_pipe_file; - error = name_pipe_file.Open(named_pipe_path, File::eOpenOptionRead); + error = port_named_pipe.OpenAsReader(named_pipe_path, false); if (error.Success()) { char port_cstr[256]; port_cstr[0] = '\0'; size_t num_bytes = sizeof(port_cstr); - error = name_pipe_file.Read(port_cstr, num_bytes); - assert (error.Success()); - assert (num_bytes > 0 && port_cstr[num_bytes-1] == '\0'); - out_port = Args::StringToUInt32(port_cstr, 0); - name_pipe_file.Close(); + // Read port from pipe with 10 second timeout. + error = port_named_pipe.ReadWithTimeout(port_cstr, num_bytes, std::chrono::microseconds(10 * 1000000), num_bytes); + if (error.Success()) + { + assert (num_bytes > 0 && port_cstr[num_bytes-1] == '\0'); + out_port = Args::StringToUInt32(port_cstr, 0); + if (log) + log->Printf("GDBRemoteCommunication::%s() debugserver listens %u port", __FUNCTION__, out_port); + } + else + { + if (log) + log->Printf("GDBRemoteCommunication::%s() failed to read a port value from named pipe %s: %s", __FUNCTION__, named_pipe_path, error.AsCString()); + + } + port_named_pipe.Close(); + } + else + { + if (log) + log->Printf("GDBRemoteCommunication::%s() failed to open named pipe %s for reading: %s", __FUNCTION__, named_pipe_path, error.AsCString()); + } + const auto err = port_named_pipe.Delete(named_pipe_path); + if (err.Fail()) + { + if (log) + log->Printf ("GDBRemoteCommunication::%s failed to delete pipe %s: %s", __FUNCTION__, named_pipe_path, err.AsCString()); } - FileSystem::Unlink(named_pipe_path); } else if (listen) { diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h index b11d385..ac203a6 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h @@ -20,6 +20,7 @@ #include "lldb/lldb-public.h" #include "lldb/Core/Communication.h" #include "lldb/Core/Listener.h" +#include "lldb/Host/HostThread.h" #include "lldb/Host/Mutex.h" #include "lldb/Host/Predicate.h" #include "lldb/Host/TimeValue.h" @@ -281,8 +282,7 @@ protected: ListenThread (lldb::thread_arg_t arg); private: - - lldb::thread_t m_listen_thread; + lldb_private::HostThread m_listen_thread; std::string m_listen_url; diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index 5e4ed76..52750de 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -20,11 +20,11 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/Triple.h" #include "lldb/Interpreter/Args.h" -#include "lldb/Core/ConnectionFileDescriptor.h" #include "lldb/Core/Log.h" #include "lldb/Core/State.h" #include "lldb/Core/StreamGDBRemote.h" #include "lldb/Core/StreamString.h" +#include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/Endian.h" #include "lldb/Host/Host.h" #include "lldb/Host/HostInfo.h" @@ -1643,7 +1643,9 @@ GDBRemoteCommunicationClient::GetHostInfo (bool force) } else if (name.compare("triple") == 0) { - triple.swap(value); + extractor.GetStringRef ().swap (value); + extractor.SetFilePos(0); + extractor.GetHexByteString (triple); ++num_keys_decoded; } else if (name.compare ("distribution_id") == 0) @@ -2331,6 +2333,10 @@ GDBRemoteCommunicationClient::DecodeProcessInfoResponse (StringExtractorGDBRemot } else if (name.compare("triple") == 0) { + StringExtractor extractor; + extractor.GetStringRef().swap(value); + extractor.SetFilePos(0); + extractor.GetHexByteString (value); process_info.GetArchitecture ().SetTriple (value.c_str()); } else if (name.compare("name") == 0) @@ -2404,6 +2410,8 @@ GDBRemoteCommunicationClient::GetProcessInfo (lldb::pid_t pid, ProcessInstanceIn bool GDBRemoteCommunicationClient::GetCurrentProcessInfo () { + Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)); + if (m_qProcessInfo_is_valid == eLazyBoolYes) return true; if (m_qProcessInfo_is_valid == eLazyBoolNo) @@ -2426,6 +2434,7 @@ GDBRemoteCommunicationClient::GetCurrentProcessInfo () std::string triple; uint32_t pointer_byte_size = 0; StringExtractor extractor; + ByteOrder byte_order = eByteOrderInvalid; uint32_t num_keys_decoded = 0; lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; while (response.GetNameColonValue(name, value)) @@ -2444,7 +2453,10 @@ GDBRemoteCommunicationClient::GetCurrentProcessInfo () } else if (name.compare("triple") == 0) { - triple = value; + StringExtractor extractor; + extractor.GetStringRef().swap(value); + extractor.SetFilePos(0); + extractor.GetHexByteString (triple); ++num_keys_decoded; } else if (name.compare("ostype") == 0) @@ -2459,10 +2471,15 @@ GDBRemoteCommunicationClient::GetCurrentProcessInfo () } else if (name.compare("endian") == 0) { - if (value.compare("little") == 0 || - value.compare("big") == 0 || - value.compare("pdp") == 0) - ++num_keys_decoded; + ++num_keys_decoded; + if (value.compare("little") == 0) + byte_order = eByteOrderLittle; + else if (value.compare("big") == 0) + byte_order = eByteOrderBig; + else if (value.compare("pdp") == 0) + byte_order = eByteOrderPDP; + else + --num_keys_decoded; } else if (name.compare("ptrsize") == 0) { @@ -2496,11 +2513,34 @@ GDBRemoteCommunicationClient::GetCurrentProcessInfo () } else if (cpu != LLDB_INVALID_CPUTYPE && !os_name.empty() && !vendor_name.empty()) { - m_process_arch.SetArchitecture (eArchTypeMachO, cpu, sub); + llvm::Triple triple(llvm::Twine("-") + vendor_name + "-" + os_name); + + assert(triple.getObjectFormat() != llvm::Triple::UnknownObjectFormat); + switch (triple.getObjectFormat()) { + case llvm::Triple::MachO: + m_process_arch.SetArchitecture (eArchTypeMachO, cpu, sub); + break; + case llvm::Triple::ELF: + m_process_arch.SetArchitecture (eArchTypeELF, cpu, sub); + break; + case llvm::Triple::COFF: + m_process_arch.SetArchitecture (eArchTypeCOFF, cpu, sub); + break; + case llvm::Triple::UnknownObjectFormat: + if (log) + log->Printf("error: failed to determine target architecture"); + return false; + } + if (pointer_byte_size) { assert (pointer_byte_size == m_process_arch.GetAddressByteSize()); } + if (byte_order != eByteOrderInvalid) + { + assert (byte_order == m_process_arch.GetByteOrder()); + } + m_process_arch.GetTriple().setVendorName (llvm::StringRef (vendor_name)); m_process_arch.GetTriple().setOSName(llvm::StringRef (os_name)); m_host_arch.GetTriple().setVendorName (llvm::StringRef (vendor_name)); m_host_arch.GetTriple().setOSName (llvm::StringRef (os_name)); @@ -2931,6 +2971,11 @@ GDBRemoteCommunicationClient::GetThreadStopInfo (lldb::tid_t tid, StringExtracto uint8_t GDBRemoteCommunicationClient::SendGDBStoppointTypePacket (GDBStoppointType type, bool insert, addr_t addr, uint32_t length) { + Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS)); + if (log) + log->Printf ("GDBRemoteCommunicationClient::%s() %s at addr = 0x%" PRIx64, + __FUNCTION__, insert ? "add" : "remove", addr); + // Check if the stub is known not to support this breakpoint type if (!SupportsGDBStoppointPacket(type)) return UINT8_MAX; diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp index ffcdd16..a714950 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp @@ -23,11 +23,11 @@ // Other libraries and framework includes #include "llvm/ADT/Triple.h" #include "lldb/Interpreter/Args.h" -#include "lldb/Core/ConnectionFileDescriptor.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/Log.h" #include "lldb/Core/State.h" #include "lldb/Core/StreamString.h" +#include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/Debug.h" #include "lldb/Host/Endian.h" #include "lldb/Host/File.h" @@ -71,7 +71,7 @@ namespace //---------------------------------------------------------------------- GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(bool is_platform) : GDBRemoteCommunication ("gdb-remote.server", "gdb-remote.server.rx_packet", is_platform), - m_platform_sp (Platform::GetDefaultPlatform ()), + m_platform_sp (Platform::GetHostPlatform ()), m_async_thread (LLDB_INVALID_HOST_THREAD), m_process_launch_info (), m_process_launch_error (), @@ -429,6 +429,14 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec, case StringExtractorGDBRemote::eServerPacketType_vAttach: packet_result = Handle_vAttach (packet); break; + + case StringExtractorGDBRemote::eServerPacketType_D: + packet_result = Handle_D (packet); + break; + + case StringExtractorGDBRemote::eServerPacketType_qThreadStopInfo: + packet_result = Handle_qThreadStopInfo (packet); + break; } } else @@ -474,13 +482,34 @@ GDBRemoteCommunicationServer::LaunchProcess () // FIXME This looks an awful lot like we could override this in // derived classes, one for lldb-platform, the other for lldb-gdbserver. if (IsGdbServer ()) - return LaunchDebugServerProcess (); + return LaunchProcessForDebugging (); else return LaunchPlatformProcess (); } +bool +GDBRemoteCommunicationServer::ShouldRedirectInferiorOutputOverGdbRemote (const lldb_private::ProcessLaunchInfo &launch_info) const +{ + // Retrieve the file actions specified for stdout and stderr. + auto stdout_file_action = launch_info.GetFileActionForFD (STDOUT_FILENO); + auto stderr_file_action = launch_info.GetFileActionForFD (STDERR_FILENO); + + // If neither stdout and stderr file actions are specified, we're not doing anything special, so + // assume we want to redirect stdout/stderr over gdb-remote $O messages. + if ((stdout_file_action == nullptr) && (stderr_file_action == nullptr)) + { + // Send stdout/stderr over the gdb-remote protocol. + return true; + } + + // Any other setting for either stdout or stderr implies we are either suppressing + // it (with /dev/null) or we've got it set to a PTY. Either way, we don't want the + // output over gdb-remote. + return false; +} + lldb_private::Error -GDBRemoteCommunicationServer::LaunchDebugServerProcess () +GDBRemoteCommunicationServer::LaunchProcessForDebugging () { Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); @@ -503,20 +532,34 @@ GDBRemoteCommunicationServer::LaunchDebugServerProcess () return error; } - // Setup stdout/stderr mapping from inferior. - auto terminal_fd = m_debugged_process_sp->GetTerminalFileDescriptor (); - if (terminal_fd >= 0) + // Handle mirroring of inferior stdout/stderr over the gdb-remote protocol as needed. + // llgs local-process debugging may specify PTYs, which will eliminate the need to reflect inferior + // stdout/stderr over the gdb-remote protocol. + if (ShouldRedirectInferiorOutputOverGdbRemote (m_process_launch_info)) { if (log) - log->Printf ("ProcessGDBRemoteCommunicationServer::%s setting inferior STDIO fd to %d", __FUNCTION__, terminal_fd); - error = SetSTDIOFileDescriptor (terminal_fd); - if (error.Fail ()) - return error; + log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " setting up stdout/stderr redirection via $O gdb-remote commands", __FUNCTION__, m_debugged_process_sp->GetID ()); + + // Setup stdout/stderr mapping from inferior to $O + auto terminal_fd = m_debugged_process_sp->GetTerminalFileDescriptor (); + if (terminal_fd >= 0) + { + if (log) + log->Printf ("ProcessGDBRemoteCommunicationServer::%s setting inferior STDIO fd to %d", __FUNCTION__, terminal_fd); + error = SetSTDIOFileDescriptor (terminal_fd); + if (error.Fail ()) + return error; + } + else + { + if (log) + log->Printf ("ProcessGDBRemoteCommunicationServer::%s ignoring inferior STDIO since terminal fd reported as %d", __FUNCTION__, terminal_fd); + } } else { if (log) - log->Printf ("ProcessGDBRemoteCommunicationServer::%s ignoring inferior STDIO since terminal fd reported as %d", __FUNCTION__, terminal_fd); + log->Printf ("GDBRemoteCommunicationServer::%s pid %" PRIu64 " skipping stdout/stderr redirection via $O: inferior will communicate over client-provided file descriptors", __FUNCTION__, m_debugged_process_sp->GetID ()); } printf ("Launched '%s' as process %" PRIu64 "...\n", m_process_launch_info.GetArguments ().GetArgumentAtIndex (0), m_process_launch_info.GetProcessID ()); @@ -526,33 +569,10 @@ GDBRemoteCommunicationServer::LaunchDebugServerProcess () if ((pid = m_process_launch_info.GetProcessID ()) != LLDB_INVALID_PROCESS_ID) { // add to spawned pids - { - Mutex::Locker locker (m_spawned_pids_mutex); - // On an lldb-gdbserver, we would expect there to be only one. - assert (m_spawned_pids.empty () && "lldb-gdbserver adding tracked process but one already existed"); - m_spawned_pids.insert (pid); - } - } - - if (error.Success ()) - { - if (log) - log->Printf ("GDBRemoteCommunicationServer::%s beginning check to wait for launched application to hit first stop", __FUNCTION__); - - int iteration = 0; - // Wait for the process to hit its first stop state. - while (!StateIsStoppedState (m_debugged_process_sp->GetState (), false)) - { - if (log) - log->Printf ("GDBRemoteCommunicationServer::%s waiting for launched process to hit first stop (%d)...", __FUNCTION__, iteration++); - - // FIXME use a finer granularity. - std::this_thread::sleep_for(std::chrono::seconds(1)); - } - - if (log) - log->Printf ("GDBRemoteCommunicationServer::%s launched application has hit first stop", __FUNCTION__); - + Mutex::Locker locker (m_spawned_pids_mutex); + // On an lldb-gdbserver, we would expect there to be only one. + assert (m_spawned_pids.empty () && "lldb-gdbserver adding tracked process but one already existed"); + m_spawned_pids.insert (pid); } return error; @@ -699,12 +719,18 @@ GDBRemoteCommunicationServer::SendWResponse (lldb_private::NativeProcessProtocol char return_type_code; switch (exit_type) { - case ExitType::eExitTypeExit: return_type_code = 'W'; break; - case ExitType::eExitTypeSignal: return_type_code = 'X'; break; - case ExitType::eExitTypeStop: return_type_code = 'S'; break; - + case ExitType::eExitTypeExit: + return_type_code = 'W'; + break; + case ExitType::eExitTypeSignal: + return_type_code = 'X'; + break; + case ExitType::eExitTypeStop: + return_type_code = 'S'; + break; case ExitType::eExitTypeInvalid: - default: return_type_code = 'E'; break; + return_type_code = 'E'; + break; } response.PutChar (return_type_code); @@ -861,21 +887,21 @@ GDBRemoteCommunicationServer::SendStopReplyPacketForThread (lldb::tid_t tid) response.Printf ("thread:%" PRIx64 ";", tid); // Include the thread name if there is one. - const char *thread_name = thread_sp->GetName (); - if (thread_name && thread_name[0]) + const std::string thread_name = thread_sp->GetName (); + if (!thread_name.empty ()) { - size_t thread_name_len = strlen(thread_name); + size_t thread_name_len = thread_name.length (); - if (::strcspn (thread_name, "$#+-;:") == thread_name_len) + if (::strcspn (thread_name.c_str (), "$#+-;:") == thread_name_len) { response.PutCString ("name:"); - response.PutCString (thread_name); + response.PutCString (thread_name.c_str ()); } else { // The thread name contains special chars, send as hex bytes. response.PutCString ("hexname:"); - response.PutCStringAsRawHex8 (thread_name); + response.PutCStringAsRawHex8 (thread_name.c_str ()); } response.PutChar (';'); } @@ -1197,7 +1223,7 @@ GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet ArchSpec host_arch(HostInfo::GetArchitecture()); const llvm::Triple &host_triple = host_arch.GetTriple(); response.PutCString("triple:"); - response.PutCString(host_triple.getTriple().c_str()); + response.PutCStringAsRawHex8(host_triple.getTriple().c_str()); response.Printf (";ptrsize:%u;",host_arch.GetAddressByteSize()); const char* distribution_id = host_arch.GetDistributionId ().AsCString (); @@ -1252,7 +1278,6 @@ GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet } std::string s; -#if !defined(__linux__) if (HostInfo::GetOSBuildString(s)) { response.PutCString ("os_build:"); @@ -1265,7 +1290,6 @@ GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet response.PutCStringAsRawHex8(s.c_str()); response.PutChar(';'); } -#endif #if defined(__APPLE__) @@ -1315,7 +1339,7 @@ CreateProcessInfoResponse (const ProcessInstanceInfo &proc_info, StreamString &r { const llvm::Triple &proc_triple = proc_arch.GetTriple(); response.PutCString("triple:"); - response.PutCString(proc_triple.getTriple().c_str()); + response.PutCStringAsRawHex8(proc_triple.getTriple().c_str()); response.PutChar(';'); } } @@ -1351,7 +1375,10 @@ CreateProcessInfoResponse_DebugServerStyle (const ProcessInstanceInfo &proc_info response.Printf ("vendor:%s;", vendor.c_str ()); #else // We'll send the triple. - response.Printf ("triple:%s;", proc_triple.getTriple().c_str ()); + response.PutCString("triple:"); + response.PutCStringAsRawHex8(proc_triple.getTriple().c_str()); + response.PutChar(';'); + #endif std::string ostype = proc_triple.getOSName (); // Adjust so ostype reports ios for Apple/ARM and Apple/ARM64. @@ -2372,8 +2399,6 @@ GDBRemoteCommunicationServer::Handle_vCont_actions (StringExtractorGDBRemote &pa return SendUnimplementedResponse (packet.GetStringRef().c_str()); } - // We handle $vCont messages for c. - // TODO add C, s and S. StreamString response; response.Printf("vCont;c;C;s;S"); @@ -3388,10 +3413,8 @@ GDBRemoteCommunicationServer::Handle_interrupt (StringExtractorGDBRemote &packet return SendErrorResponse (0x15); } - // Build the ResumeActionList - stop everything. - lldb_private::ResumeActionList actions (StateType::eStateStopped, 0); - - Error error = m_debugged_process_sp->Resume (actions); + // Interrupt the process. + Error error = m_debugged_process_sp->Interrupt (); if (error.Fail ()) { if (log) @@ -3771,7 +3794,7 @@ GDBRemoteCommunicationServer::Handle_z (StringExtractorGDBRemote &packet) } // Parse out software or hardware breakpoint requested. - packet.SetFilePos (strlen("Z")); + packet.SetFilePos (strlen("z")); if (packet.GetBytesLeft() < 1) return SendIllFormedResponse(packet, "Too short z packet, missing software/hardware specifier"); @@ -3811,7 +3834,7 @@ GDBRemoteCommunicationServer::Handle_z (StringExtractorGDBRemote &packet) if (want_breakpoint) { - // Try to set the breakpoint. + // Try to clear the breakpoint. const Error error = m_debugged_process_sp->RemoveBreakpoint (breakpoint_addr); if (error.Success ()) return SendOKResponse (); @@ -4171,8 +4194,93 @@ GDBRemoteCommunicationServer::Handle_vAttach (StringExtractorGDBRemote &packet) // Notify we attached by sending a stop packet. return SendStopReasonForState (m_debugged_process_sp->GetState (), true); +} - return PacketResult::Success; +GDBRemoteCommunicationServer::PacketResult +GDBRemoteCommunicationServer::Handle_D (StringExtractorGDBRemote &packet) +{ + Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS)); + + // We don't support if we're not llgs. + if (!IsGdbServer()) + return SendUnimplementedResponse ("only supported for lldb-gdbserver"); + + // Scope for mutex locker. + Mutex::Locker locker (m_spawned_pids_mutex); + + // Fail if we don't have a current process. + if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) + { + if (log) + log->Printf ("GDBRemoteCommunicationServer::%s failed, no process available", __FUNCTION__); + return SendErrorResponse (0x15); + } + + if (m_spawned_pids.find(m_debugged_process_sp->GetID ()) == m_spawned_pids.end()) + { + if (log) + log->Printf ("GDBRemoteCommunicationServer::%s failed to find PID %" PRIu64 " in spawned pids list", + __FUNCTION__, m_debugged_process_sp->GetID ()); + return SendErrorResponse (0x1); + } + + lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; + + // Consume the ';' after D. + packet.SetFilePos (1); + if (packet.GetBytesLeft ()) + { + if (packet.GetChar () != ';') + return SendIllFormedResponse (packet, "D missing expected ';'"); + + // Grab the PID from which we will detach (assume hex encoding). + pid = packet.GetU32 (LLDB_INVALID_PROCESS_ID, 16); + if (pid == LLDB_INVALID_PROCESS_ID) + return SendIllFormedResponse (packet, "D failed to parse the process id"); + } + + if (pid != LLDB_INVALID_PROCESS_ID && + m_debugged_process_sp->GetID () != pid) + { + return SendIllFormedResponse (packet, "Invalid pid"); + } + + if (m_stdio_communication.IsConnected ()) + { + m_stdio_communication.StopReadThread (); + } + + const Error error = m_debugged_process_sp->Detach (); + if (error.Fail ()) + { + if (log) + log->Printf ("GDBRemoteCommunicationServer::%s failed to detach from pid %" PRIu64 ": %s\n", + __FUNCTION__, m_debugged_process_sp->GetID (), error.AsCString ()); + return SendErrorResponse (0x01); + } + + m_spawned_pids.erase (m_debugged_process_sp->GetID ()); + return SendOKResponse (); +} + +GDBRemoteCommunicationServer::PacketResult +GDBRemoteCommunicationServer::Handle_qThreadStopInfo (StringExtractorGDBRemote &packet) +{ + Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD)); + + // We don't support if we're not llgs. + if (!IsGdbServer()) + return SendUnimplementedResponse ("only supported for lldb-gdbserver"); + + packet.SetFilePos (strlen("qThreadStopInfo")); + const lldb::tid_t tid = packet.GetHexMaxU32 (false, LLDB_INVALID_THREAD_ID); + if (tid == LLDB_INVALID_THREAD_ID) + { + if (log) + log->Printf ("GDBRemoteCommunicationServer::%s failed, could not parse thread id from request \"%s\"", __FUNCTION__, packet.GetStringRef ().c_str ()); + return SendErrorResponse (0x15); + } + return SendStopReplyPacketForThread (tid); } void diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h index 13c037c..07ce98e 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h @@ -58,7 +58,7 @@ public: bool &quit); virtual bool - GetThreadSuffixSupported () + GetThreadSuffixSupported () override { return true; } @@ -152,8 +152,6 @@ public: //------------------------------------------------------------------ /// Specify the program to launch and its arguments. /// - /// The LaunchProcess () command can be executed to do the lauching. - /// /// @param[in] args /// The command line to launch. /// @@ -170,8 +168,6 @@ public: //------------------------------------------------------------------ /// Specify the launch flags for the process. /// - /// The LaunchProcess () command can be executed to do the lauching. - /// /// @param[in] launch_flags /// The launch flags to use when launching this process. /// @@ -463,6 +459,12 @@ protected: PacketResult Handle_vAttach (StringExtractorGDBRemote &packet); + PacketResult + Handle_D (StringExtractorGDBRemote &packet); + + PacketResult + Handle_qThreadStopInfo (StringExtractorGDBRemote &packet); + void SetCurrentThreadID (lldb::tid_t tid); @@ -511,9 +513,9 @@ private: return !m_is_platform; } - /// Launch a process from lldb-gdbserver + /// Launch an inferior process from lldb-gdbserver lldb_private::Error - LaunchDebugServerProcess (); + LaunchProcessForDebugging (); /// Launch a process from lldb-platform lldb_private::Error @@ -540,6 +542,9 @@ private: void ClearProcessSpecificData (); + bool + ShouldRedirectInferiorOutputOverGdbRemote (const lldb_private::ProcessLaunchInfo &launch_info) const; + //------------------------------------------------------------------ // For GDBRemoteCommunicationServer only //------------------------------------------------------------------ diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index f35d954..fe99706 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -14,7 +14,6 @@ #include <errno.h> #include <stdlib.h> #ifndef LLDB_DISABLE_POSIX -#include <spawn.h> #include <netinet/in.h> #include <sys/mman.h> // for mmap #endif @@ -32,7 +31,7 @@ #include "lldb/Interpreter/Args.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Core/Debugger.h" -#include "lldb/Core/ConnectionFileDescriptor.h" +#include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/FileSpec.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" @@ -42,7 +41,9 @@ #include "lldb/Core/StreamString.h" #include "lldb/Core/Timer.h" #include "lldb/Core/Value.h" +#include "lldb/Host/HostThread.h" #include "lldb/Host/Symbols.h" +#include "lldb/Host/ThreadLauncher.h" #include "lldb/Host/TimeValue.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandObject.h" @@ -272,8 +273,6 @@ ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) : m_last_stop_packet_mutex (Mutex::eMutexTypeNormal), m_register_info (), m_async_broadcaster (NULL, "lldb.process.gdb-remote.async-broadcaster"), - m_async_thread (LLDB_INVALID_HOST_THREAD), - m_async_thread_state(eAsyncThreadNotStarted), m_async_thread_state_mutex(Mutex::eMutexTypeRecursive), m_thread_ids (), m_continue_c_tids (), @@ -749,8 +748,12 @@ ProcessGDBRemote::WillLaunchOrAttach () Error ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info) { + Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS)); Error error; + if (log) + log->Printf ("ProcessGDBRemote::%s() entered", __FUNCTION__); + uint32_t launch_flags = launch_info.GetFlags().Get(); const char *stdin_path = NULL; const char *stdout_path = NULL; @@ -777,10 +780,21 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info) stderr_path = file_action->GetPath(); } + if (log) + { + if (stdin_path || stdout_path || stderr_path) + log->Printf ("ProcessGDBRemote::%s provided with STDIO paths via launch_info: stdin=%s, stdout=%s, stdout=%s", + __FUNCTION__, + stdin_path ? stdin_path : "<null>", + stdout_path ? stdout_path : "<null>", + stderr_path ? stderr_path : "<null>"); + else + log->Printf ("ProcessGDBRemote::%s no STDIO paths given via launch_info", __FUNCTION__); + } + // ::LogSetBitMask (GDBR_LOG_DEFAULT); // ::LogSetOptions (LLDB_LOG_OPTION_THREADSAFE | LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD); // ::LogSetLogFile ("/dev/stdout"); - Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS)); ObjectFile * object_file = exe_module->GetObjectFile(); if (object_file) @@ -817,6 +831,13 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info) if (stderr_path == NULL) stderr_path = slave_name; + + if (log) + log->Printf ("ProcessGDBRemote::%s adjusted STDIO paths for local platform (IsHost() is true) using slave: stdin=%s, stdout=%s, stdout=%s", + __FUNCTION__, + stdin_path ? stdin_path : "<null>", + stdout_path ? stdout_path : "<null>", + stderr_path ? stderr_path : "<null>"); } // Set STDIN to /dev/null if we want STDIO disabled or if either @@ -834,7 +855,14 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info) if (disable_stdio || (stderr_path == NULL && (stdin_path || stdout_path))) stderr_path = "/dev/null"; - if (stdin_path) + if (log) + log->Printf ("ProcessGDBRemote::%s final STDIO paths after all adjustments: stdin=%s, stdout=%s, stdout=%s", + __FUNCTION__, + stdin_path ? stdin_path : "<null>", + stdout_path ? stdout_path : "<null>", + stderr_path ? stderr_path : "<null>"); + + if (stdin_path) m_gdb_comm.SetSTDIN (stdin_path); if (stdout_path) m_gdb_comm.SetSTDOUT (stdout_path); @@ -1026,18 +1054,38 @@ ProcessGDBRemote::DidLaunchOrAttach (ArchSpec& process_arch) // prefer that over the Host information as it will be more specific // to our process. - if (m_gdb_comm.GetProcessArchitecture().IsValid()) - process_arch = m_gdb_comm.GetProcessArchitecture(); + const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture(); + if (remote_process_arch.IsValid()) + { + process_arch = remote_process_arch; + if (log) + log->Printf ("ProcessGDBRemote::%s gdb-remote had process architecture, using %s %s", + __FUNCTION__, + process_arch.GetArchitectureName () ? process_arch.GetArchitectureName () : "<null>", + process_arch.GetTriple().getTriple ().c_str() ? process_arch.GetTriple().getTriple ().c_str() : "<null>"); + } else + { process_arch = m_gdb_comm.GetHostArchitecture(); + if (log) + log->Printf ("ProcessGDBRemote::%s gdb-remote did not have process architecture, using gdb-remote host architecture %s %s", + __FUNCTION__, + process_arch.GetArchitectureName () ? process_arch.GetArchitectureName () : "<null>", + process_arch.GetTriple().getTriple ().c_str() ? process_arch.GetTriple().getTriple ().c_str() : "<null>"); + } if (process_arch.IsValid()) { ArchSpec &target_arch = GetTarget().GetArchitecture(); - if (target_arch.IsValid()) { - // If the remote host is ARM and we have apple as the vendor, then + if (log) + log->Printf ("ProcessGDBRemote::%s analyzing target arch, currently %s %s", + __FUNCTION__, + target_arch.GetArchitectureName () ? target_arch.GetArchitectureName () : "<null>", + target_arch.GetTriple().getTriple ().c_str() ? target_arch.GetTriple().getTriple ().c_str() : "<null>"); + + // If the remote host is ARM and we have apple as the vendor, then // ARM executables and shared libraries can have mixed ARM architectures. // You can have an armv6 executable, and if the host is armv7, then the // system will load the best possible architecture for all shared libraries @@ -1048,6 +1096,11 @@ ProcessGDBRemote::DidLaunchOrAttach (ArchSpec& process_arch) process_arch.GetTriple().getVendor() == llvm::Triple::Apple) { GetTarget().SetArchitecture (process_arch); + if (log) + log->Printf ("ProcessGDBRemote::%s remote process is ARM/Apple, setting target arch to %s %s", + __FUNCTION__, + process_arch.GetArchitectureName () ? process_arch.GetArchitectureName () : "<null>", + process_arch.GetTriple().getTriple ().c_str() ? process_arch.GetTriple().getTriple ().c_str() : "<null>"); } else { @@ -1066,7 +1119,14 @@ ProcessGDBRemote::DidLaunchOrAttach (ArchSpec& process_arch) target_triple.setEnvironment (remote_triple.getEnvironment()); } } + } + + if (log) + log->Printf ("ProcessGDBRemote::%s final target arch after adjustments for remote architecture: %s %s", + __FUNCTION__, + target_arch.GetArchitectureName () ? target_arch.GetArchitectureName () : "<null>", + target_arch.GetTriple().getTriple ().c_str() ? target_arch.GetTriple().getTriple ().c_str() : "<null>"); } else { @@ -1095,7 +1155,12 @@ ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid) Error ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid, const ProcessAttachInfo &attach_info) { + Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS)); Error error; + + if (log) + log->Printf ("ProcessGDBRemote::%s()", __FUNCTION__); + // Clear out and clean up from any current state Clear(); if (attach_pid != LLDB_INVALID_PROCESS_ID) @@ -1118,13 +1183,14 @@ ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid, const Process if (error.Success()) { m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError()); - + char packet[64]; const int packet_len = ::snprintf (packet, sizeof(packet), "vAttach;%" PRIx64, attach_pid); SetID (attach_pid); m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (packet, packet_len)); } } + return error; } @@ -1432,7 +1498,7 @@ ProcessGDBRemote::DoResume () TimeValue timeout; timeout = TimeValue::Now(); timeout.OffsetWithSeconds (5); - if (!IS_VALID_LLDB_HOST_THREAD(m_async_thread)) + if (!m_async_thread.IsJoinable()) { error.SetErrorString ("Trying to resume but the async thread is dead."); if (log) @@ -2891,30 +2957,17 @@ ProcessGDBRemote::StartAsyncThread () log->Printf ("ProcessGDBRemote::%s ()", __FUNCTION__); Mutex::Locker start_locker(m_async_thread_state_mutex); - if (m_async_thread_state == eAsyncThreadNotStarted) + if (!m_async_thread.IsJoinable()) { // Create a thread that watches our internal state and controls which // events make it to clients (into the DCProcess event queue). - m_async_thread = Host::ThreadCreate ("<lldb.process.gdb-remote.async>", ProcessGDBRemote::AsyncThread, this, NULL); - if (IS_VALID_LLDB_HOST_THREAD(m_async_thread)) - { - m_async_thread_state = eAsyncThreadRunning; - return true; - } - else - return false; - } - else - { - // Somebody tried to start the async thread while it was either being started or stopped. If the former, and - // it started up successfully, then say all's well. Otherwise it is an error, since we aren't going to restart it. - if (log) - log->Printf ("ProcessGDBRemote::%s () - Called when Async thread was in state: %d.", __FUNCTION__, m_async_thread_state); - if (m_async_thread_state == eAsyncThreadRunning) - return true; - else - return false; + + m_async_thread = ThreadLauncher::LaunchThread("<lldb.process.gdb-remote.async>", ProcessGDBRemote::AsyncThread, this, NULL); } + else if (log) + log->Printf("ProcessGDBRemote::%s () - Called when Async thread was already running.", __FUNCTION__); + + return m_async_thread.IsJoinable(); } void @@ -2926,7 +2979,7 @@ ProcessGDBRemote::StopAsyncThread () log->Printf ("ProcessGDBRemote::%s ()", __FUNCTION__); Mutex::Locker start_locker(m_async_thread_state_mutex); - if (m_async_thread_state == eAsyncThreadRunning) + if (m_async_thread.IsJoinable()) { m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncThreadShouldExit); @@ -2934,17 +2987,10 @@ ProcessGDBRemote::StopAsyncThread () m_gdb_comm.Disconnect(); // Disconnect from the debug server. // Stop the stdio thread - if (IS_VALID_LLDB_HOST_THREAD(m_async_thread)) - { - Host::ThreadJoin (m_async_thread, NULL, NULL); - } - m_async_thread_state = eAsyncThreadDone; - } - else - { - if (log) - log->Printf ("ProcessGDBRemote::%s () - Called when Async thread was in state: %d.", __FUNCTION__, m_async_thread_state); + m_async_thread.Join(nullptr); } + else if (log) + log->Printf("ProcessGDBRemote::%s () - Called when Async thread was not running.", __FUNCTION__); } @@ -3086,7 +3132,7 @@ ProcessGDBRemote::AsyncThread (void *arg) if (log) log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") thread exiting...", __FUNCTION__, arg, process->GetID()); - process->m_async_thread = LLDB_INVALID_HOST_THREAD; + process->m_async_thread.Reset(); return NULL; } diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index 942b31c..e0c460a 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -25,6 +25,7 @@ #include "lldb/Core/StringList.h" #include "lldb/Core/StructuredData.h" #include "lldb/Core/ThreadSafeValue.h" +#include "lldb/Host/HostThread.h" #include "lldb/lldb-private-forward.h" #include "lldb/Target/Process.h" #include "lldb/Target/Thread.h" @@ -74,148 +75,148 @@ public: //------------------------------------------------------------------ virtual bool CanDebug (lldb_private::Target &target, - bool plugin_specified_by_name); + bool plugin_specified_by_name) override; virtual lldb_private::CommandObject * - GetPluginCommandObject(); + GetPluginCommandObject() override; //------------------------------------------------------------------ // Creating a new process, or attaching to an existing one //------------------------------------------------------------------ virtual lldb_private::Error - WillLaunch (lldb_private::Module* module); + WillLaunch (lldb_private::Module* module) override; virtual lldb_private::Error DoLaunch (lldb_private::Module *exe_module, - lldb_private::ProcessLaunchInfo &launch_info); + lldb_private::ProcessLaunchInfo &launch_info) override; virtual void - DidLaunch (); + DidLaunch () override; virtual lldb_private::Error - WillAttachToProcessWithID (lldb::pid_t pid); + WillAttachToProcessWithID (lldb::pid_t pid) override; virtual lldb_private::Error - WillAttachToProcessWithName (const char *process_name, bool wait_for_launch); + WillAttachToProcessWithName (const char *process_name, bool wait_for_launch) override; virtual lldb_private::Error - DoConnectRemote (lldb_private::Stream *strm, const char *remote_url); + DoConnectRemote (lldb_private::Stream *strm, const char *remote_url) override; lldb_private::Error WillLaunchOrAttach (); virtual lldb_private::Error - DoAttachToProcessWithID (lldb::pid_t pid); + DoAttachToProcessWithID (lldb::pid_t pid) override; virtual lldb_private::Error - DoAttachToProcessWithID (lldb::pid_t pid, const lldb_private::ProcessAttachInfo &attach_info); + DoAttachToProcessWithID (lldb::pid_t pid, const lldb_private::ProcessAttachInfo &attach_info) override; virtual lldb_private::Error DoAttachToProcessWithName (const char *process_name, - const lldb_private::ProcessAttachInfo &attach_info); + const lldb_private::ProcessAttachInfo &attach_info) override; virtual void - DidAttach (lldb_private::ArchSpec &process_arch); + DidAttach (lldb_private::ArchSpec &process_arch) override; //------------------------------------------------------------------ // PluginInterface protocol //------------------------------------------------------------------ virtual lldb_private::ConstString - GetPluginName(); + GetPluginName() override; virtual uint32_t - GetPluginVersion(); + GetPluginVersion() override; //------------------------------------------------------------------ // Process Control //------------------------------------------------------------------ virtual lldb_private::Error - WillResume (); + WillResume () override; virtual lldb_private::Error - DoResume (); + DoResume () override; virtual lldb_private::Error - DoHalt (bool &caused_stop); + DoHalt (bool &caused_stop) override; virtual lldb_private::Error - DoDetach (bool keep_stopped); + DoDetach (bool keep_stopped) override; virtual bool - DetachRequiresHalt() { return true; } + DetachRequiresHalt() override { return true; } virtual lldb_private::Error - DoSignal (int signal); + DoSignal (int signal) override; virtual lldb_private::Error - DoDestroy (); + DoDestroy () override; virtual void - RefreshStateAfterStop(); + RefreshStateAfterStop() override; //------------------------------------------------------------------ // Process Queries //------------------------------------------------------------------ virtual bool - IsAlive (); + IsAlive () override; virtual lldb::addr_t - GetImageInfoAddress(); + GetImageInfoAddress() override; //------------------------------------------------------------------ // Process Memory //------------------------------------------------------------------ virtual size_t - DoReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error); + DoReadMemory (lldb::addr_t addr, void *buf, size_t size, lldb_private::Error &error) override; virtual size_t - DoWriteMemory (lldb::addr_t addr, const void *buf, size_t size, lldb_private::Error &error); + DoWriteMemory (lldb::addr_t addr, const void *buf, size_t size, lldb_private::Error &error) override; virtual lldb::addr_t - DoAllocateMemory (size_t size, uint32_t permissions, lldb_private::Error &error); + DoAllocateMemory (size_t size, uint32_t permissions, lldb_private::Error &error) override; virtual lldb_private::Error GetMemoryRegionInfo (lldb::addr_t load_addr, - lldb_private::MemoryRegionInfo ®ion_info); + lldb_private::MemoryRegionInfo ®ion_info) override; virtual lldb_private::Error - DoDeallocateMemory (lldb::addr_t ptr); + DoDeallocateMemory (lldb::addr_t ptr) override; //------------------------------------------------------------------ // Process STDIO //------------------------------------------------------------------ virtual size_t - PutSTDIN (const char *buf, size_t buf_size, lldb_private::Error &error); + PutSTDIN (const char *buf, size_t buf_size, lldb_private::Error &error) override; //---------------------------------------------------------------------- // Process Breakpoints //---------------------------------------------------------------------- virtual lldb_private::Error - EnableBreakpointSite (lldb_private::BreakpointSite *bp_site); + EnableBreakpointSite (lldb_private::BreakpointSite *bp_site) override; virtual lldb_private::Error - DisableBreakpointSite (lldb_private::BreakpointSite *bp_site); + DisableBreakpointSite (lldb_private::BreakpointSite *bp_site) override; //---------------------------------------------------------------------- // Process Watchpoints //---------------------------------------------------------------------- virtual lldb_private::Error - EnableWatchpoint (lldb_private::Watchpoint *wp, bool notify = true); + EnableWatchpoint (lldb_private::Watchpoint *wp, bool notify = true) override; virtual lldb_private::Error - DisableWatchpoint (lldb_private::Watchpoint *wp, bool notify = true); + DisableWatchpoint (lldb_private::Watchpoint *wp, bool notify = true) override; virtual lldb_private::Error - GetWatchpointSupportInfo (uint32_t &num); + GetWatchpointSupportInfo (uint32_t &num) override; virtual lldb_private::Error - GetWatchpointSupportInfo (uint32_t &num, bool& after); + GetWatchpointSupportInfo (uint32_t &num, bool& after) override; virtual bool - StartNoticingNewThreads(); + StartNoticingNewThreads() override; virtual bool - StopNoticingNewThreads(); + StopNoticingNewThreads() override; GDBRemoteCommunicationClient & GetGDBRemote() @@ -224,13 +225,13 @@ public: } virtual lldb_private::Error - SendEventData(const char *data); + SendEventData(const char *data) override; //---------------------------------------------------------------------- // Override SetExitStatus so we can disconnect from the remote GDB server //---------------------------------------------------------------------- virtual bool - SetExitStatus (int exit_status, const char *cstr); + SetExitStatus (int exit_status, const char *cstr) override; void SetUserSpecifiedMaxMemoryTransferSize (uint64_t user_specified_max); @@ -286,7 +287,7 @@ protected: virtual bool UpdateThreadList (lldb_private::ThreadList &old_thread_list, - lldb_private::ThreadList &new_thread_list); + lldb_private::ThreadList &new_thread_list) override; lldb_private::Error LaunchAndConnectToDebugserver (const lldb_private::ProcessInfo &process_info); @@ -324,23 +325,15 @@ protected: eBroadcastBitAsyncThreadShouldExit = (1 << 1), eBroadcastBitAsyncThreadDidExit = (1 << 2) }; - - typedef enum AsyncThreadState - { - eAsyncThreadNotStarted, - eAsyncThreadRunning, - eAsyncThreadDone - } AsyncThreadState; lldb_private::Flags m_flags; // Process specific flags (see eFlags enums) GDBRemoteCommunicationClient m_gdb_comm; - lldb::pid_t m_debugserver_pid; + std::atomic<lldb::pid_t> m_debugserver_pid; StringExtractorGDBRemote m_last_stop_packet; lldb_private::Mutex m_last_stop_packet_mutex; GDBRemoteDynamicRegisterInfo m_register_info; lldb_private::Broadcaster m_async_broadcaster; - lldb::thread_t m_async_thread; - AsyncThreadState m_async_thread_state; + lldb_private::HostThread m_async_thread; lldb_private::Mutex m_async_thread_state_mutex; typedef std::vector<lldb::tid_t> tid_collection; typedef std::vector< std::pair<lldb::tid_t,int> > tid_sig_collection; @@ -395,7 +388,7 @@ protected: std::string &dispatch_queue_name); lldb_private::DynamicLoader * - GetDynamicLoader (); + GetDynamicLoader () override; private: //------------------------------------------------------------------ |