diff options
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote')
12 files changed, 543 insertions, 436 deletions
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp index 2ea1f20..f164b14 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -793,8 +793,8 @@ GDBRemoteCommunication::PacketType GDBRemoteCommunication::CheckForPacket (const uint8_t *src, size_t src_len, StringExtractorGDBRemote &packet) { // Put the packet data into the buffer in a thread safe fashion - Mutex::Locker locker(m_bytes_mutex); - + std::lock_guard<std::recursive_mutex> guard(m_bytes_mutex); + Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS)); if (src && src_len > 0) @@ -845,7 +845,7 @@ GDBRemoteCommunication::CheckForPacket (const uint8_t *src, size_t src_len, Stri case '%': // Async notify packet isNotifyPacket = true; - // Intentional fall through + LLVM_FALLTHROUGH; case '$': // Look for a standard gdb packet? @@ -1120,7 +1120,7 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *url, { Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS)); if (log) - log->Printf ("GDBRemoteCommunication::%s(url=%s, port=%" PRIu16, __FUNCTION__, url ? url : "<empty>", port ? *port : uint16_t(0)); + log->Printf ("GDBRemoteCommunication::%s(url=%s, port=%" PRIu16 ")", __FUNCTION__, url ? url : "<empty>", port ? *port : uint16_t(0)); Error error; // If we locate debugserver, keep that located version around @@ -1352,7 +1352,14 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *url, launch_info.AppendSuppressFileAction (STDIN_FILENO, true, false); launch_info.AppendSuppressFileAction (STDOUT_FILENO, false, true); launch_info.AppendSuppressFileAction (STDERR_FILENO, false, true); - + + if (log) + { + StreamString string_stream; + Platform *const platform = nullptr; + launch_info.Dump(string_stream, platform); + log->Printf("launch info for gdb-remote stub:\n%s", string_stream.GetString().c_str()); + } error = Host::LaunchProcess(launch_info); if (error.Success() && diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index c0ea9cc..a792bbb 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -55,79 +55,79 @@ using namespace lldb_private::process_gdb_remote; //---------------------------------------------------------------------- // GDBRemoteCommunicationClient constructor //---------------------------------------------------------------------- -GDBRemoteCommunicationClient::GDBRemoteCommunicationClient() : - GDBRemoteCommunication("gdb-remote.client", "gdb-remote.client.rx_packet"), - m_supports_not_sending_acks (eLazyBoolCalculate), - m_supports_thread_suffix (eLazyBoolCalculate), - m_supports_threads_in_stop_reply (eLazyBoolCalculate), - m_supports_vCont_all (eLazyBoolCalculate), - m_supports_vCont_any (eLazyBoolCalculate), - m_supports_vCont_c (eLazyBoolCalculate), - m_supports_vCont_C (eLazyBoolCalculate), - m_supports_vCont_s (eLazyBoolCalculate), - m_supports_vCont_S (eLazyBoolCalculate), - m_qHostInfo_is_valid (eLazyBoolCalculate), - m_curr_pid_is_valid (eLazyBoolCalculate), - m_qProcessInfo_is_valid (eLazyBoolCalculate), - m_qGDBServerVersion_is_valid (eLazyBoolCalculate), - m_supports_alloc_dealloc_memory (eLazyBoolCalculate), - m_supports_memory_region_info (eLazyBoolCalculate), - m_supports_watchpoint_support_info (eLazyBoolCalculate), - m_supports_detach_stay_stopped (eLazyBoolCalculate), - m_watchpoints_trigger_after_instruction(eLazyBoolCalculate), - m_attach_or_wait_reply(eLazyBoolCalculate), - m_prepare_for_reg_writing_reply (eLazyBoolCalculate), - m_supports_p (eLazyBoolCalculate), - m_supports_x (eLazyBoolCalculate), - m_avoid_g_packets (eLazyBoolCalculate), - m_supports_QSaveRegisterState (eLazyBoolCalculate), - m_supports_qXfer_auxv_read (eLazyBoolCalculate), - m_supports_qXfer_libraries_read (eLazyBoolCalculate), - m_supports_qXfer_libraries_svr4_read (eLazyBoolCalculate), - m_supports_qXfer_features_read (eLazyBoolCalculate), - m_supports_augmented_libraries_svr4_read (eLazyBoolCalculate), - m_supports_jThreadExtendedInfo (eLazyBoolCalculate), - m_supports_jLoadedDynamicLibrariesInfos (eLazyBoolCalculate), - m_supports_qProcessInfoPID (true), - m_supports_qfProcessInfo (true), - m_supports_qUserName (true), - m_supports_qGroupName (true), - m_supports_qThreadStopInfo (true), - m_supports_z0 (true), - m_supports_z1 (true), - m_supports_z2 (true), - m_supports_z3 (true), - m_supports_z4 (true), - m_supports_QEnvironment (true), - m_supports_QEnvironmentHexEncoded (true), - m_supports_qSymbol (true), - m_qSymbol_requests_done (false), - m_supports_qModuleInfo (true), - m_supports_jThreadsInfo (true), - m_curr_pid (LLDB_INVALID_PROCESS_ID), - m_curr_tid (LLDB_INVALID_THREAD_ID), - m_curr_tid_run (LLDB_INVALID_THREAD_ID), - m_num_supported_hardware_watchpoints (0), - m_async_mutex (Mutex::eMutexTypeRecursive), - m_async_packet_predicate (false), - m_async_packet (), - m_async_result (PacketResult::Success), - m_async_response (), - m_async_signal (-1), - m_interrupt_sent (false), - m_thread_id_to_used_usec_map (), - m_host_arch(), - m_process_arch(), - m_os_version_major (UINT32_MAX), - m_os_version_minor (UINT32_MAX), - m_os_version_update (UINT32_MAX), - m_os_build (), - m_os_kernel (), - m_hostname (), - m_gdb_server_name(), - m_gdb_server_version(UINT32_MAX), - m_default_packet_timeout (0), - m_max_packet_size (0) +GDBRemoteCommunicationClient::GDBRemoteCommunicationClient() + : GDBRemoteCommunication("gdb-remote.client", "gdb-remote.client.rx_packet"), + m_supports_not_sending_acks(eLazyBoolCalculate), + m_supports_thread_suffix(eLazyBoolCalculate), + m_supports_threads_in_stop_reply(eLazyBoolCalculate), + m_supports_vCont_all(eLazyBoolCalculate), + m_supports_vCont_any(eLazyBoolCalculate), + m_supports_vCont_c(eLazyBoolCalculate), + m_supports_vCont_C(eLazyBoolCalculate), + m_supports_vCont_s(eLazyBoolCalculate), + m_supports_vCont_S(eLazyBoolCalculate), + m_qHostInfo_is_valid(eLazyBoolCalculate), + m_curr_pid_is_valid(eLazyBoolCalculate), + m_qProcessInfo_is_valid(eLazyBoolCalculate), + m_qGDBServerVersion_is_valid(eLazyBoolCalculate), + m_supports_alloc_dealloc_memory(eLazyBoolCalculate), + m_supports_memory_region_info(eLazyBoolCalculate), + m_supports_watchpoint_support_info(eLazyBoolCalculate), + m_supports_detach_stay_stopped(eLazyBoolCalculate), + m_watchpoints_trigger_after_instruction(eLazyBoolCalculate), + m_attach_or_wait_reply(eLazyBoolCalculate), + m_prepare_for_reg_writing_reply(eLazyBoolCalculate), + m_supports_p(eLazyBoolCalculate), + m_supports_x(eLazyBoolCalculate), + m_avoid_g_packets(eLazyBoolCalculate), + m_supports_QSaveRegisterState(eLazyBoolCalculate), + m_supports_qXfer_auxv_read(eLazyBoolCalculate), + m_supports_qXfer_libraries_read(eLazyBoolCalculate), + m_supports_qXfer_libraries_svr4_read(eLazyBoolCalculate), + m_supports_qXfer_features_read(eLazyBoolCalculate), + m_supports_augmented_libraries_svr4_read(eLazyBoolCalculate), + m_supports_jThreadExtendedInfo(eLazyBoolCalculate), + m_supports_jLoadedDynamicLibrariesInfos(eLazyBoolCalculate), + m_supports_qProcessInfoPID(true), + m_supports_qfProcessInfo(true), + m_supports_qUserName(true), + m_supports_qGroupName(true), + m_supports_qThreadStopInfo(true), + m_supports_z0(true), + m_supports_z1(true), + m_supports_z2(true), + m_supports_z3(true), + m_supports_z4(true), + m_supports_QEnvironment(true), + m_supports_QEnvironmentHexEncoded(true), + m_supports_qSymbol(true), + m_qSymbol_requests_done(false), + m_supports_qModuleInfo(true), + m_supports_jThreadsInfo(true), + m_curr_pid(LLDB_INVALID_PROCESS_ID), + m_curr_tid(LLDB_INVALID_THREAD_ID), + m_curr_tid_run(LLDB_INVALID_THREAD_ID), + m_num_supported_hardware_watchpoints(0), + m_async_mutex(), + m_async_packet_predicate(false), + m_async_packet(), + m_async_result(PacketResult::Success), + m_async_response(), + m_async_signal(-1), + m_interrupt_sent(false), + m_thread_id_to_used_usec_map(), + m_host_arch(), + m_process_arch(), + m_os_version_major(UINT32_MAX), + m_os_version_minor(UINT32_MAX), + m_os_version_update(UINT32_MAX), + m_os_build(), + m_os_kernel(), + m_hostname(), + m_gdb_server_name(), + m_gdb_server_version(UINT32_MAX), + m_default_packet_timeout(0), + m_max_packet_size(0) { } @@ -623,6 +623,7 @@ GDBRemoteCommunicationClient::GetThreadsInfo() if (m_supports_jThreadsInfo) { StringExtractorGDBRemote response; + response.SetResponseValidatorToJSON(); if (SendPacketAndWaitForResponse("jThreadsInfo", response, false) == PacketResult::Success) { if (response.IsUnsupportedResponse()) @@ -765,9 +766,29 @@ GDBRemoteCommunicationClient::SendPacketAndWaitForResponseNoLock (const char *pa size_t payload_length, StringExtractorGDBRemote &response) { - PacketResult packet_result = SendPacketNoLock (payload, payload_length); + PacketResult packet_result = SendPacketNoLock(payload, payload_length); if (packet_result == PacketResult::Success) - packet_result = ReadPacket (response, GetPacketTimeoutInMicroSeconds (), true); + { + const size_t max_response_retries = 3; + for (size_t i=0; i<max_response_retries; ++i) + { + packet_result = ReadPacket(response, GetPacketTimeoutInMicroSeconds (), true); + // Make sure we received a response + if (packet_result != PacketResult::Success) + return packet_result; + // Make sure our response is valid for the payload that was sent + if (response.ValidateResponse()) + return packet_result; + // Response says it wasn't valid + Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS); + if (log) + log->Printf("error: packet with payload \"%*s\" got invalid response \"%s\": %s", + (int)payload_length, + payload, + response.GetStringRef().c_str(), + (i == (max_response_retries - 1)) ? "using invalid response and giving up" : "ignoring response and waiting for another"); + } + } return packet_result; } @@ -786,8 +807,8 @@ GDBRemoteCommunicationClient::SendPacketAndWaitForResponse // In order to stop async notifications from being processed in the middle of the // send/receive sequence Hijack the broadcast. Then rebroadcast any events when we are done. - static Listener hijack_listener("lldb.NotifyHijacker"); - HijackBroadcaster(&hijack_listener, eBroadcastBitGdbReadThreadGotNotify); + static ListenerSP hijack_listener_sp(Listener::MakeListener("lldb.NotifyHijacker")); + HijackBroadcaster(hijack_listener_sp, eBroadcastBitGdbReadThreadGotNotify); if (GetSequenceMutex (locker)) { @@ -799,8 +820,9 @@ GDBRemoteCommunicationClient::SendPacketAndWaitForResponse { if (IsRunning()) { - Mutex::Locker async_locker (m_async_mutex); + std::lock_guard<std::recursive_mutex> guard(m_async_mutex); m_async_packet.assign(payload, payload_length); + m_async_response.CopyResponseValidator(response); m_async_packet_predicate.SetValue (true, eBroadcastNever); if (log) @@ -867,6 +889,9 @@ GDBRemoteCommunicationClient::SendPacketAndWaitForResponse if (log) log->Printf ("async: failed to interrupt"); } + + m_async_response.SetResponseValidator(nullptr, nullptr); + } else { @@ -886,7 +911,7 @@ GDBRemoteCommunicationClient::SendPacketAndWaitForResponse // If a notification event occurred, rebroadcast since it can now be processed safely. EventSP event_sp; - if (hijack_listener.GetNextEvent(event_sp)) + if (hijack_listener_sp->GetNextEvent(event_sp)) BroadcastEvent(event_sp); return packet_result; @@ -1136,13 +1161,17 @@ GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse // which will just re-send a copy of the last stop reply // packet. If we don't do this, then the reply for our // async packet will be the repeat stop reply packet and cause - // a lot of trouble for us! - if (signo != sigint_signo && signo != sigstop_signo) + // a lot of trouble for us! We also have some debugserver + // binaries that would send two stop replies anytime the process + // was interrupted, so we need to also check for an extra + // stop reply packet if we interrupted the process + const bool received_nonstop_signal = signo != sigint_signo && signo != sigstop_signo; + if (m_interrupt_sent || received_nonstop_signal) { - continue_after_async = false; + if (received_nonstop_signal) + continue_after_async = false; - // We didn't get a SIGINT or SIGSTOP, so try for a - // very brief time (0.1s) to get another stop reply + // Try for a very brief time (0.1s) to get another stop reply // packet to make sure it doesn't get in the way StringExtractorGDBRemote extra_stop_reply_packet; uint32_t timeout_usec = 100000; @@ -1343,7 +1372,7 @@ GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse bool GDBRemoteCommunicationClient::SendAsyncSignal (int signo) { - Mutex::Locker async_locker (m_async_mutex); + std::lock_guard<std::recursive_mutex> guard(m_async_mutex); m_async_signal = signo; bool timed_out = false; Mutex::Locker locker; @@ -2064,7 +2093,8 @@ GDBRemoteCommunicationClient::GetHostInfo (bool force) if (pointer_byte_size != 0) ++num_keys_decoded; } - else if (name.compare("os_version") == 0) + else if ((name.compare("os_version") == 0) || + (name.compare("version") == 0)) // Older debugserver binaries used the "version" key instead of "os_version"... { Args::StringToVersion (value.c_str(), m_os_version_major, @@ -2114,20 +2144,6 @@ GDBRemoteCommunicationClient::GetHostInfo (bool force) assert (byte_order == m_host_arch.GetByteOrder()); } - if (!os_name.empty() && vendor_name.compare("apple") == 0 && os_name.find("darwin") == 0) - { - switch (m_host_arch.GetMachine()) - { - case llvm::Triple::aarch64: - case llvm::Triple::arm: - case llvm::Triple::thumb: - os_name = "ios"; - break; - default: - os_name = "macosx"; - break; - } - } if (!vendor_name.empty()) m_host_arch.GetTriple().setVendorName (llvm::StringRef (vendor_name)); if (!os_name.empty()) @@ -2411,6 +2427,8 @@ GDBRemoteCommunicationClient::GetMemoryRegionInfo (lldb::addr_t addr, region_info.SetExecutable (MemoryRegionInfo::eYes); else region_info.SetExecutable (MemoryRegionInfo::eNo); + + region_info.SetMapped(MemoryRegionInfo::eYes); } else { @@ -2418,6 +2436,7 @@ GDBRemoteCommunicationClient::GetMemoryRegionInfo (lldb::addr_t addr, region_info.SetReadable (MemoryRegionInfo::eNo); region_info.SetWritable (MemoryRegionInfo::eNo); region_info.SetExecutable (MemoryRegionInfo::eNo); + region_info.SetMapped(MemoryRegionInfo::eNo); } } else if (name.compare ("error") == 0) @@ -2437,6 +2456,7 @@ GDBRemoteCommunicationClient::GetMemoryRegionInfo (lldb::addr_t addr, region_info.SetReadable (MemoryRegionInfo::eNo); region_info.SetWritable (MemoryRegionInfo::eNo); region_info.SetExecutable (MemoryRegionInfo::eNo); + region_info.SetMapped(MemoryRegionInfo::eNo); } } else @@ -2836,6 +2856,7 @@ GDBRemoteCommunicationClient::GetCurrentProcessInfo (bool allow_lazy) std::string os_name; std::string vendor_name; std::string triple; + std::string elf_abi; uint32_t pointer_byte_size = 0; StringExtractor extractor; ByteOrder byte_order = eByteOrderInvalid; @@ -2897,6 +2918,11 @@ GDBRemoteCommunicationClient::GetCurrentProcessInfo (bool allow_lazy) if (pid != LLDB_INVALID_PROCESS_ID) ++num_keys_decoded; } + else if (name.compare("elf_abi") == 0) + { + elf_abi = value; + ++num_keys_decoded; + } } if (num_keys_decoded > 0) m_qProcessInfo_is_valid = eLazyBoolYes; @@ -2910,6 +2936,7 @@ GDBRemoteCommunicationClient::GetCurrentProcessInfo (bool allow_lazy) if (!triple.empty ()) { m_process_arch.SetTriple (triple.c_str ()); + m_process_arch.SetFlags(elf_abi); if (pointer_byte_size) { assert (pointer_byte_size == m_process_arch.GetAddressByteSize()); @@ -3571,6 +3598,8 @@ GDBRemoteCommunicationClient::SendGDBStoppointTypePacket (GDBStoppointType type, // Check we haven't overwritten the end of the packet buffer assert (packet_len + 1 < (int)sizeof(packet)); StringExtractorGDBRemote response; + // Make sure the response is either "OK", "EXX" where XX are two hex digits, or "" (unsupported) + response.SetResponseValidatorToOKErrorNotSupported(); // Try to send the breakpoint packet, and check that it was correctly sent if (SendPacketAndWaitForResponse(packet, packet_len, response, true) == PacketResult::Success) { @@ -4417,7 +4446,7 @@ GDBRemoteCommunicationClient::ReadExtFeature (const lldb_private::ConstString ob // last chunk case ( 'l' ): active = false; - // fall through intentional + LLVM_FALLTHROUGH; // more chunks case ( 'm' ) : diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index 311b0f3..096c4cf 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -13,6 +13,7 @@ // C Includes // C++ Includes #include <map> +#include <mutex> #include <string> #include <vector> @@ -527,7 +528,7 @@ public: bool ReadRegister(lldb::tid_t tid, - uint32_t reg_num, + uint32_t reg_num, // Must be the eRegisterKindProcessPlugin register number, to be sent to the remote StringExtractorGDBRemote &response); bool @@ -631,7 +632,7 @@ protected: // If we need to send a packet while the target is running, the m_async_XXX // member variables take care of making this happen. - Mutex m_async_mutex; + std::recursive_mutex m_async_mutex; Predicate<bool> m_async_packet_predicate; std::string m_async_packet; PacketResult m_async_result; diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp index 7f876fb..26a2e69 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp @@ -1235,12 +1235,12 @@ GDBRemoteCommunicationServerCommon::CreateProcessInfoResponse_DebugServerStyle ( break; } - if (proc_triple.isArch64Bit ()) - response.PutCString ("ptrsize:8;"); - else if (proc_triple.isArch32Bit ()) - response.PutCString ("ptrsize:4;"); - else if (proc_triple.isArch16Bit ()) - response.PutCString ("ptrsize:2;"); + // In case of MIPS64, pointer size is depend on ELF ABI + // For N32 the pointer size is 4 and for N64 it is 8 + std::string abi = proc_arch.GetTargetABI(); + if (!abi.empty()) + response.Printf("elf_abi:%s;", abi.c_str()); + response.Printf("ptrsize:%d;", proc_arch.GetAddressByteSize()); } } diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h index f55b2eb..d2fd700 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h +++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h @@ -17,7 +17,6 @@ // Other libraries and framework includes // Project includes #include "lldb/lldb-private-forward.h" -#include "lldb/Host/Mutex.h" #include "lldb/Target/Process.h" #include "GDBRemoteCommunicationServer.h" diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index 921369c..c468ba3 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -39,7 +39,6 @@ #include "lldb/Host/TimeValue.h" #include "lldb/Target/FileAction.h" #include "lldb/Target/MemoryRegionInfo.h" -#include "lldb/Target/Platform.h" #include "lldb/Host/common/NativeRegisterContext.h" #include "lldb/Host/common/NativeProcessProtocol.h" #include "lldb/Host/common/NativeThreadProtocol.h" @@ -76,25 +75,21 @@ namespace //---------------------------------------------------------------------- // GDBRemoteCommunicationServerLLGS constructor //---------------------------------------------------------------------- -GDBRemoteCommunicationServerLLGS::GDBRemoteCommunicationServerLLGS( - const lldb::PlatformSP& platform_sp, - MainLoop &mainloop) : - GDBRemoteCommunicationServerCommon ("gdb-remote.server", "gdb-remote.server.rx_packet"), - m_platform_sp (platform_sp), - m_mainloop (mainloop), - m_current_tid (LLDB_INVALID_THREAD_ID), - m_continue_tid (LLDB_INVALID_THREAD_ID), - m_debugged_process_mutex (Mutex::eMutexTypeRecursive), - m_debugged_process_sp (), - m_stdio_communication ("process.stdio"), - m_inferior_prev_state (StateType::eStateInvalid), - m_active_auxv_buffer_sp (), - m_saved_registers_mutex (), - m_saved_registers_map (), - m_next_saved_registers_id (1), - m_handshake_completed (false) -{ - assert(platform_sp); +GDBRemoteCommunicationServerLLGS::GDBRemoteCommunicationServerLLGS(MainLoop &mainloop) + : GDBRemoteCommunicationServerCommon("gdb-remote.server", "gdb-remote.server.rx_packet"), + m_mainloop(mainloop), + m_current_tid(LLDB_INVALID_THREAD_ID), + m_continue_tid(LLDB_INVALID_THREAD_ID), + m_debugged_process_mutex(), + m_debugged_process_sp(), + m_stdio_communication("process.stdio"), + m_inferior_prev_state(StateType::eStateInvalid), + m_active_auxv_buffer_sp(), + m_saved_registers_mutex(), + m_saved_registers_map(), + m_next_saved_registers_id(1), + m_handshake_completed(false) +{ RegisterPacketHandlers(); } @@ -210,7 +205,7 @@ GDBRemoteCommunicationServerLLGS::LaunchProcess () Error error; { - Mutex::Locker locker (m_debugged_process_mutex); + std::lock_guard<std::recursive_mutex> guard(m_debugged_process_mutex); assert (!m_debugged_process_sp && "lldb-gdbserver creating debugged process but one already exists"); error = NativeProcessProtocol::Launch( m_process_launch_info, @@ -1367,7 +1362,7 @@ GDBRemoteCommunicationServerLLGS::Handle_vCont (StringExtractorGDBRemote &packet thread_action.signal = packet.GetHexMaxU32 (false, 0); if (thread_action.signal == 0) return SendIllFormedResponse (packet, "Could not parse signal in vCont packet C action"); - // Fall through to next case... + LLVM_FALLTHROUGH; case 'c': // Continue @@ -1378,7 +1373,7 @@ GDBRemoteCommunicationServerLLGS::Handle_vCont (StringExtractorGDBRemote &packet thread_action.signal = packet.GetHexMaxU32 (false, 0); if (thread_action.signal == 0) return SendIllFormedResponse (packet, "Could not parse signal in vCont packet S action"); - // Fall through to next case... + LLVM_FALLTHROUGH; case 's': // Step @@ -1635,6 +1630,14 @@ GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo (StringExtractorGDBRemote response.PutChar (';'); } + if (reg_info->dynamic_size_dwarf_expr_bytes) + { + const size_t dwarf_opcode_len = reg_info->dynamic_size_dwarf_len; + response.PutCString("dynamic_size_dwarf_expr_bytes:"); + for(uint32_t i = 0; i < dwarf_opcode_len; ++i) + response.PutHex8 (reg_info->dynamic_size_dwarf_expr_bytes[i]); + response.PutChar(';'); + } return SendPacketNoLock(response.GetData(), response.GetSize()); } @@ -1830,7 +1833,10 @@ GDBRemoteCommunicationServerLLGS::Handle_P (StringExtractorGDBRemote &packet) return SendErrorResponse (0x47); } - if (reg_size != reg_info->byte_size) + // The dwarf expression are evaluate on host site + // which may cause register size to change + // Hence the reg_size may not be same as reg_info->bytes_size + if ((reg_size != reg_info->byte_size) && !(reg_info->dynamic_size_dwarf_expr_bytes)) { return SendIllFormedResponse (packet, "P packet register size is incorrect"); } @@ -2593,7 +2599,7 @@ GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState (StringExtractorGDBR // Save the register data buffer under the save id. { - Mutex::Locker locker (m_saved_registers_mutex); + std::lock_guard<std::mutex> guard(m_saved_registers_mutex); m_saved_registers_map[save_id] = register_data_sp; } @@ -2643,7 +2649,7 @@ GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState (StringExtractorG // Retrieve register state buffer, then remove from the list. DataBufferSP register_data_sp; { - Mutex::Locker locker (m_saved_registers_mutex); + std::lock_guard<std::mutex> guard(m_saved_registers_mutex); // Find the register set buffer for the given save id. auto it = m_saved_registers_map.find (save_id); @@ -2947,7 +2953,7 @@ GDBRemoteCommunicationServerLLGS::GetCurrentThreadID () const uint32_t GDBRemoteCommunicationServerLLGS::GetNextSavedRegistersID () { - Mutex::Locker locker (m_saved_registers_mutex); + std::lock_guard<std::mutex> guard(m_saved_registers_mutex); return m_next_saved_registers_id++; } diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h index f160577..caf6eb3 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h +++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h @@ -12,12 +12,12 @@ // C Includes // C++ Includes +#include <mutex> #include <unordered_map> // Other libraries and framework includes #include "lldb/lldb-private-forward.h" #include "lldb/Core/Communication.h" -#include "lldb/Host/Mutex.h" #include "lldb/Host/common/NativeProcessProtocol.h" #include "lldb/Host/MainLoop.h" @@ -40,7 +40,7 @@ public: //------------------------------------------------------------------ // Constructors and Destructors //------------------------------------------------------------------ - GDBRemoteCommunicationServerLLGS(const lldb::PlatformSP& platform_sp, MainLoop &mainloop); + GDBRemoteCommunicationServerLLGS(MainLoop &mainloop); //------------------------------------------------------------------ /// Specify the program to launch and its arguments. @@ -114,12 +114,11 @@ public: InitializeConnection (std::unique_ptr<Connection> &&connection); protected: - lldb::PlatformSP m_platform_sp; MainLoop &m_mainloop; MainLoop::ReadHandleUP m_network_handle_up; lldb::tid_t m_current_tid; lldb::tid_t m_continue_tid; - Mutex m_debugged_process_mutex; + std::recursive_mutex m_debugged_process_mutex; NativeProcessProtocolSP m_debugged_process_sp; Communication m_stdio_communication; @@ -127,7 +126,7 @@ protected: lldb::StateType m_inferior_prev_state; lldb::DataBufferSP m_active_auxv_buffer_sp; - Mutex m_saved_registers_mutex; + std::mutex m_saved_registers_mutex; std::unordered_map<uint32_t, lldb::DataBufferSP> m_saved_registers_map; uint32_t m_next_saved_registers_id; bool m_handshake_completed : 1; diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp index f88ac12..d6900c2 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp @@ -48,14 +48,13 @@ using namespace lldb_private::process_gdb_remote; // GDBRemoteCommunicationServerPlatform constructor //---------------------------------------------------------------------- GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform(const Socket::SocketProtocol socket_protocol, - const char* socket_scheme) : - GDBRemoteCommunicationServerCommon ("gdb-remote.server", "gdb-remote.server.rx_packet"), - m_socket_protocol(socket_protocol), - m_socket_scheme(socket_scheme), - m_spawned_pids_mutex (Mutex::eMutexTypeRecursive), - m_platform_sp (Platform::GetHostPlatform ()), - m_port_map (), - m_port_offset(0) + const char *socket_scheme) + : GDBRemoteCommunicationServerCommon("gdb-remote.server", "gdb-remote.server.rx_packet"), + m_socket_protocol(socket_protocol), + m_socket_scheme(socket_scheme), + m_spawned_pids_mutex(), + m_port_map(), + m_port_offset(0) { m_pending_gdb_server.pid = LLDB_INVALID_PROCESS_ID; m_pending_gdb_server.port = 0; @@ -78,11 +77,7 @@ GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform(const &GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo); RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_interrupt, - [this](StringExtractorGDBRemote packet, - Error &error, - bool &interrupt, - bool &quit) - { + [this](StringExtractorGDBRemote packet, Error &error, bool &interrupt, bool &quit) { error.SetErrorString("interrupt received"); interrupt = true; return PacketResult::Success; @@ -124,7 +119,8 @@ GDBRemoteCommunicationServerPlatform::LaunchGDBServer(const lldb_private::Args& // Do not run in a new session so that it can not linger after the // platform closes. debugserver_launch_info.SetLaunchInSeparateProcessGroup(false); - debugserver_launch_info.SetMonitorProcessCallback(ReapDebugserverProcess, this, false); + debugserver_launch_info.SetMonitorProcessCallback( + std::bind(&GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped, this, std::placeholders::_1), false); std::string platform_scheme; std::string platform_ip; @@ -135,6 +131,10 @@ GDBRemoteCommunicationServerPlatform::LaunchGDBServer(const lldb_private::Args& assert(ok); std::ostringstream url; + // debugserver does not accept the URL scheme prefix. +#if !defined(__APPLE__) + url << m_socket_scheme << "://"; +#endif uint16_t* port_ptr = &port; if (m_socket_protocol == Socket::ProtocolTcp) url << platform_ip << ":" << port; @@ -154,7 +154,7 @@ GDBRemoteCommunicationServerPlatform::LaunchGDBServer(const lldb_private::Args& pid = debugserver_launch_info.GetProcessID(); if (pid != LLDB_INVALID_PROCESS_ID) { - Mutex::Locker locker (m_spawned_pids_mutex); + std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); m_spawned_pids.insert(pid); if (port > 0) AssociatePortWithProcess(port, pid); @@ -259,7 +259,7 @@ GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess (StringExtracto // verify that we know anything about this pid. // Scope for locker { - Mutex::Locker locker (m_spawned_pids_mutex); + std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); if (m_spawned_pids.find(pid) == m_spawned_pids.end()) { // not a pid we know about @@ -279,7 +279,7 @@ GDBRemoteCommunicationServerPlatform::KillSpawnedProcess (lldb::pid_t pid) { // make sure we know about this process { - Mutex::Locker locker (m_spawned_pids_mutex); + std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); if (m_spawned_pids.find(pid) == m_spawned_pids.end()) return false; } @@ -291,7 +291,7 @@ GDBRemoteCommunicationServerPlatform::KillSpawnedProcess (lldb::pid_t pid) for (size_t i=0; i<10; ++i) { { - Mutex::Locker locker (m_spawned_pids_mutex); + std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); if (m_spawned_pids.find(pid) == m_spawned_pids.end()) { // it is now killed @@ -303,7 +303,7 @@ GDBRemoteCommunicationServerPlatform::KillSpawnedProcess (lldb::pid_t pid) // check one more time after the final usleep { - Mutex::Locker locker (m_spawned_pids_mutex); + std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); if (m_spawned_pids.find(pid) == m_spawned_pids.end()) return true; } @@ -315,7 +315,7 @@ GDBRemoteCommunicationServerPlatform::KillSpawnedProcess (lldb::pid_t pid) for (size_t i=0; i<10; ++i) { { - Mutex::Locker locker (m_spawned_pids_mutex); + std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); if (m_spawned_pids.find(pid) == m_spawned_pids.end()) { // it is now killed @@ -328,7 +328,7 @@ GDBRemoteCommunicationServerPlatform::KillSpawnedProcess (lldb::pid_t pid) // check one more time after the final usleep // Scope for locker { - Mutex::Locker locker (m_spawned_pids_mutex); + std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); if (m_spawned_pids.find(pid) == m_spawned_pids.end()) return true; } @@ -442,20 +442,9 @@ GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo(StringExtractorGDBRemo bool GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped (lldb::pid_t pid) { - Mutex::Locker locker (m_spawned_pids_mutex); + std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); FreePortForProcess(pid); - return m_spawned_pids.erase(pid) > 0; -} - -bool -GDBRemoteCommunicationServerPlatform::ReapDebugserverProcess (void *callback_baton, - lldb::pid_t pid, - bool exited, - int signal, // Zero for no signal - int status) // Exit value of process if signal is zero -{ - GDBRemoteCommunicationServerPlatform *server = (GDBRemoteCommunicationServerPlatform *)callback_baton; - server->DebugserverProcessReaped (pid); + m_spawned_pids.erase(pid); return true; } @@ -469,9 +458,11 @@ GDBRemoteCommunicationServerPlatform::LaunchProcess () // generally be what happens since we need to reap started // processes. if (!m_process_launch_info.GetMonitorProcessCallback ()) - m_process_launch_info.SetMonitorProcessCallback(ReapDebugserverProcess, this, false); + m_process_launch_info.SetMonitorProcessCallback( + std::bind(&GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped, this, std::placeholders::_1), + false); - Error error = m_platform_sp->LaunchProcess (m_process_launch_info); + Error error = Host::LaunchProcess(m_process_launch_info); if (!error.Success ()) { fprintf (stderr, "%s: failed to launch executable %s", __FUNCTION__, m_process_launch_info.GetArguments ().GetArgumentAtIndex (0)); @@ -486,7 +477,7 @@ GDBRemoteCommunicationServerPlatform::LaunchProcess () if (pid != LLDB_INVALID_PROCESS_ID) { // add to spawned pids - Mutex::Locker locker (m_spawned_pids_mutex); + std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex); m_spawned_pids.insert(pid); } diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h index 1fe7207..1f4d08c 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h +++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h @@ -13,6 +13,7 @@ // C Includes // C++ Includes #include <map> +#include <mutex> #include <set> // Other libraries and framework includes @@ -82,9 +83,8 @@ public: protected: const Socket::SocketProtocol m_socket_protocol; const std::string m_socket_scheme; - Mutex m_spawned_pids_mutex; + std::recursive_mutex m_spawned_pids_mutex; std::set<lldb::pid_t> m_spawned_pids; - lldb::PlatformSP m_platform_sp; PortMap m_port_map; uint16_t m_port_offset; @@ -121,13 +121,6 @@ private: bool DebugserverProcessReaped (lldb::pid_t pid); - static bool - ReapDebugserverProcess (void *callback_baton, - lldb::pid_t pid, - bool exited, - int signal, - int status); - static const FileSpec& GetDomainSocketDir(); diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp index b0a1eaa..57983c4 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp @@ -89,7 +89,15 @@ GDBRemoteRegisterContext::GetRegisterCount () const RegisterInfo * GDBRemoteRegisterContext::GetRegisterInfoAtIndex (size_t reg) { - return m_reg_info.GetRegisterInfoAtIndex (reg); + RegisterInfo* reg_info = m_reg_info.GetRegisterInfoAtIndex (reg); + + if (reg_info && reg_info->dynamic_size_dwarf_expr_bytes) + { + const ArchSpec &arch = m_thread.GetProcess ()->GetTarget ().GetArchitecture (); + uint8_t reg_size = UpdateDynamicRegisterSize (arch, reg_info); + reg_info->byte_size = reg_size; + } + return reg_info; } size_t @@ -198,10 +206,11 @@ bool GDBRemoteRegisterContext::GetPrimordialRegister(const RegisterInfo *reg_info, GDBRemoteCommunicationClient &gdb_comm) { - const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; + const uint32_t lldb_reg = reg_info->kinds[eRegisterKindLLDB]; + const uint32_t remote_reg = reg_info->kinds[eRegisterKindProcessPlugin]; StringExtractorGDBRemote response; - if (gdb_comm.ReadRegister(m_thread.GetProtocolID(), reg, response)) - return PrivateSetRegisterValue (reg, response); + if (gdb_comm.ReadRegister(m_thread.GetProtocolID(), remote_reg, response)) + return PrivateSetRegisterValue (lldb_reg, response); return false; } @@ -316,7 +325,7 @@ GDBRemoteRegisterContext::SetPrimordialRegister(const RegisterInfo *reg_info, StreamString packet; StringExtractorGDBRemote response; const uint32_t reg = reg_info->kinds[eRegisterKindLLDB]; - packet.Printf ("P%x=", reg); + packet.Printf ("P%x=", reg_info->kinds[eRegisterKindProcessPlugin]); packet.PutBytesAsRawHex8 (m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size), reg_info->byte_size, endian::InlHostByteOrder(), @@ -813,7 +822,7 @@ GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data if (restore_src) { StreamString packet; - packet.Printf ("P%x=", reg); + packet.Printf ("P%x=", reg_info->kinds[eRegisterKindProcessPlugin]); packet.PutBytesAsRawHex8 (restore_src, reg_byte_size, endian::InlHostByteOrder(), @@ -836,7 +845,7 @@ GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data if (write_reg) { StreamString packet; - packet.Printf ("P%x=", reg); + packet.Printf ("P%x=", reg_info->kinds[eRegisterKindProcessPlugin]); packet.PutBytesAsRawHex8 (restore_src, reg_byte_size, endian::InlHostByteOrder(), @@ -894,7 +903,7 @@ GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data continue; } StreamString packet; - packet.Printf ("P%x=", reg_info->kinds[eRegisterKindLLDB]); + packet.Printf ("P%x=", reg_info->kinds[eRegisterKindProcessPlugin]); packet.PutBytesAsRawHex8 (data_sp->GetBytes() + reg_info->byte_offset, reg_info->byte_size, endian::InlHostByteOrder(), endian::InlHostByteOrder()); if (thread_suffix_supported) packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID()); diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 6bee4e1..f53d4c6 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -70,6 +70,7 @@ #include "Plugins/Process/Utility/GDBRemoteSignals.h" #include "Plugins/Process/Utility/InferiorCallPOSIX.h" #include "Plugins/Process/Utility/StopInfoMachException.h" +//#include "Plugins/Platform/MacOSX/PlatformRemoteiOS.h" #include "Utility/StringExtractorGDBRemote.h" #include "GDBRemoteRegisterContext.h" #include "ProcessGDBRemote.h" @@ -222,11 +223,11 @@ ProcessGDBRemote::Terminate() lldb::ProcessSP -ProcessGDBRemote::CreateInstance (lldb::TargetSP target_sp, Listener &listener, const FileSpec *crash_file_path) +ProcessGDBRemote::CreateInstance (lldb::TargetSP target_sp, ListenerSP listener_sp, const FileSpec *crash_file_path) { lldb::ProcessSP process_sp; if (crash_file_path == NULL) - process_sp.reset (new ProcessGDBRemote (target_sp, listener)); + process_sp.reset (new ProcessGDBRemote (target_sp, listener_sp)); return process_sp; } @@ -266,51 +267,51 @@ ProcessGDBRemote::CanDebug (lldb::TargetSP target_sp, bool plugin_specified_by_n //---------------------------------------------------------------------- // ProcessGDBRemote constructor //---------------------------------------------------------------------- -ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, Listener &listener) : - Process (target_sp, listener), - m_flags (0), - m_gdb_comm (), - m_debugserver_pid (LLDB_INVALID_PROCESS_ID), - m_last_stop_packet_mutex (Mutex::eMutexTypeRecursive), - m_register_info (), - m_async_broadcaster (NULL, "lldb.process.gdb-remote.async-broadcaster"), - m_async_listener("lldb.process.gdb-remote.async-listener"), - m_async_thread_state_mutex(Mutex::eMutexTypeRecursive), - m_thread_ids (), - m_thread_pcs (), - m_jstopinfo_sp (), - m_jthreadsinfo_sp (), - m_continue_c_tids (), - m_continue_C_tids (), - m_continue_s_tids (), - m_continue_S_tids (), - m_max_memory_size (0), - m_remote_stub_max_memory_size (0), - m_addr_to_mmap_size (), - m_thread_create_bp_sp (), - m_waiting_for_attach (false), - m_destroy_tried_resuming (false), - m_command_sp (), - m_breakpoint_pc_offset (0), - m_initial_tid (LLDB_INVALID_THREAD_ID) +ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, ListenerSP listener_sp) + : Process(target_sp, listener_sp), + m_flags(0), + m_gdb_comm(), + m_debugserver_pid(LLDB_INVALID_PROCESS_ID), + m_last_stop_packet_mutex(), + m_register_info(), + m_async_broadcaster(NULL, "lldb.process.gdb-remote.async-broadcaster"), + m_async_listener_sp(Listener::MakeListener("lldb.process.gdb-remote.async-listener")), + m_async_thread_state_mutex(), + m_thread_ids(), + m_thread_pcs(), + m_jstopinfo_sp(), + m_jthreadsinfo_sp(), + m_continue_c_tids(), + m_continue_C_tids(), + m_continue_s_tids(), + m_continue_S_tids(), + m_max_memory_size(0), + m_remote_stub_max_memory_size(0), + m_addr_to_mmap_size(), + m_thread_create_bp_sp(), + m_waiting_for_attach(false), + m_destroy_tried_resuming(false), + m_command_sp(), + m_breakpoint_pc_offset(0), + m_initial_tid(LLDB_INVALID_THREAD_ID) { - m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadShouldExit, "async thread should exit"); - m_async_broadcaster.SetEventName (eBroadcastBitAsyncContinue, "async thread continue"); - m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadDidExit, "async thread did exit"); + m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit, "async thread should exit"); + m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue, "async thread continue"); + m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadDidExit, "async thread did exit"); - Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_ASYNC)); + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_ASYNC)); const uint32_t async_event_mask = eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit; - if (m_async_listener.StartListeningForEvents(&m_async_broadcaster, async_event_mask) != async_event_mask) + if (m_async_listener_sp->StartListeningForEvents(&m_async_broadcaster, async_event_mask) != async_event_mask) { if (log) log->Printf("ProcessGDBRemote::%s failed to listen for m_async_broadcaster events", __FUNCTION__); } - const uint32_t gdb_event_mask = Communication::eBroadcastBitReadThreadDidExit | - GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify; - if (m_async_listener.StartListeningForEvents(&m_gdb_comm, gdb_event_mask) != gdb_event_mask) + const uint32_t gdb_event_mask = + Communication::eBroadcastBitReadThreadDidExit | GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify; + if (m_async_listener_sp->StartListeningForEvents(&m_gdb_comm, gdb_event_mask) != gdb_event_mask) { if (log) log->Printf("ProcessGDBRemote::%s failed to listen for m_gdb_comm events", __FUNCTION__); @@ -499,7 +500,21 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force) } } - if (GetGDBServerRegisterInfo ()) + const ArchSpec &target_arch = GetTarget().GetArchitecture(); + const ArchSpec &remote_host_arch = m_gdb_comm.GetHostArchitecture(); + const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture(); + + // Use the process' architecture instead of the host arch, if available + ArchSpec arch_to_use; + if (remote_process_arch.IsValid ()) + arch_to_use = remote_process_arch; + else + arch_to_use = remote_host_arch; + + if (!arch_to_use.IsValid()) + arch_to_use = target_arch; + + if (GetGDBServerRegisterInfo (arch_to_use)) return; char packet[128]; @@ -524,6 +539,7 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force) ConstString set_name; std::vector<uint32_t> value_regs; std::vector<uint32_t> invalidate_regs; + std::vector<uint8_t> dwarf_opcode_bytes; RegisterInfo reg_info = { NULL, // Name NULL, // Alt name 0, // byte size @@ -538,7 +554,9 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force) reg_num // native register number }, NULL, - NULL + NULL, + NULL, // Dwarf expression opcode bytes pointer + 0 // Dwarf expression opcode bytes length }; while (response.GetNameColonValue(name, value)) @@ -623,6 +641,23 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force) { SplitCommaSeparatedRegisterNumberString(value, invalidate_regs, 16); } + else if (name.compare("dynamic_size_dwarf_expr_bytes") == 0) + { + size_t dwarf_opcode_len = value.length () / 2; + assert (dwarf_opcode_len > 0); + + dwarf_opcode_bytes.resize (dwarf_opcode_len); + StringExtractor opcode_extractor; + reg_info.dynamic_size_dwarf_len = dwarf_opcode_len; + + // Swap "value" over into "opcode_extractor" + opcode_extractor.GetStringRef ().swap (value); + uint32_t ret_val = opcode_extractor.GetHexBytesAvail (dwarf_opcode_bytes.data (), + dwarf_opcode_len); + assert (dwarf_opcode_len == ret_val); + + reg_info.dynamic_size_dwarf_expr_bytes = dwarf_opcode_bytes.data (); + } } reg_info.byte_offset = reg_offset; @@ -639,7 +674,12 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force) reg_info.invalidate_regs = invalidate_regs.data(); } - AugmentRegisterInfoViaABI (reg_info, reg_name, GetABI ()); + // We have to make a temporary ABI here, and not use the GetABI because this code + // gets called in DidAttach, when the target architecture (and consequently the ABI we'll get from + // the process) may be wrong. + ABISP abi_to_use = ABI::FindPlugin(arch_to_use); + + AugmentRegisterInfoViaABI (reg_info, reg_name, abi_to_use); m_register_info.AddRegister(reg_info, reg_name, alt_name, set_name); } @@ -667,22 +707,11 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force) // add composite registers to the existing primordial ones. bool from_scratch = (m_register_info.GetNumRegisters() == 0); - const ArchSpec &target_arch = GetTarget().GetArchitecture(); - const ArchSpec &remote_host_arch = m_gdb_comm.GetHostArchitecture(); - const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture(); - - // Use the process' architecture instead of the host arch, if available - ArchSpec remote_arch; - if (remote_process_arch.IsValid ()) - remote_arch = remote_process_arch; - else - remote_arch = remote_host_arch; - if (!target_arch.IsValid()) { - if (remote_arch.IsValid() - && (remote_arch.GetMachine() == llvm::Triple::arm || remote_arch.GetMachine() == llvm::Triple::thumb) - && remote_arch.GetTriple().getVendor() == llvm::Triple::Apple) + if (arch_to_use.IsValid() + && (arch_to_use.GetMachine() == llvm::Triple::arm || arch_to_use.GetMachine() == llvm::Triple::thumb) + && arch_to_use.GetTriple().getVendor() == llvm::Triple::Apple) m_register_info.HardcodeARMRegisters(from_scratch); } else if (target_arch.GetMachine() == llvm::Triple::arm @@ -1359,10 +1388,10 @@ ProcessGDBRemote::DoResume () if (log) log->Printf ("ProcessGDBRemote::Resume()"); - Listener listener ("gdb-remote.resume-packet-sent"); - if (listener.StartListeningForEvents (&m_gdb_comm, GDBRemoteCommunication::eBroadcastBitRunPacketSent)) + ListenerSP listener_sp (Listener::MakeListener("gdb-remote.resume-packet-sent")); + if (listener_sp->StartListeningForEvents (&m_gdb_comm, GDBRemoteCommunication::eBroadcastBitRunPacketSent)) { - listener.StartListeningForEvents (&m_async_broadcaster, ProcessGDBRemote::eBroadcastBitAsyncThreadDidExit); + listener_sp->StartListeningForEvents (&m_async_broadcaster, ProcessGDBRemote::eBroadcastBitAsyncThreadDidExit); const size_t num_threads = GetThreadList().GetSize(); @@ -1594,7 +1623,7 @@ ProcessGDBRemote::DoResume () m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (continue_packet.GetData(), continue_packet.GetSize())); - if (listener.WaitForEvent (&timeout, event_sp) == false) + if (listener_sp->WaitForEvent (&timeout, event_sp) == false) { error.SetErrorString("Resume timed out."); if (log) @@ -1637,7 +1666,7 @@ ProcessGDBRemote::HandleStopReplySequence () void ProcessGDBRemote::ClearThreadIDList () { - Mutex::Locker locker(m_thread_list_real.GetMutex()); + std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex()); m_thread_ids.clear(); m_thread_pcs.clear(); } @@ -1687,7 +1716,7 @@ ProcessGDBRemote::UpdateThreadPCsFromStopReplyThreadsValue (std::string &value) bool ProcessGDBRemote::UpdateThreadIDList () { - Mutex::Locker locker(m_thread_list_real.GetMutex()); + std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex()); if (m_jthreadsinfo_sp) { @@ -1720,8 +1749,8 @@ ProcessGDBRemote::UpdateThreadIDList () // Lock the thread stack while we access it //Mutex::Locker stop_stack_lock(m_last_stop_packet_mutex); - Mutex::Locker stop_stack_lock; - if (stop_stack_lock.TryLock(m_last_stop_packet_mutex)) + std::unique_lock<std::recursive_mutex> stop_stack_lock(m_last_stop_packet_mutex, std::defer_lock); + if (stop_stack_lock.try_lock()) { // Get the number of stop packets on the stack int nItems = m_stop_packet_stack.size(); @@ -1831,7 +1860,7 @@ ProcessGDBRemote::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new } } } - new_thread_list.AddThread(thread_sp); + new_thread_list.AddThreadSortedByIndexID (thread_sp); } } @@ -1935,7 +1964,7 @@ ProcessGDBRemote::SetThreadStopInfo (lldb::tid_t tid, // m_thread_list_real does have its own mutex, but we need to // hold onto the mutex between the call to m_thread_list_real.FindThreadByID(...) // and the m_thread_list_real.AddThread(...) so it doesn't change on us - Mutex::Locker locker (m_thread_list_real.GetMutex ()); + std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex()); thread_sp = m_thread_list_real.FindThreadByProtocolID(tid, false); if (!thread_sp) @@ -2000,7 +2029,18 @@ ProcessGDBRemote::SetThreadStopInfo (lldb::tid_t tid, { if (reason.compare("trace") == 0) { - thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp)); + addr_t pc = thread_sp->GetRegisterContext()->GetPC(); + lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc); + + // If the current pc is a breakpoint site then the StopInfo should be set to Breakpoint + // Otherwise, it will be set to Trace. + if (bp_site_sp && bp_site_sp->ValidForThisThread(thread_sp.get())) + { + thread_sp->SetStopInfo( + StopInfo::CreateStopReasonWithBreakpointSiteID(*thread_sp, bp_site_sp->GetID())); + } + else + thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp)); handled = true; } else if (reason.compare("breakpoint") == 0) @@ -2039,7 +2079,8 @@ ProcessGDBRemote::SetThreadStopInfo (lldb::tid_t tid, { WatchpointSP wp_sp; ArchSpec::Core core = GetTarget().GetArchitecture().GetCore(); - if (core >= ArchSpec::kCore_mips_first && core <= ArchSpec::kCore_mips_last) + if ((core >= ArchSpec::kCore_mips_first && core <= ArchSpec::kCore_mips_last) || + (core >= ArchSpec::eCore_arm_generic && core <= ArchSpec::eCore_arm_aarch64)) wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_hit_addr); if (!wp_sp) wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_addr); @@ -2069,6 +2110,23 @@ ProcessGDBRemote::SetThreadStopInfo (lldb::tid_t tid, handled = true; } } + else if (!signo) + { + addr_t pc = thread_sp->GetRegisterContext()->GetPC(); + lldb::BreakpointSiteSP bp_site_sp = + thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc); + + // If the current pc is a breakpoint site then the StopInfo should be set to Breakpoint + // even though the remote stub did not set it as such. This can happen when + // the thread is involuntarily interrupted (e.g. due to stops on other + // threads) just as it is about to execute the breakpoint instruction. + if (bp_site_sp && bp_site_sp->ValidForThisThread(thread_sp.get())) + { + thread_sp->SetStopInfo( + StopInfo::CreateStopReasonWithBreakpointSiteID(*thread_sp, bp_site_sp->GetID())); + handled = true; + } + } if (!handled && signo && did_exec == false) { @@ -2403,7 +2461,8 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) } else if (key.compare("threads") == 0) { - Mutex::Locker locker(m_thread_list_real.GetMutex()); + std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex()); + m_thread_ids.clear(); // A comma separated list of all threads in the current // process that includes the thread for this stop reply @@ -2626,7 +2685,8 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) void ProcessGDBRemote::RefreshStateAfterStop () { - Mutex::Locker locker(m_thread_list_real.GetMutex()); + std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex()); + m_thread_ids.clear(); m_thread_pcs.clear(); // Set the thread stop info. It might have a "threads" key whose value is @@ -2636,7 +2696,7 @@ ProcessGDBRemote::RefreshStateAfterStop () // Scope for the lock { // Lock the thread stack while we access it - Mutex::Locker stop_stack_lock(m_last_stop_packet_mutex); + std::lock_guard<std::recursive_mutex> guard(m_last_stop_packet_mutex); // Get the number of stop packets on the stack int nItems = m_stop_packet_stack.size(); // Iterate over them @@ -2782,7 +2842,7 @@ ProcessGDBRemote::DoDestroy () ThreadList &threads = GetThreadList(); { - Mutex::Locker locker(threads.GetMutex()); + std::lock_guard<std::recursive_mutex> guard(threads.GetMutex()); size_t num_threads = threads.GetSize(); for (size_t i = 0; i < num_threads; i++) @@ -2817,7 +2877,7 @@ ProcessGDBRemote::DoDestroy () // have to run the risk of letting those threads proceed a bit. { - Mutex::Locker locker(threads.GetMutex()); + std::lock_guard<std::recursive_mutex> guard(threads.GetMutex()); size_t num_threads = threads.GetSize(); for (size_t i = 0; i < num_threads; i++) @@ -2940,7 +3000,7 @@ ProcessGDBRemote::SetLastStopPacket (const StringExtractorGDBRemote &response) // Scope the lock { // Lock the thread stack while we access it - Mutex::Locker stop_stack_lock(m_last_stop_packet_mutex); + std::lock_guard<std::recursive_mutex> guard(m_last_stop_packet_mutex); // We are are not using non-stop mode, there can only be one last stop // reply packet, so clear the list. @@ -3120,35 +3180,33 @@ ProcessGDBRemote::DoAllocateMemory (size_t size, uint32_t permissions, Error &er Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS|LIBLLDB_LOG_EXPRESSIONS)); addr_t allocated_addr = LLDB_INVALID_ADDRESS; - LazyBool supported = m_gdb_comm.SupportsAllocDeallocMemory(); - switch (supported) + if (m_gdb_comm.SupportsAllocDeallocMemory() != eLazyBoolNo) { - case eLazyBoolCalculate: - case eLazyBoolYes: - allocated_addr = m_gdb_comm.AllocateMemory (size, permissions); - if (allocated_addr != LLDB_INVALID_ADDRESS || supported == eLazyBoolYes) - return allocated_addr; + allocated_addr = m_gdb_comm.AllocateMemory (size, permissions); + if (allocated_addr != LLDB_INVALID_ADDRESS || m_gdb_comm.SupportsAllocDeallocMemory() == eLazyBoolYes) + return allocated_addr; + } - case eLazyBoolNo: - // Call mmap() to create memory in the inferior.. - unsigned prot = 0; - if (permissions & lldb::ePermissionsReadable) - prot |= eMmapProtRead; - if (permissions & lldb::ePermissionsWritable) - prot |= eMmapProtWrite; - if (permissions & lldb::ePermissionsExecutable) - prot |= eMmapProtExec; - - if (InferiorCallMmap(this, allocated_addr, 0, size, prot, - eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) - m_addr_to_mmap_size[allocated_addr] = size; - else - { - allocated_addr = LLDB_INVALID_ADDRESS; - if (log) - log->Printf ("ProcessGDBRemote::%s no direct stub support for memory allocation, and InferiorCallMmap also failed - is stub missing register context save/restore capability?", __FUNCTION__); - } - break; + if (m_gdb_comm.SupportsAllocDeallocMemory() == eLazyBoolNo) + { + // Call mmap() to create memory in the inferior.. + unsigned prot = 0; + if (permissions & lldb::ePermissionsReadable) + prot |= eMmapProtRead; + if (permissions & lldb::ePermissionsWritable) + prot |= eMmapProtWrite; + if (permissions & lldb::ePermissionsExecutable) + prot |= eMmapProtExec; + + if (InferiorCallMmap(this, allocated_addr, 0, size, prot, + eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0)) + m_addr_to_mmap_size[allocated_addr] = size; + else + { + allocated_addr = LLDB_INVALID_ADDRESS; + if (log) + log->Printf ("ProcessGDBRemote::%s no direct stub support for memory allocation, and InferiorCallMmap also failed - is stub missing register context save/restore capability?", __FUNCTION__); + } } if (allocated_addr == LLDB_INVALID_ADDRESS) @@ -3274,7 +3332,8 @@ ProcessGDBRemote::EnableBreakpointSite (BreakpointSite *bp_site) if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware) && (!bp_site->HardwareRequired())) { // Try to send off a software breakpoint packet ($Z0) - if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, true, addr, bp_op_size) == 0) + uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, true, addr, bp_op_size); + if (error_no == 0) { // The breakpoint was placed successfully bp_site->SetEnabled(true); @@ -3290,7 +3349,13 @@ ProcessGDBRemote::EnableBreakpointSite (BreakpointSite *bp_site) // with the error code. If they are now unsupported, then we would like to fall through // and try another form of breakpoint. if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware)) + { + if (error_no != UINT8_MAX) + error.SetErrorStringWithFormat("error: %d sending the breakpoint request", errno); + else + error.SetErrorString("error sending the breakpoint request"); return error; + } // We reach here when software breakpoints have been found to be unsupported. For future // calls to set a breakpoint, we will not attempt to set a breakpoint with a type that is @@ -3307,7 +3372,8 @@ ProcessGDBRemote::EnableBreakpointSite (BreakpointSite *bp_site) if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware)) { // Try to send off a hardware breakpoint packet ($Z1) - if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, true, addr, bp_op_size) == 0) + uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, true, addr, bp_op_size); + if (error_no == 0) { // The breakpoint was placed successfully bp_site->SetEnabled(true); @@ -3319,7 +3385,13 @@ ProcessGDBRemote::EnableBreakpointSite (BreakpointSite *bp_site) if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware)) { // Unable to set this hardware breakpoint - error.SetErrorString("failed to set hardware breakpoint (hardware breakpoint resources might be exhausted or unavailable)"); + if (error_no != UINT8_MAX) + error.SetErrorStringWithFormat("error: %d sending the hardware breakpoint request " + "(hardware breakpoint resources might be exhausted or unavailable)", + error_no); + else + error.SetErrorString("error sending the hardware breakpoint request (hardware breakpoint resources " + "might be exhausted or unavailable)"); return error; } @@ -3551,6 +3623,8 @@ ProcessGDBRemote::EstablishConnectionIfNeeded (const ProcessInfo &process_info) Error ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info) { + using namespace std::placeholders; // For _1, _2, etc. + Error error; if (m_debugserver_pid == LLDB_INVALID_PROCESS_ID) { @@ -3562,7 +3636,9 @@ ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info // special terminal key sequences (^C) don't affect debugserver. debugserver_launch_info.SetLaunchInSeparateProcessGroup(true); - debugserver_launch_info.SetMonitorProcessCallback (MonitorDebugserverProcess, this, false); + const std::weak_ptr<ProcessGDBRemote> this_wp = std::static_pointer_cast<ProcessGDBRemote>(shared_from_this()); + debugserver_launch_info.SetMonitorProcessCallback(std::bind(MonitorDebugserverProcess, this_wp, _1, _2, _3, _4), + false); debugserver_launch_info.SetUserID(process_info.GetUserID()); #if defined (__APPLE__) && (defined (__arm__) || defined (__arm64__) || defined (__aarch64__)) @@ -3624,91 +3700,58 @@ ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info } bool -ProcessGDBRemote::MonitorDebugserverProcess -( - void *callback_baton, - lldb::pid_t debugserver_pid, - bool exited, // True if the process did exit - int signo, // Zero for no signal - int exit_status // Exit value of process if signal is zero -) +ProcessGDBRemote::MonitorDebugserverProcess(std::weak_ptr<ProcessGDBRemote> process_wp, lldb::pid_t debugserver_pid, + bool exited, // True if the process did exit + int signo, // Zero for no signal + int exit_status // Exit value of process if signal is zero + ) { - // The baton is a "ProcessGDBRemote *". Now this class might be gone - // and might not exist anymore, so we need to carefully try to get the - // target for this process first since we have a race condition when - // we are done running between getting the notice that the inferior - // process has died and the debugserver that was debugging this process. - // In our test suite, we are also continually running process after - // process, so we must be very careful to make sure: - // 1 - process object hasn't been deleted already - // 2 - that a new process object hasn't been recreated in its place - // "debugserver_pid" argument passed in is the process ID for // debugserver that we are tracking... Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + const bool handled = true; - ProcessGDBRemote *process = (ProcessGDBRemote *)callback_baton; - - // Get a shared pointer to the target that has a matching process pointer. - // This target could be gone, or the target could already have a new process - // object inside of it - TargetSP target_sp (Debugger::FindTargetWithProcess(process)); + if (log) + log->Printf("ProcessGDBRemote::%s(process_wp, pid=%" PRIu64 ", signo=%i (0x%x), exit_status=%i)", __FUNCTION__, + debugserver_pid, signo, signo, exit_status); + std::shared_ptr<ProcessGDBRemote> process_sp = process_wp.lock(); if (log) - log->Printf ("ProcessGDBRemote::MonitorDebugserverProcess (baton=%p, pid=%" PRIu64 ", signo=%i (0x%x), exit_status=%i)", callback_baton, debugserver_pid, signo, signo, exit_status); - - if (target_sp) - { - // We found a process in a target that matches, but another thread - // might be in the process of launching a new process that will - // soon replace it, so get a shared pointer to the process so we - // can keep it alive. - ProcessSP process_sp (target_sp->GetProcessSP()); - // Now we have a shared pointer to the process that can't go away on us - // so we now make sure it was the same as the one passed in, and also make - // sure that our previous "process *" didn't get deleted and have a new - // "process *" created in its place with the same pointer. To verify this - // we make sure the process has our debugserver process ID. If we pass all - // of these tests, then we are sure that this process is the one we were - // looking for. - if (process_sp && process == process_sp.get() && process->m_debugserver_pid == debugserver_pid) + log->Printf("ProcessGDBRemote::%s(process = %p)", __FUNCTION__, static_cast<void *>(process_sp.get())); + if (!process_sp || process_sp->m_debugserver_pid != debugserver_pid) + return handled; + + // Sleep for a half a second to make sure our inferior process has + // time to set its exit status before we set it incorrectly when + // both the debugserver and the inferior process shut down. + usleep(500000); + // If our process hasn't yet exited, debugserver might have died. + // If the process did exit, then we are reaping it. + const StateType state = process_sp->GetState(); + + if (state != eStateInvalid && state != eStateUnloaded && state != eStateExited && state != eStateDetached) + { + char error_str[1024]; + if (signo) { - // Sleep for a half a second to make sure our inferior process has - // time to set its exit status before we set it incorrectly when - // both the debugserver and the inferior process shut down. - usleep (500000); - // If our process hasn't yet exited, debugserver might have died. - // If the process did exit, the we are reaping it. - const StateType state = process->GetState(); - - if (process->m_debugserver_pid != LLDB_INVALID_PROCESS_ID && - state != eStateInvalid && - state != eStateUnloaded && - state != eStateExited && - state != eStateDetached) - { - char error_str[1024]; - if (signo) - { - const char *signal_cstr = process->GetUnixSignals()->GetSignalAsCString(signo); - if (signal_cstr) - ::snprintf (error_str, sizeof (error_str), DEBUGSERVER_BASENAME " died with signal %s", signal_cstr); - else - ::snprintf (error_str, sizeof (error_str), DEBUGSERVER_BASENAME " died with signal %i", signo); - } - else - { - ::snprintf (error_str, sizeof (error_str), DEBUGSERVER_BASENAME " died with an exit status of 0x%8.8x", exit_status); - } - - process->SetExitStatus (-1, error_str); - } - // Debugserver has exited we need to let our ProcessGDBRemote - // know that it no longer has a debugserver instance - process->m_debugserver_pid = LLDB_INVALID_PROCESS_ID; + const char *signal_cstr = process_sp->GetUnixSignals()->GetSignalAsCString(signo); + if (signal_cstr) + ::snprintf(error_str, sizeof(error_str), DEBUGSERVER_BASENAME " died with signal %s", signal_cstr); + else + ::snprintf(error_str, sizeof(error_str), DEBUGSERVER_BASENAME " died with signal %i", signo); } + else + { + ::snprintf(error_str, sizeof(error_str), DEBUGSERVER_BASENAME " died with an exit status of 0x%8.8x", + exit_status); + } + + process_sp->SetExitStatus(-1, error_str); } - return true; + // Debugserver has exited we need to let our ProcessGDBRemote + // know that it no longer has a debugserver instance + process_sp->m_debugserver_pid = LLDB_INVALID_PROCESS_ID; + return handled; } void @@ -3757,7 +3800,7 @@ ProcessGDBRemote::StartAsyncThread () if (log) log->Printf ("ProcessGDBRemote::%s ()", __FUNCTION__); - Mutex::Locker start_locker(m_async_thread_state_mutex); + std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex); if (!m_async_thread.IsJoinable()) { // Create a thread that watches our internal state and controls which @@ -3779,7 +3822,7 @@ ProcessGDBRemote::StopAsyncThread () if (log) log->Printf ("ProcessGDBRemote::%s ()", __FUNCTION__); - Mutex::Locker start_locker(m_async_thread_state_mutex); + std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex); if (m_async_thread.IsJoinable()) { m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncThreadShouldExit); @@ -3839,7 +3882,7 @@ ProcessGDBRemote::AsyncThread (void *arg) { if (log) log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp)...", __FUNCTION__, arg, process->GetID()); - if (process->m_async_listener.WaitForEvent (NULL, event_sp)) + if (process->m_async_listener_sp->WaitForEvent (NULL, event_sp)) { const uint32_t event_type = event_sp->GetType(); if (event_sp->BroadcasterIs (&process->m_async_broadcaster)) @@ -4154,6 +4197,7 @@ ProcessGDBRemote::GetExtendedInfoForThread (lldb::tid_t tid) packet << (char) (0x7d ^ 0x20); StringExtractorGDBRemote response; + response.SetResponseValidatorToJSON(); if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, false) == GDBRemoteCommunication::PacketResult::Success) { StringExtractorGDBRemote::ResponseType response_type = response.GetResponseType(); @@ -4195,6 +4239,7 @@ ProcessGDBRemote::GetLoadedDynamicLibrariesInfos (lldb::addr_t image_list_addres packet << (char) (0x7d ^ 0x20); StringExtractorGDBRemote response; + response.SetResponseValidatorToJSON(); if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, false) == GDBRemoteCommunication::PacketResult::Success) { StringExtractorGDBRemote::ResponseType response_type = response.GetResponseType(); @@ -4337,14 +4382,11 @@ struct GdbServerTargetInfo }; bool -ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemoteDynamicRegisterInfo &dyn_reg_info, ABISP abi_sp) +ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemoteDynamicRegisterInfo &dyn_reg_info, ABISP abi_sp, uint32_t &cur_reg_num, uint32_t ®_offset) { if (!feature_node) return false; - uint32_t cur_reg_num = 0; - uint32_t reg_offset = 0; - feature_node.ForEachChildElementWithName("reg", [&target_info, &dyn_reg_info, &cur_reg_num, ®_offset, &abi_sp](const XMLNode ®_node) -> bool { std::string gdb_group; std::string gdb_type; @@ -4353,6 +4395,7 @@ ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemot ConstString set_name; std::vector<uint32_t> value_regs; std::vector<uint32_t> invalidate_regs; + std::vector<uint8_t> dwarf_opcode_bytes; bool encoding_set = false; bool format_set = false; RegisterInfo reg_info = { NULL, // Name @@ -4369,10 +4412,12 @@ ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemot cur_reg_num // native register number }, NULL, - NULL + NULL, + NULL, // Dwarf Expression opcode bytes pointer + 0 // Dwarf Expression opcode bytes length }; - reg_node.ForEachAttribute([&target_info, &gdb_group, &gdb_type, ®_name, &alt_name, &set_name, &value_regs, &invalidate_regs, &encoding_set, &format_set, ®_info, &cur_reg_num, ®_offset](const llvm::StringRef &name, const llvm::StringRef &value) -> bool { + reg_node.ForEachAttribute([&target_info, &gdb_group, &gdb_type, ®_name, &alt_name, &set_name, &value_regs, &invalidate_regs, &encoding_set, &format_set, ®_info, &cur_reg_num, ®_offset, &dwarf_opcode_bytes](const llvm::StringRef &name, const llvm::StringRef &value) -> bool { if (name == "name") { reg_name.SetString(value); @@ -4460,6 +4505,22 @@ ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemot { SplitCommaSeparatedRegisterNumberString(value, invalidate_regs, 0); } + else if (name == "dynamic_size_dwarf_expr_bytes") + { + StringExtractor opcode_extractor; + std::string opcode_string = value.str (); + size_t dwarf_opcode_len = opcode_string.length () / 2; + assert (dwarf_opcode_len > 0); + + dwarf_opcode_bytes.resize (dwarf_opcode_len); + reg_info.dynamic_size_dwarf_len = dwarf_opcode_len; + opcode_extractor.GetStringRef ().swap (opcode_string); + uint32_t ret_val = opcode_extractor.GetHexBytesAvail (dwarf_opcode_bytes.data (), + dwarf_opcode_len); + assert (dwarf_opcode_len == ret_val); + + reg_info.dynamic_size_dwarf_expr_bytes = dwarf_opcode_bytes.data (); + } else { printf("unhandled attribute %s = %s\n", name.data(), value.data()); @@ -4521,7 +4582,7 @@ ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemot // return: 'true' on success // 'false' on failure bool -ProcessGDBRemote::GetGDBServerRegisterInfo () +ProcessGDBRemote::GetGDBServerRegisterInfo (ArchSpec &arch_to_use) { // Make sure LLDB has an XML parser it can use first if (!XMLDocument::XMLEnabled()) @@ -4600,9 +4661,16 @@ ProcessGDBRemote::GetGDBServerRegisterInfo () return true; // Keep iterating through all children of the target_node }); + // Initialize these outside of ParseRegisters, since they should not be reset inside each include feature + uint32_t cur_reg_num = 0; + uint32_t reg_offset = 0; + + // Don't use Process::GetABI, this code gets called from DidAttach, and in that context we haven't + // set the Target's architecture yet, so the ABI is also potentially incorrect. + ABISP abi_to_use_sp = ABI::FindPlugin(arch_to_use); if (feature_node) { - ParseRegisters(feature_node, target_info, this->m_register_info, GetABI()); + ParseRegisters(feature_node, target_info, this->m_register_info, abi_to_use_sp, cur_reg_num, reg_offset); } for (const auto &include : target_info.includes) @@ -4620,10 +4688,10 @@ ProcessGDBRemote::GetGDBServerRegisterInfo () XMLNode include_feature_node = include_xml_document.GetRootElement("feature"); if (include_feature_node) { - ParseRegisters(include_feature_node, target_info, this->m_register_info, GetABI()); + ParseRegisters(include_feature_node, target_info, this->m_register_info, abi_to_use_sp, cur_reg_num, reg_offset); } } - this->m_register_info.Finalize(GetTarget().GetArchitecture()); + this->m_register_info.Finalize(arch_to_use); } } @@ -4785,25 +4853,14 @@ ProcessGDBRemote::GetLoadedModuleList (LoadedModuleInfoList & list) } lldb::ModuleSP -ProcessGDBRemote::LoadModuleAtAddress (const FileSpec &file, lldb::addr_t base_addr, bool value_is_offset) +ProcessGDBRemote::LoadModuleAtAddress (const FileSpec &file, lldb::addr_t link_map, + lldb::addr_t base_addr, bool value_is_offset) { - Target &target = m_process->GetTarget(); - ModuleList &modules = target.GetImages(); - ModuleSP module_sp; + DynamicLoader *loader = GetDynamicLoader(); + if (!loader) + return nullptr; - bool changed = false; - - ModuleSpec module_spec (file, target.GetArchitecture()); - if ((module_sp = modules.FindFirstModule (module_spec))) - { - module_sp->SetLoadAddress (target, base_addr, value_is_offset, changed); - } - else if ((module_sp = target.GetSharedModule (module_spec))) - { - module_sp->SetLoadAddress (target, base_addr, value_is_offset, changed); - } - - return module_sp; + return loader->LoadModuleAtAddress(file, link_map, base_addr, value_is_offset); } size_t @@ -4822,6 +4879,7 @@ ProcessGDBRemote::LoadModules (LoadedModuleInfoList &module_list) { std::string mod_name; lldb::addr_t mod_base; + lldb::addr_t link_map; bool mod_base_is_offset; bool valid = true; @@ -4831,15 +4889,12 @@ ProcessGDBRemote::LoadModules (LoadedModuleInfoList &module_list) if (!valid) continue; - // hack (cleaner way to get file name only?) (win/unix compat?) - size_t marker = mod_name.rfind ('/'); - if (marker == std::string::npos) - marker = 0; - else - marker += 1; + if (!modInfo.get_link_map (link_map)) + link_map = LLDB_INVALID_ADDRESS; - FileSpec file (mod_name.c_str()+marker, true); - lldb::ModuleSP module_sp = LoadModuleAtAddress (file, mod_base, mod_base_is_offset); + FileSpec file (mod_name.c_str(), true); + lldb::ModuleSP module_sp = LoadModuleAtAddress (file, link_map, mod_base, + mod_base_is_offset); if (module_sp.get()) new_modules.Append (module_sp); @@ -4847,7 +4902,30 @@ ProcessGDBRemote::LoadModules (LoadedModuleInfoList &module_list) if (new_modules.GetSize() > 0) { + ModuleList removed_modules; Target &target = GetTarget(); + ModuleList &loaded_modules = m_process->GetTarget().GetImages(); + + for (size_t i = 0; i < loaded_modules.GetSize(); ++i) + { + const lldb::ModuleSP loaded_module = loaded_modules.GetModuleAtIndex(i); + + bool found = false; + for (size_t j = 0; j < new_modules.GetSize(); ++j) + { + if (new_modules.GetModuleAtIndex(j).get() == loaded_module.get()) + found = true; + } + + // The main executable will never be included in libraries-svr4, don't remove it + if (!found && loaded_module.get() != target.GetExecutableModulePointer()) + { + removed_modules.Append (loaded_module); + } + } + + loaded_modules.Remove (removed_modules); + m_process->GetTarget().ModulesDidUnload (removed_modules, false); new_modules.ForEach ([&target](const lldb::ModuleSP module_sp) -> bool { @@ -4863,13 +4941,11 @@ ProcessGDBRemote::LoadModules (LoadedModuleInfoList &module_list) return false; }); - ModuleList &loaded_modules = m_process->GetTarget().GetImages(); loaded_modules.AppendIfNeeded (new_modules); m_process->GetTarget().ModulesDidLoad (new_modules); } return new_modules.GetSize(); - } size_t @@ -5231,11 +5307,9 @@ public: class CommandObjectMultiwordProcessGDBRemote : public CommandObjectMultiword { public: - CommandObjectMultiwordProcessGDBRemote (CommandInterpreter &interpreter) : - CommandObjectMultiword (interpreter, - "process plugin", - "A set of commands for operating on a ProcessGDBRemote process.", - "process plugin <subcommand> [<subcommand-options>]") + CommandObjectMultiwordProcessGDBRemote(CommandInterpreter &interpreter) + : CommandObjectMultiword(interpreter, "process plugin", "Commands for operating on a ProcessGDBRemote process.", + "process plugin <subcommand> [<subcommand-options>]") { LoadSubCommand ("packet", CommandObjectSP (new CommandObjectProcessGDBRemotePacket (interpreter))); } diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index b48edd8..6d37396 100644 --- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -14,6 +14,7 @@ // C++ Includes #include <atomic> #include <map> +#include <mutex> #include <string> #include <vector> @@ -45,13 +46,13 @@ class ThreadGDBRemote; class ProcessGDBRemote : public Process { public: - ProcessGDBRemote(lldb::TargetSP target_sp, Listener &listener); + ProcessGDBRemote(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp); ~ProcessGDBRemote() override; static lldb::ProcessSP CreateInstance (lldb::TargetSP target_sp, - Listener &listener, + lldb::ListenerSP listener_sp, const FileSpec *crash_file_path); static void @@ -279,12 +280,12 @@ protected: GDBRemoteCommunicationClient m_gdb_comm; std::atomic<lldb::pid_t> m_debugserver_pid; std::vector<StringExtractorGDBRemote> m_stop_packet_stack; // The stop packet stack replaces the last stop packet variable - Mutex m_last_stop_packet_mutex; + std::recursive_mutex m_last_stop_packet_mutex; GDBRemoteDynamicRegisterInfo m_register_info; Broadcaster m_async_broadcaster; - Listener m_async_listener; + lldb::ListenerSP m_async_listener_sp; HostThread m_async_thread; - Mutex m_async_thread_state_mutex; + std::recursive_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; typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap; @@ -405,11 +406,8 @@ protected: AsyncThread (void *arg); static bool - MonitorDebugserverProcess (void *callback_baton, - lldb::pid_t pid, - bool exited, - int signo, - int exit_status); + MonitorDebugserverProcess(std::weak_ptr<ProcessGDBRemote> process_wp, lldb::pid_t pid, bool exited, int signo, + int exit_status); lldb::StateType SetThreadStopInfo (StringExtractor& stop_packet); @@ -461,14 +459,15 @@ protected: // Query remote GDBServer for register information bool - GetGDBServerRegisterInfo (); + GetGDBServerRegisterInfo (ArchSpec &arch); // Query remote GDBServer for a detailed loaded library list Error GetLoadedModuleList (LoadedModuleInfoList &); lldb::ModuleSP - LoadModuleAtAddress (const FileSpec &file, lldb::addr_t base_addr, bool value_is_offset); + LoadModuleAtAddress (const FileSpec &file, lldb::addr_t link_map, lldb::addr_t base_addr, + bool value_is_offset); private: //------------------------------------------------------------------ |