[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Libunwind-devel] [RFC] _ULx86_64_tdep_trace returns off-by-one addresse

From: Paul Pluzhnikov
Subject: [Libunwind-devel] [RFC] _ULx86_64_tdep_trace returns off-by-one addresses
Date: Fri, 2 Dec 2011 15:19:45 -0800 (PST)


As evidenced by this code in tests/Gtest-trace.c:

  /* Allow one in difference in comparison, trace returns adjusted addresses. */
  if (labs((unw_word_t) addresses[1][i] - (unw_word_t) addresses[2][i]) > 1)
      printf ("FAILURE: backtrace() and unw_backtrace() addresses differ at %d: 
%p vs. %p\n",
              i, addresses[1][n], addresses[2][n]);

the fast trace adjusts return addresses by one for all frames, except the
frame that actually triggered a signal (if any), and that is inconsistent
with what the "slow trace" would produce.

Aside from the inconsistency, this gives wrong address for the
__restore_rt frame:

(gdb) bt
#0  do_backtrace () at ../../tests/Gtest-trace.c:97
#1  0x0000000000401d8a in sighandler (signal=15, siginfo=0x7fffffffd270, 
context=0x7fffffffd140) at ../../tests/Gtest-trace.c:219
#2  <signal handler called>
#3  0x00007ffff7656d57 in kill () at ../sysdeps/unix/syscall-template.S:82
#4  0x0000000000401e7a in main (argc=1, argv=0x7fffffffd768) at 

(gdb) set $a =  (char **)&addresses[1]
(gdb) p/a *($a++)
$10 = 0x400e0f <do_backtrace+363>
$11 = 0x401d89 <sighandler+113>
$12 = 0x7ffff7656aef      <<< should be:  0x7ffff7656af0 <__restore_rt>
$13 = 0x7ffff7656d57 <kill+7>
$14 = 0x401e79 <main+237>
$15 = 0x7ffff7641c4c <__libc_start_main+252>
$16 = 0x400be8 <_start+40>
$17 = 0x0

I wonder what the justification for "off by one" behavior is, and what
are the ramifications of not doing that (in the trace returned, not during
the actual unwind):

diff --git a/src/x86_64/Gtrace.c b/src/x86_64/Gtrace.c
index 2d78729..2423ecc 100644
--- a/src/x86_64/Gtrace.c
+++ b/src/x86_64/Gtrace.c
@@ -522,7 +522,7 @@ tdep_trace (unw_cursor_t *cursor, void **buffer, int *size)
     /* Record this address in stack trace. We skipped the first address. */
-    buffer[depth++] = (void *) (rip - d->use_prev_instr);
+    buffer[depth++] = (void *) rip;

Paul Pluzhnikov

reply via email to

[Prev in Thread] Current Thread [Next in Thread]