[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Libunwind-devel] Linux x86_64 unw_is_signal_frame() broken?
From: |
Paul Pluzhnikov |
Subject: |
[Libunwind-devel] Linux x86_64 unw_is_signal_frame() broken? |
Date: |
Tue, 15 Apr 2008 19:03:50 -0700 |
Greetings,
libunwind fails to unwind through signal handler on my x86_64
compilations of libc. Current code reads:
/* Check if RIP points at sigreturn sequence.
on x86_64 Linux that is (see libc.so):
48 c7 c0 0f 00 00 00 mov $0xf,%rax
0f 05 syscall
66 data16
*/
...
return (w0 == 0x0f0000000fc0c748 && w1 == 0x66666605);
That second check for w1 makes absolutely no sense to me :-(
Here is what my 2 separate versions of libc look like:
$ gdb64 -q /lib64/tls/libc.so.6
(gdb) disas __restore_rt
Dump of assembler code for function __restore_rt:
0x000000000002ede0 <__restore_rt+0>: mov $0xf,%rax
0x000000000002ede7 <__restore_rt+7>: syscall
End of assembler dump.
(gdb) x/2gx 0x000000000002ede0
0x2ede0 <__restore_rt>: 0x0f0000000fc0c748 0xec81485355544105
(gdb)
$ gdb64 -q /usr/grte/v1/lib64/libc.so.6
(gdb) disas __restore_rt
Dump of assembler code for function __restore_rt:
0x000000000002fcd0 <__restore_rt+0>: mov $0xf,%rax
0x000000000002fcd7 <__restore_rt+7>: syscall
0x000000000002fcd9 <__restore_rt+9>: nopl 0x0(%rax)
End of assembler dump.
(gdb) x/2gx 0x000000000002fcd0
0x2fcd0 <__restore_rt>: 0x0f0000000fc0c748 0x00000000801f0f05
(gdb)
Proposed fix:
$ diff -u src/x86_64/Gis_signal_frame.c.orig src/x86_64/Gis_signal_frame.c
--- src/x86_64/Gis_signal_frame.c.orig 2008-04-15 18:01:12.000000000 -0700
+++ src/x86_64/Gis_signal_frame.c 2008-04-15 18:55:48.000000000 -0700
@@ -54,8 +54,8 @@
if ((ret = (*a->access_mem) (as, ip, &w0, 0, arg)) < 0
|| (ret = (*a->access_mem) (as, ip + 8, &w1, 0, arg)) < 0)
return 0;
- w1 &= 0xffffffff;
- return (w0 == 0x0f0000000fc0c748 && w1 == 0x66666605);
+ w1 &= 0xff;
+ return (w0 == 0x0f0000000fc0c748 && w1 == 0x05);
}
#else /* __linux__ */
Before the fix, "test-async-sig -v" produces:
...
sighandler(signal=26, count=225)
0000000000400b76 <do_backtrace+0x26> (sp=00007fffffffc420)
0000000000400ed3 <sighandler+0x23> (sp=00007fffffffcf40)
00002aaaaaf0a260 <_IO_funlockfile+0x48> (sp=00007fffffffcf50)
sighandler(signal=26, count=226)
...
After the fix:
...
sighandler(signal=26, count=283)
0000000000400b76 <do_backtrace+0x26> (sp=00007fffffffcb40)
0000000000400ed3 <sighandler+0x23> (sp=00007fffffffd660)
00002aaaaaf0a260 <_IO_funlockfile+0x48> (sp=00007fffffffd670)
00002aaaab14ee10 <getcontext+0x60> (sp=00007fffffffdab8)
0000000000400b76 <do_backtrace+0x26> (sp=00007fffffffdac0)
0000000000400e77 <main+0xb7> (sp=00007fffffffe5e0)
00002aaaab12faf2 <__libc_start_main+0x122> (sp=00007fffffffe6a0)
0000000000400aba <_start+0x2a> (sp=00007fffffffe750)
sighandler(signal=26, count=284)
...
Thanks,
--
Paul Pluzhnikov
- [Libunwind-devel] Linux x86_64 unw_is_signal_frame() broken?,
Paul Pluzhnikov <=