|
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 |
[Prev in Thread] | Current Thread | [Next in Thread] |