Get Callstacks and demangle C++

Dear Sirs,

while it's quite clear that I'll try to write applications that do not crash unfortunately this can happen. In this case I'd like to write a detailed crash report including callstacks for all threads to my logfiles even from Release builds on the customers machine. So I started to do some tests with backtrace and backtrace_symbols and this already seems to solve a lot. Nevertheless I don't really get as close to the error report shown by the MacOS error report as I'd have hoped. I have a problem with demangling the C++ objects and I cannot get the line numbers. So something which looks like this in the Apple MacOS error report:

5 MyCrashTestApp 0x10445f150 CZMQConnection::CFnCalledWorkerThread::Thread() + 132 (ZMQConnection.cpp:1128)

looks like this in my callstack:

5 MyCrashTestApp 0x000000010445f150 _ZN14CZMQConnection21CFnCalledWorkerThread6ThreadEv + 132

I tried different ways of demangling with calls to abi::__cxa_demangle() and dladdr() beforehand but so far the output didn't change and the filename and line numbers are completely missing.

How can I achieve an output like the one of the Apple MacOS error report including the filenames and line numbers and will this also work on customers machines? How do i have to configure my C++ XCode project for this?

Thanks and best regards, Johannes

OK, I think I figured out some of the tricks you have to do:

  • for abi::__cxa_demangle() you really have to extract only the name of the function out of the complete line you've been given from backtrace_symbols(). Looking at my example this means I have to call abi::__cxa_demangle( "_ZN14CZMQConnection21CFnCalledWorkerThread6ThreadEv", ... )

  • for the file names and line numbers you need the atos command and the DWARF file corresponding to your binary. But the tricky thing here is to find the load address of your image which is needed to call atos. You can get the load address by calling _dyld_get_image_header(0) i.e. in your c++ signal handler where you also log the backtrace and backtrace_symbols output.

Perhaps this helps anybody else searching similar things,

Johannes

In this case I'd like to write a detailed crash report including callstacks for all threads to my logfiles even from Release builds on the customers machine.

I recommend that you not do this. See Implementing Your Own Crash Reporter for a detailed explanation as to why.

If you ignore that advice, don’t try to symbolicate your backtraces in the context of the crashing process. Rather, record the info needed to symbolicate and then do your symbolication in a stable context. The required info is:

  • The addresses you want to symbolicate

  • The UUIDs and load addresses of all the Mach-O images in your process

You can get the load address by calling _dyld_get_image_header(0) i.e. in your c++ signal handler where you also log the backtrace and backtrace_symbols output.

And you’ve proving my first point here. None of the routines you mentioned — _dyld_get_image_header, backtrace and backtrace_symbols — are async signal safe.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Get Callstacks and demangle C++
 
 
Q