libunwind-devel
[Top][All Lists]
Advanced

[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




reply via email to

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