]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
scripts/decode_stacktrace.sh: guess path to modules
authorKonstantin Khlebnikov <khlebnikov@yandex-team.ru>
Fri, 7 Aug 2020 06:17:41 +0000 (23:17 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Fri, 7 Aug 2020 18:33:21 +0000 (11:33 -0700)
Try to find module in directory with vmlinux (for fresh build).  Then try
standard paths where debuginfo are usually placed.  Pick first file which
have elf section '.debug_line'.

Before:

$ echo 'tap_open+0x0/0x0 [tap]' |
  ./scripts/decode_stacktrace.sh /usr/lib/debug/boot/vmlinux-5.4.0-37-generic
WARNING! Modules path isn't set, but is needed to parse this symbol
tap_open+0x0/0x0 tap

After:

$ echo 'tap_open+0x0/0x0 [tap]' |
  ./scripts/decode_stacktrace.sh /usr/lib/debug/boot/vmlinux-5.4.0-37-generic
tap_open (drivers/net/tap.c:502) tap

Signed-off-by: Konstantin Khlebnikov <khlebnikov@yandex-team.ru>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Cc: Sasha Levin <sashal@kernel.org>
Link: http://lkml.kernel.org/r/159282923068.248444.5461337458421616083.stgit@buzz
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
scripts/decode_stacktrace.sh

index 62a70ede7f3e8eba313c3ae7239ed267d2750542..e31e253fe5bd6ba3f9f9e0ad4d452f0845f4a9a1 100755 (executable)
@@ -12,9 +12,40 @@ fi
 vmlinux=$1
 basepath=${2-auto}
 modpath=$3
+release=""
+
 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 +58,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