forked from OSchip/llvm-project
[compiler-rt] Use SignalContext in ErrorStackOverflow and ErrorDeadlySignal
Summary: Part of https://github.com/google/sanitizers/issues/637 Reviewers: eugenis, alekseyshl, filcab Subscribers: kubamracek, llvm-commits, dberris Differential Revision: https://reviews.llvm.org/D37793 llvm-svn: 313168
This commit is contained in:
parent
b215e90fb0
commit
dbde6f337c
|
@ -27,12 +27,14 @@ void ErrorStackOverflow::Print() {
|
|||
Printf("%s", d.Warning());
|
||||
Report(
|
||||
"ERROR: AddressSanitizer: %s on address %p"
|
||||
" (pc %p bp %p sp %p T%d)\n", scariness.GetDescription(),
|
||||
(void *)addr, (void *)pc, (void *)bp, (void *)sp, tid);
|
||||
" (pc %p bp %p sp %p T%d)\n",
|
||||
scariness.GetDescription(), (void *)signal.addr, (void *)signal.pc,
|
||||
(void *)signal.bp, (void *)signal.sp, tid);
|
||||
Printf("%s", d.Default());
|
||||
scariness.Print();
|
||||
BufferedStackTrace stack;
|
||||
GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, pc, bp, context,
|
||||
GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, signal.pc, signal.bp,
|
||||
signal.context,
|
||||
common_flags()->fast_unwind_on_fatal);
|
||||
stack.Print();
|
||||
ReportErrorSummary(scariness.GetDescription(), &stack);
|
||||
|
@ -41,30 +43,33 @@ void ErrorStackOverflow::Print() {
|
|||
void ErrorDeadlySignal::Print() {
|
||||
Decorator d;
|
||||
Printf("%s", d.Warning());
|
||||
const char *description = __sanitizer::DescribeSignalOrException(signo);
|
||||
const char *description = signal.Describe();
|
||||
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);
|
||||
description, (void *)signal.addr, (void *)signal.pc, (void *)signal.bp,
|
||||
(void *)signal.sp, tid);
|
||||
Printf("%s", d.Default());
|
||||
if (pc < GetPageSizeCached()) Report("Hint: pc points to the zero page.\n");
|
||||
if (is_memory_access) {
|
||||
if (signal.pc < GetPageSizeCached())
|
||||
Report("Hint: pc points to the zero page.\n");
|
||||
if (signal.is_memory_access) {
|
||||
const char *access_type =
|
||||
write_flag == SignalContext::WRITE
|
||||
signal.write_flag == SignalContext::WRITE
|
||||
? "WRITE"
|
||||
: (write_flag == SignalContext::READ ? "READ" : "UNKNOWN");
|
||||
: (signal.write_flag == SignalContext::READ ? "READ" : "UNKNOWN");
|
||||
Report("The signal is caused by a %s memory access.\n", access_type);
|
||||
if (addr < GetPageSizeCached())
|
||||
if (signal.addr < GetPageSizeCached())
|
||||
Report("Hint: address points to the zero page.\n");
|
||||
}
|
||||
MaybeReportNonExecRegion(pc);
|
||||
MaybeReportNonExecRegion(signal.pc);
|
||||
scariness.Print();
|
||||
BufferedStackTrace stack;
|
||||
GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, pc, bp, context,
|
||||
GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, signal.pc, signal.bp,
|
||||
signal.context,
|
||||
common_flags()->fast_unwind_on_fatal);
|
||||
stack.Print();
|
||||
MaybeDumpInstructionBytes(pc);
|
||||
MaybeDumpRegisters(context);
|
||||
MaybeDumpInstructionBytes(signal.pc);
|
||||
MaybeDumpRegisters(signal.context);
|
||||
Printf("AddressSanitizer can not provide additional info.\n");
|
||||
ReportErrorSummary(description, &stack);
|
||||
}
|
||||
|
|
|
@ -28,19 +28,12 @@ struct ErrorBase {
|
|||
};
|
||||
|
||||
struct ErrorStackOverflow : ErrorBase {
|
||||
uptr addr, pc, bp, sp;
|
||||
// ErrorStackOverflow never owns the context.
|
||||
void *context;
|
||||
SignalContext signal;
|
||||
// VS2013 doesn't implement unrestricted unions, so we need a trivial default
|
||||
// constructor
|
||||
ErrorStackOverflow() = default;
|
||||
ErrorStackOverflow(u32 tid, const SignalContext &sig)
|
||||
: ErrorBase(tid),
|
||||
addr(sig.addr),
|
||||
pc(sig.pc),
|
||||
bp(sig.bp),
|
||||
sp(sig.sp),
|
||||
context(sig.context) {
|
||||
: ErrorBase(tid), signal(sig) {
|
||||
scariness.Clear();
|
||||
scariness.Scare(10, "stack-overflow");
|
||||
}
|
||||
|
@ -48,34 +41,21 @@ struct ErrorStackOverflow : ErrorBase {
|
|||
};
|
||||
|
||||
struct ErrorDeadlySignal : ErrorBase {
|
||||
uptr addr, pc, bp, sp;
|
||||
// ErrorDeadlySignal never owns the context.
|
||||
void *context;
|
||||
int signo;
|
||||
SignalContext::WriteFlag write_flag;
|
||||
bool is_memory_access;
|
||||
SignalContext signal;
|
||||
// VS2013 doesn't implement unrestricted unions, so we need a trivial default
|
||||
// constructor
|
||||
ErrorDeadlySignal() = default;
|
||||
ErrorDeadlySignal(u32 tid, const SignalContext &sig)
|
||||
: ErrorBase(tid),
|
||||
addr(sig.addr),
|
||||
pc(sig.pc),
|
||||
bp(sig.bp),
|
||||
sp(sig.sp),
|
||||
context(sig.context),
|
||||
signo(sig.GetType()),
|
||||
write_flag(sig.write_flag),
|
||||
is_memory_access(sig.is_memory_access) {
|
||||
: ErrorBase(tid), signal(sig) {
|
||||
scariness.Clear();
|
||||
if (is_memory_access) {
|
||||
if (addr < GetPageSizeCached()) {
|
||||
if (signal.is_memory_access) {
|
||||
if (signal.addr < GetPageSizeCached()) {
|
||||
scariness.Scare(10, "null-deref");
|
||||
} else if (addr == pc) {
|
||||
} else if (signal.addr == signal.pc) {
|
||||
scariness.Scare(60, "wild-jump");
|
||||
} else if (write_flag == SignalContext::WRITE) {
|
||||
} else if (signal.write_flag == SignalContext::WRITE) {
|
||||
scariness.Scare(30, "wild-addr-write");
|
||||
} else if (write_flag == SignalContext::READ) {
|
||||
} else if (signal.write_flag == SignalContext::READ) {
|
||||
scariness.Scare(20, "wild-addr-read");
|
||||
} else {
|
||||
scariness.Scare(25, "wild-addr");
|
||||
|
|
|
@ -309,7 +309,6 @@ void SetSoftRssLimitExceededCallback(void (*Callback)(bool exceeded));
|
|||
typedef void (*SignalHandlerType)(int, void *, void *);
|
||||
HandleSignalMode GetHandleSignalMode(int signum);
|
||||
void InstallDeadlySignalHandlers(SignalHandlerType handler);
|
||||
const char *DescribeSignalOrException(int signo);
|
||||
// Signal reporting.
|
||||
void StartReportDeadlySignal();
|
||||
bool IsStackOverflow(const SignalContext &sig);
|
||||
|
@ -805,6 +804,9 @@ struct SignalContext {
|
|||
|
||||
enum WriteFlag { UNKNOWN, READ, WRITE } write_flag;
|
||||
|
||||
// VS2013 doesn't implement unrestricted unions, so we need a trivial default
|
||||
// constructor
|
||||
SignalContext() = default;
|
||||
// SignalContext is going to keep pointers to siginfo and context without
|
||||
// owning them.
|
||||
SignalContext(void *siginfo, void *context, uptr addr, uptr pc, uptr sp,
|
||||
|
@ -830,7 +832,7 @@ struct SignalContext {
|
|||
int GetType() const;
|
||||
|
||||
// String description of the signal.
|
||||
const char *Describe() const { return DescribeSignalOrException(GetType()); }
|
||||
const char *Describe() const;
|
||||
};
|
||||
|
||||
void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp);
|
||||
|
|
|
@ -98,7 +98,7 @@ void InitTlsSize() {}
|
|||
void PrintModuleMap() {}
|
||||
|
||||
void SignalContext::DumpAllRegisters(void *context) { UNIMPLEMENTED(); }
|
||||
const char *DescribeSignalOrException(int signo) { UNIMPLEMENTED(); }
|
||||
const char *SignalContext::Describe() const { UNIMPLEMENTED(); }
|
||||
|
||||
struct UnwindTraceArg {
|
||||
BufferedStackTrace *stack;
|
||||
|
|
|
@ -310,8 +310,8 @@ int SignalContext::GetType() const {
|
|||
return static_cast<const siginfo_t *>(siginfo)->si_signo;
|
||||
}
|
||||
|
||||
const char *DescribeSignalOrException(int signo) {
|
||||
switch (signo) {
|
||||
const char *SignalContext::Describe() const {
|
||||
switch (GetType()) {
|
||||
case SIGFPE:
|
||||
return "FPE";
|
||||
case SIGILL:
|
||||
|
|
|
@ -890,32 +890,6 @@ bool IsHandledDeadlyException(DWORD exceptionCode) {
|
|||
return false;
|
||||
}
|
||||
|
||||
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";
|
||||
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED: return "array-bounds-exceeded";
|
||||
case EXCEPTION_STACK_OVERFLOW: return "stack-overflow";
|
||||
case EXCEPTION_DATATYPE_MISALIGNMENT: return "datatype-misalignment";
|
||||
case EXCEPTION_IN_PAGE_ERROR: return "in-page-error";
|
||||
case EXCEPTION_ILLEGAL_INSTRUCTION: return "illegal-instruction";
|
||||
case EXCEPTION_PRIV_INSTRUCTION: return "priv-instruction";
|
||||
case EXCEPTION_BREAKPOINT: return "breakpoint";
|
||||
case EXCEPTION_FLT_DENORMAL_OPERAND: return "flt-denormal-operand";
|
||||
case EXCEPTION_FLT_DIVIDE_BY_ZERO: return "flt-divide-by-zero";
|
||||
case EXCEPTION_FLT_INEXACT_RESULT: return "flt-inexact-result";
|
||||
case EXCEPTION_FLT_INVALID_OPERATION: return "flt-invalid-operation";
|
||||
case EXCEPTION_FLT_OVERFLOW: return "flt-overflow";
|
||||
case EXCEPTION_FLT_STACK_CHECK: return "flt-stack-check";
|
||||
case EXCEPTION_FLT_UNDERFLOW: return "flt-underflow";
|
||||
case EXCEPTION_INT_DIVIDE_BY_ZERO: return "int-divide-by-zero";
|
||||
case EXCEPTION_INT_OVERFLOW: return "int-overflow";
|
||||
}
|
||||
return "unknown exception";
|
||||
}
|
||||
|
||||
bool IsAccessibleMemoryRange(uptr beg, uptr size) {
|
||||
SYSTEM_INFO si;
|
||||
GetNativeSystemInfo(&si);
|
||||
|
@ -978,6 +952,49 @@ int SignalContext::GetType() const {
|
|||
return static_cast<const EXCEPTION_RECORD *>(siginfo)->ExceptionCode;
|
||||
}
|
||||
|
||||
const char *SignalContext::Describe() const {
|
||||
unsigned code = GetType();
|
||||
// Get the string description of the exception if this is a known deadly
|
||||
// exception.
|
||||
switch (code) {
|
||||
case EXCEPTION_ACCESS_VIOLATION:
|
||||
return "access-violation";
|
||||
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
|
||||
return "array-bounds-exceeded";
|
||||
case EXCEPTION_STACK_OVERFLOW:
|
||||
return "stack-overflow";
|
||||
case EXCEPTION_DATATYPE_MISALIGNMENT:
|
||||
return "datatype-misalignment";
|
||||
case EXCEPTION_IN_PAGE_ERROR:
|
||||
return "in-page-error";
|
||||
case EXCEPTION_ILLEGAL_INSTRUCTION:
|
||||
return "illegal-instruction";
|
||||
case EXCEPTION_PRIV_INSTRUCTION:
|
||||
return "priv-instruction";
|
||||
case EXCEPTION_BREAKPOINT:
|
||||
return "breakpoint";
|
||||
case EXCEPTION_FLT_DENORMAL_OPERAND:
|
||||
return "flt-denormal-operand";
|
||||
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
|
||||
return "flt-divide-by-zero";
|
||||
case EXCEPTION_FLT_INEXACT_RESULT:
|
||||
return "flt-inexact-result";
|
||||
case EXCEPTION_FLT_INVALID_OPERATION:
|
||||
return "flt-invalid-operation";
|
||||
case EXCEPTION_FLT_OVERFLOW:
|
||||
return "flt-overflow";
|
||||
case EXCEPTION_FLT_STACK_CHECK:
|
||||
return "flt-stack-check";
|
||||
case EXCEPTION_FLT_UNDERFLOW:
|
||||
return "flt-underflow";
|
||||
case EXCEPTION_INT_DIVIDE_BY_ZERO:
|
||||
return "int-divide-by-zero";
|
||||
case EXCEPTION_INT_OVERFLOW:
|
||||
return "int-overflow";
|
||||
}
|
||||
return "unknown exception";
|
||||
}
|
||||
|
||||
uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) {
|
||||
// FIXME: Actually implement this function.
|
||||
CHECK_GT(buf_len, 0);
|
||||
|
|
Loading…
Reference in New Issue