summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/asan/asan_internal.h15
-rw-r--r--lib/asan/asan_posix.cc21
-rw-r--r--lib/asan/asan_report.cc19
-rw-r--r--lib/asan/asan_report.h6
-rw-r--r--lib/asan/asan_stack.h5
-rw-r--r--lib/asan/asan_win.cc25
6 files changed, 60 insertions, 31 deletions
diff --git a/lib/asan/asan_internal.h b/lib/asan/asan_internal.h
index 3771a0134..65d4a47d3 100644
--- a/lib/asan/asan_internal.h
+++ b/lib/asan/asan_internal.h
@@ -62,6 +62,21 @@ namespace __asan {
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
diff --git a/lib/asan/asan_posix.cc b/lib/asan/asan_posix.cc
index c910e2340..ad31458df 100644
--- a/lib/asan/asan_posix.cc
+++ b/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 @@ void AsanOnSIGSEGV(int, void *siginfo, void *context) {
// 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 @@ void AsanOnSIGSEGV(int, void *siginfo, void *context) {
// 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
diff --git a/lib/asan/asan_report.cc b/lib/asan/asan_report.cc
index 7b56c9b77..0fb502761 100644
--- a/lib/asan/asan_report.cc
+++ b/lib/asan/asan_report.cc
@@ -647,38 +647,37 @@ class ScopedInErrorReport {
}
};
-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);
}
diff --git a/lib/asan/asan_report.h b/lib/asan/asan_report.h
index fd65bad95..029c914b8 100644
--- a/lib/asan/asan_report.h
+++ b/lib/asan/asan_report.h
@@ -52,10 +52,8 @@ void DescribeAddress(uptr addr, uptr access_size);
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);
diff --git a/lib/asan/asan_stack.h b/lib/asan/asan_stack.h
index 8610ee43d..a99525621 100644
--- a/lib/asan/asan_stack.h
+++ b/lib/asan/asan_stack.h
@@ -78,9 +78,10 @@ void GetStackTraceWithPcBpAndContext(BufferedStackTrace *stack, uptr max_depth,
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 \
diff --git a/lib/asan/asan_win.cc b/lib/asan/asan_win.cc
index 5303d1bd1..4f02b022f 100644
--- a/lib/asan/asan_win.cc
+++ b/lib/asan/asan_win.cc
@@ -89,15 +89,26 @@ void AsanOnSIGSEGV(int, void *siginfo, void *context) {
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 @@ static long WINAPI SEHHandler(EXCEPTION_POINTERS *info) {
(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.