[U-Boot] [PATCH v3 0/2] arm: print instructions pointed to by pc

If an exception occurs in a loaded image and the relocation offset is unknown, it is helful to know the instructions pointed to by the program counter. The first patch adds the missing output.
The second patch provides the decodecode script from the Linux kernel which can be used to disassemble the 'Code:' line.
v3: use the Linux output format for the 'Code:' line
Heinrich Schuchardt (2): arm: print instructions pointed to by pc scripts: add decodecode from Linux
arch/arm/lib/interrupts.c | 25 ++++++++ scripts/decodecode | 125 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 150 insertions(+) create mode 100755 scripts/decodecode

If an exception occurs in a loaded image and the relocation offset is unknown, it is helful to know the instructions pointed to by the program counter. This patch adds the missing output.
A possible output is: Code: e1c560d0 e12fff1e e120077b e12fff1e (e7f7defb)
The parentheses indicate the instruction causing the exception.
The output can be disassembled using the decodecode script provided by the Linux kernel project.
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de --- v3: use the Linux output format for the 'Code:' line --- arch/arm/lib/interrupts.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+)
diff --git a/arch/arm/lib/interrupts.c b/arch/arm/lib/interrupts.c index 28ba3f14f36..930b25ccb81 100644 --- a/arch/arm/lib/interrupts.c +++ b/arch/arm/lib/interrupts.c @@ -56,6 +56,30 @@ static void show_efi_loaded_images(struct pt_regs *regs) efi_print_image_infos((void *)instruction_pointer(regs)); }
+static void dump_instr(struct pt_regs *regs) +{ + unsigned long addr = instruction_pointer(regs); + const int thumb = thumb_mode(regs); + const int width = thumb ? 4 : 8; + int i; + + if (thumb) + addr &= ~1L; + else + addr &= ~3L; + printf("Code: "); + for (i = -4; i < 1 + !!thumb; i++) { + unsigned int val; + + if (thumb) + val = ((u16 *)addr)[i]; + else + val = ((u32 *)addr)[i]; + printf(i == 0 ? "(%0*x) " : "%0*x ", width, val); + } + printf("\n"); +} + void show_regs (struct pt_regs *regs) { unsigned long __maybe_unused flags; @@ -96,6 +120,7 @@ void show_regs (struct pt_regs *regs) fast_interrupts_enabled (regs) ? "on" : "off", processor_modes[processor_mode (regs)], thumb_mode (regs) ? " (T)" : ""); + dump_instr(regs); }
/* fixup PC to point to the instruction leading to the exception */

On 15.05.18 19:42, Heinrich Schuchardt wrote:
If an exception occurs in a loaded image and the relocation offset is unknown, it is helful to know the instructions pointed to by the program counter. This patch adds the missing output.
A possible output is: Code: e1c560d0 e12fff1e e120077b e12fff1e (e7f7defb)
The parentheses indicate the instruction causing the exception.
The output can be disassembled using the decodecode script provided by the Linux kernel project.
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de
This is even better than my suggestion. Aweseome ;).
Reviewed-by: Alexander Graf agraf@suse.de
Alex

On Tue, May 15, 2018 at 07:42:23PM +0200, Heinrich Schuchardt wrote:
If an exception occurs in a loaded image and the relocation offset is unknown, it is helful to know the instructions pointed to by the program counter. This patch adds the missing output.
A possible output is: Code: e1c560d0 e12fff1e e120077b e12fff1e (e7f7defb)
The parentheses indicate the instruction causing the exception.
The output can be disassembled using the decodecode script provided by the Linux kernel project.
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de
Applied to u-boot/master, thanks!

The script decodecode can be used to disassemble the 'Code:' line written when an exception occurs.
The script is copied from Linux v4.16.
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de --- v3: new patch --- scripts/decodecode | 125 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100755 scripts/decodecode
diff --git a/scripts/decodecode b/scripts/decodecode new file mode 100755 index 00000000000..9cef558528a --- /dev/null +++ b/scripts/decodecode @@ -0,0 +1,125 @@ +#!/bin/sh +# SPDX-License-Identifier: GPL-2.0 +# Disassemble the Code: line in Linux oopses +# usage: decodecode < oops.file +# +# options: set env. variable AFLAGS=options to pass options to "as"; +# e.g., to decode an i386 oops on an x86_64 system, use: +# AFLAGS=--32 decodecode < 386.oops + +cleanup() { + rm -f $T $T.s $T.o $T.oo $T.aa $T.dis + exit 1 +} + +die() { + echo "$@" + exit 1 +} + +trap cleanup EXIT + +T=`mktemp` || die "cannot create temp file" +code= +cont= + +while read i ; do + +case "$i" in +*Code:*) + code=$i + cont=yes + ;; +*) + [ -n "$cont" ] && { + xdump="$(echo $i | grep '^[[:xdigit:]<>[:space:]]+$')" + if [ -n "$xdump" ]; then + code="$code $xdump" + else + cont= + fi + } + ;; +esac + +done + +if [ -z "$code" ]; then + rm $T + exit +fi + +echo $code +code=`echo $code | sed -e 's/.*Code: //'` + +width=`expr index "$code" ' '` +width=$((($width-1)/2)) +case $width in +1) type=byte ;; +2) type=2byte ;; +4) type=4byte ;; +esac + +disas() { + ${CROSS_COMPILE}as $AFLAGS -o $1.o $1.s > /dev/null 2>&1 + + if [ "$ARCH" = "arm" ]; then + if [ $width -eq 2 ]; then + OBJDUMPFLAGS="-M force-thumb" + fi + + ${CROSS_COMPILE}strip $1.o + fi + + if [ "$ARCH" = "arm64" ]; then + if [ $width -eq 4 ]; then + type=inst + fi + + ${CROSS_COMPILE}strip $1.o + fi + + ${CROSS_COMPILE}objdump $OBJDUMPFLAGS -S $1.o | \ + grep -v "/tmp|Disassembly|.text|^$" > $1.dis 2>&1 +} + +marker=`expr index "$code" "<"` +if [ $marker -eq 0 ]; then + marker=`expr index "$code" "("` +fi + +touch $T.oo +if [ $marker -ne 0 ]; then + echo All code >> $T.oo + echo ======== >> $T.oo + beforemark=`echo "$code"` + echo -n " .$type 0x" > $T.s + echo $beforemark | sed -e 's/ /,0x/g; s/[<>()]//g' >> $T.s + disas $T + cat $T.dis >> $T.oo + rm -f $T.o $T.s $T.dis + +# and fix code at-and-after marker + code=`echo "$code" | cut -c$((${marker} + 1))-` +fi +echo Code starting with the faulting instruction > $T.aa +echo =========================================== >> $T.aa +code=`echo $code | sed -e 's/ [<(]/ /;s/[>)] / /;s/ /,0x/g; s/[>)]$//'` +echo -n " .$type 0x" > $T.s +echo $code >> $T.s +disas $T +cat $T.dis >> $T.aa + +# (lines of whole $T.oo) - (lines of $T.aa, i.e. "Code starting") + 3, +# i.e. the title + the "===..=" line (sed is counting from 1, 0 address is +# special) +faultlinenum=$(( $(wc -l $T.oo | cut -d" " -f1) - \ + $(wc -l $T.aa | cut -d" " -f1) + 3)) + +faultline=`cat $T.dis | head -1 | cut -d":" -f2-` +faultline=`echo "$faultline" | sed -e 's/[/\[/g; s/]/\]/g'` + +cat $T.oo | sed -e "${faultlinenum}s/^(.*:)(.*)/\1*\2\t\t<-- trapping instruction/" +echo +cat $T.aa +cleanup

On Tue, May 15, 2018 at 07:42:24PM +0200, Heinrich Schuchardt wrote:
The script decodecode can be used to disassemble the 'Code:' line written when an exception occurs.
The script is copied from Linux v4.16.
Signed-off-by: Heinrich Schuchardt xypron.glpk@gmx.de
Applied to u-boot/master, thanks!
participants (3)
-
Alexander Graf
-
Heinrich Schuchardt
-
Tom Rini