• B
    scripts/decodecode: make faulting insn ptr more robust · 18ff44b1
    Borislav Petkov 提交于
    It can accidentally happen that the faulting insn (the exact instruction
    bytes) is repeated a little further on in the trace.  This causes that
    same instruction to be tagged twice, see example below.
    
    What we want to do, however, is to track back from the end of the whole
    disassembly so many lines as the slice which starts with the faulting
    instruction is long.  This leads us to the actual faulting instruction
    and *then* we tag it.
    
    While we're at it, we can drop the sed "g" flag because we address only
    this one line.
    
    Also, if we point to an instruction which changes decoding depending on
    the slice being objdumped, like a Jcc insn, for example, we do not even
    tag it as a faulting instruction because the instruction decode changes
    in the second slice but we use that second format as a regex on the
    fsrst disassembled buffer and more often than not that instruction
    doesn't match.
    
    Again, simply tag the line which is deduced from the original "<>"
    marking we've received from the kernel.
    
    This also solves the pathologic issue of multiple tagging like this:
    
      29:*  0f 0b                   ud2         <-- trapping instruction
      2b:*  0f 0b                   ud2         <-- trapping instruction
      2d:*  0f 0b                   ud2         <-- trapping instruction
    
    Double tagging example:
    
    Code: 34 dd 40 30 ad 81 48 c7 c0 80 f6 00 00 48 8b 3c 30 48 01 c6 b8 ff ff ff ff 48 8d 57 f0 48 39 f7 74 2f 49 8b 4c 24 08 48 8b 47 f0 <48> 39 48 08 75 0e eb 2a 66 90 48 8b 40 f0 48 39 48 08 74 1e 48
    All code
    ========
       0:   34 dd                   xor    $0xdd,%al
       2:   40 30 ad 81 48 c7 c0    xor    %bpl,-0x3f38b77f(%rbp)
       9:   80 f6 00                xor    $0x0,%dh
       c:   00 48 8b                add    %cl,-0x75(%rax)
       f:   3c 30                   cmp    $0x30,%al
      11:   48 01 c6                add    %rax,%rsi
      14:   b8 ff ff ff ff          mov    $0xffffffff,%eax
      19:   48 8d 57 f0             lea    -0x10(%rdi),%rdx
      1d:   48 39 f7                cmp    %rsi,%rdi
      20:   74 2f                   je     0x51
      22:   49 8b 4c 24 08          mov    0x8(%r12),%rcx
      27:   48 8b 47 f0             mov    -0x10(%rdi),%rax
      2b:*  48 39 48 08             cmp    %rcx,0x8(%rax)     <-- trapping instruction
      2f:   75 0e                   jne    0x3f
      31:   eb 2a                   jmp    0x5d
      33:   66 90                   xchg   %ax,%ax
      35:   48 8b 40 f0             mov    -0x10(%rax),%rax
      39:*  48 39 48 08             cmp    %rcx,0x8(%rax)     <-- trapping instruction
      3d:   74 1e                   je     0x5d
      3f:   48                      rex.W
    Signed-off-by: NBorislav Petkov <bp@suse.de>
    Cc: "H. Peter Anvin" <hpa@zytor.com>
    Signed-off-by: NAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: NLinus Torvalds <torvalds@linux-foundation.org>
    18ff44b1
decodecode 2.1 KB
#!/bin/sh
# 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=

while read i ; do

case "$i" in
*Code:*)
	code=$i
	;;
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

	${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
反馈
建议
客服 返回
顶部