summaryrefslogtreecommitdiffstats
path: root/selftest/gdb_backtrace
diff options
context:
space:
mode:
Diffstat (limited to 'selftest/gdb_backtrace')
-rwxr-xr-xselftest/gdb_backtrace145
1 files changed, 145 insertions, 0 deletions
diff --git a/selftest/gdb_backtrace b/selftest/gdb_backtrace
new file mode 100755
index 0000000..ec2396a
--- /dev/null
+++ b/selftest/gdb_backtrace
@@ -0,0 +1,145 @@
+#!/bin/sh
+
+BASENAME=$(basename $0)
+
+unset LD_PRELOAD
+
+if [ -n "$VALGRIND" -o -n "$SMBD_VALGRIND" ]; then
+ echo "${BASENAME}: Not running debugger under valgrind"
+ exit 1
+fi
+
+if [ "x$PLEASE_NO_GDB_BACKTRACE" != "x" ]; then
+ echo "${BASENAME}: Not running debugger because PLEASE_NO_GDB_BACKTRACE is set"
+ exit 0
+fi
+
+# we want everything on stderr, so the program is not disturbed
+exec 1>&2
+
+UNAME=$(uname)
+
+PID=$1
+BINARY=$2
+
+test x"${PID}" = x"" && {
+ echo "Usage: ${BASENAME} <pid> [<binary>]"
+ exit 1
+}
+
+DB_LIST="gdb"
+case "${UNAME}" in
+#
+# on Tru64 we need to try ladebug first
+# because gdb crashes itself...
+#
+OSF1)
+ DB_LIST="ladebug ${DB_LIST}"
+ ;;
+#
+# On solaris dbx is working way more better than gdb
+# let's try it first
+#
+SunOS)
+ DB_LIST="dbx ${DB_LIST}"
+ ;;
+#
+# FreeBSD comes with a flavor that works gdb66 and one that don't gdb
+# (gdb 6.1) let's try it first the one that works !
+#
+FreeBSD)
+ DB_LIST="gdb66 ${DB_LIST}"
+ ;;
+esac
+
+for DB in ${DB_LIST}; do
+ DB_BIN=$(which ${DB} 2>/dev/null | grep '^/')
+ test x"${DB_BIN}" != x"" && {
+ break
+ }
+done
+
+test x"${DB_BIN}" = x"" && {
+ echo "${BASENAME}: ERROR: No debugger found."
+ exit 1
+}
+
+need_binary="no"
+case "${DB}" in
+# These debuggers need the process binary specified:
+ladebug)
+ need_binary="yes"
+ ;;
+gdb66)
+ need_binary="yes"
+ ;;
+dbx)
+ need_binary="yes"
+ ;;
+esac
+
+test x"${need_binary}" = x"yes" && {
+
+ # we first try to use /proc/${PID}/exe or /proc/{$PID}/path for solaris
+ # then fallback to the binary from the commandline
+ # then we search for the commandline argument with
+ # 'which'
+ #
+ test -f "/proc/${PID}/exe" && BINARY="/proc/${PID}/exe"
+ test -f "/proc/${PID}/path/a.out" && BINARY=$(ls -l /proc/${PID}/path/a.out | sed 's/.*-> //')
+ test x"${BINARY}" = x"" && BINARY="/proc/${PID}/exe"
+ test -f "${BINARY}" || BINARY=$(which ${BINARY})
+
+ test -f "${BINARY}" || {
+ echo "${BASENAME}: ERROR: Cannot find binary '${BINARY}'."
+ exit 1
+ }
+}
+
+BATCHFILE_PRE=$(mktemp --tmpdir gdb_backtrace_pre.XXXXXXXXXX)
+test -n "${BATCHFILE_PRE}" || {
+ echo "mktemp doesn't work" 1>&2
+ exit 1
+}
+BATCHFILE_MAIN=$(mktemp --tmpdir gdb_backtrace_main.XXXXXXXXXX)
+test -n "${BATCHFILE_MAIN}" || {
+ echo "mktemp doesn't work" 1>&2
+ exit 1
+}
+case "${DB}" in
+ladebug)
+ cat <<EOF >${BATCHFILE_PRE}
+set \$stoponattach
+EOF
+
+ cat <<EOF >${BATCHFILE_MAIN}
+where
+quit
+EOF
+ ${DB_BIN} -c "${BATCHFILE_MAIN}" -i "${BATCHFILE_PRE}" -pid "${PID}" "${BINARY}"
+ ;;
+gdb66)
+ cat <<EOF >${BATCHFILE_MAIN}
+set height 1000
+bt full
+info locals
+kill
+quit
+EOF
+ ${DB_BIN} -x "${BATCHFILE_MAIN}" "${BINARY}" "${PID}"
+ ;;
+gdb)
+ cat <<EOF >${BATCHFILE_MAIN}
+set height 0
+bt full
+thread apply all bt full
+info locals
+quit
+EOF
+ ${DB_BIN} -batch -x "${BATCHFILE_MAIN}" --pid "${PID}" </dev/null
+ ;;
+dbx)
+ ${DB_BIN} "where;dump;kill;quit" "${BINARY}" "${PID}"
+ ;;
+esac
+/bin/rm -f ${BATCHFILE_PRE} ${BATCHFILE_MAIN}