[compiler-rt] a8520f6 - [GWP-ASan] Minor refactor of optional components.

Mitch Phillips via llvm-commits llvm-commits at lists.llvm.org
Thu Jan 14 11:14:39 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-commits mailing list