xref: /freebsd/usr.sbin/crashinfo/crashinfo.sh (revision 0183e0151669735d62584fbba9125ed90716af5e)
1#!/bin/sh
2#
3# Copyright (c) 2008 Yahoo!, Inc.
4# All rights reserved.
5#
6# Redistribution and use in source and binary forms, with or without
7# modification, are permitted provided that the following conditions
8# are met:
9# 1. Redistributions of source code must retain the above copyright
10#    notice, this list of conditions and the following disclaimer.
11# 2. Redistributions in binary form must reproduce the above copyright
12#    notice, this list of conditions and the following disclaimer in the
13#    documentation and/or other materials provided with the distribution.
14# 3. Neither the name of the author nor the names of any co-contributors
15#    may be used to endorse or promote products derived from this software
16#    without specific prior written permission.
17#
18# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
19# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
22# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
28# SUCH DAMAGE.
29#
30# $FreeBSD$
31
32usage()
33{
34	echo "usage: crashinfo [-d crashdir] [-n dumpnr] [-k kernel] [core]"
35	exit 1
36}
37
38# Find a gdb binary to use and save the value in GDB.
39find_gdb()
40{
41	local binary
42
43	for binary in /usr/local/bin/gdb /usr/libexec/gdb /usr/bin/gdb; do
44		if [ -x ${binary} ]; then
45			GDB=${binary}
46			return
47		fi
48	done
49}
50
51# Run a single gdb command against a kernel file in batch mode.
52# The kernel file is specified as the first argument and the command
53# is given in the remaining arguments.
54gdb_command()
55{
56	local k
57
58	k=$1 ; shift
59
60	if [ ${GDB} = /usr/local/bin/gdb ]; then
61		${GDB} -batch -ex "$@" $k
62	else
63		echo -e "$@" | ${GDB} -x /dev/stdin -batch $k
64	fi
65}
66
67find_kernel()
68{
69	local ivers k kvers
70
71	ivers=$(awk '
72	/Version String/ {
73		print
74		nextline=1
75		next
76	}
77	nextline==1 {
78		if ($0 ~ "^  [A-Za-z ]+: ") {
79			nextline=0
80		} else {
81			print
82		}
83	}' $INFO)
84
85	# Look for a matching kernel version.
86	for k in `sysctl -n kern.bootfile` $(ls -t /boot/*/kernel); do
87		kvers=$(gdb_command $k 'printf "  Version String: %s", version' \
88		     2>/dev/null)
89		if [ "$ivers" = "$kvers" ]; then
90			KERNEL=$k
91			break
92		fi
93	done
94}
95
96CRASHDIR=/var/crash
97DUMPNR=
98KERNEL=
99
100while getopts "d:n:k:" opt; do
101	case "$opt" in
102	d)
103		CRASHDIR=$OPTARG
104		;;
105	n)
106		DUMPNR=$OPTARG
107		;;
108	k)
109		KERNEL=$OPTARG
110		;;
111	\?)
112		usage
113		;;
114	esac
115done
116
117shift $((OPTIND - 1))
118
119if [ $# -eq 1 ]; then
120	if [ -n "$DUMPNR" ]; then
121		echo "-n and an explicit vmcore are mutually exclusive"
122		usage
123	fi
124
125	# Figure out the crash directory and number from the vmcore name.
126	CRASHDIR=`dirname $1`
127	DUMPNR=$(expr $(basename $1) : 'vmcore\.\([0-9]*\)$')
128	if [ -z "$DUMPNR" ]; then
129		echo "Unable to determine dump number from vmcore file $1."
130		exit 1
131	fi
132elif [ $# -gt 1 ]; then
133	usage
134else
135	# If we don't have an explicit dump number, operate on the most
136	# recent dump.
137	if [ -z "$DUMPNR" ]; then
138		if ! [ -r $CRASHDIR/bounds ]; then
139			echo "No crash dumps in $CRASHDIR."
140			exit 1
141		fi
142		next=`cat $CRASHDIR/bounds`
143		if [ -z "$next" ] || [ "$next" -eq 0 ]; then
144			echo "No crash dumps in $CRASHDIR."
145			exit 1
146		fi
147		DUMPNR=$(($next - 1))
148	fi
149fi
150
151VMCORE=$CRASHDIR/vmcore.$DUMPNR
152INFO=$CRASHDIR/info.$DUMPNR
153FILE=$CRASHDIR/core.txt.$DUMPNR
154HOSTNAME=`hostname`
155
156find_gdb
157if [ -z "$GDB" ]; then
158	echo "Unable to find a kernel debugger."
159	exit 1
160fi
161
162if [ ! -e $VMCORE ]; then
163	echo "$VMCORE not found"
164	exit 1
165fi
166
167if [ ! -e $INFO ]; then
168	echo "$INFO not found"
169	exit 1
170fi
171
172# If the user didn't specify a kernel, then try to find one.
173if [ -z "$KERNEL" ]; then
174	find_kernel
175	if [ -z "$KERNEL" ]; then
176		echo "Unable to find matching kernel for $VMCORE"
177		exit 1
178	fi
179elif [ ! -e $KERNEL ]; then
180	echo "$KERNEL not found"
181	exit 1
182fi
183
184echo "Writing crash summary to $FILE."
185
186umask 077
187
188# Simulate uname
189ostype=$(gdb_command $KERNEL 'printf "%s", ostype')
190osrelease=$(gdb_command $KERNEL 'printf "%s", osrelease')
191version=$(gdb_command $KERNEL 'printf "%s", version' | tr '\t\n' '  ')
192machine=$(gdb_command $KERNEL 'printf "%s", machine')
193
194exec > $FILE 2>&1
195
196echo "$HOSTNAME dumped core - see $VMCORE"
197echo
198date
199echo
200echo "$ostype $HOSTNAME $osrelease $version $machine"
201echo
202sed -ne '/^  Panic String: /{s//panic: /;p;}' $INFO
203echo
204
205# XXX: /bin/sh on 7.0+ is broken so we can't simply pipe the commands to
206# kgdb via stdin and have to use a temporary file instead.
207file=`mktemp /tmp/crashinfo.XXXXXX`
208if [ $? -eq 0 ]; then
209	echo "bt" >> $file
210	echo "quit" >> $file
211	${GDB%gdb}kgdb $KERNEL $VMCORE < $file
212	rm -f $file
213	echo
214fi
215echo
216
217echo "------------------------------------------------------------------------"
218echo "ps -axlww"
219echo
220ps -M $VMCORE -N $KERNEL -axlww
221echo
222
223echo "------------------------------------------------------------------------"
224echo "vmstat -s"
225echo
226vmstat -M $VMCORE -N $KERNEL -s
227echo
228
229echo "------------------------------------------------------------------------"
230echo "vmstat -m"
231echo
232vmstat -M $VMCORE -N $KERNEL -m
233echo
234
235echo "------------------------------------------------------------------------"
236echo "vmstat -z"
237echo
238vmstat -M $VMCORE -N $KERNEL -z
239echo
240
241echo "------------------------------------------------------------------------"
242echo "vmstat -i"
243echo
244vmstat -M $VMCORE -N $KERNEL -i
245echo
246
247echo "------------------------------------------------------------------------"
248echo "pstat -T"
249echo
250pstat -M $VMCORE -N $KERNEL -T
251echo
252
253echo "------------------------------------------------------------------------"
254echo "pstat -s"
255echo
256pstat -M $VMCORE -N $KERNEL -s
257echo
258
259echo "------------------------------------------------------------------------"
260echo "iostat"
261echo
262iostat -M $VMCORE -N $KERNEL
263echo
264
265echo "------------------------------------------------------------------------"
266echo "ipcs -a"
267echo
268ipcs -C $VMCORE -N $KERNEL -a
269echo
270
271echo "------------------------------------------------------------------------"
272echo "ipcs -T"
273echo
274ipcs -C $VMCORE -N $KERNEL -T
275echo
276
277# XXX: This doesn't actually work in 5.x+
278if false; then
279echo "------------------------------------------------------------------------"
280echo "w -dn"
281echo
282w -M $VMCORE -N $KERNEL -dn
283echo
284fi
285
286echo "------------------------------------------------------------------------"
287echo "nfsstat"
288echo
289nfsstat -M $VMCORE -N $KERNEL
290echo
291
292echo "------------------------------------------------------------------------"
293echo "netstat -s"
294echo
295netstat -M $VMCORE -N $KERNEL -s
296echo
297
298echo "------------------------------------------------------------------------"
299echo "netstat -m"
300echo
301netstat -M $VMCORE -N $KERNEL -m
302echo
303
304echo "------------------------------------------------------------------------"
305echo "netstat -anA"
306echo
307netstat -M $VMCORE -N $KERNEL -anA
308echo
309
310echo "------------------------------------------------------------------------"
311echo "netstat -aL"
312echo
313netstat -M $VMCORE -N $KERNEL -aL
314echo
315
316echo "------------------------------------------------------------------------"
317echo "fstat"
318echo
319fstat -M $VMCORE -N $KERNEL
320echo
321
322echo "------------------------------------------------------------------------"
323echo "dmesg"
324echo
325dmesg -a -M $VMCORE -N $KERNEL
326echo
327
328echo "------------------------------------------------------------------------"
329echo "kernel config"
330echo
331config -x $KERNEL
332
333echo
334echo "------------------------------------------------------------------------"
335echo "ddb capture buffer"
336echo
337
338ddb capture -M $VMCORE -N $KERNEL print
339