[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:
Vitaly Buka 2017-09-14 22:44:03 +00:00
parent 846a217bfc
commit 21ddc6219b
4 changed files with 89 additions and 57 deletions

View File

@ -22,56 +22,21 @@
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() {
if (signal.IsStackOverflow()) {
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);
}
ReportDeadlySignal(signal, tid, &OnStackUnwind, &scariness);
}
void ErrorDoubleFree::Print() {

View File

@ -31,6 +31,7 @@ extern "C" void _ReadWriteBarrier();
namespace __sanitizer {
struct AddressInfo;
struct BufferedStackTrace;
struct SignalContext;
struct StackTrace;
@ -311,10 +312,13 @@ HandleSignalMode GetHandleSignalMode(int signum);
void InstallDeadlySignalHandlers(SignalHandlerType handler);
// Signal reporting.
void StartReportDeadlySignal();
// FIXME: Hide after moving more signal handling code into common.
void MaybeReportNonExecRegion(uptr pc);
void MaybeDumpInstructionBytes(uptr pc);
void MaybeDumpRegisters(void *context);
// Each sanitizer uses slightly different implementation of stack unwinding.
typedef void (*UnwindSignalStackCallbackType)(const SignalContext &sig,
const void *callback_context,
BufferedStackTrace *stack);
void ReportDeadlySignal(const SignalContext &sig, u32 tid,
UnwindSignalStackCallbackType unwind,
const void *unwind_context);
// Alternative signal stack (POSIX-only).
void SetAlternateSignalStack();
void UnsetAlternateSignalStack();

View File

@ -148,7 +148,7 @@ void BackgroundThread(void *arg) {
#endif
#if !SANITIZER_GO
void MaybeReportNonExecRegion(uptr pc) {
static void MaybeReportNonExecRegion(uptr pc) {
#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD
MemoryMappingLayout proc_maps(/*cache_enabled*/ true);
MemoryMappedSegment segment;
@ -166,7 +166,7 @@ static void PrintMemoryByte(InternalScopedString *str, const char *before,
d.Default());
}
void MaybeDumpInstructionBytes(uptr pc) {
static void MaybeDumpInstructionBytes(uptr pc) {
if (!common_flags()->dump_instruction_bytes || (pc < GetPageSizeCached()))
return;
InternalScopedString str(1024);
@ -182,11 +182,71 @@ void MaybeDumpInstructionBytes(uptr pc) {
Report("%s", str.data());
}
void MaybeDumpRegisters(void *context) {
static void MaybeDumpRegisters(void *context) {
if (!common_flags()->dump_registers) return;
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) {
InternalScopedString msg_copy(kErrorMessageBufferSize);

View File

@ -92,6 +92,9 @@ void PrepareForSandboxing(__sanitizer_sandbox_arguments *args) {}
void DisableCoreDumperIfNecessary() {}
void InstallDeadlySignalHandlers(SignalHandlerType handler) {}
void StartReportDeadlySignal() {}
void ReportDeadlySignal(const SignalContext &sig, u32 tid,
UnwindSignalStackCallbackType unwind,
const void *unwind_context) {}
void SetAlternateSignalStack() {}
void UnsetAlternateSignalStack() {}
void InitTlsSize() {}