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