libunwind-devel
[Top][All Lists]
Advanced

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

Re: [Libunwind-devel] Libunwind support for NULL IP


From: Arun Sharma
Subject: Re: [Libunwind-devel] Libunwind support for NULL IP
Date: Wed, 4 Apr 2012 20:45:15 -0700

On Tue, Apr 3, 2012 at 8:47 AM, Prabhat Verma
<address@hidden> wrote:

> I tried this fix but it seems to be broken in more ways than expected...

The test needed a couple of fixes too :) See below.

> I am sending you the test program for reference. For now, I set the IP to a 
> non-null value and it seems to unwind all the way except that first two 
> frames are lost i.e. if main() calls foo1() calls foo() calls 
> do_null_fp_dereferece_and_segv(), then the generated stacktrace will show 
> frames foo1 - main (do_null_fp.. and foo are lost)....
> That said, for us, this is still a big improvement over backtrace and the 
> initial tests look exciting.

Were you compiling with -O2 by any chance? If so, that's to be expected.

00000000004016c0 <foo8()>:
  4016c0:       55                      push   %rbp
  4016c1:       ba 0e 00 00 00          mov    $0xe,%edx
  4016c6:       be 94 c4 40 00          mov    $0x40c494,%esi
  4016cb:       bf 80 01 61 00          mov    $0x610180,%edi
  4016d0:       48 89 e5                mov    %rsp,%rbp
  4016d3:       e8 78 fa ff ff          callq  401150
  4016d8:       5d                      pop    %rbp
  4016d9:       e9 c2 ff ff ff          jmpq   4016a0 <foo7()>
  4016de:       66 90                   xchg   %ax,%ax

Notice that there is a jmp to foo7, not a call. That's called tail
call optimization. Try compiling with -fno-optimize-sibling-calls
-fno-omit-frame-pointer.

I get:

Stack Trace ----->
temp_ip = 4015dd, temp_sp = 7fff7f403018, procedure--> _Z3foov
temp_ip = 4015fd, temp_sp = 7fff7f403030, procedure--> _Z4foo1v
temp_ip = 40161d, temp_sp = 7fff7f403040, procedure--> _Z4foo2v
temp_ip = 40163d, temp_sp = 7fff7f403050, procedure--> _Z4foo3v
temp_ip = 40165d, temp_sp = 7fff7f403060, procedure--> _Z4foo4v
temp_ip = 40167d, temp_sp = 7fff7f403070, procedure--> _Z4foo5v
temp_ip = 40169d, temp_sp = 7fff7f403080, procedure--> _Z4foo6v
temp_ip = 4016bd, temp_sp = 7fff7f403090, procedure--> _Z4foo7v
temp_ip = 4016dd, temp_sp = 7fff7f4030a0, procedure--> _Z4foo8v
temp_ip = 4016fd, temp_sp = 7fff7f4030b0, procedure--> _Z4foo9v
temp_ip = 4012fd, temp_sp = 7fff7f4030c0, procedure--> main
temp_ip = 7fef6c05d30d, temp_sp = 7fff7f403220, procedure--> __libc_start_main
temp_ip = 40135d, temp_sp = 7fff7f4032e0, procedure--> _start

diff I used (for reference only. pasted patch. may not apply):

--- myFirstExp (1).cpp  2012-04-04 20:18:36.655767001 -0700
+++ myFirstExp.cpp      2012-04-04 20:30:05.499767001 -0700
@@ -1,6 +1,7 @@
 #include <iostream>
 #include <stdio.h>
 #include <signal.h>
+#include <strings.h>

 #define UNW_LOCAL_ONLY
 #include <libunwind.h>
@@ -11,7 +12,7 @@
     unw_word_t temp_ip, temp_sp;
     ucontext_t* temp_a_uc = (ucontext_t*) a_uc;
     unw_init_local(&temp_cursor, temp_a_uc);
-    unw_set_reg(&temp_cursor, UNW_REG_IP, 1);
+    //unw_set_reg(&temp_cursor, UNW_REG_IP, 1);
     std::cout << "\nStack Trace -----> \n";
     while (unw_step(&temp_cursor) > 0) {
       unw_get_reg(&temp_cursor, UNW_REG_IP, &temp_ip);
@@ -23,6 +24,7 @@
       printf ("temp_ip = %lx, temp_sp = %lx, procedure--> %s\n",
(long) temp_ip, (long) temp_sp, buffer);
     }
     std::cout << "\n\n";
+    fflush(stdout);
 }

 void
@@ -71,7 +73,8 @@
 int
 main(){
     struct sigaction new_sigaction, old_sigaction;
-
+
+    bzero(&new_sigaction, sizeof(struct sigaction));
     new_sigaction.sa_sigaction = segv_handler;
     new_sigaction.sa_flags = SA_SIGINFO;

@@ -79,7 +82,7 @@

     sigaddset(&new_sigaction.sa_mask, SIGSEGV);

-    sigaction (SIGSEGV, NULL, &new_sigaction);
+    sigaction (SIGSEGV, &new_sigaction, NULL);

     if (old_sigaction.sa_handler != SIG_IGN){
         new_sigaction.sa_handler = test_signal_handler;

Also needed this fix to libunwind:

x86_64: continue unwinding frame chain.

dwarf_get() returns zero on success. However a return value of 0 from
unw_step() causes unwinding to stop.

--- a/src/x86_64/Gstep.c
+++ b/src/x86_64/Gstep.c
@@ -206,6 +206,7 @@ unw_step (unw_cursor_t *cursor)
              Debug (2, "returning %d\n", ret);
              return ret;
            }
+          ret = 1;
        }
       else
        c->dwarf.ip = 0;

If you want all of this to work without -fno-omit-frame-pointer,
things become a bit more complicated. We'll somehow have to
(heuristically?) unwind up to the point where IP is valid. libunwind
knows what to do after that.

 -Arun



reply via email to

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