]> git.dujemihanovic.xyz Git - u-boot.git/commitdiff
scripts/decodecode: update from Linux v6.10
authorHeinrich Schuchardt <heinrich.schuchardt@canonical.com>
Fri, 9 Aug 2024 18:22:33 +0000 (20:22 +0200)
committerTom Rini <trini@konsulko.com>
Thu, 15 Aug 2024 17:51:26 +0000 (11:51 -0600)
For decoding RISC-V dumps we need to update the script.

Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
scripts/decodecode

index 9cef558528aac890dfc2d2545aa9eb2fd8be3934..6364218b2178f538b86dab8f37ced5acfada7742 100755 (executable)
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/bin/bash
 # SPDX-License-Identifier: GPL-2.0
 # Disassemble the Code: line in Linux oopses
 # usage: decodecode < oops.file
@@ -6,6 +6,9 @@
 # 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
+# PC=hex - the PC (program counter) the oops points to
+
+faultlinenum=1
 
 cleanup() {
        rm -f $T $T.s $T.o $T.oo $T.aa $T.dis
@@ -60,15 +63,27 @@ case $width in
 4) type=4byte ;;
 esac
 
+if [ -z "$ARCH" ]; then
+    case `uname -m` in
+       aarch64*) ARCH=arm64 ;;
+       arm*) ARCH=arm ;;
+       loongarch*) ARCH=loongarch ;;
+    esac
+fi
+
+# Params: (tmp_file, pc_sub)
 disas() {
-       ${CROSS_COMPILE}as $AFLAGS -o $1.o $1.s > /dev/null 2>&1
+       t=$1
+       pc_sub=$2
+
+       ${CROSS_COMPILE}as $AFLAGS -o $t.o $t.s > /dev/null 2>&1
 
        if [ "$ARCH" = "arm" ]; then
                if [ $width -eq 2 ]; then
                        OBJDUMPFLAGS="-M force-thumb"
                fi
 
-               ${CROSS_COMPILE}strip $1.o
+               ${CROSS_COMPILE}strip $t.o
        fi
 
        if [ "$ARCH" = "arm64" ]; then
@@ -76,11 +91,120 @@ disas() {
                        type=inst
                fi
 
-               ${CROSS_COMPILE}strip $1.o
+               ${CROSS_COMPILE}strip $t.o
+       fi
+
+       if [ "$ARCH" = "riscv" ]; then
+               OBJDUMPFLAGS="-M no-aliases --section=.text -D"
+               ${CROSS_COMPILE}strip $t.o
+       fi
+
+       if [ "$ARCH" = "loongarch" ]; then
+               ${CROSS_COMPILE}strip $t.o
+       fi
+
+       if [ $pc_sub -ne 0 ]; then
+               if [ $PC ]; then
+                       adj_vma=$(( $PC - $pc_sub ))
+                       OBJDUMPFLAGS="$OBJDUMPFLAGS --adjust-vma=$adj_vma"
+               fi
        fi
 
-       ${CROSS_COMPILE}objdump $OBJDUMPFLAGS -S $1.o | \
-               grep -v "/tmp\|Disassembly\|\.text\|^$" > $1.dis 2>&1
+       ${CROSS_COMPILE}objdump $OBJDUMPFLAGS -S $t.o | \
+               grep -v "/tmp\|Disassembly\|\.text\|^$" > $t.dis 2>&1
+}
+
+# Match the maximum number of opcode bytes from @op_bytes contained within
+# @opline
+#
+# Params:
+# @op_bytes: The string of bytes from the Code: line
+# @opline: The disassembled line coming from objdump
+#
+# Returns:
+# The max number of opcode bytes from the beginning of @op_bytes which match
+# the opcode bytes in the objdump line.
+get_substr_opcode_bytes_num()
+{
+       local op_bytes=$1
+       local opline=$2
+
+       local retval=0
+       substr=""
+
+       for opc in $op_bytes;
+       do
+               substr+="$opc"
+
+               opcode="$substr"
+               if [ "$ARCH" = "riscv" ]; then
+                       opcode=$(echo $opcode | tr ' ' '\n' | tac | tr -d '\n')
+               fi
+
+               # return if opcode bytes do not match @opline anymore
+               if ! echo $opline | grep -q "$opcode";
+               then
+                       break
+               fi
+
+               # add trailing space
+               substr+=" "
+               retval=$((retval+1))
+       done
+
+       return $retval
+}
+
+# Return the line number in objdump output to where the IP marker in the Code:
+# line points to
+#
+# Params:
+# @all_code: code in bytes without the marker
+# @dis_file: disassembled file
+# @ip_byte: The byte to which the IP points to
+get_faultlinenum()
+{
+       local all_code="$1"
+       local dis_file="$2"
+
+       # num bytes including IP byte
+       local num_bytes_ip=$(( $3 + 1 * $width ))
+
+       # Add the two header lines (we're counting from 1).
+       local retval=3
+
+       # remove marker
+       all_code=$(echo $all_code | sed -e 's/[<>()]//g')
+
+       while read line
+       do
+               get_substr_opcode_bytes_num "$all_code" "$line"
+               ate_opcodes=$?
+
+               if ! (( $ate_opcodes )); then
+                       continue
+               fi
+
+               num_bytes_ip=$((num_bytes_ip - ($ate_opcodes * $width) ))
+               if (( $num_bytes_ip <= 0 )); then
+                       break
+               fi
+
+               # Delete matched opcode bytes from all_code. For that, compute
+               # how many chars those opcodes are represented by and include
+               # trailing space.
+               #
+               # a byte is 2 chars, ate_opcodes is also the number of trailing
+               # spaces
+               del_chars=$(( ($ate_opcodes * $width * 2) + $ate_opcodes ))
+
+               all_code=$(echo $all_code | sed -e "s!^.\{$del_chars\}!!")
+
+               let "retval+=1"
+
+       done < $dis_file
+
+       return $retval
 }
 
 marker=`expr index "$code" "\<"`
@@ -90,36 +214,39 @@ fi
 
 touch $T.oo
 if [ $marker -ne 0 ]; then
+       # How many bytes to subtract from the program counter
+       # in order to get to the beginning virtual address of the
+       # Code:
+       pc_sub=$(( (($marker - 1) / (2 * $width + 1)) * $width ))
        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
+
+       disas $T $pc_sub
+
        cat $T.dis >> $T.oo
-       rm -f $T.o $T.s $T.dis
 
-# and fix code at-and-after marker
+       get_faultlinenum "$code" "$T.dis" $pc_sub
+       faultlinenum=$?
+
+       # and fix code at-and-after marker
        code=`echo "$code" | cut -c$((${marker} + 1))-`
+
+       rm -f $T.o $T.s $T.dis
 fi
+
 echo Code starting with the faulting instruction  > $T.aa
 echo =========================================== >> $T.aa
-code=`echo $code | sed -e 's/ [<(]/ /;s/[>)] / /;s/ /,0x/g; s/[>)]$//'`
+code=`echo $code | sed -e 's/\r//;s/ [<(]/ /;s/[>)] / /;s/ /,0x/g; s/[>)]$//'`
 echo -n "      .$type 0x" > $T.s
 echo $code >> $T.s
-disas $T
+disas $T 0
 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/"
+cat $T.oo | sed -e "${faultlinenum}s/^\([^:]*:\)\(.*\)/\1\*\2\t\t<-- trapping instruction/"
 echo
 cat $T.aa
 cleanup