scripts/decode_stacktrace.sh: optionally use LLVM utilities

GNU's addr2line can have problems parsing a vmlinux built with LLVM,
particularly when LTO was used. In order to decode the traces correctly
this patch adds the ability to switch to LLVM's utilities readelf and
addr2line. The same approach is followed by Will in [1].

Before:
  $ scripts/decode_stacktrace.sh vmlinux < kernel.log
  [17716.240635] Call trace:
  [17716.240646] skb_cow_data (??:?)
  [17716.240654] esp6_input (ld-temp.o:?)
  [17716.240666] xfrm_input (ld-temp.o:?)
  [17716.240674] xfrm6_rcv (??:?)
  [...]

After:
  $ LLVM=1 scripts/decode_stacktrace.sh vmlinux < kernel.log
  [17716.240635] Call trace:
  [17716.240646] skb_cow_data (include/linux/skbuff.h:2172 net/core/skbuff.c:4503)
  [17716.240654] esp6_input (net/ipv6/esp6.c:977)
  [17716.240666] xfrm_input (net/xfrm/xfrm_input.c:659)
  [17716.240674] xfrm6_rcv (net/ipv6/xfrm6_input.c:172)
  [...]

Note that one could set CROSS_COMPILE=llvm- instead to hack around this
issue. However, doing so can break the decodecode routine as it will
force the selection of other LLVM utilities down the line e.g. llvm-as.

[1] https://lore.kernel.org/all/20230914131225.13415-3-will@kernel.org/

Cc: Will Deacon <will@kernel.org>
Cc: John Stultz <jstultz@google.com>
Cc: Masahiro Yamada <masahiroy@kernel.org>
Signed-off-by: Carlos Llamas <cmllamas@google.com>
This commit is contained in:
Carlos Llamas 2023-09-29 03:48:17 +00:00 committed by Michael Bestas
parent 00776106b7
commit 8dd8c6ddec
No known key found for this signature in database
GPG Key ID: CC95044519BE6669

View File

@ -9,6 +9,21 @@ if [[ $# < 1 ]]; then
exit 1
fi
UTIL_SUFFIX=
if [[ -z ${LLVM:-} ]]; then
UTIL_PREFIX=${CROSS_COMPILE:-}
else
UTIL_PREFIX=llvm-
if [[ ${LLVM} == */ ]]; then
UTIL_PREFIX=${LLVM}${UTIL_PREFIX}
elif [[ ${LLVM} == -* ]]; then
UTIL_SUFFIX=${LLVM}
fi
fi
READELF=${UTIL_PREFIX}readelf${UTIL_SUFFIX}
ADDR2LINE=${UTIL_PREFIX}addr2line${UTIL_SUFFIX}
if [[ $1 == "-r" ]] ; then
vmlinux=""
basepath="auto"
@ -39,7 +54,7 @@ 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
if ${READELF} -WS "$fn" | grep -qwF .debug_line ; then
echo $fn
return
fi
@ -129,7 +144,7 @@ parse_symbol() {
if [[ "${cache[$module,$address]+isset}" == "isset" ]]; then
local code=${cache[$module,$address]}
else
local code=$(${CROSS_COMPILE}addr2line -i -e "$objfile" "$address")
local code=$(${ADDR2LINE} -i -e "$objfile" "$address")
cache[$module,$address]=$code
fi