xref: /OK3568_Linux_fs/kernel/scripts/decodecode (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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