Index: lib/asan/asan_flags.h =================================================================== --- lib/asan/asan_flags.h +++ lib/asan/asan_flags.h @@ -71,6 +71,8 @@ int sleep_before_dying; // If set, registers ASan custom segv handler. bool handle_segv; + // If set, registers ASan custom abrt handler. + bool handle_abrt; // If set, allows user register segv handler even if ASan registers one. bool allow_user_segv_handler; // If set, uses alternate stack for signal handling. Index: lib/asan/asan_linux.cc =================================================================== --- lib/asan/asan_linux.cc +++ lib/asan/asan_linux.cc @@ -95,7 +95,8 @@ } bool AsanInterceptsSignal(int signum) { - return signum == SIGSEGV && flags()->handle_segv; + return (signum == SIGSEGV && flags()->handle_segv) || + (signum == SIGABRT && flags()->handle_abrt); } void AsanPlatformThreadInit() { Index: lib/asan/asan_mapping.h =================================================================== --- lib/asan/asan_mapping.h +++ lib/asan/asan_mapping.h @@ -216,6 +216,15 @@ return false; } +static inline void UnmapShadowMappings() { + if (kMidMemBeg) { + UnmapOrDie((void*)kLowShadowBeg, kMidMemBeg - kLowShadowBeg); + UnmapOrDie((void*)kMidMemEnd, kHighShadowEnd - kMidMemEnd); + } else { + UnmapOrDie((void*)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg); + } +} + // Must be after all calls to PROFILE_ASAN_MAPPING(). static const uptr kAsanMappingProfileSize = __LINE__; Index: lib/asan/asan_posix.cc =================================================================== --- lib/asan/asan_posix.cc +++ lib/asan/asan_posix.cc @@ -58,6 +58,38 @@ ReportSIGSEGV(pc, sp, bp, addr); } +// Invoke the default signal handler. +void InvokeDefaultSignalHandler(int signal_number) { + struct sigaction sig_action; + REAL(memset)(&sig_action, 0, sizeof(sig_action)); + sigemptyset(&sig_action.sa_mask); + sig_action.sa_handler = SIG_DFL; + if (flags()->use_sigaltstack) sig_action.sa_flags |= SA_ONSTACK; + CHECK_EQ(0, REAL(sigaction)(signal_number, &sig_action, NULL)); +} + +static void ASAN_OnSIGABRT(int, siginfo_t *siginfo, void *context) { + static atomic_uint32_t num_calls; + if (atomic_fetch_add(&num_calls, 1, memory_order_relaxed) != 0) { + Report("Reentrant call into SIGABRT handler"); + // we may end up with a reentrant call if the munmap() calls + // below fail. In that case, we should ignore the reentrant + // failure since we're in the process of exiting anyway. + return; + } + + // Write the first message using the bullet-proof write. + if (13 != internal_write(2, "ASAN:SIGABRT\n", 13)) Die(); + uptr pc, sp, bp; + GetPcSpBp(context, &pc, &sp, &bp); + ReportSIGABRT(pc, sp, bp); + + // Unmap the shadow pages so that a core dump is reasonable, + // then call through to the original SIGABRT handler + UnmapShadowMappings(); + InvokeDefaultSignalHandler(SIGABRT); +} + void SetAlternateSignalStack() { stack_t altstack, oldstack; CHECK_EQ(0, sigaltstack(0, &oldstack)); @@ -94,6 +126,7 @@ if (flags()->use_sigaltstack) SetAlternateSignalStack(); MaybeInstallSigaction(SIGSEGV, ASAN_OnSIGSEGV); MaybeInstallSigaction(SIGBUS, ASAN_OnSIGSEGV); + MaybeInstallSigaction(SIGABRT, ASAN_OnSIGABRT); } // ---------------------- TSD ---------------- {{{1 Index: lib/asan/asan_report.h =================================================================== --- lib/asan/asan_report.h +++ lib/asan/asan_report.h @@ -33,6 +33,7 @@ // Different kinds of error reports. void NORETURN ReportSIGSEGV(uptr pc, uptr sp, uptr bp, uptr addr); +void ReportSIGABRT(uptr pc, uptr sp, uptr bp); void NORETURN ReportDoubleFree(uptr addr, StackTrace *stack); void NORETURN ReportFreeNotMalloced(uptr addr, StackTrace *stack); void NORETURN ReportAllocTypeMismatch(uptr addr, StackTrace *stack, Index: lib/asan/asan_report.cc =================================================================== --- lib/asan/asan_report.cc +++ lib/asan/asan_report.cc @@ -523,6 +523,19 @@ ReportSummary("SEGV", &stack); } +void ReportSIGABRT(uptr pc, uptr sp, uptr bp) { + Decorator d; + Printf("%s", d.Warning()); + Report("ERROR: AddressSanitizer: ABRT" + " (pc %p sp %p bp %p T%d)\n", + (void*)pc, (void*)sp, (void*)bp, + GetCurrentTidOrInvalid()); + Printf("%s", d.EndWarning()); + GET_STACK_TRACE_FATAL(pc, bp); + PrintStack(&stack); + ReportSummary("ABRT", &stack); +} + void ReportDoubleFree(uptr addr, StackTrace *stack) { ScopedInErrorReport in_report; Decorator d; Index: lib/asan/asan_rtl.cc =================================================================== --- lib/asan/asan_rtl.cc +++ lib/asan/asan_rtl.cc @@ -40,12 +40,7 @@ SleepForSeconds(flags()->sleep_before_dying); } if (flags()->unmap_shadow_on_exit) { - if (kMidMemBeg) { - UnmapOrDie((void*)kLowShadowBeg, kMidMemBeg - kLowShadowBeg); - UnmapOrDie((void*)kMidMemEnd, kHighShadowEnd - kMidMemEnd); - } else { - UnmapOrDie((void*)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg); - } + UnmapShadowMappings(); } if (death_callback) death_callback(); @@ -107,6 +102,7 @@ ParseFlag(str, &f->allow_user_poisoning, "allow_user_poisoning"); ParseFlag(str, &f->sleep_before_dying, "sleep_before_dying"); ParseFlag(str, &f->handle_segv, "handle_segv"); + ParseFlag(str, &f->handle_abrt, "handle_abrt"); ParseFlag(str, &f->allow_user_segv_handler, "allow_user_segv_handler"); ParseFlag(str, &f->use_sigaltstack, "use_sigaltstack"); ParseFlag(str, &f->check_malloc_usable_size, "check_malloc_usable_size"); @@ -152,6 +148,7 @@ f->allow_user_poisoning = true; f->sleep_before_dying = 0; f->handle_segv = ASAN_NEEDS_SEGV; + f->handle_abrt = ASAN_NEEDS_SEGV; f->allow_user_segv_handler = false; f->use_sigaltstack = false; f->check_malloc_usable_size = true;