From 8f54c55ea44f1906c23b5f01aea92b548b1e8839 Mon Sep 17 00:00:00 2001 From: Gregory LEOCADIE Date: Thu, 8 Dec 2022 11:54:29 +0100 Subject: Fix bug + add test --- src/mi/backtrace.c | 20 ++++++++++++--- tests/Gtest-trace.c | 59 +++++++++++++++++++++++++++++++++++++++++++++ tests/check-namespace.sh.in | 1 + 3 files changed, 77 insertions(+), 3 deletions(-) diff --git a/src/mi/backtrace.c b/src/mi/backtrace.c index 00e4de8d..8fea3444 100644 --- a/src/mi/backtrace.c +++ b/src/mi/backtrace.c @@ -92,14 +92,28 @@ unw_backtrace2 (void **buffer, int size, unw_context_t* uc2) if (unlikely (unw_init_local2 (&cursor, &uc, UNW_INIT_SIGNAL_FRAME) < 0)) return 0; - int n = size; + // get the first ip from the context + unw_word_t ip; + + if (unw_get_reg (&cursor, UNW_REG_IP, &ip) < 0) + return 0; + buffer[0] = (void *) (uintptr_t)ip; + + // update buffer info to collect the rest of the IPs + buffer = buffer+1; + int remaining_size = size-1; + + int n = remaining_size; + + // returns the number of frames collected by tdep_trace or slow_backtrace + // and add 1 to it (the one we retrieved above) if (unlikely (tdep_trace (&cursor, buffer, &n) < 0)) { - return slow_backtrace (buffer, size, &uc, UNW_INIT_SIGNAL_FRAME); + return slow_backtrace (buffer, remaining_size, &uc, UNW_INIT_SIGNAL_FRAME) + 1; } - return n; + return n + 1; } #ifdef CONFIG_WEAK_BACKTRACE diff --git a/tests/Gtest-trace.c b/tests/Gtest-trace.c index fa207fca..e0a5d64d 100644 --- a/tests/Gtest-trace.c +++ b/tests/Gtest-trace.c @@ -139,6 +139,64 @@ do_backtrace (void) } } +void +do_backtrace_with_context(void *context) +{ + unw_word_t ip; + int ret = -UNW_ENOINFO; + int depth = 0; + int i, m; + + if (verbose) + printf ("\tnormal trace:\n"); + + if (unw_init_local2 (&cursor, (unw_context_t*)context, UNW_INIT_SIGNAL_FRAME) < 0) + panic ("unw_init_local2 failed!\n"); + + do + { + unw_get_reg (&cursor, UNW_REG_IP, &ip); + addresses[0][depth] = (void *) ip; + } + while ((ret = unw_step (&cursor)) > 0 && ++depth < 128); + + if (ret < 0) + { + unw_get_reg (&cursor, UNW_REG_IP, &ip); + printf ("FAILURE: unw_step() returned %d for ip=%lx\n", ret, (long) ip); + ++num_errors; + } + + if (verbose) + for (i = 0; i < depth; ++i) + printf ("\t #%-3d ip=%p\n", i, addresses[0][i]); + + if (verbose) + printf ("\n\tvia unw_backtrace2():\n"); + + m = unw_backtrace2 (addresses[1], 128, (unw_context_t*)context); + + if (verbose) + for (i = 0; i < m; ++i) + printf ("\t #%-3d ip=%p\n", i, addresses[1][i]); + + if (m != depth+1) + { + printf ("FAILURE: unw_step() loop and unw_backtrace2() depths differ: %d vs. %d\n", depth, m); + ++num_errors; + } + + if (m == depth + 1) + for (i = 0; i < depth; ++i) + /* Allow one in difference in comparison, trace returns adjusted addresses. */ + if (labs((unw_word_t) addresses[0][i] - (unw_word_t) addresses[1][i]) > 1) + { + printf ("FAILURE: unw_step() loop and uwn_backtrace2() addresses differ at %d: %p vs. %p\n", + i, addresses[0][i], addresses[1][i]); + ++num_errors; + } +} + void foo (long val UNUSED) { @@ -222,6 +280,7 @@ sighandler (int signal, void *siginfo UNUSED, void *context) printf ("\n"); } do_backtrace(); + do_backtrace_with_context(context); } int diff --git a/tests/check-namespace.sh.in b/tests/check-namespace.sh.in index 656e3818..a1b28a7b 100644 --- a/tests/check-namespace.sh.in +++ b/tests/check-namespace.sh.in @@ -137,6 +137,7 @@ check_local_unw_abi () { match unw_backtrace @CONFIG_WEAK_BACKTRACE_TRUE@match backtrace + match unw_backtrace2 case ${plat} in arm) -- cgit v1.2.1