18c2ecf20Sopenharmony_ci#!/bin/sh
28c2ecf20Sopenharmony_ci# SPDX-License-Identifier: GPL-2.0
38c2ecf20Sopenharmony_ci# Disassemble the Code: line in Linux oopses
48c2ecf20Sopenharmony_ci# usage: decodecode < oops.file
58c2ecf20Sopenharmony_ci#
68c2ecf20Sopenharmony_ci# options: set env. variable AFLAGS=options to pass options to "as";
78c2ecf20Sopenharmony_ci# e.g., to decode an i386 oops on an x86_64 system, use:
88c2ecf20Sopenharmony_ci# AFLAGS=--32 decodecode < 386.oops
98c2ecf20Sopenharmony_ci# PC=hex - the PC (program counter) the oops points to
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_cicleanup() {
128c2ecf20Sopenharmony_ci	rm -f $T $T.s $T.o $T.oo $T.aa $T.dis
138c2ecf20Sopenharmony_ci	exit 1
148c2ecf20Sopenharmony_ci}
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_cidie() {
178c2ecf20Sopenharmony_ci	echo "$@"
188c2ecf20Sopenharmony_ci	exit 1
198c2ecf20Sopenharmony_ci}
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_citrap cleanup EXIT
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ciT=`mktemp` || die "cannot create temp file"
248c2ecf20Sopenharmony_cicode=
258c2ecf20Sopenharmony_cicont=
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_ciwhile read i ; do
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_cicase "$i" in
308c2ecf20Sopenharmony_ci*Code:*)
318c2ecf20Sopenharmony_ci	code=$i
328c2ecf20Sopenharmony_ci	cont=yes
338c2ecf20Sopenharmony_ci	;;
348c2ecf20Sopenharmony_ci*)
358c2ecf20Sopenharmony_ci	[ -n "$cont" ] && {
368c2ecf20Sopenharmony_ci		xdump="$(echo $i | grep '^[[:xdigit:]<>[:space:]]\+$')"
378c2ecf20Sopenharmony_ci		if [ -n "$xdump" ]; then
388c2ecf20Sopenharmony_ci			code="$code $xdump"
398c2ecf20Sopenharmony_ci		else
408c2ecf20Sopenharmony_ci			cont=
418c2ecf20Sopenharmony_ci		fi
428c2ecf20Sopenharmony_ci	}
438c2ecf20Sopenharmony_ci	;;
448c2ecf20Sopenharmony_ciesac
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_cidone
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_ciif [ -z "$code" ]; then
498c2ecf20Sopenharmony_ci	rm $T
508c2ecf20Sopenharmony_ci	exit
518c2ecf20Sopenharmony_cifi
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ciecho $code
548c2ecf20Sopenharmony_cicode=`echo $code | sed -e 's/.*Code: //'`
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ciwidth=`expr index "$code" ' '`
578c2ecf20Sopenharmony_ciwidth=$((($width-1)/2))
588c2ecf20Sopenharmony_cicase $width in
598c2ecf20Sopenharmony_ci1) type=byte ;;
608c2ecf20Sopenharmony_ci2) type=2byte ;;
618c2ecf20Sopenharmony_ci4) type=4byte ;;
628c2ecf20Sopenharmony_ciesac
638c2ecf20Sopenharmony_ci
648c2ecf20Sopenharmony_ciif [ -z "$ARCH" ]; then
658c2ecf20Sopenharmony_ci    case `uname -m` in
668c2ecf20Sopenharmony_ci	aarch64*) ARCH=arm64 ;;
678c2ecf20Sopenharmony_ci	arm*) ARCH=arm ;;
688c2ecf20Sopenharmony_ci    esac
698c2ecf20Sopenharmony_cifi
708c2ecf20Sopenharmony_ci
718c2ecf20Sopenharmony_ci# Params: (tmp_file, pc_sub)
728c2ecf20Sopenharmony_cidisas() {
738c2ecf20Sopenharmony_ci	t=$1
748c2ecf20Sopenharmony_ci	pc_sub=$2
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	${CROSS_COMPILE}as $AFLAGS -o $t.o $t.s > /dev/null 2>&1
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	if [ "$ARCH" = "arm" ]; then
798c2ecf20Sopenharmony_ci		if [ $width -eq 2 ]; then
808c2ecf20Sopenharmony_ci			OBJDUMPFLAGS="-M force-thumb"
818c2ecf20Sopenharmony_ci		fi
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci		${CROSS_COMPILE}strip $t.o
848c2ecf20Sopenharmony_ci	fi
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	if [ "$ARCH" = "arm64" ]; then
878c2ecf20Sopenharmony_ci		if [ $width -eq 4 ]; then
888c2ecf20Sopenharmony_ci			type=inst
898c2ecf20Sopenharmony_ci		fi
908c2ecf20Sopenharmony_ci
918c2ecf20Sopenharmony_ci		${CROSS_COMPILE}strip $t.o
928c2ecf20Sopenharmony_ci	fi
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	if [ $pc_sub -ne 0 ]; then
958c2ecf20Sopenharmony_ci		if [ $PC ]; then
968c2ecf20Sopenharmony_ci			adj_vma=$(( $PC - $pc_sub ))
978c2ecf20Sopenharmony_ci			OBJDUMPFLAGS="$OBJDUMPFLAGS --adjust-vma=$adj_vma"
988c2ecf20Sopenharmony_ci		fi
998c2ecf20Sopenharmony_ci	fi
1008c2ecf20Sopenharmony_ci
1018c2ecf20Sopenharmony_ci	${CROSS_COMPILE}objdump $OBJDUMPFLAGS -S $t.o | \
1028c2ecf20Sopenharmony_ci		grep -v "/tmp\|Disassembly\|\.text\|^$" > $t.dis 2>&1
1038c2ecf20Sopenharmony_ci}
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_cimarker=`expr index "$code" "\<"`
1068c2ecf20Sopenharmony_ciif [ $marker -eq 0 ]; then
1078c2ecf20Sopenharmony_ci	marker=`expr index "$code" "\("`
1088c2ecf20Sopenharmony_cifi
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_citouch $T.oo
1128c2ecf20Sopenharmony_ciif [ $marker -ne 0 ]; then
1138c2ecf20Sopenharmony_ci	# 2 opcode bytes and a single space
1148c2ecf20Sopenharmony_ci	pc_sub=$(( $marker / 3 ))
1158c2ecf20Sopenharmony_ci	echo All code >> $T.oo
1168c2ecf20Sopenharmony_ci	echo ======== >> $T.oo
1178c2ecf20Sopenharmony_ci	beforemark=`echo "$code"`
1188c2ecf20Sopenharmony_ci	echo -n "	.$type 0x" > $T.s
1198c2ecf20Sopenharmony_ci	echo $beforemark | sed -e 's/ /,0x/g; s/[<>()]//g' >> $T.s
1208c2ecf20Sopenharmony_ci	disas $T $pc_sub
1218c2ecf20Sopenharmony_ci	cat $T.dis >> $T.oo
1228c2ecf20Sopenharmony_ci	rm -f $T.o $T.s $T.dis
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci# and fix code at-and-after marker
1258c2ecf20Sopenharmony_ci	code=`echo "$code" | cut -c$((${marker} + 1))-`
1268c2ecf20Sopenharmony_cifi
1278c2ecf20Sopenharmony_ciecho Code starting with the faulting instruction  > $T.aa
1288c2ecf20Sopenharmony_ciecho =========================================== >> $T.aa
1298c2ecf20Sopenharmony_cicode=`echo $code | sed -e 's/ [<(]/ /;s/[>)] / /;s/ /,0x/g; s/[>)]$//'`
1308c2ecf20Sopenharmony_ciecho -n "	.$type 0x" > $T.s
1318c2ecf20Sopenharmony_ciecho $code >> $T.s
1328c2ecf20Sopenharmony_cidisas $T 0
1338c2ecf20Sopenharmony_cicat $T.dis >> $T.aa
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_ci# (lines of whole $T.oo) - (lines of $T.aa, i.e. "Code starting") + 3,
1368c2ecf20Sopenharmony_ci# i.e. the title + the "===..=" line (sed is counting from 1, 0 address is
1378c2ecf20Sopenharmony_ci# special)
1388c2ecf20Sopenharmony_cifaultlinenum=$(( $(wc -l $T.oo  | cut -d" " -f1) - \
1398c2ecf20Sopenharmony_ci		 $(wc -l $T.aa  | cut -d" " -f1) + 3))
1408c2ecf20Sopenharmony_ci
1418c2ecf20Sopenharmony_cifaultline=`cat $T.dis | head -1 | cut -d":" -f2-`
1428c2ecf20Sopenharmony_cifaultline=`echo "$faultline" | sed -e 's/\[/\\\[/g; s/\]/\\\]/g'`
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_cicat $T.oo | sed -e "${faultlinenum}s/^\([^:]*:\)\(.*\)/\1\*\2\t\t<-- trapping instruction/"
1458c2ecf20Sopenharmony_ciecho
1468c2ecf20Sopenharmony_cicat $T.aa
1478c2ecf20Sopenharmony_cicleanup
148