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/

Link: https://lkml.kernel.org/r/20230929034836.403735-1-cmllamas@google.com
Signed-off-by: Carlos Llamas <cmllamas@google.com>
Reviewed-by: Nick Desaulniers <ndesaulniers@google.com>
Reviewed-by: Elliot Berman <quic_eberman@quicinc.com>
Tested-by: Justin Stitt <justinstitt@google.com>
Cc: Will Deacon <will@kernel.org>
Cc: John Stultz <jstultz@google.com>
Cc: Masahiro Yamada <masahiroy@kernel.org>
Cc: Nathan Chancellor <nathan@kernel.org>
Cc: Tom Rix <trix@redhat.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
Carlos Llamas 2023-09-29 03:48:17 +00:00 committed by Andrew Morton
parent cc478e0b6b
commit efbd639835
1 changed files with 17 additions and 2 deletions

View File

@ -16,6 +16,21 @@ elif type c++filt >/dev/null 2>&1 ; then
cppfilt_opts=-i cppfilt_opts=-i
fi 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 if [[ $1 == "-r" ]] ; then
vmlinux="" vmlinux=""
basepath="auto" basepath="auto"
@ -75,7 +90,7 @@ find_module() {
if [[ "$modpath" != "" ]] ; then if [[ "$modpath" != "" ]] ; then
for fn in $(find "$modpath" -name "${module//_/[-_]}.ko*") ; do 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 echo $fn
return return
fi fi
@ -169,7 +184,7 @@ parse_symbol() {
if [[ $aarray_support == true && "${cache[$module,$address]+isset}" == "isset" ]]; then if [[ $aarray_support == true && "${cache[$module,$address]+isset}" == "isset" ]]; then
local code=${cache[$module,$address]} local code=${cache[$module,$address]}
else else
local code=$(${CROSS_COMPILE}addr2line -i -e "$objfile" "$address" 2>/dev/null) local code=$(${ADDR2LINE} -i -e "$objfile" "$address" 2>/dev/null)
if [[ $aarray_support == true ]]; then if [[ $aarray_support == true ]]; then
cache[$module,$address]=$code cache[$module,$address]=$code
fi fi