summaryrefslogtreecommitdiff
path: root/scripts/stacktrace.sh
blob: 39699499efa6b7aa6b2f2f60da8dbb3971733da8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#!/bin/bash
#
# Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd
#
# SPDX-License-Identifier: GPL-2.0
#

set -e
ARGS_N=$#
INPUT_FILE=$1
SYMBOL_FILE=`find -name u-boot.sym`

echo
if [ $ARGS_N -eq 0 ]; then
	echo "Usage: "
	echo "	./scripts/stacktrace.sh <file>  // u-boot stacktrace info file"
	exit 1
elif [ ! -f $INPUT_FILE ]; then
	echo "Can't find input file: $INPUT_FILE"
	exit 1
elif [ "$SYMBOL_FILE" = '' ] || [ ! -f $SYMBOL_FILE ]; then
	echo "Can't find symbol file: u-boot.sym"
	exit 1
fi

# Parse PC and LR
echo "Call trace:"
sed -n "/:   \[</p" $INPUT_FILE | while read line
do
	echo -n " ${line}  "

	frame_pc_str=`echo $line | awk '{ print "0x"$3 }'`
	frame_pc_dec=`echo $line | awk '{ print strtonum("0x"$3); }'`
	frame_pc_hex=`echo "obase=16;${frame_pc_dec}"|bc |tr '[A-Z]' '[a-z]'`

	f_pc_dec=`cat u-boot.sym | sort | awk '/\.text/ { if (strtonum("0x"$1) > '$frame_pc_str') { print fpc; exit; } fpc=strtonum("0x"$1); }'`
	f_pc_hex=`echo "obase=16;${f_pc_dec}"|bc |tr '[A-Z]' '[a-z]'`
	f_offset_dec=$((frame_pc_dec-f_pc_dec))
	f_offset_hex=`echo "obase=16;${f_offset_dec}"|bc |tr '[A-Z]' '[a-z]'`

	cat u-boot.sym | sort |
	awk -v foffset=$f_offset_hex '/\.text/ {
		if (strtonum("0x"$1) > '$frame_pc_str') {
			printf("%s+0x%s/0x%x      ", fname, foffset, fsize);
			exit
		}
		fname=$NF;
		fsize=strtonum("0x"$5);
		fpc=strtonum("0x"$1);
	}'

	func_path=`./make.sh $frame_pc_str | awk '{ print $1 }' | sed -n "/home/p"`
	func_path=`echo ${func_path##*boot/}`
	echo $func_path
done
echo

# Parse stack
echo "Stack:"
sed -n "/        \[</p" $INPUT_FILE | while read line
do
	echo -n "       ${line}  "

	frame_pc_str=`echo $line | awk '{ print "0x"$2 }'`
	frame_pc_dec=`echo $line | awk '{ print strtonum("0x"$2); }'`
	frame_pc_hex=`echo "obase=16;${frame_pc_dec}"|bc |tr '[A-Z]' '[a-z]'`

	f_pc_dec=`cat u-boot.sym | sort | awk '/\.text/ { if (strtonum("0x"$1) > '$frame_pc_str') { print fpc; exit; } fpc=strtonum("0x"$1); }'`
	f_pc_hex=`echo "obase=16;${f_pc_dec}"|bc |tr '[A-Z]' '[a-z]'`
	f_offset_dec=$((frame_pc_dec-f_pc_dec))
	f_offset_hex=`echo "obase=16;${f_offset_dec}"|bc |tr '[A-Z]' '[a-z]'`

	cat u-boot.sym | sort |
	awk -v foffset=$f_offset_hex '/\.text/ {
		if (strtonum("0x"$1) > '$frame_pc_str') {
			printf("%s+0x%s/0x%x\n", fname, foffset, fsize);
			exit
		}
		fname=$NF;
		fsize=strtonum("0x"$5);
		fpc=strtonum("0x"$1);
	}'
done
echo