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