[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

GitOrigin-RevId: a8520f6970fd4d44ceae1ec5969563a0dbe30f54
diff --git a/optional/backtrace.h b/optional/backtrace.h
index 3a72eb3..9bb12af 100644
--- a/optional/backtrace.h
+++ b/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/optional/backtrace_fuchsia.cpp b/optional/backtrace_fuchsia.cpp
index ac7ed6c..879312a 100644
--- a/optional/backtrace_fuchsia.cpp
+++ b/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/optional/backtrace_linux_libc.cpp b/optional/backtrace_linux_libc.cpp
index 92eb293..ea8e72b 100644
--- a/optional/backtrace_linux_libc.cpp
+++ b/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 @@
 }
 
 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 @@
 } // 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/optional/backtrace_sanitizer_common.cpp b/optional/backtrace_sanitizer_common.cpp
index a8083e4..e6cce86 100644
--- a/optional/backtrace_sanitizer_common.cpp
+++ b/optional/backtrace_sanitizer_common.cpp
@@ -62,7 +62,7 @@
 }
 
 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 @@
 } // 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/optional/printf.h b/optional/printf.h
new file mode 100644
index 0000000..1004a2c
--- /dev/null
+++ b/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 different 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/optional/segv_handler.h b/optional/segv_handler.h
index e1d96a6..87d9fe1 100644
--- a/optional/segv_handler.h
+++ b/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 different 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 @@
 // 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/optional/segv_handler_fuchsia.cpp b/optional/segv_handler_fuchsia.cpp
index ec26afa..966d7d0 100644
--- a/optional/segv_handler_fuchsia.cpp
+++ b/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/optional/segv_handler_posix.cpp b/optional/segv_handler_posix.cpp
index 8d9f39a..5c9bb9f 100644
--- a/optional/segv_handler_posix.cpp
+++ b/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;
+using gwp_asan::Printf_t;
+using gwp_asan::backtrace::PrintBacktrace_t;
+using gwp_asan::backtrace::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);
-  }
-
-  // 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 @@
          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 @@
   // 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 @@
 
   // 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 @@
       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/tests/harness.h b/tests/harness.h
index 26be4a4..a61b856 100644
--- a/tests/harness.h
+++ b/tests/harness.h
@@ -21,6 +21,7 @@
 
 #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 @@
 // 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 @@
     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/tests/optional/printf_sanitizer_common.cpp b/tests/optional/printf_sanitizer_common.cpp
deleted file mode 100644
index ea7141b..0000000
--- a/tests/optional/printf_sanitizer_common.cpp
+++ /dev/null
@@ -1,20 +0,0 @@
-//===-- printf_sanitizer_common.cpp -----------------------------*- 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
-//
-//===----------------------------------------------------------------------===//
-
-#include "gwp_asan/optional/segv_handler.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
diff --git a/tests/platform_specific/printf_sanitizer_common.cpp b/tests/platform_specific/printf_sanitizer_common.cpp
new file mode 100644
index 0000000..102b1db
--- /dev/null
+++ b/tests/platform_specific/printf_sanitizer_common.cpp
@@ -0,0 +1,19 @@
+//===-- printf_sanitizer_common.cpp -----------------------------*- 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
+//
+//===----------------------------------------------------------------------===//
+
+#include "gwp_asan/optional/printf.h"
+
+#include "sanitizer_common/sanitizer_common.h"
+
+namespace gwp_asan {
+namespace test {
+
+Printf_t getPrintfFunction() { return __sanitizer::Printf; }
+
+} // namespace test
+} // namespace gwp_asan