[sanitizer] Move stack overflow and signal reporting from Asan into common.
Summary: Part of https://github.com/google/sanitizers/issues/637 Reviewers: eugenis, alekseyshl Subscribers: kubamracek Differential Revision: https://reviews.llvm.org/D37844 llvm-svn: 313310
This commit is contained in:
parent
846a217bfc
commit
21ddc6219b
|
@ -22,56 +22,21 @@
|
||||||
|
|
||||||
namespace __asan {
|
namespace __asan {
|
||||||
|
|
||||||
|
static void OnStackUnwind(const SignalContext &sig,
|
||||||
|
const void *callback_context,
|
||||||
|
BufferedStackTrace *stack) {
|
||||||
|
// Tests and maybe some users expect that scariness is going to be printed
|
||||||
|
// just before the stack. As only asan has scariness score we have no
|
||||||
|
// corresponding code in the sanitizer_common and we use this callback to
|
||||||
|
// print it.
|
||||||
|
static_cast<const ScarinessScoreBase *>(callback_context)->Print();
|
||||||
|
GetStackTraceWithPcBpAndContext(stack, kStackTraceMax, sig.pc, sig.bp,
|
||||||
|
sig.context,
|
||||||
|
common_flags()->fast_unwind_on_fatal);
|
||||||
|
}
|
||||||
|
|
||||||
void ErrorDeadlySignal::Print() {
|
void ErrorDeadlySignal::Print() {
|
||||||
if (signal.IsStackOverflow()) {
|
ReportDeadlySignal(signal, tid, &OnStackUnwind, &scariness);
|
||||||
Decorator d;
|
|
||||||
Printf("%s", d.Warning());
|
|
||||||
Report(
|
|
||||||
"ERROR: AddressSanitizer: %s on address %p"
|
|
||||||
" (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, signal.pc,
|
|
||||||
signal.bp, signal.context,
|
|
||||||
common_flags()->fast_unwind_on_fatal);
|
|
||||||
stack.Print();
|
|
||||||
ReportErrorSummary(scariness.GetDescription(), &stack);
|
|
||||||
} else {
|
|
||||||
Decorator d;
|
|
||||||
Printf("%s", d.Warning());
|
|
||||||
const char *description = signal.Describe();
|
|
||||||
Report(
|
|
||||||
"ERROR: AddressSanitizer: %s on unknown address %p (pc %p bp %p sp %p "
|
|
||||||
"T%d)\n",
|
|
||||||
description, (void *)signal.addr, (void *)signal.pc, (void *)signal.bp,
|
|
||||||
(void *)signal.sp, tid);
|
|
||||||
Printf("%s", d.Default());
|
|
||||||
if (signal.pc < GetPageSizeCached())
|
|
||||||
Report("Hint: pc points to the zero page.\n");
|
|
||||||
if (signal.is_memory_access) {
|
|
||||||
const char *access_type =
|
|
||||||
signal.write_flag == SignalContext::WRITE
|
|
||||||
? "WRITE"
|
|
||||||
: (signal.write_flag == SignalContext::READ ? "READ" : "UNKNOWN");
|
|
||||||
Report("The signal is caused by a %s memory access.\n", access_type);
|
|
||||||
if (signal.addr < GetPageSizeCached())
|
|
||||||
Report("Hint: address points to the zero page.\n");
|
|
||||||
}
|
|
||||||
MaybeReportNonExecRegion(signal.pc);
|
|
||||||
scariness.Print();
|
|
||||||
BufferedStackTrace stack;
|
|
||||||
GetStackTraceWithPcBpAndContext(&stack, kStackTraceMax, signal.pc,
|
|
||||||
signal.bp, signal.context,
|
|
||||||
common_flags()->fast_unwind_on_fatal);
|
|
||||||
stack.Print();
|
|
||||||
MaybeDumpInstructionBytes(signal.pc);
|
|
||||||
MaybeDumpRegisters(signal.context);
|
|
||||||
Printf("AddressSanitizer can not provide additional info.\n");
|
|
||||||
ReportErrorSummary(description, &stack);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ErrorDoubleFree::Print() {
|
void ErrorDoubleFree::Print() {
|
||||||
|
|
|
@ -31,6 +31,7 @@ extern "C" void _ReadWriteBarrier();
|
||||||
namespace __sanitizer {
|
namespace __sanitizer {
|
||||||
|
|
||||||
struct AddressInfo;
|
struct AddressInfo;
|
||||||
|
struct BufferedStackTrace;
|
||||||
struct SignalContext;
|
struct SignalContext;
|
||||||
struct StackTrace;
|
struct StackTrace;
|
||||||
|
|
||||||
|
@ -311,10 +312,13 @@ HandleSignalMode GetHandleSignalMode(int signum);
|
||||||
void InstallDeadlySignalHandlers(SignalHandlerType handler);
|
void InstallDeadlySignalHandlers(SignalHandlerType handler);
|
||||||
// Signal reporting.
|
// Signal reporting.
|
||||||
void StartReportDeadlySignal();
|
void StartReportDeadlySignal();
|
||||||
// FIXME: Hide after moving more signal handling code into common.
|
// Each sanitizer uses slightly different implementation of stack unwinding.
|
||||||
void MaybeReportNonExecRegion(uptr pc);
|
typedef void (*UnwindSignalStackCallbackType)(const SignalContext &sig,
|
||||||
void MaybeDumpInstructionBytes(uptr pc);
|
const void *callback_context,
|
||||||
void MaybeDumpRegisters(void *context);
|
BufferedStackTrace *stack);
|
||||||
|
void ReportDeadlySignal(const SignalContext &sig, u32 tid,
|
||||||
|
UnwindSignalStackCallbackType unwind,
|
||||||
|
const void *unwind_context);
|
||||||
// Alternative signal stack (POSIX-only).
|
// Alternative signal stack (POSIX-only).
|
||||||
void SetAlternateSignalStack();
|
void SetAlternateSignalStack();
|
||||||
void UnsetAlternateSignalStack();
|
void UnsetAlternateSignalStack();
|
||||||
|
|
|
@ -148,7 +148,7 @@ void BackgroundThread(void *arg) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if !SANITIZER_GO
|
#if !SANITIZER_GO
|
||||||
void MaybeReportNonExecRegion(uptr pc) {
|
static void MaybeReportNonExecRegion(uptr pc) {
|
||||||
#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD
|
#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD
|
||||||
MemoryMappingLayout proc_maps(/*cache_enabled*/ true);
|
MemoryMappingLayout proc_maps(/*cache_enabled*/ true);
|
||||||
MemoryMappedSegment segment;
|
MemoryMappedSegment segment;
|
||||||
|
@ -166,7 +166,7 @@ static void PrintMemoryByte(InternalScopedString *str, const char *before,
|
||||||
d.Default());
|
d.Default());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MaybeDumpInstructionBytes(uptr pc) {
|
static void MaybeDumpInstructionBytes(uptr pc) {
|
||||||
if (!common_flags()->dump_instruction_bytes || (pc < GetPageSizeCached()))
|
if (!common_flags()->dump_instruction_bytes || (pc < GetPageSizeCached()))
|
||||||
return;
|
return;
|
||||||
InternalScopedString str(1024);
|
InternalScopedString str(1024);
|
||||||
|
@ -182,11 +182,71 @@ void MaybeDumpInstructionBytes(uptr pc) {
|
||||||
Report("%s", str.data());
|
Report("%s", str.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
void MaybeDumpRegisters(void *context) {
|
static void MaybeDumpRegisters(void *context) {
|
||||||
if (!common_flags()->dump_registers) return;
|
if (!common_flags()->dump_registers) return;
|
||||||
SignalContext::DumpAllRegisters(context);
|
SignalContext::DumpAllRegisters(context);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
static void ReportStackOverflowImpl(const SignalContext &sig, u32 tid,
|
||||||
|
UnwindSignalStackCallbackType unwind,
|
||||||
|
const void *unwind_context) {
|
||||||
|
SanitizerCommonDecorator d;
|
||||||
|
Printf("%s", d.Warning());
|
||||||
|
static const char kDescription[] = "stack-overflow";
|
||||||
|
Report("ERROR: %s: %s on address %p (pc %p bp %p sp %p T%d)\n",
|
||||||
|
SanitizerToolName, kDescription, (void *)sig.addr, (void *)sig.pc,
|
||||||
|
(void *)sig.bp, (void *)sig.sp, tid);
|
||||||
|
Printf("%s", d.Default());
|
||||||
|
InternalScopedBuffer<BufferedStackTrace> stack_buffer(1);
|
||||||
|
BufferedStackTrace *stack = stack_buffer.data();
|
||||||
|
stack->Reset();
|
||||||
|
unwind(sig, unwind_context, stack);
|
||||||
|
stack->Print();
|
||||||
|
ReportErrorSummary(kDescription, stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ReportDeadlySignalImpl(const SignalContext &sig, u32 tid,
|
||||||
|
UnwindSignalStackCallbackType unwind,
|
||||||
|
const void *unwind_context) {
|
||||||
|
SanitizerCommonDecorator d;
|
||||||
|
Printf("%s", d.Warning());
|
||||||
|
const char *description = sig.Describe();
|
||||||
|
Report("ERROR: %s: %s on unknown address %p (pc %p bp %p sp %p T%d)\n",
|
||||||
|
SanitizerToolName, description, (void *)sig.addr, (void *)sig.pc,
|
||||||
|
(void *)sig.bp, (void *)sig.sp, tid);
|
||||||
|
Printf("%s", d.Default());
|
||||||
|
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");
|
||||||
|
}
|
||||||
|
MaybeReportNonExecRegion(sig.pc);
|
||||||
|
InternalScopedBuffer<BufferedStackTrace> stack_buffer(1);
|
||||||
|
BufferedStackTrace *stack = stack_buffer.data();
|
||||||
|
stack->Reset();
|
||||||
|
unwind(sig, unwind_context, stack);
|
||||||
|
stack->Print();
|
||||||
|
MaybeDumpInstructionBytes(sig.pc);
|
||||||
|
MaybeDumpRegisters(sig.context);
|
||||||
|
Printf("%s can not provide additional info.\n", SanitizerToolName);
|
||||||
|
ReportErrorSummary(description, stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ReportDeadlySignal(const SignalContext &sig, u32 tid,
|
||||||
|
UnwindSignalStackCallbackType unwind,
|
||||||
|
const void *unwind_context) {
|
||||||
|
if (sig.IsStackOverflow())
|
||||||
|
ReportStackOverflowImpl(sig, tid, unwind, unwind_context);
|
||||||
|
else
|
||||||
|
ReportDeadlySignalImpl(sig, tid, unwind, unwind_context);
|
||||||
|
}
|
||||||
|
#endif // !SANITIZER_GO
|
||||||
|
|
||||||
void WriteToSyslog(const char *msg) {
|
void WriteToSyslog(const char *msg) {
|
||||||
InternalScopedString msg_copy(kErrorMessageBufferSize);
|
InternalScopedString msg_copy(kErrorMessageBufferSize);
|
||||||
|
|
|
@ -92,6 +92,9 @@ void PrepareForSandboxing(__sanitizer_sandbox_arguments *args) {}
|
||||||
void DisableCoreDumperIfNecessary() {}
|
void DisableCoreDumperIfNecessary() {}
|
||||||
void InstallDeadlySignalHandlers(SignalHandlerType handler) {}
|
void InstallDeadlySignalHandlers(SignalHandlerType handler) {}
|
||||||
void StartReportDeadlySignal() {}
|
void StartReportDeadlySignal() {}
|
||||||
|
void ReportDeadlySignal(const SignalContext &sig, u32 tid,
|
||||||
|
UnwindSignalStackCallbackType unwind,
|
||||||
|
const void *unwind_context) {}
|
||||||
void SetAlternateSignalStack() {}
|
void SetAlternateSignalStack() {}
|
||||||
void UnsetAlternateSignalStack() {}
|
void UnsetAlternateSignalStack() {}
|
||||||
void InitTlsSize() {}
|
void InitTlsSize() {}
|
||||||
|
|
Loading…
Reference in New Issue