summaryrefslogtreecommitdiffstats
path: root/selftest/gdb_backtrace
blob: ec2396a630e34a6de91da5acdb7bd01cc5985920 (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
132
133
134
135
136
137
138
139
140
141
142
143
144
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}