The stack unwinding is for kernel addresses only. If non-kernel address
encountered, it is usually a user space address, or non-address value
like a function call parameter. So stopping stack unwinding at non-kernel
address will decrease the invalid unwind results.
Before:
crash> gdb bt
#0 0xffffffff816a8f65 in context_switch ...
#1 __schedule () ...
#2 0xffffffff816a94e9 in schedule ...
#3 0xffffffff816a86fd in schedule_hrtimeout_range_clock ...
#4 0xffffffff816a8733 in schedule_hrtimeout_range ...
#5 0xffffffff8124bb7e in ep_poll ...
#6 0xffffffff8124d00d in SYSC_epoll_wait ...
#7 SyS_epoll_wait ...
#8 <signal handler called>
#9 0x00007f0449407923 in ?? ()
#10 0xffff880100000001 in ?? ()
#11 0xffff880169b3c010 in ?? ()
#12 0x0000000000000040 in irq_stack_union ()
#13 0xffff880169b3c058 in ?? ()
#14 0xffff880169b3c048 in ?? ()
#15 0xffff880169b3c050 in ?? ()
#16 0x0000000000000000 in ?? ()
After:
crash> gdb bt
#0 0xffffffff816a8f65 in context_switch ...
#1 __schedule () ...
#2 0xffffffff816a94e9 in schedule () ...
#3 0xffffffff816a86fd in schedule_hrtimeout_range_clock ...
#4 0xffffffff816a8733 in schedule_hrtimeout_range ...
#5 0xffffffff8124bb7e in ep_poll ...
#6 0xffffffff8124d00d in SYSC_epoll_wait ...
#7 SyS_epoll_wait ...
#8 <signal handler called>
#9 0x00007f0449407923 in ?? ()
Signed-off-by: Tao Liu <ltao(a)redhat.com>
---
defs.h | 1 +
gdb-10.2.patch | 26 ++++++++++++++++++++++++++
gdb_interface.c | 6 ++++++
3 files changed, 33 insertions(+)
diff --git a/defs.h b/defs.h
index 6c47154..a6cf200 100644
--- a/defs.h
+++ b/defs.h
@@ -7901,6 +7901,7 @@ extern unsigned char *gdb_prettyprint_arrays;
extern unsigned int *gdb_repeat_count_threshold;
extern unsigned char *gdb_stop_print_at_null;
extern unsigned int *gdb_output_radix;
+int is_kvaddr(ulong);
/*
* gdb/top.c
diff --git a/gdb-10.2.patch b/gdb-10.2.patch
index e9248b5..af3859e 100644
--- a/gdb-10.2.patch
+++ b/gdb-10.2.patch
@@ -16110,3 +16110,29 @@ exit 0
}
/*
+--- gdb-10.2/gdb/frame.c.orig
++++ gdb-10.2/gdb/frame.c
+@@ -2331,6 +2331,10 @@ inside_entry_func (frame_info *this_frame)
+ This function should not contain target-dependent tests, such as
+ checking whether the program-counter is zero. */
+
++#ifdef CRASH_MERGE
++extern "C" int is_kvaddr(ulong);
++#endif
++
+ struct frame_info *
+ get_prev_frame (struct frame_info *this_frame)
+ {
+@@ -2353,7 +2357,11 @@ get_prev_frame (struct frame_info *this_frame)
+ get_frame_id (this_frame);
+
+ frame_pc_p = get_frame_pc_if_available (this_frame, &frame_pc);
+-
++#ifdef CRASH_MERGE
++ if (!is_kvaddr(frame_pc)) {
++ return NULL;
++ }
++#endif
+ /* tausq/2004-12-07: Dummy frames are skipped because it doesn't make much
+ sense to stop unwinding at a dummy frame. One place where a dummy
+ frame may have an address "inside_main_func" is on HPUX. On HPUX, the
diff --git a/gdb_interface.c b/gdb_interface.c
index b13d5fd..e76ecc6 100644
--- a/gdb_interface.c
+++ b/gdb_interface.c
@@ -947,6 +947,12 @@ gdb_lookup_module_symbol(ulong addr, ulong *offset)
}
}
+int
+is_kvaddr(ulong addr)
+{
+ return IS_KVADDR(addr);
+}
+
/*
* Used by gdb_interface() to catch gdb-related errors, if desired.
*/
--
2.40.1