forked from OSchip/llvm-project
[asan] Reify ErrorDeadlySignal
Summary: Keep reifying other errors. Reviewers: kcc, samsonov Subscribers: llvm-commits, kubabrecka Differential Revision: https://reviews.llvm.org/D23873 llvm-svn: 280930
This commit is contained in:
parent
753c18f5c0
commit
1989be7cf0
|
@ -13,7 +13,9 @@
|
|||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "asan_errors.h"
|
||||
#include <signal.h>
|
||||
#include "asan_descriptions.h"
|
||||
#include "asan_report.h"
|
||||
#include "asan_stack.h"
|
||||
|
||||
namespace __asan {
|
||||
|
@ -34,6 +36,50 @@ void ErrorStackOverflow::Print() {
|
|||
ReportErrorSummary("stack-overflow", &stack);
|
||||
}
|
||||
|
||||
static void MaybeDumpInstructionBytes(uptr pc) {
|
||||
if (!flags()->dump_instruction_bytes || (pc < GetPageSizeCached())) return;
|
||||
InternalScopedString str(1024);
|
||||
str.append("First 16 instruction bytes at pc: ");
|
||||
if (IsAccessibleMemoryRange(pc, 16)) {
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
PrintMemoryByte(&str, "", ((u8 *)pc)[i], /*in_shadow*/ false, " ");
|
||||
}
|
||||
str.append("\n");
|
||||
} else {
|
||||
str.append("unaccessible\n");
|
||||
}
|
||||
Report("%s", str.data());
|
||||
}
|
||||
|
||||
void ErrorDeadlySignal::Print() {
|
||||
Decorator d;
|
||||
Printf("%s", d.Warning());
|
||||
const char *description = DescribeSignalOrException(signo);
|
||||
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, tid);
|
||||
Printf("%s", d.EndWarning());
|
||||
if (pc < GetPageSizeCached()) Report("Hint: pc points to the zero page.\n");
|
||||
if (is_memory_access) {
|
||||
const char *access_type =
|
||||
write_flag == SignalContext::WRITE
|
||||
? "WRITE"
|
||||
: (write_flag == SignalContext::READ ? "READ" : "UNKNOWN");
|
||||
Report("The signal is caused by a %s memory access.\n", access_type);
|
||||
if (addr < GetPageSizeCached())
|
||||
Report("Hint: address points to the zero page.\n");
|
||||
}
|
||||
scariness.Print();
|
||||
BufferedStackTrace stack;
|
||||
GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, pc, bp, context,
|
||||
common_flags()->fast_unwind_on_fatal);
|
||||
stack.Print();
|
||||
MaybeDumpInstructionBytes(pc);
|
||||
Printf("AddressSanitizer can not provide additional info.\n");
|
||||
ReportErrorSummary(description, &stack);
|
||||
}
|
||||
|
||||
void ErrorDoubleFree::Print() {
|
||||
Decorator d;
|
||||
Printf("%s", d.Warning());
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "asan_descriptions.h"
|
||||
#include "asan_scariness_score.h"
|
||||
#include "sanitizer_common/sanitizer_common.h"
|
||||
|
||||
namespace __asan {
|
||||
|
||||
|
@ -44,6 +45,47 @@ struct ErrorStackOverflow : ErrorBase {
|
|||
void Print();
|
||||
};
|
||||
|
||||
struct ErrorDeadlySignal : ErrorBase {
|
||||
u32 tid;
|
||||
uptr addr, pc, bp, sp;
|
||||
int signo;
|
||||
SignalContext::WriteFlag write_flag;
|
||||
bool is_memory_access;
|
||||
// ErrorDeadlySignal never owns the context.
|
||||
void *context;
|
||||
// VS2013 doesn't implement unrestricted unions, so we need a trivial default
|
||||
// constructor
|
||||
ErrorDeadlySignal() = default;
|
||||
ErrorDeadlySignal(int signo_, const SignalContext &sig, u32 tid_)
|
||||
: tid(tid_),
|
||||
addr(sig.addr),
|
||||
pc(sig.pc),
|
||||
bp(sig.bp),
|
||||
sp(sig.sp),
|
||||
signo(signo_),
|
||||
write_flag(sig.write_flag),
|
||||
is_memory_access(sig.is_memory_access),
|
||||
context(sig.context) {
|
||||
scariness.Clear();
|
||||
if (is_memory_access) {
|
||||
if (addr < GetPageSizeCached()) {
|
||||
scariness.Scare(10, "null-deref");
|
||||
} else if (addr == pc) {
|
||||
scariness.Scare(60, "wild-jump");
|
||||
} else if (write_flag == SignalContext::WRITE) {
|
||||
scariness.Scare(30, "wild-addr-write");
|
||||
} else if (write_flag == SignalContext::READ) {
|
||||
scariness.Scare(20, "wild-addr-read");
|
||||
} else {
|
||||
scariness.Scare(25, "wild-addr");
|
||||
}
|
||||
} else {
|
||||
scariness.Scare(10, "signal");
|
||||
}
|
||||
}
|
||||
void Print();
|
||||
};
|
||||
|
||||
struct ErrorDoubleFree : ErrorBase {
|
||||
u32 tid;
|
||||
HeapAddressDescription addr_description;
|
||||
|
@ -84,6 +126,7 @@ struct ErrorNewDeleteSizeMismatch : ErrorBase {
|
|||
enum ErrorKind {
|
||||
kErrorKindInvalid = 0,
|
||||
kErrorKindStackOverflow,
|
||||
kErrorKindDeadlySignal,
|
||||
kErrorKindDoubleFree,
|
||||
kErrorKindNewDeleteSizeMismatch,
|
||||
};
|
||||
|
@ -97,6 +140,7 @@ struct ErrorDescription {
|
|||
// add a lot of code and the benefit wouldn't be that big.
|
||||
union {
|
||||
ErrorStackOverflow stack_overflow;
|
||||
ErrorDeadlySignal deadly_signal;
|
||||
ErrorDoubleFree double_free;
|
||||
ErrorNewDeleteSizeMismatch new_delete_size_mismatch;
|
||||
};
|
||||
|
@ -104,6 +148,9 @@ struct ErrorDescription {
|
|||
ErrorDescription(const ErrorStackOverflow &e) // NOLINT
|
||||
: kind(kErrorKindStackOverflow),
|
||||
stack_overflow(e) {}
|
||||
ErrorDescription(const ErrorDeadlySignal &e) // NOLINT
|
||||
: kind(kErrorKindDeadlySignal),
|
||||
deadly_signal(e) {}
|
||||
ErrorDescription(const ErrorDoubleFree &e) // NOLINT
|
||||
: kind(kErrorKindDoubleFree),
|
||||
double_free(e) {}
|
||||
|
@ -117,6 +164,9 @@ struct ErrorDescription {
|
|||
case kErrorKindStackOverflow:
|
||||
stack_overflow.Print();
|
||||
return;
|
||||
case kErrorKindDeadlySignal:
|
||||
deadly_signal.Print();
|
||||
return;
|
||||
case kErrorKindDoubleFree:
|
||||
double_free.Print();
|
||||
return;
|
||||
|
|
|
@ -65,6 +65,9 @@ void AsanInitFromRtl();
|
|||
// asan_win.cc
|
||||
void InitializePlatformExceptionHandlers();
|
||||
|
||||
// asan_win.cc / asan_posix.cc
|
||||
const char *DescribeSignalOrException(int signo);
|
||||
|
||||
// asan_rtl.cc
|
||||
void NORETURN ShowStatsAndAbort();
|
||||
|
||||
|
|
|
@ -33,6 +33,17 @@
|
|||
|
||||
namespace __asan {
|
||||
|
||||
const char *DescribeSignalOrException(int signo) {
|
||||
switch (signo) {
|
||||
case SIGFPE:
|
||||
return "FPE";
|
||||
case SIGILL:
|
||||
return "ILL";
|
||||
default:
|
||||
return "SEGV";
|
||||
}
|
||||
}
|
||||
|
||||
void AsanOnDeadlySignal(int signo, void *siginfo, void *context) {
|
||||
ScopedDeadlySignal signal_scope(GetCurrentThread());
|
||||
int code = (int)((siginfo_t*)siginfo)->si_code;
|
||||
|
@ -84,14 +95,8 @@ void AsanOnDeadlySignal(int signo, void *siginfo, void *context) {
|
|||
// unaligned memory access.
|
||||
if (IsStackAccess && (code == si_SEGV_MAPERR || code == si_SEGV_ACCERR))
|
||||
ReportStackOverflow(sig);
|
||||
else if (signo == SIGFPE)
|
||||
ReportDeadlySignal("FPE", sig);
|
||||
else if (signo == SIGILL)
|
||||
ReportDeadlySignal("ILL", sig);
|
||||
else if (signo == SIGABRT)
|
||||
ReportDeadlySignal("ABRT", sig);
|
||||
else
|
||||
ReportDeadlySignal("SEGV", sig);
|
||||
ReportDeadlySignal(signo, sig);
|
||||
}
|
||||
|
||||
// ---------------------- TSD ---------------- {{{1
|
||||
|
|
|
@ -69,8 +69,8 @@ void AppendToErrorMessageBuffer(const char *buffer) {
|
|||
|
||||
// ---------------------- Helper functions ----------------------- {{{1
|
||||
|
||||
static void PrintMemoryByte(InternalScopedString *str, const char *before,
|
||||
u8 byte, bool in_shadow, const char *after = "\n") {
|
||||
void PrintMemoryByte(InternalScopedString *str, const char *before, u8 byte,
|
||||
bool in_shadow, const char *after) {
|
||||
Decorator d;
|
||||
str->append("%s%s%x%x%s%s", before,
|
||||
in_shadow ? d.ShadowByte(byte) : d.MemoryByte(),
|
||||
|
@ -135,22 +135,6 @@ static void PrintLegend(InternalScopedString *str) {
|
|||
PrintShadowByte(str, " Right alloca redzone: ", kAsanAllocaRightMagic);
|
||||
}
|
||||
|
||||
void MaybeDumpInstructionBytes(uptr pc) {
|
||||
if (!flags()->dump_instruction_bytes || (pc < GetPageSizeCached()))
|
||||
return;
|
||||
InternalScopedString str(1024);
|
||||
str.append("First 16 instruction bytes at pc: ");
|
||||
if (IsAccessibleMemoryRange(pc, 16)) {
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
PrintMemoryByte(&str, "", ((u8 *)pc)[i], /*in_shadow*/false, " ");
|
||||
}
|
||||
str.append("\n");
|
||||
} else {
|
||||
str.append("unaccessible\n");
|
||||
}
|
||||
Report("%s", str.data());
|
||||
}
|
||||
|
||||
static void PrintShadowMemoryForAddress(uptr addr) {
|
||||
if (!AddrIsInMem(addr)) return;
|
||||
uptr shadow_addr = MemToShadow(addr);
|
||||
|
@ -344,46 +328,10 @@ void ReportStackOverflow(const SignalContext &sig) {
|
|||
in_report.ReportError(error);
|
||||
}
|
||||
|
||||
void ReportDeadlySignal(const char *description, const SignalContext &sig) {
|
||||
void ReportDeadlySignal(int signo, const SignalContext &sig) {
|
||||
ScopedInErrorReport in_report(/*report*/ nullptr, /*fatal*/ true);
|
||||
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 *)sig.addr, (void *)sig.pc, (void *)sig.bp,
|
||||
(void *)sig.sp, GetCurrentTidOrInvalid());
|
||||
Printf("%s", d.EndWarning());
|
||||
ScarinessScore SS;
|
||||
if (sig.pc < GetPageSizeCached())
|
||||
Report("Hint: pc points to the zero page.\n");
|
||||
if (sig.is_memory_access) {
|
||||
const char *access_type =
|
||||
sig.write_flag == SignalContext::WRITE
|
||||
? "WRITE"
|
||||
: (sig.write_flag == SignalContext::READ ? "READ" : "UNKNOWN");
|
||||
Report("The signal is caused by a %s memory access.\n", access_type);
|
||||
if (sig.addr < GetPageSizeCached()) {
|
||||
Report("Hint: address points to the zero page.\n");
|
||||
SS.Scare(10, "null-deref");
|
||||
} else if (sig.addr == sig.pc) {
|
||||
SS.Scare(60, "wild-jump");
|
||||
} else if (sig.write_flag == SignalContext::WRITE) {
|
||||
SS.Scare(30, "wild-addr-write");
|
||||
} else if (sig.write_flag == SignalContext::READ) {
|
||||
SS.Scare(20, "wild-addr-read");
|
||||
} else {
|
||||
SS.Scare(25, "wild-addr");
|
||||
}
|
||||
} else {
|
||||
SS.Scare(10, "signal");
|
||||
}
|
||||
SS.Print();
|
||||
GET_STACK_TRACE_SIGNAL(sig);
|
||||
stack.Print();
|
||||
MaybeDumpInstructionBytes(sig.pc);
|
||||
Printf("AddressSanitizer can not provide additional info.\n");
|
||||
ReportErrorSummary(description, &stack);
|
||||
ErrorDeadlySignal error(signo, sig, GetCurrentTidOrInvalid());
|
||||
in_report.ReportError(error);
|
||||
}
|
||||
|
||||
void ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack) {
|
||||
|
|
|
@ -42,6 +42,9 @@ const char *MaybeDemangleGlobalName(const char *name);
|
|||
void PrintGlobalNameIfASCII(InternalScopedString *str, const __asan_global &g);
|
||||
void PrintGlobalLocation(InternalScopedString *str, const __asan_global &g);
|
||||
|
||||
void PrintMemoryByte(InternalScopedString *str, const char *before, u8 byte,
|
||||
bool in_shadow, const char *after = "\n");
|
||||
|
||||
// The following functions prints address description depending
|
||||
// on the memory type (shadow/heap/stack/global).
|
||||
bool ParseFrameDescription(const char *frame_descr,
|
||||
|
@ -51,7 +54,7 @@ bool ParseFrameDescription(const char *frame_descr,
|
|||
void ReportGenericError(uptr pc, uptr bp, uptr sp, uptr addr, bool is_write,
|
||||
uptr access_size, u32 exp, bool fatal);
|
||||
void ReportStackOverflow(const SignalContext &sig);
|
||||
void ReportDeadlySignal(const char *description, const SignalContext &sig);
|
||||
void ReportDeadlySignal(int signo, const SignalContext &sig);
|
||||
void ReportNewDeleteSizeMismatch(uptr addr, uptr delete_size,
|
||||
BufferedStackTrace *free_stack);
|
||||
void ReportDoubleFree(uptr addr, BufferedStackTrace *free_stack);
|
||||
|
|
|
@ -270,7 +270,10 @@ static bool ShouldReportDeadlyException(unsigned code) {
|
|||
}
|
||||
|
||||
// Return the textual name for this exception.
|
||||
static const char *DescribeDeadlyException(unsigned code) {
|
||||
const char *DescribeSignalOrException(int signo) {
|
||||
unsigned code = signo;
|
||||
// Get the string description of the exception if this is a known deadly
|
||||
// exception.
|
||||
switch (code) {
|
||||
case EXCEPTION_ACCESS_VIOLATION:
|
||||
return "access-violation";
|
||||
|
@ -289,12 +292,8 @@ static long WINAPI SEHHandler(EXCEPTION_POINTERS *info) {
|
|||
CONTEXT *context = info->ContextRecord;
|
||||
|
||||
if (ShouldReportDeadlyException(exception_record->ExceptionCode)) {
|
||||
// Get the string description of the exception if this is a known deadly
|
||||
// exception.
|
||||
const char *description =
|
||||
DescribeDeadlyException(exception_record->ExceptionCode);
|
||||
SignalContext sig = SignalContext::Create(exception_record, context);
|
||||
ReportDeadlySignal(description, sig);
|
||||
ReportDeadlySignal(exception_record->ExceptionCode, sig);
|
||||
}
|
||||
|
||||
// FIXME: Handle EXCEPTION_STACK_OVERFLOW here.
|
||||
|
|
Loading…
Reference in New Issue