Blame SOURCES/gdb-6.5-BEA-testsuite.patch

4c2ad1
From FEDORA_PATCHES Mon Sep 17 00:00:00 2001
4c2ad1
From: Fedora GDB patches <invalid@email.com>
4c2ad1
Date: Fri, 27 Oct 2017 21:07:50 +0200
4c2ad1
Subject: gdb-6.5-BEA-testsuite.patch
4c2ad1
4c2ad1
;; Improved testsuite results by the testsuite provided by the courtesy of BEA.
4c2ad1
;;=fedoratest: For upstream it should be rewritten as a dejagnu test, the test of no "??" was useful.
4c2ad1
4c2ad1
diff --git a/gdb/testsuite/gdb.threads/threadcrash.c b/gdb/testsuite/gdb.threads/threadcrash.c
4c2ad1
new file mode 100644
4c2ad1
--- /dev/null
4c2ad1
+++ b/gdb/testsuite/gdb.threads/threadcrash.c
4c2ad1
@@ -0,0 +1,301 @@
4c2ad1
+/*
4c2ad1
+ * The point of this program is to crash in a multi-threaded app.
4c2ad1
+ * There are seven threads, doing the following things:
4c2ad1
+ * * Spinning
4c2ad1
+ * * Spinning inside a signal handler
4c2ad1
+ * * Spinning inside a signal handler executing on the altstack
4c2ad1
+ * * In a syscall
4c2ad1
+ * * In a syscall inside a signal handler
4c2ad1
+ * * In a syscall inside a signal handler executing on the altstack
4c2ad1
+ * * Finally, the main thread crashes in main, with no frills.
4c2ad1
+ *
4c2ad1
+ * These are the things threads in JRockit tend to be doing.  If gdb
4c2ad1
+ * can handle those things, both in core files and during live
4c2ad1
+ * debugging, that will help (at least) JRockit development.
4c2ad1
+ *
4c2ad1
+ * Let the program create a core file, then load the core file into
4c2ad1
+ * gdb.  Inside gdb, you should be able to do something like this:
4c2ad1
+ *
4c2ad1
+ * (gdb) t a a bt
4c2ad1
+ * 
4c2ad1
+ * Thread 7 (process 4352):
4c2ad1
+ * #0  0x001ba7dc in __nanosleep_nocancel () from /lib/tls/libc.so.6
4c2ad1
+ * #1  0x001ba5ff in sleep () from /lib/tls/libc.so.6
4c2ad1
+ * #2  0x080488a2 in makeSyscall (ignored=0x0) at threadcrash.c:118
4c2ad1
+ * #3  0x006aadec in start_thread () from /lib/tls/libpthread.so.0
4c2ad1
+ * #4  0x001ed19a in clone () from /lib/tls/libc.so.6
4c2ad1
+ * 
4c2ad1
+ * Thread 6 (process 4353):
4c2ad1
+ * #0  0x001ba7dc in __nanosleep_nocancel () from /lib/tls/libc.so.6
4c2ad1
+ * #1  0x001ba5ff in sleep () from /lib/tls/libc.so.6
4c2ad1
+ * #2  0x0804898f in syscallingSighandler (signo=10, info=0xb6be76f0, context=0xb6be7770)
4c2ad1
+ *     at threadcrash.c:168
4c2ad1
+ * #3  <signal handler called>
4c2ad1
+ * #4  0x006adf5e in pthread_kill () from /lib/tls/libpthread.so.0
4c2ad1
+ * #5  0x08048a51 in makeSyscallFromSighandler (ignored=0x0) at threadcrash.c:204
4c2ad1
+ * #6  0x006aadec in start_thread () from /lib/tls/libpthread.so.0
4c2ad1
+ * #7  0x001ed19a in clone () from /lib/tls/libc.so.6
4c2ad1
+ * 
4c2ad1
+ * Thread 5 (process 4354):
4c2ad1
+ * #0  0x001ba7dc in __nanosleep_nocancel () from /lib/tls/libc.so.6
4c2ad1
+ * #1  0x001ba5ff in sleep () from /lib/tls/libc.so.6
4c2ad1
+ * #2  0x08048936 in syscallingAltSighandler (signo=3, info=0x959cd70, context=0x959cdf0)
4c2ad1
+ *     at threadcrash.c:144
4c2ad1
+ * #3  <signal handler called>
4c2ad1
+ * #4  0x006adf5e in pthread_kill () from /lib/tls/libpthread.so.0
4c2ad1
+ * #5  0x080489e2 in makeSyscallFromAltSighandler (ignored=0x0) at threadcrash.c:190
4c2ad1
+ * #6  0x006aadec in start_thread () from /lib/tls/libpthread.so.0
4c2ad1
+ * #7  0x001ed19a in clone () from /lib/tls/libc.so.6
4c2ad1
+ * 
4c2ad1
+ * Thread 4 (process 4355):
4c2ad1
+ * #0  spin (ignored=0x0) at threadcrash.c:242
4c2ad1
+ * #1  0x006aadec in start_thread () from /lib/tls/libpthread.so.0
4c2ad1
+ * #2  0x001ed19a in clone () from /lib/tls/libc.so.6
4c2ad1
+ * 
4c2ad1
+ * Thread 3 (process 4356):
4c2ad1
+ * #0  spinningSighandler (signo=12, info=0xb4de46f0, context=0xb4de4770) at threadcrash.c:180
4c2ad1
+ * #1  <signal handler called>
4c2ad1
+ * #2  0x006adf5e in pthread_kill () from /lib/tls/libpthread.so.0
4c2ad1
+ * #3  0x08048b2f in spinFromSighandler (ignored=0x0) at threadcrash.c:232
4c2ad1
+ * #4  0x006aadec in start_thread () from /lib/tls/libpthread.so.0
4c2ad1
+ * #5  0x001ed19a in clone () from /lib/tls/libc.so.6
4c2ad1
+ * 
4c2ad1
+ * Thread 2 (process 4357):
4c2ad1
+ * #0  spinningAltSighandler (signo=14, info=0x959ee50, context=0x959eed0) at threadcrash.c:156
4c2ad1
+ * #1  <signal handler called>
4c2ad1
+ * #2  0x006adf5e in pthread_kill () from /lib/tls/libpthread.so.0
4c2ad1
+ * #3  0x08048ac0 in spinFromAltSighandler (ignored=0x0) at threadcrash.c:218
4c2ad1
+ * #4  0x006aadec in start_thread () from /lib/tls/libpthread.so.0
4c2ad1
+ * #5  0x001ed19a in clone () from /lib/tls/libc.so.6
4c2ad1
+ * 
4c2ad1
+ * Thread 1 (process 4351):
4c2ad1
+ * #0  0x08048cf3 in main (argc=1, argv=0xbfff9d74) at threadcrash.c:273
4c2ad1
+ * (gdb)
4c2ad1
+ */
4c2ad1
+
4c2ad1
+#include <pthread.h>
4c2ad1
+#include <signal.h>
4c2ad1
+#include <assert.h>
4c2ad1
+#include <unistd.h>
4c2ad1
+#include <stdio.h>
4c2ad1
+#include <stdlib.h>
4c2ad1
+#include <string.h>
4c2ad1
+
4c2ad1
+#define SIGSYSCALL_ALT SIGQUIT
4c2ad1
+#define SIGSYSCALL SIGUSR1
4c2ad1
+#define SIGSPIN_ALT SIGALRM
4c2ad1
+#define SIGSPIN SIGUSR2
4c2ad1
+
4c2ad1
+typedef void (*sigaction_t)(int, siginfo_t *, void *);
4c2ad1
+
4c2ad1
+static void installHandler(int signo, sigaction_t handler, int onAltstack) {
4c2ad1
+   struct sigaction action;
4c2ad1
+   sigset_t sigset;
4c2ad1
+   int result;
4c2ad1
+   stack_t altstack;
4c2ad1
+   stack_t oldaltstack;
4c2ad1
+   
4c2ad1
+   memset(&action, 0, sizeof(action));
4c2ad1
+   memset(&altstack, 0, sizeof(altstack));
4c2ad1
+   memset(&oldaltstack, 0, sizeof(oldaltstack));
4c2ad1
+   
4c2ad1
+   if (onAltstack) {
4c2ad1
+      altstack.ss_sp = malloc(SIGSTKSZ);
4c2ad1
+      assert(altstack.ss_sp != NULL);
4c2ad1
+      altstack.ss_size = SIGSTKSZ;
4c2ad1
+      altstack.ss_flags = 0;
4c2ad1
+      result = sigaltstack(&altstack, &oldaltstack);
4c2ad1
+      assert(result == 0);
4c2ad1
+      assert(oldaltstack.ss_flags == SS_DISABLE);
4c2ad1
+   }
4c2ad1
+   
4c2ad1
+   sigemptyset(&sigset);
4c2ad1
+   
4c2ad1
+   action.sa_handler = NULL;
4c2ad1
+   action.sa_sigaction = handler;
4c2ad1
+   action.sa_mask = sigset;
4c2ad1
+   action.sa_flags = SA_SIGINFO;
4c2ad1
+   if (onAltstack) {
4c2ad1
+      action.sa_flags |= SA_ONSTACK;
4c2ad1
+   }
4c2ad1
+   
4c2ad1
+   result = sigaction(signo, &action, NULL);
4c2ad1
+   assert(result == 0);
4c2ad1
+}
4c2ad1
+
4c2ad1
+static void installNormalHandler(int signo, sigaction_t handler) {
4c2ad1
+   installHandler(signo, handler, 0);
4c2ad1
+}
4c2ad1
+
4c2ad1
+static void installAlthandler(int signo, sigaction_t handler) {
4c2ad1
+   installHandler(signo, handler, 1);
4c2ad1
+}
4c2ad1
+
4c2ad1
+static void *makeSyscall(void *ignored) {
4c2ad1
+   (void)ignored;
4c2ad1
+
4c2ad1
+   sleep(42);
4c2ad1
+
4c2ad1
+   fprintf(stderr, "%s: returning\n", __FUNCTION__);
4c2ad1
+   return NULL;
4c2ad1
+}
4c2ad1
+
4c2ad1
+/* Return true if we're currently executing on the altstack */
4c2ad1
+static int onAltstack(void) {
4c2ad1
+   stack_t stack;
4c2ad1
+   int result;
4c2ad1
+   
4c2ad1
+   result = sigaltstack(NULL, &stack);
4c2ad1
+   assert(result == 0);
4c2ad1
+   
4c2ad1
+   return stack.ss_flags & SS_ONSTACK;
4c2ad1
+}
4c2ad1
+
4c2ad1
+static void syscallingAltSighandler(int signo, siginfo_t *info, void *context) {
4c2ad1
+   (void)signo;
4c2ad1
+   (void)info;
4c2ad1
+   (void)context;
4c2ad1
+   
4c2ad1
+   if (!onAltstack()) {
4c2ad1
+      printf("%s() not running on altstack!\n", __FUNCTION__);
4c2ad1
+   }
4c2ad1
+   
4c2ad1
+   sleep(42);
4c2ad1
+}
4c2ad1
+
4c2ad1
+static void spinningAltSighandler(int signo, siginfo_t *info, void *context) {
4c2ad1
+   (void)signo;
4c2ad1
+   (void)info;
4c2ad1
+   (void)context;
4c2ad1
+   
4c2ad1
+   if (!onAltstack()) {
4c2ad1
+      printf("%s() not running on altstack!\n", __FUNCTION__);
4c2ad1
+   }
4c2ad1
+   
4c2ad1
+   while (1);
4c2ad1
+}
4c2ad1
+
4c2ad1
+static void syscallingSighandler(int signo, siginfo_t *info, void *context) {
4c2ad1
+   (void)signo;
4c2ad1
+   (void)info;
4c2ad1
+   (void)context;
4c2ad1
+   
4c2ad1
+   if (onAltstack()) {
4c2ad1
+      printf("%s() running on altstack!\n", __FUNCTION__);
4c2ad1
+   }
4c2ad1
+   
4c2ad1
+   sleep(42);
4c2ad1
+}
4c2ad1
+
4c2ad1
+static void spinningSighandler(int signo, siginfo_t *info, void *context) {
4c2ad1
+   (void)signo;
4c2ad1
+   (void)info;
4c2ad1
+   (void)context;
4c2ad1
+   
4c2ad1
+   if (onAltstack()) {
4c2ad1
+      printf("%s() running on altstack!\n", __FUNCTION__);
4c2ad1
+   }
4c2ad1
+   
4c2ad1
+   while (1);
4c2ad1
+}
4c2ad1
+
4c2ad1
+static void *makeSyscallFromAltSighandler(void *ignored) {
4c2ad1
+   (void)ignored;
4c2ad1
+   
4c2ad1
+   int result;
4c2ad1
+   
4c2ad1
+   installAlthandler(SIGSYSCALL_ALT, syscallingAltSighandler);
4c2ad1
+   
4c2ad1
+   result = pthread_kill(pthread_self(), SIGSYSCALL_ALT);
4c2ad1
+   assert(result == 0);
4c2ad1
+   
4c2ad1
+   fprintf(stderr, "%s: returning\n", __FUNCTION__);
4c2ad1
+   return NULL;
4c2ad1
+}
4c2ad1
+
4c2ad1
+static void *makeSyscallFromSighandler(void *ignored) {
4c2ad1
+   (void)ignored;
4c2ad1
+   
4c2ad1
+   int result;
4c2ad1
+   
4c2ad1
+   installNormalHandler(SIGSYSCALL, syscallingSighandler);
4c2ad1
+   
4c2ad1
+   result = pthread_kill(pthread_self(), SIGSYSCALL);
4c2ad1
+   assert(result == 0);
4c2ad1
+   
4c2ad1
+   fprintf(stderr, "%s: returning\n", __FUNCTION__);
4c2ad1
+   return NULL;
4c2ad1
+}
4c2ad1
+
4c2ad1
+static void *spinFromAltSighandler(void *ignored) {
4c2ad1
+   (void)ignored;
4c2ad1
+   
4c2ad1
+   int result;
4c2ad1
+   
4c2ad1
+   installAlthandler(SIGSPIN_ALT, spinningAltSighandler);
4c2ad1
+   
4c2ad1
+   result = pthread_kill(pthread_self(), SIGSPIN_ALT);
4c2ad1
+   assert(result == 0);
4c2ad1
+   
4c2ad1
+   fprintf(stderr, "%s: returning\n", __FUNCTION__);
4c2ad1
+   return NULL;
4c2ad1
+}
4c2ad1
+
4c2ad1
+static void *spinFromSighandler(void *ignored) {
4c2ad1
+   (void)ignored;
4c2ad1
+   
4c2ad1
+   int result;
4c2ad1
+   
4c2ad1
+   installNormalHandler(SIGSPIN, spinningSighandler);
4c2ad1
+   
4c2ad1
+   result = pthread_kill(pthread_self(), SIGSPIN);
4c2ad1
+   assert(result == 0);
4c2ad1
+   
4c2ad1
+   fprintf(stderr, "%s: returning\n", __FUNCTION__);
4c2ad1
+   return NULL;
4c2ad1
+}
4c2ad1
+
4c2ad1
+static void *spin(void *ignored) {
4c2ad1
+   (void)ignored;
4c2ad1
+   
4c2ad1
+   while (1);
4c2ad1
+
4c2ad1
+   fprintf(stderr, "%s: returning\n", __FUNCTION__);
4c2ad1
+   return NULL;
4c2ad1
+}
4c2ad1
+
4c2ad1
+int main(int argc, char *argv[]) {
4c2ad1
+   int result;
4c2ad1
+   pthread_t thread;
4c2ad1
+   volatile int bad;
4c2ad1
+   
4c2ad1
+   result = pthread_create(&thread, NULL, makeSyscall, NULL);
4c2ad1
+   assert(result == 0);
4c2ad1
+   result = pthread_create(&thread, NULL, makeSyscallFromSighandler, NULL);
4c2ad1
+   assert(result == 0);
4c2ad1
+   result = pthread_create(&thread, NULL, makeSyscallFromAltSighandler, NULL);
4c2ad1
+   assert(result == 0);
4c2ad1
+   result = pthread_create(&thread, NULL, spin, NULL);
4c2ad1
+   assert(result == 0);
4c2ad1
+   result = pthread_create(&thread, NULL, spinFromSighandler, NULL);
4c2ad1
+   assert(result == 0);
4c2ad1
+   result = pthread_create(&thread, NULL, spinFromAltSighandler, NULL);
4c2ad1
+   assert(result == 0);
4c2ad1
+   
4c2ad1
+   // Give threads some time to get going
4c2ad1
+   sleep(3);
4c2ad1
+   
4c2ad1
+   // Crash
4c2ad1
+   bad = *(int*)7;
4c2ad1
+
4c2ad1
+   /* Workaround: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29628
4c2ad1
+      Simulate use to ensure `DW_AT_location' for them:
4c2ad1
+      readelf -a --debug threadcrash|grep -A5 -w argc
4c2ad1
+      --> DW_AT_location    : 2 byte block: 71 0     (DW_OP_breg1: 0)
4c2ad1
+      This case verified on: gcc-4.1.1-30.i386
4c2ad1
+      Keep it late to ensure persistency in the registers.  */
4c2ad1
+   bad = (int) argc;
4c2ad1
+   bad = (unsigned long) argv;
4c2ad1
+   
4c2ad1
+   return 0;
4c2ad1
+}
4c2ad1
diff --git a/gdb/testsuite/gdb.threads/threadcrash.exp b/gdb/testsuite/gdb.threads/threadcrash.exp
4c2ad1
new file mode 100644
4c2ad1
--- /dev/null
4c2ad1
+++ b/gdb/testsuite/gdb.threads/threadcrash.exp
4c2ad1
@@ -0,0 +1,37 @@
4c2ad1
+# threadcrash.exp - The point of this program is to crash in a multi-threaded app.
4c2ad1
+
4c2ad1
+
4c2ad1
+set testfile threadcrash
4c2ad1
+set srcfile ${testfile}.c
4c2ad1
+set shellfile ${srcdir}/${subdir}/${testfile}.sh
4c2ad1
+set binfile [standard_output_file ${testfile}]
4c2ad1
+
4c2ad1
+set GDB_abs ${GDB}
4c2ad1
+if [regexp "^\[^/\]" ${GDB_abs}] {
4c2ad1
+    set GDB_abs $env(PWD)/${GDB_abs}
4c2ad1
+}
4c2ad1
+
4c2ad1
+if [istarget "*-*-linux"] then {
4c2ad1
+    set target_cflags "-D_MIT_POSIX_THREADS"
4c2ad1
+} else {
4c2ad1
+    set target_cflags ""
4c2ad1
+}
4c2ad1
+
4c2ad1
+if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
4c2ad1
+    return -1
4c2ad1
+}
4c2ad1
+
4c2ad1
+# ${shellfile} argument must not contain any directories.
4c2ad1
+set fd [open "|bash ${shellfile} ${binfile} $GDB $INTERNAL_GDBFLAGS $GDBFLAGS [host_info gdb_opts]" r]
4c2ad1
+while { [gets $fd line] >= 0 } {
4c2ad1
+    if [regexp " PASS: (.*)$" $line trash message] {
4c2ad1
+	pass $message
4c2ad1
+    } elseif [regexp " FAIL: (.*)$" $line trash message] {
4c2ad1
+	fail $message
4c2ad1
+    }
4c2ad1
+}
4c2ad1
+catch {
4c2ad1
+    close $fd
4c2ad1
+}
4c2ad1
+
4c2ad1
+return 0
4c2ad1
diff --git a/gdb/testsuite/gdb.threads/threadcrash.sh b/gdb/testsuite/gdb.threads/threadcrash.sh
4c2ad1
new file mode 100644
4c2ad1
--- /dev/null
4c2ad1
+++ b/gdb/testsuite/gdb.threads/threadcrash.sh
4c2ad1
@@ -0,0 +1,324 @@
4c2ad1
+#! /bin/bash
4c2ad1
+
4c2ad1
+# NOTE: threadcrash.c *must* be built with debugging symbols
4c2ad1
+#
4c2ad1
+# The point of this shell script is to crash treadcrash.c, load the
4c2ad1
+# resulting core file into gdb and verify that gdb can extract enough
4c2ad1
+# information from the core file.
4c2ad1
+#
4c2ad1
+# The return code from this script is the number of failed tests.
4c2ad1
+
4c2ad1
+LOG=gdbresult.log
4c2ad1
+
4c2ad1
+if [ $# = 0 ] ; then
4c2ad1
+    echo >&2 Syntax: $0 \<name of threadcrash binary\> [\<gdb binary\> \<args...\>]
4c2ad1
+    exit 1
4c2ad1
+fi
4c2ad1
+RUNME="$1"
4c2ad1
+shift
4c2ad1
+GDB="${*:-gdb}"
4c2ad1
+
4c2ad1
+
4c2ad1
+pf_prefix=""
4c2ad1
+function pf_prefix() {
4c2ad1
+	pf_prefix="$*"
4c2ad1
+}
4c2ad1
+
4c2ad1
+set_test=""
4c2ad1
+function set_test() {
4c2ad1
+	if [ -n "$set_test" ] ; then
4c2ad1
+		echo >&2 "DEJAGNU-BASH ERROR: set_test already set"
4c2ad1
+		exit 1
4c2ad1
+	fi
4c2ad1
+	set_test="$*"
4c2ad1
+	if [ -n "$pf_prefix" ] ; then
4c2ad1
+		set_test="$pf_prefix: $set_test"
4c2ad1
+	fi
4c2ad1
+}
4c2ad1
+
4c2ad1
+# INTERNAL
4c2ad1
+function record_test {
4c2ad1
+	if [ -z "$set_test" ] ; then
4c2ad1
+		echo >&2 "DEJAGNU-BASH ERROR: set_test not set"
4c2ad1
+		exit 1
4c2ad1
+	fi
4c2ad1
+	# Provide the leading whitespace delimiter:
4c2ad1
+	echo " $1: $set_test"
4c2ad1
+	set_test=""
4c2ad1
+}
4c2ad1
+
4c2ad1
+function pass() {
4c2ad1
+	record_test PASS
4c2ad1
+}
4c2ad1
+function fail() {
4c2ad1
+	record_test FAIL
4c2ad1
+}
4c2ad1
+
4c2ad1
+
4c2ad1
+# Verify that the gdb output doesn't contain $1.
4c2ad1
+function mustNotHave() {
4c2ad1
+    local BADWORD=$1
4c2ad1
+    set_test gdb output contains "$BADWORD"
4c2ad1
+    if grep -q "$BADWORD" $LOG ; then
4c2ad1
+        fail
4c2ad1
+        return 1
4c2ad1
+    fi
4c2ad1
+    pass
4c2ad1
+    return 0
4c2ad1
+}
4c2ad1
+
4c2ad1
+# Verify that the gdb output contains exactly $1 $2s.
4c2ad1
+function mustHaveCorrectAmount() {
4c2ad1
+    local WANTEDNUMBER=$1
4c2ad1
+    local GOODWORD=$2
4c2ad1
+    local ACTUALNUMBER=$(grep "$GOODWORD" $LOG | wc -l)
4c2ad1
+    set_test gdb output contained $ACTUALNUMBER \""$GOODWORD"\", not $WANTEDNUMBER as expected
4c2ad1
+    if [ $ACTUALNUMBER != $WANTEDNUMBER ] ; then
4c2ad1
+        fail
4c2ad1
+        return 1
4c2ad1
+    fi
4c2ad1
+    pass
4c2ad1
+    return 0
4c2ad1
+}
4c2ad1
+
4c2ad1
+# Verify that the gdb output contains seven threads
4c2ad1
+function mustHaveSevenThreads() {
4c2ad1
+    NTHREADS=$(egrep "^Thread [1-7] \(" $LOG | wc -l)
4c2ad1
+    set_test gdb output contains $NTHREADS threads, not 7 as expected
4c2ad1
+    if [ $NTHREADS != 7 ] ; then
4c2ad1
+        fail
4c2ad1
+        return 1
4c2ad1
+    fi
4c2ad1
+    pass
4c2ad1
+    return 0
4c2ad1
+}
4c2ad1
+
4c2ad1
+# Verify that the gdb output has all parameters on consecutive lines
4c2ad1
+function mustHaveSequence() {
4c2ad1
+    SEQUENCE="$*"
4c2ad1
+    NPARTS=$#
4c2ad1
+    grep "$1" -A$((NPARTS - 1)) $LOG > matches.log
4c2ad1
+
4c2ad1
+    while [ $# -gt 1 ] ; do
4c2ad1
+        shift
4c2ad1
+        ((NPARTS--))
4c2ad1
+        grep "$1" -A$((NPARTS - 1)) matches.log > temp.log
4c2ad1
+        mv temp.log matches.log
4c2ad1
+    done
4c2ad1
+    LASTPART=$1
4c2ad1
+
4c2ad1
+    set_test gdb output does not contain the sequence: $SEQUENCE
4c2ad1
+    if ! grep -q "$LASTPART" matches.log ; then
4c2ad1
+        fail
4c2ad1
+        return 1
4c2ad1
+    fi
4c2ad1
+    pass
4c2ad1
+    return 0
4c2ad1
+}
4c2ad1
+
4c2ad1
+# Verify that $LOG contains all information we want
4c2ad1
+function verifyLog() {
4c2ad1
+    local FAILURES=0
4c2ad1
+    
4c2ad1
+    mustNotHave '??' || ((FAILURES++))
4c2ad1
+    mustHaveCorrectAmount 11 threadcrash.c: || ((FAILURES++))
4c2ad1
+    
4c2ad1
+    mustHaveSevenThreads || ((FAILURES++))
4c2ad1
+    mustHaveSequence sleep "makeSyscall (ignored=" || ((FAILURES++))
4c2ad1
+    
4c2ad1
+    mustHaveSequence sleep "syscallingSighandler (signo=" "signal handler called" 0x || ((FAILURES++))
4c2ad1
+    mustHaveSequence pthread_kill "makeSyscallFromSighandler (ignored=" || ((FAILURES++))
4c2ad1
+    
4c2ad1
+    mustHaveSequence sleep "syscallingAltSighandler (signo=" "signal handler called" 0x || ((FAILURES++))
4c2ad1
+    mustHaveSequence pthread_kill "makeSyscallFromAltSighandler (ignored=" || ((FAILURES++))
4c2ad1
+    
4c2ad1
+    mustHaveSequence Thread "spin (ignored=" || ((FAILURES++))
4c2ad1
+    
4c2ad1
+    mustHaveSequence "spinningSighandler (signo=" "signal handler called" 0x || ((FAILURES++))
4c2ad1
+    mustHaveSequence pthread_kill "spinFromSighandler (ignored=" || ((FAILURES++))
4c2ad1
+    
4c2ad1
+    mustHaveSequence "spinningAltSighandler (signo=" "signal handler called" 0x || ((FAILURES++))
4c2ad1
+    mustHaveSequence pthread_kill "spinFromAltSighandler (ignored=" || ((FAILURES++))
4c2ad1
+    
4c2ad1
+    mustHaveSequence Thread "main (argc=1, argv=" || ((FAILURES++))
4c2ad1
+
4c2ad1
+    return $FAILURES
4c2ad1
+}
4c2ad1
+
4c2ad1
+# Put result of debugging a core file in $LOG
4c2ad1
+function getLogFromCore() {
4c2ad1
+    # Make sure we get a core file
4c2ad1
+    set_test Make sure we get a core file
4c2ad1
+    if ! ulimit -c unlimited ; then
4c2ad1
+        fail
4c2ad1
+        exit 1
4c2ad1
+    fi
4c2ad1
+    pass
4c2ad1
+
4c2ad1
+    # Run the crasher
4c2ad1
+    ./$(basename "$RUNME")
4c2ad1
+    EXITCODE=$?
4c2ad1
+
4c2ad1
+    # Verify that we actually crashed
4c2ad1
+    set_test $RUNME should have been killed by a signal, got non-signal exit code $EXITCODE
4c2ad1
+    if [ $EXITCODE -lt 128 ] ; then
4c2ad1
+        fail
4c2ad1
+        exit 1
4c2ad1
+    fi
4c2ad1
+    pass
4c2ad1
+
4c2ad1
+    # Verify that we got a core file
4c2ad1
+    set_test $RUNME did not create a core file
4c2ad1
+    if [ ! -r core* ] ; then
4c2ad1
+        fail
4c2ad1
+        exit 1
4c2ad1
+    fi
4c2ad1
+    pass
4c2ad1
+
4c2ad1
+    # Run gdb
4c2ad1
+    cat > gdbscript.gdb <
4c2ad1
+set width 0
4c2ad1
+t a a bt 100
4c2ad1
+quit
4c2ad1
+EOF
4c2ad1
+    cat gdbscript.gdb /dev/zero | $GDB -nx "./$(basename "$RUNME")" core* > $LOG
4c2ad1
+    EXITCODE=$?
4c2ad1
+
4c2ad1
+    set_test gdb exited with error code
4c2ad1
+    if [ $EXITCODE != 0 ] ; then
4c2ad1
+        ((FAILURES++))
4c2ad1
+        echo >&2 gdb exited with error code $EXITCODE
4c2ad1
+	fail
4c2ad1
+    fi
4c2ad1
+    pass
4c2ad1
+}
4c2ad1
+
4c2ad1
+# Put result of debugging a gcore file in $LOG
4c2ad1
+function getLogFromGcore() {
4c2ad1
+    # Create the core file
4c2ad1
+    rm -f core*
4c2ad1
+    cat > gdbscript.gdb <
4c2ad1
+handle SIGQUIT pass noprint nostop
4c2ad1
+handle SIGUSR1 pass noprint nostop
4c2ad1
+handle SIGUSR2 pass noprint nostop
4c2ad1
+handle SIGALRM pass noprint nostop
4c2ad1
+run
4c2ad1
+gcore
4c2ad1
+quit
4c2ad1
+EOF
4c2ad1
+    cat gdbscript.gdb /dev/zero | $GDB -nx "./$(basename "$RUNME")" > /dev/null
4c2ad1
+    EXITCODE=$?
4c2ad1
+
4c2ad1
+    set_test gdb exited with error code when creating gcore file
4c2ad1
+    if [ $EXITCODE != 0 ] ; then
4c2ad1
+        ((FAILURES++))
4c2ad1
+        echo >&2 gdb exited with error code $EXITCODE when creating gcore file
4c2ad1
+	fail
4c2ad1
+    fi
4c2ad1
+    pass
4c2ad1
+    
4c2ad1
+    # Verify that we got a core file from gcore
4c2ad1
+    set_test gdb gcore did not create a core file
4c2ad1
+    if [ ! -r core* ] ; then
4c2ad1
+        fail
4c2ad1
+        exit 1
4c2ad1
+    fi
4c2ad1
+    pass
4c2ad1
+
4c2ad1
+    # Run gdb on the gcore file
4c2ad1
+    cat > gdbscript.gdb <
4c2ad1
+set width 0
4c2ad1
+t a a bt 100
4c2ad1
+quit
4c2ad1
+EOF
4c2ad1
+    cat gdbscript.gdb /dev/zero | $GDB -nx "./$(basename "$RUNME")" core* > $LOG
4c2ad1
+    EXITCODE=$?
4c2ad1
+
4c2ad1
+    set_test gdb exited with error code when examining gcore file
4c2ad1
+    if [ $EXITCODE != 0 ] ; then
4c2ad1
+        ((FAILURES++))
4c2ad1
+        echo >&2 gdb exited with error code $EXITCODE when examining gcore file
4c2ad1
+	fail
4c2ad1
+    fi
4c2ad1
+    pass
4c2ad1
+}
4c2ad1
+
4c2ad1
+# Put result of debugging a core file in $LOG
4c2ad1
+function getLogFromLiveProcess() {
4c2ad1
+    # Run gdb
4c2ad1
+    cat > gdbscript.gdb <
4c2ad1
+handle SIGQUIT pass noprint nostop
4c2ad1
+handle SIGUSR1 pass noprint nostop
4c2ad1
+handle SIGUSR2 pass noprint nostop
4c2ad1
+handle SIGALRM pass noprint nostop
4c2ad1
+set width 0
4c2ad1
+run
4c2ad1
+t a a bt 100
4c2ad1
+quit
4c2ad1
+EOF
4c2ad1
+    cat gdbscript.gdb /dev/zero | $GDB -nx "./$(basename "$RUNME")" > $LOG
4c2ad1
+    EXITCODE=$?
4c2ad1
+
4c2ad1
+    set_test gdb exited with error code
4c2ad1
+    if [ $EXITCODE != 0 ] ; then
4c2ad1
+        ((FAILURES++))
4c2ad1
+        echo >&2 gdb exited with error code $EXITCODE
4c2ad1
+	fail
4c2ad1
+    fi
4c2ad1
+    pass
4c2ad1
+}
4c2ad1
+
4c2ad1
+####### Main program follows #####################
4c2ad1
+
4c2ad1
+# Make sure we don't clobber anybody else's (core) file(s)
4c2ad1
+WORKDIR=/tmp/$PPID
4c2ad1
+mkdir -p $WORKDIR
4c2ad1
+cp "$RUNME" $WORKDIR
4c2ad1
+cd $WORKDIR
4c2ad1
+
4c2ad1
+# Count problems
4c2ad1
+FAILURES=0
4c2ad1
+
4c2ad1
+echo === Testing gdb vs core file...
4c2ad1
+pf_prefix core file
4c2ad1
+getLogFromCore
4c2ad1
+verifyLog
4c2ad1
+((FAILURES+=$?))
4c2ad1
+pf_prefix
4c2ad1
+echo === Core file tests done.
4c2ad1
+
4c2ad1
+echo
4c2ad1
+
4c2ad1
+echo === Testing gdb vs gcore file...
4c2ad1
+pf_prefix gcore file
4c2ad1
+getLogFromGcore
4c2ad1
+verifyLog
4c2ad1
+((FAILURES+=$?))
4c2ad1
+pf_prefix
4c2ad1
+echo === Gcore file tests done.
4c2ad1
+
4c2ad1
+echo
4c2ad1
+
4c2ad1
+echo === Testing gdb vs live process...
4c2ad1
+pf_prefix live process
4c2ad1
+getLogFromLiveProcess
4c2ad1
+verifyLog
4c2ad1
+((FAILURES+=$?))
4c2ad1
+pf_prefix
4c2ad1
+echo === Live process tests done.
4c2ad1
+
4c2ad1
+# Executive summary
4c2ad1
+echo
4c2ad1
+if [ $FAILURES == 0 ] ; then
4c2ad1
+    echo All tests passed!
4c2ad1
+else
4c2ad1
+    echo $FAILURES tests failed!
4c2ad1
+    echo
4c2ad1
+    echo Make sure the threadcrash binary contains debugging information \(build with \"gcc -g\"\).
4c2ad1
+fi
4c2ad1
+
4c2ad1
+# Clean up
4c2ad1
+cd /
4c2ad1
+rm -rf $WORKDIR
4c2ad1
+
4c2ad1
+exit $FAILURES
4c2ad1
diff --git a/gdb/testsuite/gdb.threads/threadcrash.sh-orig b/gdb/testsuite/gdb.threads/threadcrash.sh-orig
4c2ad1
new file mode 100644
4c2ad1
--- /dev/null
4c2ad1
+++ b/gdb/testsuite/gdb.threads/threadcrash.sh-orig
4c2ad1
@@ -0,0 +1,248 @@
4c2ad1
+#! /bin/bash
4c2ad1
+
4c2ad1
+# NOTE: threadcrash.c *must* be built with debugging symbols
4c2ad1
+#
4c2ad1
+# The point of this shell script is to crash treadcrash.c, load the
4c2ad1
+# resulting core file into gdb and verify that gdb can extract enough
4c2ad1
+# information from the core file.
4c2ad1
+#
4c2ad1
+# The return code from this script is the number of failed tests.
4c2ad1
+
4c2ad1
+LOG=gdbresult.log
4c2ad1
+
4c2ad1
+if [ $# != 1 ] ; then
4c2ad1
+    echo > /dev/stderr Syntax: $0 \<name of threadcrash binary\>
4c2ad1
+    exit 1
4c2ad1
+fi
4c2ad1
+RUNME="$1"
4c2ad1
+
4c2ad1
+# Verify that the gdb output doesn't contain $1.
4c2ad1
+function mustNotHave() {
4c2ad1
+    local BADWORD=$1
4c2ad1
+    if grep -q "$BADWORD" $LOG ; then
4c2ad1
+        echo >> /dev/stderr WARNING: gdb output contains "$BADWORD"
4c2ad1
+        return 1
4c2ad1
+    fi
4c2ad1
+    return 0
4c2ad1
+}
4c2ad1
+
4c2ad1
+# Verify that the gdb output contains exactly $1 $2s.
4c2ad1
+function mustHaveCorrectAmount() {
4c2ad1
+    local WANTEDNUMBER=$1
4c2ad1
+    local GOODWORD=$2
4c2ad1
+    local ACTUALNUMBER=$(grep "$GOODWORD" $LOG | wc -l)
4c2ad1
+    if [ $ACTUALNUMBER != $WANTEDNUMBER ] ; then
4c2ad1
+        echo >> /dev/stderr WARNING: gdb output contained $ACTUALNUMBER \""$GOODWORD"\", not $WANTEDNUMBER as expected
4c2ad1
+        return 1
4c2ad1
+    fi
4c2ad1
+    return 0
4c2ad1
+}
4c2ad1
+
4c2ad1
+# Verify that the gdb output contains seven threads
4c2ad1
+function mustHaveSevenThreads() {
4c2ad1
+    NTHREADS=$(egrep "^Thread [1-7] \(" $LOG | wc -l)
4c2ad1
+    if [ $NTHREADS != 7 ] ; then
4c2ad1
+        echo >> /dev/stderr WARNING: gdb output contains $NTHREADS threads, not 7 as expected
4c2ad1
+        return 1
4c2ad1
+    fi
4c2ad1
+    return 0
4c2ad1
+}
4c2ad1
+
4c2ad1
+# Verify that the gdb output has all parameters on consecutive lines
4c2ad1
+function mustHaveSequence() {
4c2ad1
+    SEQUENCE="$*"
4c2ad1
+    NPARTS=$#
4c2ad1
+    grep "$1" -A$((NPARTS - 1)) $LOG > matches.log
4c2ad1
+
4c2ad1
+    while [ $# -gt 1 ] ; do
4c2ad1
+        shift
4c2ad1
+        ((NPARTS--))
4c2ad1
+        grep "$1" -A$((NPARTS - 1)) matches.log > temp.log
4c2ad1
+        mv temp.log matches.log
4c2ad1
+    done
4c2ad1
+    LASTPART=$1
4c2ad1
+
4c2ad1
+    if ! grep -q "$LASTPART" matches.log ; then
4c2ad1
+        echo >> /dev/stderr WARNING: gdb output does not contain the sequence: $SEQUENCE
4c2ad1
+        return 1
4c2ad1
+    fi
4c2ad1
+    return 0
4c2ad1
+}
4c2ad1
+
4c2ad1
+# Verify that $LOG contains all information we want
4c2ad1
+function verifyLog() {
4c2ad1
+    local FAILURES=0
4c2ad1
+    
4c2ad1
+    mustNotHave '??' || ((FAILURES++))
4c2ad1
+    mustHaveCorrectAmount 12 threadcrash.c: || ((FAILURES++))
4c2ad1
+    
4c2ad1
+    mustHaveSevenThreads || ((FAILURES++))
4c2ad1
+    mustHaveSequence sleep "makeSyscall (ignored=" || ((FAILURES++))
4c2ad1
+    
4c2ad1
+    mustHaveSequence sleep "syscallingSighandler (signo=" "signal handler called" 0x || ((FAILURES++))
4c2ad1
+    mustHaveSequence pthread_kill "makeSyscallFromSighandler (ignored=" || ((FAILURES++))
4c2ad1
+    
4c2ad1
+    mustHaveSequence sleep "syscallingAltSighandler (signo=" "signal handler called" 0x || ((FAILURES++))
4c2ad1
+    mustHaveSequence pthread_kill "makeSyscallFromAltSighandler (ignored=" || ((FAILURES++))
4c2ad1
+    
4c2ad1
+    mustHaveSequence Thread "spin (ignored=" || ((FAILURES++))
4c2ad1
+    
4c2ad1
+    mustHaveSequence "spinningSighandler (signo=" "signal handler called" 0x || ((FAILURES++))
4c2ad1
+    mustHaveSequence pthread_kill "spinFromSighandler (ignored=" || ((FAILURES++))
4c2ad1
+    
4c2ad1
+    mustHaveSequence "spinningAltSighandler (signo=" "signal handler called" 0x || ((FAILURES++))
4c2ad1
+    mustHaveSequence pthread_kill "spinFromAltSighandler (ignored=" || ((FAILURES++))
4c2ad1
+    
4c2ad1
+    mustHaveSequence Thread "main (argc=1, argv=" || ((FAILURES++))
4c2ad1
+
4c2ad1
+    return $FAILURES
4c2ad1
+}
4c2ad1
+
4c2ad1
+# Put result of debugging a core file in $LOG
4c2ad1
+function getLogFromCore() {
4c2ad1
+    # Make sure we get a core file
4c2ad1
+    ulimit -c unlimited || exit 1
4c2ad1
+
4c2ad1
+    # Run the crasher
4c2ad1
+    ./$(basename "$RUNME")
4c2ad1
+    EXITCODE=$?
4c2ad1
+
4c2ad1
+    # Verify that we actually crashed
4c2ad1
+    if [ $EXITCODE -lt 128 ] ; then
4c2ad1
+        echo >> /dev/stderr ERROR: $RUNME should have been killed by a signal, got non-signal exit code $EXITCODE
4c2ad1
+        exit 1
4c2ad1
+    fi
4c2ad1
+
4c2ad1
+    # Verify that we got a core file
4c2ad1
+    if [ ! -r core* ] ; then
4c2ad1
+        echo >> /dev/stderr ERROR: $RUNME did not create a core file
4c2ad1
+        exit 1
4c2ad1
+    fi
4c2ad1
+
4c2ad1
+    # Run gdb
4c2ad1
+    cat > gdbscript.gdb <
4c2ad1
+set width 0
4c2ad1
+t a a bt 100
4c2ad1
+quit
4c2ad1
+EOF
4c2ad1
+    cat gdbscript.gdb /dev/zero | gdb -nx "./$(basename "$RUNME")" core* > $LOG
4c2ad1
+    EXITCODE=$?
4c2ad1
+
4c2ad1
+    if [ $EXITCODE != 0 ] ; then
4c2ad1
+        ((FAILURES++))
4c2ad1
+        echo >> /dev/stderr WARNING: gdb exited with error code $EXITCODE
4c2ad1
+    fi
4c2ad1
+}
4c2ad1
+
4c2ad1
+# Put result of debugging a gcore file in $LOG
4c2ad1
+function getLogFromGcore() {
4c2ad1
+    # Create the core file
4c2ad1
+    rm -f core*
4c2ad1
+    cat > gdbscript.gdb <
4c2ad1
+handle SIGQUIT pass noprint nostop
4c2ad1
+handle SIGUSR1 pass noprint nostop
4c2ad1
+handle SIGUSR2 pass noprint nostop
4c2ad1
+handle SIGALRM pass noprint nostop
4c2ad1
+run
4c2ad1
+gcore
4c2ad1
+quit
4c2ad1
+EOF
4c2ad1
+    cat gdbscript.gdb /dev/zero | gdb -nx "./$(basename "$RUNME")" > /dev/null
4c2ad1
+    EXITCODE=$?
4c2ad1
+
4c2ad1
+    if [ $EXITCODE != 0 ] ; then
4c2ad1
+        ((FAILURES++))
4c2ad1
+        echo >> /dev/stderr WARNING: gdb exited with error code $EXITCODE when creating gcore file
4c2ad1
+    fi
4c2ad1
+    
4c2ad1
+    # Verify that we got a core file from gcore
4c2ad1
+    if [ ! -r core* ] ; then
4c2ad1
+        echo >> /dev/stderr ERROR: gdb gcore did not create a core file
4c2ad1
+        exit 1
4c2ad1
+    fi
4c2ad1
+
4c2ad1
+    # Run gdb on the gcore file
4c2ad1
+    cat > gdbscript.gdb <
4c2ad1
+set width 0
4c2ad1
+t a a bt 100
4c2ad1
+quit
4c2ad1
+EOF
4c2ad1
+    cat gdbscript.gdb /dev/zero | gdb -nx "./$(basename "$RUNME")" core* > $LOG
4c2ad1
+    EXITCODE=$?
4c2ad1
+
4c2ad1
+    if [ $EXITCODE != 0 ] ; then
4c2ad1
+        ((FAILURES++))
4c2ad1
+        echo >> /dev/stderr WARNING: gdb exited with error code $EXITCODE when examining gcore file
4c2ad1
+    fi
4c2ad1
+}
4c2ad1
+
4c2ad1
+# Put result of debugging a core file in $LOG
4c2ad1
+function getLogFromLiveProcess() {
4c2ad1
+    # Run gdb
4c2ad1
+    cat > gdbscript.gdb <
4c2ad1
+handle SIGQUIT pass noprint nostop
4c2ad1
+handle SIGUSR1 pass noprint nostop
4c2ad1
+handle SIGUSR2 pass noprint nostop
4c2ad1
+handle SIGALRM pass noprint nostop
4c2ad1
+set width 0
4c2ad1
+run
4c2ad1
+t a a bt 100
4c2ad1
+quit
4c2ad1
+EOF
4c2ad1
+    cat gdbscript.gdb /dev/zero | gdb -nx "./$(basename "$RUNME")" > $LOG
4c2ad1
+    EXITCODE=$?
4c2ad1
+
4c2ad1
+    if [ $EXITCODE != 0 ] ; then
4c2ad1
+        ((FAILURES++))
4c2ad1
+        echo >> /dev/stderr WARNING: gdb exited with error code $EXITCODE
4c2ad1
+    fi
4c2ad1
+}
4c2ad1
+
4c2ad1
+####### Main program follows #####################
4c2ad1
+
4c2ad1
+# Make sure we don't clobber anybody else's (core) file(s)
4c2ad1
+WORKDIR=/tmp/$PPID
4c2ad1
+mkdir -p $WORKDIR
4c2ad1
+cp "$RUNME" $WORKDIR
4c2ad1
+cd $WORKDIR
4c2ad1
+
4c2ad1
+# Count problems
4c2ad1
+FAILURES=0
4c2ad1
+
4c2ad1
+echo === Testing gdb vs core file...
4c2ad1
+getLogFromCore
4c2ad1
+verifyLog
4c2ad1
+((FAILURES+=$?))
4c2ad1
+echo === Core file tests done.
4c2ad1
+
4c2ad1
+echo
4c2ad1
+
4c2ad1
+echo === Testing gdb vs gcore file...
4c2ad1
+getLogFromGcore
4c2ad1
+verifyLog
4c2ad1
+((FAILURES+=$?))
4c2ad1
+echo === Gcore file tests done.
4c2ad1
+
4c2ad1
+echo
4c2ad1
+
4c2ad1
+echo === Testing gdb vs live process...
4c2ad1
+getLogFromLiveProcess
4c2ad1
+verifyLog
4c2ad1
+((FAILURES+=$?))
4c2ad1
+echo === Live process tests done.
4c2ad1
+
4c2ad1
+# Executive summary
4c2ad1
+echo
4c2ad1
+if [ $FAILURES == 0 ] ; then
4c2ad1
+    echo All tests passed!
4c2ad1
+else
4c2ad1
+    echo $FAILURES tests failed!
4c2ad1
+    echo
4c2ad1
+    echo Make sure the threadcrash binary contains debugging information \(build with \"gcc -g\"\).
4c2ad1
+fi
4c2ad1
+
4c2ad1
+# Clean up
4c2ad1
+cd /
4c2ad1
+rm -rf $WORKDIR
4c2ad1
+
4c2ad1
+exit $FAILURES