public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] decode_stacktrace: Support heuristic caller address search
@ 2026-03-05  5:12 Masami Hiramatsu (Google)
  2026-03-05 14:56 ` Matthieu Baerts
  2026-03-05 15:51 ` Sasha Levin
  0 siblings, 2 replies; 6+ messages in thread
From: Masami Hiramatsu (Google) @ 2026-03-05  5:12 UTC (permalink / raw)
  To: Matthieu Baerts, Andrew Morton, Sasha Levin
  Cc: Carlos Llamas, Luca Ceresoli, Masami Hiramatsu, linux-kernel

From: Masami Hiramatsu (Google) <mhiramat@kernel.org>

Add -c option to search call address search to decode_stacktrace.
This tries to decode line info backwards, starting from 1byte before
the return address, and displays the first line info it founds as
the caller address.
If it tries up to 10bytes before (or the symbol address) and still
can not find it, it gives up and decodes the return address.

With -c option:
 Call Trace:
  <TASK>
  dump_stack_lvl (lib/dump_stack.c:94 lib/dump_stack.c:120)
  lockdep_rcu_suspicious (kernel/locking/lockdep.c:6876)
  event_filter_pid_sched_process_fork (kernel/trace/trace_events.c:1057)
  kernel_clone (include/trace/events/sched.h:396 include/trace/events/sched.h:396 kernel/fork.c:2664)
  __x64_sys_clone (kernel/fork.c:2795 kernel/fork.c:2779 kernel/fork.c:2779)
  do_syscall_64 (arch/x86/entry/syscall_64.c:63 arch/x86/entry/syscall_64.c:94)
  ? entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)
  ? trace_irq_disable (include/trace/events/preemptirq.h:36)
  entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:121)


Without -c option:
 Call Trace:
  <TASK>
  dump_stack_lvl (lib/dump_stack.c:122)
  lockdep_rcu_suspicious (kernel/locking/lockdep.c:6877)
  event_filter_pid_sched_process_fork (kernel/trace/trace_events.c:?)
  kernel_clone (include/trace/events/sched.h:? include/trace/events/sched.h:396 kernel/fork.c:2664)
  __x64_sys_clone (kernel/fork.c:2779)
  do_syscall_64 (arch/x86/entry/syscall_64.c:?)
  ? entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:130)
  ? trace_irq_disable (include/trace/events/preemptirq.h:36)
  entry_SYSCALL_64_after_hwframe (arch/x86/entry/entry_64.S:130)

Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
 scripts/decode_stacktrace.sh |   51 ++++++++++++++++++++++++++++++++++++++----
 1 file changed, 46 insertions(+), 5 deletions(-)

diff --git a/scripts/decode_stacktrace.sh b/scripts/decode_stacktrace.sh
index 8d01b741de62..78e0810af476 100755
--- a/scripts/decode_stacktrace.sh
+++ b/scripts/decode_stacktrace.sh
@@ -5,9 +5,11 @@
 
 usage() {
 	echo "Usage:"
-	echo "	$0 -r <release>"
-	echo "	$0 [<vmlinux> [<base_path>|auto [<modules_path>]]]"
+	echo "	$0 [-c] -r <release>"
+	echo "	$0 [-c] [<vmlinux> [<base_path>|auto [<modules_path>]]]"
 	echo "	$0 -h"
+	echo "Options:"
+	echo "   -c: Decode heuristically searched call address."
 }
 
 # Try to find a Rust demangler
@@ -33,11 +35,17 @@ fi
 READELF=${UTIL_PREFIX}readelf${UTIL_SUFFIX}
 ADDR2LINE=${UTIL_PREFIX}addr2line${UTIL_SUFFIX}
 NM=${UTIL_PREFIX}nm${UTIL_SUFFIX}
+call_search=false
 
 if [[ $1 == "-h" ]] ; then
 	usage
 	exit 0
-elif [[ $1 == "-r" ]] ; then
+elif [[ $1 == "-c" ]] ; then
+	call_search=true
+	shift 1
+fi
+
+if [[ $1 == "-r" ]] ; then
 	vmlinux=""
 	basepath="auto"
 	modpath=""
@@ -123,6 +131,28 @@ find_module() {
 	return 1
 }
 
+UNKNOWN_LINE="??:0"
+
+search_call_site() {
+	# Instead of using the return address, use the nearest line info
+	# address before given address.
+	local return_addr=${2}
+	local max=${3}
+	local i
+
+	for i in $(seq 1 ${max}); do
+		local expr=$((0x$return_addr-$i))
+		local address=$(printf "%x\n" "$expr")
+
+		local code=$(${ADDR2LINE} -i -e "${1}" "$address" 2>/dev/null)
+		local first=${code% *}
+		if [[ "$code" != "" && "$code" != ${UNKNOWN_LINE} && "${first#*:}" != "?" ]]; then
+			echo "$code"
+			break
+		fi
+	done
+}
+
 parse_symbol() {
 	# The structure of symbol at this point is:
 	#   ([name]+[offset]/[total length])
@@ -176,6 +206,9 @@ parse_symbol() {
 	# Let's start doing the math to get the exact address into the
 	# symbol. First, strip out the symbol total length.
 	local expr=${symbol%/*}
+	# Also parse the offset from symbol.
+	local offset=${expr#*+}
+	offset=$((offset))
 
 	# Now, replace the symbol name with the base address we found
 	# before.
@@ -190,7 +223,15 @@ parse_symbol() {
 	if [[ $aarray_support == true && "${cache[$module,$address]+isset}" == "isset" ]]; then
 		local code=${cache[$module,$address]}
 	else
-		local code=$(${ADDR2LINE} -i -e "$objfile" "$address" 2>/dev/null)
+		local code
+		if [[ $call_search == true && $offset != 0 ]]; then
+			code=$(search_call_site "$objfile" "$address" "$offset")
+		fi
+
+		if [[ "$code" == "" ]]; then
+			code=$(${ADDR2LINE} -i -e "$objfile" "$address" 2>/dev/null)
+		fi
+
 		if [[ $aarray_support == true ]]; then
 			cache[$module,$address]=$code
 		fi
@@ -199,7 +240,7 @@ parse_symbol() {
 	# addr2line doesn't return a proper error code if it fails, so
 	# we detect it using the value it prints so that we could preserve
 	# the offset/size into the function and bail out
-	if [[ $code == "??:0" ]]; then
+	if [[ $code == ${UNKNOWN_LINE} ]]; then
 		return
 	fi
 


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2026-03-05 20:38 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-05  5:12 [PATCH] decode_stacktrace: Support heuristic caller address search Masami Hiramatsu (Google)
2026-03-05 14:56 ` Matthieu Baerts
2026-03-05 16:11   ` Masami Hiramatsu
2026-03-05 15:51 ` Sasha Levin
2026-03-05 16:32   ` Masami Hiramatsu
2026-03-05 20:38     ` Sasha Levin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox