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