FennelStackTrace

From Eigenpedia

Jump to: navigation, search

How do I get a Fennel stack trace, and once I've got one, what do I do with it?


(See FarragoFennelDebugging if you want to use gdb for this purpose, or the JRockit notes from FarragoStackTrace for obtaining a stack trace from a JVM hanging in Fennel code.)

On Linux, Fennel installs signal handlers which produce a stack trace (also known as a backtrace) automatically whenever one of the following events occurs:

  • SIGSEGV, SIGBUS, or SIGILL: some kind of memory access fault
  • SIGABRT: abort (e.g due to unhandled exception, assertion failure, or explicit abort call)

Signal handling is installed for all unit tests, as well as when Fennel is loaded into a Java VM by Farrago. Output spews to stderr, and also to the current trace file if any (each Fennel unit test gets its own trace file; backtraces which occur when run from Farrago are teed to FarragoTrace.log; see FarragoTracing). For a unit test which exercises backtrace on various kinds of events, see fennel/common/testBacktrace.cpp. Here's an example of running it to explicitly cause a SIGSEGV:

jvs@bagheera:~/open/dev/fennel/common$ ./testBacktrace s
'''* CAUGHT SIGNAL 11; BACKTRACE:
./testBacktrace(fennel::AutoBacktrace::signal_handler(int)+0x29) [0x8059909]
[0xffffe420]
./testBacktrace(_STL::basic_istream<char, _STL::char_traits<char> >::sentry::sentry(_STL::basic_istream<char,
    _STL::char_traits<char> >&, bool)+0x27) [0x8060f43]
./testBacktrace(_STL::basic_istream<char, _STL::char_traits<char> >& _STL::operator>><char, _STL::char_traits<char>,
    _STL::allocator<char> >(_STL::basic_istream<char, _STL::char_traits<char> >&, _STL::_Nondebug_string<char,
    _STL::char_traits<char>, _STL::allocator<char> >&)+0x2d) [0x805ec83]
./testBacktrace(fennel::ConfigMap::readParams(_STL::basic_istream<char, _STL::char_traits<char> >&)+0x3c) [0x805e040]
./testBacktrace(main+0x227) [0x805813b]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xd2) [0x14ea2]
./testBacktrace(__gxx_personality_v0+0x211) [0x8057cb1]
Segmentation fault

As you can see, method names have been demangled in all their templatized glory, but no source file/line number information is provided, even though the executable was compiled with debug info. Instead, only machine code instruction addresses are provided. Fortunately, a utility is provided for performing the desired translation. Run open/util/bin/analyzeBacktrace, supplying the lines of interest from the original backtrace on stdin. The example below shows the results corresponding to several frames from the above backtrace:

jvs@bagheera:~/open/dev/fennel/common$ ./testBacktrace s 2> test.txt
Segmentation fault
jvs@bagheera:~/open/dev/fennel/common$ tail -6 test.txt | analyzeBacktrace
/home/jvs/open/dev/thirdparty/stlport/stlport/stl/_istream.h:224: _STL::basic_istream<char,
    _STL::char_traits<char> >::sentry::sentry(_STL::basic_istream<char, _STL::char_traits<char> >&, bool)
/home/jvs/open/dev/thirdparty/stlport/stlport/stl/_string_io.c:88: _STL::basic_istream<char,
    _STL::char_traits<char> >& _STL::operator>><char, _STL::char_traits<char>,
    _STL::allocator<char> >(_STL::basic_istream<char, _STL::char_traits<char> >&,
    _STL::_Nondebug_string<char, _STL::char_traits<char>, _STL::allocator<char> >&)
/home/jvs/open/dev/fennel/common/ConfigMap.cpp:45: fennel::ConfigMap::readParams(_STL::basic_istream<char,
    _STL::char_traits<char> >&)
/home/jvs/open/dev/fennel/common/testBacktrace.cpp:103: main
??:0: __libc_start_main
../sysdeps/i386/elf/start.S:122: __gxx_personality_v0

__IMPORTANT NOTE__: if you receive a backtrace from someone else, analyzeBacktrace can only be used if

  • Your machine where analyzeBacktrace runs has the exact same Fennel build as the machine where the backtrace was produced. If this isn't the case, you'll end up with bogus source locations.
  • The shared object file locations in the backtrace match your machine. If this isn't the case, you might be able to use search/replace on the backtrace to fake it.

Even with everything matching perfectly, backtrace analysis isn't always guaranteed to work, particularly if the build was run with optimization.



Shared Libraries

The Fennel backtrace support automatically adjusts instruction addresses in shared libraries by subtracting the base address at which the .so was loaded, allowing the addr2line utility (on which analyzeBacktrace is based) to function correctly.

This means that if you obtain a backtrace from somewhere else, e.g. the Java SIGQUIT mechanism described in FarragoStackTrace, you can't run analyzeBacktrace on it directly, because the absolute instruction addresses won't correspond to the shared library image. In that case, if you really need it, it's possible to get what you want if you can determine the base address at which the shared libraries were loaded; the SIGQUIT dump includes this information. Maybe someone should write a parser for it to perform the analysis automatically?


Personal tools