From: Keith Seitz <keiths@redhat.com>
To: gdb-patches@sourceware.org
Subject: [PATCH v2] Add gstack script
Date: Thu, 12 Dec 2024 13:07:41 -0800 [thread overview]
Message-ID: <08a19a3debe4a1e3c6072a807e79566277a7c0dc.1734022384.git.keiths@redhat.com> (raw)
In-Reply-To: <ad8ac1e5d5b9c0c84150daa6800c3bc918879a4f.1732557806.git.keiths@redhat.com>
--- Changes in v2
- Review feedback from Andrew Burgess
o Don't chmod gstack.in in configure.ac.
o Fix testsuite issues which could mislead users into thinking
that tests succeeded when they did not.
---
This commit adds support for a `gstack' command which Fedora has
been carrying for many years. gstack is a natural counterpart to
the gcore command. Whereas gcore dumps a core file, gstack prints
stack traces of a running process.
There are many improvements over Fedora's version of this script.
The dependency on procfs is gone; gstack will run anywhere gdb
runs. The only runtime dependencies are bash and awk.
The script includes suggestions from gdb/32325 to include
versioning and help. [If this approach to gdb/32325 is acceptable,
I could propagate the solution to gcore/gdb-add-index.]
I've rewritten the documentation, integrating it into the User Manual.
The manpage is now output using this one source.
Example run (on x86_64 Fedora 40)
$ gstack --help
Usage: gstack [-h|--help] [-v|--version] PID
Print a stack trace of a running program
-h, --help Print this message then exit.
-v, --version Print version information then exit.
$ gstack -v
GNU gstack (GDB) 16.0.50.20241119-git
$ gstack 12345678
Process 12345678 not found.
$ gstack $(pidof emacs)
Thread 6 (Thread 0x7f382a8006c0 (LWP 1265626) "pool-spawner"):
#0 0x00007f383ffca3dd in syscall () at /lib64/libc.so.6
#1 0x00007f3849cc0ccd in g_cond_wait () at /lib64/libglib-2.0.so.0
#2 0x00007f3849c2c61b in g_async_queue_pop_intern_unlocked () at /lib64/libglib-2.0.so.0
#3 0x00007f3849c93a03 in g_thread_pool_spawn_thread () at /lib64/libglib-2.0.so.0
#4 0x00007f3849c92813 in g_thread_proxy () at /lib64/libglib-2.0.so.0
#5 0x00007f383ff486d7 in start_thread () at /lib64/libc.so.6
#6 0x00007f383ffcc60c in clone3 () at /lib64/libc.so.6
Thread 5 (Thread 0x7f3829e006c0 (LWP 1265627) "gmain"):
#0 0x00007f383ffbe87d in poll () at /lib64/libc.so.6
#1 0x00007f3849cc3c34 in g_main_context_iterate_unlocked.isra () at /lib64/libglib-2.0.so.0
#2 0x00007f3849c63383 in g_main_context_iteration () at /lib64/libglib-2.0.so.0
#3 0x00007f3849c633e1 in glib_worker_main () at /lib64/libglib-2.0.so.0
#4 0x00007f3849c92813 in g_thread_proxy () at /lib64/libglib-2.0.so.0
#5 0x00007f383ff486d7 in start_thread () at /lib64/libc.so.6
#6 0x00007f383ffcc60c in clone3 () at /lib64/libc.so.6
Thread 4 (Thread 0x7f38294006c0 (LWP 1265628) "gdbus"):
#0 0x00007f383ffbe87d in poll () at /lib64/libc.so.6
#1 0x00007f3849cc3c34 in g_main_context_iterate_unlocked.isra () at /lib64/libglib-2.0.so.0
#2 0x00007f3849c67f37 in g_main_loop_run () at /lib64/libglib-2.0.so.0
#3 0x00007f3849ec7682 in gdbus_shared_thread_func.lto_priv () at /lib64/libgio-2.0.so.0
#4 0x00007f3849c92813 in g_thread_proxy () at /lib64/libglib-2.0.so.0
#5 0x00007f383ff486d7 in start_thread () at /lib64/libc.so.6
#6 0x00007f383ffcc60c in clone3 () at /lib64/libc.so.6
Thread 3 (Thread 0x7f3828a006c0 (LWP 1265629) "emacs"):
#0 0x00007f383ffca3dd in syscall () at /lib64/libc.so.6
#1 0x00007f3849cc0ccd in g_cond_wait () at /lib64/libglib-2.0.so.0
#2 0x00007f3849c2c61b in g_async_queue_pop_intern_unlocked () at /lib64/libglib-2.0.so.0
#3 0x00007f3849c2c67c in g_async_queue_pop () at /lib64/libglib-2.0.so.0
#4 0x00007f3842c340d9 in fc_thread_func () at /lib64/libpangoft2-1.0.so.0
#5 0x00007f3849c92813 in g_thread_proxy () at /lib64/libglib-2.0.so.0
#6 0x00007f383ff486d7 in start_thread () at /lib64/libc.so.6
#7 0x00007f383ffcc60c in clone3 () at /lib64/libc.so.6
Thread 2 (Thread 0x7f3823e006c0 (LWP 1265630) "dconf worker"):
#0 0x00007f383ffbe87d in poll () at /lib64/libc.so.6
#1 0x00007f3849cc3c34 in g_main_context_iterate_unlocked.isra () at /lib64/libglib-2.0.so.0
#2 0x00007f3849c63383 in g_main_context_iteration () at /lib64/libglib-2.0.so.0
#3 0x00007f382a845705 in dconf_gdbus_worker_thread () at /usr/lib64/gio/modules/libdconfsettings.so
#4 0x00007f3849c92813 in g_thread_proxy () at /lib64/libglib-2.0.so.0
#5 0x00007f383ff486d7 in start_thread () at /lib64/libc.so.6
#6 0x00007f383ffcc60c in clone3 () at /lib64/libc.so.6
Thread 1 (Thread 0x7f383b642280 (LWP 1265621) "emacs"):
#0 0x00007f383ffc9197 in pselect () at /lib64/libc.so.6
#1 0x00000000006b9e01 in really_call_select.lto_priv ()
#2 0x00000000006e1979 in xg_select ()
#3 0x00000000006899d1 in wait_reading_process_output ()
#4 0x000000000057e91c in kbd_buffer_get_event ()
#5 0x0000000000580bc6 in read_char ()
#6 0x0000000000589c03 in read_key_sequence.lto_priv ()
#7 0x0000000000576135 in command_loop_1.lto_priv ()
#8 0x00000000006131ce in internal_condition_case ()
#9 0x000000000057569e in command_loop_2 ()
#10 0x0000000000613127 in internal_catch ()
#11 0x0000000000575af3 in command_loop ()
#12 0x0000000000575bef in recursive_edit_1 ()
#13 0x0000000000575ddd in Frecursive_edit ()
#14 0x00000000004795a9 in main ()
Since this is essentially a complete rewrite of the original
script and documentation, I've chosen to only keep a 2024 copyright date.
---
gdb/Makefile.in | 38 ++++++++-
gdb/NEWS | 3 +
gdb/configure | 14 +++-
gdb/configure.ac | 7 ++
gdb/doc/Makefile.in | 11 ++-
gdb/doc/gdb.texinfo | 48 ++++++++++++
gdb/gstack-1.in | 126 ++++++++++++++++++++++++++++++
gdb/testsuite/gdb.base/gstack.c | 32 ++++++++
gdb/testsuite/gdb.base/gstack.exp | 85 ++++++++++++++++++++
9 files changed, 359 insertions(+), 5 deletions(-)
create mode 100755 gdb/gstack-1.in
create mode 100644 gdb/testsuite/gdb.base/gstack.c
create mode 100644 gdb/testsuite/gdb.base/gstack.exp
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 52950759711..aae7a8b4790 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -590,6 +590,7 @@ CONFIG_CLEAN = @CONFIG_CLEAN@
CONFIG_INSTALL = @CONFIG_INSTALL@
CONFIG_UNINSTALL = @CONFIG_UNINSTALL@
HAVE_NATIVE_GCORE_TARGET = @HAVE_NATIVE_GCORE_TARGET@
+HAVE_GSTACK = @HAVE_GSTACK@
CONFIG_SRC_SUBDIR = arch cli dwarf2 mi compile tui unittests guile python \
target nat
@@ -1945,7 +1946,7 @@ generated_files = \
# Flags needed to compile Python code
PYTHON_CFLAGS = @PYTHON_CFLAGS@
-all: gdb$(EXEEXT) $(CONFIG_ALL) gdb-gdb.py gdb-gdb.gdb gcore
+all: gdb$(EXEEXT) $(CONFIG_ALL) gdb-gdb.py gdb-gdb.gdb gcore gstack
@$(MAKE) $(FLAGS_TO_PASS) DO=all "DODIRS=$(SUBDIRS)" subdir_do
# Rule for compiling .c files in the top-level gdb directory.
@@ -2104,6 +2105,19 @@ install-only: $(CONFIG_INSTALL)
$(INSTALL_SCRIPT) gcore \
$(DESTDIR)$(bindir)/$$transformed_name; \
fi
+ if test "x${HAVE_GSTACK}" != x; \
+ then \
+ transformed_name=`t='$(program_transform_name)'; \
+ echo gstack | sed -e "$$t"` ; \
+ if test "x$$transformed_name" = x; then \
+ transformed_name=gstack ; \
+ else \
+ true ; \
+ fi ; \
+ $(SHELL) $(srcdir)/../mkinstalldirs $(DESTDIR)$(bindir) ; \
+ $(INSTALL_SCRIPT) gstack \
+ $(DESTDIR)$(bindir)/$$transformed_name; \
+ fi
transformed_name=`t='$(program_transform_name)'; \
echo gdb-add-index | sed -e "$$t"` ; \
if test "x$$transformed_name" = x; then \
@@ -2148,6 +2162,17 @@ uninstall: force $(CONFIG_UNINSTALL)
fi ; \
rm -f $(DESTDIR)$(bindir)/$$transformed_name; \
fi
+ if test "x$(HAVE_GSTACK)" != x; \
+ then \
+ transformed_name=`t='$(program_transform_name)'; \
+ echo gstack | sed -e "$$t"` ; \
+ if test "x$$transformed_name" = x; then \
+ transformed_name=gstack ; \
+ else \
+ true ; \
+ fi ; \
+ rm -f $(DESTDIR)$(bindir)/$$transformed_name; \
+ fi
transformed_name=`t='$(program_transform_name)'; \
echo gdb-add-index | sed -e "$$t"` ; \
if test "x$$transformed_name" = x; then \
@@ -2259,7 +2284,7 @@ clean mostlyclean: $(CONFIG_CLEAN)
# functionality described is if the distributed files are unmodified.
distclean: clean
@$(MAKE) $(FLAGS_TO_PASS) DO=distclean "DODIRS=$(CLEANDIRS)" subdir_do
- rm -f nm.h config.status config.h stamp-h b jit-reader.h gcore stamp-nmh
+ rm -f nm.h config.status config.h stamp-h b jit-reader.h gcore gstack gstack.in stamp-nmh
rm -f gdb-gdb.py gdb-gdb.gdb
rm -f y.output yacc.acts yacc.tmp y.tab.h
rm -f config.log config.cache
@@ -2320,6 +2345,15 @@ jit-reader.h: $(srcdir)/jit-reader.in config.status
gcore: $(srcdir)/gcore.in config.status
$(ECHO_GEN) $(SHELL) config.status $(SILENT_FLAG) $@
+gstack: gstack.in version.c
+ $(ECHO_GEN) \
+ vv=`grep 'version\[\] = ' version.c | grep -o '".*"' | tr -d \"`; \
+ sed -e "s,@VERSION@,$$vv," $< > $@
+ @chmod +x $@
+
+gstack.in: $(srcdir)/gstack-1.in config.status
+ $(ECHO_GEN) $(SHELL) config.status $(SILENT_FLAG) $@
+
gdb-gdb.py: $(srcdir)/gdb-gdb.py.in config.status
$(ECHO_GEN) $(SHELL) config.status $(SILENT_FLAG) $@
diff --git a/gdb/NEWS b/gdb/NEWS
index 7f0bd7edfc8..465217b388c 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -62,6 +62,9 @@
* Support for process record/replay and reverse debugging on loongarch*-linux*
targets has been added.
+* Newly installed $prefix/bin/gstack uses GDB to print stack traces of
+ running processes.
+
* Python API
** Added gdb.record.clear. Clears the trace data of the current recording.
diff --git a/gdb/configure b/gdb/configure
index de750f4fafe..1531f62f76a 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -760,6 +760,7 @@ HAVE_NATIVE_GCORE_TARGET
TARGET_OBS
AMD_DBGAPI_LIBS
AMD_DBGAPI_CFLAGS
+HAVE_GSTACK
ENABLE_BFD_64_BIT_FALSE
ENABLE_BFD_64_BIT_TRUE
subdirs
@@ -11499,7 +11500,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11502 "configure"
+#line 11503 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -11605,7 +11606,7 @@ else
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
lt_status=$lt_dlunknown
cat > conftest.$ac_ext <<_LT_EOF
-#line 11608 "configure"
+#line 11609 "configure"
#include "confdefs.h"
#if HAVE_DLFCN_H
@@ -25008,6 +25009,12 @@ if test x${all_targets} = xtrue; then
fi
fi
+HAVE_GSTACK=0
+if test $gdb_native = yes; then
+ HAVE_GSTACK=1
+fi
+
+
# AMD debugger API support.
@@ -33761,6 +33768,8 @@ fi
ac_config_files="$ac_config_files gcore"
+ac_config_files="$ac_config_files gstack.in:gstack-1.in"
+
ac_config_files="$ac_config_files Makefile gdb-gdb.gdb gdb-gdb.py doc/Makefile data-directory/Makefile"
@@ -34861,6 +34870,7 @@ do
"jit-reader.h") CONFIG_FILES="$CONFIG_FILES jit-reader.h:jit-reader.in" ;;
"nm.h") CONFIG_LINKS="$CONFIG_LINKS nm.h:$GDB_NM_FILE" ;;
"gcore") CONFIG_FILES="$CONFIG_FILES gcore" ;;
+ "gstack.in") CONFIG_FILES="$CONFIG_FILES gstack.in:gstack-1.in" ;;
"Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
"gdb-gdb.gdb") CONFIG_FILES="$CONFIG_FILES gdb-gdb.gdb" ;;
"gdb-gdb.py") CONFIG_FILES="$CONFIG_FILES gdb-gdb.py" ;;
diff --git a/gdb/configure.ac b/gdb/configure.ac
index 230c0be79c7..e9312b1bc64 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -261,6 +261,12 @@ if test x${all_targets} = xtrue; then
fi
fi
+HAVE_GSTACK=0
+if test $gdb_native = yes; then
+ HAVE_GSTACK=1
+fi
+AC_SUBST(HAVE_GSTACK)
+
# AMD debugger API support.
AC_ARG_WITH([amd-dbgapi],
@@ -2264,6 +2270,7 @@ GDB_AC_SELFTEST([
GDB_AC_TRANSFORM([gdb], [GDB_TRANSFORM_NAME])
GDB_AC_TRANSFORM([gcore], [GCORE_TRANSFORM_NAME])
AC_CONFIG_FILES([gcore], [chmod +x gcore])
+AC_CONFIG_FILES([gstack.in:gstack-1.in])
AC_CONFIG_FILES([Makefile gdb-gdb.gdb gdb-gdb.py doc/Makefile data-directory/Makefile])
AC_OUTPUT
diff --git a/gdb/doc/Makefile.in b/gdb/doc/Makefile.in
index 181325fd0c9..c75714b5de2 100644
--- a/gdb/doc/Makefile.in
+++ b/gdb/doc/Makefile.in
@@ -188,7 +188,7 @@ TEXI2POD = perl $(srcdir)/../../etc/texi2pod.pl \
POD2MAN = pod2man --center="GNU Development Tools"
# List of man pages generated from gdb.texi
-MAN1S = gdb.1 gdbserver.1 gcore.1 gdb-add-index.1
+MAN1S = gdb.1 gdbserver.1 gcore.1 gstack.1 gdb-add-index.1
MAN5S = gdbinit.5
MANS = $(MAN1S) $(MAN5S)
@@ -199,6 +199,7 @@ POD_FILE_TMPS = $(patsubst %.1,%.pod,$(MAN1S)) \
HAVE_NATIVE_GCORE_TARGET = @HAVE_NATIVE_GCORE_TARGET@
HAVE_NATIVE_GCORE_HOST = @HAVE_NATIVE_GCORE_HOST@
+HAVE_GSTACK = @HAVE_GSTACK@
###
@@ -339,6 +340,10 @@ install-man1: $(MAN1S)
-a "$$p" = gcore.1; then \
continue; \
fi; \
+ if test "x$(HAVE_GSTACK)" = x \
+ -a "$$p" = gstack.1; then \
+ continue; \
+ fi; \
if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \
f=`echo $$p | sed -e 's|^.*/||' -e '$(transform)'`; \
echo " $(INSTALL_DATA) '$$d$$p' '$(DESTDIR)$(man1dir)/$$f'"; \
@@ -363,6 +368,10 @@ uninstall-man1:
-a "$$i" = gcore.1; then \
continue; \
fi; \
+ if test "x$(HAVE_GSTACK)" = x \
+ -a "$$i" = gstack.1; then \
+ continue; \
+ fi; \
echo "$$i"; \
done | \
sed -n '/\.1[a-z]*$$/p'; \
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index 85ac3d9aab6..3cae61a8e5b 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -50553,6 +50553,7 @@ Show the current verbosity setting.
* gdb man:: The GNU Debugger man page
* gdbserver man:: Remote Server for the GNU Debugger man page
* gcore man:: Generate a core file of a running program
+* gstack man:: Print a stack trace of a running program
* gdbinit man:: gdbinit scripts
* gdb-add-index man:: Add index files to speed up GDB
@end menu
@@ -51235,6 +51236,53 @@ Richard M. Stallman and Roland H. Pesch, July 1991.
@end ifset
@c man end
+@node gstack man
+@heading gstack
+
+@c man title gstack Print a stack trace of a running program
+
+@format
+@c man begin SYNOPSIS gstack
+gstack [-h | --help] [-v | --version] @var{pid}
+@c man end
+@end format
+
+@c man begin DESCRIPTION gstack
+Print a stack trace of a running program with process ID @var{pid}. If the process
+is multi-threaded, @command{gstack} outputs backtraces for every thread which exists
+in the process.
+@c man end
+
+@c man begin OPTIONS gstack
+@table @env
+@item --help
+@itemx -h
+List all options, with brief explanations.
+
+@item --version
+@itemx -v
+Print version information and then exit.
+@end table
+@c man end
+
+@c man begin SEEALSO gstack
+@ifset man
+The full documentation for @value{GDBN} is maintained as a Texinfo manual.
+If the @code{info} and @code{gdb} programs and @value{GDBN}'s Texinfo
+documentation are properly installed at your site, the command
+
+@smallexample
+info gdb
+@end smallexample
+
+@noindent
+should give you access to the complete manual.
+
+@cite{Using GDB: A Guide to the GNU Source-Level Debugger},
+Richard M. Stallman and Roland H. Pesch, July 1991.
+@end ifset
+@c man end
+
@node gdbinit man
@heading gdbinit
diff --git a/gdb/gstack-1.in b/gdb/gstack-1.in
new file mode 100755
index 00000000000..53249f01399
--- /dev/null
+++ b/gdb/gstack-1.in
@@ -0,0 +1,126 @@
+#!/usr/bin/env bash
+
+# Copyright (C) 2024 Free Software Foundation, Inc.
+
+# 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/>.
+
+# Print a stack trace of a running process.
+# Similar to the gcore command, but instead of creating a core file,
+# we simply have gdb print out the stack backtrace to the terminal.
+
+GDB=${GDB:-$(command -v gdb)}
+GDBARGS=${GDBARGS:-}
+PKGVERSION=@PKGVERSION@
+VERSION=@VERSION@
+
+function print_usage() {
+ echo "Usage: $0 [-h|--help] [-v|--version] PID" 1>&2
+}
+
+function print_try_help() {
+ echo "Try '$0 --help' for more information."
+}
+
+function print_help() {
+ print_usage
+ echo "Print a stack trace of a running program"
+ echo
+ echo " -h, --help Print this message then exit."
+ echo " -v, --version Print version information then exit."
+}
+
+function print_version() {
+ echo "GNU gstack (${PKGVERSION}) ${VERSION}"
+}
+
+# Parse options.
+while getopts hv-: OPT; do
+ if [ "$OPT" = "-" ]; then
+ OPT="${OPTARG%%=*}"
+ OPTARG="${OPTARG#'$OPT'}"
+ OPTARG="${OPTARG#=}"
+ fi
+
+ case "$OPT" in
+ h | help)
+ print_help
+ exit 0
+ ;;
+ v | version)
+ print_version
+ exit 0
+ ;;
+ \?)
+ # getopts has already output an error message.
+ print_try_help
+ exit 2 ;;
+ *)
+ echo "$0: unrecognized option '--$OPT'" >&2
+ print_try_help
+ exit 2
+ ;;
+ esac
+done
+shift $((OPTIND-1))
+
+# The sole remaining argument should be the PID of the process
+# whose backtrace is desired.
+if [ $# -ne 1 ]; then
+ print_usage
+ exit 1
+fi
+
+PID=$1
+
+awk_script=$(cat << EOF
+BEGIN {
+ first=1
+ attach_okay=0
+}
+
+/ATTACHED/ {
+ attach_okay=1
+}
+
+/^#/ {
+ if (attach_okay) {
+ print \$0
+ }
+}
+
+/^Thread/ {
+ if (attach_okay) {
+ if (!first)
+ print ""
+ first=0
+ print \$0
+ }
+}
+EOF
+ )
+
+# Run GDB and remove some unwanted noise.
+$GDB --quiet -nx $GDBARGS <<EOF |
+set width 0
+set height 0
+set pagination no
+set debuginfod enabled off
+define attach-bt
+attach \$arg0
+echo "ATTACHED"
+thread apply all bt
+end
+attach-bt $PID
+EOF
+awk -- "$awk_script"
diff --git a/gdb/testsuite/gdb.base/gstack.c b/gdb/testsuite/gdb.base/gstack.c
new file mode 100644
index 00000000000..639e9a7ea93
--- /dev/null
+++ b/gdb/testsuite/gdb.base/gstack.c
@@ -0,0 +1,32 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+ Copyright 2024 Free Software Foundation, Inc.
+
+ 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 <unistd.h>
+#include <string.h>
+
+int
+main (void)
+{
+ const char msg[] = "looping\n";
+
+ /* Output a simple string for the expect script to monitor us. */
+ write (1, msg, strlen (msg));
+
+ for (;;) ; /* forever */
+
+ return 0;
+}
diff --git a/gdb/testsuite/gdb.base/gstack.exp b/gdb/testsuite/gdb.base/gstack.exp
new file mode 100644
index 00000000000..66ca233fa5b
--- /dev/null
+++ b/gdb/testsuite/gdb.base/gstack.exp
@@ -0,0 +1,85 @@
+# Copyright (C) 2024 Free Software Foundation, Inc.
+
+# 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/>.
+
+require !gdb_protocol_is_remote
+standard_testfile
+
+if {[prepare_for_testing "failed to prepare" $testfile $srcfile {debug}] == -1} {
+ return -1
+}
+
+set command "$binfile"
+set res [remote_spawn host $command]
+if { ![gdb_assert { ![expr {$res < 0 || $res == ""}] } "spawn inferior"] } {
+ return
+}
+
+# The spawn id of the test inferior.
+set test_spawn_id $res
+
+# Wait for the spawned program to loop.
+set test "wait for inferior to loop"
+gdb_expect {
+ -re "looping\r\n" {
+ pass $test
+ }
+ eof {
+ fail "$test (eof)"
+ return
+ }
+ timeout {
+ fail "$test (timeout)"
+ return
+ }
+}
+
+# The test case uses a very simple notification not to get caught by attach on
+# exiting the function.
+
+set test "spawn gstack"
+set pid [spawn_id_get_pid $test_spawn_id]
+set gstack_cmd [findfile $base_dir/../../gdb/gstack]
+set command "sh -c GDB=$GDB\\ GDBARGS=-data-directory\\\\\\ $GDB_DATA_DIRECTORY\\ $gstack_cmd\\ $pid\\;echo\\ GSTACK-END"
+set res [remote_spawn host $command]
+if { ![gdb_assert { ![expr {$res < 0 || $res == ""}] } $test] } {
+ return
+}
+
+set test "got backtrace"
+set saw_backtrace false
+set lineno [gdb_get_line_number "forever"]
+gdb_test_multiple "" $test {
+ -i "$res" -re "#0 +(0x\[0-9a-f\]+ in )?main \(\).*${srcfile}:$lineno.*\r\nGSTACK-END\r\n\$" {
+ set saw_backtrace true
+ pass $test
+ exp_continue
+ }
+
+ eof {
+ set result [wait -i $res]
+ verbose $result
+
+ gdb_assert { [lindex $result 2] == 0 } "gstack exits with no error"
+ gdb_assert { [lindex $result 3] == 0 } "gstack's exit status is 0"
+
+ remote_close host
+ }
+}
+if {!$saw_backtrace} {
+ fail $test
+}
+
+# Kill the test inferior.
+kill_wait_spawned_process $test_spawn_id
base-commit: a5939d229614a4913daf3c687ec54fdf3020d496
--
2.47.0
next prev parent reply other threads:[~2024-12-12 21:14 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-11-25 18:18 [PATCH] " Keith Seitz
2024-12-11 16:51 ` Andrew Burgess
2024-12-11 16:58 ` Keith Seitz
2024-12-12 21:07 ` Keith Seitz [this message]
2024-12-13 7:36 ` [PATCH v2] " Eli Zaretskii
2024-12-13 18:21 ` Keith Seitz
2024-12-13 19:04 ` Eli Zaretskii
2024-12-13 19:45 ` Tom Tromey
2024-12-13 19:57 ` Keith Seitz
2024-12-18 18:05 ` [PATCH v3] " Keith Seitz
2024-12-18 19:22 ` Eli Zaretskii
2024-12-18 21:47 ` Keith Seitz
2024-12-20 16:15 ` Tom Tromey
2024-12-20 18:18 ` Keith Seitz
2024-12-20 18:26 ` Tom Tromey
2024-12-20 20:47 ` Keith Seitz
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=08a19a3debe4a1e3c6072a807e79566277a7c0dc.1734022384.git.keiths@redhat.com \
--to=keiths@redhat.com \
--cc=gdb-patches@sourceware.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox