summaryrefslogtreecommitdiff
path: root/lib/sanitizer_common
diff options
context:
space:
mode:
authorVitaly Buka <vitalybuka@google.com>2017-09-14 22:44:03 +0000
committerVitaly Buka <vitalybuka@google.com>2017-09-14 22:44:03 +0000
commit476bb23ca07911c2a52644e743fabdba40a0c1b4 (patch)
tree734f872445496062acb17e00a54b1760efeb08a9 /lib/sanitizer_common
parente3c17f18663a16b332846f3971ea1ab38cc7639c (diff)
[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 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@313310 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/sanitizer_common')
-rw-r--r--lib/sanitizer_common/sanitizer_common.h12
-rw-r--r--lib/sanitizer_common/sanitizer_common_libcdep.cc68
-rw-r--r--lib/sanitizer_common/sanitizer_fuchsia.cc3
3 files changed, 75 insertions, 8 deletions
diff --git a/lib/sanitizer_common/sanitizer_common.h b/lib/sanitizer_common/sanitizer_common.h
index 988acb794..75508cbe4 100644
--- a/lib/sanitizer_common/sanitizer_common.h
+++ b/lib/sanitizer_common/sanitizer_common.h
@@ -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();
diff --git a/lib/sanitizer_common/sanitizer_common_libcdep.cc b/lib/sanitizer_common/sanitizer_common_libcdep.cc
index 21a591e64..4f26a2227 100644
--- a/lib/sanitizer_common/sanitizer_common_libcdep.cc
+++ b/lib/sanitizer_common/sanitizer_common_libcdep.cc
@@ -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);
diff --git a/lib/sanitizer_common/sanitizer_fuchsia.cc b/lib/sanitizer_common/sanitizer_fuchsia.cc
index e518708c0..708f7f0c5 100644
--- a/lib/sanitizer_common/sanitizer_fuchsia.cc
+++ b/lib/sanitizer_common/sanitizer_fuchsia.cc
@@ -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() {}