forked from OSchip/llvm-project
[Asan] Pack signal context into a structure
Differential Revision: http://reviews.llvm.org/D6148 llvm-svn: 222756
This commit is contained in:
parent
a3ec1a3267
commit
9b75b757de
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Reference in New Issue