From Bugzilla Helper: User-Agent: Mozilla/5.0 (compatible; Konqueror/3.4; Linux) KHTML/3.4.91 (like Gecko) Description of problem: The glibc function backtrace() does not resolve symbols in programs which were compiled with the gcc option -fvisibility=hidden. Here is an example program (backtrace.c) to reproduce the problem: ------------------------------------------------------------------- /* Works: cc -o backtrace backtrace.c -Wl,--export-dynamic */ /* Fails: cc -o backtrace backtrace.c -fvisibility=hidden -Wl,--export-dynamic */ #include <stdio.h> #include <unistd.h> #include <string.h> #include <execinfo.h> #include <stdlib.h> #include <signal.h> void showFuncStack() { int addrs; void * addr[10]; addrs = backtrace(addr, sizeof(addr)/sizeof(addr[0])); backtrace_symbols_fd(addr, addrs, 2); } void cc() { showFuncStack(); } int main(int argc, char *argv[]) { cc(); return 0; } Version-Release number of selected component (if applicable): glibc-2.3.5-10.3 How reproducible: Always Steps to Reproduce: 1. compile above program: "cc -o backtrace backtrace.c -fvisibility=hidden -Wl,--export-dynamic" 2. run the program: ./backtrace 3. you will not see the symbols "showFuncStack" or "cc" in the output. Now how it works: 4. compile above program without the "-fvisibility=hidden" option: "cc -o backtrace backtrace.c -fvisibility=default -Wl,--export-dynamic" 5. run the program again: ./backtrace 6: you will see all symbols. Actual Results: The output is: ./backtrace[0x4006fe] ./backtrace[0x400722] ./backtrace[0x40073d] /lib64/libc.so.6(__libc_start_main+0xef)[0x337c41c3cf] ./backtrace[0x400659] Expected Results: The output should be (which ./backtrace(showFuncStack+0x16)[0x40075e] ./backtrace(cc+0xe)[0x400782] ./backtrace(main+0x19)[0x40079d] /lib64/libc.so.6(__libc_start_main+0xef)[0x337c41c3cf] ./backtrace[0x4006b9] Additional info: It's true, that hidden symbols should not be visible when linking with other programs. Nevertheless, backtrace() should show the symbols at least, since they are necessary if you want to debug a program after it has crashed....
That's a feature. backtrace_symbols{,_fd} () uses only the dynamic symbol table, something that is already loaded and can be looked up easily. Hidden symbols aren't in the dynamic symbol table, so they don't show up in backtrace_symbols{,_fd} (). If that's not enough and either non-allocated symbol table or debugging info needs to be analyzed, that's a job of other utilities (like addrline).
Hello Jakub, that's really bad. We use the backtrace() function in our application to produce a backtrace in a log file, which then later can be used by development to find the real problem. It's really unhandy to ask customers to run addrline or such. So, what do you propose ? _Would_ it be possible to make backtrace look/load the non-dynamic symbol table as well ? Would it be hard to implement ? What about a chance of making it possible, if it would be a feature request ? I'm just asking again, since without having the backtrace() functionality it does not make sense to compile and ship our application with the -fvisibility=hidden flag (which should bring some more performance on Linux). TIA, Helge PS: Please close it afterwards as "NOTABUG" again...
FYI, backtrace () just gives you addresses, you are really talking about backtrace_symbols{,_fd} (). But glibc is certainly not meant to be a kitchen sink and even just finding the library, opening it, finding the symbol and string tables and looking information there would mean glibc would need to contain quite a lot of ELF handling code, probably a copy of libelf. Plus most of the symbol and string tables as well as debug info in our distro are stripped into separate files, so it would need to handle that too. Not to mention that using debug info as opposed to just symbol table you can get far better info, see e.g. addr2line -i option in rawhide that gives you info about inlined functions in the backtrace. Nothing prevents you from spawning addr2line utility (or eu-addr2line) and passing it the addresses from backtrace () and reporting back what it printed. And that's the best solution here IMHO.
Hello Jakub, spawning addr2line will not work in our case, since our application dlopen() other shared libraries, which addr2line will not know about and thus will not be able to decode. I agree, that glibc should not be a kitchen sync, but without being able to see at least the (newly) local text symbols (which have been global text symbols before the -fvisibility=hidden flag) the backtrace_symbols()-functions in glibc is IMHO more or less useless. All you normally will see is "main()". What about dropping backtrace_symbols() [and maybe backtrace()] from glibc and provide full functionality in an external optional library ? Helge