diff options
| author | Stephen Boyd <swboyd@chromium.org> | 2021-07-07 18:09:31 -0700 | 
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2021-07-08 11:48:22 -0700 | 
| commit | 26681eb3724b617c4894cfb53cad2e3740323bc2 (patch) | |
| tree | 1fcd30b39b3526e1b0a7f68e9cc8639a64bbc769 | |
| parent | 9ef8af2a8f25b16eec6d2865ca7d9116a24ad46a (diff) | |
| download | linux-26681eb3724b617c4894cfb53cad2e3740323bc2.tar.bz2 | |
scripts/decode_stacktrace.sh: support debuginfod
Now that stacktraces contain the build ID information we can update this
script to use debuginfod-find to locate the debuginfo for the vmlinux and
modules automatically.  This can replace the existing code that requires
specifying a path to vmlinux or tries to find the vmlinux and modules
automatically by using the release number.  Work it into the script as a
fallback option if the vmlinux isn't specified on the commandline.
Link: https://lkml.kernel.org/r/20210511003845.2429846-9-swboyd@chromium.org
Signed-off-by: Stephen Boyd <swboyd@chromium.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Jessica Yu <jeyu@kernel.org>
Cc: Evan Green <evgreen@chromium.org>
Cc: Hsin-Yi Wang <hsinyi@chromium.org>
Cc: Konstantin Khlebnikov <khlebnikov@yandex-team.ru>
Cc: Sasha Levin <sashal@kernel.org>
Cc: Petr Mladek <pmladek@suse.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Baoquan He <bhe@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Dave Young <dyoung@redhat.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Rasmus Villemoes <linux@rasmusvillemoes.dk>
Cc: Sergey Senozhatsky <sergey.senozhatsky@gmail.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Vivek Goyal <vgoyal@redhat.com>
Cc: Will Deacon <will@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
| -rwxr-xr-x | scripts/decode_stacktrace.sh | 81 | 
1 files changed, 70 insertions, 11 deletions
diff --git a/scripts/decode_stacktrace.sh b/scripts/decode_stacktrace.sh index 90398347e366..ca21f8bdf5f2 100755 --- a/scripts/decode_stacktrace.sh +++ b/scripts/decode_stacktrace.sh @@ -3,11 +3,10 @@  # (c) 2014, Sasha Levin <sasha.levin@oracle.com>  #set -x -if [[ $# < 1 ]]; then +usage() {  	echo "Usage:"  	echo "	$0 -r <release> | <vmlinux> [base path] [modules path]" -	exit 1 -fi +}  if [[ $1 == "-r" ]] ; then  	vmlinux="" @@ -24,6 +23,7 @@ if [[ $1 == "-r" ]] ; then  	if [[ $vmlinux == "" ]] ; then  		echo "ERROR! vmlinux image for release $release is not found" >&2 +		usage  		exit 2  	fi  else @@ -31,12 +31,35 @@ else  	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 @@ -150,6 +173,27 @@ parse_symbol() {  	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]}"` @@ -157,6 +201,14 @@ decode_code() {  }  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 @@ -182,16 +234,28 @@ handle_line() {  		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] @@ -201,14 +265,6 @@ handle_line() {  	echo "${words[@]}" "$symbol $module"  } -if [[ $basepath == "auto" ]] ; then -	module="" -	symbol="kernel_init+0x0/0x0" -	parse_symbol -	basepath=${symbol#kernel_init (} -	basepath=${basepath%/init/main.c:*)} -fi -  while read line; do  	# Let's see if we have an address in the line  	if [[ $line =~ \[\<([^]]+)\>\] ]] || @@ -218,6 +274,9 @@ while read line; do  	# 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"  |