Generating C++ BackTraces in OS/X (10.5.7)
-
16-09-2019 - |
Question
I've been utilizing backtrace and backtrace_symbols to generate programmatic stack traces for the purposes of logging/diagnosis. It seems to roughly work, however, I'm getting a little bit of mangling and there are no accompanying file/line numbers associated with each function invocation (as I'd expect within a gdb bt call or something). Here's an example:
1 leonardo 0x00006989 _ZN9ExceptionC2E13ExceptionType + 111
2 leonardo 0x00006a20 _ZN9ExceptionC1E13ExceptionType + 24
3 leonardo 0x0000ab64 _ZN5Rules11ApplyActionER16ApplicableActionR9GameState + 1060
4 leonardo 0x0000ed15 _ZN9Simulator8SimulateEv + 2179
5 leonardo 0x0000eec9 _ZN9Simulator8SimulateEi + 37
6 leonardo 0x00009729 main + 45
7 leonardo 0x000025c6 start + 54
Anything I'm missing something, doing something silly, or is this all I can expect out of backtrace on OS/X?
Some other tidbits:
rdynamic
link option for the g++ version (4.0.1) I'm using.-g/-g3
doesn't make any difference.
abi::__cxa__demangle
doesn't seem to do anything
Solution
The backtraces typically come back from backtrace_symbols in the following format:
./MyApp(_ZN4test3fooEv+0x8) [0x821c874]
abi::__cxa_demangle expects only the function name. Thus, some parsing must first be done on the trace:
std::string trace(backtrace[idx]);
// attempt to demangle
{
std::string::size_type begin, end;
// find the beginning and the end of the useful part of the trace
begin = trace.find_first_of('(') + 1;
end = trace.find_last_of('+');
// if they were found, we'll go ahead and demangle
if (begin != std::string::npos && end != std::string::npos) {
trace = trace.substr(begin, end - begin);
size_t maxName = 1024;
int demangleStatus;
char* demangledName = (char*) malloc(maxName);
if ((demangledName = abi::__cxa_demangle(trace.c_str(), demangledName, &maxName,
&demangleStatus)) && demangleStatus == 0) {
trace = demangledName; // the demangled name is now in our trace string
}
free(demangledName);
}
}
I've tested this is on my own project, and it gives somewhat nicer backtraces with the following format:
test::foo()
Sure, there are no line numbers, but I'm not certain that is even possible.
OTHER TIPS
I don't know of any implementation of backtrace_symbols()
which gives any more than symbol+offset.
With regards to abi:: __cxa__demangle
, you need to ensure that you only pass it the symbol name, without the + line
suffix, otherwise it won't recognise the symbol as valid.