Factoring out signal handling. (#84)

diff --git a/demos/l1tf.cc b/demos/l1tf.cc
index 6fc7593..65c245e 100644
--- a/demos/l1tf.cc
+++ b/demos/l1tf.cc
@@ -37,6 +37,7 @@
 #include "cache_sidechannel.h"
 #include "instr.h"
 #include "local_content.h"
+#include "meltdown_local_content.h"
 #include "utils.h"
 
 char *private_page = nullptr;
@@ -99,34 +100,8 @@
   }
 }
 
-static void Sigsegv(
-    int /* signum */, siginfo_t * /* siginfo */, void *context) {
-  // SIGSEGV signal handler.
-  // Moves the instruction pointer to the "afterspeculation" label.
-  ucontext_t *ucontext = static_cast<ucontext_t *>(context);
-#if SAFESIDE_X64
-  ucontext->uc_mcontext.gregs[REG_RIP] =
-      reinterpret_cast<greg_t>(afterspeculation);
-#elif SAFESIDE_IA32
-  ucontext->uc_mcontext.gregs[REG_EIP] =
-      reinterpret_cast<greg_t>(afterspeculation);
-#elif SAFESIDE_PPC
-  ucontext->uc_mcontext.regs->nip =
-      reinterpret_cast<size_t>(afterspeculation);
-#else
-#  error Unsupported CPU.
-#endif
-}
-
-static void SetSignal() {
-  struct sigaction act;
-  act.sa_sigaction = Sigsegv;
-  act.sa_flags = SA_SIGINFO;
-  sigaction(SIGSEGV, &act, NULL);
-}
-
 int main() {
-  SetSignal();
+  OnSignalMoveRipToAfterspeculation(SIGSEGV);
   private_page = reinterpret_cast<char *>(mmap(nullptr, kPageSizeBytes,
       PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
   memcpy(private_page, private_data, strlen(private_data) + 1);
diff --git a/demos/local_content.h b/demos/local_content.h
index f34d355..33aa4c4 100644
--- a/demos/local_content.h
+++ b/demos/local_content.h
@@ -13,11 +13,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#ifndef DEMOS_LOCAL_LABELS_H
-#define DEMOS_LOCAL_LABELS_H
 
-#include "compiler_specifics.h"
-
+#ifndef DEMOS_LOCAL_CONTENT_H
+#define DEMOS_LOCAL_CONTENT_H
 // Generic strings used across examples. The public_data is intended to be
 // accessed in the C++ execution model. The content of the private_data is
 // intended to be leaked outside of the C++ execution model using sidechannels.
@@ -25,23 +23,4 @@
 // demonstrating.
 const char *public_data = "Hello, world!";
 const char *private_data = "It's a s3kr3t!!!";
-
-#if SAFESIDE_ARM64
-// Local handler necessary for avoiding local/global linking mismatches on ARM.
-// When we use extern char[] declaration for a label defined in assembly, the
-// compiler yields this sequence that fails loading the actual address of the
-// label:
-// adrp x0, :got:label
-// ldr x0, [x0, #:got_lo12:label]
-// On the other hand when we use this local handler, the compiler yield this
-// sequence of instructions:
-// adrp x0, label
-// add x0, x0, :lo12:label
-// and that works correctly because it if an effective equivalent of
-// adr x0, label.
-static void LocalHandler() {
-  asm volatile("b afterspeculation");
-}
-#endif
-
-#endif  // DEMOS_LOCAL_LABELS_H
+#endif  // DEMOS_LOCAL_CONTENT_H
diff --git a/demos/meltdown.cc b/demos/meltdown.cc
index 541439a..ebf48ae 100644
--- a/demos/meltdown.cc
+++ b/demos/meltdown.cc
@@ -34,6 +34,7 @@
 #include "cache_sidechannel.h"
 #include "instr.h"
 #include "local_content.h"
+#include "meltdown_local_content.h"
 #include "utils.h"
 
 // Leaks the byte that is physically located at &text[0] + offset, without
@@ -81,32 +82,6 @@
   }
 }
 
-static void Sigsegv(
-    int /* signum */, siginfo_t * /* siginfo */, void *context) {
-  // SIGSEGV signal handler.
-  // Moves the instruction pointer to the "afterspeculation" label.
-  ucontext_t *ucontext = static_cast<ucontext_t *>(context);
-#if SAFESIDE_X64
-  ucontext->uc_mcontext.gregs[REG_RIP] =
-      reinterpret_cast<greg_t>(afterspeculation);
-#elif SAFESIDE_IA32
-  ucontext->uc_mcontext.gregs[REG_EIP] =
-      reinterpret_cast<greg_t>(afterspeculation);
-#elif SAFESIDE_PPC
-  ucontext->uc_mcontext.regs->nip =
-      reinterpret_cast<size_t>(afterspeculation);
-#else
-#  error Unsupported CPU.
-#endif
-}
-
-static void SetSignal() {
-  struct sigaction act;
-  act.sa_sigaction = Sigsegv;
-  act.sa_flags = SA_SIGINFO;
-  sigaction(SIGSEGV, &act, NULL);
-}
-
 int main() {
   size_t private_data, private_length;
   std::ifstream in("/proc/safeside_meltdown/address");
@@ -122,7 +97,7 @@
   in >> std::dec >> private_length;
   in.close();
 
-  SetSignal();
+  OnSignalMoveRipToAfterspeculation(SIGSEGV);
   std::cout << "Leaking the string: ";
   std::cout.flush();
   const size_t private_offset =
diff --git a/demos/meltdown_ac.cc b/demos/meltdown_ac.cc
index 8624ec1..9051215 100644
--- a/demos/meltdown_ac.cc
+++ b/demos/meltdown_ac.cc
@@ -49,6 +49,7 @@
 #include "cache_sidechannel.h"
 #include "instr.h"
 #include "local_content.h"
+#include "meltdown_local_content.h"
 #include "utils.h"
 
 // Storage for the public data.
@@ -123,30 +124,9 @@
   }
 }
 
-static void sigbus(
-    int /* signum */, siginfo_t * /* siginfo */, void *context) {
-  // SIGBUS signal handler.
-  // Moves the instruction pointer to the "afterspeculation" label.
-  ucontext_t *ucontext = static_cast<ucontext_t *>(context);
-#if SAFESIDE_X64
-  ucontext->uc_mcontext.gregs[REG_RIP] =
-      reinterpret_cast<greg_t>(afterspeculation);
-#else
-  ucontext->uc_mcontext.gregs[REG_EIP] =
-      reinterpret_cast<greg_t>(afterspeculation);
-#endif
-}
-
-static void SetSignal() {
-  struct sigaction act;
-  act.sa_sigaction = sigbus;
-  act.sa_flags = SA_SIGINFO;
-  sigaction(SIGBUS, &act, NULL);
-}
-
 int main() {
   InitializeUnalignedData();
-  SetSignal();
+  OnSignalMoveRipToAfterspeculation(SIGBUS);
   std::cout << "Leaking the string: ";
   std::cout.flush();
   size_t private_offset = unaligned_private_data - unaligned_public_data;
diff --git a/demos/meltdown_br.cc b/demos/meltdown_br.cc
index 8d84bc2..ac97256 100644
--- a/demos/meltdown_br.cc
+++ b/demos/meltdown_br.cc
@@ -43,6 +43,7 @@
 #include "cache_sidechannel.h"
 #include "instr.h"
 #include "local_content.h"
+#include "meltdown_local_content.h"
 #include "utils.h"
 
 // ICC requires the offset variable to be volatile. If it isn't, ICC schedules
@@ -99,38 +100,14 @@
   }
 }
 
-static void Sigsegv(
-    int /* signum */, siginfo_t * /* siginfo */, void *context) {
-  // SIGSEGV signal handler.
-  // Moves the instruction pointer to the "afterspeculation" label.
-  ucontext_t *ucontext = static_cast<ucontext_t *>(context);
-#if SAFESIDE_LINUX
-  ucontext->uc_mcontext.gregs[REG_EIP] =
-      reinterpret_cast<greg_t>(afterspeculation);
-#elif SAFESIDE_MAC
-  ucontext->uc_mcontext->__ss.__eip =
-      reinterpret_cast<uintptr_t>(afterspeculation);
-#else
-#  error Unsupported OS.
-#endif
-}
-
-static void SetSignal() {
-  struct sigaction act;
-  memset(&act, 0, sizeof(struct sigaction));
-  act.sa_sigaction = Sigsegv;
-  act.sa_flags = SA_SIGINFO;
-#if SAFESIDE_LINUX
-  sigaction(SIGSEGV, &act, nullptr);
-#elif SAFESIDE_MAC
-  sigaction(SIGTRAP, &act, nullptr);
-#else
-#  error Unsupported OS.
-#endif
-}
-
 int main() {
-  SetSignal();
+#if SAFESIDE_LINUX
+  OnSignalMoveRipToAfterspeculation(SIGSEGV);
+#elif SAFESIDE_MAC
+  OnSignalMoveRipToAfterspeculation(SIGTRAP);
+#else
+#  error Unsupported OS.
+#endif
   std::cout << "Leaking the string: ";
   std::cout.flush();
   size_t private_offset = private_data - public_data;
diff --git a/demos/meltdown_de.cc b/demos/meltdown_de.cc
index cbbd66d..8ac8cf6 100644
--- a/demos/meltdown_de.cc
+++ b/demos/meltdown_de.cc
@@ -68,6 +68,7 @@
 
 #include "cache_sidechannel.h"
 #include "instr.h"
+#include "meltdown_local_content.h"
 #include "utils.h"
 
 const char *public_data = "Hello, world!";
@@ -142,31 +143,8 @@
   }
 }
 
-static void Sigfpe(
-    int /* signum */, siginfo_t * /* siginfo */, void *context) {
-  // SIGFPE signal handler.
-  // Moves the instruction pointer to the "afterspeculation" label.
-  ucontext_t *ucontext = static_cast<ucontext_t *>(context);
-#if SAFESIDE_X64
-  ucontext->uc_mcontext.gregs[REG_RIP] =
-      reinterpret_cast<greg_t>(afterspeculation);
-#elif SAFESIDE_IA32
-  ucontext->uc_mcontext.gregs[REG_EIP] =
-      reinterpret_cast<greg_t>(afterspeculation);
-#else
-#  error Unsupported architecture.
-#endif
-}
-
-static void SetSignal() {
-  struct sigaction act;
-  act.sa_sigaction = Sigfpe;
-  act.sa_flags = SA_SIGINFO;
-  sigaction(SIGFPE, &act, NULL);
-}
-
 int main() {
-  SetSignal();
+  OnSignalMoveRipToAfterspeculation(SIGFPE);
   std::cout << "Leaking the string: ";
   std::cout.flush();
   for (size_t i = 0; i < kPrivateDataLength; ++i) {
diff --git a/demos/meltdown_local_content.h b/demos/meltdown_local_content.h
new file mode 100644
index 0000000..deafa2a
--- /dev/null
+++ b/demos/meltdown_local_content.h
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2019 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *   https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef DEMOS_MELTDOWN_LOCAL_CONTENT_H
+#define DEMOS_MELTDOWN_LOCAL_CONTENT_H
+
+#include "compiler_specifics.h"
+
+#if SAFESIDE_LINUX || SAFESIDE_MAC
+#include <signal.h>
+#endif
+
+#if SAFESIDE_ARM64
+// Local handler necessary for avoiding local/global linking mismatches on ARM.
+// When we use extern char[] declaration for a label defined in assembly, the
+// compiler yields this sequence that fails loading the actual address of the
+// label:
+// adrp x0, :got:label
+// ldr x0, [x0, #:got_lo12:label]
+// On the other hand when we use this local handler, the compiler yield this
+// sequence of instructions:
+// adrp x0, label
+// add x0, x0, :lo12:label
+// and that works correctly because it if an effective equivalent of
+// adr x0, label.
+static void LocalHandler() {
+  asm volatile("b afterspeculation");
+}
+#endif
+
+static void SignalHandler(
+    int /* signum */, siginfo_t * /* siginfo */, void *context) {
+  // On IA32, X64 and PPC moves the instruction pointer to the
+  // "afterspeculation" label. On ARM64 moves the instruction pointer to the
+  // "LocalHandler" label.
+  ucontext_t *ucontext = static_cast<ucontext_t *>(context);
+#if SAFESIDE_LINUX && SAFESIDE_IA32
+  ucontext->uc_mcontext.gregs[REG_EIP] =
+      reinterpret_cast<greg_t>(afterspeculation);
+#elif SAFESIDE_LINUX && SAFESIDE_X64
+  ucontext->uc_mcontext.gregs[REG_RIP] =
+      reinterpret_cast<greg_t>(afterspeculation);
+#elif SAFESIDE_LINUX && SAFESIDE_ARM64
+  ucontext->uc_mcontext.pc = reinterpret_cast<greg_t>(LocalHandler);
+#elif SAFESIDE_LINUX && SAFESIDE_PPC
+  ucontext->uc_mcontext.regs->nip =
+      reinterpret_cast<uintptr_t>(afterspeculation);
+#elif SAFESIDE_MAC && SAFESIDE_IA32
+  ucontext->uc_mcontext->__ss.__eip =
+      reinterpret_cast<uintptr_t>(afterspeculation);
+#elif SAFESIDE_MAC && SAFESIDE_X64
+  ucontext->uc_mcontext->__ss.__rip =
+      reinterpret_cast<uintptr_t>(afterspeculation);
+#else
+#  error Unsupported OS/CPU combination.
+#endif
+}
+
+// Sets up signal handling that moves the instruction pointer to the
+// afterspeculation (or LocalHandler in case of ARM) label. See the commentary
+// to LocalHandler function why we must treat ARM differently.
+static void OnSignalMoveRipToAfterspeculation(int signal) {
+  struct sigaction act;
+  memset(&act, 0, sizeof(struct sigaction));
+  act.sa_sigaction = SignalHandler;
+  act.sa_flags = SA_SIGINFO;
+  sigaction(signal, &act, nullptr);
+}
+#endif  // DEMOS_MELTDOWN_LOCAL_CONTENT_H
diff --git a/demos/meltdown_of.cc b/demos/meltdown_of.cc
index e5f6173..55c2096 100644
--- a/demos/meltdown_of.cc
+++ b/demos/meltdown_of.cc
@@ -44,6 +44,7 @@
 
 #include "cache_sidechannel.h"
 #include "instr.h"
+#include "meltdown_local_content.h"
 #include "local_content.h"
 
 static char LeakByte(const char *data, size_t offset) {
@@ -78,9 +79,9 @@
       }
 
       // SIGSEGV signal handler moves the instruction pointer to this label.
-#ifdef __linux__
+#if SAFESIDE_LINUX
       asm volatile("afterspeculation:");
-#elif defined(__APPLE__)
+#elif SAFESIDE_MAC
       asm volatile("_afterspeculation:");
 #else
 #  error Unsupported OS.
@@ -101,37 +102,14 @@
   }
 }
 
-static void Sigsegv(
-    int /* signum */, siginfo_t * /* siginfo */, void *context) {
-  // SIGSEGV signal handler.
-  // Moves the instruction pointer to the "afterspeculation" label.
-  ucontext_t *ucontext = static_cast<ucontext_t *>(context);
-#ifdef __linux__
-  ucontext->uc_mcontext.gregs[REG_EIP] =
-      reinterpret_cast<greg_t>(afterspeculation);
-#elif defined(__APPLE__)
-  ucontext->uc_mcontext->__ss.__eip =
-      reinterpret_cast<uintptr_t>(afterspeculation);
-#else
-#  error Unsupported OS.
-#endif
-}
-
-static void SetSignal() {
-  struct sigaction act;
-  act.sa_sigaction = Sigsegv;
-  act.sa_flags = SA_SIGINFO;
-#ifdef __linux__
-  sigaction(SIGSEGV, &act, nullptr);
-#elif defined(__APPLE__)
-  sigaction(SIGFPE, &act, nullptr);
-#else
-#  error Unsupported OS.
-#endif
-}
-
 int main() {
-  SetSignal();
+#if SAFESIDE_LINUX
+  OnSignalMoveRipToAfterspeculation(SIGSEGV);
+#elif SAFESIDE_MAC
+  OnSignalMoveRipToAfterspeculation(SIGFPE);
+#else
+#  error Unsupported OS.
+#endif
   std::cout << "Leaking the string: ";
   std::cout.flush();
   const size_t private_offset = private_data - public_data;
diff --git a/demos/meltdown_ss.cc b/demos/meltdown_ss.cc
index 5ff302f..283a1bc 100644
--- a/demos/meltdown_ss.cc
+++ b/demos/meltdown_ss.cc
@@ -51,6 +51,7 @@
 #include "cache_sidechannel.h"
 #include "instr.h"
 #include "local_content.h"
+#include "meltdown_local_content.h"
 #include "utils.h"
 
 // Sets up a segment descriptor in the local descriptor table.
@@ -154,24 +155,8 @@
   }
 }
 
-static void Sigsegv(
-    int /* signum */, siginfo_t * /* siginfo */, void *context) {
-  // SIGSEGV signal handler.
-  // Moves the instruction pointer to the "afterspeculation" label.
-  ucontext_t *ucontext = static_cast<ucontext_t *>(context);
-  ucontext->uc_mcontext.gregs[REG_EIP] =
-      reinterpret_cast<greg_t>(afterspeculation);
-}
-
-static void SetSignal() {
-  struct sigaction act;
-  act.sa_sigaction = Sigsegv;
-  act.sa_flags = SA_SIGINFO;
-  sigaction(SIGSEGV, &act, NULL);
-}
-
 int main() {
-  SetSignal();
+  OnSignalMoveRipToAfterspeculation(SIGSEGV);
   // Setup the public data segment descriptor on index 0. It is always present.
   SetupSegment(0, public_data, true);
   std::cout << "Leaking the string: ";
diff --git a/demos/meltdown_ud.cc b/demos/meltdown_ud.cc
index ed19dec..6370b55 100644
--- a/demos/meltdown_ud.cc
+++ b/demos/meltdown_ud.cc
@@ -34,6 +34,7 @@
 #include "cache_sidechannel.h"
 #include "instr.h"
 #include "local_content.h"
+#include "meltdown_local_content.h"
 #include "utils.h"
 
 static char LeakByte(const char *data, size_t offset) {
@@ -79,24 +80,8 @@
   }
 }
 
-static void Sigill(
-    int /* signum */, siginfo_t * /* siginfo */, void *context) {
-  // SIGILL signal handler.
-  // Moves the instruction pointer to the "afterspeculation" label jumping to
-  // the "LocalHandler" function.
-  ucontext_t *ucontext = static_cast<ucontext_t *>(context);
-  ucontext->uc_mcontext.pc = reinterpret_cast<greg_t>(LocalHandler);
-}
-
-static void SetSignal() {
-  struct sigaction act;
-  act.sa_sigaction = Sigill;
-  act.sa_flags = SA_SIGINFO;
-  sigaction(SIGILL, &act, NULL);
-}
-
 int main() {
-  SetSignal();
+  OnSignalMoveRipToAfterspeculation(SIGILL);
   std::cout << "Leaking the string: ";
   std::cout.flush();
   const size_t private_offset = private_data - public_data;
diff --git a/demos/speculation_over_hw_breakpoint.cc b/demos/speculation_over_hw_breakpoint.cc
index 830e9a9..05a87e4 100644
--- a/demos/speculation_over_hw_breakpoint.cc
+++ b/demos/speculation_over_hw_breakpoint.cc
@@ -46,6 +46,7 @@
 #include "cache_sidechannel.h"
 #include "instr.h"
 #include "local_content.h"
+#include "meltdown_local_content.h"
 #include "utils.h"
 
 static char LeakByte(const char *data, size_t data_length, size_t offset) {
diff --git a/demos/speculation_over_sw_breakpoint.cc b/demos/speculation_over_sw_breakpoint.cc
index 3721124..425a9c4 100644
--- a/demos/speculation_over_sw_breakpoint.cc
+++ b/demos/speculation_over_sw_breakpoint.cc
@@ -39,6 +39,7 @@
 #include "cache_sidechannel.h"
 #include "instr.h"
 #include "local_content.h"
+#include "meltdown_local_content.h"
 
 static char LeakByte(const char *data, size_t offset) {
   CacheSideChannel sidechannel;
@@ -87,24 +88,8 @@
   }
 }
 
-static void Sigtrap(
-    int /* signum */, siginfo_t * /* siginfo */, void *context) {
-  // SIGTRAP signal handler.
-  // Moves the instruction pointer to the "afterspeculation" label jumping to
-  // the "LocalHandler" function.
-  ucontext_t *ucontext = static_cast<ucontext_t *>(context);
-  ucontext->uc_mcontext.pc = reinterpret_cast<greg_t>(LocalHandler);
-}
-
-static void SetSignal() {
-  struct sigaction act;
-  act.sa_sigaction = Sigtrap;
-  act.sa_flags = SA_SIGINFO;
-  sigaction(SIGTRAP, &act, NULL);
-}
-
 int main() {
-  SetSignal();
+  OnSignalMoveRipToAfterspeculation(SIGTRAP);
   std::cout << "Leaking the string: ";
   std::cout.flush();
   const size_t private_offset = private_data - public_data;
diff --git a/demos/speculation_over_syscall.cc b/demos/speculation_over_syscall.cc
index 80c24df..0f81d18 100644
--- a/demos/speculation_over_syscall.cc
+++ b/demos/speculation_over_syscall.cc
@@ -36,6 +36,7 @@
 #include "cache_sidechannel.h"
 #include "instr.h"
 #include "local_content.h"
+#include "meltdown_local_content.h"
 #include "utils.h"
 
 static char LeakByte(const char *data, size_t offset) {
@@ -88,24 +89,8 @@
   }
 }
 
-static void Sigusr1(
-    int /* signum */, siginfo_t * /* siginfo */, void *context) {
-  // SIGUSR1 signal handler.
-  // Moves the instruction pointer to the "afterspeculation" label jumping to
-  // the "LocalHandler" function.
-  ucontext_t *ucontext = static_cast<ucontext_t *>(context);
-  ucontext->uc_mcontext.pc = reinterpret_cast<greg_t>(LocalHandler);
-}
-
-static void SetSignal() {
-  struct sigaction act;
-  act.sa_sigaction = Sigusr1;
-  act.sa_flags = SA_SIGINFO;
-  sigaction(SIGUSR1, &act, NULL);
-}
-
 int main() {
-  SetSignal();
+  OnSignalMoveRipToAfterspeculation(SIGUSR1);
   std::cout << "Leaking the string: ";
   std::cout.flush();
   const size_t private_offset = private_data - public_data;