diff options
Diffstat (limited to 'source/Plugins/Process/gdb-remote')
17 files changed, 2058 insertions, 1312 deletions
| diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp index 9c263c8c40879..2ea1f206008a7 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -30,6 +30,7 @@  #include "lldb/Host/StringConvert.h"  #include "lldb/Host/ThreadLauncher.h"  #include "lldb/Host/TimeValue.h" +#include "lldb/Target/Platform.h"  #include "lldb/Target/Process.h"  #include "llvm/ADT/SmallString.h" @@ -574,15 +575,24 @@ GDBRemoteCommunication::DecompressPacket ()          return true;      if (m_bytes[1] != 'C' && m_bytes[1] != 'N')          return true; -    if (m_bytes[pkt_size - 3] != '#') + +    size_t hash_mark_idx = m_bytes.find ('#'); +    if (hash_mark_idx == std::string::npos) +        return true; +    if (hash_mark_idx + 2 >= m_bytes.size())          return true; -    if (!::isxdigit (m_bytes[pkt_size - 2]) || !::isxdigit (m_bytes[pkt_size - 1])) + +    if (!::isxdigit (m_bytes[hash_mark_idx + 1]) || !::isxdigit (m_bytes[hash_mark_idx + 2]))          return true; -    size_t content_length = pkt_size - 5;   // not counting '$', 'C' | 'N', '#', & the two hex checksum chars -    size_t content_start = 2;               // The first character of the compressed/not-compressed text of the packet -    size_t hash_mark_idx = pkt_size - 3;    // The '#' character marking the end of the packet -    size_t checksum_idx = pkt_size - 2;     // The first character of the two hex checksum characters +    size_t content_length = pkt_size - 5;    // not counting '$', 'C' | 'N', '#', & the two hex checksum chars +    size_t content_start = 2;                // The first character of the compressed/not-compressed text of the packet +    size_t checksum_idx = hash_mark_idx + 1; // The first character of the two hex checksum characters + +    // Normally size_of_first_packet == m_bytes.size() but m_bytes may contain multiple packets. +    // size_of_first_packet is the size of the initial packet which we'll replace with the decompressed +    // version of, leaving the rest of m_bytes unmodified. +    size_t size_of_first_packet = hash_mark_idx + 3;       // Compressed packets ("$C") start with a base10 number which is the size of the uncompressed payload,      // then a : and then the compressed data.  e.g. $C1024:<binary>#00 @@ -604,7 +614,7 @@ GDBRemoteCommunication::DecompressPacket ()              decompressed_bufsize = ::strtoul (bufsize_str.c_str(), NULL, 10);              if (errno != 0 || decompressed_bufsize == ULONG_MAX)              { -                m_bytes.erase (0, pkt_size); +                m_bytes.erase (0, size_of_first_packet);                  return false;              }          } @@ -633,7 +643,7 @@ GDBRemoteCommunication::DecompressPacket ()          if (!success)          {              SendNack(); -            m_bytes.erase (0, pkt_size); +            m_bytes.erase (0, size_of_first_packet);              return false;          }          else @@ -677,7 +687,7 @@ GDBRemoteCommunication::DecompressPacket ()          decompressed_buffer = (uint8_t *) malloc (decompressed_bufsize + 1);          if (decompressed_buffer == nullptr)          { -            m_bytes.erase (0, pkt_size); +            m_bytes.erase (0, size_of_first_packet);              return false;          } @@ -751,7 +761,7 @@ GDBRemoteCommunication::DecompressPacket ()      {          if (decompressed_buffer)              free (decompressed_buffer); -        m_bytes.erase (0, pkt_size); +        m_bytes.erase (0, size_of_first_packet);          return false;      } @@ -773,7 +783,7 @@ GDBRemoteCommunication::DecompressPacket ()          new_packet.push_back ('0');      } -    m_bytes = new_packet; +    m_bytes.replace (0, size_of_first_packet, new_packet.data(), new_packet.size());      free (decompressed_buffer);      return true; @@ -927,8 +937,10 @@ GDBRemoteCommunication::CheckForPacket (const uint8_t *src, size_t src_len, Stri                  {                      for (size_t i=0; !binary && i<total_length; ++i)                      { -                        if (isprint(m_bytes[i]) == 0) +                        if (isprint (m_bytes[i]) == 0 && isspace (m_bytes[i]) == 0) +                        {                              binary = true; +                        }                      }                  }                  if (binary) @@ -1100,16 +1112,16 @@ GDBRemoteCommunication::ListenThread (lldb::thread_arg_t arg)  }  Error -GDBRemoteCommunication::StartDebugserverProcess (const char *hostname, -                                                 uint16_t in_port, +GDBRemoteCommunication::StartDebugserverProcess (const char *url, +                                                 Platform *platform,                                                   ProcessLaunchInfo &launch_info, -                                                 uint16_t &out_port) +                                                 uint16_t *port, +                                                 const Args& inferior_args)  {      Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));      if (log) -        log->Printf ("GDBRemoteCommunication::%s(hostname=%s, in_port=%" PRIu16 ", out_port=%" PRIu16, __FUNCTION__, hostname ? hostname : "<empty>", in_port, out_port); +        log->Printf ("GDBRemoteCommunication::%s(url=%s, port=%" PRIu16, __FUNCTION__, url ? url : "<empty>", port ? *port : uint16_t(0)); -    out_port = in_port;      Error error;      // If we locate debugserver, keep that located version around      static FileSpec g_debugserver_file_spec; @@ -1146,11 +1158,20 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,              }              else              { -                if (log) -                    log->Printf ("GDBRemoteCommunication::%s() could not find gdb-remote stub exe '%s'", __FUNCTION__, debugserver_file_spec.GetPath ().c_str ()); - +                debugserver_file_spec = platform->LocateExecutable(DEBUGSERVER_BASENAME); +                if (debugserver_file_spec) +                { +                    // Platform::LocateExecutable() wouldn't return a path if it doesn't exist +                    debugserver_exists = true; +                } +                else +                { +                    if (log) +                        log->Printf ("GDBRemoteCommunication::%s() could not find gdb-remote stub exe '%s'", __FUNCTION__, debugserver_file_spec.GetPath ().c_str ()); +                } +                // Don't cache the platform specific GDB server binary as it could change +                // from platform to platform                  g_debugserver_file_spec.Clear(); -                debugserver_file_spec.Clear();              }          }      } @@ -1171,17 +1192,9 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,          debugserver_args.AppendArgument("gdbserver");  #endif -        // If a host and port is supplied then use it -        char host_and_port[128]; -        if (hostname) -        { -            snprintf (host_and_port, sizeof(host_and_port), "%s:%u", hostname, in_port); -            debugserver_args.AppendArgument(host_and_port); -        } -        else -        { -            host_and_port[0] = '\0'; -        } +        // If a url is supplied then use it +        if (url) +            debugserver_args.AppendArgument(url);          // use native registers, not the GDB registers          debugserver_args.AppendArgument("--native-regs"); @@ -1192,30 +1205,41 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,          }          llvm::SmallString<PATH_MAX> named_pipe_path; -        Pipe port_pipe; - -        if (host_and_port[0] && in_port == 0) +        // socket_pipe is used by debug server to communicate back either +        // TCP port or domain socket name which it listens on. +        // The second purpose of the pipe to serve as a synchronization point - +        // once data is written to the pipe, debug server is up and running. +        Pipe socket_pipe; + +        // port is null when debug server should listen on domain socket - +        // we're not interested in port value but rather waiting for debug server +        // to become available. +        if ((port != nullptr && *port == 0) || port == nullptr)          { -            // Create a temporary file to get the stdout/stderr and redirect the -            // output of the command into this file. We will later read this file -            // if all goes well and fill the data into "command_output_ptr" - -            // Binding to port zero, we need to figure out what port it ends up -            // using using a named pipe... -            error = port_pipe.CreateWithUniqueName("debugserver-named-pipe", false, named_pipe_path); -            if (error.Success()) +            if (url)              { +                // Create a temporary file to get the stdout/stderr and redirect the +                // output of the command into this file. We will later read this file +                // if all goes well and fill the data into "command_output_ptr" +     +#if defined(__APPLE__) +                // Binding to port zero, we need to figure out what port it ends up +                // using using a named pipe... +                error = socket_pipe.CreateWithUniqueName("debugserver-named-pipe", false, named_pipe_path); +                if (error.Fail()) +                { +                    if (log) +                        log->Printf("GDBRemoteCommunication::%s() " +                                "named pipe creation failed: %s", +                                __FUNCTION__, error.AsCString()); +                    return error; +                }                  debugserver_args.AppendArgument("--named-pipe");                  debugserver_args.AppendArgument(named_pipe_path.c_str()); -            } -            else -            { -                if (log) -                    log->Printf("GDBRemoteCommunication::%s() " -                            "named pipe creation failed: %s", -                            __FUNCTION__, error.AsCString()); -                // let's try an unnamed pipe -                error = port_pipe.CreateNew(true); +#else +                // Binding to port zero, we need to figure out what port it ends up +                // using using an unnamed pipe... +                error = socket_pipe.CreateNew(true);                  if (error.Fail())                  {                      if (log) @@ -1224,42 +1248,43 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,                                  __FUNCTION__, error.AsCString());                      return error;                  } -                int write_fd = port_pipe.GetWriteFileDescriptor(); +                int write_fd = socket_pipe.GetWriteFileDescriptor();                  debugserver_args.AppendArgument("--pipe");                  debugserver_args.AppendArgument(std::to_string(write_fd).c_str()); -                launch_info.AppendCloseFileAction(port_pipe.GetReadFileDescriptor()); -            } -        } -        else -        { -            // No host and port given, so lets listen on our end and make the debugserver -            // connect to us.. -            error = StartListenThread ("127.0.0.1", 0); -            if (error.Fail()) -            { -                if (log) -                    log->Printf ("GDBRemoteCommunication::%s() unable to start listen thread: %s", __FUNCTION__, error.AsCString()); -                return error; -            } - -            ConnectionFileDescriptor *connection = (ConnectionFileDescriptor *)GetConnection (); -            // Wait for 10 seconds to resolve the bound port -            out_port = connection->GetListeningPort(10); -            if (out_port > 0) -            { -                char port_cstr[32]; -                snprintf(port_cstr, sizeof(port_cstr), "127.0.0.1:%i", out_port); -                // Send the host and port down that debugserver and specify an option -                // so that it connects back to the port we are listening to in this process -                debugserver_args.AppendArgument("--reverse-connect"); -                debugserver_args.AppendArgument(port_cstr); +                launch_info.AppendCloseFileAction(socket_pipe.GetReadFileDescriptor()); +#endif              }              else              { -                error.SetErrorString ("failed to bind to port 0 on 127.0.0.1"); -                if (log) -                    log->Printf ("GDBRemoteCommunication::%s() failed: %s", __FUNCTION__, error.AsCString()); -                return error; +                // No host and port given, so lets listen on our end and make the debugserver +                // connect to us.. +                error = StartListenThread ("127.0.0.1", 0); +                if (error.Fail()) +                { +                    if (log) +                        log->Printf ("GDBRemoteCommunication::%s() unable to start listen thread: %s", __FUNCTION__, error.AsCString()); +                    return error; +                } +     +                ConnectionFileDescriptor *connection = (ConnectionFileDescriptor *)GetConnection (); +                // Wait for 10 seconds to resolve the bound port +                *port = connection->GetListeningPort(10); +                if (*port > 0) +                { +                    char port_cstr[32]; +                    snprintf(port_cstr, sizeof(port_cstr), "127.0.0.1:%i", *port); +                    // Send the host and port down that debugserver and specify an option +                    // so that it connects back to the port we are listening to in this process +                    debugserver_args.AppendArgument("--reverse-connect"); +                    debugserver_args.AppendArgument(port_cstr); +                } +                else +                { +                    error.SetErrorString ("failed to bind to port 0 on 127.0.0.1"); +                    if (log) +                        log->Printf ("GDBRemoteCommunication::%s() failed: %s", __FUNCTION__, error.AsCString()); +                    return error; +                }              }          } @@ -1304,6 +1329,20 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,              }          } while (has_env_var); +        if (inferior_args.GetArgumentCount() > 0) +        { +            debugserver_args.AppendArgument ("--"); +            debugserver_args.AppendArguments (inferior_args); +        } + +        // Copy the current environment to the gdbserver/debugserver instance +        StringList env; +        if (Host::GetEnvironment(env)) +        { +            for (size_t i = 0; i < env.GetSize(); ++i) +                launch_info.GetEnvironmentEntries().AppendArgument(env[i].c_str()); +        } +          // Close STDIN, STDOUT and STDERR.          launch_info.AppendCloseFileAction (STDIN_FILENO);          launch_info.AppendCloseFileAction (STDOUT_FILENO); @@ -1316,11 +1355,12 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,          error = Host::LaunchProcess(launch_info); -        if (error.Success() && launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) +        if (error.Success() && +            launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)          {              if (named_pipe_path.size() > 0)              { -                error = port_pipe.OpenAsReader(named_pipe_path, false); +                error = socket_pipe.OpenAsReader(named_pipe_path, false);                  if (error.Fail())                      if (log)                          log->Printf("GDBRemoteCommunication::%s() " @@ -1328,24 +1368,24 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,                                  __FUNCTION__, named_pipe_path.c_str(), error.AsCString());              } -            if (port_pipe.CanWrite()) -                port_pipe.CloseWriteFileDescriptor(); -            if (port_pipe.CanRead()) +            if (socket_pipe.CanWrite()) +                socket_pipe.CloseWriteFileDescriptor(); +            if (socket_pipe.CanRead())              { -                char port_cstr[256]; +                char port_cstr[PATH_MAX] = {0};                  port_cstr[0] = '\0';                  size_t num_bytes = sizeof(port_cstr);                  // Read port from pipe with 10 second timeout. -                error = port_pipe.ReadWithTimeout(port_cstr, num_bytes, +                error = socket_pipe.ReadWithTimeout(port_cstr, num_bytes,                          std::chrono::seconds{10}, num_bytes); -                if (error.Success()) +                if (error.Success() && (port != nullptr))                  {                      assert(num_bytes > 0 && port_cstr[num_bytes-1] == '\0'); -                    out_port = StringConvert::ToUInt32(port_cstr, 0); +                    *port = StringConvert::ToUInt32(port_cstr, 0);                      if (log)                          log->Printf("GDBRemoteCommunication::%s() " -                                "debugserver listens %u port", -                                __FUNCTION__, out_port); +                                    "debugserver listens %u port", +                                    __FUNCTION__, *port);                  }                  else                  { @@ -1355,12 +1395,12 @@ GDBRemoteCommunication::StartDebugserverProcess (const char *hostname,                                  __FUNCTION__, named_pipe_path.c_str(), error.AsCString());                  } -                port_pipe.Close(); +                socket_pipe.Close();              }              if (named_pipe_path.size() > 0)              { -                const auto err = port_pipe.Delete(named_pipe_path); +                const auto err = socket_pipe.Delete(named_pipe_path);                  if (err.Fail())                  {                      if (log) diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h index 7379bb3aa09b1..2a01bcec260ca 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h @@ -12,9 +12,9 @@  // C Includes  // C++ Includes -#include <list>  #include <string>  #include <queue> +#include <vector>  // Other libraries and framework includes  // Project includes @@ -25,6 +25,7 @@  #include "lldb/Host/Mutex.h"  #include "lldb/Host/Predicate.h"  #include "lldb/Host/TimeValue.h" +#include "lldb/Interpreter/Args.h"  #include "Utility/StringExtractorGDBRemote.h" @@ -94,14 +95,10 @@ public:          uint32_t m_saved_timeout;      }; -    //------------------------------------------------------------------ -    // Constructors and Destructors -    //------------------------------------------------------------------      GDBRemoteCommunication(const char *comm_name,                              const char *listener_name); -    virtual -    ~GDBRemoteCommunication(); +    ~GDBRemoteCommunication() override;      PacketResult      GetAck (); @@ -117,12 +114,13 @@ public:                          size_t payload_length);      bool -    GetSequenceMutex (Mutex::Locker& locker, const char *failure_message = NULL); +    GetSequenceMutex(Mutex::Locker& locker, const char *failure_message = nullptr);      PacketType      CheckForPacket (const uint8_t *src,                       size_t src_len,                       StringExtractorGDBRemote &packet); +      bool      IsRunning() const      { @@ -162,21 +160,22 @@ public:      {          return m_packet_timeout * TimeValue::MicroSecPerSec;      } +      //------------------------------------------------------------------      // Start a debugserver instance on the current host using the      // supplied connection URL.      //------------------------------------------------------------------      Error -    StartDebugserverProcess (const char *hostname, -                             uint16_t in_port, // If set to zero, then out_port will contain the bound port on exit -                             ProcessLaunchInfo &launch_info, -                             uint16_t &out_port); +    StartDebugserverProcess(const char *url, +                            Platform *platform, // If non nullptr, then check with the platform for the GDB server binary if it can't be located +                            ProcessLaunchInfo &launch_info, +                            uint16_t *port, +                            const Args& inferior_args = Args());      void      DumpHistory(Stream &strm);  protected: -      class History      {      public: @@ -223,6 +222,7 @@ protected:          AddPacket (char packet_char,                     PacketType type,                     uint32_t bytes_transmitted); +          void          AddPacket (const std::string &src,                     uint32_t src_len, @@ -241,7 +241,7 @@ protected:              return m_dumped_to_log;          } -protected: +    protected:          uint32_t          GetFirstSavedPacketIndex () const          { @@ -275,13 +275,30 @@ protected:              return i % m_packets.size();          } -                  std::vector<Entry> m_packets;          uint32_t m_curr_idx;          uint32_t m_total_packet_count;          mutable bool m_dumped_to_log;      }; +    uint32_t m_packet_timeout; +    uint32_t m_echo_number; +    LazyBool m_supports_qEcho; +#ifdef ENABLE_MUTEX_ERROR_CHECKING +    TrackingMutex m_sequence_mutex; +#else +    Mutex m_sequence_mutex;    // Restrict access to sending/receiving packets to a single thread at a time +#endif +    Predicate<bool> m_public_is_running; +    Predicate<bool> m_private_is_running; +    History m_history; +    bool m_send_acks; +    bool m_is_platform; // Set to true if this class represents a platform, +                        // false if this class represents a debug session for +                        // a single process +     +    CompressionType m_compression_type; +      PacketResult      SendPacket (const char *payload,                  size_t payload_length); @@ -321,27 +338,6 @@ protected:      bool      DecompressPacket (); -    //------------------------------------------------------------------ -    // Classes that inherit from GDBRemoteCommunication can see and modify these -    //------------------------------------------------------------------ -    uint32_t m_packet_timeout; -    uint32_t m_echo_number; -    LazyBool m_supports_qEcho; -#ifdef ENABLE_MUTEX_ERROR_CHECKING -    TrackingMutex m_sequence_mutex; -#else -    Mutex m_sequence_mutex;    // Restrict access to sending/receiving packets to a single thread at a time -#endif -    Predicate<bool> m_public_is_running; -    Predicate<bool> m_private_is_running; -    History m_history; -    bool m_send_acks; -    bool m_is_platform; // Set to true if this class represents a platform, -                        // false if this class represents a debug session for -                        // a single process -     -    CompressionType m_compression_type; -      Error      StartListenThread (const char *hostname = "127.0.0.1", uint16_t port = 0); @@ -361,10 +357,12 @@ protected:      // This method is defined as part of communication.h      // when the read thread gets any bytes it will pass them on to this function -    virtual void AppendBytesToCache (const uint8_t * bytes, size_t len, bool broadcast, lldb::ConnectionStatus status); +    void AppendBytesToCache(const uint8_t * bytes, +                            size_t len, +                            bool broadcast, +                            lldb::ConnectionStatus status) override;  private: -      std::queue<StringExtractorGDBRemote> m_packet_queue; // The packet queue      lldb_private::Mutex m_packet_queue_mutex;            // Mutex for accessing queue      Condition m_condition_queue_not_empty;               // Condition variable to wait for packets @@ -372,13 +370,10 @@ private:      HostThread m_listen_thread;      std::string m_listen_url; -    //------------------------------------------------------------------ -    // For GDBRemoteCommunication only -    //------------------------------------------------------------------      DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunication);  };  } // namespace process_gdb_remote  } // namespace lldb_private -#endif  // liblldb_GDBRemoteCommunication_h_ +#endif // liblldb_GDBRemoteCommunication_h_ diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index b8c67c593b1f2..5c7f6caca511f 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -619,7 +619,6 @@ GDBRemoteCommunicationClient::GetThreadsInfo()      if (m_supports_jThreadsInfo)      {          StringExtractorGDBRemote response; -        m_supports_jThreadExtendedInfo = eLazyBoolNo;          if (SendPacketAndWaitForResponse("jThreadsInfo", response, false) == PacketResult::Success)          {              if (response.IsUnsupportedResponse()) @@ -782,7 +781,7 @@ GDBRemoteCommunicationClient::SendPacketAndWaitForResponse      Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));      // In order to stop async notifications from being processed in the middle of the -    // send/recieve sequence Hijack the broadcast. Then rebroadcast any events when we are done. +    // send/receive sequence Hijack the broadcast. Then rebroadcast any events when we are done.      static Listener hijack_listener("lldb.NotifyHijacker");      HijackBroadcaster(&hijack_listener, eBroadcastBitGdbReadThreadGotNotify);     @@ -878,10 +877,10 @@ GDBRemoteCommunicationClient::SendPacketAndWaitForResponse          }      } -    // Remove our Hijacking listner from the broadcast. +    // Remove our Hijacking listener from the broadcast.      RestoreBroadcaster(); -    // If a notification event occured, rebroadcast since it can now be processed safely.   +    // If a notification event occurred, rebroadcast since it can now be processed safely.      EventSP event_sp;      if (hijack_listener.GetNextEvent(event_sp))          BroadcastEvent(event_sp); @@ -1050,7 +1049,6 @@ GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse      Mutex::Locker locker(m_sequence_mutex);      StateType state = eStateRunning; -    BroadcastEvent(eBroadcastBitRunPacketSent, NULL);      m_public_is_running.SetValue (true, eBroadcastNever);      // Set the starting continue packet into "continue_packet". This packet      // may change if we are interrupted and we continue after an async packet... @@ -1060,6 +1058,7 @@ GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse      const auto sigint_signo = process->GetUnixSignals()->GetSignalNumberFromName("SIGINT");      bool got_async_packet = false; +    bool broadcast_sent = false;      while (state == eStateRunning)      { @@ -1072,6 +1071,12 @@ GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse              else                  m_interrupt_sent = false; +            if (! broadcast_sent) +            { +                BroadcastEvent(eBroadcastBitRunPacketSent, NULL); +                broadcast_sent = true; +            } +              m_private_is_running.SetValue (true, eBroadcastAlways);          } @@ -1133,10 +1138,10 @@ GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse                                  continue_after_async = false;                                  // We didn't get a SIGINT or SIGSTOP, so try for a -                                // very brief time (1 ms) to get another stop reply +                                // 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 = 1000; +                                uint32_t timeout_usec = 100000;                                  if (ReadPacket (extra_stop_reply_packet, timeout_usec, false) == PacketResult::Success)                                  {                                      switch (extra_stop_reply_packet.GetChar()) @@ -1262,9 +1267,13 @@ GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse                          got_async_packet = true;                          std::string inferior_stdout;                          inferior_stdout.reserve(response.GetBytesLeft () / 2); -                        char ch; -                        while ((ch = response.GetHexU8()) != '\0') -                            inferior_stdout.append(1, ch); + +                        uint8_t ch; +                        while (response.GetHexU8Ex(ch)) +                        { +                            if (ch != 0) +                                inferior_stdout.append(1, (char)ch); +                        }                          process->AppendSTDOUT (inferior_stdout.c_str(), inferior_stdout.size());                      }                      break; @@ -1574,6 +1583,8 @@ GDBRemoteCommunicationClient::SendEnvironmentPacket (char const *name_equal_valu                  {                      case '$':                      case '#': +                    case '*': +                    case '}':                          send_hex_encoding = true;                          break;                      default: @@ -2308,7 +2319,8 @@ GDBRemoteCommunicationClient::Detach (bool keep_stopped)              const int packet_len = ::snprintf(packet, sizeof(packet), "qSupportsDetachAndStayStopped:");              assert (packet_len < (int)sizeof(packet));              StringExtractorGDBRemote response; -            if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success) +            if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success +                  && response.IsOKResponse())              {                  m_supports_detach_stay_stopped = eLazyBoolYes;                      } @@ -2326,7 +2338,7 @@ GDBRemoteCommunicationClient::Detach (bool keep_stopped)          else          {              StringExtractorGDBRemote response; -            PacketResult packet_result = SendPacketAndWaitForResponse ("D1", 1, response, false); +            PacketResult packet_result = SendPacketAndWaitForResponse ("D1", 2, response, false);              if (packet_result != PacketResult::Success)                  error.SetErrorString ("Sending extended disconnect packet failed.");          } @@ -3311,10 +3323,16 @@ GDBRemoteCommunicationClient::SendSpeedTestPacket (uint32_t send_size, uint32_t      return SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false)  == PacketResult::Success;  } -uint16_t -GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort (lldb::pid_t &pid, const char *remote_accept_hostname) +bool +GDBRemoteCommunicationClient::LaunchGDBServer (const char *remote_accept_hostname, +                                               lldb::pid_t &pid, +                                               uint16_t &port, +                                               std::string &socket_name)  {      pid = LLDB_INVALID_PROCESS_ID; +    port = 0; +    socket_name.clear(); +      StringExtractorGDBRemote response;      StreamString stream;      stream.PutCString("qLaunchGDBServer;"); @@ -3339,22 +3357,67 @@ GDBRemoteCommunicationClient::LaunchGDBserverAndGetPort (lldb::pid_t &pid, const      // give the process a few seconds to startup      GDBRemoteCommunication::ScopedTimeout timeout (*this, 10); -     +      if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)      {          std::string name;          std::string value; -        uint16_t port = 0; +        StringExtractor extractor;          while (response.GetNameColonValue(name, value))          {              if (name.compare("port") == 0)                  port = StringConvert::ToUInt32(value.c_str(), 0, 0);              else if (name.compare("pid") == 0)                  pid = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_PROCESS_ID, 0); +            else if (name.compare("socket_name") == 0) +            { +                extractor.GetStringRef().swap(value); +                extractor.SetFilePos(0); +                extractor.GetHexByteString(value); + +                socket_name = value; +            }          } -        return port; +        return true;      } -    return 0; +    return false; +} + +size_t +GDBRemoteCommunicationClient::QueryGDBServer (std::vector<std::pair<uint16_t, std::string>>& connection_urls) +{ +    connection_urls.clear(); + +    StringExtractorGDBRemote response; +    if (SendPacketAndWaitForResponse("qQueryGDBServer", response, false) != PacketResult::Success) +        return 0; + +    StructuredData::ObjectSP data = StructuredData::ParseJSON(response.GetStringRef()); +    if (!data) +        return 0; + +    StructuredData::Array* array = data->GetAsArray(); +    if (!array) +        return 0; + +    for (size_t i = 0, count = array->GetSize(); i < count; ++i) +    { +        StructuredData::Dictionary* element = nullptr; +        if (!array->GetItemAtIndexAsDictionary(i, element)) +            continue; + +        uint16_t port = 0; +        if (StructuredData::ObjectSP port_osp = element->GetValueForKey(llvm::StringRef("port"))) +            port = port_osp->GetIntegerValue(0); + +        std::string socket_name; +        if (StructuredData::ObjectSP socket_name_osp = element->GetValueForKey(llvm::StringRef("socket_name"))) +            socket_name = socket_name_osp->GetStringValue(); + +        if (port != 0 || !socket_name.empty()) +            connection_urls.emplace_back(port, socket_name); +    } +    return connection_urls.size();  }  bool @@ -3395,6 +3458,17 @@ GDBRemoteCommunicationClient::SetCurrentThread (uint64_t tid)              m_curr_tid = tid;              return true;          } + +        /* +         * Connected bare-iron target (like YAMON gdb-stub) may not have support for Hg packet. +         * The reply from '?' packet could be as simple as 'S05'. There is no packet which can +         * give us pid and/or tid. Assume pid=tid=1 in such cases. +        */ +        if (response.IsUnsupportedResponse() && IsConnected()) +        { +            m_curr_tid = 1; +            return true; +        }      }      return false;  } @@ -3421,6 +3495,17 @@ GDBRemoteCommunicationClient::SetCurrentThreadForRun (uint64_t tid)              m_curr_tid_run = tid;              return true;          } + +        /* +         * Connected bare-iron target (like YAMON gdb-stub) may not have support for Hc packet. +         * The reply from '?' packet could be as simple as 'S05'. There is no packet which can +         * give us pid and/or tid. Assume pid=tid=1 in such cases. +        */ +        if (response.IsUnsupportedResponse() && IsConnected()) +        { +            m_curr_tid_run = 1; +            return true; +        }      }      return false;  } @@ -3546,6 +3631,17 @@ GDBRemoteCommunicationClient::GetCurrentThreadIDs (std::vector<lldb::tid_t> &thr                  } while (ch == ',');            // Make sure we got a comma separator              }          } + +        /* +         * Connected bare-iron target (like YAMON gdb-stub) may not have support for +         * qProcessInfo, qC and qfThreadInfo packets. The reply from '?' packet could +         * be as simple as 'S05'. There is no packet which can give us pid and/or tid. +         * Assume pid=tid=1 in such cases. +        */ +        if (response.IsUnsupportedResponse() && thread_ids.size() == 0 && IsConnected()) +        { +            thread_ids.push_back (1); +        }      }      else      { @@ -4347,100 +4443,97 @@ GDBRemoteCommunicationClient::ServeSymbolLookups(lldb_private::Process *process)          {              StreamString packet;              packet.PutCString ("qSymbol::"); -            while (1) +            StringExtractorGDBRemote response; +            while (SendPacketAndWaitForResponseNoLock(packet.GetData(), packet.GetSize(), response) == PacketResult::Success)              { -                StringExtractorGDBRemote response; -                if (SendPacketAndWaitForResponseNoLock(packet.GetData(), packet.GetSize(), response) == PacketResult::Success) +                if (response.IsOKResponse())                  { -                    if (response.IsOKResponse()) -                    { -                        // We are done serving symbols requests -                        return; -                    } +                    // We are done serving symbols requests +                    return; +                } -                    if (response.IsUnsupportedResponse()) -                    { -                        // qSymbol is not supported by the current GDB server we are connected to -                        m_supports_qSymbol = false; -                        return; -                    } -                    else +                if (response.IsUnsupportedResponse()) +                { +                    // qSymbol is not supported by the current GDB server we are connected to +                    m_supports_qSymbol = false; +                    return; +                } +                else +                { +                    llvm::StringRef response_str(response.GetStringRef()); +                    if (response_str.startswith("qSymbol:"))                      { -                        llvm::StringRef response_str(response.GetStringRef()); -                        if (response_str.startswith("qSymbol:")) +                        response.SetFilePos(strlen("qSymbol:")); +                        std::string symbol_name; +                        if (response.GetHexByteString(symbol_name))                          { -                            response.SetFilePos(strlen("qSymbol:")); -                            std::string symbol_name; -                            if (response.GetHexByteString(symbol_name)) -                            { -                                if (symbol_name.empty()) -                                    return; +                            if (symbol_name.empty()) +                                return; -                                addr_t symbol_load_addr = LLDB_INVALID_ADDRESS; -                                lldb_private::SymbolContextList sc_list; -                                if (process->GetTarget().GetImages().FindSymbolsWithNameAndType(ConstString(symbol_name), eSymbolTypeAny, sc_list)) +                            addr_t symbol_load_addr = LLDB_INVALID_ADDRESS; +                            lldb_private::SymbolContextList sc_list; +                            if (process->GetTarget().GetImages().FindSymbolsWithNameAndType(ConstString(symbol_name), eSymbolTypeAny, sc_list)) +                            { +                                const size_t num_scs = sc_list.GetSize(); +                                for (size_t sc_idx=0; sc_idx<num_scs && symbol_load_addr == LLDB_INVALID_ADDRESS; ++sc_idx)                                  { -                                    const size_t num_scs = sc_list.GetSize(); -                                    for (size_t sc_idx=0; sc_idx<num_scs && symbol_load_addr == LLDB_INVALID_ADDRESS; ++sc_idx) +                                    SymbolContext sc; +                                    if (sc_list.GetContextAtIndex(sc_idx, sc))                                      { -                                        SymbolContext sc; -                                        if (sc_list.GetContextAtIndex(sc_idx, sc)) +                                        if (sc.symbol)                                          { -                                            if (sc.symbol) +                                            switch (sc.symbol->GetType())                                              { -                                                switch (sc.symbol->GetType()) -                                                { -                                                case eSymbolTypeInvalid: -                                                case eSymbolTypeAbsolute: -                                                case eSymbolTypeUndefined: -                                                case eSymbolTypeSourceFile: -                                                case eSymbolTypeHeaderFile: -                                                case eSymbolTypeObjectFile: -                                                case eSymbolTypeCommonBlock: -                                                case eSymbolTypeBlock: -                                                case eSymbolTypeLocal: -                                                case eSymbolTypeParam: -                                                case eSymbolTypeVariable: -                                                case eSymbolTypeVariableType: -                                                case eSymbolTypeLineEntry: -                                                case eSymbolTypeLineHeader: -                                                case eSymbolTypeScopeBegin: -                                                case eSymbolTypeScopeEnd: -                                                case eSymbolTypeAdditional: -                                                case eSymbolTypeCompiler: -                                                case eSymbolTypeInstrumentation: -                                                case eSymbolTypeTrampoline: -                                                    break; - -                                                case eSymbolTypeCode: -                                                case eSymbolTypeResolver: -                                                case eSymbolTypeData: -                                                case eSymbolTypeRuntime: -                                                case eSymbolTypeException: -                                                case eSymbolTypeObjCClass: -                                                case eSymbolTypeObjCMetaClass: -                                                case eSymbolTypeObjCIVar: -                                                case eSymbolTypeReExported: -                                                    symbol_load_addr = sc.symbol->GetLoadAddress(&process->GetTarget()); -                                                    break; -                                                } +                                            case eSymbolTypeInvalid: +                                            case eSymbolTypeAbsolute: +                                            case eSymbolTypeUndefined: +                                            case eSymbolTypeSourceFile: +                                            case eSymbolTypeHeaderFile: +                                            case eSymbolTypeObjectFile: +                                            case eSymbolTypeCommonBlock: +                                            case eSymbolTypeBlock: +                                            case eSymbolTypeLocal: +                                            case eSymbolTypeParam: +                                            case eSymbolTypeVariable: +                                            case eSymbolTypeVariableType: +                                            case eSymbolTypeLineEntry: +                                            case eSymbolTypeLineHeader: +                                            case eSymbolTypeScopeBegin: +                                            case eSymbolTypeScopeEnd: +                                            case eSymbolTypeAdditional: +                                            case eSymbolTypeCompiler: +                                            case eSymbolTypeInstrumentation: +                                            case eSymbolTypeTrampoline: +                                                break; + +                                            case eSymbolTypeCode: +                                            case eSymbolTypeResolver: +                                            case eSymbolTypeData: +                                            case eSymbolTypeRuntime: +                                            case eSymbolTypeException: +                                            case eSymbolTypeObjCClass: +                                            case eSymbolTypeObjCMetaClass: +                                            case eSymbolTypeObjCIVar: +                                            case eSymbolTypeReExported: +                                                symbol_load_addr = sc.symbol->GetLoadAddress(&process->GetTarget()); +                                                break;                                              }                                          }                                      }                                  } -                                // This is the normal path where our symbol lookup was successful and we want -                                // to send a packet with the new symbol value and see if another lookup needs to be -                                // done. - -                                // Change "packet" to contain the requested symbol value and name -                                packet.Clear(); -                                packet.PutCString("qSymbol:"); -                                if (symbol_load_addr != LLDB_INVALID_ADDRESS) -                                    packet.Printf("%" PRIx64, symbol_load_addr); -                                packet.PutCString(":"); -                                packet.PutBytesAsRawHex8(symbol_name.data(), symbol_name.size()); -                                continue; // go back to the while loop and send "packet" and wait for another response                              } +                            // This is the normal path where our symbol lookup was successful and we want +                            // to send a packet with the new symbol value and see if another lookup needs to be +                            // done. + +                            // Change "packet" to contain the requested symbol value and name +                            packet.Clear(); +                            packet.PutCString("qSymbol:"); +                            if (symbol_load_addr != LLDB_INVALID_ADDRESS) +                                packet.Printf("%" PRIx64, symbol_load_addr); +                            packet.PutCString(":"); +                            packet.PutBytesAsRawHex8(symbol_name.data(), symbol_name.size()); +                            continue; // go back to the while loop and send "packet" and wait for another response                          }                      }                  } diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index b08ff0647797c..d2df214d0dbad 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -12,6 +12,8 @@  // C Includes  // C++ Includes +#include <map> +#include <string>  #include <vector>  // Other libraries and framework includes @@ -28,12 +30,9 @@ namespace process_gdb_remote {  class GDBRemoteCommunicationClient : public GDBRemoteCommunication  {  public: -    //------------------------------------------------------------------ -    // Constructors and Destructors -    //------------------------------------------------------------------      GDBRemoteCommunicationClient(); -    ~GDBRemoteCommunicationClient(); +    ~GDBRemoteCommunicationClient() override;      //------------------------------------------------------------------      // After connecting, send the handshake to the server to make sure @@ -79,6 +78,7 @@ public:                                            const char *packet_payload,                                            size_t packet_length,                                            StringExtractorGDBRemote &response); +      bool      SendvContPacket (ProcessGDBRemote *process,                       const char *payload, @@ -114,9 +114,15 @@ public:      bool      GetLaunchSuccess (std::string &error_str); -    uint16_t -    LaunchGDBserverAndGetPort (lldb::pid_t &pid, const char *remote_accept_hostname); -     +    bool +    LaunchGDBServer (const char *remote_accept_hostname, +                     lldb::pid_t &pid, +                     uint16_t &port, +                     std::string &socket_name); + +    size_t +    QueryGDBServer (std::vector<std::pair<uint16_t, std::string>>& connection_urls); +      bool      KillSpawnedProcess (lldb::pid_t pid); @@ -161,7 +167,7 @@ public:      SendLaunchArchPacket (const char *arch);      int -    SendLaunchEventDataPacket (const char *data, bool *was_supported = NULL); +    SendLaunchEventDataPacket(const char *data, bool *was_supported = nullptr);      //------------------------------------------------------------------      /// Sends a "vAttach:PID" where PID is in hex.  @@ -182,7 +188,6 @@ public:      SendAttach (lldb::pid_t pid,                   StringExtractorGDBRemote& response); -      //------------------------------------------------------------------      /// Sends a GDB remote protocol 'I' packet that delivers stdin      /// data to the remote process. @@ -396,6 +401,7 @@ public:          default:                    return false;          }      } +      uint8_t      SendGDBStoppointTypePacket (GDBStoppointType type,   // Type of breakpoint or watchpoint                                  bool insert,              // Insert or remove? @@ -505,11 +511,11 @@ public:      GetFileExists (const FileSpec& file_spec);      Error -    RunShellCommand(const char *command,           // Shouldn't be NULL +    RunShellCommand(const char *command,           // Shouldn't be nullptr                      const FileSpec &working_dir,   // Pass empty FileSpec to use the current working directory -                    int *status_ptr,               // Pass NULL if you don't want the process exit status -                    int *signo_ptr,                // Pass NULL if you don't want the signal that caused the process to exit -                    std::string *command_output,   // Pass NULL if you don't want the command output +                    int *status_ptr,               // Pass nullptr if you don't want the process exit status +                    int *signo_ptr,                // Pass nullptr if you don't want the signal that caused the process to exit +                    std::string *command_output,   // Pass nullptr if you don't want the command output                      uint32_t timeout_sec);         // Timeout in seconds to wait for shell program to finish      bool @@ -567,26 +573,6 @@ public:      ServeSymbolLookups(lldb_private::Process *process);  protected: - -    PacketResult -    SendPacketAndWaitForResponseNoLock (const char *payload, -                                        size_t payload_length, -                                        StringExtractorGDBRemote &response); - -    bool -    GetCurrentProcessInfo (bool allow_lazy_pid = true); - -    bool -    GetGDBServerVersion(); - -    // Given the list of compression types that the remote debug stub can support, -    // possibly enable compression if we find an encoding we can handle. -    void -    MaybeEnableCompression (std::vector<std::string> supported_compressions); - -    //------------------------------------------------------------------ -    // Classes that inherit from GDBRemoteCommunicationClient can see and modify these -    //------------------------------------------------------------------      LazyBool m_supports_not_sending_acks;      LazyBool m_supports_thread_suffix;      LazyBool m_supports_threads_in_stop_reply; @@ -639,7 +625,6 @@ protected:      lldb::tid_t m_curr_tid;         // Current gdb remote protocol thread index for all other operations      lldb::tid_t m_curr_tid_run;     // Current gdb remote protocol thread index for continue, step, etc -      uint32_t m_num_supported_hardware_watchpoints;      // If we need to send a packet while the target is running, the m_async_XXX @@ -667,18 +652,31 @@ protected:      uint32_t m_default_packet_timeout;      uint64_t m_max_packet_size;  // as returned by qSupported -     +    PacketResult +    SendPacketAndWaitForResponseNoLock (const char *payload, +                                        size_t payload_length, +                                        StringExtractorGDBRemote &response); + +    bool +    GetCurrentProcessInfo (bool allow_lazy_pid = true); + +    bool +    GetGDBServerVersion(); + +    // Given the list of compression types that the remote debug stub can support, +    // possibly enable compression if we find an encoding we can handle. +    void +    MaybeEnableCompression (std::vector<std::string> supported_compressions); +      bool      DecodeProcessInfoResponse (StringExtractorGDBRemote &response,                                  ProcessInstanceInfo &process_info); +  private: -    //------------------------------------------------------------------ -    // For GDBRemoteCommunicationClient only -    //------------------------------------------------------------------      DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunicationClient);  };  } // namespace process_gdb_remote  } // namespace lldb_private -#endif  // liblldb_GDBRemoteCommunicationClient_h_ +#endif // liblldb_GDBRemoteCommunicationClient_h_ diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h index 44c0f6a32f5b7..1d512bf1de595 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h @@ -39,8 +39,7 @@ public:      GDBRemoteCommunicationServer(const char *comm_name,                                   const char *listener_name); -    virtual -    ~GDBRemoteCommunicationServer(); +    ~GDBRemoteCommunicationServer() override;      void RegisterPacketHandler(StringExtractorGDBRemote::ServerPacketType packet_type,                                 PacketHandler handler); @@ -73,13 +72,10 @@ protected:      SendOKResponse ();  private: -    //------------------------------------------------------------------ -    // For GDBRemoteCommunicationServer only -    //------------------------------------------------------------------      DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunicationServer);  };  } // namespace process_gdb_remote  } // namespace lldb_private -#endif  // liblldb_GDBRemoteCommunicationServer_h_ +#endif // liblldb_GDBRemoteCommunicationServer_h_ diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp index 698854e5dfbd7..7f876fb393d9d 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp @@ -58,8 +58,6 @@ using namespace lldb_private::process_gdb_remote;  //----------------------------------------------------------------------  GDBRemoteCommunicationServerCommon::GDBRemoteCommunicationServerCommon(const char *comm_name, const char *listener_name) :      GDBRemoteCommunicationServer (comm_name, listener_name), -    m_spawned_pids (), -    m_spawned_pids_mutex (Mutex::eMutexTypeRecursive),      m_process_launch_info (),      m_process_launch_error (),      m_proc_infos (), @@ -79,8 +77,6 @@ GDBRemoteCommunicationServerCommon::GDBRemoteCommunicationServerCommon(const cha                                    &GDBRemoteCommunicationServerCommon::Handle_qGroupName);      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qHostInfo,                                    &GDBRemoteCommunicationServerCommon::Handle_qHostInfo); -    RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess, -                                  &GDBRemoteCommunicationServerCommon::Handle_qKillSpawnedProcess);      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QLaunchArch,                                    &GDBRemoteCommunicationServerCommon::Handle_QLaunchArch);      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess, @@ -185,14 +181,20 @@ GDBRemoteCommunicationServerCommon::Handle_qHostInfo (StringExtractorGDBRemote &      else          response.Printf("watchpoint_exceptions_received:after;");  #else -    if (host_arch.GetMachine() == llvm::Triple::mips64 || -        host_arch.GetMachine() == llvm::Triple::mips64el) +    if (host_arch.GetMachine() == llvm::Triple::aarch64 || +        host_arch.GetMachine() == llvm::Triple::aarch64_be || +        host_arch.GetMachine() == llvm::Triple::arm || +        host_arch.GetMachine() == llvm::Triple::armeb || +        host_arch.GetMachine() == llvm::Triple::mips64 || +        host_arch.GetMachine() == llvm::Triple::mips64el || +        host_arch.GetMachine() == llvm::Triple::mips || +        host_arch.GetMachine() == llvm::Triple::mipsel)          response.Printf("watchpoint_exceptions_received:before;");      else          response.Printf("watchpoint_exceptions_received:after;");  #endif -    switch (lldb::endian::InlHostByteOrder()) +    switch (endian::InlHostByteOrder())      {      case eByteOrderBig:     response.PutCString ("endian:big;"); break;      case eByteOrderLittle:  response.PutCString ("endian:little;"); break; @@ -485,94 +487,6 @@ GDBRemoteCommunicationServerCommon::Handle_qSpeedTest (StringExtractorGDBRemote  }  GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerCommon::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet) -{ -    packet.SetFilePos(::strlen ("qKillSpawnedProcess:")); - -    lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID); - -    // verify that we know anything about this pid. -    // Scope for locker -    { -        Mutex::Locker locker (m_spawned_pids_mutex); -        if (m_spawned_pids.find(pid) == m_spawned_pids.end()) -        { -            // not a pid we know about -            return SendErrorResponse (10); -        } -    } - -    // go ahead and attempt to kill the spawned process -    if (KillSpawnedProcess (pid)) -        return SendOKResponse (); -    else -        return SendErrorResponse (11); -} - -bool -GDBRemoteCommunicationServerCommon::KillSpawnedProcess (lldb::pid_t pid) -{ -    // make sure we know about this process -    { -        Mutex::Locker locker (m_spawned_pids_mutex); -        if (m_spawned_pids.find(pid) == m_spawned_pids.end()) -            return false; -    } - -    // first try a SIGTERM (standard kill) -    Host::Kill (pid, SIGTERM); - -    // check if that worked -    for (size_t i=0; i<10; ++i) -    { -        { -            Mutex::Locker locker (m_spawned_pids_mutex); -            if (m_spawned_pids.find(pid) == m_spawned_pids.end()) -            { -                // it is now killed -                return true; -            } -        } -        usleep (10000); -    } - -    // check one more time after the final usleep -    { -        Mutex::Locker locker (m_spawned_pids_mutex); -        if (m_spawned_pids.find(pid) == m_spawned_pids.end()) -            return true; -    } - -    // the launched process still lives.  Now try killing it again, -    // this time with an unblockable signal. -    Host::Kill (pid, SIGKILL); - -    for (size_t i=0; i<10; ++i) -    { -        { -            Mutex::Locker locker (m_spawned_pids_mutex); -            if (m_spawned_pids.find(pid) == m_spawned_pids.end()) -            { -                // it is now killed -                return true; -            } -        } -        usleep (10000); -    } - -    // check one more time after the final usleep -    // Scope for locker -    { -        Mutex::Locker locker (m_spawned_pids_mutex); -        if (m_spawned_pids.find(pid) == m_spawned_pids.end()) -            return true; -    } - -    // no luck - the process still lives -    return false; -} - -GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServerCommon::Handle_vFile_Open (StringExtractorGDBRemote &packet)  {      packet.SetFilePos(::strlen("vFile:open:")); @@ -1299,6 +1213,7 @@ GDBRemoteCommunicationServerCommon::CreateProcessInfoResponse_DebugServerStyle (              switch (proc_triple.getArch ())              {                  case llvm::Triple::arm: +                case llvm::Triple::thumb:                  case llvm::Triple::aarch64:                      ostype = "ios";                      break; diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h index 62b129bb18b9a..f55b2eb3f4dc7 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h @@ -12,14 +12,14 @@  // C Includes  // C++ Includes -#include <set> +#include <string>  // Other libraries and framework includes +// Project includes  #include "lldb/lldb-private-forward.h"  #include "lldb/Host/Mutex.h"  #include "lldb/Target/Process.h" -// Project includes  #include "GDBRemoteCommunicationServer.h"  #include "GDBRemoteCommunicationServerCommon.h" @@ -36,12 +36,9 @@ class GDBRemoteCommunicationServerCommon :  public:      GDBRemoteCommunicationServerCommon(const char *comm_name, const char *listener_name); -    virtual -    ~GDBRemoteCommunicationServerCommon(); +    ~GDBRemoteCommunicationServerCommon() override;  protected: -    std::set<lldb::pid_t> m_spawned_pids; -    Mutex m_spawned_pids_mutex;      ProcessLaunchInfo m_process_launch_info;      Error m_process_launch_error;      ProcessInstanceInfoList m_proc_infos; @@ -74,9 +71,6 @@ protected:      Handle_qSpeedTest (StringExtractorGDBRemote &packet);      PacketResult -    Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet); - -    PacketResult      Handle_vFile_Open (StringExtractorGDBRemote &packet);      PacketResult @@ -160,9 +154,6 @@ protected:      PacketResult      Handle_QLaunchArch (StringExtractorGDBRemote &packet); -    bool -    KillSpawnedProcess (lldb::pid_t pid); -      static void      CreateProcessInfoResponse (const ProcessInstanceInfo &proc_info,                                 StreamString &response); @@ -213,4 +204,4 @@ protected:  } // namespace process_gdb_remote  } // namespace lldb_private -#endif  // liblldb_GDBRemoteCommunicationServerCommon_h_ +#endif // liblldb_GDBRemoteCommunicationServerCommon_h_ diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index c4523252f1908..921369c7ef21c 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -43,6 +43,8 @@  #include "lldb/Host/common/NativeRegisterContext.h"  #include "lldb/Host/common/NativeProcessProtocol.h"  #include "lldb/Host/common/NativeThreadProtocol.h" +#include "lldb/Utility/JSON.h" +#include "lldb/Utility/LLDBAssert.h"  // Project includes  #include "Utility/StringExtractorGDBRemote.h" @@ -96,20 +98,6 @@ GDBRemoteCommunicationServerLLGS::GDBRemoteCommunicationServerLLGS(      RegisterPacketHandlers();  } -//---------------------------------------------------------------------- -// Destructor -//---------------------------------------------------------------------- -GDBRemoteCommunicationServerLLGS::~GDBRemoteCommunicationServerLLGS() -{ -    Mutex::Locker locker (m_debugged_process_mutex); - -    if (m_debugged_process_sp) -    { -        m_debugged_process_sp->Terminate (); -        m_debugged_process_sp.reset (); -    } -} -  void  GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers()  { @@ -126,7 +114,7 @@ GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers()      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_interrupt,                                    &GDBRemoteCommunicationServerLLGS::Handle_interrupt);      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_m, -                                  &GDBRemoteCommunicationServerLLGS::Handle_m); +                                  &GDBRemoteCommunicationServerLLGS::Handle_memory_read);      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_M,                                    &GDBRemoteCommunicationServerLLGS::Handle_M);      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_p, @@ -161,6 +149,8 @@ GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers()                                    &GDBRemoteCommunicationServerLLGS::Handle_qsThreadInfo);      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qThreadStopInfo,                                    &GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo); +    RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_jThreadsInfo, +                                  &GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo);      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qWatchpointSupportInfo,                                    &GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo);      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qXfer_auxv_read, @@ -175,6 +165,8 @@ GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers()                                    &GDBRemoteCommunicationServerLLGS::Handle_vCont);      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vCont_actions,                                    &GDBRemoteCommunicationServerLLGS::Handle_vCont_actions); +    RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_x, +                                  &GDBRemoteCommunicationServerLLGS::Handle_memory_read);      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_Z,                                    &GDBRemoteCommunicationServerLLGS::Handle_Z);      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_z, @@ -223,6 +215,7 @@ GDBRemoteCommunicationServerLLGS::LaunchProcess ()          error = NativeProcessProtocol::Launch(              m_process_launch_info,              *this, +            m_mainloop,              m_debugged_process_sp);      } @@ -274,17 +267,6 @@ GDBRemoteCommunicationServerLLGS::LaunchProcess ()      printf ("Launched '%s' as process %" PRIu64 "...\n", m_process_launch_info.GetArguments ().GetArgumentAtIndex (0), m_process_launch_info.GetProcessID ()); -    // Add to list of spawned processes. -    lldb::pid_t pid; -    if ((pid = m_process_launch_info.GetProcessID ()) != LLDB_INVALID_PROCESS_ID) -    { -        // add to spawned pids -        Mutex::Locker locker (m_spawned_pids_mutex); -        // On an lldb-gdbserver, we would expect there to be only one. -        assert (m_spawned_pids.empty () && "lldb-gdbserver adding tracked process but one already existed"); -        m_spawned_pids.insert (pid); -    } -      return error;  } @@ -297,48 +279,37 @@ GDBRemoteCommunicationServerLLGS::AttachToProcess (lldb::pid_t pid)      if (log)          log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64, __FUNCTION__, pid); -    // Scope for mutex locker. +    // Before we try to attach, make sure we aren't already monitoring something else. +    if (m_debugged_process_sp  && m_debugged_process_sp->GetID() != LLDB_INVALID_PROCESS_ID) +        return Error("cannot attach to a process %" PRIu64 " when another process with pid %" PRIu64 " is being debugged.", pid, m_debugged_process_sp->GetID()); + +    // Try to attach. +    error = NativeProcessProtocol::Attach(pid, *this, m_mainloop, m_debugged_process_sp); +    if (!error.Success ())      { -        // Before we try to attach, make sure we aren't already monitoring something else. -        Mutex::Locker locker (m_spawned_pids_mutex); -        if (!m_spawned_pids.empty ()) -        { -            error.SetErrorStringWithFormat ("cannot attach to a process %" PRIu64 " when another process with pid %" PRIu64 " is being debugged.", pid, *m_spawned_pids.begin()); -            return error; -        } +        fprintf (stderr, "%s: failed to attach to process %" PRIu64 ": %s", __FUNCTION__, pid, error.AsCString ()); +        return error; +    } -        // Try to attach. -        error = NativeProcessProtocol::Attach(pid, *this, m_debugged_process_sp); -        if (!error.Success ()) -        { -            fprintf (stderr, "%s: failed to attach to process %" PRIu64 ": %s", __FUNCTION__, pid, error.AsCString ()); +    // Setup stdout/stderr mapping from inferior. +    auto terminal_fd = m_debugged_process_sp->GetTerminalFileDescriptor (); +    if (terminal_fd >= 0) +    { +        if (log) +            log->Printf ("ProcessGDBRemoteCommunicationServerLLGS::%s setting inferior STDIO fd to %d", __FUNCTION__, terminal_fd); +        error = SetSTDIOFileDescriptor (terminal_fd); +        if (error.Fail ())              return error; -        } - -        // Setup stdout/stderr mapping from inferior. -        auto terminal_fd = m_debugged_process_sp->GetTerminalFileDescriptor (); -        if (terminal_fd >= 0) -        { -            if (log) -                log->Printf ("ProcessGDBRemoteCommunicationServerLLGS::%s setting inferior STDIO fd to %d", __FUNCTION__, terminal_fd); -            error = SetSTDIOFileDescriptor (terminal_fd); -            if (error.Fail ()) -                return error; -        } -        else -        { -            if (log) -                log->Printf ("ProcessGDBRemoteCommunicationServerLLGS::%s ignoring inferior STDIO since terminal fd reported as %d", __FUNCTION__, terminal_fd); -        } - -        printf ("Attached to process %" PRIu64 "...\n", pid); +    } +    else +    { +        if (log) +            log->Printf ("ProcessGDBRemoteCommunicationServerLLGS::%s ignoring inferior STDIO since terminal fd reported as %d", __FUNCTION__, terminal_fd); +    } -        // Add to list of spawned processes. -        assert (m_spawned_pids.empty () && "lldb-gdbserver adding tracked process but one already existed"); -        m_spawned_pids.insert (pid); +    printf ("Attached to process %" PRIu64 "...\n", pid); -        return error; -    } +    return error;  }  void @@ -455,6 +426,178 @@ WriteRegisterValueInHexFixedWidth (StreamString &response,      }  } +static JSONObject::SP +GetRegistersAsJSON(NativeThreadProtocol &thread, bool abridged) +{ +    Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_THREAD)); + +    NativeRegisterContextSP reg_ctx_sp = thread.GetRegisterContext (); +    if (! reg_ctx_sp) +        return nullptr; + +    JSONObject::SP register_object_sp = std::make_shared<JSONObject>(); + +#ifdef LLDB_JTHREADSINFO_FULL_REGISTER_SET +    // Expedite all registers in the first register set (i.e. should be GPRs) that are not contained in other registers. +    const RegisterSet *reg_set_p = reg_ctx_sp->GetRegisterSet(0); +    if (! reg_set_p) +        return nullptr; +    for (const uint32_t *reg_num_p = reg_set_p->registers; *reg_num_p != LLDB_INVALID_REGNUM; ++reg_num_p) +    { +        uint32_t reg_num = *reg_num_p; +#else +    // Expedite only a couple of registers until we figure out why sending registers is +    // expensive. +    static const uint32_t k_expedited_registers[] = { +        LLDB_REGNUM_GENERIC_PC, LLDB_REGNUM_GENERIC_SP, LLDB_REGNUM_GENERIC_FP, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM +    }; +    static const uint32_t k_abridged_expedited_registers[] = { +        LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM +    }; + +    for (const uint32_t *generic_reg_p = abridged ? k_abridged_expedited_registers : k_expedited_registers; +         *generic_reg_p != LLDB_INVALID_REGNUM; +         ++generic_reg_p) +    { +        uint32_t reg_num = reg_ctx_sp->ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, *generic_reg_p); +        if (reg_num == LLDB_INVALID_REGNUM) +            continue; // Target does not support the given register. +#endif + +        const RegisterInfo *const reg_info_p = reg_ctx_sp->GetRegisterInfoAtIndex(reg_num); +        if (reg_info_p == nullptr) +        { +            if (log) +                log->Printf("%s failed to get register info for register index %" PRIu32, +                        __FUNCTION__, reg_num); +            continue; +        } + +        if (reg_info_p->value_regs != nullptr) +            continue; // Only expedite registers that are not contained in other registers. + +        RegisterValue reg_value; +        Error error = reg_ctx_sp->ReadRegister(reg_info_p, reg_value); +        if (error.Fail()) +        { +            if (log) +                log->Printf("%s failed to read register '%s' index %" PRIu32 ": %s", __FUNCTION__, +                        reg_info_p->name ? reg_info_p->name : "<unnamed-register>", reg_num, +                        error.AsCString ()); +            continue; +        } + +        StreamString stream; +        WriteRegisterValueInHexFixedWidth(stream, reg_ctx_sp, *reg_info_p, ®_value); + +        register_object_sp->SetObject(std::to_string(reg_num), +                std::make_shared<JSONString>(stream.GetString())); +    } + +    return register_object_sp; +} + +static const char * +GetStopReasonString(StopReason stop_reason) +{ +    switch (stop_reason) +    { +    case eStopReasonTrace: +        return "trace"; +    case eStopReasonBreakpoint: +        return "breakpoint"; +    case eStopReasonWatchpoint: +        return "watchpoint"; +    case eStopReasonSignal: +        return "signal"; +    case eStopReasonException: +        return "exception"; +    case eStopReasonExec: +        return "exec"; +    case eStopReasonInstrumentation: +    case eStopReasonInvalid: +    case eStopReasonPlanComplete: +    case eStopReasonThreadExiting: +    case eStopReasonNone: +        break; // ignored +    } +    return nullptr; +} + +static JSONArray::SP +GetJSONThreadsInfo(NativeProcessProtocol &process, bool abridged) +{ +    Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); + +    JSONArray::SP threads_array_sp = std::make_shared<JSONArray>(); + +    // Ensure we can get info on the given thread. +    uint32_t thread_idx = 0; +    for ( NativeThreadProtocolSP thread_sp; +          (thread_sp = process.GetThreadAtIndex(thread_idx)) != nullptr; +          ++thread_idx) +    { + +        lldb::tid_t tid = thread_sp->GetID(); + +        // Grab the reason this thread stopped. +        struct ThreadStopInfo tid_stop_info; +        std::string description; +        if (!thread_sp->GetStopReason (tid_stop_info, description)) +            return nullptr; + +        const int signum = tid_stop_info.details.signal.signo; +        if (log) +        { +            log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 " got signal signo = %d, reason = %d, exc_type = %" PRIu64, +                    __FUNCTION__, +                    process.GetID (), +                    tid, +                    signum, +                    tid_stop_info.reason, +                    tid_stop_info.details.exception.type); +        } + +        JSONObject::SP thread_obj_sp = std::make_shared<JSONObject>(); +        threads_array_sp->AppendObject(thread_obj_sp); + +        if (JSONObject::SP registers_sp = GetRegistersAsJSON(*thread_sp, abridged)) +            thread_obj_sp->SetObject("registers", registers_sp); + +        thread_obj_sp->SetObject("tid", std::make_shared<JSONNumber>(tid)); +        if (signum != 0) +            thread_obj_sp->SetObject("signal", std::make_shared<JSONNumber>(signum)); + +        const std::string thread_name = thread_sp->GetName (); +        if (! thread_name.empty()) +            thread_obj_sp->SetObject("name", std::make_shared<JSONString>(thread_name)); + +        if (const char *stop_reason_str = GetStopReasonString(tid_stop_info.reason)) +            thread_obj_sp->SetObject("reason", std::make_shared<JSONString>(stop_reason_str)); + +        if (! description.empty()) +            thread_obj_sp->SetObject("description", std::make_shared<JSONString>(description)); + +        if ((tid_stop_info.reason == eStopReasonException) && tid_stop_info.details.exception.type) +        { +            thread_obj_sp->SetObject("metype", +                    std::make_shared<JSONNumber>(tid_stop_info.details.exception.type)); + +            JSONArray::SP medata_array_sp = std::make_shared<JSONArray>(); +            for (uint32_t i = 0; i < tid_stop_info.details.exception.data_count; ++i) +            { +                medata_array_sp->AppendObject(std::make_shared<JSONNumber>( +                            tid_stop_info.details.exception.data[i])); +            } +            thread_obj_sp->SetObject("medata", medata_array_sp); +        } + +        // TODO: Expedite interesting regions of inferior memory +    } + +    return threads_array_sp; +} +  GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread (lldb::tid_t tid)  { @@ -548,6 +691,31 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread (lldb::tid_t tid)              response.Printf ("%" PRIx64, listed_thread_sp->GetID ());          }          response.PutChar (';'); + +        // Include JSON info that describes the stop reason for any threads +        // that actually have stop reasons. We use the new "jstopinfo" key +        // whose values is hex ascii JSON that contains the thread IDs +        // thread stop info only for threads that have stop reasons. Only send +        // this if we have more than one thread otherwise this packet has all +        // the info it needs. +        if (thread_index > 0) +        { +            const bool threads_with_valid_stop_info_only = true; +            JSONArray::SP threads_info_sp = GetJSONThreadsInfo(*m_debugged_process_sp, +                                                               threads_with_valid_stop_info_only); +            if (threads_info_sp) +            { +                response.PutCString("jstopinfo:"); +                StreamString unescaped_response; +                threads_info_sp->Write(unescaped_response); +                response.PutCStringAsRawHex8(unescaped_response.GetData()); +                response.PutChar(';'); +            } +            else if (log) +                log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to prepare a jstopinfo field for pid %" PRIu64, +                        __FUNCTION__, m_debugged_process_sp->GetID()); + +        }      }      // @@ -595,34 +763,7 @@ GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread (lldb::tid_t tid)          }      } -    const char* reason_str = nullptr; -    switch (tid_stop_info.reason) -    { -    case eStopReasonTrace: -        reason_str = "trace"; -        break; -    case eStopReasonBreakpoint: -        reason_str = "breakpoint"; -        break; -    case eStopReasonWatchpoint: -        reason_str = "watchpoint"; -        break; -    case eStopReasonSignal: -        reason_str = "signal"; -        break; -    case eStopReasonException: -        reason_str = "exception"; -        break; -    case eStopReasonExec: -        reason_str = "exec"; -        break; -    case eStopReasonInstrumentation: -    case eStopReasonInvalid: -    case eStopReasonPlanComplete: -    case eStopReasonThreadExiting: -    case eStopReasonNone: -        break; -    } +    const char* reason_str = GetStopReasonString(tid_stop_info.reason);      if (reason_str != nullptr)      {          response.Printf ("reason:%s;", reason_str); @@ -663,43 +804,15 @@ GDBRemoteCommunicationServerLLGS::HandleInferiorState_Exited (NativeProcessProto      if (log)          log->Printf ("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); -    // Send the exit result, and don't flush output. -    // Note: flushing output here would join the inferior stdio reflection thread, which -    // would gunk up the waitpid monitor thread that is calling this. -    PacketResult result = SendStopReasonForState (StateType::eStateExited, false); +    PacketResult result = SendStopReasonForState(StateType::eStateExited);      if (result != PacketResult::Success)      {          if (log)              log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to send stop notification for PID %" PRIu64 ", state: eStateExited", __FUNCTION__, process->GetID ());      } -    // Remove the process from the list of spawned pids. -    { -        Mutex::Locker locker (m_spawned_pids_mutex); -        if (m_spawned_pids.erase (process->GetID ()) < 1) -        { -            if (log) -                log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to remove PID %" PRIu64 " from the spawned pids list", __FUNCTION__, process->GetID ()); - -        } -    } - -    // FIXME can't do this yet - since process state propagation is currently -    // synchronous, it is running off the NativeProcessProtocol's innards and -    // will tear down the NPP while it still has code to execute. -#if 0 -    // Clear the NativeProcessProtocol pointer. -    { -        Mutex::Locker locker (m_debugged_process_mutex); -        m_debugged_process_sp.reset(); -    } -#endif -      // Close the pipe to the inferior terminal i/o if we launched it -    // and set one up.  Otherwise, 'k' and its flush of stdio could -    // end up waiting on a thread join that will never end.  Consider -    // adding a timeout to the connection thread join call so we -    // can avoid that scenario altogether. +    // and set one up.      MaybeCloseInferiorTerminalConnection ();      // We are ready to exit the debug monitor. @@ -725,7 +838,7 @@ GDBRemoteCommunicationServerLLGS::HandleInferiorState_Stopped (NativeProcessProt              break;          default:              // In all other cases, send the stop reason. -            PacketResult result = SendStopReasonForState (StateType::eStateStopped, false); +            PacketResult result = SendStopReasonForState(StateType::eStateStopped);              if (result != PacketResult::Success)              {                  if (log) @@ -748,21 +861,30 @@ GDBRemoteCommunicationServerLLGS::ProcessStateChanged (NativeProcessProtocol *pr                  StateAsCString (state));      } -    // Make sure we get all of the pending stdout/stderr from the inferior -    // and send it to the lldb host before we send the state change -    // notification -    m_stdio_communication.SynchronizeWithReadThread(); -      switch (state)      { -    case StateType::eStateExited: -        HandleInferiorState_Exited (process); +    case StateType::eStateRunning: +        StartSTDIOForwarding();          break;      case StateType::eStateStopped: +        // Make sure we get all of the pending stdout/stderr from the inferior +        // and send it to the lldb host before we send the state change +        // notification +        SendProcessOutput(); +        // Then stop the forwarding, so that any late output (see llvm.org/pr25652) does not +        // interfere with our protocol. +        StopSTDIOForwarding();          HandleInferiorState_Stopped (process);          break; +    case StateType::eStateExited: +        // Same as above +        SendProcessOutput(); +        StopSTDIOForwarding(); +        HandleInferiorState_Exited (process); +        break; +      default:          if (log)          { @@ -796,7 +918,6 @@ GDBRemoteCommunicationServerLLGS::DataAvailableCallback ()              if(log)                  log->Printf("GDBRemoteCommunicationServerLLGS::%s handshake with client failed, exiting",                          __FUNCTION__); -            m_read_handle_up.reset();              m_mainloop.RequestTermination();              return;          } @@ -817,7 +938,6 @@ GDBRemoteCommunicationServerLLGS::DataAvailableCallback ()              if(log)                  log->Printf("GDBRemoteCommunicationServerLLGS::%s processing a packet failed: %s",                          __FUNCTION__, error.AsCString()); -            m_read_handle_up.reset();              m_mainloop.RequestTermination();              break;          } @@ -831,7 +951,7 @@ GDBRemoteCommunicationServerLLGS::InitializeConnection (std::unique_ptr<Connecti      GDBRemoteCommunicationServer::SetConnection(connection.release());      Error error; -    m_read_handle_up = m_mainloop.RegisterReadObject(read_object_sp, +    m_network_handle_up = m_mainloop.RegisterReadObject(read_object_sp,              [this] (MainLoopBase &) { DataAvailableCallback(); }, error);      return error;  } @@ -857,7 +977,7 @@ GDBRemoteCommunicationServerLLGS::SetSTDIOFileDescriptor (int fd)  {      Error error; -    // Set up the Read Thread for reading/handling process I/O +    // Set up the reading/handling of process I/O      std::unique_ptr<ConnectionFileDescriptor> conn_up (new ConnectionFileDescriptor (fd, true));      if (!conn_up)      { @@ -873,29 +993,73 @@ GDBRemoteCommunicationServerLLGS::SetSTDIOFileDescriptor (int fd)          return error;      } +    return Error(); +} + +void +GDBRemoteCommunicationServerLLGS::StartSTDIOForwarding() +{ +    // Don't forward if not connected (e.g. when attaching). +    if (! m_stdio_communication.IsConnected()) +        return; +      // llgs local-process debugging may specify PTY paths, which will make these      // file actions non-null      // process launch -e/o will also make these file actions non-null      // nullptr means that the traffic is expected to flow over gdb-remote protocol -    if ( -        m_process_launch_info.GetFileActionForFD(STDOUT_FILENO) == nullptr || -        m_process_launch_info.GetFileActionForFD(STDERR_FILENO) == nullptr -        ) +    if ( m_process_launch_info.GetFileActionForFD(STDOUT_FILENO) && +         m_process_launch_info.GetFileActionForFD(STDERR_FILENO)) +        return; + +    Error error; +    lldbassert(! m_stdio_handle_up); +    m_stdio_handle_up = m_mainloop.RegisterReadObject( +            m_stdio_communication.GetConnection()->GetReadObject(), +            [this] (MainLoopBase &) { SendProcessOutput(); }, error); + +    if (! m_stdio_handle_up)      { -        // output from the process must be forwarded over gdb-remote -        // create a thread to read the handle and send the data -        m_stdio_communication.SetReadThreadBytesReceivedCallback (STDIOReadThreadBytesReceived, this); -        m_stdio_communication.StartReadThread(); +        // Not much we can do about the failure. Log it and continue without forwarding. +        if (Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)) +            log->Printf("GDBRemoteCommunicationServerLLGS::%s Failed to set up stdio forwarding: %s", +                        __FUNCTION__, error.AsCString());      } +} -    return error; +void +GDBRemoteCommunicationServerLLGS::StopSTDIOForwarding() +{ +    m_stdio_handle_up.reset();  }  void -GDBRemoteCommunicationServerLLGS::STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_len) +GDBRemoteCommunicationServerLLGS::SendProcessOutput()  { -    GDBRemoteCommunicationServerLLGS *server = reinterpret_cast<GDBRemoteCommunicationServerLLGS*> (baton); -    static_cast<void> (server->SendONotification (static_cast<const char *>(src), src_len)); +    char buffer[1024]; +    ConnectionStatus status; +    Error error; +    while (true) +    { +        size_t bytes_read = m_stdio_communication.Read(buffer, sizeof buffer, 0, status, &error); +        switch (status) +        { +        case eConnectionStatusSuccess: +            SendONotification(buffer, bytes_read); +            break; +        case eConnectionStatusLostConnection: +        case eConnectionStatusEndOfFile: +        case eConnectionStatusError: +        case eConnectionStatusNoConnection: +            if (Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)) +                log->Printf("GDBRemoteCommunicationServerLLGS::%s Stopping stdio forwarding as communication returned status %d (error: %s)", __FUNCTION__, status, error.AsCString()); +            m_stdio_handle_up.reset(); +            return; + +        case eConnectionStatusInterrupted: +        case eConnectionStatusTimedOut: +            return; +        } +    }  }  GDBRemoteCommunication::PacketResult @@ -941,49 +1105,24 @@ GDBRemoteCommunicationServerLLGS::Handle_qC (StringExtractorGDBRemote &packet)      return SendPacketNoLock (response.GetData(), response.GetSize());  } -bool -GDBRemoteCommunicationServerLLGS::DebuggedProcessReaped (lldb::pid_t pid) -{ -    // reap a process that we were debugging (but not debugserver) -    Mutex::Locker locker (m_spawned_pids_mutex); -    return m_spawned_pids.erase(pid) > 0; -} - -bool -GDBRemoteCommunicationServerLLGS::ReapDebuggedProcess (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 -{ -    GDBRemoteCommunicationServerLLGS *server = (GDBRemoteCommunicationServerLLGS *)callback_baton; -    server->DebuggedProcessReaped (pid); -    return true; -} -  GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServerLLGS::Handle_k (StringExtractorGDBRemote &packet)  { -    // shutdown all spawned processes -    std::set<lldb::pid_t> spawned_pids_copy; +    Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); -    // copy pids -    { -        Mutex::Locker locker (m_spawned_pids_mutex); -        spawned_pids_copy.insert (m_spawned_pids.begin (), m_spawned_pids.end ()); -    } +    StopSTDIOForwarding(); -    // nuke the spawned processes -    for (auto it = spawned_pids_copy.begin (); it != spawned_pids_copy.end (); ++it) +    if (! m_debugged_process_sp)      { -        lldb::pid_t spawned_pid = *it; -        if (!KillSpawnedProcess (spawned_pid)) -        { -            fprintf (stderr, "%s: failed to kill spawned pid %" PRIu64 ", ignoring.\n", __FUNCTION__, spawned_pid); -        } +        if (log) +            log->Printf("GDBRemoteCommunicationServerLLGS::%s No debugged process found.", __FUNCTION__); +        return PacketResult::Success;      } -    FlushInferiorOutput (); +    Error error = m_debugged_process_sp->Kill(); +    if (error.Fail() && log) +        log->Printf("GDBRemoteCommunicationServerLLGS::%s Failed to kill debugged process %" PRIu64 ": %s", +                __FUNCTION__, m_debugged_process_sp->GetID(), error.AsCString());      // No OK response for kill packet.      // return SendOKResponse (); @@ -1316,11 +1455,11 @@ GDBRemoteCommunicationServerLLGS::Handle_stop_reason (StringExtractorGDBRemote &      if (!m_debugged_process_sp)          return SendErrorResponse (02); -    return SendStopReasonForState (m_debugged_process_sp->GetState (), true); +    return SendStopReasonForState (m_debugged_process_sp->GetState());  }  GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::SendStopReasonForState (lldb::StateType process_state, bool flush_on_exit) +GDBRemoteCommunicationServerLLGS::SendStopReasonForState (lldb::StateType process_state)  {      Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); @@ -1349,8 +1488,6 @@ GDBRemoteCommunicationServerLLGS::SendStopReasonForState (lldb::StateType proces          case eStateInvalid:          case eStateUnloaded:          case eStateExited: -            if (flush_on_exit) -                FlushInferiorOutput ();              return SendWResponse(m_debugged_process_sp.get());          default: @@ -1448,8 +1585,8 @@ GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo (StringExtractorGDBRemote          response.PutChar (';');      } -    if (reg_info->kinds[RegisterKind::eRegisterKindGCC] != LLDB_INVALID_REGNUM) -        response.Printf ("gcc:%" PRIu32 ";", reg_info->kinds[RegisterKind::eRegisterKindGCC]); +    if (reg_info->kinds[RegisterKind::eRegisterKindEHFrame] != LLDB_INVALID_REGNUM) +        response.Printf ("ehframe:%" PRIu32 ";", reg_info->kinds[RegisterKind::eRegisterKindEHFrame]);      if (reg_info->kinds[RegisterKind::eRegisterKindDWARF] != LLDB_INVALID_REGNUM)          response.Printf ("dwarf:%" PRIu32 ";", reg_info->kinds[RegisterKind::eRegisterKindDWARF]); @@ -1856,7 +1993,7 @@ GDBRemoteCommunicationServerLLGS::Handle_interrupt (StringExtractorGDBRemote &pa  }  GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_m (StringExtractorGDBRemote &packet) +GDBRemoteCommunicationServerLLGS::Handle_memory_read(StringExtractorGDBRemote &packet)  {      Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); @@ -1889,7 +2026,7 @@ GDBRemoteCommunicationServerLLGS::Handle_m (StringExtractorGDBRemote &packet)      {          if (log)              log->Printf ("GDBRemoteCommunicationServerLLGS::%s nothing to read: zero-length packet", __FUNCTION__); -        return PacketResult::Success; +        return SendOKResponse();      }      // Allocate the response buffer. @@ -1916,8 +2053,16 @@ GDBRemoteCommunicationServerLLGS::Handle_m (StringExtractorGDBRemote &packet)      }      StreamGDBRemote response; -    for (size_t i = 0; i < bytes_read; ++i) -        response.PutHex8(buf[i]); +    packet.SetFilePos(0); +    char kind = packet.GetChar('?'); +    if (kind == 'x') +        response.PutEscapedBytes(buf.data(), byte_count); +    else +    { +        assert(kind == 'm'); +        for (size_t i = 0; i < bytes_read; ++i) +            response.PutHex8(buf[i]); +    }      return SendPacketNoLock(response.GetData(), response.GetSize());  } @@ -2108,6 +2253,7 @@ GDBRemoteCommunicationServerLLGS::Handle_Z (StringExtractorGDBRemote &packet)      bool want_breakpoint = true;      bool want_hardware = false; +    uint32_t watch_flags = 0;      const GDBStoppointType stoppoint_type =          GDBStoppointType(packet.GetS32 (eStoppointInvalid)); @@ -2118,10 +2264,13 @@ GDBRemoteCommunicationServerLLGS::Handle_Z (StringExtractorGDBRemote &packet)          case eBreakpointHardware:              want_hardware = true;  want_breakpoint = true;  break;          case eWatchpointWrite: +            watch_flags = 1;              want_hardware = true;  want_breakpoint = false; break;          case eWatchpointRead: +            watch_flags = 2;              want_hardware = true;  want_breakpoint = false; break;          case eWatchpointReadWrite: +            watch_flags = 3;              want_hardware = true;  want_breakpoint = false; break;          case eStoppointInvalid:              return SendIllFormedResponse(packet, "Z packet had invalid software/hardware specifier"); @@ -2161,11 +2310,6 @@ GDBRemoteCommunicationServerLLGS::Handle_Z (StringExtractorGDBRemote &packet)      }      else      { -        uint32_t watch_flags = -            stoppoint_type == eWatchpointWrite -            ? 0x1  // Write -            : 0x3; // ReadWrite -          // Try to set the watchpoint.          const Error error = m_debugged_process_sp->SetWatchpoint (                  addr, size, watch_flags, want_hardware); @@ -2555,7 +2699,7 @@ GDBRemoteCommunicationServerLLGS::Handle_vAttach (StringExtractorGDBRemote &pack      }      // Notify we attached by sending a stop packet. -    return SendStopReasonForState (m_debugged_process_sp->GetState (), true); +    return SendStopReasonForState (m_debugged_process_sp->GetState ());  }  GDBRemoteCommunication::PacketResult @@ -2563,8 +2707,7 @@ GDBRemoteCommunicationServerLLGS::Handle_D (StringExtractorGDBRemote &packet)  {      Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS)); -    // Scope for mutex locker. -    Mutex::Locker locker (m_spawned_pids_mutex); +    StopSTDIOForwarding();      // Fail if we don't have a current process.      if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) @@ -2574,14 +2717,6 @@ GDBRemoteCommunicationServerLLGS::Handle_D (StringExtractorGDBRemote &packet)          return SendErrorResponse (0x15);      } -    if (m_spawned_pids.find(m_debugged_process_sp->GetID ()) == m_spawned_pids.end()) -    { -        if (log) -            log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to find PID %" PRIu64 " in spawned pids list", -                         __FUNCTION__, m_debugged_process_sp->GetID ()); -        return SendErrorResponse (0x1); -    } -      lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;      // Consume the ';' after D. @@ -2603,11 +2738,6 @@ GDBRemoteCommunicationServerLLGS::Handle_D (StringExtractorGDBRemote &packet)          return SendIllFormedResponse (packet, "Invalid pid");      } -    if (m_stdio_communication.IsConnected ()) -    { -        m_stdio_communication.StopReadThread (); -    } -      const Error error = m_debugged_process_sp->Detach ();      if (error.Fail ())      { @@ -2617,7 +2747,6 @@ GDBRemoteCommunicationServerLLGS::Handle_D (StringExtractorGDBRemote &packet)          return SendErrorResponse (0x01);      } -    m_spawned_pids.erase (m_debugged_process_sp->GetID ());      return SendOKResponse ();  } @@ -2638,6 +2767,38 @@ GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo (StringExtractorGDBRemo  }  GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo (StringExtractorGDBRemote &) +{ +    Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); + +    // Ensure we have a debugged process. +    if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)) +        return SendErrorResponse (50); + +    if (log) +        log->Printf ("GDBRemoteCommunicationServerLLGS::%s preparing packet for pid %" PRIu64, +                __FUNCTION__, m_debugged_process_sp->GetID()); + + +    StreamString response; +    const bool threads_with_valid_stop_info_only = false; +    JSONArray::SP threads_array_sp = GetJSONThreadsInfo(*m_debugged_process_sp, +                                                        threads_with_valid_stop_info_only); +    if (! threads_array_sp) +    { +        if (log) +            log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to prepare a packet for pid %" PRIu64, +                    __FUNCTION__, m_debugged_process_sp->GetID()); +        return SendErrorResponse(52); +    } + +    threads_array_sp->Write(response); +    StreamGDBRemote escaped_response; +    escaped_response.PutEscapedBytes(response.GetData(), response.GetSize()); +    return SendPacketNoLock (escaped_response.GetData(), escaped_response.GetSize()); +} + +GDBRemoteCommunication::PacketResult  GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo (StringExtractorGDBRemote &packet)  {      // Fail if we don't have a current process. @@ -2686,21 +2847,6 @@ GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress (StringExtractorGDBRem  }  void -GDBRemoteCommunicationServerLLGS::FlushInferiorOutput () -{ -    // If we're not monitoring an inferior's terminal, ignore this. -    if (!m_stdio_communication.IsConnected()) -        return; - -    Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD)); -    if (log) -        log->Printf ("GDBRemoteCommunicationServerLLGS::%s() called", __FUNCTION__); - -    // FIXME implement a timeout on the join. -    m_stdio_communication.JoinReadThread(); -} - -void  GDBRemoteCommunicationServerLLGS::MaybeCloseInferiorTerminalConnection ()  {      Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h index 29f3fdebcfb0c..f16057781ddc4 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h @@ -42,9 +42,6 @@ public:      //------------------------------------------------------------------      GDBRemoteCommunicationServerLLGS(const lldb::PlatformSP& platform_sp, MainLoop &mainloop); -    virtual -    ~GDBRemoteCommunicationServerLLGS(); -      //------------------------------------------------------------------      /// Specify the program to launch and its arguments.      /// @@ -119,12 +116,15 @@ public:  protected:      lldb::PlatformSP m_platform_sp;      MainLoop &m_mainloop; -    MainLoop::ReadHandleUP m_read_handle_up; +    MainLoop::ReadHandleUP m_network_handle_up;      lldb::tid_t m_current_tid;      lldb::tid_t m_continue_tid;      Mutex m_debugged_process_mutex;      NativeProcessProtocolSP m_debugged_process_sp; +      Communication m_stdio_communication; +    MainLoop::ReadHandleUP m_stdio_handle_up; +      lldb::StateType m_inferior_prev_state;      lldb::DataBufferSP m_active_auxv_buffer_sp;      Mutex m_saved_registers_mutex; @@ -142,7 +142,7 @@ protected:      SendStopReplyPacketForThread (lldb::tid_t tid);      PacketResult -    SendStopReasonForState (lldb::StateType process_state, bool flush_on_exit); +    SendStopReasonForState (lldb::StateType process_state);      PacketResult      Handle_k (StringExtractorGDBRemote &packet); @@ -201,8 +201,9 @@ protected:      PacketResult      Handle_interrupt (StringExtractorGDBRemote &packet); +    // Handles $m and $x packets.      PacketResult -    Handle_m (StringExtractorGDBRemote &packet); +    Handle_memory_read (StringExtractorGDBRemote &packet);      PacketResult      Handle_M (StringExtractorGDBRemote &packet); @@ -241,6 +242,9 @@ protected:      Handle_qThreadStopInfo (StringExtractorGDBRemote &packet);      PacketResult +    Handle_jThreadsInfo (StringExtractorGDBRemote &packet); + +    PacketResult      Handle_qWatchpointSupportInfo (StringExtractorGDBRemote &packet);      PacketResult @@ -261,32 +265,16 @@ protected:      Error      SetSTDIOFileDescriptor (int fd); -    static void -    STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_len); -      FileSpec      FindModuleFile (const std::string& module_path, const ArchSpec& arch) override;  private: -    bool -    DebuggedProcessReaped (lldb::pid_t pid); - -    static bool -    ReapDebuggedProcess (void *callback_baton, -                         lldb::pid_t pid, -                         bool exited, -                         int signal, -                         int status); -      void      HandleInferiorState_Exited (NativeProcessProtocol *process);      void      HandleInferiorState_Stopped (NativeProcessProtocol *process); -    void -    FlushInferiorOutput (); -      NativeThreadProtocolSP      GetThreadFromSuffix (StringExtractorGDBRemote &packet); @@ -305,6 +293,15 @@ private:      void      DataAvailableCallback (); +    void +    SendProcessOutput (); + +    void +    StartSTDIOForwarding(); + +    void +    StopSTDIOForwarding(); +      //------------------------------------------------------------------      // For GDBRemoteCommunicationServerLLGS only      //------------------------------------------------------------------ diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp index 1205049db3fb8..f88ac12475260 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp @@ -15,19 +15,26 @@  // C++ Includes  #include <cstring>  #include <chrono> +#include <mutex> +#include <sstream>  // Other libraries and framework includes +#include "llvm/Support/FileSystem.h" +  #include "lldb/Core/Log.h" +#include "lldb/Core/StreamGDBRemote.h"  #include "lldb/Core/StreamString.h"  #include "lldb/Core/StructuredData.h"  #include "lldb/Host/Config.h"  #include "lldb/Host/ConnectionFileDescriptor.h"  #include "lldb/Host/Host.h" +#include "lldb/Host/HostInfo.h"  #include "lldb/Host/StringConvert.h"  #include "lldb/Target/FileAction.h"  #include "lldb/Target/Platform.h"  #include "lldb/Target/Process.h"  #include "lldb/Target/UnixSignals.h" +#include "lldb/Utility/JSON.h"  // Project includes  #include "Utility/StringExtractorGDBRemote.h" @@ -40,18 +47,29 @@ using namespace lldb_private::process_gdb_remote;  //----------------------------------------------------------------------  // GDBRemoteCommunicationServerPlatform constructor  //---------------------------------------------------------------------- -GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform() : +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)  { +    m_pending_gdb_server.pid = LLDB_INVALID_PROCESS_ID; +    m_pending_gdb_server.port = 0; +      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qC,                                    &GDBRemoteCommunicationServerPlatform::Handle_qC);      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir,                                    &GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir);      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer,                                    &GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer); +    RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qQueryGDBServer, +                                  &GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer); +    RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess, +                                  &GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess);      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qProcessInfo,                                    &GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo);      RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir, @@ -78,38 +96,16 @@ GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform()  {  } -GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet) +Error +GDBRemoteCommunicationServerPlatform::LaunchGDBServer(const lldb_private::Args& args, +                                                      std::string hostname, +                                                      lldb::pid_t& pid, +                                                      uint16_t& port, +                                                      std::string& socket_name)  { -#ifdef _WIN32 -    return SendErrorResponse(9); -#else -    // Spawn a local debugserver as a platform so we can then attach or launch -    // a process... - -    Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); -    if (log) -        log->Printf ("GDBRemoteCommunicationServerPlatform::%s() called", __FUNCTION__); - -    // Sleep and wait a bit for debugserver to start to listen... -    ConnectionFileDescriptor file_conn; -    std::string hostname; -    // TODO: /tmp/ should not be hardcoded. User might want to override /tmp -    // with the TMPDIR environment variable -    packet.SetFilePos(::strlen ("qLaunchGDBServer;")); -    std::string name; -    std::string value; -    uint16_t port = UINT16_MAX; -    while (packet.GetNameColonValue(name, value)) -    { -        if (name.compare ("host") == 0) -            hostname.swap(value); -        else if (name.compare ("port") == 0) -            port = StringConvert::ToUInt32(value.c_str(), 0, 0); -    }      if (port == UINT16_MAX)          port = GetNextAvailablePort(); - +          // Spawn a new thread to accept the port that gets bound after      // binding to port 0 (zero). @@ -120,6 +116,8 @@ GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer (StringExtractorGD      ProcessLaunchInfo debugserver_launch_info;      if (hostname.empty())          hostname = "127.0.0.1"; + +    Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));      if (log)          log->Printf("Launching debugserver with: %s:%u...", hostname.c_str(), port); @@ -133,53 +131,210 @@ GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer (StringExtractorGD      int platform_port;      std::string platform_path;      bool ok = UriParser::Parse(GetConnection()->GetURI().c_str(), platform_scheme, platform_ip, platform_port, platform_path); +    UNUSED_IF_ASSERT_DISABLED(ok);      assert(ok); -    Error error = StartDebugserverProcess ( -                                     platform_ip.c_str(), -                                     port, -                                     debugserver_launch_info, -                                     port); -    lldb::pid_t debugserver_pid = debugserver_launch_info.GetProcessID(); +    std::ostringstream url; +    uint16_t* port_ptr = &port; +    if (m_socket_protocol == Socket::ProtocolTcp) +        url << platform_ip << ":" << port; +    else +    { +        socket_name = GetDomainSocketPath("gdbserver").GetPath(); +        url << socket_name; +        port_ptr = nullptr; +    } +    Error error = StartDebugserverProcess (url.str().c_str(), +                                           nullptr, +                                           debugserver_launch_info, +                                           port_ptr, +                                           args); -    if (debugserver_pid != LLDB_INVALID_PROCESS_ID) +    pid = debugserver_launch_info.GetProcessID(); +    if (pid != LLDB_INVALID_PROCESS_ID)      {          Mutex::Locker locker (m_spawned_pids_mutex); -        m_spawned_pids.insert(debugserver_pid); +        m_spawned_pids.insert(pid);          if (port > 0) -            AssociatePortWithProcess(port, debugserver_pid); +            AssociatePortWithProcess(port, pid);      }      else      {          if (port > 0) -            FreePort (port); +            FreePort(port); +    } +    return error; +} + +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet) +{ +#ifdef _WIN32 +    return SendErrorResponse(9); +#else +    // Spawn a local debugserver as a platform so we can then attach or launch +    // a process... + +    Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM)); +    if (log) +        log->Printf ("GDBRemoteCommunicationServerPlatform::%s() called", __FUNCTION__); + +    ConnectionFileDescriptor file_conn; +    std::string hostname; +    packet.SetFilePos(::strlen ("qLaunchGDBServer;")); +    std::string name; +    std::string value; +    uint16_t port = UINT16_MAX; +    while (packet.GetNameColonValue(name, value)) +    { +        if (name.compare ("host") == 0) +            hostname.swap(value); +        else if (name.compare ("port") == 0) +            port = StringConvert::ToUInt32(value.c_str(), 0, 0);      } -    if (error.Success()) +    lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID; +    std::string socket_name; +    Error error = LaunchGDBServer(Args(), hostname, debugserver_pid, port, socket_name); +    if (error.Fail())      {          if (log) -            log->Printf ("GDBRemoteCommunicationServerPlatform::%s() debugserver launched successfully as pid %" PRIu64, __FUNCTION__, debugserver_pid); +            log->Printf("GDBRemoteCommunicationServerPlatform::%s() debugserver launch failed: %s", __FUNCTION__, error.AsCString ()); +        return SendErrorResponse(9); +    } -        char response[256]; -        const int response_len = ::snprintf (response, sizeof(response), "pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset); -        assert (response_len < (int)sizeof(response)); -        PacketResult packet_result = SendPacketNoLock (response, response_len); +    if (log) +        log->Printf ("GDBRemoteCommunicationServerPlatform::%s() debugserver launched successfully as pid %" PRIu64, __FUNCTION__, debugserver_pid); -        if (packet_result != PacketResult::Success) +    StreamGDBRemote response; +    response.Printf("pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset); +    if (!socket_name.empty()) +    { +        response.PutCString("socket_name:"); +        response.PutCStringAsRawHex8(socket_name.c_str()); +        response.PutChar(';'); +    } + +    PacketResult packet_result = SendPacketNoLock(response.GetData(), response.GetSize()); +    if (packet_result != PacketResult::Success) +    { +        if (debugserver_pid != LLDB_INVALID_PROCESS_ID) +            ::kill (debugserver_pid, SIGINT); +    } +    return packet_result; +#endif +} + +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer (StringExtractorGDBRemote &packet) +{ +    if (m_pending_gdb_server.pid == LLDB_INVALID_PROCESS_ID) +        return SendErrorResponse(4); + +    JSONObject::SP server_sp = std::make_shared<JSONObject>(); +    server_sp->SetObject("port", std::make_shared<JSONNumber>(m_pending_gdb_server.port)); +    if (!m_pending_gdb_server.socket_name.empty()) +        server_sp->SetObject("socket_name", +                             std::make_shared<JSONString>(m_pending_gdb_server.socket_name.c_str())); + +    JSONArray server_list; +    server_list.AppendObject(server_sp); + +    StreamGDBRemote response; +    server_list.Write(response); + +    StreamGDBRemote escaped_response; +    escaped_response.PutEscapedBytes(response.GetData(), response.GetSize()); +    return SendPacketNoLock(escaped_response.GetData(), escaped_response.GetSize()); +} + +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet) +{ +    packet.SetFilePos(::strlen ("qKillSpawnedProcess:")); + +    lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID); + +    // verify that we know anything about this pid. +    // Scope for locker +    { +        Mutex::Locker locker (m_spawned_pids_mutex); +        if (m_spawned_pids.find(pid) == m_spawned_pids.end())          { -            if (debugserver_pid != LLDB_INVALID_PROCESS_ID) -                ::kill (debugserver_pid, SIGINT); +            // not a pid we know about +            return SendErrorResponse (10);          } -        return packet_result;      } + +    // go ahead and attempt to kill the spawned process +    if (KillSpawnedProcess (pid)) +        return SendOKResponse ();      else +        return SendErrorResponse (11); +} + +bool +GDBRemoteCommunicationServerPlatform::KillSpawnedProcess (lldb::pid_t pid) +{ +    // make sure we know about this process      { -        if (log) -            log->Printf ("GDBRemoteCommunicationServerPlatform::%s() debugserver launch failed: %s", __FUNCTION__, error.AsCString ()); +        Mutex::Locker locker (m_spawned_pids_mutex); +        if (m_spawned_pids.find(pid) == m_spawned_pids.end()) +            return false;      } -    return SendErrorResponse (9); -#endif + +    // first try a SIGTERM (standard kill) +    Host::Kill (pid, SIGTERM); + +    // check if that worked +    for (size_t i=0; i<10; ++i) +    { +        { +            Mutex::Locker locker (m_spawned_pids_mutex); +            if (m_spawned_pids.find(pid) == m_spawned_pids.end()) +            { +                // it is now killed +                return true; +            } +        } +        usleep (10000); +    } + +    // check one more time after the final usleep +    { +        Mutex::Locker locker (m_spawned_pids_mutex); +        if (m_spawned_pids.find(pid) == m_spawned_pids.end()) +            return true; +    } + +    // the launched process still lives.  Now try killing it again, +    // this time with an unblockable signal. +    Host::Kill (pid, SIGKILL); + +    for (size_t i=0; i<10; ++i) +    { +        { +            Mutex::Locker locker (m_spawned_pids_mutex); +            if (m_spawned_pids.find(pid) == m_spawned_pids.end()) +            { +                // it is now killed +                return true; +            } +        } +        usleep (10000); +    } + +    // check one more time after the final usleep +    // Scope for locker +    { +        Mutex::Locker locker (m_spawned_pids_mutex); +        if (m_spawned_pids.find(pid) == m_spawned_pids.end()) +            return true; +    } + +    // no luck - the process still lives +    return false;  }  GDBRemoteCommunication::PacketResult @@ -402,8 +557,48 @@ GDBRemoteCommunicationServerPlatform::FreePortForProcess (lldb::pid_t pid)      return false;  } +const FileSpec& +GDBRemoteCommunicationServerPlatform::GetDomainSocketDir() +{ +    static FileSpec g_domainsocket_dir; +    static std::once_flag g_once_flag; + +    std::call_once(g_once_flag, []() { +        const char* domainsocket_dir_env = ::getenv("LLDB_DEBUGSERVER_DOMAINSOCKET_DIR"); +        if (domainsocket_dir_env != nullptr) +            g_domainsocket_dir = FileSpec(domainsocket_dir_env, false); +        else +            HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, g_domainsocket_dir); +    }); + +    return g_domainsocket_dir; +} + +FileSpec +GDBRemoteCommunicationServerPlatform::GetDomainSocketPath(const char* prefix) +{ +    llvm::SmallString<PATH_MAX> socket_path; +    llvm::SmallString<PATH_MAX> socket_name((llvm::StringRef(prefix) + ".%%%%%%").str()); + +    FileSpec socket_path_spec(GetDomainSocketDir()); +    socket_path_spec.AppendPathComponent(socket_name.c_str()); + +    llvm::sys::fs::createUniqueFile(socket_path_spec.GetCString(), socket_path); +    return FileSpec(socket_path.c_str(), false); +} +  void -GDBRemoteCommunicationServerPlatform::SetPortOffset (uint16_t port_offset) +GDBRemoteCommunicationServerPlatform::SetPortOffset(uint16_t port_offset)  {      m_port_offset = port_offset;  } + +void +GDBRemoteCommunicationServerPlatform::SetPendingGdbServer(lldb::pid_t pid, +                                                          uint16_t port, +                                                          const std::string& socket_name) +{ +    m_pending_gdb_server.pid = pid; +    m_pending_gdb_server.port = port; +    m_pending_gdb_server.socket_name = socket_name; +} diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h index 5c011371a3ebe..1fe7207d2bc2e 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h @@ -10,7 +10,15 @@  #ifndef liblldb_GDBRemoteCommunicationServerPlatform_h_  #define liblldb_GDBRemoteCommunicationServerPlatform_h_ +// C Includes +// C++ Includes +#include <map> +#include <set> + +// Other libraries and framework includes +// Project includes  #include "GDBRemoteCommunicationServerCommon.h" +#include "lldb/Host/Socket.h"  namespace lldb_private {  namespace process_gdb_remote { @@ -21,10 +29,10 @@ class GDBRemoteCommunicationServerPlatform :  public:      typedef std::map<uint16_t, lldb::pid_t> PortMap; -    GDBRemoteCommunicationServerPlatform(); +    GDBRemoteCommunicationServerPlatform(const Socket::SocketProtocol socket_protocol, +                                         const char* socket_scheme); -    virtual -    ~GDBRemoteCommunicationServerPlatform(); +    ~GDBRemoteCommunicationServerPlatform() override;      Error      LaunchProcess () override; @@ -58,16 +66,40 @@ public:      void      SetPortOffset (uint16_t port_offset); +    void +    SetInferiorArguments (const lldb_private::Args& args); + +    Error +    LaunchGDBServer(const lldb_private::Args& args, +                    std::string hostname, +                    lldb::pid_t& pid, +                    uint16_t& port, +                    std::string& socket_name); + +    void +    SetPendingGdbServer(lldb::pid_t pid, uint16_t port, const std::string& socket_name); +  protected: +    const Socket::SocketProtocol m_socket_protocol; +    const std::string m_socket_scheme; +    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; +    struct { lldb::pid_t pid; uint16_t port; std::string socket_name; } m_pending_gdb_server;      PacketResult      Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet);      PacketResult +    Handle_qQueryGDBServer (StringExtractorGDBRemote &packet); + +    PacketResult +    Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet); + +    PacketResult      Handle_qProcessInfo (StringExtractorGDBRemote &packet);      PacketResult @@ -84,6 +116,9 @@ protected:  private:      bool +    KillSpawnedProcess (lldb::pid_t pid); + +    bool      DebugserverProcessReaped (lldb::pid_t pid);      static bool @@ -93,13 +128,16 @@ private:                              int signal,                              int status); -    //------------------------------------------------------------------ -    // For GDBRemoteCommunicationServerPlatform only -    //------------------------------------------------------------------ +    static const FileSpec& +    GetDomainSocketDir(); + +    static FileSpec +    GetDomainSocketPath(const char* prefix); +      DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunicationServerPlatform);  };  } // namespace process_gdb_remote  } // namespace lldb_private -#endif  // liblldb_GDBRemoteCommunicationServerPlatform_h_ +#endif // liblldb_GDBRemoteCommunicationServerPlatform_h_ diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp index f5f134e80d6ab..b0a1eaaeb79c0 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp +++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp @@ -17,9 +17,6 @@  #include "lldb/Core/RegisterValue.h"  #include "lldb/Core/Scalar.h"  #include "lldb/Core/StreamString.h" -#ifndef LLDB_DISABLE_PYTHON -#include "lldb/Interpreter/PythonDataObjects.h" -#endif  #include "lldb/Target/ExecutionContext.h"  #include "lldb/Target/Target.h"  #include "lldb/Utility/Utils.h" @@ -28,8 +25,8 @@  #include "ProcessGDBRemote.h"  #include "ProcessGDBRemoteLog.h"  #include "ThreadGDBRemote.h" -#include "Utility/ARM_GCC_Registers.h"  #include "Utility/ARM_DWARF_Registers.h" +#include "Utility/ARM_ehframe_Registers.h"  using namespace lldb;  using namespace lldb_private; @@ -150,6 +147,52 @@ GDBRemoteRegisterContext::PrivateSetRegisterValue (uint32_t reg, StringExtractor      return success;  } +bool +GDBRemoteRegisterContext::PrivateSetRegisterValue (uint32_t reg, uint64_t new_reg_val) +{ +    const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg); +    if (reg_info == NULL) +        return false; + +    // Early in process startup, we can get a thread that has an invalid byte order +    // because the process hasn't been completely set up yet (see the ctor where the +    // byte order is setfrom the process).  If that's the case, we can't set the +    // value here. +    if (m_reg_data.GetByteOrder() == eByteOrderInvalid) +    { +        return false; +    } + +    // Invalidate if needed +    InvalidateIfNeeded (false); + +    DataBufferSP buffer_sp (new DataBufferHeap (&new_reg_val, sizeof (new_reg_val))); +    DataExtractor data (buffer_sp, endian::InlHostByteOrder(), sizeof (void*)); + +    // If our register context and our register info disagree, which should never happen, don't +    // overwrite past the end of the buffer. +    if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size) +        return false; + +    // Grab a pointer to where we are going to put this register +    uint8_t *dst = const_cast<uint8_t*>(m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size)); + +    if (dst == NULL) +        return false; + + +    if (data.CopyByteOrderedData (0,                            // src offset +                                  reg_info->byte_size,          // src length +                                  dst,                          // dst +                                  reg_info->byte_size,          // dst length +                                  m_reg_data.GetByteOrder()))   // dst byte order +    { +        SetRegisterIsValid (reg, true); +        return true; +    } +    return false; +} +  // Helper function for GDBRemoteRegisterContext::ReadRegisterBytes().  bool  GDBRemoteRegisterContext::GetPrimordialRegister(const RegisterInfo *reg_info, @@ -186,7 +229,8 @@ GDBRemoteRegisterContext::ReadRegisterBytes (const RegisterInfo *reg_info, DataE              if (!gdb_comm.ReadAllRegisters(m_thread.GetProtocolID(), response))                  return false;              if (response.IsNormalResponse()) -                if (response.GetHexBytes ((void *)m_reg_data.GetDataStart(), m_reg_data.GetByteSize(), '\xcc') == m_reg_data.GetByteSize()) +                if (response.GetHexBytes(const_cast<void *>(reinterpret_cast<const void *>(m_reg_data.GetDataStart())), +                                         m_reg_data.GetByteSize(), '\xcc') == m_reg_data.GetByteSize())                      SetAllRegisterValid (true);          }          else if (reg_info->value_regs) @@ -275,8 +319,8 @@ GDBRemoteRegisterContext::SetPrimordialRegister(const RegisterInfo *reg_info,      packet.Printf ("P%x=", reg);      packet.PutBytesAsRawHex8 (m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size),                                reg_info->byte_size, -                              lldb::endian::InlHostByteOrder(), -                              lldb::endian::InlHostByteOrder()); +                              endian::InlHostByteOrder(), +                              endian::InlHostByteOrder());      if (gdb_comm.GetThreadSuffixSupported())          packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID()); @@ -372,8 +416,8 @@ GDBRemoteRegisterContext::WriteRegisterBytes (const RegisterInfo *reg_info, Data                      packet.PutChar ('G');                      packet.PutBytesAsRawHex8 (m_reg_data.GetDataStart(),                                                m_reg_data.GetByteSize(), -                                              lldb::endian::InlHostByteOrder(), -                                              lldb::endian::InlHostByteOrder()); +                                              endian::InlHostByteOrder(), +                                              endian::InlHostByteOrder());                      if (thread_suffix_supported)                          packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID()); @@ -772,8 +816,8 @@ GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data                                  packet.Printf ("P%x=", reg);                                  packet.PutBytesAsRawHex8 (restore_src,                                                            reg_byte_size, -                                                          lldb::endian::InlHostByteOrder(), -                                                          lldb::endian::InlHostByteOrder()); +                                                          endian::InlHostByteOrder(), +                                                          endian::InlHostByteOrder());                                  if (thread_suffix_supported)                                      packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID()); @@ -795,8 +839,8 @@ GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data                                      packet.Printf ("P%x=", reg);                                      packet.PutBytesAsRawHex8 (restore_src,                                                                reg_byte_size, -                                                              lldb::endian::InlHostByteOrder(), -                                                              lldb::endian::InlHostByteOrder()); +                                                              endian::InlHostByteOrder(), +                                                              endian::InlHostByteOrder());                                      if (thread_suffix_supported)                                          packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID()); @@ -851,7 +895,7 @@ GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data                      }                      StreamString packet;                      packet.Printf ("P%x=", reg_info->kinds[eRegisterKindLLDB]); -                    packet.PutBytesAsRawHex8 (data_sp->GetBytes() + reg_info->byte_offset, reg_info->byte_size, lldb::endian::InlHostByteOrder(), lldb::endian::InlHostByteOrder()); +                    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()); @@ -941,115 +985,115 @@ GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters(bool from_scratch)      };      static RegisterInfo g_register_infos[] = { -//   NAME    ALT    SZ  OFF  ENCODING          FORMAT          COMPILER             DWARF                GENERIC                 GDB    LLDB      VALUE REGS    INVALIDATE REGS -//   ======  ====== === ===  =============     ============    ===================  ===================  ======================  ===    ====      ==========    =============== -    { "r0", "arg1",   4,   0, eEncodingUint,    eFormatHex,   { gcc_r0,              dwarf_r0,            LLDB_REGNUM_GENERIC_ARG1,0,      0 },        NULL,              NULL}, -    { "r1", "arg2",   4,   0, eEncodingUint,    eFormatHex,   { gcc_r1,              dwarf_r1,            LLDB_REGNUM_GENERIC_ARG2,1,      1 },        NULL,              NULL}, -    { "r2", "arg3",   4,   0, eEncodingUint,    eFormatHex,   { gcc_r2,              dwarf_r2,            LLDB_REGNUM_GENERIC_ARG3,2,      2 },        NULL,              NULL}, -    { "r3", "arg4",   4,   0, eEncodingUint,    eFormatHex,   { gcc_r3,              dwarf_r3,            LLDB_REGNUM_GENERIC_ARG4,3,      3 },        NULL,              NULL}, -    { "r4",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r4,              dwarf_r4,            LLDB_INVALID_REGNUM,     4,      4 },        NULL,              NULL}, -    { "r5",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r5,              dwarf_r5,            LLDB_INVALID_REGNUM,     5,      5 },        NULL,              NULL}, -    { "r6",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r6,              dwarf_r6,            LLDB_INVALID_REGNUM,     6,      6 },        NULL,              NULL}, -    { "r7",   "fp",   4,   0, eEncodingUint,    eFormatHex,   { gcc_r7,              dwarf_r7,            LLDB_REGNUM_GENERIC_FP,  7,      7 },        NULL,              NULL}, -    { "r8",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r8,              dwarf_r8,            LLDB_INVALID_REGNUM,     8,      8 },        NULL,              NULL}, -    { "r9",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r9,              dwarf_r9,            LLDB_INVALID_REGNUM,     9,      9 },        NULL,              NULL}, -    { "r10",  NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r10,             dwarf_r10,           LLDB_INVALID_REGNUM,    10,     10 },        NULL,              NULL}, -    { "r11",  NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r11,             dwarf_r11,           LLDB_INVALID_REGNUM,    11,     11 },        NULL,              NULL}, -    { "r12",  NULL,   4,   0, eEncodingUint,    eFormatHex,   { gcc_r12,             dwarf_r12,           LLDB_INVALID_REGNUM,    12,     12 },        NULL,              NULL}, -    { "sp",   "r13",  4,   0, eEncodingUint,    eFormatHex,   { gcc_sp,              dwarf_sp,            LLDB_REGNUM_GENERIC_SP, 13,     13 },        NULL,              NULL}, -    { "lr",   "r14",  4,   0, eEncodingUint,    eFormatHex,   { gcc_lr,              dwarf_lr,            LLDB_REGNUM_GENERIC_RA, 14,     14 },        NULL,              NULL}, -    { "pc",   "r15",  4,   0, eEncodingUint,    eFormatHex,   { gcc_pc,              dwarf_pc,            LLDB_REGNUM_GENERIC_PC, 15,     15 },        NULL,              NULL}, -    { "f0",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    16,     16 },        NULL,              NULL}, -    { "f1",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    17,     17 },        NULL,              NULL}, -    { "f2",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    18,     18 },        NULL,              NULL}, -    { "f3",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    19,     19 },        NULL,              NULL}, -    { "f4",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    20,     20 },        NULL,              NULL}, -    { "f5",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    21,     21 },        NULL,              NULL}, -    { "f6",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    22,     22 },        NULL,              NULL}, -    { "f7",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    23,     23 },        NULL,              NULL}, -    { "fps",  NULL,   4,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    24,     24 },        NULL,              NULL}, -    { "cpsr","flags", 4,   0, eEncodingUint,    eFormatHex,   { gcc_cpsr,            dwarf_cpsr,          LLDB_INVALID_REGNUM,    25,     25 },        NULL,              NULL}, -    { "s0",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0,            LLDB_INVALID_REGNUM,    26,     26 },        NULL,              NULL}, -    { "s1",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1,            LLDB_INVALID_REGNUM,    27,     27 },        NULL,              NULL}, -    { "s2",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2,            LLDB_INVALID_REGNUM,    28,     28 },        NULL,              NULL}, -    { "s3",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3,            LLDB_INVALID_REGNUM,    29,     29 },        NULL,              NULL}, -    { "s4",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4,            LLDB_INVALID_REGNUM,    30,     30 },        NULL,              NULL}, -    { "s5",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5,            LLDB_INVALID_REGNUM,    31,     31 },        NULL,              NULL}, -    { "s6",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6,            LLDB_INVALID_REGNUM,    32,     32 },        NULL,              NULL}, -    { "s7",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7,            LLDB_INVALID_REGNUM,    33,     33 },        NULL,              NULL}, -    { "s8",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8,            LLDB_INVALID_REGNUM,    34,     34 },        NULL,              NULL}, -    { "s9",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9,            LLDB_INVALID_REGNUM,    35,     35 },        NULL,              NULL}, -    { "s10",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10,           LLDB_INVALID_REGNUM,    36,     36 },        NULL,              NULL}, -    { "s11",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11,           LLDB_INVALID_REGNUM,    37,     37 },        NULL,              NULL}, -    { "s12",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12,           LLDB_INVALID_REGNUM,    38,     38 },        NULL,              NULL}, -    { "s13",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13,           LLDB_INVALID_REGNUM,    39,     39 },        NULL,              NULL}, -    { "s14",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14,           LLDB_INVALID_REGNUM,    40,     40 },        NULL,              NULL}, -    { "s15",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15,           LLDB_INVALID_REGNUM,    41,     41 },        NULL,              NULL}, -    { "s16",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16,           LLDB_INVALID_REGNUM,    42,     42 },        NULL,              NULL}, -    { "s17",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17,           LLDB_INVALID_REGNUM,    43,     43 },        NULL,              NULL}, -    { "s18",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18,           LLDB_INVALID_REGNUM,    44,     44 },        NULL,              NULL}, -    { "s19",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19,           LLDB_INVALID_REGNUM,    45,     45 },        NULL,              NULL}, -    { "s20",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20,           LLDB_INVALID_REGNUM,    46,     46 },        NULL,              NULL}, -    { "s21",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21,           LLDB_INVALID_REGNUM,    47,     47 },        NULL,              NULL}, -    { "s22",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22,           LLDB_INVALID_REGNUM,    48,     48 },        NULL,              NULL}, -    { "s23",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23,           LLDB_INVALID_REGNUM,    49,     49 },        NULL,              NULL}, -    { "s24",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24,           LLDB_INVALID_REGNUM,    50,     50 },        NULL,              NULL}, -    { "s25",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25,           LLDB_INVALID_REGNUM,    51,     51 },        NULL,              NULL}, -    { "s26",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26,           LLDB_INVALID_REGNUM,    52,     52 },        NULL,              NULL}, -    { "s27",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27,           LLDB_INVALID_REGNUM,    53,     53 },        NULL,              NULL}, -    { "s28",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28,           LLDB_INVALID_REGNUM,    54,     54 },        NULL,              NULL}, -    { "s29",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29,           LLDB_INVALID_REGNUM,    55,     55 },        NULL,              NULL}, -    { "s30",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30,           LLDB_INVALID_REGNUM,    56,     56 },        NULL,              NULL}, -    { "s31",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31,           LLDB_INVALID_REGNUM,    57,     57 },        NULL,              NULL}, -    { "fpscr",NULL,   4,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    58,     58 },        NULL,              NULL}, -    { "d16",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16,           LLDB_INVALID_REGNUM,    59,     59 },        NULL,              NULL}, -    { "d17",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17,           LLDB_INVALID_REGNUM,    60,     60 },        NULL,              NULL}, -    { "d18",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18,           LLDB_INVALID_REGNUM,    61,     61 },        NULL,              NULL}, -    { "d19",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19,           LLDB_INVALID_REGNUM,    62,     62 },        NULL,              NULL}, -    { "d20",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20,           LLDB_INVALID_REGNUM,    63,     63 },        NULL,              NULL}, -    { "d21",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21,           LLDB_INVALID_REGNUM,    64,     64 },        NULL,              NULL}, -    { "d22",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22,           LLDB_INVALID_REGNUM,    65,     65 },        NULL,              NULL}, -    { "d23",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23,           LLDB_INVALID_REGNUM,    66,     66 },        NULL,              NULL}, -    { "d24",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24,           LLDB_INVALID_REGNUM,    67,     67 },        NULL,              NULL}, -    { "d25",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25,           LLDB_INVALID_REGNUM,    68,     68 },        NULL,              NULL}, -    { "d26",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26,           LLDB_INVALID_REGNUM,    69,     69 },        NULL,              NULL}, -    { "d27",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27,           LLDB_INVALID_REGNUM,    70,     70 },        NULL,              NULL}, -    { "d28",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28,           LLDB_INVALID_REGNUM,    71,     71 },        NULL,              NULL}, -    { "d29",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29,           LLDB_INVALID_REGNUM,    72,     72 },        NULL,              NULL}, -    { "d30",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30,           LLDB_INVALID_REGNUM,    73,     73 },        NULL,              NULL}, -    { "d31",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31,           LLDB_INVALID_REGNUM,    74,     74 },        NULL,              NULL}, -    { "d0",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d0,            LLDB_INVALID_REGNUM,    75,     75 },   g_d0_regs,              NULL}, -    { "d1",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d1,            LLDB_INVALID_REGNUM,    76,     76 },   g_d1_regs,              NULL}, -    { "d2",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d2,            LLDB_INVALID_REGNUM,    77,     77 },   g_d2_regs,              NULL}, -    { "d3",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d3,            LLDB_INVALID_REGNUM,    78,     78 },   g_d3_regs,              NULL}, -    { "d4",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d4,            LLDB_INVALID_REGNUM,    79,     79 },   g_d4_regs,              NULL}, -    { "d5",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d5,            LLDB_INVALID_REGNUM,    80,     80 },   g_d5_regs,              NULL}, -    { "d6",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d6,            LLDB_INVALID_REGNUM,    81,     81 },   g_d6_regs,              NULL}, -    { "d7",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d7,            LLDB_INVALID_REGNUM,    82,     82 },   g_d7_regs,              NULL}, -    { "d8",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d8,            LLDB_INVALID_REGNUM,    83,     83 },   g_d8_regs,              NULL}, -    { "d9",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d9,            LLDB_INVALID_REGNUM,    84,     84 },   g_d9_regs,              NULL}, -    { "d10",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d10,           LLDB_INVALID_REGNUM,    85,     85 },  g_d10_regs,              NULL}, -    { "d11",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d11,           LLDB_INVALID_REGNUM,    86,     86 },  g_d11_regs,              NULL}, -    { "d12",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d12,           LLDB_INVALID_REGNUM,    87,     87 },  g_d12_regs,              NULL}, -    { "d13",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d13,           LLDB_INVALID_REGNUM,    88,     88 },  g_d13_regs,              NULL}, -    { "d14",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d14,           LLDB_INVALID_REGNUM,    89,     89 },  g_d14_regs,              NULL}, -    { "d15",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d15,           LLDB_INVALID_REGNUM,    90,     90 },  g_d15_regs,              NULL}, -    { "q0",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q0,    LLDB_INVALID_REGNUM,    91,     91 },   g_q0_regs,              NULL}, -    { "q1",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q1,    LLDB_INVALID_REGNUM,    92,     92 },   g_q1_regs,              NULL}, -    { "q2",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q2,    LLDB_INVALID_REGNUM,    93,     93 },   g_q2_regs,              NULL}, -    { "q3",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q3,    LLDB_INVALID_REGNUM,    94,     94 },   g_q3_regs,              NULL}, -    { "q4",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q4,    LLDB_INVALID_REGNUM,    95,     95 },   g_q4_regs,              NULL}, -    { "q5",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q5,    LLDB_INVALID_REGNUM,    96,     96 },   g_q5_regs,              NULL}, -    { "q6",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q6,    LLDB_INVALID_REGNUM,    97,     97 },   g_q6_regs,              NULL}, -    { "q7",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q7,    LLDB_INVALID_REGNUM,    98,     98 },   g_q7_regs,              NULL}, -    { "q8",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q8,    LLDB_INVALID_REGNUM,    99,     99 },   g_q8_regs,              NULL}, -    { "q9",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q9,    LLDB_INVALID_REGNUM,   100,    100 },   g_q9_regs,              NULL}, -    { "q10",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q10,   LLDB_INVALID_REGNUM,   101,    101 },  g_q10_regs,              NULL}, -    { "q11",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q11,   LLDB_INVALID_REGNUM,   102,    102 },  g_q11_regs,              NULL}, -    { "q12",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q12,   LLDB_INVALID_REGNUM,   103,    103 },  g_q12_regs,              NULL}, -    { "q13",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q13,   LLDB_INVALID_REGNUM,   104,    104 },  g_q13_regs,              NULL}, -    { "q14",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q14,   LLDB_INVALID_REGNUM,   105,    105 },  g_q14_regs,              NULL}, -    { "q15",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q15,   LLDB_INVALID_REGNUM,   106,    106 },  g_q15_regs,              NULL} +//   NAME    ALT    SZ  OFF  ENCODING          FORMAT          EH_FRAME             DWARF                GENERIC                 PROCESS PLUGIN  LLDB      VALUE REGS    INVALIDATE REGS +//   ======  ====== === ===  =============     ============    ===================  ===================  ======================  =============   ====      ==========    =============== +    { "r0", "arg1",   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r0,          dwarf_r0,            LLDB_REGNUM_GENERIC_ARG1,0,               0 },        NULL,              NULL}, +    { "r1", "arg2",   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r1,          dwarf_r1,            LLDB_REGNUM_GENERIC_ARG2,1,               1 },        NULL,              NULL}, +    { "r2", "arg3",   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r2,          dwarf_r2,            LLDB_REGNUM_GENERIC_ARG3,2,               2 },        NULL,              NULL}, +    { "r3", "arg4",   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r3,          dwarf_r3,            LLDB_REGNUM_GENERIC_ARG4,3,               3 },        NULL,              NULL}, +    { "r4",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r4,          dwarf_r4,            LLDB_INVALID_REGNUM,     4,               4 },        NULL,              NULL}, +    { "r5",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r5,          dwarf_r5,            LLDB_INVALID_REGNUM,     5,               5 },        NULL,              NULL}, +    { "r6",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r6,          dwarf_r6,            LLDB_INVALID_REGNUM,     6,               6 },        NULL,              NULL}, +    { "r7",   "fp",   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r7,          dwarf_r7,            LLDB_REGNUM_GENERIC_FP,  7,               7 },        NULL,              NULL}, +    { "r8",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r8,          dwarf_r8,            LLDB_INVALID_REGNUM,     8,               8 },        NULL,              NULL}, +    { "r9",   NULL,   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r9,          dwarf_r9,            LLDB_INVALID_REGNUM,     9,               9 },        NULL,              NULL}, +    { "r10",  NULL,   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r10,         dwarf_r10,           LLDB_INVALID_REGNUM,    10,              10 },        NULL,              NULL}, +    { "r11",  NULL,   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r11,         dwarf_r11,           LLDB_INVALID_REGNUM,    11,              11 },        NULL,              NULL}, +    { "r12",  NULL,   4,   0, eEncodingUint,    eFormatHex,   { ehframe_r12,         dwarf_r12,           LLDB_INVALID_REGNUM,    12,              12 },        NULL,              NULL}, +    { "sp",   "r13",  4,   0, eEncodingUint,    eFormatHex,   { ehframe_sp,          dwarf_sp,            LLDB_REGNUM_GENERIC_SP, 13,              13 },        NULL,              NULL}, +    { "lr",   "r14",  4,   0, eEncodingUint,    eFormatHex,   { ehframe_lr,          dwarf_lr,            LLDB_REGNUM_GENERIC_RA, 14,              14 },        NULL,              NULL}, +    { "pc",   "r15",  4,   0, eEncodingUint,    eFormatHex,   { ehframe_pc,          dwarf_pc,            LLDB_REGNUM_GENERIC_PC, 15,              15 },        NULL,              NULL}, +    { "f0",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    16,              16 },        NULL,              NULL}, +    { "f1",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    17,              17 },        NULL,              NULL}, +    { "f2",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    18,              18 },        NULL,              NULL}, +    { "f3",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    19,              19 },        NULL,              NULL}, +    { "f4",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    20,              20 },        NULL,              NULL}, +    { "f5",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    21,              21 },        NULL,              NULL}, +    { "f6",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    22,              22 },        NULL,              NULL}, +    { "f7",   NULL,  12,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    23,              23 },        NULL,              NULL}, +    { "fps",  NULL,   4,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    24,              24 },        NULL,              NULL}, +    { "cpsr","flags", 4,   0, eEncodingUint,    eFormatHex,   { ehframe_cpsr,        dwarf_cpsr,          LLDB_INVALID_REGNUM,    25,              25 },        NULL,              NULL}, +    { "s0",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0,            LLDB_INVALID_REGNUM,    26,              26 },        NULL,              NULL}, +    { "s1",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1,            LLDB_INVALID_REGNUM,    27,              27 },        NULL,              NULL}, +    { "s2",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2,            LLDB_INVALID_REGNUM,    28,              28 },        NULL,              NULL}, +    { "s3",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3,            LLDB_INVALID_REGNUM,    29,              29 },        NULL,              NULL}, +    { "s4",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4,            LLDB_INVALID_REGNUM,    30,              30 },        NULL,              NULL}, +    { "s5",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5,            LLDB_INVALID_REGNUM,    31,              31 },        NULL,              NULL}, +    { "s6",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6,            LLDB_INVALID_REGNUM,    32,              32 },        NULL,              NULL}, +    { "s7",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7,            LLDB_INVALID_REGNUM,    33,              33 },        NULL,              NULL}, +    { "s8",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8,            LLDB_INVALID_REGNUM,    34,              34 },        NULL,              NULL}, +    { "s9",   NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9,            LLDB_INVALID_REGNUM,    35,              35 },        NULL,              NULL}, +    { "s10",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10,           LLDB_INVALID_REGNUM,    36,              36 },        NULL,              NULL}, +    { "s11",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11,           LLDB_INVALID_REGNUM,    37,              37 },        NULL,              NULL}, +    { "s12",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12,           LLDB_INVALID_REGNUM,    38,              38 },        NULL,              NULL}, +    { "s13",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13,           LLDB_INVALID_REGNUM,    39,              39 },        NULL,              NULL}, +    { "s14",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14,           LLDB_INVALID_REGNUM,    40,              40 },        NULL,              NULL}, +    { "s15",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15,           LLDB_INVALID_REGNUM,    41,              41 },        NULL,              NULL}, +    { "s16",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16,           LLDB_INVALID_REGNUM,    42,              42 },        NULL,              NULL}, +    { "s17",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17,           LLDB_INVALID_REGNUM,    43,              43 },        NULL,              NULL}, +    { "s18",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18,           LLDB_INVALID_REGNUM,    44,              44 },        NULL,              NULL}, +    { "s19",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19,           LLDB_INVALID_REGNUM,    45,              45 },        NULL,              NULL}, +    { "s20",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20,           LLDB_INVALID_REGNUM,    46,              46 },        NULL,              NULL}, +    { "s21",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21,           LLDB_INVALID_REGNUM,    47,              47 },        NULL,              NULL}, +    { "s22",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22,           LLDB_INVALID_REGNUM,    48,              48 },        NULL,              NULL}, +    { "s23",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23,           LLDB_INVALID_REGNUM,    49,              49 },        NULL,              NULL}, +    { "s24",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24,           LLDB_INVALID_REGNUM,    50,              50 },        NULL,              NULL}, +    { "s25",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25,           LLDB_INVALID_REGNUM,    51,              51 },        NULL,              NULL}, +    { "s26",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26,           LLDB_INVALID_REGNUM,    52,              52 },        NULL,              NULL}, +    { "s27",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27,           LLDB_INVALID_REGNUM,    53,              53 },        NULL,              NULL}, +    { "s28",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28,           LLDB_INVALID_REGNUM,    54,              54 },        NULL,              NULL}, +    { "s29",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29,           LLDB_INVALID_REGNUM,    55,              55 },        NULL,              NULL}, +    { "s30",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30,           LLDB_INVALID_REGNUM,    56,              56 },        NULL,              NULL}, +    { "s31",  NULL,   4,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31,           LLDB_INVALID_REGNUM,    57,              57 },        NULL,              NULL}, +    { "fpscr",NULL,   4,   0, eEncodingUint,    eFormatHex,   { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,    58,              58 },        NULL,              NULL}, +    { "d16",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16,           LLDB_INVALID_REGNUM,    59,              59 },        NULL,              NULL}, +    { "d17",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17,           LLDB_INVALID_REGNUM,    60,              60 },        NULL,              NULL}, +    { "d18",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18,           LLDB_INVALID_REGNUM,    61,              61 },        NULL,              NULL}, +    { "d19",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19,           LLDB_INVALID_REGNUM,    62,              62 },        NULL,              NULL}, +    { "d20",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20,           LLDB_INVALID_REGNUM,    63,              63 },        NULL,              NULL}, +    { "d21",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21,           LLDB_INVALID_REGNUM,    64,              64 },        NULL,              NULL}, +    { "d22",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22,           LLDB_INVALID_REGNUM,    65,              65 },        NULL,              NULL}, +    { "d23",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23,           LLDB_INVALID_REGNUM,    66,              66 },        NULL,              NULL}, +    { "d24",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24,           LLDB_INVALID_REGNUM,    67,              67 },        NULL,              NULL}, +    { "d25",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25,           LLDB_INVALID_REGNUM,    68,              68 },        NULL,              NULL}, +    { "d26",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26,           LLDB_INVALID_REGNUM,    69,              69 },        NULL,              NULL}, +    { "d27",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27,           LLDB_INVALID_REGNUM,    70,              70 },        NULL,              NULL}, +    { "d28",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28,           LLDB_INVALID_REGNUM,    71,              71 },        NULL,              NULL}, +    { "d29",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29,           LLDB_INVALID_REGNUM,    72,              72 },        NULL,              NULL}, +    { "d30",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30,           LLDB_INVALID_REGNUM,    73,              73 },        NULL,              NULL}, +    { "d31",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31,           LLDB_INVALID_REGNUM,    74,              74 },        NULL,              NULL}, +    { "d0",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d0,            LLDB_INVALID_REGNUM,    75,              75 },   g_d0_regs,              NULL}, +    { "d1",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d1,            LLDB_INVALID_REGNUM,    76,              76 },   g_d1_regs,              NULL}, +    { "d2",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d2,            LLDB_INVALID_REGNUM,    77,              77 },   g_d2_regs,              NULL}, +    { "d3",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d3,            LLDB_INVALID_REGNUM,    78,              78 },   g_d3_regs,              NULL}, +    { "d4",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d4,            LLDB_INVALID_REGNUM,    79,              79 },   g_d4_regs,              NULL}, +    { "d5",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d5,            LLDB_INVALID_REGNUM,    80,              80 },   g_d5_regs,              NULL}, +    { "d6",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d6,            LLDB_INVALID_REGNUM,    81,              81 },   g_d6_regs,              NULL}, +    { "d7",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d7,            LLDB_INVALID_REGNUM,    82,              82 },   g_d7_regs,              NULL}, +    { "d8",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d8,            LLDB_INVALID_REGNUM,    83,              83 },   g_d8_regs,              NULL}, +    { "d9",   NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d9,            LLDB_INVALID_REGNUM,    84,              84 },   g_d9_regs,              NULL}, +    { "d10",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d10,           LLDB_INVALID_REGNUM,    85,              85 },  g_d10_regs,              NULL}, +    { "d11",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d11,           LLDB_INVALID_REGNUM,    86,              86 },  g_d11_regs,              NULL}, +    { "d12",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d12,           LLDB_INVALID_REGNUM,    87,              87 },  g_d12_regs,              NULL}, +    { "d13",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d13,           LLDB_INVALID_REGNUM,    88,              88 },  g_d13_regs,              NULL}, +    { "d14",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d14,           LLDB_INVALID_REGNUM,    89,              89 },  g_d14_regs,              NULL}, +    { "d15",  NULL,   8,   0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d15,           LLDB_INVALID_REGNUM,    90,              90 },  g_d15_regs,              NULL}, +    { "q0",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q0,    LLDB_INVALID_REGNUM,    91,              91 },   g_q0_regs,              NULL}, +    { "q1",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q1,    LLDB_INVALID_REGNUM,    92,              92 },   g_q1_regs,              NULL}, +    { "q2",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q2,    LLDB_INVALID_REGNUM,    93,              93 },   g_q2_regs,              NULL}, +    { "q3",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q3,    LLDB_INVALID_REGNUM,    94,              94 },   g_q3_regs,              NULL}, +    { "q4",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q4,    LLDB_INVALID_REGNUM,    95,              95 },   g_q4_regs,              NULL}, +    { "q5",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q5,    LLDB_INVALID_REGNUM,    96,              96 },   g_q5_regs,              NULL}, +    { "q6",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q6,    LLDB_INVALID_REGNUM,    97,              97 },   g_q6_regs,              NULL}, +    { "q7",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q7,    LLDB_INVALID_REGNUM,    98,              98 },   g_q7_regs,              NULL}, +    { "q8",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q8,    LLDB_INVALID_REGNUM,    99,              99 },   g_q8_regs,              NULL}, +    { "q9",   NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q9,    LLDB_INVALID_REGNUM,   100,             100 },   g_q9_regs,              NULL}, +    { "q10",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q10,   LLDB_INVALID_REGNUM,   101,             101 },  g_q10_regs,              NULL}, +    { "q11",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q11,   LLDB_INVALID_REGNUM,   102,             102 },  g_q11_regs,              NULL}, +    { "q12",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q12,   LLDB_INVALID_REGNUM,   103,             103 },  g_q12_regs,              NULL}, +    { "q13",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q13,   LLDB_INVALID_REGNUM,   104,             104 },  g_q13_regs,              NULL}, +    { "q14",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q14,   LLDB_INVALID_REGNUM,   105,             105 },  g_q14_regs,              NULL}, +    { "q15",  NULL,   16,  0, eEncodingVector,  eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q15,   LLDB_INVALID_REGNUM,   106,             106 },  g_q15_regs,              NULL}      };      static const uint32_t num_registers = llvm::array_lengthof(g_register_infos); diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h index 117d280cc547a..0e26c69eb2a9f 100644 --- a/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h +++ b/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h @@ -42,32 +42,22 @@ public:      {      } -    ~GDBRemoteDynamicRegisterInfo () -    { -    } +    ~GDBRemoteDynamicRegisterInfo() override = default;      void      HardcodeARMRegisters(bool from_scratch); -  };  class GDBRemoteRegisterContext : public RegisterContext  {  public: -    //------------------------------------------------------------------ -    // Constructors and Destructors -    //------------------------------------------------------------------      GDBRemoteRegisterContext (ThreadGDBRemote &thread,                                uint32_t concrete_frame_idx,                                GDBRemoteDynamicRegisterInfo ®_info,                                bool read_all_at_once); -    virtual -    ~GDBRemoteRegisterContext (); +    ~GDBRemoteRegisterContext() override; -    //------------------------------------------------------------------ -    // Subclasses must override these functions -    //------------------------------------------------------------------      void      InvalidateAllRegisters () override; @@ -119,6 +109,9 @@ protected:      bool      PrivateSetRegisterValue (uint32_t reg, StringExtractor &response); +    bool +    PrivateSetRegisterValue (uint32_t reg, uint64_t val); +      void      SetAllRegisterValid (bool b); @@ -166,13 +159,10 @@ private:      bool SetPrimordialRegister(const RegisterInfo *reg_info,                                 GDBRemoteCommunicationClient &gdb_comm); -    //------------------------------------------------------------------ -    // For GDBRemoteRegisterContext only -    //------------------------------------------------------------------      DISALLOW_COPY_AND_ASSIGN (GDBRemoteRegisterContext);  };  } // namespace process_gdb_remote  } // namespace lldb_private -#endif  // lldb_GDBRemoteRegisterContext_h_ +#endif // lldb_GDBRemoteRegisterContext_h_ diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 1e150b1dda9fd..2e7a5b5384f46 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -40,6 +40,7 @@  #include "lldb/Core/Timer.h"  #include "lldb/Core/Value.h"  #include "lldb/DataFormatters/FormatManager.h" +#include "lldb/Host/FileSystem.h"  #include "lldb/Host/HostThread.h"  #include "lldb/Host/StringConvert.h"  #include "lldb/Host/Symbols.h" @@ -56,6 +57,7 @@  #include "lldb/Interpreter/OptionGroupUInt64.h"  #include "lldb/Interpreter/Property.h"  #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Target/ABI.h"  #include "lldb/Target/DynamicLoader.h"  #include "lldb/Target/Target.h"  #include "lldb/Target/TargetList.h" @@ -192,7 +194,7 @@ public:          {              for (uint32_t i = 0; i < e_num; ++i)                  m_has[i] = false; -        }; +        }          void set_name (const std::string & name)          { @@ -216,6 +218,16 @@ public:              return m_has[e_has_base];          } +        void set_base_is_offset (bool is_offset) +        { +            m_base_is_offset = is_offset; +        } +        bool get_base_is_offset(bool & out) const +        { +            out = m_base_is_offset; +            return m_has[e_has_base]; +        } +          void set_link_map (const lldb::addr_t addr)          {              m_link_map = addr; @@ -250,6 +262,7 @@ public:          std::string m_name;          lldb::addr_t m_link_map;          lldb::addr_t m_base; +        bool m_base_is_offset;          lldb::addr_t m_dynamic;      }; @@ -322,22 +335,22 @@ ProcessGDBRemote::Terminate()  lldb::ProcessSP -ProcessGDBRemote::CreateInstance (Target &target, Listener &listener, const FileSpec *crash_file_path) +ProcessGDBRemote::CreateInstance (lldb::TargetSP target_sp, Listener &listener, const FileSpec *crash_file_path)  {      lldb::ProcessSP process_sp;      if (crash_file_path == NULL) -        process_sp.reset (new ProcessGDBRemote (target, listener)); +        process_sp.reset (new ProcessGDBRemote (target_sp, listener));      return process_sp;  }  bool -ProcessGDBRemote::CanDebug (Target &target, bool plugin_specified_by_name) +ProcessGDBRemote::CanDebug (lldb::TargetSP target_sp, bool plugin_specified_by_name)  {      if (plugin_specified_by_name)          return true;      // For now we are just making sure the file exists for a given module -    Module *exe_module = target.GetExecutableModulePointer(); +    Module *exe_module = target_sp->GetExecutableModulePointer();      if (exe_module)      {          ObjectFile *exe_objfile = exe_module->GetObjectFile(); @@ -366,17 +379,20 @@ ProcessGDBRemote::CanDebug (Target &target, bool plugin_specified_by_name)  //----------------------------------------------------------------------  // ProcessGDBRemote constructor  //---------------------------------------------------------------------- -ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) : -    Process (target, listener), +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_threads_info_sp (), +    m_thread_pcs (), +    m_jstopinfo_sp (), +    m_jthreadsinfo_sp (),      m_continue_c_tids (),      m_continue_C_tids (),      m_continue_s_tids (), @@ -394,6 +410,25 @@ ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) :      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)); + +    const uint32_t async_event_mask = eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit; + +    if (m_async_listener.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) +    { +        if (log) +            log->Printf("ProcessGDBRemote::%s failed to listen for m_gdb_comm events", __FUNCTION__); +    } +      const uint64_t timeout_seconds = GetGlobalPluginProperties()->GetPacketTimeout();      if (timeout_seconds > 0)          m_gdb_comm.SetPacketTimeout(timeout_seconds); @@ -481,6 +516,40 @@ ProcessGDBRemote::ParsePythonTargetDefinition(const FileSpec &target_definition_      return false;  } +// If the remote stub didn't give us eh_frame or DWARF register numbers for a register, +// see if the ABI can provide them. +// DWARF and eh_frame register numbers are defined as a part of the ABI. +static void +AugmentRegisterInfoViaABI (RegisterInfo ®_info, ConstString reg_name, ABISP abi_sp) +{ +    if (reg_info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM +        || reg_info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM) +    { +        if (abi_sp) +        { +            RegisterInfo abi_reg_info; +            if (abi_sp->GetRegisterInfoByName (reg_name, abi_reg_info)) +            { +                if (reg_info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM && +                    abi_reg_info.kinds[eRegisterKindEHFrame] != LLDB_INVALID_REGNUM) +                { +                    reg_info.kinds[eRegisterKindEHFrame] = abi_reg_info.kinds[eRegisterKindEHFrame]; +                } +                if (reg_info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM && +                    abi_reg_info.kinds[eRegisterKindDWARF] != LLDB_INVALID_REGNUM) +                { +                    reg_info.kinds[eRegisterKindDWARF] = abi_reg_info.kinds[eRegisterKindDWARF]; +                } +                if (reg_info.kinds[eRegisterKindGeneric] == LLDB_INVALID_REGNUM && +                    abi_reg_info.kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM) +                { +                    reg_info.kinds[eRegisterKindGeneric] = abi_reg_info.kinds[eRegisterKindGeneric]; +                } +            } +        } +    } +} +  static size_t  SplitCommaSeparatedRegisterNumberString(const llvm::StringRef &comma_separated_regiter_numbers, std::vector<uint32_t> ®nums, int base)  { @@ -524,11 +593,23 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)      //     3 - Fall back on the qRegisterInfo packets.      FileSpec target_definition_fspec = GetGlobalPluginProperties()->GetTargetDefinitionFile (); +    if (!target_definition_fspec.Exists()) +    { +        // If the filename doesn't exist, it may be a ~ not having been expanded - try to resolve it. +        target_definition_fspec.ResolvePath(); +    }      if (target_definition_fspec)      {          // See if we can get register definitions from a python file          if (ParsePythonTargetDefinition (target_definition_fspec)) +        {              return; +        } +        else +        { +            StreamSP stream_sp = GetTarget().GetDebugger().GetAsyncOutputStream(); +            stream_sp->Printf ("ERROR: target description file %s failed to parse.\n", target_definition_fspec.GetPath().c_str()); +        }      }      if (GetGDBServerRegisterInfo ()) @@ -561,12 +642,12 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)                      0,                    // byte size                      reg_offset,           // offset                      eEncodingUint,        // encoding -                    eFormatHex,           // formate +                    eFormatHex,           // format                      { -                        LLDB_INVALID_REGNUM, // GCC reg num +                        LLDB_INVALID_REGNUM, // eh_frame reg num                          LLDB_INVALID_REGNUM, // DWARF reg num                          LLDB_INVALID_REGNUM, // generic reg num -                        reg_num,             // GDB reg num +                        reg_num,             // process plugin reg num                          reg_num           // native register number                      },                      NULL, @@ -635,9 +716,9 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)                      {                          set_name.SetCString(value.c_str());                      } -                    else if (name.compare("gcc") == 0) +                    else if (name.compare("gcc") == 0 || name.compare("ehframe") == 0)                      { -                        reg_info.kinds[eRegisterKindGCC] = StringConvert::ToUInt32(value.c_str(), LLDB_INVALID_REGNUM, 0); +                        reg_info.kinds[eRegisterKindEHFrame] = StringConvert::ToUInt32(value.c_str(), LLDB_INVALID_REGNUM, 0);                      }                      else if (name.compare("dwarf") == 0)                      { @@ -671,6 +752,8 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)                      reg_info.invalidate_regs = invalidate_regs.data();                  } +                AugmentRegisterInfoViaABI (reg_info, reg_name, GetABI ()); +                  m_register_info.AddRegister(reg_info, reg_name, alt_name, set_name);              }              else @@ -711,11 +794,12 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)      if (!target_arch.IsValid())      {          if (remote_arch.IsValid() -              && remote_arch.GetMachine() == llvm::Triple::arm +              && (remote_arch.GetMachine() == llvm::Triple::arm || remote_arch.GetMachine() == llvm::Triple::thumb)                && remote_arch.GetTriple().getVendor() == llvm::Triple::Apple)              m_register_info.HardcodeARMRegisters(from_scratch);      } -    else if (target_arch.GetMachine() == llvm::Triple::arm) +    else if (target_arch.GetMachine() == llvm::Triple::arm +            || target_arch.GetMachine() == llvm::Triple::thumb)      {          m_register_info.HardcodeARMRegisters(from_scratch);      } @@ -779,20 +863,21 @@ ProcessGDBRemote::DoConnectRemote (Stream *strm, const char *remote_url)              if (GetTarget().GetNonStopModeEnabled())                  HandleStopReplySequence(); -            if (!m_target.GetArchitecture().IsValid())  +            Target &target = GetTarget(); +            if (!target.GetArchitecture().IsValid())               {                  if (m_gdb_comm.GetProcessArchitecture().IsValid())                  { -                    m_target.SetArchitecture(m_gdb_comm.GetProcessArchitecture()); +                    target.SetArchitecture(m_gdb_comm.GetProcessArchitecture());                  }                  else                  { -                    m_target.SetArchitecture(m_gdb_comm.GetHostArchitecture()); +                    target.SetArchitecture(m_gdb_comm.GetHostArchitecture());                  }              }              const StateType state = SetThreadStopInfo (response); -            if (state == eStateStopped) +            if (state != eStateInvalid)              {                  SetPrivateState (state);              } @@ -910,27 +995,22 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info)      ObjectFile * object_file = exe_module->GetObjectFile();      if (object_file)      { -        // Make sure we aren't already connected? -        if (!m_gdb_comm.IsConnected()) -        { -            error = LaunchAndConnectToDebugserver (launch_info); -        } -         +        error = EstablishConnectionIfNeeded (launch_info);          if (error.Success())          {              lldb_utility::PseudoTerminal pty;              const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0; -            PlatformSP platform_sp (m_target.GetPlatform()); +            PlatformSP platform_sp (GetTarget().GetPlatform());              if (disable_stdio)              {                  // set to /dev/null unless redirected to a file above                  if (!stdin_file_spec) -                    stdin_file_spec.SetFile("/dev/null", false); +                    stdin_file_spec.SetFile(FileSystem::DEV_NULL, false);                  if (!stdout_file_spec) -                    stdout_file_spec.SetFile("/dev/null", false); +                    stdout_file_spec.SetFile(FileSystem::DEV_NULL, false);                  if (!stderr_file_spec) -                    stderr_file_spec.SetFile("/dev/null", false); +                    stderr_file_spec.SetFile(FileSystem::DEV_NULL, false);              }              else if (platform_sp && platform_sp->IsHost())              { @@ -977,7 +1057,7 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info)              m_gdb_comm.SetDisableASLR (launch_flags & eLaunchFlagDisableASLR);              m_gdb_comm.SetDetachOnError (launch_flags & eLaunchFlagDetachOnError); -            m_gdb_comm.SendLaunchArchPacket (m_target.GetArchitecture().GetArchitectureName()); +            m_gdb_comm.SendLaunchArchPacket (GetTarget().GetArchitecture().GetArchitectureName());              const char * launch_event_data = launch_info.GetLaunchEventData();              if (launch_event_data != NULL && *launch_event_data != '\0') @@ -1044,13 +1124,13 @@ ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info)                  if (process_arch.IsValid())                  { -                    m_target.MergeArchitecture(process_arch); +                    GetTarget().MergeArchitecture(process_arch);                  }                  else                  {                      const ArchSpec &host_arch = m_gdb_comm.GetHostArchitecture();                      if (host_arch.IsValid()) -                        m_target.MergeArchitecture(host_arch); +                        GetTarget().MergeArchitecture(host_arch);                  }                  SetPrivateState (SetThreadStopInfo (response)); @@ -1226,8 +1306,8 @@ ProcessGDBRemote::DidLaunchOrAttach (ArchSpec& process_arch)                  // it has, so we really need to take the remote host architecture as our                  // defacto architecture in this case. -                if (process_arch.GetMachine() == llvm::Triple::arm && -                    process_arch.GetTriple().getVendor() == llvm::Triple::Apple) +                if ((process_arch.GetMachine() == llvm::Triple::arm || process_arch.GetMachine() == llvm::Triple::thumb) +                    && process_arch.GetTriple().getVendor() == llvm::Triple::Apple)                  {                      GetTarget().SetArchitecture (process_arch);                      if (log) @@ -1295,21 +1375,7 @@ ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid, const Process      Clear();      if (attach_pid != LLDB_INVALID_PROCESS_ID)      { -        // Make sure we aren't already connected? -        if (!m_gdb_comm.IsConnected()) -        { -            error = LaunchAndConnectToDebugserver (attach_info); -             -            if (error.Fail()) -            { -                const char *error_string = error.AsCString(); -                if (error_string == NULL) -                    error_string = "unable to launch " DEBUGSERVER_BASENAME; - -                SetExitStatus (-1, error_string); -            } -        } -     +        error = EstablishConnectionIfNeeded (attach_info);          if (error.Success())          {              m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError()); @@ -1319,6 +1385,8 @@ ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid, const Process              SetID (attach_pid);                          m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (packet, packet_len));          } +        else +            SetExitStatus (-1, error.AsCString());      }      return error; @@ -1333,21 +1401,7 @@ ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, const Pro      if (process_name && process_name[0])      { -        // Make sure we aren't already connected? -        if (!m_gdb_comm.IsConnected()) -        { -            error = LaunchAndConnectToDebugserver (attach_info); - -            if (error.Fail()) -            { -                const char *error_string = error.AsCString(); -                if (error_string == NULL) -                    error_string = "unable to launch " DEBUGSERVER_BASENAME; - -                SetExitStatus (-1, error_string); -            } -        } - +        error = EstablishConnectionIfNeeded (attach_info);          if (error.Success())          {              StreamString packet; @@ -1371,11 +1425,13 @@ ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, const Pro              else                  packet.PutCString("vAttachName");              packet.PutChar(';'); -            packet.PutBytesAsRawHex8(process_name, strlen(process_name), lldb::endian::InlHostByteOrder(), lldb::endian::InlHostByteOrder()); +            packet.PutBytesAsRawHex8(process_name, strlen(process_name), endian::InlHostByteOrder(), endian::InlHostByteOrder());              m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (packet.GetData(), packet.GetSize()));          } +        else +            SetExitStatus (-1, error.AsCString());      }      return error;  } @@ -1403,6 +1459,8 @@ ProcessGDBRemote::WillResume ()      m_continue_C_tids.clear();      m_continue_s_tids.clear();      m_continue_S_tids.clear(); +    m_jstopinfo_sp.reset(); +    m_jthreadsinfo_sp.reset();      return Error();  } @@ -1694,12 +1752,14 @@ ProcessGDBRemote::ClearThreadIDList ()  {      Mutex::Locker locker(m_thread_list_real.GetMutex());      m_thread_ids.clear(); +    m_thread_pcs.clear();  }  size_t  ProcessGDBRemote::UpdateThreadIDsFromStopReplyThreadsValue (std::string &value)  {      m_thread_ids.clear(); +    m_thread_pcs.clear();      size_t comma_pos;      lldb::tid_t tid;      while ((comma_pos = value.find(',')) != std::string::npos) @@ -1717,18 +1777,39 @@ ProcessGDBRemote::UpdateThreadIDsFromStopReplyThreadsValue (std::string &value)      return m_thread_ids.size();  } +size_t +ProcessGDBRemote::UpdateThreadPCsFromStopReplyThreadsValue (std::string &value) +{ +    m_thread_pcs.clear(); +    size_t comma_pos; +    lldb::addr_t pc; +    while ((comma_pos = value.find(',')) != std::string::npos) +    { +        value[comma_pos] = '\0'; +        pc = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_ADDRESS, 16); +        if (pc != LLDB_INVALID_ADDRESS) +            m_thread_pcs.push_back (pc); +        value.erase(0, comma_pos + 1); +    } +    pc = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_ADDRESS, 16); +    if (pc != LLDB_INVALID_THREAD_ID) +        m_thread_pcs.push_back (pc); +    return m_thread_pcs.size(); +} +  bool  ProcessGDBRemote::UpdateThreadIDList ()  {      Mutex::Locker locker(m_thread_list_real.GetMutex()); -    if (m_threads_info_sp) +    if (m_jthreadsinfo_sp)      {          // If we have the JSON threads info, we can get the thread list from that -        StructuredData::Array *thread_infos = m_threads_info_sp->GetAsArray(); +        StructuredData::Array *thread_infos = m_jthreadsinfo_sp->GetAsArray();          if (thread_infos && thread_infos->GetSize() > 0)          {              m_thread_ids.clear(); +            m_thread_pcs.clear();              thread_infos->ForEach([this](StructuredData::Object* object) -> bool {                  StructuredData::Dictionary *thread_dict = object->GetAsDictionary();                  if (thread_dict) @@ -1751,25 +1832,43 @@ ProcessGDBRemote::UpdateThreadIDList ()          // that might contain a "threads" key/value pair          // Lock the thread stack while we access it -        Mutex::Locker stop_stack_lock(m_last_stop_packet_mutex); -        // Get the number of stop packets on the stack -        int nItems = m_stop_packet_stack.size(); -        // Iterate over them -        for (int i = 0; i < nItems; i++) +        //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))          { -            // Get the thread stop info -            StringExtractorGDBRemote &stop_info = m_stop_packet_stack[i]; -            const std::string &stop_info_str = stop_info.GetStringRef(); -            const size_t threads_pos = stop_info_str.find(";threads:"); -            if (threads_pos != std::string::npos) +            // Get the number of stop packets on the stack +            int nItems = m_stop_packet_stack.size(); +            // Iterate over them +            for (int i = 0; i < nItems; i++)              { -                const size_t start = threads_pos + strlen(";threads:"); -                const size_t end = stop_info_str.find(';', start); -                if (end != std::string::npos) +                // Get the thread stop info +                StringExtractorGDBRemote &stop_info = m_stop_packet_stack[i]; +                const std::string &stop_info_str = stop_info.GetStringRef(); + +                m_thread_pcs.clear(); +                const size_t thread_pcs_pos = stop_info_str.find(";thread-pcs:"); +                if (thread_pcs_pos != std::string::npos) +                { +                    const size_t start = thread_pcs_pos + strlen(";thread-pcs:"); +                    const size_t end = stop_info_str.find(';', start); +                    if (end != std::string::npos) +                    { +                        std::string value = stop_info_str.substr(start, end - start); +                        UpdateThreadPCsFromStopReplyThreadsValue(value); +                    } +                } + +                const size_t threads_pos = stop_info_str.find(";threads:"); +                if (threads_pos != std::string::npos)                  { -                    std::string value = stop_info_str.substr(start, end - start); -                    if (UpdateThreadIDsFromStopReplyThreadsValue(value)) -                        return true; +                    const size_t start = threads_pos + strlen(";threads:"); +                    const size_t end = stop_info_str.find(';', start); +                    if (end != std::string::npos) +                    { +                        std::string value = stop_info_str.substr(start, end - start); +                        if (UpdateThreadIDsFromStopReplyThreadsValue(value)) +                            return true; +                    }                  }              }          } @@ -1826,6 +1925,25 @@ ProcessGDBRemote::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new                             __FUNCTION__, static_cast<void*>(thread_sp.get()),                             thread_sp->GetID());              } +            // The m_thread_pcs vector has pc values in big-endian order, not target-endian, unlike most +            // of the register read/write packets in gdb-remote protocol.   +            // Early in the process startup, we may not yet have set the process ByteOrder so we ignore these; +            // they are a performance improvement over fetching thread register values individually, the +            // method we will fall back to if needed. +            if (m_thread_ids.size() == m_thread_pcs.size() && thread_sp.get() && GetByteOrder() != eByteOrderInvalid) +            { +                ThreadGDBRemote *gdb_thread = static_cast<ThreadGDBRemote *> (thread_sp.get()); +                RegisterContextSP reg_ctx_sp (thread_sp->GetRegisterContext()); +                if (reg_ctx_sp) +                { +                    uint32_t pc_regnum = reg_ctx_sp->ConvertRegisterKindToRegisterNumber  +                                                                   (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC); +                    if (pc_regnum != LLDB_INVALID_REGNUM) +                    { +                        gdb_thread->PrivateSetRegisterValue (pc_regnum, m_thread_pcs[i]); +                    } +                } +            }              new_thread_list.AddThread(thread_sp);          }      } @@ -1846,13 +1964,14 @@ ProcessGDBRemote::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new      return true;  } +  bool -ProcessGDBRemote::CalculateThreadStopInfo (ThreadGDBRemote *thread) +ProcessGDBRemote::GetThreadStopInfoFromJSON (ThreadGDBRemote *thread, const StructuredData::ObjectSP &thread_infos_sp)  {      // See if we got thread stop infos for all threads via the "jThreadsInfo" packet -    if (m_threads_info_sp) +    if (thread_infos_sp)      { -        StructuredData::Array *thread_infos = m_threads_info_sp->GetAsArray(); +        StructuredData::Array *thread_infos = thread_infos_sp->GetAsArray();          if (thread_infos)          {              lldb::tid_t tid; @@ -1865,12 +1984,36 @@ ProcessGDBRemote::CalculateThreadStopInfo (ThreadGDBRemote *thread)                      if (thread_dict->GetValueForKeyAsInteger<lldb::tid_t>("tid", tid, LLDB_INVALID_THREAD_ID))                      {                          if (tid == thread->GetID()) -                            return SetThreadStopInfo(thread_dict); +                            return (bool)SetThreadStopInfo(thread_dict);                      }                  }              }          }      } +    return false; +} + +bool +ProcessGDBRemote::CalculateThreadStopInfo (ThreadGDBRemote *thread) +{ +    // See if we got thread stop infos for all threads via the "jThreadsInfo" packet +    if (GetThreadStopInfoFromJSON (thread, m_jthreadsinfo_sp)) +        return true; + +    // See if we got thread stop info for any threads valid stop info reasons threads +    // via the "jstopinfo" packet stop reply packet key/value pair? +    if (m_jstopinfo_sp) +    { +        // If we have "jstopinfo" then we have stop descriptions for all threads +        // that have stop reasons, and if there is no entry for a thread, then +        // it has no stop reason. +        thread->GetRegisterContext()->InvalidateIfNeeded(true); +        if (!GetThreadStopInfoFromJSON (thread, m_jstopinfo_sp)) +        { +            thread->SetStopInfo (StopInfoSP()); +        } +        return true; +    }      // Fall back to using the qThreadStopInfo packet      StringExtractorGDBRemote stop_packet; @@ -1926,8 +2069,6 @@ ProcessGDBRemote::SetThreadStopInfo (lldb::tid_t tid,                  gdb_thread->PrivateSetRegisterValue (pair.first, reg_value_extractor);              } -            // Clear the stop info just in case we don't set it to anything -            thread_sp->SetStopInfo (StopInfoSP());              thread_sp->SetName (thread_name.empty() ? NULL : thread_name.c_str());              gdb_thread->SetThreadDispatchQAddr (thread_dispatch_qaddr); @@ -1937,145 +2078,159 @@ ProcessGDBRemote::SetThreadStopInfo (lldb::tid_t tid,              else                  gdb_thread->ClearQueueInfo(); - -            if (exc_type != 0) -            { -                const size_t exc_data_size = exc_data.size(); - -                thread_sp->SetStopInfo (StopInfoMachException::CreateStopReasonWithMachException (*thread_sp, -                                                                                                  exc_type, -                                                                                                  exc_data_size, -                                                                                                  exc_data_size >= 1 ? exc_data[0] : 0, -                                                                                                  exc_data_size >= 2 ? exc_data[1] : 0, -                                                                                                  exc_data_size >= 3 ? exc_data[2] : 0)); -            } -            else +            // Make sure we update our thread stop reason just once +            if (!thread_sp->StopInfoIsUpToDate())              { -                bool handled = false; -                bool did_exec = false; -                if (!reason.empty()) +                thread_sp->SetStopInfo (StopInfoSP()); +                // If there's a memory thread backed by this thread, we need to use it to calcualte StopInfo. +                ThreadSP memory_thread_sp = m_thread_list.FindThreadByProtocolID(thread_sp->GetProtocolID()); +                if (memory_thread_sp) +                    thread_sp = memory_thread_sp; + +                if (exc_type != 0)                  { -                    if (reason.compare("trace") == 0) -                    { -                        thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp)); -                        handled = true; -                    } -                    else if (reason.compare("breakpoint") == 0) +                    const size_t exc_data_size = exc_data.size(); + +                    thread_sp->SetStopInfo (StopInfoMachException::CreateStopReasonWithMachException (*thread_sp, +                                                                                                      exc_type, +                                                                                                      exc_data_size, +                                                                                                      exc_data_size >= 1 ? exc_data[0] : 0, +                                                                                                      exc_data_size >= 2 ? exc_data[1] : 0, +                                                                                                      exc_data_size >= 3 ? exc_data[2] : 0)); +                } +                else +                { +                    bool handled = false; +                    bool did_exec = false; +                    if (!reason.empty())                      { -                        addr_t pc = thread_sp->GetRegisterContext()->GetPC(); -                        lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc); -                        if (bp_site_sp) +                        if (reason.compare("trace") == 0)                          { -                            // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread, -                            // we can just report no reason.  We don't need to worry about stepping over the breakpoint here, that -                            // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc. +                            thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp));                              handled = true; -                            if (bp_site_sp->ValidForThisThread (thread_sp.get())) -                            { -                                thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID())); -                            } -                            else +                        } +                        else if (reason.compare("breakpoint") == 0) +                        { +                            addr_t pc = thread_sp->GetRegisterContext()->GetPC(); +                            lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc); +                            if (bp_site_sp)                              { -                                StopInfoSP invalid_stop_info_sp; -                                thread_sp->SetStopInfo (invalid_stop_info_sp); +                                // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread, +                                // we can just report no reason.  We don't need to worry about stepping over the breakpoint here, that +                                // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc. +                                handled = true; +                                if (bp_site_sp->ValidForThisThread (thread_sp.get())) +                                { +                                    thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID())); +                                } +                                else +                                { +                                    StopInfoSP invalid_stop_info_sp; +                                    thread_sp->SetStopInfo (invalid_stop_info_sp); +                                }                              }                          } -                    } -                    else if (reason.compare("trap") == 0) -                    { -                        // Let the trap just use the standard signal stop reason below... -                    } -                    else if (reason.compare("watchpoint") == 0) -                    { -                        StringExtractor desc_extractor(description.c_str()); -                        addr_t wp_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS); -                        uint32_t wp_index = desc_extractor.GetU32(LLDB_INVALID_INDEX32); -                        addr_t wp_hit_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS); -                        watch_id_t watch_id = LLDB_INVALID_WATCH_ID; -                        if (wp_addr != LLDB_INVALID_ADDRESS) +                        else if (reason.compare("trap") == 0)                          { -                            WatchpointSP wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_addr); -                            if (wp_sp) +                            // Let the trap just use the standard signal stop reason below... +                        } +                        else if (reason.compare("watchpoint") == 0) +                        { +                            StringExtractor desc_extractor(description.c_str()); +                            addr_t wp_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS); +                            uint32_t wp_index = desc_extractor.GetU32(LLDB_INVALID_INDEX32); +                            addr_t wp_hit_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS); +                            watch_id_t watch_id = LLDB_INVALID_WATCH_ID; +                            if (wp_addr != LLDB_INVALID_ADDRESS) +                            { +                                WatchpointSP wp_sp; +                                ArchSpec::Core core = GetTarget().GetArchitecture().GetCore(); +                                if (core >= ArchSpec::kCore_mips_first && core <= ArchSpec::kCore_mips_last) +                                    wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_hit_addr); +                                if (!wp_sp) +                                    wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_addr); +                                if (wp_sp) +                                { +                                    wp_sp->SetHardwareIndex(wp_index); +                                    watch_id = wp_sp->GetID(); +                                } +                            } +                            if (watch_id == LLDB_INVALID_WATCH_ID)                              { -                                wp_sp->SetHardwareIndex(wp_index); -                                watch_id = wp_sp->GetID(); +                                Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_WATCHPOINTS)); +                                if (log) log->Printf ("failed to find watchpoint");                              } +                            thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID (*thread_sp, watch_id, wp_hit_addr)); +                            handled = true;                          } -                        if (watch_id == LLDB_INVALID_WATCH_ID) +                        else if (reason.compare("exception") == 0)                          { -                            Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_WATCHPOINTS)); -                            if (log) log->Printf ("failed to find watchpoint"); +                            thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithException(*thread_sp, description.c_str())); +                            handled = true; +                        } +                        else if (reason.compare("exec") == 0) +                        { +                            did_exec = true; +                            thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithExec(*thread_sp)); +                            handled = true;                          } -                        thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID (*thread_sp, watch_id, wp_hit_addr)); -                        handled = true; -                    } -                    else if (reason.compare("exception") == 0) -                    { -                        thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithException(*thread_sp, description.c_str())); -                        handled = true; -                    } -                    else if (reason.compare("exec") == 0) -                    { -                        did_exec = true; -                        thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithExec(*thread_sp)); -                        handled = true;                      } -                } -                if (!handled && signo && did_exec == false) -                { -                    if (signo == SIGTRAP) +                    if (!handled && signo && did_exec == false)                      { -                        // Currently we are going to assume SIGTRAP means we are either -                        // hitting a breakpoint or hardware single stepping. -                        handled = true; -                        addr_t pc = thread_sp->GetRegisterContext()->GetPC() + m_breakpoint_pc_offset; -                        lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc); - -                        if (bp_site_sp) +                        if (signo == SIGTRAP)                          { -                            // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread, -                            // we can just report no reason.  We don't need to worry about stepping over the breakpoint here, that -                            // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc. -                            if (bp_site_sp->ValidForThisThread (thread_sp.get())) +                            // Currently we are going to assume SIGTRAP means we are either +                            // hitting a breakpoint or hardware single stepping. +                            handled = true; +                            addr_t pc = thread_sp->GetRegisterContext()->GetPC() + m_breakpoint_pc_offset; +                            lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc); + +                            if (bp_site_sp)                              { -                                if(m_breakpoint_pc_offset != 0) -                                    thread_sp->GetRegisterContext()->SetPC(pc); -                                thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID())); +                                // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread, +                                // we can just report no reason.  We don't need to worry about stepping over the breakpoint here, that +                                // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc. +                                if (bp_site_sp->ValidForThisThread (thread_sp.get())) +                                { +                                    if(m_breakpoint_pc_offset != 0) +                                        thread_sp->GetRegisterContext()->SetPC(pc); +                                    thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID())); +                                } +                                else +                                { +                                    StopInfoSP invalid_stop_info_sp; +                                    thread_sp->SetStopInfo (invalid_stop_info_sp); +                                }                              }                              else                              { -                                StopInfoSP invalid_stop_info_sp; -                                thread_sp->SetStopInfo (invalid_stop_info_sp); +                                // If we were stepping then assume the stop was the result of the trace.  If we were +                                // not stepping then report the SIGTRAP. +                                // FIXME: We are still missing the case where we single step over a trap instruction. +                                if (thread_sp->GetTemporaryResumeState() == eStateStepping) +                                    thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp)); +                                else +                                    thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithSignal(*thread_sp, signo, description.c_str()));                              }                          } -                        else -                        { -                            // If we were stepping then assume the stop was the result of the trace.  If we were -                            // not stepping then report the SIGTRAP. -                            // FIXME: We are still missing the case where we single step over a trap instruction. -                            if (thread_sp->GetTemporaryResumeState() == eStateStepping) -                                thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp)); -                            else -                                thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithSignal(*thread_sp, signo, description.c_str())); -                        } +                        if (!handled) +                            thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithSignal (*thread_sp, signo, description.c_str()));                      } -                    if (!handled) -                        thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithSignal (*thread_sp, signo, description.c_str())); -                } -                if (!description.empty()) -                { -                    lldb::StopInfoSP stop_info_sp (thread_sp->GetStopInfo ()); -                    if (stop_info_sp) -                    { -                        const char *stop_info_desc = stop_info_sp->GetDescription(); -                        if (!stop_info_desc || !stop_info_desc[0]) -                            stop_info_sp->SetDescription (description.c_str()); -                    } -                    else +                    if (!description.empty())                      { -                        thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithException (*thread_sp, description.c_str())); +                        lldb::StopInfoSP stop_info_sp (thread_sp->GetStopInfo ()); +                        if (stop_info_sp) +                        { +                            const char *stop_info_desc = stop_info_sp->GetDescription(); +                            if (!stop_info_desc || !stop_info_desc[0]) +                                stop_info_sp->SetDescription (description.c_str()); +                        } +                        else +                        { +                            thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithException (*thread_sp, description.c_str())); +                        }                      }                  }              } @@ -2084,7 +2239,7 @@ ProcessGDBRemote::SetThreadStopInfo (lldb::tid_t tid,      return thread_sp;  } -StateType +lldb::ThreadSP  ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)  {      static ConstString g_key_tid("tid"); @@ -2101,6 +2256,7 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)      static ConstString g_key_address("address");      static ConstString g_key_bytes("bytes");      static ConstString g_key_description("description"); +    static ConstString g_key_signal("signal");      // Stop with signal and thread info      lldb::tid_t tid = LLDB_INVALID_THREAD_ID; @@ -2159,7 +2315,7 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)          }          else if (key == g_key_name)          { -            thread_name = std::move(object->GetStringValue()); +            thread_name = object->GetStringValue();          }          else if (key == g_key_qaddr)          { @@ -2168,7 +2324,7 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)          else if (key == g_key_queue_name)          {              queue_vars_valid = true; -            queue_name = std::move(object->GetStringValue()); +            queue_name = object->GetStringValue();          }          else if (key == g_key_queue_kind)          { @@ -2192,11 +2348,11 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)          }          else if (key == g_key_reason)          { -            reason = std::move(object->GetStringValue()); +            reason = object->GetStringValue();          }          else if (key == g_key_description)          { -            description = std::move(object->GetStringValue()); +            description = object->GetStringValue();          }          else if (key == g_key_registers)          { @@ -2207,7 +2363,7 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)                  registers_dict->ForEach([&expedited_register_map](ConstString key, StructuredData::Object* object) -> bool {                      const uint32_t reg = StringConvert::ToUInt32 (key.GetCString(), UINT32_MAX, 10);                      if (reg != UINT32_MAX) -                        expedited_register_map[reg] = std::move(object->GetStringValue()); +                        expedited_register_map[reg] = object->GetStringValue();                      return true; // Keep iterating through all array items                  });              } @@ -2245,24 +2401,24 @@ ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)              }          } +        else if (key == g_key_signal) +            signo = object->GetIntegerValue(LLDB_INVALID_SIGNAL_NUMBER);          return true; // Keep iterating through all dictionary key/value pairs      }); -    SetThreadStopInfo (tid, -                       expedited_register_map, -                       signo, -                       thread_name, -                       reason, -                       description, -                       exc_type, -                       exc_data, -                       thread_dispatch_qaddr, -                       queue_vars_valid, -                       queue_name, -                       queue_kind, -                       queue_serial); - -    return eStateExited; +    return SetThreadStopInfo (tid, +                              expedited_register_map, +                              signo, +                              thread_name, +                              reason, +                              description, +                              exc_type, +                              exc_data, +                              thread_dispatch_qaddr, +                              queue_vars_valid, +                              queue_name, +                              queue_kind, +                              queue_serial);  }  StateType @@ -2348,6 +2504,39 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)                      if (tid != LLDB_INVALID_THREAD_ID)                          m_thread_ids.push_back (tid);                  } +                else if (key.compare("thread-pcs") == 0) +                { +                    m_thread_pcs.clear(); +                    // A comma separated list of all threads in the current +                    // process that includes the thread for this stop reply +                    // packet +                    size_t comma_pos; +                    lldb::addr_t pc; +                    while ((comma_pos = value.find(',')) != std::string::npos) +                    { +                        value[comma_pos] = '\0'; +                        // thread in big endian hex +                        pc = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_ADDRESS, 16); +                        if (pc != LLDB_INVALID_ADDRESS) +                            m_thread_pcs.push_back (pc); +                        value.erase(0, comma_pos + 1); +                    } +                    pc = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_ADDRESS, 16); +                    if (pc != LLDB_INVALID_ADDRESS) +                        m_thread_pcs.push_back (pc); +                } +                else if (key.compare("jstopinfo") == 0) +                { +                    StringExtractor json_extractor; +                    // Swap "value" over into "name_extractor" +                    json_extractor.GetStringRef().swap(value); +                    // Now convert the HEX bytes into a string value +                    json_extractor.GetHexByteString (value); + +                    // This JSON contains thread IDs and thread stop info for all threads. +                    // It doesn't contain expedited registers, memory or queue info. +                    m_jstopinfo_sp = StructuredData::ParseJSON (value); +                }                  else if (key.compare("hexname") == 0)                  {                      StringExtractor name_extractor; @@ -2431,7 +2620,7 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)                          if (mem_cache_addr != LLDB_INVALID_ADDRESS)                          {                              StringExtractor bytes; -                            bytes.GetStringRef() = std::move(pair.second.str()); +                            bytes.GetStringRef() = pair.second.str();                              const size_t byte_size = bytes.GetStringRef().size()/2;                              DataBufferSP data_buffer_sp(new DataBufferHeap(byte_size, 0));                              const size_t bytes_copied = bytes.GetHexBytes (data_buffer_sp->GetBytes(), byte_size, 0); @@ -2455,6 +2644,10 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)                      ostr.Printf("%" PRIu64 " %" PRIu32, wp_addr, wp_index);                      description = ostr.GetString().c_str();                  } +                else if (key.compare("library") == 0) +                { +                    LoadModules(); +                }                  else if (key.size() == 2 && ::isxdigit(key[0]) && ::isxdigit(key[1]))                  {                      uint32_t reg = StringConvert::ToUInt32 (key.c_str(), UINT32_MAX, 16); @@ -2509,6 +2702,7 @@ ProcessGDBRemote::RefreshStateAfterStop ()  {      Mutex::Locker locker(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      // a list of all thread IDs in the current process, so m_thread_ids might      // get set. @@ -2545,11 +2739,6 @@ ProcessGDBRemote::RefreshStateAfterStop ()          m_initial_tid = LLDB_INVALID_THREAD_ID;      } -    // Fetch the threads via an efficient packet that gets stop infos for all threads -    // only if we have more than one thread -    if (m_thread_ids.size() > 1) -        m_threads_info_sp = m_gdb_comm.GetThreadsInfo(); -      // Let all threads recover from stopping and do any clean up based      // on the previous thread state (if any).      m_thread_list_real.RefreshStateAfterStop(); @@ -2824,6 +3013,12 @@ ProcessGDBRemote::SetLastStopPacket (const StringExtractorGDBRemote &response)      {          // Lock the thread stack while we access it          Mutex::Locker stop_stack_lock(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. +        if (GetTarget().GetNonStopModeEnabled() == false) +            m_stop_packet_stack.clear(); +          // Add this stop packet to the stop packet stack          // This stack will get popped and examined when we switch to the          // Stopped state @@ -2831,6 +3026,11 @@ ProcessGDBRemote::SetLastStopPacket (const StringExtractorGDBRemote &response)      }  } +void +ProcessGDBRemote::SetUnixSignals(const UnixSignalsSP &signals_sp) +{ +    Process::SetUnixSignals(std::make_shared<GDBRemoteSignals>(signals_sp)); +}  //------------------------------------------------------------------  // Process Queries @@ -2839,7 +3039,7 @@ ProcessGDBRemote::SetLastStopPacket (const StringExtractorGDBRemote &response)  bool  ProcessGDBRemote::IsAlive ()  { -    return m_gdb_comm.IsConnected() && m_private_state.GetValue() != eStateExited; +    return m_gdb_comm.IsConnected() && Process::IsAlive();  }  addr_t @@ -2859,6 +3059,35 @@ ProcessGDBRemote::GetImageInfoAddress()      return addr;  } +void +ProcessGDBRemote::WillPublicStop () +{ +    // See if the GDB remote client supports the JSON threads info. +    // If so, we gather stop info for all threads, expedited registers, +    // expedited memory, runtime queue information (iOS and MacOSX only), +    // and more. Expediting memory will help stack backtracing be much +    // faster. Expediting registers will make sure we don't have to read +    // the thread registers for GPRs. +    m_jthreadsinfo_sp = m_gdb_comm.GetThreadsInfo(); + +    if (m_jthreadsinfo_sp) +    { +        // Now set the stop info for each thread and also expedite any registers +        // and memory that was in the jThreadsInfo response. +        StructuredData::Array *thread_infos = m_jthreadsinfo_sp->GetAsArray(); +        if (thread_infos) +        { +            const size_t n = thread_infos->GetSize(); +            for (size_t i=0; i<n; ++i) +            { +                StructuredData::Dictionary *thread_dict = thread_infos->GetItemAtIndex(i)->GetAsDictionary(); +                if (thread_dict) +                    SetThreadStopInfo(thread_dict); +            } +        } +    } +} +  //------------------------------------------------------------------  // Process Memory  //------------------------------------------------------------------ @@ -2877,14 +3106,8 @@ ProcessGDBRemote::DoReadMemory (addr_t addr, void *buf, size_t size, Error &erro      char packet[64];      int packet_len;      bool binary_memory_read = m_gdb_comm.GetxPacketSupported(); -    if (binary_memory_read) -    { -        packet_len = ::snprintf (packet, sizeof(packet), "x0x%" PRIx64 ",0x%" PRIx64, (uint64_t)addr, (uint64_t)size); -    } -    else -    { -        packet_len = ::snprintf (packet, sizeof(packet), "m%" PRIx64 ",%" PRIx64, (uint64_t)addr, (uint64_t)size); -    } +    packet_len = ::snprintf(packet, sizeof(packet), "%c%" PRIx64 ",%" PRIx64, +                            binary_memory_read ? 'x' : 'm', (uint64_t)addr, (uint64_t)size);      assert (packet_len + 1 < (int)sizeof(packet));      StringExtractorGDBRemote response;      if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, true) == GDBRemoteCommunication::PacketResult::Success) @@ -2940,7 +3163,7 @@ ProcessGDBRemote::DoWriteMemory (addr_t addr, const void *buf, size_t size, Erro      StreamString packet;      packet.Printf("M%" PRIx64 ",%" PRIx64 ":", addr, (uint64_t)size); -    packet.PutBytesAsRawHex8(buf, size, lldb::endian::InlHostByteOrder(), lldb::endian::InlHostByteOrder()); +    packet.PutBytesAsRawHex8(buf, size, endian::InlHostByteOrder(), endian::InlHostByteOrder());      StringExtractorGDBRemote response;      if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, true) == GDBRemoteCommunication::PacketResult::Success)      { @@ -3377,6 +3600,27 @@ ProcessGDBRemote::DoSignal (int signo)  }  Error +ProcessGDBRemote::EstablishConnectionIfNeeded (const ProcessInfo &process_info) +{ +    // Make sure we aren't already connected? +    if (m_gdb_comm.IsConnected()) +        return Error(); + +    PlatformSP platform_sp (GetTarget ().GetPlatform ()); +    if (platform_sp && !platform_sp->IsHost ()) +        return Error("Lost debug server connection"); + +    auto error = LaunchAndConnectToDebugserver (process_info); +    if (error.Fail()) +    { +        const char *error_string = error.AsCString(); +        if (error_string == nullptr) +            error_string = "unable to launch " DEBUGSERVER_BASENAME; +    } +    return error; +} + +Error  ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info)  {      Error error; @@ -3401,14 +3645,22 @@ ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info          // Set hostname being NULL to do the reverse connect where debugserver          // will bind to port zero and it will communicate back to us the port          // that we will connect to -        const char *hostname = NULL; +        const char *hostname = nullptr;          uint16_t port = 0;  #endif -        error = m_gdb_comm.StartDebugserverProcess (hostname, -                                                    port, +        StreamString url_str; +        const char* url = nullptr; +        if (hostname != nullptr) +        { +            url_str.Printf("%s:%u", hostname, port); +            url = url_str.GetData(); +        } + +        error = m_gdb_comm.StartDebugserverProcess (url, +                                                    GetTarget().GetPlatform().get(),                                                      debugserver_launch_info, -                                                    port); +                                                    &port);          if (error.Success ())              m_debugserver_pid = debugserver_launch_info.GetProcessID(); @@ -3653,164 +3905,174 @@ ProcessGDBRemote::AsyncThread (void *arg)      if (log)          log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") thread starting...", __FUNCTION__, arg, process->GetID()); -    Listener listener ("ProcessGDBRemote::AsyncThread");      EventSP event_sp; -    const uint32_t desired_event_mask = eBroadcastBitAsyncContinue | -                                        eBroadcastBitAsyncThreadShouldExit; - -    if (listener.StartListeningForEvents (&process->m_async_broadcaster, desired_event_mask) == desired_event_mask) +    bool done = false; +    while (!done)      { -        listener.StartListeningForEvents (&process->m_gdb_comm, Communication::eBroadcastBitReadThreadDidExit | -                                                                GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify); - -        bool done = false; -        while (!done) +        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 (log) -                log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp)...", __FUNCTION__, arg, process->GetID()); -            if (listener.WaitForEvent (NULL, event_sp)) +            const uint32_t event_type = event_sp->GetType(); +            if (event_sp->BroadcasterIs (&process->m_async_broadcaster))              { -                const uint32_t event_type = event_sp->GetType(); -                if (event_sp->BroadcasterIs (&process->m_async_broadcaster)) +                if (log) +                    log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") Got an event of type: %d...", __FUNCTION__, arg, process->GetID(), event_type); + +                switch (event_type)                  { -                    if (log) -                        log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") Got an event of type: %d...", __FUNCTION__, arg, process->GetID(), event_type); +                    case eBroadcastBitAsyncContinue: +                        { +                            const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event_sp.get()); -                    switch (event_type) -                    { -                        case eBroadcastBitAsyncContinue: +                            if (continue_packet)                              { -                                const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event_sp.get()); +                                const char *continue_cstr = (const char *)continue_packet->GetBytes (); +                                const size_t continue_cstr_len = continue_packet->GetByteSize (); +                                if (log) +                                    log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got eBroadcastBitAsyncContinue: %s", __FUNCTION__, arg, process->GetID(), continue_cstr); -                                if (continue_packet) +                                if (::strstr (continue_cstr, "vAttach") == NULL) +                                    process->SetPrivateState(eStateRunning); +                                StringExtractorGDBRemote response; + +                                // If in Non-Stop-Mode +                                if (process->GetTarget().GetNonStopModeEnabled())                                  { -                                    const char *continue_cstr = (const char *)continue_packet->GetBytes (); -                                    const size_t continue_cstr_len = continue_packet->GetByteSize (); -                                    if (log) -                                        log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got eBroadcastBitAsyncContinue: %s", __FUNCTION__, arg, process->GetID(), continue_cstr); - -                                    if (::strstr (continue_cstr, "vAttach") == NULL) -                                        process->SetPrivateState(eStateRunning); -                                    StringExtractorGDBRemote response; -   -                                    // If in Non-Stop-Mode -                                    if (process->GetTarget().GetNonStopModeEnabled()) +                                    // send the vCont packet +                                    if (!process->GetGDBRemote().SendvContPacket(process, continue_cstr, continue_cstr_len, response))                                      { -                                        // send the vCont packet -                                        if (!process->GetGDBRemote().SendvContPacket(process, continue_cstr, continue_cstr_len, response)) -                                        { -                                            // Something went wrong -                                            done = true; -                                            break; -                                        } +                                        // Something went wrong +                                        done = true; +                                        break;                                      } -                                    // If in All-Stop-Mode -                                    else -                                    { -                                        StateType stop_state = process->GetGDBRemote().SendContinuePacketAndWaitForResponse (process, continue_cstr, continue_cstr_len, response); - -                                        // We need to immediately clear the thread ID list so we are sure to get a valid list of threads. -                                        // The thread ID list might be contained within the "response", or the stop reply packet that -                                        // caused the stop. So clear it now before we give the stop reply packet to the process -                                        // using the process->SetLastStopPacket()... -                                        process->ClearThreadIDList (); +                                } +                                // If in All-Stop-Mode +                                else +                                { +                                    StateType stop_state = process->GetGDBRemote().SendContinuePacketAndWaitForResponse (process, continue_cstr, continue_cstr_len, response); -                                        switch (stop_state) -                                        { -                                        case eStateStopped: -                                        case eStateCrashed: -                                        case eStateSuspended: -                                            process->SetLastStopPacket (response); -                                            process->SetPrivateState (stop_state); -                                            break; +                                    // We need to immediately clear the thread ID list so we are sure to get a valid list of threads. +                                    // The thread ID list might be contained within the "response", or the stop reply packet that +                                    // caused the stop. So clear it now before we give the stop reply packet to the process +                                    // using the process->SetLastStopPacket()... +                                    process->ClearThreadIDList (); -                                        case eStateExited: +                                    switch (stop_state) +                                    { +                                    case eStateStopped: +                                    case eStateCrashed: +                                    case eStateSuspended: +                                        process->SetLastStopPacket (response); +                                        process->SetPrivateState (stop_state); +                                        break; + +                                    case eStateExited: +                                    { +                                        process->SetLastStopPacket (response); +                                        process->ClearThreadIDList(); +                                        response.SetFilePos(1); +                                         +                                        int exit_status = response.GetHexU8(); +                                        const char *desc_cstr = NULL; +                                        StringExtractor extractor; +                                        std::string desc_string; +                                        if (response.GetBytesLeft() > 0 && response.GetChar('-') == ';')                                          { -                                            process->SetLastStopPacket (response); -                                            process->ClearThreadIDList(); -                                            response.SetFilePos(1); -                                             -                                            int exit_status = response.GetHexU8(); -                                            const char *desc_cstr = NULL; -                                            StringExtractor extractor; -                                            std::string desc_string; -                                            if (response.GetBytesLeft() > 0 && response.GetChar('-') == ';') +                                            std::string desc_token; +                                            while (response.GetNameColonValue (desc_token, desc_string))                                              { -                                                std::string desc_token; -                                                while (response.GetNameColonValue (desc_token, desc_string)) +                                                if (desc_token == "description")                                                  { -                                                    if (desc_token == "description") -                                                    { -                                                        extractor.GetStringRef().swap(desc_string); -                                                        extractor.SetFilePos(0); -                                                        extractor.GetHexByteString (desc_string); -                                                        desc_cstr = desc_string.c_str(); -                                                    } +                                                    extractor.GetStringRef().swap(desc_string); +                                                    extractor.SetFilePos(0); +                                                    extractor.GetHexByteString (desc_string); +                                                    desc_cstr = desc_string.c_str();                                                  }                                              } -                                            process->SetExitStatus(exit_status, desc_cstr); -                                            done = true; -                                            break;                                          } -                                        case eStateInvalid: +                                        process->SetExitStatus(exit_status, desc_cstr); +                                        done = true; +                                        break; +                                    } +                                    case eStateInvalid: +                                    { +                                        // Check to see if we were trying to attach and if we got back +                                        // the "E87" error code from debugserver -- this indicates that +                                        // the process is not debuggable.  Return a slightly more helpful +                                        // error message about why the attach failed. +                                        if (::strstr (continue_cstr, "vAttach") != NULL +                                            && response.GetError() == 0x87) +                                        { +                                            process->SetExitStatus(-1, "cannot attach to process due to System Integrity Protection"); +                                        } +                                        // E01 code from vAttach means that the attach failed +                                        if (::strstr (continue_cstr, "vAttach") != NULL +                                            && response.GetError() == 0x1) +                                        { +                                            process->SetExitStatus(-1, "unable to attach"); +                                        } +                                        else +                                        {                                              process->SetExitStatus(-1, "lost connection"); +                                        }                                              break; +                                    } -                                        default: -                                            process->SetPrivateState (stop_state); -                                            break; -                                        } // switch(stop_state) -                                    } // else // if in All-stop-mode -                                } // if (continue_packet) -                            } // case eBroadcastBitAysncContinue -                            break; +                                    default: +                                        process->SetPrivateState (stop_state); +                                        break; +                                    } // switch(stop_state) +                                } // else // if in All-stop-mode +                            } // if (continue_packet) +                        } // case eBroadcastBitAysncContinue +                        break; -                        case eBroadcastBitAsyncThreadShouldExit: -                            if (log) -                                log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got eBroadcastBitAsyncThreadShouldExit...", __FUNCTION__, arg, process->GetID()); -                            done = true; -                            break; +                    case eBroadcastBitAsyncThreadShouldExit: +                        if (log) +                            log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got eBroadcastBitAsyncThreadShouldExit...", __FUNCTION__, arg, process->GetID()); +                        done = true; +                        break; -                        default: -                            if (log) -                                log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type); -                            done = true; -                            break; -                    } +                    default: +                        if (log) +                            log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type); +                        done = true; +                        break;                  } -                else if (event_sp->BroadcasterIs (&process->m_gdb_comm)) +            } +            else if (event_sp->BroadcasterIs (&process->m_gdb_comm)) +            { +                switch (event_type)                  { -                    switch (event_type) -                    { -                        case Communication::eBroadcastBitReadThreadDidExit: -                            process->SetExitStatus (-1, "lost connection"); -                            done = true; -                            break; - -                        case GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify: -                        { -                            lldb_private::Event *event = event_sp.get(); -                            const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event); -                            StringExtractorGDBRemote notify((const char*)continue_packet->GetBytes()); -                            // Hand this over to the process to handle -                            process->HandleNotifyPacket(notify); -                            break; -                        } +                    case Communication::eBroadcastBitReadThreadDidExit: +                        process->SetExitStatus (-1, "lost connection"); +                        done = true; +                        break; -                        default: -                            if (log) -                                log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type); -                            done = true; -                            break; +                    case GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify: +                    { +                        lldb_private::Event *event = event_sp.get(); +                        const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event); +                        StringExtractorGDBRemote notify((const char*)continue_packet->GetBytes()); +                        // Hand this over to the process to handle +                        process->HandleNotifyPacket(notify); +                        break;                      } + +                    default: +                        if (log) +                            log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type); +                        done = true; +                        break;                  }              } -            else -            { -                if (log) -                    log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp) => false", __FUNCTION__, arg, process->GetID()); -                done = true; -            } +        } +        else +        { +            if (log) +                log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp) => false", __FUNCTION__, arg, process->GetID()); +            done = true;          }      } @@ -3864,10 +4126,10 @@ ProcessGDBRemote::StartNoticingNewThreads()      }      else      { -        PlatformSP platform_sp (m_target.GetPlatform()); +        PlatformSP platform_sp (GetTarget().GetPlatform());          if (platform_sp)          { -            m_thread_create_bp_sp = platform_sp->SetThreadCreationBreakpoint(m_target); +            m_thread_create_bp_sp = platform_sp->SetThreadCreationBreakpoint(GetTarget());              if (m_thread_create_bp_sp)              {                  if (log && log->GetVerbose()) @@ -3986,6 +4248,9 @@ ProcessGDBRemote::GetLoadedDynamicLibrariesInfos (lldb::addr_t image_list_addres      if (m_gdb_comm.GetLoadedDynamicLibrariesInfosSupported())      { +        // Scope for the scoped timeout object +        GDBRemoteCommunication::ScopedTimeout timeout (m_gdb_comm, 10); +          StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());          args_dict->GetAsDictionary()->AddIntegerItem ("image_list_address", image_list_address);          args_dict->GetAsDictionary()->AddIntegerItem ("image_count", image_count); @@ -4009,8 +4274,6 @@ ProcessGDBRemote::GetLoadedDynamicLibrariesInfos (lldb::addr_t image_list_addres              {                  if (!response.Empty())                  { -                    // The packet has already had the 0x7d xor quoting stripped out at the -                    // GDBRemoteCommunication packet receive level.                      object_sp = StructuredData::ParseJSON (response.GetStringRef());                  }              } @@ -4019,7 +4282,6 @@ ProcessGDBRemote::GetLoadedDynamicLibrariesInfos (lldb::addr_t image_list_addres      return object_sp;  } -  // Establish the largest memory read/write payloads we should use.  // If the remote stub has a max packet size, stay under that size.  //  @@ -4113,6 +4375,18 @@ ProcessGDBRemote::GetModuleSpec(const FileSpec& module_file_spec,      return true;  } +bool +ProcessGDBRemote::GetHostOSVersion(uint32_t &major, +                                   uint32_t &minor, +                                   uint32_t &update) +{ +    if (m_gdb_comm.GetOSVersion(major, minor, update)) +        return true; +    // We failed to get the host OS version, defer to the base +    // implementation to correctly invalidate the arguments. +    return Process::GetHostOSVersion(major, minor, update); +} +  namespace {  typedef std::vector<std::string> stringVec; @@ -4135,15 +4409,15 @@ struct GdbServerTargetInfo  };  bool -ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemoteDynamicRegisterInfo &dyn_reg_info) +ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemoteDynamicRegisterInfo &dyn_reg_info, ABISP abi_sp)  {      if (!feature_node)          return false; -    uint32_t prev_reg_num = 0; +    uint32_t cur_reg_num = 0;      uint32_t reg_offset = 0; -    feature_node.ForEachChildElementWithName("reg", [&target_info, &dyn_reg_info, &prev_reg_num, ®_offset](const XMLNode ®_node) -> bool { +    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;          ConstString reg_name; @@ -4158,19 +4432,19 @@ ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemot              0,                    // byte size              reg_offset,           // offset              eEncodingUint,        // encoding -            eFormatHex,           // formate +            eFormatHex,           // format              { -                LLDB_INVALID_REGNUM, // GCC reg num +                LLDB_INVALID_REGNUM, // eh_frame reg num                  LLDB_INVALID_REGNUM, // DWARF reg num                  LLDB_INVALID_REGNUM, // generic reg num -                prev_reg_num,        // GDB reg num -                prev_reg_num         // native register number +                cur_reg_num,        // process plugin reg num +                cur_reg_num         // native register number              },              NULL,              NULL          }; -        reg_node.ForEachAttribute([&target_info, &gdb_group, &gdb_type, ®_name, &alt_name, &set_name, &value_regs, &invalidate_regs, &encoding_set, &format_set, ®_info, &prev_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](const llvm::StringRef &name, const llvm::StringRef &value) -> bool {              if (name == "name")              {                  reg_name.SetString(value); @@ -4192,9 +4466,7 @@ ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemot                  const uint32_t regnum = StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0);                  if (regnum != LLDB_INVALID_REGNUM)                  { -                    reg_info.kinds[eRegisterKindGDB] = regnum; -                    reg_info.kinds[eRegisterKindLLDB] = regnum; -                    prev_reg_num = regnum; +                    reg_info.kinds[eRegisterKindProcessPlugin] = regnum;                  }              }              else if (name == "offset") @@ -4240,9 +4512,9 @@ ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemot                  if (pos != target_info.reg_set_map.end())                      set_name = pos->second.name;              } -            else if (name == "gcc_regnum") +            else if (name == "gcc_regnum" || name == "ehframe_regnum")              { -                reg_info.kinds[eRegisterKindGCC] = StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0); +                reg_info.kinds[eRegisterKindEHFrame] = StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0);              }              else if (name == "dwarf_regnum")              { @@ -4305,7 +4577,8 @@ ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemot              reg_info.invalidate_regs = invalidate_regs.data();          } -        ++prev_reg_num; +        ++cur_reg_num; +        AugmentRegisterInfoViaABI (reg_info, reg_name, abi_sp);          dyn_reg_info.AddRegister(reg_info, reg_name, alt_name, set_name);          return true; // Keep iterating through all "reg" elements @@ -4401,7 +4674,7 @@ ProcessGDBRemote::GetGDBServerRegisterInfo ()              if (feature_node)              { -                ParseRegisters(feature_node, target_info, this->m_register_info); +                ParseRegisters(feature_node, target_info, this->m_register_info, GetABI());              }              for (const auto &include : target_info.includes) @@ -4419,7 +4692,7 @@ 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); +                    ParseRegisters(include_feature_node, target_info, this->m_register_info, GetABI());                  }              }              this->m_register_info.Finalize(GetTarget().GetArchitecture()); @@ -4489,7 +4762,8 @@ ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList & list)                  {                      // the displacement as read from the field 'l_addr' of the link_map struct.                      module.set_base(StringConvert::ToUInt64(value.data(), LLDB_INVALID_ADDRESS, 0)); -                     +                    // base address is always a displacement, not an absolute value. +                    module.set_base_is_offset(true);                  }                  else if (name == "l_ld")                  { @@ -4504,13 +4778,15 @@ ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList & list)              {                  std::string name;                  lldb::addr_t lm=0, base=0, ld=0; +                bool base_is_offset;                  module.get_name (name);                  module.get_link_map (lm);                  module.get_base (base); +                module.get_base_is_offset (base_is_offset);                  module.get_dynamic (ld); -                log->Printf ("found (link_map:0x08%" PRIx64 ", base:0x08%" PRIx64 ", ld:0x08%" PRIx64 ", name:'%s')", lm, base, ld, name.c_str()); +                log->Printf ("found (link_map:0x%08" PRIx64 ", base:0x%08" PRIx64 "[%s], ld:0x%08" PRIx64 ", name:'%s')", lm, base, (base_is_offset ? "offset" : "absolute"), ld, name.c_str());              }              list.add (module); @@ -4552,15 +4828,19 @@ ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList & list)              const XMLNode §ion = library.FindFirstChildElementWithName("section");              llvm::StringRef address = section.GetAttributeValue("address");              module.set_base(StringConvert::ToUInt64(address.data(), LLDB_INVALID_ADDRESS, 0)); +            // These addresses are absolute values. +            module.set_base_is_offset(false);              if (log)              {                  std::string name;                  lldb::addr_t base = 0; +                bool base_is_offset;                  module.get_name (name);                  module.get_base (base); +                module.get_base_is_offset (base_is_offset); -                log->Printf ("found (base:0x%" PRIx64 ", name:'%s')", base, name.c_str()); +                log->Printf ("found (base:0x%08" PRIx64 "[%s], name:'%s')", base, (base_is_offset ? "offset" : "absolute"), name.c_str());              }              list.add (module); @@ -4577,7 +4857,7 @@ ProcessGDBRemote::GetLoadedModuleList (GDBLoadedModuleInfoList & list)  }  lldb::ModuleSP -ProcessGDBRemote::LoadModuleAtAddress (const FileSpec &file, lldb::addr_t base_addr) +ProcessGDBRemote::LoadModuleAtAddress (const FileSpec &file, lldb::addr_t base_addr, bool value_is_offset)  {      Target &target = m_process->GetTarget();      ModuleList &modules = target.GetImages(); @@ -4588,11 +4868,11 @@ ProcessGDBRemote::LoadModuleAtAddress (const FileSpec &file, lldb::addr_t base_a      ModuleSpec module_spec (file, target.GetArchitecture());      if ((module_sp = modules.FindFirstModule (module_spec)))      { -        module_sp->SetLoadAddress (target, base_addr, true, changed); +        module_sp->SetLoadAddress (target, base_addr, value_is_offset, changed);      }      else if ((module_sp = target.GetSharedModule (module_spec)))      { -        module_sp->SetLoadAddress (target, base_addr, true, changed); +        module_sp->SetLoadAddress (target, base_addr, value_is_offset, changed);      }      return module_sp; @@ -4615,10 +4895,12 @@ ProcessGDBRemote::LoadModules ()      {          std::string  mod_name;          lldb::addr_t mod_base; +        bool         mod_base_is_offset;          bool valid = true;          valid &= modInfo.get_name (mod_name);          valid &= modInfo.get_base (mod_base); +        valid &= modInfo.get_base_is_offset (mod_base_is_offset);          if (!valid)              continue; @@ -4630,7 +4912,7 @@ ProcessGDBRemote::LoadModules ()              marker += 1;          FileSpec file (mod_name.c_str()+marker, true); -        lldb::ModuleSP module_sp = LoadModuleAtAddress (file, mod_base); +        lldb::ModuleSP module_sp = LoadModuleAtAddress (file, mod_base, mod_base_is_offset);          if (module_sp.get())              new_modules.Append (module_sp); @@ -4638,7 +4920,7 @@ ProcessGDBRemote::LoadModules ()      if (new_modules.GetSize() > 0)      { -        Target & target = m_target; +        Target &target = GetTarget();          new_modules.ForEach ([&target](const lldb::ModuleSP module_sp) -> bool          { diff --git a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index 45c74ea64ee50..54749827d6ac6 100644 --- a/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -11,12 +11,14 @@  #define liblldb_ProcessGDBRemote_h_  // C Includes -  // C++ Includes -#include <list> +#include <atomic> +#include <map> +#include <string>  #include <vector>  // Other libraries and framework includes +// Project includes  #include "lldb/Core/ArchSpec.h"  #include "lldb/Core/Broadcaster.h"  #include "lldb/Core/ConstString.h" @@ -42,11 +44,12 @@ class ThreadGDBRemote;  class ProcessGDBRemote : public Process  {  public: -    //------------------------------------------------------------------ -    // Constructors and Destructors -    //------------------------------------------------------------------ +    ProcessGDBRemote(lldb::TargetSP target_sp, Listener &listener); + +    ~ProcessGDBRemote() override; +      static lldb::ProcessSP -    CreateInstance (Target& target,  +    CreateInstance (lldb::TargetSP target_sp,                      Listener &listener,                      const FileSpec *crash_file_path); @@ -66,18 +69,10 @@ public:      GetPluginDescriptionStatic();      //------------------------------------------------------------------ -    // Constructors and Destructors -    //------------------------------------------------------------------ -    ProcessGDBRemote(Target& target, Listener &listener); - -    virtual -    ~ProcessGDBRemote(); - -    //------------------------------------------------------------------      // Check if a given Process      //------------------------------------------------------------------      bool -    CanDebug (Target &target, bool plugin_specified_by_name) override; +    CanDebug (lldb::TargetSP target_sp, bool plugin_specified_by_name) override;      CommandObject *      GetPluginCommandObject() override; @@ -152,6 +147,9 @@ public:      void      RefreshStateAfterStop() override; +    void +    SetUnixSignals(const lldb::UnixSignalsSP &signals_sp); +      //------------------------------------------------------------------      // Process Queries      //------------------------------------------------------------------ @@ -161,6 +159,9 @@ public:      lldb::addr_t      GetImageInfoAddress() override; +    void +    WillPublicStop () override; +      //------------------------------------------------------------------      // Process Memory      //------------------------------------------------------------------ @@ -238,6 +239,11 @@ public:                    const ArchSpec& arch,                    ModuleSpec &module_spec) override; +    bool +    GetHostOSVersion(uint32_t &major, +                     uint32_t &minor, +                     uint32_t &update) override; +      size_t      LoadModules() override; @@ -257,20 +263,63 @@ protected:      class GDBLoadedModuleInfoList; +    //------------------------------------------------------------------ +    /// Broadcaster event bits definitions. +    //------------------------------------------------------------------ +    enum +    { +        eBroadcastBitAsyncContinue                  = (1 << 0), +        eBroadcastBitAsyncThreadShouldExit          = (1 << 1), +        eBroadcastBitAsyncThreadDidExit             = (1 << 2) +    }; +     +    Flags m_flags;            // Process specific flags (see eFlags enums) +    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; +    GDBRemoteDynamicRegisterInfo m_register_info; +    Broadcaster m_async_broadcaster; +    Listener m_async_listener; +    HostThread m_async_thread; +    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; +    typedef std::map<uint32_t, std::string> ExpeditedRegisterMap; +    tid_collection m_thread_ids; // Thread IDs for all threads. This list gets updated after stopping +    std::vector<lldb::addr_t> m_thread_pcs; // PC values for all the threads. +    StructuredData::ObjectSP m_jstopinfo_sp; // Stop info only for any threads that have valid stop infos +    StructuredData::ObjectSP m_jthreadsinfo_sp; // Full stop info, expedited registers and memory for all threads if "jThreadsInfo" packet is supported +    tid_collection m_continue_c_tids;                  // 'c' for continue +    tid_sig_collection m_continue_C_tids; // 'C' for continue with signal +    tid_collection m_continue_s_tids;                  // 's' for step +    tid_sig_collection m_continue_S_tids; // 'S' for step with signal +    uint64_t m_max_memory_size;       // The maximum number of bytes to read/write when reading and writing memory +    uint64_t m_remote_stub_max_memory_size;    // The maximum memory size the remote gdb stub can handle +    MMapMap m_addr_to_mmap_size; +    lldb::BreakpointSP m_thread_create_bp_sp; +    bool m_waiting_for_attach; +    bool m_destroy_tried_resuming; +    lldb::CommandObjectSP m_command_sp; +    int64_t m_breakpoint_pc_offset; +    lldb::tid_t m_initial_tid; // The initial thread ID, given by stub on attach +      //----------------------------------------------------------------------      // Accessors      //----------------------------------------------------------------------      bool      IsRunning ( lldb::StateType state )      { -        return    state == lldb::eStateRunning || IsStepping(state); +        return state == lldb::eStateRunning || IsStepping(state);      }      bool      IsStepping ( lldb::StateType state)      { -        return    state == lldb::eStateStepping; +        return state == lldb::eStateStepping;      } +      bool      CanResume ( lldb::StateType state)      { @@ -306,6 +355,9 @@ protected:                        ThreadList &new_thread_list) override;      Error +    EstablishConnectionIfNeeded (const ProcessInfo &process_info); + +    Error      LaunchAndConnectToDebugserver (const ProcessInfo &process_info);      void @@ -333,46 +385,10 @@ protected:      CalculateThreadStopInfo (ThreadGDBRemote *thread);      size_t -    UpdateThreadIDsFromStopReplyThreadsValue (std::string &value); +    UpdateThreadPCsFromStopReplyThreadsValue (std::string &value); -    //------------------------------------------------------------------ -    /// Broadcaster event bits definitions. -    //------------------------------------------------------------------ -    enum -    { -        eBroadcastBitAsyncContinue                  = (1 << 0), -        eBroadcastBitAsyncThreadShouldExit          = (1 << 1), -        eBroadcastBitAsyncThreadDidExit             = (1 << 2) -    }; -     -    Flags m_flags;            // Process specific flags (see eFlags enums) -    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; -    GDBRemoteDynamicRegisterInfo m_register_info; -    Broadcaster m_async_broadcaster; -    HostThread m_async_thread; -    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; -    typedef std::map<uint32_t, std::string> ExpeditedRegisterMap; -    tid_collection m_thread_ids; // Thread IDs for all threads. This list gets updated after stopping -    StructuredData::ObjectSP m_threads_info_sp; // Stop info for all threads if "jThreadsInfo" packet is supported -    tid_collection m_continue_c_tids;                  // 'c' for continue -    tid_sig_collection m_continue_C_tids; // 'C' for continue with signal -    tid_collection m_continue_s_tids;                  // 's' for step -    tid_sig_collection m_continue_S_tids; // 'S' for step with signal -    uint64_t m_max_memory_size;       // The maximum number of bytes to read/write when reading and writing memory -    uint64_t m_remote_stub_max_memory_size;    // The maximum memory size the remote gdb stub can handle -    MMapMap m_addr_to_mmap_size; -    lldb::BreakpointSP m_thread_create_bp_sp; -    bool m_waiting_for_attach; -    bool m_destroy_tried_resuming; -    lldb::CommandObjectSP m_command_sp; -    int64_t m_breakpoint_pc_offset; -    lldb::tid_t m_initial_tid; // The inital thread ID, given by stub on attach +    size_t +    UpdateThreadIDsFromStopReplyThreadsValue (std::string &value);      bool      HandleNotifyPacket(StringExtractorGDBRemote &packet); @@ -396,7 +412,10 @@ protected:      lldb::StateType      SetThreadStopInfo (StringExtractor& stop_packet); -    lldb::StateType +    bool +    GetThreadStopInfoFromJSON (ThreadGDBRemote *thread, const StructuredData::ObjectSP &thread_infos_sp); + +    lldb::ThreadSP      SetThreadStopInfo (StructuredData::Dictionary *thread_dict);      lldb::ThreadSP @@ -445,7 +464,7 @@ protected:      GetLoadedModuleList (GDBLoadedModuleInfoList &);      lldb::ModuleSP -    LoadModuleAtAddress (const FileSpec &file, lldb::addr_t base_addr); +    LoadModuleAtAddress (const FileSpec &file, lldb::addr_t base_addr, bool value_is_offset);  private:      //------------------------------------------------------------------ @@ -458,10 +477,9 @@ private:                           lldb::user_id_t break_loc_id);      DISALLOW_COPY_AND_ASSIGN (ProcessGDBRemote); -  };  } // namespace process_gdb_remote  } // namespace lldb_private -#endif  // liblldb_ProcessGDBRemote_h_ +#endif // liblldb_ProcessGDBRemote_h_ diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp index d2a6503caf8e0..9b410d8b5b8c2 100644 --- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp +++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp @@ -313,6 +313,14 @@ ThreadGDBRemote::PrivateSetRegisterValue (uint32_t reg, StringExtractor &respons  }  bool +ThreadGDBRemote::PrivateSetRegisterValue (uint32_t reg, uint64_t regval) +{ +    GDBRemoteRegisterContext *gdb_reg_ctx = static_cast<GDBRemoteRegisterContext *>(GetRegisterContext ().get()); +    assert (gdb_reg_ctx); +    return gdb_reg_ctx->PrivateSetRegisterValue (reg, regval); +} + +bool  ThreadGDBRemote::CalculateStopInfo ()  {      ProcessSP process_sp (GetProcess()); diff --git a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h index 175433a3e20c1..24693ba891ccb 100644 --- a/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h +++ b/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h @@ -10,8 +10,12 @@  #ifndef liblldb_ThreadGDBRemote_h_  #define liblldb_ThreadGDBRemote_h_ +// C Includes +// C++ Includes  #include <string> +// Other libraries and framework includes +// Project includes  #include "lldb/Core/StructuredData.h"  #include "lldb/Target/Process.h"  #include "lldb/Target/Thread.h" @@ -28,8 +32,7 @@ class ThreadGDBRemote : public Thread  public:      ThreadGDBRemote (Process &process, lldb::tid_t tid); -    virtual -    ~ThreadGDBRemote (); +    ~ThreadGDBRemote() override;      void      WillResume (lldb::StateType resume_state) override; @@ -101,30 +104,27 @@ public:      FetchThreadExtendedInfo () override;  protected: -          friend class ProcessGDBRemote; +    std::string m_thread_name; +    std::string m_dispatch_queue_name; +    lldb::addr_t m_thread_dispatch_qaddr; +    lldb::QueueKind m_queue_kind;     // Queue info from stop reply/stop info for thread +    uint64_t m_queue_serial;    // Queue info from stop reply/stop info for thread +      bool      PrivateSetRegisterValue (uint32_t reg,                                StringExtractor &response);      bool +    PrivateSetRegisterValue (uint32_t reg,  +                             uint64_t regval); + +    bool      CachedQueueInfoIsValid() const      {          return m_queue_kind != lldb::eQueueKindUnknown;      } -    //------------------------------------------------------------------ -    // Member variables. -    //------------------------------------------------------------------ -    std::string m_thread_name; -    std::string m_dispatch_queue_name; -    lldb::addr_t m_thread_dispatch_qaddr; -    lldb::QueueKind m_queue_kind;     // Queue info from stop reply/stop info for thread -    uint64_t m_queue_serial;    // Queue info from stop reply/stop info for thread -    //------------------------------------------------------------------ -    // Member variables. -    //------------------------------------------------------------------ -      void      SetStopInfoFromPacket (StringExtractor &stop_packet, uint32_t stop_id); @@ -135,4 +135,4 @@ protected:  } // namespace process_gdb_remote  } // namespace lldb_private -#endif  // liblldb_ThreadGDBRemote_h_ +#endif // liblldb_ThreadGDBRemote_h_ | 
