diff options
author | Maxime Ripard <maxime@cerno.tech> | 2020-08-18 15:14:25 +0300 |
---|---|---|
committer | Maxime Ripard <maxime@cerno.tech> | 2020-08-18 15:14:25 +0300 |
commit | d85ddd1318e66c0c2665dbfcbc21a8b66c9152aa (patch) | |
tree | e49e401abd2468b398d4bc84c7e05c2c2c3b0966 /scripts/decode_stacktrace.sh | |
parent | 652bcaec7da0f06f00be578c200e1c57099449d2 (diff) | |
parent | 9123e3a74ec7b934a4a099e98af6a61c2f80bbf5 (diff) | |
download | linux-d85ddd1318e66c0c2665dbfcbc21a8b66c9152aa.tar.xz |
Merge v5.9-rc1 into drm-misc-next
Sam needs 5.9-rc1 to have dev_err_probe in to merge some patches.
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Diffstat (limited to 'scripts/decode_stacktrace.sh')
-rwxr-xr-x | scripts/decode_stacktrace.sh | 79 |
1 files changed, 70 insertions, 9 deletions
diff --git a/scripts/decode_stacktrace.sh b/scripts/decode_stacktrace.sh index 0869def435ee..90398347e366 100755 --- a/scripts/decode_stacktrace.sh +++ b/scripts/decode_stacktrace.sh @@ -3,18 +3,68 @@ # (c) 2014, Sasha Levin <sasha.levin@oracle.com> #set -x -if [[ $# < 2 ]]; then +if [[ $# < 1 ]]; then echo "Usage:" - echo " $0 [vmlinux] [base path] [modules path]" + echo " $0 -r <release> | <vmlinux> [base path] [modules path]" exit 1 fi -vmlinux=$1 -basepath=$2 -modpath=$3 +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 + exit 2 + fi +else + vmlinux=$1 + basepath=${2-auto} + modpath=$3 + release="" +fi + declare -A cache declare -A modcache +find_module() { + 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" | 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]) @@ -27,12 +77,11 @@ parse_symbol() { elif [[ "${modcache[$module]+isset}" == "isset" ]]; then local objfile=${modcache[$module]} else - if [[ $modpath == "" ]]; then + local objfile=$(find_module) + if [[ $objfile == "" ]] ; then echo "WARNING! Modules path isn't set, but is needed to parse this symbol" >&2 return fi - local objfile=$(find "$modpath" -name "${module//_/[-_]}.ko*" -print -quit) - [[ $objfile == "" ]] && return modcache[$module]=$objfile fi @@ -56,7 +105,11 @@ parse_symbol() { if [[ "${cache[$module,$name]+isset}" == "isset" ]]; then local base_addr=${cache[$module,$name]} else - local base_addr=$(nm "$objfile" | grep -i ' t ' | awk "/ $name\$/ {print \$1}" | head -n1) + local base_addr=$(nm "$objfile" | 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 @@ -148,6 +201,14 @@ 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 =~ \[\<([^]]+)\>\] ]] || |