From b048379f11ba6e234bd1ba3e94abd09a7a3e76fe Mon Sep 17 00:00:00 2001 From: Jan Kratochvil Date: Thu, 2 Nov 2006 22:58:41 +0000 Subject: [PATCH] - Fix "??" resolving of symbols from (non-prelinked) debuginfo packages. - Fix "??" resolving of symbols from overlapping functions (nanosleep(3)). - Also disable testcase "checkpoint.exp" for a possible kernel Bug 207002. - Improved testsuite results by the testsuite provided by the courtesy of BEA. - Related: rhbz#179399 Note: i386 test results of the BEA testsuite uuencode(1)d for `gdb2fail.sh' are too bogus, retest (RHTS?) required on the matching kernel. `WONTFIX' by makem. --- gdb-6.5-BEA-testsuite.patch | 938 ++++++++++++++++++++++++++++++++++ gdb-6.5-relativedebug.patch | 143 ++++++ gdb-6.5-symbols-overlap.patch | 195 +++++++ gdb.spec | 25 +- 4 files changed, 1299 insertions(+), 2 deletions(-) create mode 100644 gdb-6.5-BEA-testsuite.patch create mode 100644 gdb-6.5-relativedebug.patch create mode 100644 gdb-6.5-symbols-overlap.patch diff --git a/gdb-6.5-BEA-testsuite.patch b/gdb-6.5-BEA-testsuite.patch new file mode 100644 index 0000000..76d7566 --- /dev/null +++ b/gdb-6.5-BEA-testsuite.patch @@ -0,0 +1,938 @@ +Index: ./gdb/testsuite/gdb.threads/threadcrash.c +=================================================================== +RCS file: gdb/testsuite/gdb.threads/threadcrash.c +diff -N gdb/testsuite/gdb.threads/threadcrash.c +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.threads/threadcrash.c 31 Oct 2006 17:54:38 -0000 +@@ -0,0 +1,301 @@ ++/* ++ * The point of this program is to crash in a multi-threaded app. ++ * There are seven threads, doing the following things: ++ * * Spinning ++ * * Spinning inside a signal handler ++ * * Spinning inside a signal handler executing on the altstack ++ * * In a syscall ++ * * In a syscall inside a signal handler ++ * * In a syscall inside a signal handler executing on the altstack ++ * * Finally, the main thread crashes in main, with no frills. ++ * ++ * These are the things threads in JRockit tend to be doing. If gdb ++ * can handle those things, both in core files and during live ++ * debugging, that will help (at least) JRockit development. ++ * ++ * Let the program create a core file, then load the core file into ++ * gdb. Inside gdb, you should be able to do something like this: ++ * ++ * (gdb) t a a bt ++ * ++ * Thread 7 (process 4352): ++ * #0 0x001ba7dc in __nanosleep_nocancel () from /lib/tls/libc.so.6 ++ * #1 0x001ba5ff in sleep () from /lib/tls/libc.so.6 ++ * #2 0x080488a2 in makeSyscall (ignored=0x0) at threadcrash.c:118 ++ * #3 0x006aadec in start_thread () from /lib/tls/libpthread.so.0 ++ * #4 0x001ed19a in clone () from /lib/tls/libc.so.6 ++ * ++ * Thread 6 (process 4353): ++ * #0 0x001ba7dc in __nanosleep_nocancel () from /lib/tls/libc.so.6 ++ * #1 0x001ba5ff in sleep () from /lib/tls/libc.so.6 ++ * #2 0x0804898f in syscallingSighandler (signo=10, info=0xb6be76f0, context=0xb6be7770) ++ * at threadcrash.c:168 ++ * #3 ++ * #4 0x006adf5e in pthread_kill () from /lib/tls/libpthread.so.0 ++ * #5 0x08048a51 in makeSyscallFromSighandler (ignored=0x0) at threadcrash.c:204 ++ * #6 0x006aadec in start_thread () from /lib/tls/libpthread.so.0 ++ * #7 0x001ed19a in clone () from /lib/tls/libc.so.6 ++ * ++ * Thread 5 (process 4354): ++ * #0 0x001ba7dc in __nanosleep_nocancel () from /lib/tls/libc.so.6 ++ * #1 0x001ba5ff in sleep () from /lib/tls/libc.so.6 ++ * #2 0x08048936 in syscallingAltSighandler (signo=3, info=0x959cd70, context=0x959cdf0) ++ * at threadcrash.c:144 ++ * #3 ++ * #4 0x006adf5e in pthread_kill () from /lib/tls/libpthread.so.0 ++ * #5 0x080489e2 in makeSyscallFromAltSighandler (ignored=0x0) at threadcrash.c:190 ++ * #6 0x006aadec in start_thread () from /lib/tls/libpthread.so.0 ++ * #7 0x001ed19a in clone () from /lib/tls/libc.so.6 ++ * ++ * Thread 4 (process 4355): ++ * #0 spin (ignored=0x0) at threadcrash.c:242 ++ * #1 0x006aadec in start_thread () from /lib/tls/libpthread.so.0 ++ * #2 0x001ed19a in clone () from /lib/tls/libc.so.6 ++ * ++ * Thread 3 (process 4356): ++ * #0 spinningSighandler (signo=12, info=0xb4de46f0, context=0xb4de4770) at threadcrash.c:180 ++ * #1 ++ * #2 0x006adf5e in pthread_kill () from /lib/tls/libpthread.so.0 ++ * #3 0x08048b2f in spinFromSighandler (ignored=0x0) at threadcrash.c:232 ++ * #4 0x006aadec in start_thread () from /lib/tls/libpthread.so.0 ++ * #5 0x001ed19a in clone () from /lib/tls/libc.so.6 ++ * ++ * Thread 2 (process 4357): ++ * #0 spinningAltSighandler (signo=14, info=0x959ee50, context=0x959eed0) at threadcrash.c:156 ++ * #1 ++ * #2 0x006adf5e in pthread_kill () from /lib/tls/libpthread.so.0 ++ * #3 0x08048ac0 in spinFromAltSighandler (ignored=0x0) at threadcrash.c:218 ++ * #4 0x006aadec in start_thread () from /lib/tls/libpthread.so.0 ++ * #5 0x001ed19a in clone () from /lib/tls/libc.so.6 ++ * ++ * Thread 1 (process 4351): ++ * #0 0x08048cf3 in main (argc=1, argv=0xbfff9d74) at threadcrash.c:273 ++ * (gdb) ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#define SIGSYSCALL_ALT SIGQUIT ++#define SIGSYSCALL SIGUSR1 ++#define SIGSPIN_ALT SIGALRM ++#define SIGSPIN SIGUSR2 ++ ++typedef void (*sigaction_t)(int, siginfo_t *, void *); ++ ++static void installHandler(int signo, sigaction_t handler, int onAltstack) { ++ struct sigaction action; ++ sigset_t sigset; ++ int result; ++ stack_t altstack; ++ stack_t oldaltstack; ++ ++ memset(&action, 0, sizeof(action)); ++ memset(&altstack, 0, sizeof(altstack)); ++ memset(&oldaltstack, 0, sizeof(oldaltstack)); ++ ++ if (onAltstack) { ++ altstack.ss_sp = malloc(SIGSTKSZ); ++ assert(altstack.ss_sp != NULL); ++ altstack.ss_size = SIGSTKSZ; ++ altstack.ss_flags = 0; ++ result = sigaltstack(&altstack, &oldaltstack); ++ assert(result == 0); ++ assert(oldaltstack.ss_flags == SS_DISABLE); ++ } ++ ++ sigemptyset(&sigset); ++ ++ action.sa_handler = NULL; ++ action.sa_sigaction = handler; ++ action.sa_mask = sigset; ++ action.sa_flags = SA_SIGINFO; ++ if (onAltstack) { ++ action.sa_flags |= SA_ONSTACK; ++ } ++ ++ result = sigaction(signo, &action, NULL); ++ assert(result == 0); ++} ++ ++static void installNormalHandler(int signo, sigaction_t handler) { ++ installHandler(signo, handler, 0); ++} ++ ++static void installAlthandler(int signo, sigaction_t handler) { ++ installHandler(signo, handler, 1); ++} ++ ++static void *makeSyscall(void *ignored) { ++ (void)ignored; ++ ++ sleep(42); ++ ++ fprintf(stderr, "%s: returning\n", __FUNCTION__); ++ return NULL; ++} ++ ++/* Return true if we're currently executing on the altstack */ ++static int onAltstack(void) { ++ stack_t stack; ++ int result; ++ ++ result = sigaltstack(NULL, &stack); ++ assert(result == 0); ++ ++ return stack.ss_flags & SS_ONSTACK; ++} ++ ++static void syscallingAltSighandler(int signo, siginfo_t *info, void *context) { ++ (void)signo; ++ (void)info; ++ (void)context; ++ ++ if (!onAltstack()) { ++ printf("%s() not running on altstack!\n", __FUNCTION__); ++ } ++ ++ sleep(42); ++} ++ ++static void spinningAltSighandler(int signo, siginfo_t *info, void *context) { ++ (void)signo; ++ (void)info; ++ (void)context; ++ ++ if (!onAltstack()) { ++ printf("%s() not running on altstack!\n", __FUNCTION__); ++ } ++ ++ while (1); ++} ++ ++static void syscallingSighandler(int signo, siginfo_t *info, void *context) { ++ (void)signo; ++ (void)info; ++ (void)context; ++ ++ if (onAltstack()) { ++ printf("%s() running on altstack!\n", __FUNCTION__); ++ } ++ ++ sleep(42); ++} ++ ++static void spinningSighandler(int signo, siginfo_t *info, void *context) { ++ (void)signo; ++ (void)info; ++ (void)context; ++ ++ if (onAltstack()) { ++ printf("%s() running on altstack!\n", __FUNCTION__); ++ } ++ ++ while (1); ++} ++ ++static void *makeSyscallFromAltSighandler(void *ignored) { ++ (void)ignored; ++ ++ int result; ++ ++ installAlthandler(SIGSYSCALL_ALT, syscallingAltSighandler); ++ ++ result = pthread_kill(pthread_self(), SIGSYSCALL_ALT); ++ assert(result == 0); ++ ++ fprintf(stderr, "%s: returning\n", __FUNCTION__); ++ return NULL; ++} ++ ++static void *makeSyscallFromSighandler(void *ignored) { ++ (void)ignored; ++ ++ int result; ++ ++ installNormalHandler(SIGSYSCALL, syscallingSighandler); ++ ++ result = pthread_kill(pthread_self(), SIGSYSCALL); ++ assert(result == 0); ++ ++ fprintf(stderr, "%s: returning\n", __FUNCTION__); ++ return NULL; ++} ++ ++static void *spinFromAltSighandler(void *ignored) { ++ (void)ignored; ++ ++ int result; ++ ++ installAlthandler(SIGSPIN_ALT, spinningAltSighandler); ++ ++ result = pthread_kill(pthread_self(), SIGSPIN_ALT); ++ assert(result == 0); ++ ++ fprintf(stderr, "%s: returning\n", __FUNCTION__); ++ return NULL; ++} ++ ++static void *spinFromSighandler(void *ignored) { ++ (void)ignored; ++ ++ int result; ++ ++ installNormalHandler(SIGSPIN, spinningSighandler); ++ ++ result = pthread_kill(pthread_self(), SIGSPIN); ++ assert(result == 0); ++ ++ fprintf(stderr, "%s: returning\n", __FUNCTION__); ++ return NULL; ++} ++ ++static void *spin(void *ignored) { ++ (void)ignored; ++ ++ while (1); ++ ++ fprintf(stderr, "%s: returning\n", __FUNCTION__); ++ return NULL; ++} ++ ++int main(int argc, char *argv[]) { ++ int result; ++ pthread_t thread; ++ volatile int bad; ++ ++ result = pthread_create(&thread, NULL, makeSyscall, NULL); ++ assert(result == 0); ++ result = pthread_create(&thread, NULL, makeSyscallFromSighandler, NULL); ++ assert(result == 0); ++ result = pthread_create(&thread, NULL, makeSyscallFromAltSighandler, NULL); ++ assert(result == 0); ++ result = pthread_create(&thread, NULL, spin, NULL); ++ assert(result == 0); ++ result = pthread_create(&thread, NULL, spinFromSighandler, NULL); ++ assert(result == 0); ++ result = pthread_create(&thread, NULL, spinFromAltSighandler, NULL); ++ assert(result == 0); ++ ++ // Give threads some time to get going ++ sleep(3); ++ ++ // Crash ++ bad = *(int*)7; ++ ++ /* Workaround: http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29628 ++ Simulate use to ensure `DW_AT_location' for them: ++ readelf -a --debug threadcrash|grep -A5 -w argc ++ --> DW_AT_location : 2 byte block: 71 0 (DW_OP_breg1: 0) ++ This case verified on: gcc-4.1.1-30.i386 ++ Keep it late to ensure persistency in the registers. */ ++ bad = (int) argc; ++ bad = (unsigned long) argv; ++ ++ return 0; ++} +Index: ./gdb/testsuite/gdb.threads/threadcrash.exp +=================================================================== +RCS file: gdb/testsuite/gdb.threads/threadcrash.exp +diff -N gdb/testsuite/gdb.threads/threadcrash.exp +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.threads/threadcrash.exp 31 Oct 2006 17:54:38 -0000 +@@ -0,0 +1,37 @@ ++# threadcrash.exp - The point of this program is to crash in a multi-threaded app. ++ ++ ++set testfile threadcrash ++set srcfile ${testfile}.c ++set shellfile ${srcdir}/${subdir}/${testfile}.sh ++set binfile ${objdir}/${subdir}/${testfile} ++ ++set GDB_abs ${GDB} ++if [regexp "^\[^/\]" ${GDB_abs}] { ++ set GDB_abs $env(PWD)/${GDB_abs} ++} ++ ++if [istarget "*-*-linux"] then { ++ set target_cflags "-D_MIT_POSIX_THREADS" ++} else { ++ set target_cflags "" ++} ++ ++if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { ++ return -1 ++} ++ ++# ${shellfile} argument must not contain any directories. ++set fd [open "|bash ${shellfile} ${binfile} $GDB -nw $GDBFLAGS" r] ++while { [gets $fd line] >= 0 } { ++ if [regexp " PASS: (.*)$" $line trash message] { ++ pass $message ++ } elseif [regexp " FAIL: (.*)$" $line trash message] { ++ fail $message ++ } ++} ++catch { ++ close $fd ++} ++ ++return 0 +Index: ./gdb/testsuite/gdb.threads/threadcrash.sh +=================================================================== +RCS file: gdb/testsuite/gdb.threads/threadcrash.sh +diff -N gdb/testsuite/gdb.threads/threadcrash.sh +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.threads/threadcrash.sh 31 Oct 2006 17:54:38 -0000 +@@ -0,0 +1,324 @@ ++#! /bin/bash ++ ++# NOTE: threadcrash.c *must* be built with debugging symbols ++# ++# The point of this shell script is to crash treadcrash.c, load the ++# resulting core file into gdb and verify that gdb can extract enough ++# information from the core file. ++# ++# The return code from this script is the number of failed tests. ++ ++LOG=gdbresult.log ++ ++if [ $# = 0 ] ; then ++ echo >&2 Syntax: $0 \ [\ \] ++ exit 1 ++fi ++RUNME="$1" ++shift ++GDB="${*:-gdb}" ++ ++ ++pf_prefix="" ++function pf_prefix() { ++ pf_prefix="$*" ++} ++ ++set_test="" ++function set_test() { ++ if [ -n "$set_test" ] ; then ++ echo >&2 "DEJAGNU-BASH ERROR: set_test already set" ++ exit 1 ++ fi ++ set_test="$*" ++ if [ -n "$pf_prefix" ] ; then ++ set_test="$pf_prefix: $set_test" ++ fi ++} ++ ++# INTERNAL ++function record_test { ++ if [ -z "$set_test" ] ; then ++ echo >&2 "DEJAGNU-BASH ERROR: set_test not set" ++ exit 1 ++ fi ++ # Provide the leading whitespace delimiter: ++ echo " $1: $set_test" ++ set_test="" ++} ++ ++function pass() { ++ record_test PASS ++} ++function fail() { ++ record_test FAIL ++} ++ ++ ++# Verify that the gdb output doesn't contain $1. ++function mustNotHave() { ++ local BADWORD=$1 ++ set_test gdb output contains "$BADWORD" ++ if grep -q "$BADWORD" $LOG ; then ++ fail ++ return 1 ++ fi ++ pass ++ return 0 ++} ++ ++# Verify that the gdb output contains exactly $1 $2s. ++function mustHaveCorrectAmount() { ++ local WANTEDNUMBER=$1 ++ local GOODWORD=$2 ++ local ACTUALNUMBER=$(grep "$GOODWORD" $LOG | wc -l) ++ set_test gdb output contained $ACTUALNUMBER \""$GOODWORD"\", not $WANTEDNUMBER as expected ++ if [ $ACTUALNUMBER != $WANTEDNUMBER ] ; then ++ fail ++ return 1 ++ fi ++ pass ++ return 0 ++} ++ ++# Verify that the gdb output contains seven threads ++function mustHaveSevenThreads() { ++ NTHREADS=$(egrep "^Thread [1-7] \(" $LOG | wc -l) ++ set_test gdb output contains $NTHREADS threads, not 7 as expected ++ if [ $NTHREADS != 7 ] ; then ++ fail ++ return 1 ++ fi ++ pass ++ return 0 ++} ++ ++# Verify that the gdb output has all parameters on consecutive lines ++function mustHaveSequence() { ++ SEQUENCE="$*" ++ NPARTS=$# ++ grep "$1" -A$((NPARTS - 1)) $LOG > matches.log ++ ++ while [ $# -gt 1 ] ; do ++ shift ++ ((NPARTS--)) ++ grep "$1" -A$((NPARTS - 1)) matches.log > temp.log ++ mv temp.log matches.log ++ done ++ LASTPART=$1 ++ ++ set_test gdb output does not contain the sequence: $SEQUENCE ++ if ! grep -q "$LASTPART" matches.log ; then ++ fail ++ return 1 ++ fi ++ pass ++ return 0 ++} ++ ++# Verify that $LOG contains all information we want ++function verifyLog() { ++ local FAILURES=0 ++ ++ mustNotHave '??' || ((FAILURES++)) ++ mustHaveCorrectAmount 12 threadcrash.c: || ((FAILURES++)) ++ ++ mustHaveSevenThreads || ((FAILURES++)) ++ mustHaveSequence sleep "makeSyscall (ignored=" || ((FAILURES++)) ++ ++ mustHaveSequence sleep "syscallingSighandler (signo=" "signal handler called" 0x || ((FAILURES++)) ++ mustHaveSequence pthread_kill "makeSyscallFromSighandler (ignored=" || ((FAILURES++)) ++ ++ mustHaveSequence sleep "syscallingAltSighandler (signo=" "signal handler called" 0x || ((FAILURES++)) ++ mustHaveSequence pthread_kill "makeSyscallFromAltSighandler (ignored=" || ((FAILURES++)) ++ ++ mustHaveSequence Thread "spin (ignored=" || ((FAILURES++)) ++ ++ mustHaveSequence "spinningSighandler (signo=" "signal handler called" 0x || ((FAILURES++)) ++ mustHaveSequence pthread_kill "spinFromSighandler (ignored=" || ((FAILURES++)) ++ ++ mustHaveSequence "spinningAltSighandler (signo=" "signal handler called" 0x || ((FAILURES++)) ++ mustHaveSequence pthread_kill "spinFromAltSighandler (ignored=" || ((FAILURES++)) ++ ++ mustHaveSequence Thread "main (argc=1, argv=" || ((FAILURES++)) ++ ++ return $FAILURES ++} ++ ++# Put result of debugging a core file in $LOG ++function getLogFromCore() { ++ # Make sure we get a core file ++ set_test Make sure we get a core file ++ if ! ulimit -c unlimited ; then ++ fail ++ exit 1 ++ fi ++ pass ++ ++ # Run the crasher ++ ./$(basename "$RUNME") ++ EXITCODE=$? ++ ++ # Verify that we actually crashed ++ set_test $RUNME should have been killed by a signal, got non-signal exit code $EXITCODE ++ if [ $EXITCODE -lt 128 ] ; then ++ fail ++ exit 1 ++ fi ++ pass ++ ++ # Verify that we got a core file ++ set_test $RUNME did not create a core file ++ if [ ! -r core* ] ; then ++ fail ++ exit 1 ++ fi ++ pass ++ ++ # Run gdb ++ cat > gdbscript.gdb < $LOG ++ EXITCODE=$? ++ ++ set_test gdb exited with error code ++ if [ $EXITCODE != 0 ] ; then ++ ((FAILURES++)) ++ echo >&2 gdb exited with error code $EXITCODE ++ fail ++ fi ++ pass ++} ++ ++# Put result of debugging a gcore file in $LOG ++function getLogFromGcore() { ++ # Create the core file ++ rm -f core* ++ cat > gdbscript.gdb < /dev/null ++ EXITCODE=$? ++ ++ set_test gdb exited with error code when creating gcore file ++ if [ $EXITCODE != 0 ] ; then ++ ((FAILURES++)) ++ echo >&2 gdb exited with error code $EXITCODE when creating gcore file ++ fail ++ fi ++ pass ++ ++ # Verify that we got a core file from gcore ++ set_test gdb gcore did not create a core file ++ if [ ! -r core* ] ; then ++ fail ++ exit 1 ++ fi ++ pass ++ ++ # Run gdb on the gcore file ++ cat > gdbscript.gdb < $LOG ++ EXITCODE=$? ++ ++ set_test gdb exited with error code when examining gcore file ++ if [ $EXITCODE != 0 ] ; then ++ ((FAILURES++)) ++ echo >&2 gdb exited with error code $EXITCODE when examining gcore file ++ fail ++ fi ++ pass ++} ++ ++# Put result of debugging a core file in $LOG ++function getLogFromLiveProcess() { ++ # Run gdb ++ cat > gdbscript.gdb < $LOG ++ EXITCODE=$? ++ ++ set_test gdb exited with error code ++ if [ $EXITCODE != 0 ] ; then ++ ((FAILURES++)) ++ echo >&2 gdb exited with error code $EXITCODE ++ fail ++ fi ++ pass ++} ++ ++####### Main program follows ##################### ++ ++# Make sure we don't clobber anybody else's (core) file(s) ++WORKDIR=/tmp/$PPID ++mkdir -p $WORKDIR ++cp "$RUNME" $WORKDIR ++cd $WORKDIR ++ ++# Count problems ++FAILURES=0 ++ ++echo === Testing gdb vs core file... ++pf_prefix core file ++getLogFromCore ++verifyLog ++((FAILURES+=$?)) ++pf_prefix ++echo === Core file tests done. ++ ++echo ++ ++echo === Testing gdb vs gcore file... ++pf_prefix gcore file ++getLogFromGcore ++verifyLog ++((FAILURES+=$?)) ++pf_prefix ++echo === Gcore file tests done. ++ ++echo ++ ++echo === Testing gdb vs live process... ++pf_prefix live process ++getLogFromLiveProcess ++verifyLog ++((FAILURES+=$?)) ++pf_prefix ++echo === Live process tests done. ++ ++# Executive summary ++echo ++if [ $FAILURES == 0 ] ; then ++ echo All tests passed! ++else ++ echo $FAILURES tests failed! ++ echo ++ echo Make sure the threadcrash binary contains debugging information \(build with \"gcc -g\"\). ++fi ++ ++# Clean up ++cd / ++rm -rf $WORKDIR ++ ++exit $FAILURES +Index: ./gdb/testsuite/gdb.threads/threadcrash.sh-orig +=================================================================== +RCS file: gdb/testsuite/gdb.threads/threadcrash.sh-orig +diff -N gdb/testsuite/gdb.threads/threadcrash.sh-orig +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.threads/threadcrash.sh-orig 31 Oct 2006 17:54:38 -0000 +@@ -0,0 +1,248 @@ ++#! /bin/bash ++ ++# NOTE: threadcrash.c *must* be built with debugging symbols ++# ++# The point of this shell script is to crash treadcrash.c, load the ++# resulting core file into gdb and verify that gdb can extract enough ++# information from the core file. ++# ++# The return code from this script is the number of failed tests. ++ ++LOG=gdbresult.log ++ ++if [ $# != 1 ] ; then ++ echo > /dev/stderr Syntax: $0 \ ++ exit 1 ++fi ++RUNME="$1" ++ ++# Verify that the gdb output doesn't contain $1. ++function mustNotHave() { ++ local BADWORD=$1 ++ if grep -q "$BADWORD" $LOG ; then ++ echo >> /dev/stderr WARNING: gdb output contains "$BADWORD" ++ return 1 ++ fi ++ return 0 ++} ++ ++# Verify that the gdb output contains exactly $1 $2s. ++function mustHaveCorrectAmount() { ++ local WANTEDNUMBER=$1 ++ local GOODWORD=$2 ++ local ACTUALNUMBER=$(grep "$GOODWORD" $LOG | wc -l) ++ if [ $ACTUALNUMBER != $WANTEDNUMBER ] ; then ++ echo >> /dev/stderr WARNING: gdb output contained $ACTUALNUMBER \""$GOODWORD"\", not $WANTEDNUMBER as expected ++ return 1 ++ fi ++ return 0 ++} ++ ++# Verify that the gdb output contains seven threads ++function mustHaveSevenThreads() { ++ NTHREADS=$(egrep "^Thread [1-7] \(" $LOG | wc -l) ++ if [ $NTHREADS != 7 ] ; then ++ echo >> /dev/stderr WARNING: gdb output contains $NTHREADS threads, not 7 as expected ++ return 1 ++ fi ++ return 0 ++} ++ ++# Verify that the gdb output has all parameters on consecutive lines ++function mustHaveSequence() { ++ SEQUENCE="$*" ++ NPARTS=$# ++ grep "$1" -A$((NPARTS - 1)) $LOG > matches.log ++ ++ while [ $# -gt 1 ] ; do ++ shift ++ ((NPARTS--)) ++ grep "$1" -A$((NPARTS - 1)) matches.log > temp.log ++ mv temp.log matches.log ++ done ++ LASTPART=$1 ++ ++ if ! grep -q "$LASTPART" matches.log ; then ++ echo >> /dev/stderr WARNING: gdb output does not contain the sequence: $SEQUENCE ++ return 1 ++ fi ++ return 0 ++} ++ ++# Verify that $LOG contains all information we want ++function verifyLog() { ++ local FAILURES=0 ++ ++ mustNotHave '??' || ((FAILURES++)) ++ mustHaveCorrectAmount 12 threadcrash.c: || ((FAILURES++)) ++ ++ mustHaveSevenThreads || ((FAILURES++)) ++ mustHaveSequence sleep "makeSyscall (ignored=" || ((FAILURES++)) ++ ++ mustHaveSequence sleep "syscallingSighandler (signo=" "signal handler called" 0x || ((FAILURES++)) ++ mustHaveSequence pthread_kill "makeSyscallFromSighandler (ignored=" || ((FAILURES++)) ++ ++ mustHaveSequence sleep "syscallingAltSighandler (signo=" "signal handler called" 0x || ((FAILURES++)) ++ mustHaveSequence pthread_kill "makeSyscallFromAltSighandler (ignored=" || ((FAILURES++)) ++ ++ mustHaveSequence Thread "spin (ignored=" || ((FAILURES++)) ++ ++ mustHaveSequence "spinningSighandler (signo=" "signal handler called" 0x || ((FAILURES++)) ++ mustHaveSequence pthread_kill "spinFromSighandler (ignored=" || ((FAILURES++)) ++ ++ mustHaveSequence "spinningAltSighandler (signo=" "signal handler called" 0x || ((FAILURES++)) ++ mustHaveSequence pthread_kill "spinFromAltSighandler (ignored=" || ((FAILURES++)) ++ ++ mustHaveSequence Thread "main (argc=1, argv=" || ((FAILURES++)) ++ ++ return $FAILURES ++} ++ ++# Put result of debugging a core file in $LOG ++function getLogFromCore() { ++ # Make sure we get a core file ++ ulimit -c unlimited || exit 1 ++ ++ # Run the crasher ++ ./$(basename "$RUNME") ++ EXITCODE=$? ++ ++ # Verify that we actually crashed ++ if [ $EXITCODE -lt 128 ] ; then ++ echo >> /dev/stderr ERROR: $RUNME should have been killed by a signal, got non-signal exit code $EXITCODE ++ exit 1 ++ fi ++ ++ # Verify that we got a core file ++ if [ ! -r core* ] ; then ++ echo >> /dev/stderr ERROR: $RUNME did not create a core file ++ exit 1 ++ fi ++ ++ # Run gdb ++ cat > gdbscript.gdb < $LOG ++ EXITCODE=$? ++ ++ if [ $EXITCODE != 0 ] ; then ++ ((FAILURES++)) ++ echo >> /dev/stderr WARNING: gdb exited with error code $EXITCODE ++ fi ++} ++ ++# Put result of debugging a gcore file in $LOG ++function getLogFromGcore() { ++ # Create the core file ++ rm -f core* ++ cat > gdbscript.gdb < /dev/null ++ EXITCODE=$? ++ ++ if [ $EXITCODE != 0 ] ; then ++ ((FAILURES++)) ++ echo >> /dev/stderr WARNING: gdb exited with error code $EXITCODE when creating gcore file ++ fi ++ ++ # Verify that we got a core file from gcore ++ if [ ! -r core* ] ; then ++ echo >> /dev/stderr ERROR: gdb gcore did not create a core file ++ exit 1 ++ fi ++ ++ # Run gdb on the gcore file ++ cat > gdbscript.gdb < $LOG ++ EXITCODE=$? ++ ++ if [ $EXITCODE != 0 ] ; then ++ ((FAILURES++)) ++ echo >> /dev/stderr WARNING: gdb exited with error code $EXITCODE when examining gcore file ++ fi ++} ++ ++# Put result of debugging a core file in $LOG ++function getLogFromLiveProcess() { ++ # Run gdb ++ cat > gdbscript.gdb < $LOG ++ EXITCODE=$? ++ ++ if [ $EXITCODE != 0 ] ; then ++ ((FAILURES++)) ++ echo >> /dev/stderr WARNING: gdb exited with error code $EXITCODE ++ fi ++} ++ ++####### Main program follows ##################### ++ ++# Make sure we don't clobber anybody else's (core) file(s) ++WORKDIR=/tmp/$PPID ++mkdir -p $WORKDIR ++cp "$RUNME" $WORKDIR ++cd $WORKDIR ++ ++# Count problems ++FAILURES=0 ++ ++echo === Testing gdb vs core file... ++getLogFromCore ++verifyLog ++((FAILURES+=$?)) ++echo === Core file tests done. ++ ++echo ++ ++echo === Testing gdb vs gcore file... ++getLogFromGcore ++verifyLog ++((FAILURES+=$?)) ++echo === Gcore file tests done. ++ ++echo ++ ++echo === Testing gdb vs live process... ++getLogFromLiveProcess ++verifyLog ++((FAILURES+=$?)) ++echo === Live process tests done. ++ ++# Executive summary ++echo ++if [ $FAILURES == 0 ] ; then ++ echo All tests passed! ++else ++ echo $FAILURES tests failed! ++ echo ++ echo Make sure the threadcrash binary contains debugging information \(build with \"gcc -g\"\). ++fi ++ ++# Clean up ++cd / ++rm -rf $WORKDIR ++ ++exit $FAILURES diff --git a/gdb-6.5-relativedebug.patch b/gdb-6.5-relativedebug.patch new file mode 100644 index 0000000..3f53ffa --- /dev/null +++ b/gdb-6.5-relativedebug.patch @@ -0,0 +1,143 @@ +2006-10-29 Jan Kratochvil + + * gdb/symtab.c (matching_bfd_sections): Fix VMA matching for objects + loaded at a different address than stored on the disk. + +2006-10-29 Jan Kratochvil + + * gdb.base/relativedebug.c, gdb.base/relativedebug.exp: New file, + resolving of PC in libc pause(3) (with possibly different on-disk VMA). + + +Index: ./gdb/symtab.c +=================================================================== +--- ./gdb/symtab.c 17 Oct 2006 20:17:44 -0000 1.148 ++++ ./gdb/symtab.c 29 Oct 2006 22:29:21 -0000 +@@ -739,8 +739,11 @@ matching_bfd_sections (asection *first, + if (bfd_get_section_size (first) != bfd_get_section_size (second)) + return 0; + ++ /* In-memory addresses may start at a different offset, relativize them. */ + if (bfd_get_section_vma (first->owner, first) +- != bfd_get_section_vma (second->owner, second)) ++ - bfd_get_start_address (first->owner) ++ != bfd_get_section_vma (second->owner, second) ++ - bfd_get_start_address (second->owner)) + return 0; + + if (bfd_get_section_name (first->owner, first) == NULL +Index: ./gdb/testsuite/gdb.base/relativedebug.c +=================================================================== +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.base/relativedebug.c 29 Oct 2006 22:29:21 -0000 +@@ -0,0 +1,37 @@ ++/* This testcase is part of GDB, the GNU debugger. ++ ++ Copyright 2006 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 2 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, write to the Free Software ++ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA ++ 02111-1307, USA. */ ++ ++#include ++#include ++#include ++ ++ ++static void handler (int signo) ++{ ++ abort (); ++} ++ ++int main (void) ++{ ++ signal (SIGALRM, handler); ++ alarm (1); ++ pause (); ++ pause (); ++ return 0; ++} +Index: ./gdb/testsuite/gdb.base/relativedebug.exp +=================================================================== +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.base/relativedebug.exp 29 Oct 2006 22:29:21 -0000 +@@ -0,0 +1,68 @@ ++# Copyright 2006 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 2 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, write to the Free Software ++# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ ++if $tracelevel then { ++ strace $tracelevel ++} ++ ++set testfile relativedebug ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } { ++ untested "Couldn't compile test program" ++ return -1 ++} ++ ++# Get things started. ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++# pause () -> SIGALRM -> handler () -> abort () ++ ++gdb_test "run" \ ++ ".*Program received signal SIGABRT, Aborted..*" \ ++ "run" ++ ++# incorrect (#6): ++# (gdb) bt ++# #0 0x00325402 in __kernel_vsyscall () ++# #1 0x00718f20 in *__GI_raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64 ++# #2 0x0071a801 in *__GI_abort () at abort.c:88 ++# #3 0x0804841f in handler (signo=14) at ./gdb.base/relativedebug.c:27 ++# #4 ++# #5 0x00325402 in __kernel_vsyscall () ++# #6 0x0077ebc6 in ?? () from /lib/i686/nosegneg/libc.so.6 ++# #7 0x08048455 in main () at ./gdb.base/relativedebug.c:34 ++# (gdb) ++ ++# correct (#6): ++# (gdb) bt ++# #0 0x00b33402 in __kernel_vsyscall () ++# #1 0x00718f20 in *__GI_raise (sig=6) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64 ++# #2 0x0071a801 in *__GI_abort () at abort.c:88 ++# #3 0x0804841f in handler (signo=14) at ./gdb.base/relativedebug.c:27 ++# #4 ++# #5 0x00b33402 in __kernel_vsyscall () ++# #6 0x0077ebc6 in __pause_nocancel () from /lib/i686/nosegneg/libc.so.6 ++# #7 0x08048455 in main () at ./gdb.base/relativedebug.c:34 ++# (gdb) ++ ++gdb_test "bt" \ ++ ".*\[^a-zA-Z\]pause\[^a-zA-Z\].*" \ ++ "pause(3) seen there" diff --git a/gdb-6.5-symbols-overlap.patch b/gdb-6.5-symbols-overlap.patch new file mode 100644 index 0000000..9cfa29d --- /dev/null +++ b/gdb-6.5-symbols-overlap.patch @@ -0,0 +1,195 @@ +2006-10-30 Jan Kratochvil + + * gdb/minsyms.c (lookup_minimal_symbol_by_pc_section): Handle + overlapping non-zero sized functions (for glibc `__nanosleep'). + +2006-10-30 Jan Kratochvil + + * gdb.arch/i386-size-overlap.c, gdb.arch/i386-size-overlap.exp: New + file, provide nested (overlapping) functions for the PC resolving. + + +--- gdb-6.5/gdb/minsyms.c-orig 2006-10-31 08:21:32.000000000 -0500 ++++ gdb-6.5/gdb/minsyms.c 2006-10-31 08:24:37.000000000 -0500 +@@ -464,6 +464,7 @@ + objfile's minimal symbol table. See if it is the best one + overall. */ + ++ while (0 + /* Skip any absolute symbols. This is apparently what adb + and dbx do, and is needed for the CM-5. There are two + known possible problems: (1) on ELF, apparently end, edata, +@@ -473,8 +474,27 @@ + NeXT are absolute. If we want special handling for this + it probably should be triggered by a special + mst_abs_or_lib or some such. */ +- while (hi >= 0 +- && msymbol[hi].type == mst_abs) ++ || (hi >= 0 ++ && msymbol[hi].type == mst_abs) ++ /* We are behind the current symbol's size. ++ Try the previous symbol - if it is non-zero sized one it ++ may overlap the current one and reach our PC. ++ It occurs for GNU/Linux glibc `__nanosleep' overlapping ++ later `__nanosleep_nocancel' with PC at 0077ec66: ++ Num: Value Size Type Bind Vis Ndx Name ++ 7247: 0077ec20 124 FUNC WEAK DEFAULT 11 __nanosleep ++ 4651: 0077ec2a 32 FUNC LOCAL DEFAULT 11 __nanosleep_nocancel ++ Test `gdb.arch/i386-size' + `gdb.arch/i386-unwind'. ++ Limit it only for the overlapping cases as we could harm ++ the zero-sized symbols detection logic around. ++ */ ++ || (hi > 0 ++ && MSYMBOL_SIZE (&msymbol[hi]) != 0 ++ && pc >= (SYMBOL_VALUE_ADDRESS (&msymbol[hi]) ++ + MSYMBOL_SIZE (&msymbol[hi])) ++ && pc < (SYMBOL_VALUE_ADDRESS (&msymbol[hi - 1]) ++ + MSYMBOL_SIZE (&msymbol[hi - 1]))) ++ ) + --hi; + + /* If "section" specified, skip any symbol from wrong section */ +Index: ./gdb/testsuite/gdb.arch/i386-size-overlap.c +=================================================================== +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.arch/i386-size-overlap.c 30 Oct 2006 12:41:35 -0000 +@@ -0,0 +1,53 @@ ++/* Overlapping symbol sizes test program. ++ ++ Copyright 2006 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 2 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, write to the Free Software ++ Foundation, Inc., 59 Temple Place - Suite 330, ++ Boston, MA 02111-1307, USA. */ ++ ++#ifdef SYMBOL_PREFIX ++#define SYMBOL(str) SYMBOL_PREFIX #str ++#else ++#define SYMBOL(str) #str ++#endif ++ ++void ++trap (void) ++{ ++ asm ("int $0x03"); ++} ++ ++/* Jump from a function with its symbol size set, to a function ++ named by a local label. GDB should report the `main' function ++ even for the rest, after the global `inner' ends. */ ++ ++asm(".text\n" ++ " .align 8\n" ++ " .globl " SYMBOL (main) "\n" ++ SYMBOL (main) ":\n" ++ " pushl %ebp\n" ++ " mov %esp, %ebp\n" ++ " call .Lfunc\n" ++ " ret\n" ++ SYMBOL (inner) ":\n" ++ " ret\n" ++ " .size " SYMBOL (inner) ", .-" SYMBOL (inner) "\n" ++ ".Lfunc:\n" ++ " pushl %ebp\n" ++ " mov %esp, %ebp\n" ++ " call " SYMBOL (trap) "\n" ++ " .size " SYMBOL (main) ", .-" SYMBOL (main) "\n"); +Index: ./gdb/testsuite/gdb.arch/i386-size-overlap.exp +=================================================================== +RCS file: gdb/testsuite/gdb.arch/i386-size-overlap.exp +diff -N gdb/testsuite/gdb.arch/i386-size-overlap.exp +--- /dev/null 1 Jan 1970 00:00:00 -0000 ++++ ./gdb/testsuite/gdb.arch/i386-size-overlap.exp 30 Oct 2006 12:41:35 -0000 +@@ -0,0 +1,79 @@ ++# Copyright 2006 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 2 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, write to the Free Software ++# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ ++# Please email any bugs, comments, and/or additions to this file to: ++# bug-gdb@gnu.org ++ ++# This file is part of the gdb testsuite. ++ ++if $tracelevel { ++ strace $tracelevel ++} ++ ++# Test that GDB can handle overlapping sizes of symbols. ++ ++if ![istarget "i?86-*-*"] then { ++ verbose "Skipping i386 unwinder tests." ++ return ++} ++ ++set testfile "i386-size-overlap" ++set srcfile ${testfile}.c ++set binfile ${objdir}/${subdir}/${testfile} ++ ++# some targets have leading underscores on assembly symbols. ++# TODO: detect this automatically ++set additional_flags "" ++if [istarget "i?86-*-cygwin*"] then { ++ set additional_flags "additional_flags=-DSYMBOL_PREFIX=\"_\"" ++} ++ ++if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" \ ++ executable [list debug $additional_flags]] != "" } { ++ untested "i386-size" ++ return -1 ++} ++ ++gdb_exit ++gdb_start ++gdb_reinitialize_dir $srcdir/$subdir ++gdb_load ${binfile} ++ ++# We use gdb_run_cmd so this stands a chance to work for remote ++# targets too. ++gdb_run_cmd ++ ++gdb_expect { ++ -re "Program received signal SIGTRAP.*$gdb_prompt $" { ++ pass "run past main" ++ } ++ -re ".*$gdb_prompt $" { ++ fail "run past main" ++ } ++ timeout { ++ fail "run past main (timeout)" ++ } ++} ++ ++set message "backtrace shows the outer function" ++gdb_test_multiple "backtrace 10" $message { ++ -re "#1\[ \t]*$hex in inner.*$gdb_prompt $" { ++ fail $message ++ } ++ -re "#1\[ \t]*$hex in main.*$gdb_prompt $" { ++ pass $message ++ } ++} diff --git a/gdb.spec b/gdb.spec index d7c3f73..1811a80 100644 --- a/gdb.spec +++ b/gdb.spec @@ -11,7 +11,7 @@ Name: gdb Version: 6.5 # The release always contains a leading reserved number, start it at 0. -Release: 13%{?dist} +Release: 14%{?dist} License: GPL Group: Development/Debuggers @@ -286,6 +286,17 @@ Patch201: gdb-6.5-gcore-i386-on-amd64.patch # Fix deadlock accessing last address space byte; for corrupted backtraces. Patch203: gdb-6.5-last-address-space-byte.patch +# Fix "??" resolving of symbols from (non-prelinked) debuginfo packages. +# "gdb-6.5-matching_bfd_sections.patch" is a prerequisited CVS backport. +Patch205: gdb-6.5-matching_bfd_sections.patch +Patch206: gdb-6.5-relativedebug.patch + +# Fix "??" resolving of symbols from overlapping functions (nanosleep(3)). +Patch207: gdb-6.5-symbols-overlap.patch + +# Improved testsuite results by the testsuite provided by the courtesy of BEA. +Patch208: gdb-6.5-BEA-testsuite.patch + BuildRequires: ncurses-devel glibc-devel gcc make gzip texinfo dejagnu gettext BuildRequires: flex bison sharutils @@ -399,6 +410,10 @@ and printing their data. %patch200 -p1 %patch201 -p1 %patch203 -p1 +%patch205 -p1 +%patch206 -p1 +%patch207 -p1 +%patch208 -p1 # Change the version that gets printed at GDB startup, so it is RedHat # specific. @@ -476,7 +491,7 @@ echo ====================TESTING========================= cd gdb/testsuite # Need to use a single --ignore option, second use overrides first. # "chng-syms.exp" for possibly avoiding Linux kernel crash - Bug 207002. -make -k check RUNTESTFLAGS='--ignore "bigcore.exp chng-syms.exp"' || : +make -k check RUNTESTFLAGS='--ignore "bigcore.exp chng-syms.exp checkpoint.exp"' || : for t in sum log; do ln gdb.$t gdb-%{_target_platform}.$t || : done @@ -560,6 +575,12 @@ fi # don't include the files in include, they are part of binutils %changelog +* Sat Nov 2 2006 Jan Kratochvil - 6.5-14 +- Fix "??" resolving of symbols from (non-prelinked) debuginfo packages. +- Fix "??" resolving of symbols from overlapping functions (nanosleep(3)). +- Also disable testcase "checkpoint.exp" for a possible kernel Bug 207002. +- Improved testsuite results by the testsuite provided by the courtesy of BEA. + * Sat Oct 14 2006 Jan Kratochvil - 6.5-13 - Fix deadlock accessing last address space byte; for corrupted backtraces.