[Sanitizers] Enable stack traces on FreeBSD

Differential Revision: http://reviews.llvm.org/D6086

llvm-svn: 221595
This commit is contained in:
Viktor Kutuzov 2014-11-10 15:22:04 +00:00
parent 156ffbc4c0
commit dc6cbfe859
4 changed files with 34 additions and 5 deletions

View File

@ -33,6 +33,7 @@
namespace __asan {
void AsanOnSIGSEGV(int, void *siginfo, void *context) {
ScopedDeadlySignal signal_scope(GetCurrentThread());
uptr addr = (uptr)((siginfo_t*)siginfo)->si_addr;
int code = (int)((siginfo_t*)siginfo)->si_code;
// Write the first message using the bullet-proof write.

View File

@ -35,6 +35,10 @@ void GetStackTraceWithPcBpAndContext(BufferedStackTrace *stack, uptr max_depth,
stack->size = 0;
if (LIKELY(asan_inited)) {
if ((t = GetCurrentThread()) && !t->isUnwinding()) {
// On FreeBSD the slow unwinding that leverages _Unwind_Backtrace()
// yields the call stack of the signal's handler and not of the code
// that raised the signal (as it does on Linux).
if (SANITIZER_FREEBSD && t->isInDeadlySignal()) fast = true;
uptr stack_top = t->stack_top();
uptr stack_bottom = t->stack_bottom();
ScopedUnwinding unwind_scope(t);

View File

@ -108,6 +108,10 @@ class AsanThread {
bool isUnwinding() const { return unwinding_; }
void setUnwinding(bool b) { unwinding_ = b; }
// True if we are in a deadly signal handler.
bool isInDeadlySignal() const { return in_deadly_signal_; }
void setInDeadlySignal(bool b) { in_deadly_signal_ = b; }
AsanThreadLocalMallocStorage &malloc_storage() { return malloc_storage_; }
AsanStats &stats() { return stats_; }
@ -133,6 +137,7 @@ class AsanThread {
AsanThreadLocalMallocStorage malloc_storage_;
AsanStats stats_;
bool unwinding_;
bool in_deadly_signal_;
};
// ScopedUnwinding is a scope for stacktracing member of a context
@ -147,6 +152,20 @@ class ScopedUnwinding {
AsanThread *thread;
};
// ScopedDeadlySignal is a scope for handling deadly signals.
class ScopedDeadlySignal {
public:
explicit ScopedDeadlySignal(AsanThread *t) : thread(t) {
if (thread) thread->setInDeadlySignal(true);
}
~ScopedDeadlySignal() {
if (thread) thread->setInDeadlySignal(false);
}
private:
AsanThread *thread;
};
struct CreateThreadContextArgs {
AsanThread *thread;
StackTrace *stack;

View File

@ -29,6 +29,15 @@ static const uptr kStackTraceMax = 256;
# define SANITIZER_CAN_FAST_UNWIND 1
#endif
// Fast unwind is the only option on Mac for now; we will need to
// revisit this macro when slow unwind works on Mac, see
// https://code.google.com/p/address-sanitizer/issues/detail?id=137
#if SANITIZER_MAC
# define SANITIZER_CAN_SLOW_UNWIND 0
#else
# define SANITIZER_CAN_SLOW_UNWIND 1
#endif
struct StackTrace {
const uptr *trace;
uptr size;
@ -40,13 +49,9 @@ struct StackTrace {
void Print() const;
static bool WillUseFastUnwind(bool request_fast_unwind) {
// Check if fast unwind is available. Fast unwind is the only option on Mac.
// It is also the only option on FreeBSD as the slow unwinding that
// leverages _Unwind_Backtrace() yields the call stack of the signal's
// handler and not of the code that raised the signal (as it does on Linux).
if (!SANITIZER_CAN_FAST_UNWIND)
return false;
else if (SANITIZER_MAC != 0 || SANITIZER_FREEBSD != 0)
else if (!SANITIZER_CAN_SLOW_UNWIND)
return true;
return request_fast_unwind;
}