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