[llvm-branch-commits] [compiler-rt] a8520f6 - [GWP-ASan] Minor refactor of optional components.
Mitch Phillips via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Thu Jan 14 11:19:22 PST 2021
Author: Mitch Phillips
Date: 2021-01-14T11:14:11-08:00
New Revision: a8520f6970fd4d44ceae1ec5969563a0dbe30f54
URL: https://github.com/llvm/llvm-project/commit/a8520f6970fd4d44ceae1ec5969563a0dbe30f54
DIFF: https://github.com/llvm/llvm-project/commit/a8520f6970fd4d44ceae1ec5969563a0dbe30f54.diff
LOG: [GWP-ASan] Minor refactor of optional components.
In preparation for the inbuilt options parser, this is a minor refactor
of optional components including:
- Putting certain optional elements in the right header files,
according to their function and their dependencies.
- Cleaning up some old and mostly-dead code.
- Moving some functions into anonymous namespaces to prevent symbol
export.
Reviewed By: cryptoad, eugenis
Differential Revision: https://reviews.llvm.org/D94117
Added:
compiler-rt/lib/gwp_asan/optional/printf.h
compiler-rt/lib/gwp_asan/tests/platform_specific/printf_sanitizer_common.cpp
Modified:
compiler-rt/lib/gwp_asan/optional/backtrace.h
compiler-rt/lib/gwp_asan/optional/backtrace_fuchsia.cpp
compiler-rt/lib/gwp_asan/optional/backtrace_linux_libc.cpp
compiler-rt/lib/gwp_asan/optional/backtrace_sanitizer_common.cpp
compiler-rt/lib/gwp_asan/optional/segv_handler.h
compiler-rt/lib/gwp_asan/optional/segv_handler_fuchsia.cpp
compiler-rt/lib/gwp_asan/optional/segv_handler_posix.cpp
compiler-rt/lib/gwp_asan/tests/CMakeLists.txt
compiler-rt/lib/gwp_asan/tests/harness.h
compiler-rt/lib/scudo/scudo_allocator.cpp
compiler-rt/lib/scudo/standalone/combined.h
Removed:
compiler-rt/lib/gwp_asan/tests/optional/printf_sanitizer_common.cpp
################################################################################
diff --git a/compiler-rt/lib/gwp_asan/optional/backtrace.h b/compiler-rt/lib/gwp_asan/optional/backtrace.h
index 3a72eb3d08e8..9bb12af206a5 100644
--- a/compiler-rt/lib/gwp_asan/optional/backtrace.h
+++ b/compiler-rt/lib/gwp_asan/optional/backtrace.h
@@ -9,21 +9,45 @@
#ifndef GWP_ASAN_OPTIONAL_BACKTRACE_H_
#define GWP_ASAN_OPTIONAL_BACKTRACE_H_
-#include "gwp_asan/optional/segv_handler.h"
+#include "gwp_asan/optional/printf.h"
#include "gwp_asan/options.h"
namespace gwp_asan {
-namespace options {
-// Functions to get the platform-specific and implementation-specific backtrace
-// and backtrace printing functions when RTGwpAsanBacktraceLibc or
-// RTGwpAsanBacktraceSanitizerCommon are linked. Use these functions to get the
-// backtrace function for populating the Options::Backtrace and
-// Options::PrintBacktrace when initialising the GuardedPoolAllocator. Please
-// note any thread-safety descriptions for the implementation of these functions
-// that you use.
-Backtrace_t getBacktraceFunction();
-crash_handler::PrintBacktrace_t getPrintBacktraceFunction();
-} // namespace options
+namespace backtrace {
+// ================================ Description ================================
+// This function shall take the backtrace provided in `TraceBuffer`, and print
+// it in a human-readable format using `Print`. Generally, this function shall
+// resolve raw pointers to section offsets and print them with the following
+// sanitizer-common format:
+// " #{frame_number} {pointer} in {function name} ({binary name}+{offset}"
+// e.g. " #5 0x420459 in _start (/tmp/uaf+0x420459)"
+// This format allows the backtrace to be symbolized offline successfully using
+// llvm-symbolizer.
+// =================================== Notes ===================================
+// This function may directly or indirectly call malloc(), as the
+// GuardedPoolAllocator contains a reentrancy barrier to prevent infinite
+// recursion. Any allocation made inside this function will be served by the
+// supporting allocator, and will not have GWP-ASan protections.
+typedef void (*PrintBacktrace_t)(uintptr_t *TraceBuffer, size_t TraceLength,
+ Printf_t Print);
+
+// Returns a function pointer to a backtrace function that's suitable for
+// unwinding through a signal handler. This is important primarily for frame-
+// pointer based unwinders, DWARF or other unwinders can simply provide the
+// normal backtrace function as the implementation here. On POSIX, SignalContext
+// should be the `ucontext_t` from the signal handler.
+typedef size_t (*SegvBacktrace_t)(uintptr_t *TraceBuffer, size_t Size,
+ void *SignalContext);
+
+// Returns platform-specific provided implementations of Backtrace_t for use
+// inside the GWP-ASan core allocator.
+options::Backtrace_t getBacktraceFunction();
+
+// Returns platform-specific provided implementations of PrintBacktrace_t and
+// SegvBacktrace_t for use in the optional SEGV handler.
+PrintBacktrace_t getPrintBacktraceFunction();
+SegvBacktrace_t getSegvBacktraceFunction();
+} // namespace backtrace
} // namespace gwp_asan
#endif // GWP_ASAN_OPTIONAL_BACKTRACE_H_
diff --git a/compiler-rt/lib/gwp_asan/optional/backtrace_fuchsia.cpp b/compiler-rt/lib/gwp_asan/optional/backtrace_fuchsia.cpp
index ac7ed6c709d7..879312a7631e 100644
--- a/compiler-rt/lib/gwp_asan/optional/backtrace_fuchsia.cpp
+++ b/compiler-rt/lib/gwp_asan/optional/backtrace_fuchsia.cpp
@@ -11,12 +11,11 @@
// GWP-ASan on Fuchsia doesn't currently support backtraces.
namespace gwp_asan {
-namespace options {
-Backtrace_t getBacktraceFunction() { return nullptr; }
-crash_handler::PrintBacktrace_t getPrintBacktraceFunction() { return nullptr; }
-} // namespace options
+namespace backtrace {
-namespace crash_handler {
+options::Backtrace_t getBacktraceFunction() { return nullptr; }
+PrintBacktrace_t getPrintBacktraceFunction() { return nullptr; }
SegvBacktrace_t getSegvBacktraceFunction() { return nullptr; }
-} // namespace crash_handler
+
+} // namespace backtrace
} // namespace gwp_asan
diff --git a/compiler-rt/lib/gwp_asan/optional/backtrace_linux_libc.cpp b/compiler-rt/lib/gwp_asan/optional/backtrace_linux_libc.cpp
index 92eb293dab49..ea8e72be287d 100644
--- a/compiler-rt/lib/gwp_asan/optional/backtrace_linux_libc.cpp
+++ b/compiler-rt/lib/gwp_asan/optional/backtrace_linux_libc.cpp
@@ -13,7 +13,9 @@
#include <stdlib.h>
#include <string.h>
+#include "gwp_asan/definitions.h"
#include "gwp_asan/optional/backtrace.h"
+#include "gwp_asan/optional/printf.h"
#include "gwp_asan/options.h"
namespace {
@@ -32,7 +34,7 @@ GWP_ASAN_ALWAYS_INLINE size_t SegvBacktrace(uintptr_t *TraceBuffer, size_t Size,
}
static void PrintBacktrace(uintptr_t *Trace, size_t TraceLength,
- gwp_asan::crash_handler::Printf_t Printf) {
+ gwp_asan::Printf_t Printf) {
if (TraceLength == 0) {
Printf(" <not found (does your allocator support backtracing?)>\n\n");
return;
@@ -55,14 +57,11 @@ static void PrintBacktrace(uintptr_t *Trace, size_t TraceLength,
} // anonymous namespace
namespace gwp_asan {
-namespace options {
-Backtrace_t getBacktraceFunction() { return Backtrace; }
-crash_handler::PrintBacktrace_t getPrintBacktraceFunction() {
- return PrintBacktrace;
-}
-} // namespace options
+namespace backtrace {
-namespace crash_handler {
+options::Backtrace_t getBacktraceFunction() { return Backtrace; }
+PrintBacktrace_t getPrintBacktraceFunction() { return PrintBacktrace; }
SegvBacktrace_t getSegvBacktraceFunction() { return SegvBacktrace; }
-} // namespace crash_handler
+
+} // namespace backtrace
} // namespace gwp_asan
diff --git a/compiler-rt/lib/gwp_asan/optional/backtrace_sanitizer_common.cpp b/compiler-rt/lib/gwp_asan/optional/backtrace_sanitizer_common.cpp
index a8083e4e64cb..e6cce86e3b7b 100644
--- a/compiler-rt/lib/gwp_asan/optional/backtrace_sanitizer_common.cpp
+++ b/compiler-rt/lib/gwp_asan/optional/backtrace_sanitizer_common.cpp
@@ -62,7 +62,7 @@ size_t SegvBacktrace(uintptr_t *TraceBuffer, size_t Size, void *Context) {
}
static void PrintBacktrace(uintptr_t *Trace, size_t TraceLength,
- gwp_asan::crash_handler::Printf_t Printf) {
+ gwp_asan::Printf_t Printf) {
__sanitizer::StackTrace StackTrace;
StackTrace.trace = reinterpret_cast<__sanitizer::uptr *>(Trace);
StackTrace.size = TraceLength;
@@ -77,25 +77,23 @@ static void PrintBacktrace(uintptr_t *Trace, size_t TraceLength,
} // anonymous namespace
namespace gwp_asan {
-namespace options {
+namespace backtrace {
+
// This function is thread-compatible. It must be synchronised in respect to any
// other calls to getBacktraceFunction(), calls to getPrintBacktraceFunction(),
// and calls to either of the functions that they return. Furthermore, this may
// require synchronisation with any calls to sanitizer_common that use flags.
// Generally, this function will be called during the initialisation of the
// allocator, which is done in a thread-compatible manner.
-Backtrace_t getBacktraceFunction() {
+options::Backtrace_t getBacktraceFunction() {
// The unwinder requires the default flags to be set.
__sanitizer::SetCommonFlagsDefaults();
__sanitizer::InitializeCommonFlags();
return Backtrace;
}
-crash_handler::PrintBacktrace_t getPrintBacktraceFunction() {
- return PrintBacktrace;
-}
-} // namespace options
-namespace crash_handler {
+PrintBacktrace_t getPrintBacktraceFunction() { return PrintBacktrace; }
SegvBacktrace_t getSegvBacktraceFunction() { return SegvBacktrace; }
-} // namespace crash_handler
+
+} // namespace backtrace
} // namespace gwp_asan
diff --git a/compiler-rt/lib/gwp_asan/optional/printf.h b/compiler-rt/lib/gwp_asan/optional/printf.h
new file mode 100644
index 000000000000..1004a2c24989
--- /dev/null
+++ b/compiler-rt/lib/gwp_asan/optional/printf.h
@@ -0,0 +1,33 @@
+//===-- printf.h ------------------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef GWP_ASAN_OPTIONAL_PRINTF_H_
+#define GWP_ASAN_OPTIONAL_PRINTF_H_
+
+namespace gwp_asan {
+
+// ================================ Requirements ===============================
+// This function is required to be provided by the supporting allocator iff the
+// allocator wants to use any of the optional components.
+// ================================ Description ================================
+// This function shall produce output according to a strict subset of the C
+// standard library's printf() family. This function must support printing the
+// following formats:
+// 1. integers: "%([0-9]*)?(z|ll)?{d,u,x,X}"
+// 2. pointers: "%p"
+// 3. strings: "%[-]([0-9]*)?(\\.\\*)?s"
+// 4. chars: "%c"
+// This function must be implemented in a signal-safe manner, and thus must not
+// malloc().
+// =================================== Notes ===================================
+// This function has a slightly
diff erent signature than the C standard
+// library's printf(). Notably, it returns 'void' rather than 'int'.
+typedef void (*Printf_t)(const char *Format, ...);
+
+} // namespace gwp_asan
+#endif // GWP_ASAN_OPTIONAL_PRINTF_H_
diff --git a/compiler-rt/lib/gwp_asan/optional/segv_handler.h b/compiler-rt/lib/gwp_asan/optional/segv_handler.h
index e1d96a6cd81f..87d9fe1dff17 100644
--- a/compiler-rt/lib/gwp_asan/optional/segv_handler.h
+++ b/compiler-rt/lib/gwp_asan/optional/segv_handler.h
@@ -10,64 +10,11 @@
#define GWP_ASAN_OPTIONAL_SEGV_HANDLER_H_
#include "gwp_asan/guarded_pool_allocator.h"
-#include "gwp_asan/options.h"
+#include "gwp_asan/optional/backtrace.h"
+#include "gwp_asan/optional/printf.h"
namespace gwp_asan {
-namespace crash_handler {
-// ================================ Requirements ===============================
-// This function must be provided by the supporting allocator only when this
-// provided crash handler is used to dump the generic report.
-// sanitizer::Printf() function can be simply used here.
-// ================================ Description ================================
-// This function shall produce output according to a strict subset of the C
-// standard library's printf() family. This function must support printing the
-// following formats:
-// 1. integers: "%([0-9]*)?(z|ll)?{d,u,x,X}"
-// 2. pointers: "%p"
-// 3. strings: "%[-]([0-9]*)?(\\.\\*)?s"
-// 4. chars: "%c"
-// This function must be implemented in a signal-safe manner, and thus must not
-// malloc().
-// =================================== Notes ===================================
-// This function has a slightly
diff erent signature than the C standard
-// library's printf(). Notably, it returns 'void' rather than 'int'.
-typedef void (*Printf_t)(const char *Format, ...);
-
-// ================================ Requirements ===============================
-// This function is required for the supporting allocator, but one of the three
-// provided implementations may be used (RTGwpAsanBacktraceLibc,
-// RTGwpAsanBacktraceSanitizerCommon, or BasicPrintBacktraceFunction).
-// ================================ Description ================================
-// This function shall take the backtrace provided in `TraceBuffer`, and print
-// it in a human-readable format using `Print`. Generally, this function shall
-// resolve raw pointers to section offsets and print them with the following
-// sanitizer-common format:
-// " #{frame_number} {pointer} in {function name} ({binary name}+{offset}"
-// e.g. " #5 0x420459 in _start (/tmp/uaf+0x420459)"
-// This format allows the backtrace to be symbolized offline successfully using
-// llvm-symbolizer.
-// =================================== Notes ===================================
-// This function may directly or indirectly call malloc(), as the
-// GuardedPoolAllocator contains a reentrancy barrier to prevent infinite
-// recursion. Any allocation made inside this function will be served by the
-// supporting allocator, and will not have GWP-ASan protections.
-typedef void (*PrintBacktrace_t)(uintptr_t *TraceBuffer, size_t TraceLength,
- Printf_t Print);
-
-// Returns a function pointer to a basic PrintBacktrace implementation. This
-// implementation simply prints the stack trace in a human readable fashion
-// without any symbolization.
-PrintBacktrace_t getBasicPrintBacktraceFunction();
-
-// Returns a function pointer to a backtrace function that's suitable for
-// unwinding through a signal handler. This is important primarily for frame-
-// pointer based unwinders, DWARF or other unwinders can simply provide the
-// normal backtrace function as the implementation here. On POSIX, SignalContext
-// should be the `ucontext_t` from the signal handler.
-typedef size_t (*SegvBacktrace_t)(uintptr_t *TraceBuffer, size_t Size,
- void *SignalContext);
-SegvBacktrace_t getSegvBacktraceFunction();
-
+namespace segv_handler {
// Install the SIGSEGV crash handler for printing use-after-free and heap-
// buffer-{under|over}flow exceptions if the user asked for it. This is platform
// specific as even though POSIX and Windows both support registering handlers
@@ -75,16 +22,12 @@ SegvBacktrace_t getSegvBacktraceFunction();
// the address that caused the SIGSEGV exception. GPA->init() must be called
// before this function.
void installSignalHandlers(gwp_asan::GuardedPoolAllocator *GPA, Printf_t Printf,
- PrintBacktrace_t PrintBacktrace,
- SegvBacktrace_t SegvBacktrace);
+ gwp_asan::backtrace::PrintBacktrace_t PrintBacktrace,
+ gwp_asan::backtrace::SegvBacktrace_t SegvBacktrace);
+// Uninistall the signal handlers, test-only.
void uninstallSignalHandlers();
-
-void dumpReport(uintptr_t ErrorPtr, const gwp_asan::AllocatorState *State,
- const gwp_asan::AllocationMetadata *Metadata,
- SegvBacktrace_t SegvBacktrace, Printf_t Printf,
- PrintBacktrace_t PrintBacktrace, void *Context);
-} // namespace crash_handler
+} // namespace segv_handler
} // namespace gwp_asan
#endif // GWP_ASAN_OPTIONAL_SEGV_HANDLER_H_
diff --git a/compiler-rt/lib/gwp_asan/optional/segv_handler_fuchsia.cpp b/compiler-rt/lib/gwp_asan/optional/segv_handler_fuchsia.cpp
index ec26afae6c08..966d7d0bd996 100644
--- a/compiler-rt/lib/gwp_asan/optional/segv_handler_fuchsia.cpp
+++ b/compiler-rt/lib/gwp_asan/optional/segv_handler_fuchsia.cpp
@@ -11,12 +11,12 @@
// GWP-ASan on Fuchsia doesn't currently support signal handlers.
namespace gwp_asan {
-namespace crash_handler {
+namespace segv_handler {
void installSignalHandlers(gwp_asan::GuardedPoolAllocator * /* GPA */,
Printf_t /* Printf */,
- PrintBacktrace_t /* PrintBacktrace */,
- SegvBacktrace_t /* SegvBacktrace */) {}
+ backtrace::PrintBacktrace_t /* PrintBacktrace */,
+ backtrace::SegvBacktrace_t /* SegvBacktrace */) {}
void uninstallSignalHandlers() {}
-} // namespace crash_handler
+} // namespace segv_handler
} // namespace gwp_asan
diff --git a/compiler-rt/lib/gwp_asan/optional/segv_handler_posix.cpp b/compiler-rt/lib/gwp_asan/optional/segv_handler_posix.cpp
index 8d9f39a7bd00..5c9bb9f3a2e7 100644
--- a/compiler-rt/lib/gwp_asan/optional/segv_handler_posix.cpp
+++ b/compiler-rt/lib/gwp_asan/optional/segv_handler_posix.cpp
@@ -12,62 +12,30 @@
#include "gwp_asan/optional/segv_handler.h"
#include "gwp_asan/options.h"
+// RHEL creates the PRIu64 format macro (for printing uint64_t's) only when this
+// macro is defined before including <inttypes.h>.
+#ifndef __STDC_FORMAT_MACROS
+#define __STDC_FORMAT_MACROS 1
+#endif
+
#include <assert.h>
#include <inttypes.h>
#include <signal.h>
#include <stdio.h>
-namespace {
using gwp_asan::AllocationMetadata;
using gwp_asan::Error;
using gwp_asan::GuardedPoolAllocator;
-using gwp_asan::crash_handler::PrintBacktrace_t;
-using gwp_asan::crash_handler::Printf_t;
-using gwp_asan::crash_handler::SegvBacktrace_t;
-
-struct sigaction PreviousHandler;
-bool SignalHandlerInstalled;
-gwp_asan::GuardedPoolAllocator *GPAForSignalHandler;
-Printf_t PrintfForSignalHandler;
-PrintBacktrace_t PrintBacktraceForSignalHandler;
-SegvBacktrace_t BacktraceForSignalHandler;
-
-static void sigSegvHandler(int sig, siginfo_t *info, void *ucontext) {
- if (GPAForSignalHandler) {
- GPAForSignalHandler->stop();
-
- gwp_asan::crash_handler::dumpReport(
- reinterpret_cast<uintptr_t>(info->si_addr),
- GPAForSignalHandler->getAllocatorState(),
- GPAForSignalHandler->getMetadataRegion(), BacktraceForSignalHandler,
- PrintfForSignalHandler, PrintBacktraceForSignalHandler, ucontext);
- }
+using gwp_asan::Printf_t;
+using gwp_asan::backtrace::PrintBacktrace_t;
+using gwp_asan::backtrace::SegvBacktrace_t;
- // Process any previous handlers.
- if (PreviousHandler.sa_flags & SA_SIGINFO) {
- PreviousHandler.sa_sigaction(sig, info, ucontext);
- } else if (PreviousHandler.sa_handler == SIG_DFL) {
- // If the previous handler was the default handler, cause a core dump.
- signal(SIGSEGV, SIG_DFL);
- raise(SIGSEGV);
- } else if (PreviousHandler.sa_handler == SIG_IGN) {
- // If the previous segv handler was SIGIGN, crash iff we were responsible
- // for the crash.
- if (__gwp_asan_error_is_mine(GPAForSignalHandler->getAllocatorState(),
- reinterpret_cast<uintptr_t>(info->si_addr))) {
- signal(SIGSEGV, SIG_DFL);
- raise(SIGSEGV);
- }
- } else {
- PreviousHandler.sa_handler(sig);
- }
-}
+namespace {
struct ScopedEndOfReportDecorator {
- ScopedEndOfReportDecorator(gwp_asan::crash_handler::Printf_t Printf)
- : Printf(Printf) {}
+ ScopedEndOfReportDecorator(gwp_asan::Printf_t Printf) : Printf(Printf) {}
~ScopedEndOfReportDecorator() { Printf("*** End GWP-ASan report ***\n"); }
- gwp_asan::crash_handler::Printf_t Printf;
+ gwp_asan::Printf_t Printf;
};
// Prints the provided error and metadata information.
@@ -117,47 +85,6 @@ void printHeader(Error E, uintptr_t AccessPtr,
AccessPtr, DescriptionBuffer, ThreadBuffer);
}
-void defaultPrintStackTrace(uintptr_t *Trace, size_t TraceLength,
- gwp_asan::crash_handler::Printf_t Printf) {
- if (TraceLength == 0)
- Printf(" <unknown (does your allocator support backtracing?)>\n");
-
- for (size_t i = 0; i < TraceLength; ++i) {
- Printf(" #%zu 0x%zx in <unknown>\n", i, Trace[i]);
- }
- Printf("\n");
-}
-
-} // anonymous namespace
-
-namespace gwp_asan {
-namespace crash_handler {
-PrintBacktrace_t getBasicPrintBacktraceFunction() {
- return defaultPrintStackTrace;
-}
-
-void installSignalHandlers(gwp_asan::GuardedPoolAllocator *GPA, Printf_t Printf,
- PrintBacktrace_t PrintBacktrace,
- SegvBacktrace_t SegvBacktrace) {
- GPAForSignalHandler = GPA;
- PrintfForSignalHandler = Printf;
- PrintBacktraceForSignalHandler = PrintBacktrace;
- BacktraceForSignalHandler = SegvBacktrace;
-
- struct sigaction Action = {};
- Action.sa_sigaction = sigSegvHandler;
- Action.sa_flags = SA_SIGINFO;
- sigaction(SIGSEGV, &Action, &PreviousHandler);
- SignalHandlerInstalled = true;
-}
-
-void uninstallSignalHandlers() {
- if (SignalHandlerInstalled) {
- sigaction(SIGSEGV, &PreviousHandler, nullptr);
- SignalHandlerInstalled = false;
- }
-}
-
void dumpReport(uintptr_t ErrorPtr, const gwp_asan::AllocatorState *State,
const gwp_asan::AllocationMetadata *Metadata,
SegvBacktrace_t SegvBacktrace, Printf_t Printf,
@@ -205,7 +132,7 @@ void dumpReport(uintptr_t ErrorPtr, const gwp_asan::AllocatorState *State,
// Maybe print the deallocation trace.
if (__gwp_asan_is_deallocated(AllocMeta)) {
uint64_t ThreadID = __gwp_asan_get_deallocation_thread_id(AllocMeta);
- if (ThreadID == kInvalidThreadID)
+ if (ThreadID == gwp_asan::kInvalidThreadID)
Printf("0x%zx was deallocated by thread <unknown> here:\n", ErrorPtr);
else
Printf("0x%zx was deallocated by thread %zu here:\n", ErrorPtr, ThreadID);
@@ -216,7 +143,7 @@ void dumpReport(uintptr_t ErrorPtr, const gwp_asan::AllocatorState *State,
// Print the allocation trace.
uint64_t ThreadID = __gwp_asan_get_allocation_thread_id(AllocMeta);
- if (ThreadID == kInvalidThreadID)
+ if (ThreadID == gwp_asan::kInvalidThreadID)
Printf("0x%zx was allocated by thread <unknown> here:\n", ErrorPtr);
else
Printf("0x%zx was allocated by thread %zu here:\n", ErrorPtr, ThreadID);
@@ -224,5 +151,75 @@ void dumpReport(uintptr_t ErrorPtr, const gwp_asan::AllocatorState *State,
AllocMeta, Trace, kMaximumStackFramesForCrashTrace);
PrintBacktrace(Trace, TraceLength, Printf);
}
-} // namespace crash_handler
+
+struct sigaction PreviousHandler;
+bool SignalHandlerInstalled;
+gwp_asan::GuardedPoolAllocator *GPAForSignalHandler;
+Printf_t PrintfForSignalHandler;
+PrintBacktrace_t PrintBacktraceForSignalHandler;
+SegvBacktrace_t BacktraceForSignalHandler;
+
+static void sigSegvHandler(int sig, siginfo_t *info, void *ucontext) {
+ if (GPAForSignalHandler) {
+ GPAForSignalHandler->stop();
+
+ dumpReport(reinterpret_cast<uintptr_t>(info->si_addr),
+ GPAForSignalHandler->getAllocatorState(),
+ GPAForSignalHandler->getMetadataRegion(),
+ BacktraceForSignalHandler, PrintfForSignalHandler,
+ PrintBacktraceForSignalHandler, ucontext);
+ }
+
+ // Process any previous handlers.
+ if (PreviousHandler.sa_flags & SA_SIGINFO) {
+ PreviousHandler.sa_sigaction(sig, info, ucontext);
+ } else if (PreviousHandler.sa_handler == SIG_DFL) {
+ // If the previous handler was the default handler, cause a core dump.
+ signal(SIGSEGV, SIG_DFL);
+ raise(SIGSEGV);
+ } else if (PreviousHandler.sa_handler == SIG_IGN) {
+ // If the previous segv handler was SIGIGN, crash iff we were responsible
+ // for the crash.
+ if (__gwp_asan_error_is_mine(GPAForSignalHandler->getAllocatorState(),
+ reinterpret_cast<uintptr_t>(info->si_addr))) {
+ signal(SIGSEGV, SIG_DFL);
+ raise(SIGSEGV);
+ }
+ } else {
+ PreviousHandler.sa_handler(sig);
+ }
+}
+} // anonymous namespace
+
+namespace gwp_asan {
+namespace segv_handler {
+
+void installSignalHandlers(gwp_asan::GuardedPoolAllocator *GPA, Printf_t Printf,
+ PrintBacktrace_t PrintBacktrace,
+ SegvBacktrace_t SegvBacktrace) {
+ assert(GPA && "GPA wasn't provided to installSignalHandlers.");
+ assert(Printf && "Printf wasn't provided to installSignalHandlers.");
+ assert(PrintBacktrace &&
+ "PrintBacktrace wasn't provided to installSignalHandlers.");
+ assert(SegvBacktrace &&
+ "SegvBacktrace wasn't provided to installSignalHandlers.");
+ GPAForSignalHandler = GPA;
+ PrintfForSignalHandler = Printf;
+ PrintBacktraceForSignalHandler = PrintBacktrace;
+ BacktraceForSignalHandler = SegvBacktrace;
+
+ struct sigaction Action = {};
+ Action.sa_sigaction = sigSegvHandler;
+ Action.sa_flags = SA_SIGINFO;
+ sigaction(SIGSEGV, &Action, &PreviousHandler);
+ SignalHandlerInstalled = true;
+}
+
+void uninstallSignalHandlers() {
+ if (SignalHandlerInstalled) {
+ sigaction(SIGSEGV, &PreviousHandler, nullptr);
+ SignalHandlerInstalled = false;
+ }
+}
+} // namespace segv_handler
} // namespace gwp_asan
diff --git a/compiler-rt/lib/gwp_asan/tests/CMakeLists.txt b/compiler-rt/lib/gwp_asan/tests/CMakeLists.txt
index f88d90c19d5b..c9634e471d99 100644
--- a/compiler-rt/lib/gwp_asan/tests/CMakeLists.txt
+++ b/compiler-rt/lib/gwp_asan/tests/CMakeLists.txt
@@ -10,7 +10,7 @@ set(GWP_ASAN_UNITTEST_CFLAGS
file(GLOB GWP_ASAN_HEADERS ../*.h)
set(GWP_ASAN_UNITTESTS
- optional/printf_sanitizer_common.cpp
+ platform_specific/printf_sanitizer_common.cpp
alignment.cpp
backtrace.cpp
basic.cpp
diff --git a/compiler-rt/lib/gwp_asan/tests/harness.h b/compiler-rt/lib/gwp_asan/tests/harness.h
index 26be4a40faf3..a61b856c6a38 100644
--- a/compiler-rt/lib/gwp_asan/tests/harness.h
+++ b/compiler-rt/lib/gwp_asan/tests/harness.h
@@ -21,6 +21,7 @@ using Test = ::testing::Test;
#include "gwp_asan/guarded_pool_allocator.h"
#include "gwp_asan/optional/backtrace.h"
+#include "gwp_asan/optional/printf.h"
#include "gwp_asan/optional/segv_handler.h"
#include "gwp_asan/options.h"
@@ -30,7 +31,7 @@ namespace test {
// their own signal-safe Printf function. In LLVM, we use
// `optional/printf_sanitizer_common.cpp` which supplies the __sanitizer::Printf
// for this purpose.
-crash_handler::Printf_t getPrintfFunction();
+Printf_t getPrintfFunction();
// First call returns true, all the following calls return false.
bool OnlyOnce();
@@ -86,19 +87,19 @@ class BacktraceGuardedPoolAllocator : public Test {
gwp_asan::options::Options Opts;
Opts.setDefaults();
- Opts.Backtrace = gwp_asan::options::getBacktraceFunction();
+ Opts.Backtrace = gwp_asan::backtrace::getBacktraceFunction();
Opts.InstallForkHandlers = gwp_asan::test::OnlyOnce();
GPA.init(Opts);
- gwp_asan::crash_handler::installSignalHandlers(
+ gwp_asan::segv_handler::installSignalHandlers(
&GPA, gwp_asan::test::getPrintfFunction(),
- gwp_asan::options::getPrintBacktraceFunction(),
- gwp_asan::crash_handler::getSegvBacktraceFunction());
+ gwp_asan::backtrace::getPrintBacktraceFunction(),
+ gwp_asan::backtrace::getSegvBacktraceFunction());
}
void TearDown() override {
GPA.uninitTestOnly();
- gwp_asan::crash_handler::uninstallSignalHandlers();
+ gwp_asan::segv_handler::uninstallSignalHandlers();
}
protected:
diff --git a/compiler-rt/lib/gwp_asan/tests/optional/printf_sanitizer_common.cpp b/compiler-rt/lib/gwp_asan/tests/platform_specific/printf_sanitizer_common.cpp
similarity index 52%
rename from compiler-rt/lib/gwp_asan/tests/optional/printf_sanitizer_common.cpp
rename to compiler-rt/lib/gwp_asan/tests/platform_specific/printf_sanitizer_common.cpp
index ea7141b46ac8..102b1dbfe511 100644
--- a/compiler-rt/lib/gwp_asan/tests/optional/printf_sanitizer_common.cpp
+++ b/compiler-rt/lib/gwp_asan/tests/platform_specific/printf_sanitizer_common.cpp
@@ -6,15 +6,14 @@
//
//===----------------------------------------------------------------------===//
-#include "gwp_asan/optional/segv_handler.h"
+#include "gwp_asan/optional/printf.h"
+
#include "sanitizer_common/sanitizer_common.h"
namespace gwp_asan {
namespace test {
-// This printf-function getter allows other platforms (e.g. Android) to define
-// their own signal-safe Printf function. In LLVM, we use
-// `optional/printf_sanitizer_common.cpp` which supplies the __sanitizer::Printf
-// for this purpose.
-crash_handler::Printf_t getPrintfFunction() { return __sanitizer::Printf; }
-}; // namespace test
-}; // namespace gwp_asan
+
+Printf_t getPrintfFunction() { return __sanitizer::Printf; }
+
+} // namespace test
+} // namespace gwp_asan
diff --git a/compiler-rt/lib/scudo/scudo_allocator.cpp b/compiler-rt/lib/scudo/scudo_allocator.cpp
index c6a3309cb925..954e51bdee63 100644
--- a/compiler-rt/lib/scudo/scudo_allocator.cpp
+++ b/compiler-rt/lib/scudo/scudo_allocator.cpp
@@ -674,14 +674,14 @@ void initScudo() {
#ifdef GWP_ASAN_HOOKS
gwp_asan::options::initOptions();
gwp_asan::options::Options &Opts = gwp_asan::options::getOptions();
- Opts.Backtrace = gwp_asan::options::getBacktraceFunction();
+ Opts.Backtrace = gwp_asan::backtrace::getBacktraceFunction();
GuardedAlloc.init(Opts);
if (Opts.InstallSignalHandlers)
- gwp_asan::crash_handler::installSignalHandlers(
+ gwp_asan::segv_handler::installSignalHandlers(
&GuardedAlloc, __sanitizer::Printf,
- gwp_asan::options::getPrintBacktraceFunction(),
- gwp_asan::crash_handler::getSegvBacktraceFunction());
+ gwp_asan::backtrace::getPrintBacktraceFunction(),
+ gwp_asan::backtrace::getSegvBacktraceFunction());
#endif // GWP_ASAN_HOOKS
}
diff --git a/compiler-rt/lib/scudo/standalone/combined.h b/compiler-rt/lib/scudo/standalone/combined.h
index 911c49dcc3fd..11370be3fb4a 100644
--- a/compiler-rt/lib/scudo/standalone/combined.h
+++ b/compiler-rt/lib/scudo/standalone/combined.h
@@ -198,13 +198,14 @@ class Allocator {
// Allocator::disable calling GWPASan.disable). Disable GWP-ASan's atfork
// handler.
Opt.InstallForkHandlers = false;
- Opt.Backtrace = gwp_asan::options::getBacktraceFunction();
+ Opt.Backtrace = gwp_asan::backtrace::getBacktraceFunction();
GuardedAlloc.init(Opt);
if (Opt.InstallSignalHandlers)
- gwp_asan::crash_handler::installSignalHandlers(
- &GuardedAlloc, Printf, gwp_asan::options::getPrintBacktraceFunction(),
- gwp_asan::crash_handler::getSegvBacktraceFunction());
+ gwp_asan::segv_handler::installSignalHandlers(
+ &GuardedAlloc, Printf,
+ gwp_asan::backtrace::getPrintBacktraceFunction(),
+ gwp_asan::backtrace::getSegvBacktraceFunction());
#endif // GWP_ASAN_HOOKS
}
@@ -219,7 +220,7 @@ class Allocator {
Primary.unmapTestOnly();
#ifdef GWP_ASAN_HOOKS
if (getFlags()->GWP_ASAN_InstallSignalHandlers)
- gwp_asan::crash_handler::uninstallSignalHandlers();
+ gwp_asan::segv_handler::uninstallSignalHandlers();
GuardedAlloc.uninitTestOnly();
#endif // GWP_ASAN_HOOKS
}
More information about the llvm-branch-commits
mailing list