hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/scripts/decode_stacktrace.sh
....@@ -3,17 +3,67 @@
33 # (c) 2014, Sasha Levin <sasha.levin@oracle.com>
44 #set -x
55
6
-if [[ $# < 2 ]]; then
6
+if [[ $# < 1 ]]; then
77 echo "Usage:"
8
- echo " $0 [vmlinux] [base path] [modules path]"
8
+ echo " $0 -r <release> | <vmlinux> [base path] [modules path]"
99 exit 1
1010 fi
1111
12
-vmlinux=$1
13
-basepath=$2
14
-modpath=$3
12
+if [[ $1 == "-r" ]] ; then
13
+ vmlinux=""
14
+ basepath="auto"
15
+ modpath=""
16
+ release=$2
17
+
18
+ for fn in {,/usr/lib/debug}/boot/vmlinux-$release{,.debug} /lib/modules/$release{,/build}/vmlinux ; do
19
+ if [ -e "$fn" ] ; then
20
+ vmlinux=$fn
21
+ break
22
+ fi
23
+ done
24
+
25
+ if [[ $vmlinux == "" ]] ; then
26
+ echo "ERROR! vmlinux image for release $release is not found" >&2
27
+ exit 2
28
+ fi
29
+else
30
+ vmlinux=$1
31
+ basepath=${2-auto}
32
+ modpath=$3
33
+ release=""
34
+fi
35
+
1536 declare -A cache
1637 declare -A modcache
38
+
39
+find_module() {
40
+ if [[ "$modpath" != "" ]] ; then
41
+ for fn in $(find "$modpath" -name "${module//_/[-_]}.ko*") ; do
42
+ if readelf -WS "$fn" | grep -qwF .debug_line ; then
43
+ echo $fn
44
+ return
45
+ fi
46
+ done
47
+ return 1
48
+ fi
49
+
50
+ modpath=$(dirname "$vmlinux")
51
+ find_module && return
52
+
53
+ if [[ $release == "" ]] ; then
54
+ release=$(gdb -ex 'print init_uts_ns.name.release' -ex 'quit' -quiet -batch "$vmlinux" | sed -n 's/\$1 = "\(.*\)".*/\1/p')
55
+ fi
56
+
57
+ for dn in {/usr/lib/debug,}/lib/modules/$release ; do
58
+ if [ -e "$dn" ] ; then
59
+ modpath="$dn"
60
+ find_module && return
61
+ fi
62
+ done
63
+
64
+ modpath=""
65
+ return 1
66
+}
1767
1868 parse_symbol() {
1969 # The structure of symbol at this point is:
....@@ -27,15 +77,24 @@
2777 elif [[ "${modcache[$module]+isset}" == "isset" ]]; then
2878 local objfile=${modcache[$module]}
2979 else
30
- [[ $modpath == "" ]] && return
31
- local objfile=$(find "$modpath" -name $module.ko -print -quit)
32
- [[ $objfile == "" ]] && return
80
+ local objfile=$(find_module)
81
+ if [[ $objfile == "" ]] ; then
82
+ echo "WARNING! Modules path isn't set, but is needed to parse this symbol" >&2
83
+ return
84
+ fi
3385 modcache[$module]=$objfile
3486 fi
3587
3688 # Remove the englobing parenthesis
3789 symbol=${symbol#\(}
3890 symbol=${symbol%\)}
91
+
92
+ # Strip segment
93
+ local segment
94
+ if [[ $symbol == *:* ]] ; then
95
+ segment=${symbol%%:*}:
96
+ symbol=${symbol#*:}
97
+ fi
3998
4099 # Strip the symbol name so that we could look it up
41100 local name=${symbol%+*}
....@@ -46,7 +105,11 @@
46105 if [[ "${cache[$module,$name]+isset}" == "isset" ]]; then
47106 local base_addr=${cache[$module,$name]}
48107 else
49
- local base_addr=$(nm "$objfile" | grep -i ' t ' | awk "/ $name\$/ {print \$1}" | head -n1)
108
+ local base_addr=$(nm "$objfile" | awk '$3 == "'$name'" && ($2 == "t" || $2 == "T") {print $1; exit}')
109
+ if [[ $base_addr == "" ]] ; then
110
+ # address not found
111
+ return
112
+ fi
50113 cache[$module,$name]="$base_addr"
51114 fi
52115 # Let's start doing the math to get the exact address into the
....@@ -84,7 +147,7 @@
84147 code=${code//$'\n'/' '}
85148
86149 # Replace old address with pretty line numbers
87
- symbol="$name ($code)"
150
+ symbol="$segment$name ($code)"
88151 }
89152
90153 decode_code() {
....@@ -138,6 +201,14 @@
138201 echo "${words[@]}" "$symbol $module"
139202 }
140203
204
+if [[ $basepath == "auto" ]] ; then
205
+ module=""
206
+ symbol="kernel_init+0x0/0x0"
207
+ parse_symbol
208
+ basepath=${symbol#kernel_init (}
209
+ basepath=${basepath%/init/main.c:*)}
210
+fi
211
+
141212 while read line; do
142213 # Let's see if we have an address in the line
143214 if [[ $line =~ \[\<([^]]+)\>\] ]] ||