diff options
Diffstat (limited to 'source/Plugins/Process/gdb-remote')
12 files changed, 466 insertions, 439 deletions
diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp index 2ea1f206008a..f164b1411be8 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/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/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index c0ea9cceea2e..c90706a88b84 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/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 @@ -3571,6 +3591,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 +4439,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/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index 311b0f3267c8..096c4cf81015 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/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/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h index f55b2eb3f4dc..d2fd70042ccc 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h +++ b/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/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index 921369c7ef21..fc6b31ec088e 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/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 @@ -2593,7 +2588,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 +2638,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 +2942,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/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h index f16057781ddc..caf6eb319e63 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h +++ b/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/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp index f88ac1247526..d6900c27293c 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp +++ b/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/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h index 1fe7207d2bc2..1f4d08c64e00 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h +++ b/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/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp index b0a1eaaeb79c..e5b347c9f72d 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp @@ -198,10 +198,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 +317,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 +814,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 +837,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 +895,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/source/Plugins/Process/gdb-remote/Makefile b/source/Plugins/Process/gdb-remote/Makefile deleted file mode 100644 index 8a9b61077875..000000000000 --- a/source/Plugins/Process/gdb-remote/Makefile +++ /dev/null @@ -1,14 +0,0 @@ -##===- source/Plugins/Process/gdb-remote/Makefile -------------*- Makefile -*-===## -#  -#                     The LLVM Compiler Infrastructure -# -# This file is distributed under the University of Illinois Open Source -# License. See LICENSE.TXT for details. -#  -##===----------------------------------------------------------------------===## - -LLDB_LEVEL := ../../../.. -LIBRARYNAME := lldbPluginProcessGDBRemote -BUILD_ARCHIVE = 1 - -include $(LLDB_LEVEL)/Makefile diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 856ea35aef99..4d56f6ea3ba1 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -223,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;  } @@ -267,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__); @@ -500,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]; @@ -640,7 +654,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);              } @@ -668,22 +687,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 @@ -1360,10 +1368,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(); @@ -1595,7 +1603,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) @@ -1638,7 +1646,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();  } @@ -1688,7 +1696,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)      { @@ -1721,8 +1729,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(); @@ -1832,7 +1840,7 @@ ProcessGDBRemote::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new                      }                  }              } -            new_thread_list.AddThread(thread_sp); +            new_thread_list.AddThreadSortedByIndexID (thread_sp);          }      } @@ -1936,7 +1944,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) @@ -2001,7 +2009,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) @@ -2040,7 +2059,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); @@ -2070,6 +2090,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)                      { @@ -2404,7 +2441,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 @@ -2627,7 +2665,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 @@ -2637,7 +2676,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 +2821,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 +2856,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++) @@ -2939,7 +2978,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. @@ -3119,35 +3158,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) @@ -3273,7 +3310,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); @@ -3289,7 +3327,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 @@ -3306,7 +3350,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); @@ -3318,7 +3363,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;          } @@ -3550,6 +3601,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)      { @@ -3561,7 +3614,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__)) @@ -3623,91 +3678,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 @@ -3756,7 +3778,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 @@ -3778,7 +3800,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); @@ -3838,7 +3860,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)) @@ -4153,6 +4175,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(); @@ -4194,6 +4217,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(); @@ -4336,14 +4360,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; @@ -4520,7 +4541,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()) @@ -4599,9 +4620,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) @@ -4619,10 +4647,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);          }      } @@ -4784,25 +4812,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; - -    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); -    } +    DynamicLoader *loader = GetDynamicLoader(); +    if (!loader) +        return nullptr; -    return module_sp; +    return loader->LoadModuleAtAddress(file, link_map, base_addr, value_is_offset);  }  size_t @@ -4821,6 +4838,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; @@ -4830,15 +4848,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); @@ -4846,7 +4861,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          { @@ -4862,13 +4900,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 @@ -5230,11 +5266,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/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index b48edd836a74..6d373965fc42 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/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:      //------------------------------------------------------------------  | 
