libbacktrace skip parameter can skip several inlined functions
bhaible opened this issue · comments
On Ubuntu 16.04, when I compile a program with "-g" or "-ggdb", for 32-bit mode programs, libbacktrace can infer file and line numbers. For 64-bit mode programs, this does not work.
How to reproduce: Compile this program in 64-bit mode.
backtrace-via-libbacktrace.c.gz
$ gcc -g -O2 -lbacktrace
$ ./a.out
0x7f7b8e38e83f ???
???:0
0x401178 ???
???:0
0xffffffffffffffff ???
???:0
and
$ gcc -ggdb -O2 -lbacktrace
$ ./a.out
0x7f63a997183f ???
???:0
0x401178 ???
???:0
0xffffffffffffffff ???
???:0
gcc is version 5.4.0. gdb does understand the debug info.
I run libbacktrace on x86_64 all the time. I don't see any problem reading x86_64 debug info.
If I change your program to pass a skip argument of 0 to backtrace_print
, it prints a full backtrace. The same is true if the program is compiled without -O2
. What is happening with your test program is that all the functions are inlined into main
. The skip argument is being applied before considering the inlining. The effect is that the code that skips print_trace
also skips dummy_function
and main
. This does seem like a bug in the handling of the skip
parameter.
If I change your program to pass a skip argument of 0 to backtrace_print, it prints a full backtrace. The same is true if the program is compiled without -O2.
Yes, I reproduce this.
What is happening with your test program is that all the functions are inlined into main.
Not entirely.
Without -O2, there are three stack frames: print_trace, dummy_function, main.
With -O2, dummy_function gets optimized away, and there are two stack frames: print_trace, main. (main
contains a call print_trace
.) With skip = 0, I get this output:
0x401148 dummy_function
/media/develdata/devel/GNULIB/old/backtrace-via-libbacktrace.c:18
0x401148 main
/media/develdata/devel/GNULIB/old/backtrace-via-libbacktrace.c:30
0x7f28b3ee483f ???
???:0
0x401178 ???
???:0
0xffffffffffffffff ???
???:0
The first line here is wrong. It should reflect the frame of print_trace
. But instead, it reflects the frame of dummy_function
(which has been eliminated), and the frame of print_trace
has been lost.
That the frame-skipping logic then, for skip = 1, eliminates two frames instead of one, is understandable (given that both frames show the same code address). But the original problem exists already with skip = 0.