@@ -3684,31 +3684,17 @@ static char *pack_threadlist_request (char *pkt, int startflag,
static int remote_newthread_step (threadref *ref, void *context);
-/* Write a PTID to BUF. ENDBUF points to one-passed-the-end of the
+/* Write a PTID to BUF. ENDBUF points to one-past-the-end of the
buffer we're allowed to write to. Returns
BUF+CHARACTERS_WRITTEN. */
char *
remote_target::write_ptid (char *buf, const char *endbuf, ptid_t ptid)
{
- ptid_t::pid_type pid;
- ptid_t::lwp_type lwp;
-
- if (m_features.remote_multi_process_p ())
- {
- pid = ptid.pid ();
- if (pid < 0)
- buf += xsnprintf (buf, endbuf - buf, "p-%x.", -pid);
- else
- buf += xsnprintf (buf, endbuf - buf, "p%x.", pid);
- }
- lwp = ptid.lwp ();
- if (lwp < 0)
- buf += xsnprintf (buf, endbuf - buf, "-%lx", -lwp);
- else
- buf += xsnprintf (buf, endbuf - buf, "%lx", lwp);
-
- return buf;
+ std::string repr = ptid.to_rsp_string (m_features.remote_multi_process_p ());
+ gdb_assert (repr.length () < endbuf - buf);
+ strcpy (buf, repr.c_str ());
+ return buf + repr.length ();
}
/* Extract a PTID from BUF. If non-null, OBUF is set to one past the
@@ -3718,67 +3704,21 @@ remote_target::write_ptid (char *buf, const char *endbuf, ptid_t ptid)
static ptid_t
read_ptid (const char *buf, const char **obuf)
{
- const char *p = buf;
- const char *pp;
- ptid_t::pid_type pid = 0;
- ptid_t::lwp_type lwp = 0;
- ULONGEST hex;
-
- if (*p == 'p')
- {
- /* Multi-process ptid. */
- pp = unpack_varlen_hex (p + 1, &hex);
- if ((pp == (p + 1)) || (*pp != '.'))
- error (_("invalid remote ptid: %s"), buf);
-
- pid = (ptid_t::pid_type) (LONGEST) hex;
- if (hex != ((ULONGEST) pid))
- error (_("invalid remote ptid: %s"), buf);
-
- p = pp + 1;
- pp = unpack_varlen_hex (p, &hex);
- if (pp == p)
- error (_("invalid remote ptid: %s"), buf);
-
- lwp = (ptid_t::lwp_type) (LONGEST) hex;
- if (hex != ((ULONGEST) lwp))
- error (_("invalid remote ptid: %s"), buf);
-
- if (obuf)
- *obuf = pp;
-
- return ptid_t (pid, lwp);
- }
-
- /* No multi-process. Just a thread id. */
- pp = unpack_varlen_hex (p, &hex);
-
- /* Return null_ptid when no thread id is found. */
- if (p == pp)
- {
- if (obuf)
- *obuf = pp;
- return null_ptid;
- }
-
- lwp = (ptid_t::lwp_type) (LONGEST) hex;
- if (hex != ((ULONGEST) lwp))
- error (_("invalid remote ptid: %s"), buf);
-
- /* Since the stub is not sending a process id, default to what's
- current_inferior, unless it doesn't have a PID yet. If so,
- then since there's no way to know the pid of the reported
- threads, use the magic number. */
- inferior *inf = current_inferior ();
- if (inf->pid == 0)
- pid = magic_null_ptid.pid ();
- else
- pid = inf->pid;
-
- if (obuf)
- *obuf = pp;
-
- return ptid_t (pid, lwp);
+ return ptid_t::parse (buf, obuf, false,
+ [] ()
+ {
+ /* Since the stub is not sending a process id, default to
+ what's current_inferior, unless it doesn't have a PID yet.
+ If so, then since there's no way to know the pid of the
+ reported threads, use the magic number. */
+ inferior *inf = current_inferior ();
+ ptid_t::pid_type pid;
+ if (inf->pid == 0)
+ pid = magic_null_ptid.pid ();
+ else
+ pid = inf->pid;
+ return pid;
+ });
}
static int
@@ -18,6 +18,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "gdbsupport/ptid.h"
+#include "gdbsupport/selftest.h"
#include <type_traits>
namespace selftests {
@@ -149,6 +150,51 @@ static_assert (both.matches (both), "both matches both");
static_assert (!ptid_t (2, 2, 2).matches (both),
"other both doesn't match both");
+/* Helper function to parse and return a single PTID. */
+static ptid_t
+parse_one (const char *str, bool for_remote)
+{
+ const char *out;
+ ptid_t result = ptid_t::parse (str, &out, for_remote,
+ [] ()
+ {
+ return ptid_t::pid_type (23);
+ });
+ SELF_CHECK (*out == '\0');
+ return result;
+}
+
+/* Test ptid_t reading and writing. */
+static void
+test ()
+{
+ SELF_CHECK (minus_one_ptid.to_rsp_string (false) == "0");
+ SELF_CHECK (minus_one_ptid.to_rsp_string (true) == "p-1.0");
+
+ SELF_CHECK (lwp.to_rsp_string (false) == "2");
+ SELF_CHECK (lwp.to_rsp_string (true) == "p1.2");
+
+ ptid_t negative (-57, -32);
+ /* This is kind of lame but currently the types are host-dependent
+ so we have to adapt to those here. */
+ std::string the_pid = string_printf ("%x", (unsigned) -57);
+ std::string the_lwp = string_printf ("%lx", (unsigned long) -32);
+ std::string full = "p" + the_pid + "." + the_lwp;
+ SELF_CHECK (negative.to_rsp_string (false) == the_lwp);
+ SELF_CHECK (negative.to_rsp_string (true) == full);
+
+ SELF_CHECK (parse_one ("p1.2", false) == lwp);
+ SELF_CHECK (parse_one ("p1.-1", true) == ptid_t (1, -1));
+ SELF_CHECK (parse_one ("-1", true) == minus_one_ptid);
+ SELF_CHECK (parse_one ("0", false) == null_ptid);
+ SELF_CHECK (parse_one (full.c_str (), false) == negative);
+ SELF_CHECK (parse_one (full.c_str (), true) == negative);
+}
} /* namespace ptid */
} /* namespace selftests */
+
+INIT_GDB_FILE (ptid_selftests)
+{
+ selftests::register_test ("ptid_t", selftests::ptid::test);
+}
@@ -519,43 +519,9 @@ char *
write_ptid (char *buf, ptid_t ptid)
{
client_state &cs = get_client_state ();
- ptid_t::pid_type pid;
- ptid_t::lwp_type lwp;
-
- if (cs.multi_process)
- {
- pid = ptid.pid ();
- if (pid < 0)
- buf += sprintf (buf, "p-%x.", -pid);
- else
- buf += sprintf (buf, "p%x.", pid);
- }
- lwp = ptid.lwp ();
- if (lwp < 0)
- buf += sprintf (buf, "-%lx", -lwp);
- else
- buf += sprintf (buf, "%lx", lwp);
-
- return buf;
-}
-
-static ULONGEST
-hex_or_minus_one (const char *buf, const char **obuf)
-{
- ULONGEST ret;
-
- if (startswith (buf, "-1"))
- {
- ret = (ULONGEST) -1;
- buf += 2;
- }
- else
- buf = unpack_varlen_hex (buf, &ret);
-
- if (obuf)
- *obuf = buf;
-
- return ret;
+ std::string repr = ptid.to_rsp_string (cs.multi_process);
+ strcpy (buf, repr.c_str ());
+ return buf + repr.length ();
}
/* Extract a PTID from BUF. If non-null, OBUF is set to one past the last
@@ -563,61 +529,14 @@ hex_or_minus_one (const char *buf, const char **obuf)
ptid_t
read_ptid (const char *buf, const char **obuf)
{
- const char *p = buf;
- const char *pp;
- ptid_t::pid_type pid = 0;
- ptid_t::lwp_type lwp = 0;
- ULONGEST hex;
-
- if (*p == 'p')
- {
- /* Multi-process ptid. */
- pp = unpack_varlen_hex (p + 1, &hex);
- if (pp == (p + 1) || *pp != '.')
- error ("invalid remote ptid: %s\n", buf);
-
- pid = (ptid_t::pid_type) (LONGEST) hex;
- if (hex != ((ULONGEST) pid))
- error (_("invalid remote ptid: %s"), buf);
-
- p = pp + 1;
- hex = hex_or_minus_one (p, &pp);
- if (pp == p)
- error ("invalid remote ptid: %s\n", buf);
-
- lwp = (ptid_t::lwp_type) (LONGEST) hex;
- if (hex != ((ULONGEST) lwp))
- error (_("invalid remote ptid: %s"), buf);
-
- if (obuf)
- *obuf = pp;
-
- return ptid_t (pid, lwp);
- }
-
- /* No multi-process. Just a thread id. */
- hex = hex_or_minus_one (p, &pp);
-
- /* Handle special thread ids. */
- if (hex == (ULONGEST) -1)
- return minus_one_ptid;
-
- if (hex == 0)
- return null_ptid;
-
- lwp = (ptid_t::lwp_type) (LONGEST) hex;
- if (hex != ((ULONGEST) lwp))
- error (_("invalid remote ptid: %s"), buf);
-
- /* Since GDB is not sending a process id (multi-process extensions
- are off), then there's only one process. Default to the first in
- the list. */
- pid = get_first_process ()->pid;
-
- if (obuf)
- *obuf = pp;
-
- return ptid_t (pid, lwp);
+ return ptid_t::parse (buf, obuf, true,
+ [] ()
+ {
+ /* Since GDB is not sending a process id (multi-process
+ extensions are off), then there's only one process.
+ Default to the first in the list. */
+ return get_first_process ()->pid;
+ });
}
/* Write COUNT bytes in BUF to the client. Returns true if all bytes
@@ -19,6 +19,7 @@
#include "ptid.h"
#include "print-utils.h"
+#include "rsp-low.h"
/* See ptid.h for these. */
@@ -27,8 +28,114 @@ ptid_t const minus_one_ptid = ptid_t::make_minus_one ();
/* See ptid.h. */
+std::string
+ptid_t::to_rsp_string (bool multi) const
+{
+ char result[50];
+ char *buf = result;
+ char *endbuf = &result[sizeof (result)];
+
+ if (multi)
+ {
+ if (m_pid == -1)
+ buf += xsnprintf (buf, endbuf - buf, "p-1.");
+ else
+ buf += xsnprintf (buf, endbuf - buf, "p%x.", (unsigned) m_pid);
+ }
+ if (m_lwp == -1)
+ xsnprintf (buf, endbuf - buf, "-1");
+ else
+ xsnprintf (buf, endbuf - buf, "%lx", (unsigned long) m_lwp);
+
+ return result;
+}
+
+/* See ptid.h. */
+
std::string
ptid_t::to_string () const
{
return string_printf ("%d.%ld.%s", m_pid, m_lwp, pulongest (m_tid));
}
+
+/* See ptid.h. */
+
+static ULONGEST
+hex_or_minus_one (const char *buf, const char **obuf, bool for_remote)
+{
+ ULONGEST ret;
+
+ if (for_remote && startswith (buf, "-1"))
+ {
+ ret = (ULONGEST) -1;
+ buf += 2;
+ }
+ else
+ buf = unpack_varlen_hex (buf, &ret);
+
+ if (obuf != nullptr)
+ *obuf = buf;
+
+ return ret;
+}
+
+ptid_t
+ptid_t::parse (const char *buf, const char **obuf, bool for_remote,
+ gdb::function_view<pid_type ()> default_pid)
+{
+ const char *p = buf;
+ const char *pp;
+ ptid_t::pid_type pid = 0;
+ ptid_t::lwp_type lwp = 0;
+ ULONGEST hex;
+
+ using unsigned_pid_type = std::make_unsigned<pid_type>::type;
+ using unsigned_lwp_type = std::make_unsigned<lwp_type>::type;
+
+ if (*p == 'p')
+ {
+ /* Multi-process ptid. */
+ pp = unpack_varlen_hex (p + 1, &hex);
+ if (pp == (p + 1) || *pp != '.')
+ error (_("invalid remote ptid: %s"), buf);
+
+ pid = (ptid_t::pid_type) hex;
+ if (hex != ((unsigned_pid_type) pid))
+ error (_("invalid remote ptid: %s"), buf);
+
+ p = pp + 1;
+ hex = hex_or_minus_one (p, &pp, for_remote);
+ if (pp == p)
+ error (_("invalid remote ptid: %s"), buf);
+
+ lwp = (ptid_t::lwp_type) hex;
+ if (hex != ((unsigned_lwp_type) lwp))
+ error (_("invalid remote ptid: %s"), buf);
+
+ if (obuf != nullptr)
+ *obuf = pp;
+
+ return ptid_t (pid, lwp);
+ }
+
+ /* No multi-process. Just a thread id. */
+ hex = hex_or_minus_one (p, &pp, for_remote);
+
+ /* Handle special thread ids. */
+ if (hex == (ULONGEST) -1)
+ return minus_one_ptid;
+
+ if (hex == 0)
+ return null_ptid;
+
+ lwp = (ptid_t::lwp_type) hex;
+ if (hex != ((unsigned_lwp_type) lwp))
+ error (_("invalid remote ptid: %s"), buf);
+
+ pid = default_pid ();
+
+ if (obuf != nullptr)
+ *obuf = pp;
+
+ return ptid_t (pid, lwp);
+}
@@ -35,6 +35,7 @@
#include <functional>
#include <string>
#include "gdbsupport/common-types.h"
+#include "gdbsupport/function-view.h"
class ptid_t
{
@@ -130,6 +131,12 @@ class ptid_t
|| *this == filter);
}
+ /* Return a remote-protocol-compatible string representation of this
+ ptid. The MULTI argument controls whether the multi-process
+ representation is used. */
+
+ std::string to_rsp_string (bool multi) const;
+
/* Return a string representation of the ptid.
This is only meant to be used in debug messages. */
@@ -146,6 +153,16 @@ class ptid_t
static constexpr ptid_t make_minus_one ()
{ return ptid_t (-1, 0, 0); }
+ /* Extract a PTID from BUF. If non-null, OBUF is set to one past
+ the last parsed char. FOR_REMOTE is true for "gdbserver" style
+ parsing, that is, applying a special meaning to "-1" (see RSP
+ docs for details). DEFAULT_PID is called when the parsed string
+ does not provide a process ID; it should return the default PID
+ to use. This function throws on error. */
+
+ static ptid_t parse (const char *buf, const char **obuf, bool for_remote,
+ gdb::function_view<pid_type ()> default_pid);
+
private:
/* Process id. */
pid_type m_pid;