aboutsummaryrefslogtreecommitdiff
path: root/gold/testsuite/relro_test.cc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>2008-05-20 04:00:47 +0000
committerIan Lance Taylor <ian@airs.com>2008-05-20 04:00:47 +0000
commit9f1d377b33ab688f86e1cc9a454d87f991d65f19 (patch)
treec1b3a61a840a01d29858641f0db6b017124501d4 /gold/testsuite/relro_test.cc
parent3285cf2c2fa75927a67ef845d47f5eb81770ac21 (diff)
downloadbinutils-9f1d377b33ab688f86e1cc9a454d87f991d65f19.zip
binutils-9f1d377b33ab688f86e1cc9a454d87f991d65f19.tar.gz
binutils-9f1d377b33ab688f86e1cc9a454d87f991d65f19.tar.bz2
* options.h (class General_options): Add -z relro.
* layout.cc (Layout::Layout): Initialize relro_segment_. (Layout::add_output_section_data): Return the output section. (Layout::make_output_section): Rcognize relro sections and mark them appropriately. (Layout::attach_allocated_section_to_segment): Put relro sections in a PT_GNU_RELRO segment. (Layout::create_initial_dynamic_sections): Mark the .dynamic section as relro. (Layout::segment_precedes): Sort PT_GNU_RELRO segments after PT_TLS segments. (Layout::linkonce_mapping): Map d.rel.ro.local to .data.rel.ro.local. (Layout::output_section_name): Us .data.rel.ro.local for any section which begins with that. * layout.h (class Layout): Update add_output_section_data declaration. Add relro_segment_ field. * output.cc (Output_section::Output_section): Initialize is_relro_ and is_relro_local_ fields. (Output_segment::add_output_section): Group relro sections. (Output_segment::is_first_section_relro): New function. (Output_segment::maximum_alignment): If there is a relro section, align the segment to the common page size. (Output_segment::set_section_addresses): Track whether we are looking at relro sections. If the last section is a relro section, align to the common page size. (Output_segment::set_section_list_addresses): Add in_relro parameter. Change all callers. Align to the page size when moving from relro to non-relro section. (Output_segment::set_offset): Align memsz of a PT_GNU_RELRO segment. * output.h (class Output_section): Add is_relro_ and is_relro_local_ fields. (Output_section::is_relro): New function. (Output_section::set_is_relro): New function. (Output_section::is_relro_local): New function. (Output_section::set_is_relro_local): New function. (class Output_segment): Update declarations. * i386.cc (Target_i386::got_section): Mark .got section as relro. * sparc.cc (Target_sparc::got_section): Likewise. * x86_64.cc (Target_x86_64::got_section): Likewise. * testsuite/relro_test_main.cc: New file. * testsuite/relro_test.cc: New file. * testsuite/Makefile.am (check_PROGRAMS): Add relro_test. (relro_test_SOURCES, relro_test_DEPENDENCIES): New variables. (relro_test_LDFLAGS, relro_test_LDADD): New variables. (relro_test.so, relro_test_pic.o): New targets. * testsuite/Makefile.in: Rebuild.
Diffstat (limited to 'gold/testsuite/relro_test.cc')
-rw-r--r--gold/testsuite/relro_test.cc114
1 files changed, 114 insertions, 0 deletions
diff --git a/gold/testsuite/relro_test.cc b/gold/testsuite/relro_test.cc
new file mode 100644
index 0000000..d1bd9dd
--- /dev/null
+++ b/gold/testsuite/relro_test.cc
@@ -0,0 +1,114 @@
+// relro_test.cc -- test -z relro for gold
+
+// Copyright 2008 Free Software Foundation, Inc.
+// Written by Ian Lance Taylor <iant@google.com>.
+
+// This file is part of gold.
+
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 3 of the License, or
+// (at your option) any later version.
+
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+// MA 02110-1301, USA.
+
+#include <cassert>
+#include <csignal>
+#include <stdint.h>
+#include <unistd.h>
+
+// This code is put into a shared library linked with -z relro.
+
+// i1 and i2 are not relro variables.
+int i1 = 1;
+static int i2 = 2;
+
+// P1 is a global relro variable.
+int* const p1 = &i1;
+
+// P2 is a local relro variable.
+int* const p2 = &i2;
+
+// Test symbol addresses.
+
+bool
+t1()
+{
+ void* i1addr = static_cast<void*>(&i1);
+ void* i2addr = static_cast<void*>(&i2);
+ const void* p1addr = static_cast<const void*>(&p1);
+ const void* p2addr = static_cast<const void*>(&p2);
+
+ // The relro variables should precede the non-relro variables in the
+ // memory image.
+ assert(i1addr > p1addr);
+ assert(i1addr > p2addr);
+ assert(i2addr > p1addr);
+ assert(i2addr > p2addr);
+
+ // The relro variables should not be on the same page as the
+ // non-relro variables.
+ const size_t page_size = getpagesize();
+ uintptr_t i1page = reinterpret_cast<uintptr_t>(i1addr) & ~ (page_size - 1);
+ uintptr_t i2page = reinterpret_cast<uintptr_t>(i2addr) & ~ (page_size - 1);
+ uintptr_t p1page = reinterpret_cast<uintptr_t>(p1addr) & ~ (page_size - 1);
+ uintptr_t p2page = reinterpret_cast<uintptr_t>(p2addr) & ~ (page_size - 1);
+ assert(i1page != p1page);
+ assert(i1page != p2page);
+ assert(i2page != p1page);
+ assert(i2page != p2page);
+
+ return true;
+}
+
+// A signal handler for SIGSEGV.
+
+extern "C"
+void
+sigsegv_handler(int)
+{
+ throw 0;
+}
+
+// Use a separate function to throw the exception, so that we don't
+// need to use -fnon-call-exceptions.
+
+void f2() __attribute__ ((noinline));
+void
+f2()
+{
+ int** pp1 = const_cast<int**>(&p1);
+ *pp1 = &i2;
+
+ // We shouldn't get here--the assignment to *pp1 should write to
+ // memory which the dynamic linker marked as read-only, giving us a
+ // SIGSEGV, causing sigsegv_handler to be invoked, to throw past us.
+ assert(0);
+}
+
+// Changing a relro variable should give us a SIGSEGV.
+
+bool
+t2()
+{
+ signal(SIGSEGV, sigsegv_handler);
+
+ try
+ {
+ f2();
+ return false;
+ }
+ catch (int i)
+ {
+ assert(i == 0);
+ return true;
+ }
+}