libunwind-devel
[Top][All Lists]
Advanced

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

[Libunwind-devel] Libunwind support for NULL IP


From: Prabhat Verma
Subject: [Libunwind-devel] Libunwind support for NULL IP
Date: Fri, 16 Mar 2012 15:55:37 +0000

Hello,

 

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:

 

void (*p)() = NULL;

p();

 

In our case, we may have a call-chain that can look like:

Foo() calls bar() calls foobar() calls …. calls p()

 

Ideally, the aim is to get a trace starting with p() down to the start….

 

As a POC, I wrote a small test-case that makes nested function calls. In the most nested function, I do a getcontext and unw_init_local. During unw_step I clobber one of the IP (from the initialized cursor) using set_unw_reg. The subsequent call to unw_step either segfaults or aborts (based on what configuration options were used to build libunwind). Is this a correct simulation of my test-case?

 

I would like to ask the developers if such an abort is the expected behavior (I have limited knowledge of stack unwinding)? If not, is there any fix or workaround that would enable moving on to the next frame (possibly dropping the NULL IP frame or replacing it with a known dummy frame?). As a second experiment, I tried setting the IP to some dummy address and the results are unreliable (sometimes it works and other times it fails).

 

In our case, libunwind calls will sit inside our signal handler. On the current platform, getcontext() and unw_getcontext() seem to be interchangeable (I am guessing unw_context does less work than getcontext).

 

All help is highly appreciated.

 

Regards,

Prabhat

 

Specs:

Debian GNU/Linux 6.0.1

 

% g++ -v

Using built-in specs.

Target: x86_64-linux-gnu

Configured with: ../src/configure -v --with-pkgversion='Debian 4.4.5-8' --with-bugurl=file:///usr/share/doc/gcc-4.4/README.Bugs --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.4 --enable-shared --enable-multiarch --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.4 --libdir=/usr/lib --enable-nls --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc --with-arch-32=i586 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu

Thread model: posix

gcc version 4.4.5 (Debian 4.4.5-8)

 

 

The output of testcase (foo9 calls foo8 calls …..foo1 calls foo):

No Clobber:

 

Inside foo9()

Inside foo8()

Inside foo7()

Inside foo6()

Inside foo5()

Inside foo4()

Inside foo3()

Inside foo2()

Inside foo1()

Inside foo ()

 

Depth   Registers

0--->      ip = 400ae7, sp = 7fff8706c4f0

1--->      ip = 400b01, sp = 7fff8706c500

2--->      ip = 400b1b, sp = 7fff8706c510

3--->      ip = 400b35, sp = 7fff8706c520

4--->      ip = 400b4f, sp = 7fff8706c530

5--->      ip = 400b69, sp = 7fff8706c540

6--->      ip = 400b83, sp = 7fff8706c550

7--->      ip = 400b9d, sp = 7fff8706c560

8--->      ip = 400bb7, sp = 7fff8706c570

9--->      ip = 400bd1, sp = 7fff8706c580

10--->    ip = 400bfd, sp = 7fff8706c590

11--->    ip = 7fe960cf2c4d, sp = 7fff8706c5a0

12--->    ip = 400919, sp = 7fff8706c660

 

Clobbered IP:

 

Inside foo9()

Inside foo8()

Inside foo7()

Inside foo6()

Inside foo5()

Inside foo4()

Inside foo3()

Inside foo2()

Inside foo1()

Inside foo ()

 

Depth   Registers

libunwindtest: dwarf/Gparser.c:754: apply_reg_state: Assertion `rs->reg[17].where == DWARF_WHERE_EXPR' failed.

Aborted


reply via email to

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