ianlancetaylor / libbacktrace

A C library that may be linked into a C/C++ program to produce symbolic backtraces

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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.