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
_______________________________________________
Libunwind-devel mailing list
[email protected]
https://lists.nongnu.org/mailman/listinfo/libunwind-devel

Reply via email to