aboutsummaryrefslogtreecommitdiff
path: root/gdbsupport
diff options
context:
space:
mode:
Diffstat (limited to 'gdbsupport')
-rw-r--r--gdbsupport/Makefile.am1
-rw-r--r--gdbsupport/Makefile.in14
-rw-r--r--gdbsupport/common-defs.h15
-rw-r--r--gdbsupport/common-utils.cc21
-rw-r--r--gdbsupport/common-utils.h10
-rw-r--r--gdbsupport/common.m41
-rwxr-xr-xgdbsupport/configure112
-rw-r--r--gdbsupport/event-loop.cc3
-rw-r--r--gdbsupport/filestuff.cc8
-rw-r--r--gdbsupport/filtered-iterator.h24
-rw-r--r--gdbsupport/format.cc91
-rw-r--r--gdbsupport/format.h27
-rw-r--r--gdbsupport/gdb-safe-ctype.h49
-rw-r--r--gdbsupport/gdb_argv_vec.h15
-rw-r--r--gdbsupport/iterator-range.h1
-rw-r--r--gdbsupport/parallel-for.h10
-rw-r--r--gdbsupport/pathstuff.cc17
-rw-r--r--gdbsupport/poison.h2
-rw-r--r--gdbsupport/print-utils.cc18
-rw-r--r--gdbsupport/print-utils.h30
-rw-r--r--gdbsupport/remote-args.cc43
-rw-r--r--gdbsupport/remote-args.h60
-rw-r--r--gdbsupport/run-time-clock.cc43
-rw-r--r--gdbsupport/run-time-clock.h33
-rw-r--r--gdbsupport/x86-xstate.h7
25 files changed, 341 insertions, 314 deletions
diff --git a/gdbsupport/Makefile.am b/gdbsupport/Makefile.am
index 79aef95..20122e4 100644
--- a/gdbsupport/Makefile.am
+++ b/gdbsupport/Makefile.am
@@ -80,6 +80,7 @@ libgdbsupport_a_SOURCES = \
pathstuff.cc \
print-utils.cc \
ptid.cc \
+ remote-args.cc \
rsp-low.cc \
run-time-clock.cc \
safe-strerror.cc \
diff --git a/gdbsupport/Makefile.in b/gdbsupport/Makefile.in
index c2feacc..66b8891 100644
--- a/gdbsupport/Makefile.in
+++ b/gdbsupport/Makefile.in
@@ -163,12 +163,12 @@ am_libgdbsupport_a_OBJECTS = agent.$(OBJEXT) btrace-common.$(OBJEXT) \
gdb_tilde_expand.$(OBJEXT) gdb_wait.$(OBJEXT) \
gdb_vecs.$(OBJEXT) job-control.$(OBJEXT) netstuff.$(OBJEXT) \
new-op.$(OBJEXT) osabi.$(OBJEXT) pathstuff.$(OBJEXT) \
- print-utils.$(OBJEXT) ptid.$(OBJEXT) rsp-low.$(OBJEXT) \
- run-time-clock.$(OBJEXT) safe-strerror.$(OBJEXT) \
- scoped_mmap.$(OBJEXT) search.$(OBJEXT) signals.$(OBJEXT) \
- signals-state-save-restore.$(OBJEXT) task-group.$(OBJEXT) \
- tdesc.$(OBJEXT) thread-pool.$(OBJEXT) xml-utils.$(OBJEXT) \
- $(am__objects_1) $(am__objects_2)
+ print-utils.$(OBJEXT) ptid.$(OBJEXT) remote-args.$(OBJEXT) \
+ rsp-low.$(OBJEXT) run-time-clock.$(OBJEXT) \
+ safe-strerror.$(OBJEXT) scoped_mmap.$(OBJEXT) search.$(OBJEXT) \
+ signals.$(OBJEXT) signals-state-save-restore.$(OBJEXT) \
+ task-group.$(OBJEXT) tdesc.$(OBJEXT) thread-pool.$(OBJEXT) \
+ xml-utils.$(OBJEXT) $(am__objects_1) $(am__objects_2)
libgdbsupport_a_OBJECTS = $(am_libgdbsupport_a_OBJECTS)
AM_V_P = $(am__v_P_@AM_V@)
am__v_P_ = $(am__v_P_@AM_DEFAULT_V@)
@@ -438,6 +438,7 @@ libgdbsupport_a_SOURCES = \
pathstuff.cc \
print-utils.cc \
ptid.cc \
+ remote-args.cc \
rsp-low.cc \
run-time-clock.cc \
safe-strerror.cc \
@@ -548,6 +549,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pathstuff.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/print-utils.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ptid.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/remote-args.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rsp-low.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/run-time-clock.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/safe-strerror.Po@am__quote@
diff --git a/gdbsupport/common-defs.h b/gdbsupport/common-defs.h
index 07caf3b..6f58914 100644
--- a/gdbsupport/common-defs.h
+++ b/gdbsupport/common-defs.h
@@ -27,6 +27,14 @@
#pragma GCC optimize("-fno-hoist-adjacent-loads")
#endif
+#if defined (__GNUC__) && !defined (__clang__) \
+ && ((__GNUC__ >= 12 && __GNUC__ <= 15) \
+ || (__GNUC__ == 16 && __GNUC_MINOR__ < 1))
+/* Work around PR gcc/120987 starting gcc 12, and assume it will be fixed in
+ the gcc 16.1 release. */
+#pragma GCC optimize("-fno-ipa-modref")
+#endif
+
#include <gdbsupport/config.h>
#undef PACKAGE_NAME
@@ -208,13 +216,18 @@
#include "errors.h"
#include "print-utils.h"
#include "common-debug.h"
-#include "cleanups.h"
#include "common-exceptions.h"
#include "gdbsupport/poison.h"
/* Pull in gdb::unique_xmalloc_ptr. */
#include "gdbsupport/gdb_unique_ptr.h"
+/* Note that there's no simple way to enforce the use of the c-ctype
+ functions. We can't poison the <ctype.h> functions (see
+ safe-ctype.h) because that will provoke errors from libstdc++
+ headers. */
+#include "c-ctype.h"
+
/* sbrk on macOS is not useful for our purposes, since sbrk(0) always
returns the same value. brk/sbrk on macOS is just an emulation
that always returns a pointer to a 4MB section reserved for
diff --git a/gdbsupport/common-utils.cc b/gdbsupport/common-utils.cc
index 266d836..5c7ba31 100644
--- a/gdbsupport/common-utils.cc
+++ b/gdbsupport/common-utils.cc
@@ -19,7 +19,6 @@
#include "common-utils.h"
#include "host-defs.h"
-#include "gdbsupport/gdb-safe-ctype.h"
#include "gdbsupport/gdb-xfree.h"
void *
@@ -180,7 +179,7 @@ extract_string_maybe_quoted (const char **arg)
/* Parse p similarly to gdb_argv buildargv function. */
while (*p != '\0')
{
- if (ISSPACE (*p) && !squote && !dquote && !bsquote)
+ if (c_isspace (*p) && !squote && !dquote && !bsquote)
break;
else
{
@@ -254,21 +253,21 @@ make_quoted_string (const char *str)
static int
is_digit_in_base (unsigned char digit, int base)
{
- if (!ISALNUM (digit))
+ if (!c_isalnum (digit))
return 0;
if (base <= 10)
- return (ISDIGIT (digit) && digit < base + '0');
+ return (c_isdigit (digit) && digit < base + '0');
else
- return (ISDIGIT (digit) || TOLOWER (digit) < base - 10 + 'a');
+ return (c_isdigit (digit) || c_tolower (digit) < base - 10 + 'a');
}
static int
digit_to_int (unsigned char c)
{
- if (ISDIGIT (c))
+ if (c_isdigit (c))
return c - '0';
else
- return TOLOWER (c) - 'a' + 10;
+ return c_tolower (c) - 'a' + 10;
}
/* As for strtoul, but for ULONGEST results. */
@@ -282,7 +281,7 @@ strtoulst (const char *num, const char **trailer, int base)
int i = 0;
/* Skip leading whitespace. */
- while (ISSPACE (num[i]))
+ while (c_isspace (num[i]))
i++;
/* Handle prefixes. */
@@ -349,7 +348,7 @@ skip_spaces (char *chp)
{
if (chp == NULL)
return NULL;
- while (*chp && ISSPACE (*chp))
+ while (*chp && c_isspace (*chp))
chp++;
return chp;
}
@@ -361,7 +360,7 @@ skip_spaces (const char *chp)
{
if (chp == NULL)
return NULL;
- while (*chp && ISSPACE (*chp))
+ while (*chp && c_isspace (*chp))
chp++;
return chp;
}
@@ -373,7 +372,7 @@ skip_to_space (const char *chp)
{
if (chp == NULL)
return NULL;
- while (*chp && !ISSPACE (*chp))
+ while (*chp && !c_isspace (*chp))
chp++;
return chp;
}
diff --git a/gdbsupport/common-utils.h b/gdbsupport/common-utils.h
index a168458..10bf9f4 100644
--- a/gdbsupport/common-utils.h
+++ b/gdbsupport/common-utils.h
@@ -196,6 +196,16 @@ in_inclusive_range (T value, T low, T high)
extern ULONGEST align_up (ULONGEST v, int n);
extern ULONGEST align_down (ULONGEST v, int n);
+/* Sign-extend the value V, using N as the number of valid bits. That
+ is, bit N-1 is the sign bit. The higher-order bits (those outside
+ 0..N-1) must be zero. */
+static inline ULONGEST
+sign_extend (ULONGEST v, int n)
+{
+ ULONGEST mask = (ULONGEST) 1 << (n - 1);
+ return (v ^ mask) - mask;
+}
+
/* Convert hex digit A to a number, or throw an exception. */
extern int fromhex (int a);
diff --git a/gdbsupport/common.m4 b/gdbsupport/common.m4
index f265af9..cde8bd6 100644
--- a/gdbsupport/common.m4
+++ b/gdbsupport/common.m4
@@ -21,7 +21,6 @@ AC_DEFUN([GDB_AC_COMMON], [
# Set the 'development' global.
. $srcdir/../bfd/development.sh
- AC_HEADER_STDC
AC_FUNC_ALLOCA
WIN32APILIBS=
diff --git a/gdbsupport/configure b/gdbsupport/configure
index bcfae34..133ddfa 100755
--- a/gdbsupport/configure
+++ b/gdbsupport/configure
@@ -10704,118 +10704,6 @@ $as_echo "$ac_cv_path_SED" >&6; }
# Set the 'development' global.
. $srcdir/../bfd/development.sh
- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
-$as_echo_n "checking for ANSI C header files... " >&6; }
-if ${ac_cv_header_stdc+:} false; then :
- $as_echo_n "(cached) " >&6
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <float.h>
-
-int
-main ()
-{
-
- ;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_compile "$LINENO"; then :
- ac_cv_header_stdc=yes
-else
- ac_cv_header_stdc=no
-fi
-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
-
-if test $ac_cv_header_stdc = yes; then
- # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <string.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "memchr" >/dev/null 2>&1; then :
-
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
- # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <stdlib.h>
-
-_ACEOF
-if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
- $EGREP "free" >/dev/null 2>&1; then :
-
-else
- ac_cv_header_stdc=no
-fi
-rm -f conftest*
-
-fi
-
-if test $ac_cv_header_stdc = yes; then
- # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
- if test "$cross_compiling" = yes; then :
- :
-else
- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
-/* end confdefs.h. */
-#include <ctype.h>
-#include <stdlib.h>
-#if ((' ' & 0x0FF) == 0x020)
-# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
-# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
-#else
-# define ISLOWER(c) \
- (('a' <= (c) && (c) <= 'i') \
- || ('j' <= (c) && (c) <= 'r') \
- || ('s' <= (c) && (c) <= 'z'))
-# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
-#endif
-
-#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
-int
-main ()
-{
- int i;
- for (i = 0; i < 256; i++)
- if (XOR (islower (i), ISLOWER (i))
- || toupper (i) != TOUPPER (i))
- return 2;
- return 0;
-}
-_ACEOF
-if ac_fn_c_try_run "$LINENO"; then :
-
-else
- ac_cv_header_stdc=no
-fi
-rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
- conftest.$ac_objext conftest.beam conftest.$ac_ext
-fi
-
-fi
-fi
-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
-$as_echo "$ac_cv_header_stdc" >&6; }
-if test $ac_cv_header_stdc = yes; then
-
-$as_echo "#define STDC_HEADERS 1" >>confdefs.h
-
-fi
-
# The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
# for constant arguments. Useless!
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for working alloca.h" >&5
diff --git a/gdbsupport/event-loop.cc b/gdbsupport/event-loop.cc
index c080490..e7b21e7 100644
--- a/gdbsupport/event-loop.cc
+++ b/gdbsupport/event-loop.cc
@@ -827,7 +827,8 @@ update_wait_timeout (void)
/* Update the timeout for select/ poll. */
#ifdef HAVE_POLL
if (use_poll)
- gdb_notifier.poll_timeout = timeout.tv_sec * 1000;
+ gdb_notifier.poll_timeout = (timeout.tv_sec * 1000 +
+ (timeout.tv_usec + 1000 - 1) / 1000);
else
#endif /* HAVE_POLL */
{
diff --git a/gdbsupport/filestuff.cc b/gdbsupport/filestuff.cc
index 5c1817e..817663b 100644
--- a/gdbsupport/filestuff.cc
+++ b/gdbsupport/filestuff.cc
@@ -333,14 +333,10 @@ gdb_fopen_cloexec (const char *filename, const char *opentype)
if (!fopen_e_ever_failed_einval)
{
- char *copy;
-
- copy = (char *) alloca (strlen (opentype) + 2);
- strcpy (copy, opentype);
/* This is a glibc extension but we try it unconditionally on
this path. */
- strcat (copy, "e");
- result = fopen (filename, copy);
+ auto opentype_e = std::string (opentype) + 'e';
+ result = fopen (filename, opentype_e.c_str ());
if (result == NULL && errno == EINVAL)
{
diff --git a/gdbsupport/filtered-iterator.h b/gdbsupport/filtered-iterator.h
index e824d61..4952582 100644
--- a/gdbsupport/filtered-iterator.h
+++ b/gdbsupport/filtered-iterator.h
@@ -19,8 +19,6 @@
#ifndef GDBSUPPORT_FILTERED_ITERATOR_H
#define GDBSUPPORT_FILTERED_ITERATOR_H
-#include <type_traits>
-
/* A filtered iterator. This wraps BaseIterator and automatically
skips elements that FilterFunc filters out. Requires that
default-constructing a BaseIterator creates a valid one-past-end
@@ -30,12 +28,14 @@ template<typename BaseIterator, typename FilterFunc>
class filtered_iterator
{
public:
- typedef filtered_iterator self_type;
- typedef typename BaseIterator::value_type value_type;
- typedef typename BaseIterator::reference reference;
- typedef typename BaseIterator::pointer pointer;
- typedef typename BaseIterator::iterator_category iterator_category;
- typedef typename BaseIterator::difference_type difference_type;
+ using self_type = filtered_iterator;
+ using value_type = typename std::iterator_traits<BaseIterator>::value_type;
+ using reference = typename std::iterator_traits<BaseIterator>::reference;
+ using pointer = typename std::iterator_traits<BaseIterator>::pointer;
+ using iterator_category
+ = typename std::iterator_traits<BaseIterator>::iterator_category;
+ using difference_type
+ = typename std::iterator_traits<BaseIterator>::difference_type;
/* Construct by forwarding all arguments to the underlying
iterator. */
@@ -44,6 +44,10 @@ public:
: m_it (std::forward<Args> (args)...)
{ skip_filtered (); }
+ filtered_iterator (BaseIterator begin, BaseIterator end)
+ : m_it (std::move (begin)), m_end (std::move (end))
+ { skip_filtered (); }
+
/* Create a one-past-end iterator. */
filtered_iterator () = default;
@@ -56,9 +60,7 @@ public:
: filtered_iterator (static_cast<const filtered_iterator &> (other))
{}
- typename std::invoke_result<decltype(&BaseIterator::operator*),
- BaseIterator>::type
- operator* () const
+ decltype(auto) operator* () const
{ return *m_it; }
self_type &operator++ ()
diff --git a/gdbsupport/format.cc b/gdbsupport/format.cc
index be3d821..145c876 100644
--- a/gdbsupport/format.cc
+++ b/gdbsupport/format.cc
@@ -22,14 +22,11 @@
format_pieces::format_pieces (const char **arg, bool gdb_extensions,
bool value_extension)
{
- const char *s;
+ const char *s = *arg;
const char *string;
- const char *prev_start;
- const char *percent_loc;
- char *sub_start, *current_substring;
- enum argclass this_argclass;
- s = *arg;
+ /* Buffer to hold the escaped-processed version of the string. */
+ std::string de_escaped;
if (gdb_extensions)
{
@@ -40,10 +37,6 @@ format_pieces::format_pieces (const char **arg, bool gdb_extensions,
{
/* Parse the format-control string and copy it into the string STRING,
processing some kinds of escape sequence. */
-
- char *f = (char *) alloca (strlen (s) + 1);
- string = f;
-
while (*s != '"' && *s != '\0')
{
int c = *s++;
@@ -56,34 +49,34 @@ format_pieces::format_pieces (const char **arg, bool gdb_extensions,
switch (c = *s++)
{
case '\\':
- *f++ = '\\';
+ de_escaped += '\\';
break;
case 'a':
- *f++ = '\a';
+ de_escaped += '\a';
break;
case 'b':
- *f++ = '\b';
+ de_escaped += '\b';
break;
case 'e':
- *f++ = '\e';
+ de_escaped += '\e';
break;
case 'f':
- *f++ = '\f';
+ de_escaped += '\f';
break;
case 'n':
- *f++ = '\n';
+ de_escaped += '\n';
break;
case 'r':
- *f++ = '\r';
+ de_escaped += '\r';
break;
case 't':
- *f++ = '\t';
+ de_escaped += '\t';
break;
case 'v':
- *f++ = '\v';
+ de_escaped += '\v';
break;
case '"':
- *f++ = '"';
+ de_escaped += '"';
break;
default:
/* ??? TODO: handle other escape sequences. */
@@ -93,29 +86,23 @@ format_pieces::format_pieces (const char **arg, bool gdb_extensions,
break;
default:
- *f++ = c;
+ de_escaped += c;
}
}
- /* Terminate our escape-processed copy. */
- *f++ = '\0';
+ string = de_escaped.c_str ();
/* Whether the format string ended with double-quote or zero, we're
done with it; it's up to callers to complain about syntax. */
*arg = s;
}
- /* Need extra space for the '\0's. Doubling the size is sufficient. */
-
- current_substring = (char *) xmalloc (strlen (string) * 2 + 1000);
- m_storage.reset (current_substring);
-
/* Now scan the string for %-specs and see what kinds of args they want.
argclass classifies the %-specs so we can give printf-type functions
something of the right size. */
-
const char *f = string;
- prev_start = string;
+ const char *prev_start = string;
+
while (*f)
if (*f++ == '%')
{
@@ -135,16 +122,15 @@ format_pieces::format_pieces (const char **arg, bool gdb_extensions,
continue;
}
- sub_start = current_substring;
+ std::string::size_type sub_start = m_storage.size ();
- strncpy (current_substring, prev_start, f - 1 - prev_start);
- current_substring += f - 1 - prev_start;
- *current_substring++ = '\0';
+ m_storage.append (prev_start, f - 1 - prev_start);
+ m_storage += '\0';
- if (*sub_start != '\0')
+ if (m_storage[sub_start] != '\0')
m_pieces.emplace_back (sub_start, literal_piece, 0);
- percent_loc = f - 1;
+ const char *percent_loc = f - 1;
/* Check the validity of the format specifier, and work
out what argument it expects. We only accept C89
@@ -251,6 +237,8 @@ format_pieces::format_pieces (const char **arg, bool gdb_extensions,
break;
}
+ argclass this_argclass;
+
switch (*f)
{
case 'u':
@@ -381,7 +369,7 @@ format_pieces::format_pieces (const char **arg, bool gdb_extensions,
f++;
- sub_start = current_substring;
+ sub_start = m_storage.size ();
if (lcount > 1 && !seen_i64 && USE_PRINTF_I64)
{
@@ -389,11 +377,9 @@ format_pieces::format_pieces (const char **arg, bool gdb_extensions,
Convert %lld to %I64d. */
int length_before_ll = f - percent_loc - 1 - lcount;
- strncpy (current_substring, percent_loc, length_before_ll);
- strcpy (current_substring + length_before_ll, "I64");
- current_substring[length_before_ll + 3] =
- percent_loc[length_before_ll + lcount];
- current_substring += length_before_ll + 4;
+ m_storage.append (percent_loc, length_before_ll);
+ m_storage += "I64";
+ m_storage += percent_loc[length_before_ll + lcount];
}
else if (this_argclass == wide_string_arg
|| this_argclass == wide_char_arg)
@@ -401,18 +387,13 @@ format_pieces::format_pieces (const char **arg, bool gdb_extensions,
/* Convert %ls or %lc to %s. */
int length_before_ls = f - percent_loc - 2;
- strncpy (current_substring, percent_loc, length_before_ls);
- strcpy (current_substring + length_before_ls, "s");
- current_substring += length_before_ls + 2;
+ m_storage.append (percent_loc, length_before_ls);
+ m_storage += "s";
}
else
- {
- strncpy (current_substring, percent_loc, f - percent_loc);
- current_substring += f - percent_loc;
- }
-
- *current_substring++ = '\0';
+ m_storage.append (percent_loc, f - percent_loc);
+ m_storage += '\0';
prev_start = f;
m_pieces.emplace_back (sub_start, this_argclass, n_int_args);
@@ -422,11 +403,9 @@ format_pieces::format_pieces (const char **arg, bool gdb_extensions,
if (f > prev_start)
{
- sub_start = current_substring;
-
- strncpy (current_substring, prev_start, f - prev_start);
- current_substring += f - prev_start;
- *current_substring++ = '\0';
+ std::string::size_type sub_start = m_storage.size ();
+ m_storage.append (prev_start, f - prev_start);
+ /* No need for a final '\0', std::string already has one. */
m_pieces.emplace_back (sub_start, literal_piece, 0);
}
diff --git a/gdbsupport/format.h b/gdbsupport/format.h
index 118b947..46dae22 100644
--- a/gdbsupport/format.h
+++ b/gdbsupport/format.h
@@ -20,8 +20,6 @@
#ifndef GDBSUPPORT_FORMAT_H
#define GDBSUPPORT_FORMAT_H
-#include <string_view>
-
#if defined(__MINGW32__) && !defined(PRINTF_HAS_LONG_LONG)
# define USE_PRINTF_I64 1
# define PRINTF_HAS_LONG_LONG
@@ -51,21 +49,15 @@ enum argclass
struct format_piece
{
- format_piece (const char *str, enum argclass argc, int n)
- : string (str),
+ format_piece (std::string::size_type start, enum argclass argc, int n)
+ : start (start),
argclass (argc),
n_int_args (n)
- {
- gdb_assert (str != nullptr);
- }
+ {}
- bool operator== (const format_piece &other) const
- {
- return (this->argclass == other.argclass
- && std::string_view (this->string) == other.string);
- }
+ /* Where this piece starts, within FORMAT_PIECES::M_STORAGE. */
+ std::string::size_type start;
- const char *string;
enum argclass argclass;
/* Count the number of preceding 'int' arguments that must be passed
along. This is used for a width or precision of '*'. Note that
@@ -95,10 +87,17 @@ public:
return m_pieces.end ();
}
+ /* Return the string associated to PIECE. */
+ const char *piece_str (const format_piece &piece)
+ { return &m_storage[piece.start]; }
+
private:
std::vector<format_piece> m_pieces;
- gdb::unique_xmalloc_ptr<char> m_storage;
+
+ /* This is used as a buffer of concatenated null-terminated strings. The
+ individual strings are referenced by FORMAT_PIECE::START. */
+ std::string m_storage;
};
#endif /* GDBSUPPORT_FORMAT_H */
diff --git a/gdbsupport/gdb-safe-ctype.h b/gdbsupport/gdb-safe-ctype.h
deleted file mode 100644
index 36b78f5..0000000
--- a/gdbsupport/gdb-safe-ctype.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* Wrapper around libiberty's safe-ctype.h for GDB, the GNU debugger.
-
- Copyright (C) 2019-2025 Free Software Foundation, Inc.
-
- This file is part of GDB.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#ifndef GDBSUPPORT_GDB_SAFE_CTYPE_H
-#define GDBSUPPORT_GDB_SAFE_CTYPE_H
-
-/* After safe-ctype.h is included, we can no longer use the host's
- ctype routines. Trying to do so results in compile errors. Code
- that uses safe-ctype.h that wants to refer to the locale-dependent
- ctype functions must call these wrapper versions instead.
- When compiling in C++ mode, also include <locale> before "safe-ctype.h"
- which also defines is* functions. */
-
-static inline int
-gdb_isprint (int ch)
-{
- return isprint (ch);
-}
-
-/* readline.h defines these symbols too, but we want libiberty's
- versions. */
-#undef ISALPHA
-#undef ISALNUM
-#undef ISDIGIT
-#undef ISLOWER
-#undef ISPRINT
-#undef ISUPPER
-#undef ISXDIGIT
-
-#include <locale>
-#include "safe-ctype.h"
-
-#endif /* GDBSUPPORT_GDB_SAFE_CTYPE_H */
diff --git a/gdbsupport/gdb_argv_vec.h b/gdbsupport/gdb_argv_vec.h
index 1f3b6db..43571ae 100644
--- a/gdbsupport/gdb_argv_vec.h
+++ b/gdbsupport/gdb_argv_vec.h
@@ -90,6 +90,15 @@ public:
m_args.push_back (value);
}
+ /* Like calling emplace_back on the underlying vector. This class takes
+ ownership of the value added to the vector, and will release the value
+ by calling xfree() on it when this object is destroyed. */
+ template<typename... Args>
+ reference emplace_back (Args &&...args)
+ {
+ return m_args.emplace_back (std::forward<Args> (args)...);
+ }
+
/* Non constant iterator to start of m_args. */
iterator begin ()
{
@@ -133,6 +142,12 @@ public:
{
return m_args.empty ();
}
+
+ /* Clear the argument vector. */
+ void clear ()
+ {
+ free_vector_argv (m_args);
+ }
};
} /* namespac gdb */
diff --git a/gdbsupport/iterator-range.h b/gdbsupport/iterator-range.h
index a8cacfb..9653d40 100644
--- a/gdbsupport/iterator-range.h
+++ b/gdbsupport/iterator-range.h
@@ -36,7 +36,6 @@ struct iterator_range
{}
/* Create an iterator range using explicit BEGIN and END iterators. */
- template <typename... Args>
iterator_range (IteratorType begin, IteratorType end)
: m_begin (std::move (begin)), m_end (std::move (end))
{}
diff --git a/gdbsupport/parallel-for.h b/gdbsupport/parallel-for.h
index c485c36..b74c806 100644
--- a/gdbsupport/parallel-for.h
+++ b/gdbsupport/parallel-for.h
@@ -40,10 +40,9 @@ namespace gdb
at least N elements processed per thread. Setting N to 0 is not
allowed. */
-template<class RandomIt, class RangeFunction>
+template<std::size_t n, class RandomIt, class RangeFunction>
void
-parallel_for_each (unsigned n, RandomIt first, RandomIt last,
- RangeFunction callback)
+parallel_for_each (RandomIt first, RandomIt last, RangeFunction callback)
{
/* If enabled, print debug info about how the work is distributed across
the threads. */
@@ -73,7 +72,7 @@ parallel_for_each (unsigned n, RandomIt first, RandomIt last,
if (parallel_for_each_debug)
{
debug_printf (_("Parallel for: n_elements: %zu\n"), n_elements);
- debug_printf (_("Parallel for: minimum elements per thread: %u\n"), n);
+ debug_printf (_("Parallel for: minimum elements per thread: %zu\n"), n);
debug_printf (_("Parallel for: elts_per_thread: %zu\n"), elts_per_thread);
}
@@ -141,8 +140,7 @@ parallel_for_each (unsigned n, RandomIt first, RandomIt last,
template<class RandomIt, class RangeFunction>
void
-sequential_for_each (unsigned n, RandomIt first, RandomIt last,
- RangeFunction callback)
+sequential_for_each (RandomIt first, RandomIt last, RangeFunction callback)
{
callback (first, last);
}
diff --git a/gdbsupport/pathstuff.cc b/gdbsupport/pathstuff.cc
index ce01c95..8142bd5 100644
--- a/gdbsupport/pathstuff.cc
+++ b/gdbsupport/pathstuff.cc
@@ -89,34 +89,25 @@ std::string
gdb_realpath_keepfile (const char *filename)
{
const char *base_name = lbasename (filename);
- char *dir_name;
/* Extract the basename of filename, and return immediately
a copy of filename if it does not contain any directory prefix. */
if (base_name == filename)
return filename;
- dir_name = (char *) alloca ((size_t) (base_name - filename + 2));
- /* Allocate enough space to store the dir_name + plus one extra
- character sometimes needed under Windows (see below), and
- then the closing \000 character. */
- strncpy (dir_name, filename, base_name - filename);
- dir_name[base_name - filename] = '\000';
+ std::string dir_name (filename, base_name - filename);
#ifdef HAVE_DOS_BASED_FILE_SYSTEM
/* We need to be careful when filename is of the form 'd:foo', which
is equivalent of d:./foo, which is totally different from d:/foo. */
- if (strlen (dir_name) == 2 && isalpha (dir_name[0]) && dir_name[1] == ':')
- {
- dir_name[2] = '.';
- dir_name[3] = '\000';
- }
+ if (dir_name.size () == 2 && c_isalpha (dir_name[0]) && dir_name[1] == ':')
+ dir_name += '.';
#endif
/* Canonicalize the directory prefix, and build the resulting
filename. If the dirname realpath already contains an ending
directory separator, avoid doubling it. */
- gdb::unique_xmalloc_ptr<char> path_storage = gdb_realpath (dir_name);
+ gdb::unique_xmalloc_ptr<char> path_storage = gdb_realpath (dir_name.c_str ());
const char *real_path = path_storage.get ();
return path_join (real_path, base_name);
}
diff --git a/gdbsupport/poison.h b/gdbsupport/poison.h
index 791a18f..a91ee5d 100644
--- a/gdbsupport/poison.h
+++ b/gdbsupport/poison.h
@@ -183,7 +183,7 @@ xnewvar (size_t s)
{
static_assert (IsMallocable<T>::value, "Trying to use XNEWVAR with a \
non-POD data type.");
- return XNEWVAR (T, s);;
+ return XNEWVAR (T, s);
}
#undef XNEWVAR
diff --git a/gdbsupport/print-utils.cc b/gdbsupport/print-utils.cc
index 84a7485..8514720 100644
--- a/gdbsupport/print-utils.cc
+++ b/gdbsupport/print-utils.cc
@@ -145,7 +145,7 @@ static int thirty_two = 32;
/* See print-utils.h. */
const char *
-phex (ULONGEST l, int sizeof_l)
+phex_ulongest (ULONGEST l, int sizeof_l)
{
char *str;
@@ -170,7 +170,7 @@ phex (ULONGEST l, int sizeof_l)
xsnprintf (str, PRINT_CELL_SIZE, "%02x", (unsigned short) (l & 0xff));
break;
default:
- return phex (l, sizeof (l));
+ return phex (l);
break;
}
@@ -180,7 +180,7 @@ phex (ULONGEST l, int sizeof_l)
/* See print-utils.h. */
const char *
-phex_nz (ULONGEST l, int sizeof_l)
+phex_nz_ulongest (ULONGEST l, int sizeof_l)
{
char *str;
@@ -212,7 +212,7 @@ phex_nz (ULONGEST l, int sizeof_l)
xsnprintf (str, PRINT_CELL_SIZE, "%x", (unsigned short) (l & 0xff));
break;
default:
- return phex_nz (l, sizeof (l));
+ return phex_nz (l);
break;
}
@@ -226,7 +226,7 @@ hex_string (LONGEST num)
{
char *result = get_print_cell ();
- xsnprintf (result, PRINT_CELL_SIZE, "0x%s", phex_nz (num, sizeof (num)));
+ xsnprintf (result, PRINT_CELL_SIZE, "0x%s", phex_nz (num));
return result;
}
@@ -237,7 +237,7 @@ hex_string_custom (LONGEST num, int width)
{
char *result = get_print_cell ();
char *result_end = result + PRINT_CELL_SIZE - 1;
- const char *hex = phex_nz (num, sizeof (num));
+ const char *hex = phex_nz (num);
int hex_len = strlen (hex);
if (hex_len > width)
@@ -304,8 +304,7 @@ core_addr_to_string (const CORE_ADDR addr)
{
char *str = get_print_cell ();
- strcpy (str, "0x");
- strcat (str, phex (addr, sizeof (addr)));
+ xsnprintf (str, PRINT_CELL_SIZE, "0x%s", phex (addr));
return str;
}
@@ -316,8 +315,7 @@ core_addr_to_string_nz (const CORE_ADDR addr)
{
char *str = get_print_cell ();
- strcpy (str, "0x");
- strcat (str, phex_nz (addr, sizeof (addr)));
+ xsnprintf (str, PRINT_CELL_SIZE, "0x%s", phex_nz (addr));
return str;
}
diff --git a/gdbsupport/print-utils.h b/gdbsupport/print-utils.h
index e50d96f..dc5011c 100644
--- a/gdbsupport/print-utils.h
+++ b/gdbsupport/print-utils.h
@@ -34,15 +34,35 @@ extern const char *pulongest (ULONGEST u);
extern const char *plongest (LONGEST l);
-/* Convert a ULONGEST into a HEX string, like %lx, with leading zeros.
+/* Convert L (of type ULONGEST) into a hex string, like %lx, with leading
+ zeros. The result is stored in a circular static buffer, NUMCELLS
+ deep. */
+
+extern const char *phex_ulongest (ULONGEST l, int sizeof_l);
+
+/* Convert L into a HEX string, like %lx, with leading zeros.
The result is stored in a circular static buffer, NUMCELLS deep. */
-extern const char *phex (ULONGEST l, int sizeof_l);
+template<typename T>
+const char *phex (T l, int sizeof_l = sizeof (T))
+{
+ return phex_ulongest (l, sizeof_l);
+}
+
+/* Convert L (of type ULONGEST) into a hex string, like %lx, without leading
+ zeros. The result is stored in a circular static buffer, NUMCELLS
+ deep. */
-/* Convert a ULONGEST into a HEX string, like %lx, without leading zeros.
- The result is stored in a circular static buffer, NUMCELLS deep. */
+extern const char *phex_nz_ulongest (ULONGEST l, int sizeof_l);
+
+/* Convert L into a hex string, like %lx, without leading zeros.
+ The result is stored in a circular static buffer, NUMCELLS deep. */
-extern const char *phex_nz (ULONGEST l, int sizeof_l);
+template<typename T>
+const char *phex_nz (T l, int sizeof_l = sizeof (T))
+{
+ return phex_nz_ulongest (l, sizeof_l);
+}
/* Converts a LONGEST to a C-format hexadecimal literal and stores it
in a static string. Returns a pointer to this string. */
diff --git a/gdbsupport/remote-args.cc b/gdbsupport/remote-args.cc
new file mode 100644
index 0000000..2493433
--- /dev/null
+++ b/gdbsupport/remote-args.cc
@@ -0,0 +1,43 @@
+/* Copyright (C) 2023-2025 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#include "gdbsupport/common-defs.h"
+#include "gdbsupport/remote-args.h"
+#include "gdbsupport/common-inferior.h"
+#include "gdbsupport/buildargv.h"
+
+/* See remote-args.h. */
+
+std::vector<std::string>
+gdb::remote_args::split (const std::string &args)
+{
+ std::vector<std::string> results;
+
+ gdb_argv argv (args.c_str ());
+ for (int i = 0; argv[i] != nullptr; i++)
+ results.emplace_back (argv[i]);
+
+ return results;
+}
+
+/* See remote-args.h. */
+
+std::string
+gdb::remote_args::join (const std::vector<char *> &args)
+{
+ return construct_inferior_arguments (args, true);
+}
diff --git a/gdbsupport/remote-args.h b/gdbsupport/remote-args.h
new file mode 100644
index 0000000..0533da6
--- /dev/null
+++ b/gdbsupport/remote-args.h
@@ -0,0 +1,60 @@
+/* Functions to help when passing arguments between GDB and gdbserver.
+
+ Copyright (C) 2023-2025 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
+
+#ifndef GDBSUPPORT_REMOTE_ARGS_H
+#define GDBSUPPORT_REMOTE_ARGS_H
+
+/* The functions declared here are used when passing inferior arguments
+ from GDB to gdbserver.
+
+ The remote protocol requires that arguments are passed as a vector of
+ separate argument while GDB stores the arguments as a single string, and
+ gdbserver also requires the arguments be a single string.
+
+ These functions then provide a mechanism to split up an argument string
+ and recombine it within gdbserver while preserving escaping of special
+ characters within the argument string. */
+
+namespace gdb
+{
+
+namespace remote_args
+{
+
+/* ARGS is an inferior argument string. This function splits ARGS into
+ individual arguments and returns a vector containing each argument. */
+
+extern std::vector<std::string> split (const std::string &args);
+
+/* Join together the separate arguments in ARGS and build a single
+ inferior argument string. The string returned by this function will be
+ equivalent, but not necessarily identical to the string passed to
+ ::split, for example passing the string '"a b"' (without the single
+ quotes, but including the double quotes) to ::split, will return an
+ argument of 'a b' (without the single quotes). When this argument is
+ passed through ::join we will get back the string 'a\ b' (without the
+ single quotes), that is, we choose to escape the white space, rather
+ than wrap the argument in quotes. */
+extern std::string join (const std::vector<char *> &args);
+
+} /* namespace remote_args */
+
+} /* namespace gdb */
+
+#endif /* GDBSUPPORT_REMOTE_ARGS_H */
diff --git a/gdbsupport/run-time-clock.cc b/gdbsupport/run-time-clock.cc
index 43da1d9..cda60b0 100644
--- a/gdbsupport/run-time-clock.cc
+++ b/gdbsupport/run-time-clock.cc
@@ -37,14 +37,51 @@ timeval_to_microseconds (struct timeval *tv)
}
#endif
+/* See run-time-clock.h. */
+
+bool
+get_run_time_thread_scope_available ()
+{
+#if defined HAVE_GETRUSAGE && defined RUSAGE_THREAD
+ return true;
+#else
+ return false;
+#endif
+}
+
void
-run_time_clock::now (user_cpu_time_clock::time_point &user,
- system_cpu_time_clock::time_point &system) noexcept
+get_run_time (user_cpu_time_clock::time_point &user,
+ system_cpu_time_clock::time_point &system,
+ run_time_scope scope) noexcept
{
#ifdef HAVE_GETRUSAGE
+
+ /* If we can't provide thread scope run time usage, fallback to
+ process scope. This will at least be right if GDB is built
+ without threading support in the first place (or is set to use
+ zero worker threads). */
+# ifndef RUSAGE_THREAD
+# define RUSAGE_THREAD RUSAGE_SELF
+# endif
+
struct rusage rusage;
+ int who;
+
+ switch (scope)
+ {
+ case run_time_scope::thread:
+ who = RUSAGE_THREAD;
+ break;
+
+ case run_time_scope::process:
+ who = RUSAGE_SELF;
+ break;
+
+ default:
+ gdb_assert_not_reached ("invalid run_time_scope value");
+ }
- getrusage (RUSAGE_SELF, &rusage);
+ getrusage (who, &rusage);
microseconds utime = timeval_to_microseconds (&rusage.ru_utime);
microseconds stime = timeval_to_microseconds (&rusage.ru_stime);
diff --git a/gdbsupport/run-time-clock.h b/gdbsupport/run-time-clock.h
index a961f4c..2743514 100644
--- a/gdbsupport/run-time-clock.h
+++ b/gdbsupport/run-time-clock.h
@@ -51,6 +51,33 @@ struct system_cpu_time_clock
static time_point now () noexcept = delete;
};
+/* Whether to measure time run time for the whole process or just one
+ thread. */
+
+enum class run_time_scope
+{
+ process,
+ thread,
+};
+
+/* Return the user/system time as separate time points, if
+ supported. If not supported, then the combined user+kernel time
+ is returned in USER and SYSTEM is set to zero.
+
+ SCOPE indicates whether to return the run time for the whole
+ process or just for the calling thread. If the latter isn't
+ supported, then returns the run time for the whole process even if
+ run_time_scope::thread is requested. */
+
+void get_run_time (user_cpu_time_clock::time_point &user,
+ system_cpu_time_clock::time_point &system,
+ run_time_scope scope) noexcept;
+
+/* Returns true if is it possible for get_run_time above to return the
+ run time for just the calling thread. */
+
+bool get_run_time_thread_scope_available ();
+
/* Count the total amount of time spent executing in userspace+kernel
mode. */
@@ -64,12 +91,6 @@ struct run_time_clock
static constexpr bool is_steady = true;
static time_point now () noexcept;
-
- /* Return the user/system time as separate time points, if
- supported. If not supported, then the combined user+kernel time
- is returned in USER and SYSTEM is set to zero. */
- static void now (user_cpu_time_clock::time_point &user,
- system_cpu_time_clock::time_point &system) noexcept;
};
#endif /* GDBSUPPORT_RUN_TIME_CLOCK_H */
diff --git a/gdbsupport/x86-xstate.h b/gdbsupport/x86-xstate.h
index 5d563ff..6657c45 100644
--- a/gdbsupport/x86-xstate.h
+++ b/gdbsupport/x86-xstate.h
@@ -28,6 +28,7 @@
#define X86_XSTATE_ZMM_H_ID 6
#define X86_XSTATE_ZMM_ID 7
#define X86_XSTATE_PKRU_ID 9
+#define X86_XSTATE_CET_U_ID 11
/* The extended state feature bits. */
#define X86_XSTATE_X87 (1ULL << X86_XSTATE_X87_ID)
@@ -42,6 +43,7 @@
| X86_XSTATE_ZMM)
#define X86_XSTATE_PKRU (1ULL << X86_XSTATE_PKRU_ID)
+#define X86_XSTATE_CET_U (1ULL << X86_XSTATE_CET_U_ID)
/* Total size of the XSAVE area extended region and offsets of
register states within the region. Offsets are set to 0 to
@@ -83,8 +85,11 @@ constexpr bool operator!= (const x86_xsave_layout &lhs,
#define X86_XSTATE_AVX_AVX512_PKU_MASK (X86_XSTATE_AVX_MASK\
| X86_XSTATE_AVX512 | X86_XSTATE_PKRU)
-#define X86_XSTATE_ALL_MASK (X86_XSTATE_AVX_AVX512_PKU_MASK)
+/* Supported mask of state-component bitmap xstate_bv. The SDM defines
+ xstate_bv as XCR0 | IA32_XSS. */
+#define X86_XSTATE_ALL_MASK (X86_XSTATE_AVX_AVX512_PKU_MASK\
+ | X86_XSTATE_CET_U)
#define X86_XSTATE_SSE_SIZE 576
#define X86_XSTATE_AVX_SIZE 832