Skip to content
Navigation Menu
Toggle navigation
Sign in
In this repository
All GitHub Enterprise
↵
Jump to
↵
No suggested jump to results
In this repository
All GitHub Enterprise
↵
Jump to
↵
In this organization
All GitHub Enterprise
↵
Jump to
↵
In this repository
All GitHub Enterprise
↵
Jump to
↵
Sign in
Reseting focus
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
mariux64
/
linux
Public
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Issues
2
Pull requests
0
Actions
Projects
0
Wiki
Security
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Wiki
Security
Insights
Files
5bf0f3b
Documentation
LICENSES
arch
block
certs
crypto
drivers
fs
include
init
ipc
kernel
lib
mm
net
samples
scripts
atomic
basic
clang-tools
coccinelle
dtc
dummy-tools
gcc-plugins
gdb
genksyms
kconfig
ksymoops
mod
package
selinux
tracing
.gitignore
Kbuild.include
Kconfig.include
Lindent
Makefile
Makefile.asm-generic
Makefile.build
Makefile.clean
Makefile.compiler
Makefile.dtbinst
Makefile.extrawarn
Makefile.gcc-plugins
Makefile.headersinst
Makefile.host
Makefile.kasan
Makefile.kcov
Makefile.kcsan
Makefile.lib
Makefile.modfinal
Makefile.modinst
Makefile.modpost
Makefile.package
Makefile.ubsan
Makefile.userprogs
adjust_autoksyms.sh
as-version.sh
asn1_compiler.c
bin2c.c
bloat-o-meter
bootgraph.pl
bpf_doc.py
cc-can-link.sh
cc-version.sh
check-sysctl-docs
check_extable.sh
checkdeclares.pl
checkincludes.pl
checkkconfigsymbols.py
checkpatch.pl
checkstack.pl
checksyscalls.sh
checkversion.pl
cleanfile
cleanpatch
coccicheck
config
const_structs.checkpatch
decode_stacktrace.sh
decodecode
depmod.sh
dev-needs.sh
diffconfig
documentation-file-ref-check
export_report.pl
extract-cert.c
extract-ikconfig
extract-module-sig.pl
extract-sys-certs.pl
extract-vmlinux
extract_xc3028.pl
faddr2line
file-size.sh
find-unused-docs.sh
gcc-goto.sh
gcc-ld
gcc-x86_32-has-stack-protector.sh
gcc-x86_64-has-stack-protector.sh
gen_autoksyms.sh
gen_ksymdeps.sh
generate_initcall_order.pl
get_abi.pl
get_dvb_firmware
get_feat.pl
get_maintainer.pl
gfp-translate
headerdep.pl
headers_check.pl
headers_install.sh
insert-sys-cert.c
jobserver-exec
kallsyms.c
kernel-doc
ld-version.sh
leaking_addresses.pl
link-vmlinux.sh
makelst
markup_oops.pl
min-tool-version.sh
mkcompile_h
mkmakefile
mksysmap
mkuboot.sh
module.lds.S
modules-check.sh
nsdeps
objdiff
parse-maintainers.pl
patch-kernel
profile2linkerlist.pl
prune-kernel
recordmcount.c
recordmcount.h
recordmcount.pl
remove-stale-files
setlocalversion
show_delta
sign-file.c
sorttable.c
sorttable.h
spdxcheck-test.sh
spdxcheck.py
spelling.txt
sphinx-pre-install
split-man.pl
stackdelta
stackusage
subarch.include
syscallhdr.sh
syscalltbl.sh
tags.sh
tools-support-relr.sh
unifdef.c
ver_linux
xen-hypercalls.sh
xz_wrap.sh
security
sound
tools
usr
virt
.clang-format
.cocciconfig
.get_maintainer.ignore
.gitattributes
.gitignore
.mailmap
COPYING
CREDITS
Kbuild
Kconfig
MAINTAINERS
Makefile
README
Breadcrumbs
linux
/
scripts
/
decode_stacktrace.sh
Blame
Blame
Latest commit
History
History
executable file
·
284 lines (240 loc) · 6.54 KB
Breadcrumbs
linux
/
scripts
/
decode_stacktrace.sh
Top
File metadata and controls
Code
Blame
executable file
·
284 lines (240 loc) · 6.54 KB
Raw
#!/bin/bash # SPDX-License-Identifier: GPL-2.0 # (c) 2014, Sasha Levin <sasha.levin@oracle.com> #set -x usage() { echo "Usage:" echo " $0 -r <release> | <vmlinux> [base path] [modules path]" } if [[ $1 == "-r" ]] ; then vmlinux="" basepath="auto" modpath="" release=$2 for fn in {,/usr/lib/debug}/boot/vmlinux-$release{,.debug} /lib/modules/$release{,/build}/vmlinux ; do if [ -e "$fn" ] ; then vmlinux=$fn break fi done if [[ $vmlinux == "" ]] ; then echo "ERROR! vmlinux image for release $release is not found" >&2 usage exit 2 fi else vmlinux=$1 basepath=${2-auto} modpath=$3 release="" debuginfod= # Can we use debuginfod-find? if type debuginfod-find >/dev/null 2>&1 ; then debuginfod=${1-only} fi if [[ $vmlinux == "" && -z $debuginfod ]] ; then echo "ERROR! vmlinux image must be specified" >&2 usage exit 1 fi fi declare -A cache declare -A modcache find_module() { if [[ -n $debuginfod ]] ; then if [[ -n $modbuildid ]] ; then debuginfod-find debuginfo $modbuildid && return fi # Only using debuginfod so don't try to find vmlinux module path if [[ $debuginfod == "only" ]] ; then return fi fi if [[ "$modpath" != "" ]] ; then for fn in $(find "$modpath" -name "${module//_/[-_]}.ko*") ; do if readelf -WS "$fn" | grep -qwF .debug_line ; then echo $fn return fi done return 1 fi modpath=$(dirname "$vmlinux") find_module && return if [[ $release == "" ]] ; then release=$(gdb -ex 'print init_uts_ns.name.release' -ex 'quit' -quiet -batch "$vmlinux" 2>/dev/null | sed -n 's/\$1 = "\(.*\)".*/\1/p') fi for dn in {/usr/lib/debug,}/lib/modules/$release ; do if [ -e "$dn" ] ; then modpath="$dn" find_module && return fi done modpath="" return 1 } parse_symbol() { # The structure of symbol at this point is: # ([name]+[offset]/[total length]) # # For example: # do_basic_setup+0x9c/0xbf if [[ $module == "" ]] ; then local objfile=$vmlinux elif [[ "${modcache[$module]+isset}" == "isset" ]]; then local objfile=${modcache[$module]} else local objfile=$(find_module) if [[ $objfile == "" ]] ; then echo "WARNING! Modules path isn't set, but is needed to parse this symbol" >&2 return fi modcache[$module]=$objfile fi # Remove the englobing parenthesis symbol=${symbol#\(} symbol=${symbol%\)} # Strip segment local segment if [[ $symbol == *:* ]] ; then segment=${symbol%%:*}: symbol=${symbol#*:} fi # Strip the symbol name so that we could look it up local name=${symbol%+*} # Use 'nm vmlinux' to figure out the base address of said symbol. # It's actually faster to call it every time than to load it # all into bash. if [[ "${cache[$module,$name]+isset}" == "isset" ]]; then local base_addr=${cache[$module,$name]} else local base_addr=$(nm "$objfile" 2>/dev/null | awk '$3 == "'$name'" && ($2 == "t" || $2 == "T") {print $1; exit}') if [[ $base_addr == "" ]] ; then # address not found return fi cache[$module,$name]="$base_addr" fi # Let's start doing the math to get the exact address into the # symbol. First, strip out the symbol total length. local expr=${symbol%/*} # Now, replace the symbol name with the base address we found # before. expr=${expr/$name/0x$base_addr} # Evaluate it to find the actual address expr=$((expr)) local address=$(printf "%x\n" "$expr") # Pass it to addr2line to get filename and line number # Could get more than one result if [[ "${cache[$module,$address]+isset}" == "isset" ]]; then local code=${cache[$module,$address]} else local code=$(${CROSS_COMPILE}addr2line -i -e "$objfile" "$address" 2>/dev/null) cache[$module,$address]=$code fi # addr2line doesn't return a proper error code if it fails, so # we detect it using the value it prints so that we could preserve # the offset/size into the function and bail out if [[ $code == "??:0" ]]; then return fi # Strip out the base of the path on each line code=$(while read -r line; do echo "${line#$basepath/}"; done <<< "$code") # In the case of inlines, move everything to same line code=${code//$'\n'/' '} # Replace old address with pretty line numbers symbol="$segment$name ($code)" } debuginfod_get_vmlinux() { local vmlinux_buildid=${1##* } if [[ $vmlinux != "" ]]; then return fi if [[ $vmlinux_buildid =~ ^[0-9a-f]+ ]]; then vmlinux=$(debuginfod-find debuginfo $vmlinux_buildid) if [[ $? -ne 0 ]] ; then echo "ERROR! vmlinux image not found via debuginfod-find" >&2 usage exit 2 fi return fi echo "ERROR! Build ID for vmlinux not found. Try passing -r or specifying vmlinux" >&2 usage exit 2 } decode_code() { local scripts=`dirname "${BASH_SOURCE[0]}"` echo "$1" | $scripts/decodecode } handle_line() { if [[ $basepath == "auto" && $vmlinux != "" ]] ; then module="" symbol="kernel_init+0x0/0x0" parse_symbol basepath=${symbol#kernel_init (} basepath=${basepath%/init/main.c:*)} fi local words # Tokenize read -a words <<<"$1" # Remove hex numbers. Do it ourselves until it happens in the # kernel # We need to know the index of the last element before we # remove elements because arrays are sparse local last=$(( ${#words[@]} - 1 )) for i in "${!words[@]}"; do # Remove the address if [[ ${words[$i]} =~ \[\<([^]]+)\>\] ]]; then unset words[$i] fi # Format timestamps with tabs if [[ ${words[$i]} == \[ && ${words[$i+1]} == *\] ]]; then unset words[$i] words[$i+1]=$(printf "[%13s\n" "${words[$i+1]}") fi done if [[ ${words[$last]} =~ ^[0-9a-f]+\] ]]; then words[$last-1]="${words[$last-1]} ${words[$last]}" unset words[$last] last=$(( $last - 1 )) fi if [[ ${words[$last]} =~ \[([^]]+)\] ]]; then module=${words[$last]} module=${module#\[} module=${module%\]} modbuildid=${module#* } module=${module% *} if [[ $modbuildid == $module ]]; then modbuildid= fi symbol=${words[$last-1]} unset words[$last-1] else # The symbol is the last element, process it symbol=${words[$last]} module= modbuildid= fi unset words[$last] parse_symbol # modifies $symbol # Add up the line number to the symbol echo "${words[@]}" "$symbol $module" } while read line; do # Let's see if we have an address in the line if [[ $line =~ \[\<([^]]+)\>\] ]] || [[ $line =~ [^+\ ]+\+0x[0-9a-f]+/0x[0-9a-f]+ ]]; then # Translate address to line numbers handle_line "$line" # Is it a code line? elif [[ $line == *Code:* ]]; then decode_code "$line" # Is it a version line? elif [[ -n $debuginfod && $line =~ PID:\ [0-9]+\ Comm: ]]; then debuginfod_get_vmlinux "$line" else # Nothing special in this line, show it as is echo "$line" fi done
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
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
You can’t perform that action at this time.