[Asan] Pack signal context into a structure

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

llvm-svn: 222756
This commit is contained in:
Viktor Kutuzov 2014-11-25 13:00:21 +00:00
parent a3ec1a3267
commit 9b75b757de
6 changed files with 61 additions and 32 deletions

View File

@ -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

View File

@ -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

View File

@ -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);
}

View File

@ -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);

View File

@ -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 \

View File

@ -89,15 +89,26 @@ void AsanOnSIGSEGV(int, void *siginfo, void *context) {
static LPTOP_LEVEL_EXCEPTION_FILTER default_seh_handler;
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_record->Rbp;
uptr sp = (uptr)context_record->Rsp;
#else
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;
uptr pc = (uptr)exception_record->ExceptionAddress;
#ifdef _WIN64
uptr bp = (uptr)context->Rbp, sp = (uptr)context->Rsp;
#else
uptr bp = (uptr)context->Ebp, sp = (uptr)context->Esp;
#endif
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.