^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) #!/bin/sh
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) # SPDX-License-Identifier: GPL-2.0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) # Disassemble the Code: line in Linux oopses
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) # usage: decodecode < oops.file
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) # options: set env. variable AFLAGS=options to pass options to "as";
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) # e.g., to decode an i386 oops on an x86_64 system, use:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) # AFLAGS=--32 decodecode < 386.oops
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) # PC=hex - the PC (program counter) the oops points to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) cleanup() {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) rm -f $T $T.s $T.o $T.oo $T.aa $T.dis
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) exit 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) die() {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) echo "$@"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) exit 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) trap cleanup EXIT
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) T=`mktemp` || die "cannot create temp file"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) code=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) cont=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) while read i ; do
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) case "$i" in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) *Code:*)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) code=$i
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) cont=yes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) ;;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) [ -n "$cont" ] && {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) xdump="$(echo $i | grep '^[[:xdigit:]<>[:space:]]\+$')"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) if [ -n "$xdump" ]; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) code="$code $xdump"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) cont=
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) ;;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) esac
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) done
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) if [ -z "$code" ]; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) rm $T
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) exit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) echo $code
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) code=`echo $code | sed -e 's/.*Code: //'`
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) width=`expr index "$code" ' '`
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) width=$((($width-1)/2))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) case $width in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) 1) type=byte ;;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) 2) type=2byte ;;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) 4) type=4byte ;;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) esac
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) if [ -z "$ARCH" ]; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) case `uname -m` in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) aarch64*) ARCH=arm64 ;;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) arm*) ARCH=arm ;;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) esac
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) # Params: (tmp_file, pc_sub)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) disas() {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) t=$1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) pc_sub=$2
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) ${CROSS_COMPILE}as $AFLAGS -o $t.o $t.s > /dev/null 2>&1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) if [ "$ARCH" = "arm" ]; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) if [ $width -eq 2 ]; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) OBJDUMPFLAGS="-M force-thumb"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) ${CROSS_COMPILE}strip $t.o
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if [ "$ARCH" = "arm64" ]; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if [ $width -eq 4 ]; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) type=inst
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) ${CROSS_COMPILE}strip $t.o
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if [ $pc_sub -ne 0 ]; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) if [ $PC ]; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) adj_vma=$(( $PC - $pc_sub ))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) OBJDUMPFLAGS="$OBJDUMPFLAGS --adjust-vma=$adj_vma"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) ${CROSS_COMPILE}objdump $OBJDUMPFLAGS -S $t.o | \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) grep -v "/tmp\|Disassembly\|\.text\|^$" > $t.dis 2>&1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) marker=`expr index "$code" "\<"`
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) if [ $marker -eq 0 ]; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) marker=`expr index "$code" "\("`
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) touch $T.oo
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if [ $marker -ne 0 ]; then
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) # 2 opcode bytes and a single space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) pc_sub=$(( $marker / 3 ))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) echo All code >> $T.oo
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) echo ======== >> $T.oo
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) beforemark=`echo "$code"`
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) echo -n " .$type 0x" > $T.s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) echo $beforemark | sed -e 's/ /,0x/g; s/[<>()]//g' >> $T.s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) disas $T $pc_sub
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) cat $T.dis >> $T.oo
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) rm -f $T.o $T.s $T.dis
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) # and fix code at-and-after marker
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) code=`echo "$code" | cut -c$((${marker} + 1))-`
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) fi
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) echo Code starting with the faulting instruction > $T.aa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) echo =========================================== >> $T.aa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) code=`echo $code | sed -e 's/ [<(]/ /;s/[>)] / /;s/ /,0x/g; s/[>)]$//'`
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) echo -n " .$type 0x" > $T.s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) echo $code >> $T.s
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) disas $T 0
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) cat $T.dis >> $T.aa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) # (lines of whole $T.oo) - (lines of $T.aa, i.e. "Code starting") + 3,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) # i.e. the title + the "===..=" line (sed is counting from 1, 0 address is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) # special)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) faultlinenum=$(( $(wc -l $T.oo | cut -d" " -f1) - \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) $(wc -l $T.aa | cut -d" " -f1) + 3))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) faultline=`cat $T.dis | head -1 | cut -d":" -f2-`
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) faultline=`echo "$faultline" | sed -e 's/\[/\\\[/g; s/\]/\\\]/g'`
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) cat $T.oo | sed -e "${faultlinenum}s/^\([^:]*:\)\(.*\)/\1\*\2\t\t<-- trapping instruction/"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) echo
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) cat $T.aa
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) cleanup