Fix a typo.
[binutils-gdb.git] / gold / testsuite / relro_test.cc
index d1bd9dd1db085ba73505d4de4cd7a05c783056b0..bc6c77b91ebeb8aae810aeacca72d5f6f3cf4a59 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.
@@ -42,6 +50,9 @@ int* const p2 = &i2;
 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);
@@ -69,15 +80,42 @@ t1()
   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 +137,11 @@ f2()
 bool
 t2()
 {
+  if (using_script)
+    return true;
+
   signal(SIGSEGV, sigsegv_handler);
+  orig_terminate = std::set_terminate(terminate_handler);
 
   try
     {