-----Original Message-----
From: [email protected] [mailto:[email protected]] On Behalf Of Arun 
Sharma
Sent: Sunday, March 25, 2012 9:53 PM
To: Prabhat Verma
Cc: [email protected]
Subject: Re: [Libunwind-devel] Libunwind support for NULL IP

On Fri, Mar 16, 2012 at 8:55 AM, Prabhat Verma <[email protected]> 
wrote:
> We are trying to replace backtrace with libunwind (local unwinding) 
> for our diagnostic purposes. A major motivation behind this decision 
> was the inability of backtrace to handle stack frames containing NULL 
> IP. In our case, this may happen if someone ends up doing this:

>>I pushed a few changes to the git repo. Could you please try them to see if 
>>things work better for you?

>>In short: dwarf says NULL RBP is the end of the callchain. But libunwind was 
>>terminating unwind on NULL RIP as well.

>>In the process I seem to have introduced a test failure (run-ptrace-misc used 
>>to pass earlier). I'll dig into it when I get a chance. On the face of it, it 
>>looks like unwinding from (ip == 0) used to succeed earlier, but it fails now 
>>(due to lack of unwind info?).

 >>-Arun


I tried this fix but it seems to be broken in more ways than expected... 
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.

-Prabhat
#include <iostream>
#include <stdio.h>
#include <signal.h>

#define UNW_LOCAL_ONLY
#include <libunwind.h>

void 
my_unw_step_and_print_stack_native(void * a_uc) {
    unw_cursor_t temp_cursor;
    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);
    std::cout << "\nStack Trace -----> \n";
    while (unw_step(&temp_cursor) > 0) {
      unw_get_reg(&temp_cursor, UNW_REG_IP, &temp_ip);
      unw_get_reg(&temp_cursor, UNW_REG_SP, &temp_sp);
      char buffer[100];
      unw_word_t offset, *poffset; 
      poffset = &offset;
      unw_get_proc_name(&temp_cursor, (char *)buffer, 99, poffset);
      printf ("temp_ip = %lx, temp_sp = %lx, procedure--> %s\n", (long) 
temp_ip, (long) temp_sp, buffer);
    }
    std::cout << "\n\n";
}

void 
bail(){
   std::cout << "\nInside bail ()\n";
   void (*fp)() = NULL; 
   fp();
}

void foo () { 
   std::cout << "\nInside foo ()\n";
   bail();
}

void foo1() { std::cout << "\nInside foo1()"; foo (); }
void foo2() { std::cout << "\nInside foo2()"; foo1(); }
void foo3() { std::cout << "\nInside foo3()"; foo2(); }
void foo4() { std::cout << "\nInside foo4()"; foo3(); }
void foo5() { std::cout << "\nInside foo5()"; foo4(); }
void foo6() { std::cout << "\nInside foo6()"; foo5(); }
void foo7() { std::cout << "\nInside foo7()"; foo6(); }
void foo8() { std::cout << "\nInside foo8()"; foo7(); }
void foo9() { std::cout << "\nInside foo9()"; foo8(); }


void
segv_handler (int signum, siginfo_t* info, void *old_context){
    std::cout << "\nInside segv_handler\n";

    //Let OS supply context
    my_unw_step_and_print_stack_native(old_context);    

    std::cout << "\n\nBAILING...\n\n";
    //Bail on SIGSEGV default bahavior
    signal(SIGSEGV, SIG_DFL);
}

void
test_signal_handler(int signum){
    std::cout << "\nInside test_signal_handler. I should not be here...\n";
    //Bail on SIGSEGV (default behavior)
    signal(SIGSEGV, SIG_DFL);
}


int 
main(){
    struct sigaction new_sigaction, old_sigaction;
    
    new_sigaction.sa_sigaction = segv_handler;
    new_sigaction.sa_flags = SA_SIGINFO;

    sigemptyset (&new_sigaction.sa_mask);
    
    sigaddset(&new_sigaction.sa_mask, SIGSEGV);    
    
    sigaction (SIGSEGV, NULL, &new_sigaction);

    if (old_sigaction.sa_handler != SIG_IGN){
        new_sigaction.sa_handler = test_signal_handler;
        new_sigaction.sa_sigaction = segv_handler;
        sigaction (SIGSEGV, &new_sigaction, &old_sigaction);
    }
    foo9();
    return 0;
}
_______________________________________________
Libunwind-devel mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/libunwind-devel

Reply via email to