gold/
[deliverable/binutils-gdb.git] / gold / testsuite / relro_test.cc
index d1bd9dd1db085ba73505d4de4cd7a05c783056b0..795ad391097ec4a8c6e17e32c7800250d2967005 100644 (file)
 
 #include <cassert>
 #include <csignal>
+#include <cstdio>
+#include <cstdlib>
+#include <exception>
 #include <stdint.h>
 #include <unistd.h>
 
+// This tests we were linked with a script.  If we were linked with a
+// script, relro currently does not work.
+
+extern char using_script[] __attribute__ ((weak));
+
 // This code is put into a shared library linked with -z relro.
 
 // i1 and i2 are not relro variables.
@@ -32,16 +40,22 @@ int i1 = 1;
 static int i2 = 2;
 
 // P1 is a global relro variable.
-int* const p1 = &i1;
+int* const p1 __attribute__ ((aligned(64))) = &i1;
 
 // P2 is a local relro variable.
-int* const p2 = &i2;
+int* const p2 __attribute__ ((aligned(64))) = &i2;
+
+// Add a TLS variable to make sure -z relro works correctly with TLS.
+__thread int i3 = 1;
 
 // Test symbol addresses.
 
 bool
 t1()
 {
+  if (using_script)
+    return true;
+
   void* i1addr = static_cast<void*>(&i1);
   void* i2addr = static_cast<void*>(&i2);
   const void* p1addr = static_cast<const void*>(&p1);
@@ -65,19 +79,47 @@ t1()
   assert(i1page != p2page);
   assert(i2page != p1page);
   assert(i2page != p2page);
+  assert(i3 == 1);
 
   return true;
 }
 
+// Tell terminate handler that we are throwing from a signal handler.
+
+static bool throwing;
+
 // A signal handler for SIGSEGV.
 
 extern "C"
 void
 sigsegv_handler(int)
 {
+  throwing = true;
   throw 0;
 }
 
+// The original terminate handler.
+
+std::terminate_handler orig_terminate;
+
+// Throwing an exception out of a signal handler doesn't always work
+// reliably.  When that happens the program will call terminate.  We
+// set a terminate handler to indicate that the test probably passed.
+
+void
+terminate_handler()
+{
+  if (!throwing)
+    {
+      orig_terminate();
+      ::exit(EXIT_FAILURE);
+    }
+  fprintf(stderr,
+         "relro_test: terminate called due to failure to throw through signal handler\n");
+  fprintf(stderr, "relro_test: assuming test succeeded\n");
+  ::exit(EXIT_SUCCESS);
+}
+
 // Use a separate function to throw the exception, so that we don't
 // need to use -fnon-call-exceptions.
 
@@ -99,7 +141,11 @@ f2()
 bool
 t2()
 {
+  if (using_script)
+    return true;
+
   signal(SIGSEGV, sigsegv_handler);
+  orig_terminate = std::set_terminate(terminate_handler);
 
   try
     {
This page took 0.024944 seconds and 4 git commands to generate.