backward-cpp
backward-cpp copied to clipboard
Any hints as to what's needed for a PR to work on OSX
Tinkering around and would like to get stack traces on osx. binutils is in homebrew and I found argp-standalone in homebrew (required by elfutils), then I got elfutils to not complain about GNU99 support, guessing that this is an issue in elfutils?
you need two things to get the traces:
- first a way to "walk the stack", which should be provided by gcc/clang under the unwind api. If that works, you should at least get the bare stacktrace. ie: a list of addresses.
- then you need a way to map the addresses to the debug info of your executable. This is where elfutils/bfd are coming into play on linux. I have no idea if this works the same on macosx.
So i was able to do something like this to get backtraces on sigs...
void* callstack[128];
size_t size = backtrace(callstack, 128);
char** symbols = backtrace_symbols(callstack, size);
Then loop over the symbols, converting the symbols (after a little regexing) like leveraging abi...
char* name = abi::__cxa_demangle(s.c_str(), NULL, NULL, &status);
The problem is, the general solution (as i have found so far) for mapping addresses to files is a linux specific tool (addr2line) which depends on a bunch of crazy things to parse drawf. However, i recently found this which seems to be able to parse DWv4 files. So maybe it's possible to bypass elfutils using this (which seems to be able to map the line numbers). Im definitely going down a rabbit hole, considering how awesome lldb::gui is and how much more powerful core dumps are, but this is really fun :)
~~does libbfd is available on macox? because its more accurate than libelfutils anyway.~~
Does libdw is available on macosx? because its more accurate than libbfd from the binutils anyway.
Also, just to clear things up: libunwind != unwind API. backward uses the unwind API from gcc/clang. libunwind is an advanced library for walking the stack (with way more features than backward).
I'm fairly certain that none of the dwarf-parsing libraries will work on OS X because they all assume ELF-executable format and OS X uses Mach-O instead.
I've been able to get a backtrace_symbols-based version of this working and will submit a PR for it shortly. It's not nearly as pretty as the Linux versions can be, but it's more useful than the default output.
Sample:
$ ./test_stacktrace
-- running test case: minitrace
Stack trace (most recent call last) in thread 6837446:
#6 Object "???", at 0x1, in 0x0 + 1
#5 Object "libdyld.dylib", at 0x7fff98da7235, in start + 1
#4 Object "libtest_main.dylib", at 0x10b5e8912, in main + 578
#3 Object "libtest_main.dylib", at 0x10b5e8375, in run_test(test::TestBase&) + 85
#2 Object "libtest_main.dylib", at 0x10b5e8555, in test::TestBase::run() + 21
#1 Object "test_stacktrace", at 0x10b5b4d1b, in TEST_minitrace::do_test() + 43
#0 Object "test_stacktrace", at 0x10b5b4bac, in collect_trace(backward::StackTrace&) + 28
-- test case success: minitrace
-- running test case: smalltrace
Stack trace (most recent call last) in thread 6837447:
#9 Object "???", at 0x1, in 0x0 + 1
#8 Object "libdyld.dylib", at 0x7fff98da7235, in start + 1
#7 Object "libtest_main.dylib", at 0x10b5e8912, in main + 578
#6 Object "libtest_main.dylib", at 0x10b5e8375, in run_test(test::TestBase&) + 85
#5 Object "libtest_main.dylib", at 0x10b5e8555, in test::TestBase::run() + 21
#4 Object "test_stacktrace", at 0x10b5b511b, in TEST_smalltrace::do_test() + 43
#3 Object "test_stacktrace", at 0x10b5b50c5, in a(backward::StackTrace&) + 21
#2 Object "test_stacktrace", at 0x10b5b50a5, in b(backward::StackTrace&) + 21
#1 Object "test_stacktrace", at 0x10b5b5085, in c(backward::StackTrace&) + 21
#0 Object "test_stacktrace", at 0x10b5b505c, in d(backward::StackTrace&) + 28
-- test case success: smalltrace
-- tests passing: 2/2 (100%)
Nice work. I saw your PR. And is the copy paste is mostly renaming. We can probably add some macro to represent the common parts. I don't have much time right now. But I am definitely keeping an eye on your work.
For the mac, when I enable BACKWARD_HAS_BACKTRACE_SYMBOL=1, the stack traces disappear entirely, even though I am linking in libbacktrace (-lbacktrace, libraries present, libbacktrace.dylib, libbacktrace.0.dylib). I'm hoping to see the ultimate output like I do on linux for this amazing library. Any ideas?