xref: /freebsd/usr.sbin/crashinfo/crashinfo.sh (revision f56f82e0)
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 [-b] [-d crashdir] [-n dumpnr]" \
35		"[-k kernel] [core]"
36	exit 1
37}
38
39# Find a gdb binary to use and save the value in GDB.
40find_gdb()
41{
42	local binary
43
44	for binary in /usr/local/bin/gdb /usr/libexec/gdb /usr/bin/gdb; do
45		if [ -x ${binary} ]; then
46			GDB=${binary}
47			return
48		fi
49	done
50}
51
52# Run a single gdb command against a kernel file in batch mode.
53# The kernel file is specified as the first argument and the command
54# is given in the remaining arguments.
55gdb_command()
56{
57	local k
58
59	k=$1 ; shift
60
61	if [ ${GDB} = /usr/local/bin/gdb ]; then
62		${GDB} -batch -ex "$@" $k
63	else
64		echo -e "$@" | ${GDB} -x /dev/stdin -batch $k
65	fi
66}
67
68find_kernel()
69{
70	local ivers k kvers
71
72	ivers=$(awk '
73	/Version String/ {
74		print
75		nextline=1
76		next
77	}
78	nextline==1 {
79		if ($0 ~ "^  [A-Za-z ]+: ") {
80			nextline=0
81		} else {
82			print
83		}
84	}' $INFO)
85
86	# Look for a matching kernel version.
87	for k in `sysctl -n kern.bootfile` $(ls -t /boot/*/kernel); do
88		kvers=$(gdb_command $k 'printf "  Version String: %s", version' \
89		     2>/dev/null)
90		if [ "$ivers" = "$kvers" ]; then
91			KERNEL=$k
92			break
93		fi
94	done
95}
96
97BATCH=false
98CRASHDIR=/var/crash
99DUMPNR=
100KERNEL=
101
102while getopts "bd:n:k:" opt; do
103	case "$opt" in
104	b)
105		BATCH=true
106		;;
107	d)
108		CRASHDIR=$OPTARG
109		;;
110	n)
111		DUMPNR=$OPTARG
112		;;
113	k)
114		KERNEL=$OPTARG
115		;;
116	\?)
117		usage
118		;;
119	esac
120done
121
122shift $((OPTIND - 1))
123
124if [ $# -eq 1 ]; then
125	if [ -n "$DUMPNR" ]; then
126		echo "-n and an explicit vmcore are mutually exclusive"
127		usage
128	fi
129
130	# Figure out the crash directory and number from the vmcore name.
131	CRASHDIR=`dirname $1`
132	DUMPNR=$(expr $(basename $1) : 'vmcore\.\([0-9]*\)$')
133	if [ -z "$DUMPNR" ]; then
134		echo "Unable to determine dump number from vmcore file $1."
135		exit 1
136	fi
137elif [ $# -gt 1 ]; then
138	usage
139else
140	# If we don't have an explicit dump number, operate on the most
141	# recent dump.
142	if [ -z "$DUMPNR" ]; then
143		if ! [ -r $CRASHDIR/bounds ]; then
144			echo "No crash dumps in $CRASHDIR."
145			exit 1
146		fi
147		next=`cat $CRASHDIR/bounds`
148		if [ -z "$next" ] || [ "$next" -eq 0 ]; then
149			echo "No crash dumps in $CRASHDIR."
150			exit 1
151		fi
152		DUMPNR=$(($next - 1))
153	fi
154fi
155
156VMCORE=$CRASHDIR/vmcore.$DUMPNR
157INFO=$CRASHDIR/info.$DUMPNR
158FILE=$CRASHDIR/core.txt.$DUMPNR
159HOSTNAME=`hostname`
160
161if $BATCH; then
162	echo "Writing crash summary to $FILE."
163	exec > $FILE 2>&1
164fi
165
166find_gdb
167if [ -z "$GDB" ]; then
168	echo "Unable to find a kernel debugger."
169	exit 1
170fi
171
172if [ ! -e $VMCORE ]; then
173	echo "$VMCORE not found"
174	exit 1
175fi
176
177if [ ! -e $INFO ]; then
178	echo "$INFO not found"
179	exit 1
180fi
181
182# If the user didn't specify a kernel, then try to find one.
183if [ -z "$KERNEL" ]; then
184	find_kernel
185	if [ -z "$KERNEL" ]; then
186		echo "Unable to find matching kernel for $VMCORE"
187		exit 1
188	fi
189elif [ ! -e $KERNEL ]; then
190	echo "$KERNEL not found"
191	exit 1
192fi
193
194umask 077
195
196# Simulate uname
197ostype=$(gdb_command $KERNEL 'printf "%s", ostype')
198osrelease=$(gdb_command $KERNEL 'printf "%s", osrelease')
199version=$(gdb_command $KERNEL 'printf "%s", version' | tr '\t\n' '  ')
200machine=$(gdb_command $KERNEL 'printf "%s", machine')
201
202if ! $BATCH; then
203	echo "Writing crash summary to $FILE."
204	exec > $FILE 2>&1
205fi
206
207echo "$HOSTNAME dumped core - see $VMCORE"
208echo
209date
210echo
211echo "$ostype $HOSTNAME $osrelease $version $machine"
212echo
213sed -ne '/^  Panic String: /{s//panic: /;p;}' $INFO
214echo
215
216# XXX: /bin/sh on 7.0+ is broken so we can't simply pipe the commands to
217# kgdb via stdin and have to use a temporary file instead.
218file=`mktemp /tmp/crashinfo.XXXXXX`
219if [ $? -eq 0 ]; then
220	echo "bt" >> $file
221	echo "quit" >> $file
222	${GDB%gdb}kgdb $KERNEL $VMCORE < $file
223	rm -f $file
224	echo
225fi
226echo
227
228echo "------------------------------------------------------------------------"
229echo "ps -axlww"
230echo
231ps -M $VMCORE -N $KERNEL -axlww
232echo
233
234echo "------------------------------------------------------------------------"
235echo "vmstat -s"
236echo
237vmstat -M $VMCORE -N $KERNEL -s
238echo
239
240echo "------------------------------------------------------------------------"
241echo "vmstat -m"
242echo
243vmstat -M $VMCORE -N $KERNEL -m
244echo
245
246echo "------------------------------------------------------------------------"
247echo "vmstat -z"
248echo
249vmstat -M $VMCORE -N $KERNEL -z
250echo
251
252echo "------------------------------------------------------------------------"
253echo "vmstat -i"
254echo
255vmstat -M $VMCORE -N $KERNEL -i
256echo
257
258echo "------------------------------------------------------------------------"
259echo "pstat -T"
260echo
261pstat -M $VMCORE -N $KERNEL -T
262echo
263
264echo "------------------------------------------------------------------------"
265echo "pstat -s"
266echo
267pstat -M $VMCORE -N $KERNEL -s
268echo
269
270echo "------------------------------------------------------------------------"
271echo "iostat"
272echo
273iostat -M $VMCORE -N $KERNEL
274echo
275
276echo "------------------------------------------------------------------------"
277echo "ipcs -a"
278echo
279ipcs -C $VMCORE -N $KERNEL -a
280echo
281
282echo "------------------------------------------------------------------------"
283echo "ipcs -T"
284echo
285ipcs -C $VMCORE -N $KERNEL -T
286echo
287
288# XXX: This doesn't actually work in 5.x+
289if false; then
290echo "------------------------------------------------------------------------"
291echo "w -dn"
292echo
293w -M $VMCORE -N $KERNEL -dn
294echo
295fi
296
297echo "------------------------------------------------------------------------"
298echo "nfsstat"
299echo
300nfsstat -M $VMCORE -N $KERNEL
301echo
302
303echo "------------------------------------------------------------------------"
304echo "netstat -s"
305echo
306netstat -M $VMCORE -N $KERNEL -s
307echo
308
309echo "------------------------------------------------------------------------"
310echo "netstat -m"
311echo
312netstat -M $VMCORE -N $KERNEL -m
313echo
314
315echo "------------------------------------------------------------------------"
316echo "netstat -anA"
317echo
318netstat -M $VMCORE -N $KERNEL -anA
319echo
320
321echo "------------------------------------------------------------------------"
322echo "netstat -aL"
323echo
324netstat -M $VMCORE -N $KERNEL -aL
325echo
326
327echo "------------------------------------------------------------------------"
328echo "fstat"
329echo
330fstat -M $VMCORE -N $KERNEL
331echo
332
333echo "------------------------------------------------------------------------"
334echo "dmesg"
335echo
336dmesg -a -M $VMCORE -N $KERNEL
337echo
338
339echo "------------------------------------------------------------------------"
340echo "kernel config"
341echo
342config -x $KERNEL
343
344echo
345echo "------------------------------------------------------------------------"
346echo "ddb capture buffer"
347echo
348
349ddb capture -M $VMCORE -N $KERNEL print
350