Bug 243746

Summary: llvm-libunwind does not provide an API useful in signal handler context
Product: Base System Reporter: Matthias Andree <mandree>
Component: binAssignee: freebsd-toolchain (Nobody) <toolchain>
Status: New ---    
Severity: Affects Only Me CC: cem, dchagin, emaste, jbeich, pi
Priority: --- Keywords: patch
Version: CURRENT   
Hardware: Any   
OS: Any   
See Also: https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=242798

Description Matthias Andree freebsd_committer freebsd_triage 2020-01-30 22:25:26 UTC
*** Description
Trying to debug e2fsprogs, which uses backtrace(), I did not see stack backtraces for a crasher.

I have then adapted a test program found on the net, which also does not find stack backtraces - running the same executable under gdb until it receives a provoked SIGSEGV yields a proper backtrace.

*** Received output:
Signal 11 in dump_trace - have 0 frames

*** Expected output SIMILAR TO (this is taken from the same program under Linux - only adapted to use int, not size_t, and omitting -lexecinfo because backtrace is part of GNU libc):
Signal in dump_trace - have 8 frames
./try-bt[0x401185]
/lib64/libc.so.6(+0x3c6b0)[0x7f951de3a6b0]
./try-bt(boom+0x10)[0x4011e0]
./try-bt(two+0xe)[0x4011f4]
./try-bt(one+0xe)[0x401205]
./try-bt(main+0x1d)[0x401225]
/lib64/libc.so.6(__libc_start_main+0xf3)[0x7f951de251a3]
./try-bt(_start+0x2e)[0x4010ae]



*** Program:

/* save as try-bt.c then compile with:
cc -rdynamic -fno-omit-frame-pointer -g -std=c99 -o try-bt try-bt.c -fno-inline -lexecinfo -lelf */
#include <execinfo.h>
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>

static void dump_trace(int sig) {
	size_t max_frames = 32;
	void *buffer[max_frames];
	size_t calls = backtrace(buffer, max_frames);
	fprintf(stderr, "Signal %d in dump_trace - have %zu frames\n", sig, calls);
	backtrace_symbols_fd(buffer, calls, 2);
	_Exit(EXIT_FAILURE);
}

void boom() {
	volatile char *a = 0;
	*a = 17;
}

void two() {boom(); }
void one() {two(); }

int main(void) {
	signal(SIGSEGV, dump_trace);
	one();
	exit(EXIT_SUCCESS);
}
/* END */
Comment 1 Conrad Meyer freebsd_committer freebsd_triage 2020-01-31 00:31:55 UTC
Yeah, our libunwind doesn't know how to backtrace out of a signal handler at this time.  I have a WIP patch to unwind starting from a `ucontext`, which signal handlers created with sigaction(2) can access, but I haven't had time to work on it for a while; it would also require slightly different code in the signal handler.
Comment 2 Conrad Meyer freebsd_committer freebsd_triage 2020-01-31 00:37:38 UTC
Here is the WIP: https://people.freebsd.org/~cem/libexecinfo.backtrace_ctx3.patch

It works on amd64 (not tested recently) and maybe i386 (untested) and does not have support for other architectures.  It is mostly missing tests, I think. Otherwise it just needs rebasing on the current tree, and eventually it will be nice to support non-x86 architectures.
Comment 3 Dmitry Chagin freebsd_committer freebsd_triage 2023-06-15 07:38:56 UTC
it would be nice to add something like https://reviews.llvm.org/rGc82deed6764cbc63966374baf9721331901ca958#change-9Mv5koDaVLbn