From: Tony Houghton on
Is there a way to get a C program to print a backtrace of itself, like
the ones you get in gdb? I tried backtrace() with backtrace_symbols()
and backtrace_symbols_fd() but instead of printing function names it
prints /home/tony/boxstard/boxstard/boxstard() which is actually the
filename of the executable. I can get meaningful backtraces from it in
gdb, but if I use breakpoints and enter bt and run manually the time
delay will interfere with what the program's doing, so I need to get the
program to print backtraces automatically.

--
TH * http://www.realh.co.uk
From: Tony Houghton on
In <slrni34rtu.m4s.h(a)realh.co.uk>,
Tony Houghton <h(a)realh.co.uk> wrote:

> Is there a way to get a C program to print a backtrace of itself, like
> the ones you get in gdb? I tried backtrace() with backtrace_symbols()
> and backtrace_symbols_fd() but instead of printing function names it
> prints /home/tony/boxstard/boxstard/boxstard() which is actually the
> filename of the executable. I can get meaningful backtraces from it in
> gdb, but if I use breakpoints and enter bt and run manually the time

That looks confusing, I should have typed:

: if I use breakpoints and enter "bt" and then "cont" manually, ...

> delay will interfere with what the program's doing, so I need to get the
> program to print backtraces automatically.
>


--
TH * http://www.realh.co.uk
From: Richard Kettlewell on
Tony Houghton <h(a)realh.co.uk> writes:

> Is there a way to get a C program to print a backtrace of itself, like
> the ones you get in gdb? I tried backtrace() with backtrace_symbols()
> and backtrace_symbols_fd() but instead of printing function names it
> prints /home/tony/boxstard/boxstard/boxstard() which is actually the
> filename of the executable. I can get meaningful backtraces from it in
> gdb, but if I use breakpoints and enter bt and run manually the time
> delay will interfere with what the program's doing, so I need to get the
> program to print backtraces automatically.

You don't say what compiler flags you're using, but perhaps you're
missing -rdynamic. This is documented though it took me a while to spot
it!

Also, you may need to pass additional flags to the linker to make
the function names available to the program. (For example, on
systems using GNU ld, you must pass (`-rdynamic'.)

For instance, using the example program from the Glibc manual:

richard(a)deodand:~$ gcc -o u u.c && ./u
Obtained 5 stack frames.
./u() [0x80484dd]
./u() [0x8048549]
./u() [0x8048556]
/lib/i686/cmov/libc.so.6(__libc_start_main+0xe6) [0xb75ddc76]
./u() [0x8048431]
richard(a)deodand:~$ gcc -rdynamic -o u u.c && ./u
Obtained 5 stack frames.
./u(print_trace+0x19) [0x804871d]
./u(dummy_function+0xb) [0x8048789]
./u(main+0xb) [0x8048796]
/lib/i686/cmov/libc.so.6(__libc_start_main+0xe6) [0xb76f0c76]
./u() [0x8048671]

--
http://www.greenend.org.uk/rjk/
From: Tony Houghton on
In <87d3v0lrfo.fsf(a)araminta.anjou.terraraq.org.uk>,
Richard Kettlewell <rjk(a)greenend.org.uk> wrote:

> Tony Houghton <h(a)realh.co.uk> writes:
>
>> Is there a way to get a C program to print a backtrace of itself, like
>> the ones you get in gdb? I tried backtrace() with backtrace_symbols()
>> and backtrace_symbols_fd() but instead of printing function names it
>> prints /home/tony/boxstard/boxstard/boxstard() which is actually the
>> filename of the executable. I can get meaningful backtraces from it in
>> gdb, but if I use breakpoints and enter bt and run manually the time
>> delay will interfere with what the program's doing, so I need to get the
>> program to print backtraces automatically.
>
> You don't say what compiler flags you're using, but perhaps you're
> missing -rdynamic. This is documented though it took me a while to spot
> it!
>
> Also, you may need to pass additional flags to the linker to make
> the function names available to the program. (For example, on
> systems using GNU ld, you must pass (`-rdynamic'.)

Ah, so it doesn't get them the same way gdb does?

--
TH * http://www.realh.co.uk
From: Nix on
On 6 Jul 2010, Tony Houghton said:

> In <87d3v0lrfo.fsf(a)araminta.anjou.terraraq.org.uk>,
> Richard Kettlewell <rjk(a)greenend.org.uk> wrote:
>
>> Tony Houghton <h(a)realh.co.uk> writes:
>>> Is there a way to get a C program to print a backtrace of itself, like
>>> the ones you get in gdb? I tried backtrace() with backtrace_symbols()
>>> and backtrace_symbols_fd() but instead of printing function names it
>>> prints /home/tony/boxstard/boxstard/boxstard() which is actually the
>>> filename of the executable. I can get meaningful backtraces from it in
>>> gdb, but if I use breakpoints and enter bt and run manually the time
>>> delay will interfere with what the program's doing, so I need to get the
>>> program to print backtraces automatically.
>>
>> You don't say what compiler flags you're using, but perhaps you're
>> missing -rdynamic. This is documented though it took me a while to spot
>> it!
>>
>> Also, you may need to pass additional flags to the linker to make
>> the function names available to the program. (For example, on
>> systems using GNU ld, you must pass (`-rdynamic'.)
>
> Ah, so it doesn't get them the same way gdb does?

Not quite.

On x86/x86_64, where possible, gets the *addresses* of the backtrace
using _Unwind_Backtrace(), which is the exception unwinder from
libgcc. This preferentially uses the DWARF exception frame section to
unwind, but in C code on x86 this is only available if you compile with
-fexceptions. Failing that, it falls back to walking stack frames,
which only works if you have frame pointers: *these* are not compiled in
by default on x86_64.

Note that the common case works in all situations: on x86_64, it always
uses DWARF; on x86, it uses DWARF in C++ code and frame pointers
otherwise. However, -fomit-frame-pointer is a common GCC parameter on
x86, because it speeds up the program significantly because of the
platform's chronic register starvation: with that provided, and without
-fexceptions, backtrace() will fail to work with non-C++ code.

However, libunwind can't map from addresses to symbols. GDB does this by
parsing DWARF2 debugging information, but it's a stretch to require that
for everything you might want to backtrace (it has a tendency to be
huge). So instead glibc gets the mapping from addresses to symbols using
a table it already has available: the symbol table. But without
-rdynamic, main programs don't have one of those. Hence the requirement
to pass -rdynamic if you want useful backtraces (out of main programs,
anyway).