Index: compiler-rt/trunk/lib/asan/asan_internal.h =================================================================== --- compiler-rt/trunk/lib/asan/asan_internal.h +++ compiler-rt/trunk/lib/asan/asan_internal.h @@ -62,6 +62,21 @@ class AsanThread; using __sanitizer::StackTrace; +struct SignalContext { + void *context; + uptr addr; + uptr pc; + uptr sp; + uptr bp; + + SignalContext(void *context, uptr addr, uptr pc, uptr sp, uptr bp) : + context(context), addr(addr), pc(pc), sp(sp), bp(bp) { + } + + // Creates signal context in a platform-specific manner. + static SignalContext Create(void *siginfo, void *context); +}; + void AsanInitFromRtl(); // asan_rtl.cc Index: compiler-rt/trunk/lib/asan/asan_posix.cc =================================================================== --- compiler-rt/trunk/lib/asan/asan_posix.cc +++ compiler-rt/trunk/lib/asan/asan_posix.cc @@ -32,19 +32,24 @@ namespace __asan { +SignalContext SignalContext::Create(void *siginfo, void *context) { + uptr addr = (uptr)((siginfo_t*)siginfo)->si_addr; + uptr pc, sp, bp; + GetPcSpBp(context, &pc, &sp, &bp); + return SignalContext(context, addr, pc, sp, bp); +} + 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. if (13 != internal_write(2, "ASAN:SIGSEGV\n", 13)) Die(); - uptr pc, sp, bp; - GetPcSpBp(context, &pc, &sp, &bp); + SignalContext sig = SignalContext::Create(siginfo, context); // Access at a reasonable offset above SP, or slightly below it (to account // for x86_64 or PowerPC redzone, ARM push of multiple registers, etc) is // probably a stack overflow. - bool IsStackAccess = addr + 512 > sp && addr < sp + 0xFFFF; + bool IsStackAccess = sig.addr + 512 > sig.sp && sig.addr < sig.sp + 0xFFFF; #if __powerpc__ // Large stack frames can be allocated with e.g. @@ -53,8 +58,8 @@ // If the store faults then sp will not have been updated, so test above // will not work, becase the fault address will be more than just "slightly" // below sp. - if (!IsStackAccess && IsAccessibleMemoryRange(pc, 4)) { - u32 inst = *(unsigned *)pc; + if (!IsStackAccess && IsAccessibleMemoryRange(sig.pc, 4)) { + u32 inst = *(unsigned *)sig.pc; u32 ra = (inst >> 16) & 0x1F; u32 opcd = inst >> 26; u32 xo = (inst >> 1) & 0x3FF; @@ -75,9 +80,9 @@ // then hitting the guard page or unmapped memory, like, for example, // unaligned memory access. if (IsStackAccess && (code == si_SEGV_MAPERR || code == si_SEGV_ACCERR)) - ReportStackOverflow(pc, sp, bp, context, addr); + ReportStackOverflow(sig); else - ReportSIGSEGV("SEGV", pc, sp, bp, context, addr); + ReportSIGSEGV("SEGV", sig); } // ---------------------- TSD ---------------- {{{1 Index: compiler-rt/trunk/lib/asan/asan_report.h =================================================================== --- compiler-rt/trunk/lib/asan/asan_report.h +++ compiler-rt/trunk/lib/asan/asan_report.h @@ -52,10 +52,8 @@ void DescribeThread(AsanThreadContext *context); // Different kinds of error reports. -void NORETURN - ReportStackOverflow(uptr pc, uptr sp, uptr bp, void *context, uptr addr); -void NORETURN ReportSIGSEGV(const char *description, uptr pc, uptr sp, uptr bp, - void *context, uptr addr); +void NORETURN ReportStackOverflow(const SignalContext &sig); +void NORETURN ReportSIGSEGV(const char *description, const SignalContext &sig); void NORETURN ReportNewDeleteSizeMismatch(uptr addr, uptr delete_size, BufferedStackTrace *free_stack); void NORETURN ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack); Index: compiler-rt/trunk/lib/asan/asan_report.cc =================================================================== --- compiler-rt/trunk/lib/asan/asan_report.cc +++ compiler-rt/trunk/lib/asan/asan_report.cc @@ -647,38 +647,37 @@ } }; -void ReportStackOverflow(uptr pc, uptr sp, uptr bp, void *context, uptr addr) { +void ReportStackOverflow(const SignalContext &sig) { ScopedInErrorReport in_report; Decorator d; Printf("%s", d.Warning()); Report( "ERROR: AddressSanitizer: stack-overflow on address %p" " (pc %p bp %p sp %p T%d)\n", - (void *)addr, (void *)pc, (void *)bp, (void *)sp, + (void *)sig.addr, (void *)sig.pc, (void *)sig.bp, (void *)sig.sp, GetCurrentTidOrInvalid()); Printf("%s", d.EndWarning()); - GET_STACK_TRACE_SIGNAL(pc, bp, context); + GET_STACK_TRACE_SIGNAL(sig); stack.Print(); ReportErrorSummary("stack-overflow", &stack); } -void ReportSIGSEGV(const char *description, uptr pc, uptr sp, uptr bp, - void *context, uptr addr) { +void ReportSIGSEGV(const char *description, const SignalContext &sig) { ScopedInErrorReport in_report; Decorator d; Printf("%s", d.Warning()); Report( "ERROR: AddressSanitizer: %s on unknown address %p" " (pc %p bp %p sp %p T%d)\n", - description, (void *)addr, (void *)pc, (void *)bp, (void *)sp, - GetCurrentTidOrInvalid()); - if (pc < GetPageSizeCached()) { + description, (void *)sig.addr, (void *)sig.pc, (void *)sig.bp, + (void *)sig.sp, GetCurrentTidOrInvalid()); + if (sig.pc < GetPageSizeCached()) { Report("Hint: pc points to the zero page.\n"); } Printf("%s", d.EndWarning()); - GET_STACK_TRACE_SIGNAL(pc, bp, context); + GET_STACK_TRACE_SIGNAL(sig); stack.Print(); - MaybeDumpInstructionBytes(pc); + MaybeDumpInstructionBytes(sig.pc); Printf("AddressSanitizer can not provide additional info.\n"); ReportErrorSummary("SEGV", &stack); } Index: compiler-rt/trunk/lib/asan/asan_stack.h =================================================================== --- compiler-rt/trunk/lib/asan/asan_stack.h +++ compiler-rt/trunk/lib/asan/asan_stack.h @@ -78,9 +78,10 @@ GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, pc, bp, 0, \ common_flags()->fast_unwind_on_fatal) -#define GET_STACK_TRACE_SIGNAL(pc, bp, context) \ +#define GET_STACK_TRACE_SIGNAL(sig) \ BufferedStackTrace stack; \ - GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, pc, bp, context, \ + GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, \ + (sig).pc, (sig).bp, (sig).context, \ common_flags()->fast_unwind_on_fatal) #define GET_STACK_TRACE_FATAL_HERE \ Index: compiler-rt/trunk/lib/asan/asan_win.cc =================================================================== --- compiler-rt/trunk/lib/asan/asan_win.cc +++ compiler-rt/trunk/lib/asan/asan_win.cc @@ -89,15 +89,26 @@ static LPTOP_LEVEL_EXCEPTION_FILTER default_seh_handler; -static long WINAPI SEHHandler(EXCEPTION_POINTERS *info) { - EXCEPTION_RECORD *exception_record = info->ExceptionRecord; - CONTEXT *context = info->ContextRecord; +SignalContext SignalContext::Create(void *siginfo, void *context) { + EXCEPTION_RECORD *exception_record = (EXCEPTION_RECORD*)siginfo; + CONTEXT *context_record = (CONTEXT*)context; + uptr pc = (uptr)exception_record->ExceptionAddress; #ifdef _WIN64 - uptr bp = (uptr)context->Rbp, sp = (uptr)context->Rsp; + uptr bp = (uptr)context_record->Rbp; + uptr sp = (uptr)context_record->Rsp; #else - uptr bp = (uptr)context->Ebp, sp = (uptr)context->Esp; + uptr bp = (uptr)context_record->Ebp; + uptr sp = (uptr)context_record->Esp; #endif + uptr access_addr = exception_record->ExceptionInformation[1]; + + return SignalContext(context, access_addr, pc, sp, bp); +} + +static long WINAPI SEHHandler(EXCEPTION_POINTERS *info) { + EXCEPTION_RECORD *exception_record = info->ExceptionRecord; + CONTEXT *context = info->ContextRecord; if (exception_record->ExceptionCode == EXCEPTION_ACCESS_VIOLATION || exception_record->ExceptionCode == EXCEPTION_IN_PAGE_ERROR) { @@ -105,8 +116,8 @@ (exception_record->ExceptionCode == EXCEPTION_ACCESS_VIOLATION) ? "access-violation" : "in-page-error"; - uptr access_addr = exception_record->ExceptionInformation[1]; - ReportSIGSEGV(description, pc, sp, bp, context, access_addr); + SignalContext sig = SignalContext::Create(exception_record, context); + ReportSIGSEGV(description, sig); } // FIXME: Handle EXCEPTION_STACK_OVERFLOW here.