[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) |
Greetings,
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]);
++num_errors;
}
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
../../tests/Gtest-trace.c:243
(gdb) set $a = (char **)&addresses[1]
(gdb) p/a *($a++)
$10 = 0x400e0f <do_backtrace+363>
(gdb)
$11 = 0x401d89 <sighandler+113>
(gdb)
$12 = 0x7ffff7656aef <<< should be: 0x7ffff7656af0 <__restore_rt>
(gdb)
$13 = 0x7ffff7656d57 <kill+7>
(gdb)
$14 = 0x401e79 <main+237>
(gdb)
$15 = 0x7ffff7641c4c <__libc_start_main+252>
(gdb)
$16 = 0x400be8 <_start+40>
(gdb)
$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)
break;
/* Record this address in stack trace. We skipped the first address. */
- buffer[depth++] = (void *) (rip - d->use_prev_instr);
+ buffer[depth++] = (void *) rip;
}
#if UNW_DEBUG
Thanks,
--
Paul Pluzhnikov
- [Libunwind-devel] [RFC] _ULx86_64_tdep_trace returns off-by-one addresses,
Paul Pluzhnikov <=