summaryrefslogtreecommitdiffstats
path: root/selftest/gdb_backtrace
blob: 28ac064bcd400fbfc09b40697f34de422926e0b5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#!/bin/sh

BASENAME=`basename $0`

if [ -n "$VALGRIND" -o -n "$SMBD_VALGRIND" ]; then
	echo "${BASENAME}: Not running debugger under valgrind"
	exit 1
fi

# we want everything on stderr, so the program is not disturbed
exec 1>&2

BASENAME=`basename $0`
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=/tmp/gdb_backtrace_pre.$$
BATCHFILE_MAIN=/tmp/gdb_backtrace_main.$$
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}