From 2d924fd9ebc6a97f9ef93208597e563c88f5e9e8 Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Wed, 13 Aug 2008 07:37:46 +0000 Subject: [PATCH] * layout.cc (Layout::attach_allocated_section_to_segment): Don't set tls_segment_ or relro_segment_. (Layout::make_output_segment): Set tls_segment_ and relro_segment_ when appropriate. * output.h (Output_section::clear_is_relro): New function. * output.cc (Output_segment::add_output_section): Handle SHF_TLS sections specially even when output_data_ is empty. (Output_segment::maximum_alignment): When first section is relro, only force alignment for PT_LOAD segments. * script.cc (script_data_segment_align): New function. (script_data_segment_relro_end): New function. * script-c.h (script_data_segment_align): Declare. (script_data_segment_relro_end): Declare. * script-sections.h (class Script_sections): Declare data_segment_align and data_segment_relro_end. Add fields segment_align_index_ and saw_relro_end_. * script-sections.cc (class Sections_element): Add set_is_relro virtual function. Add new bool* parameter to place_orphan_here. Add get_output_section virtual function. (class Output_section_definition): Add set_is_relro. Add new bool* parameter to place_orphan_here. Add get_output_section. Add is_relro_ field. (Output_section_definition::Output_section_definition): Initialize evaluated_address_, evaluated_load_address, evaluated_addralign_, and is_relro_ fields. (Output_section_definition::place_orphan_here): Add is_relro parameter. (Output_section_definition::set_section_addresses): Set relro for output section. (Output_section_definition::alternate_constraint): Likewise. (class Orphan_output_section): Add new bool* parameter to place_orphan_here. Add get_output_section. (Orphan_output_section::place_orphan_here): Add is_relro parameter. (Script_sections::Script_sections): Initialize data_segment_align_index_ and saw_relro_end_. (Script_sections::data_segment_align): New function. (Script_sections::data_segment_relro_end): New function. (Script_sections::place_orphan): Set or clear is_relro. (Script_sections::set_section_addresses): Force alignment of first TLS section. * yyscript.y (exp): Call script_data_segment_align and script_data_segment_relro_end. * testsuite/relro_script_test.t: New file. * testsuite/relro_test.cc (using_script): Declare. (t1, t2): Test using_script. * testsuite/Makefile.am (check_PROGRAMS): Add relro_script_test. (relro_script_test_SOURCES): Define. (relro_script_test_DEPENDENCIES): Define. (relro_script_test_LDFLAGS): Define. (relro_script_test_LDADD): Define. (relro_script_test.so): New target. * testsuite/Makefile.in: Rebuild. --- gold/ChangeLog | 56 +++++++++++++ gold/layout.cc | 12 ++- gold/output.cc | 7 +- gold/output.h | 5 ++ gold/script-c.h | 8 ++ gold/script-sections.cc | 128 +++++++++++++++++++++++++++-- gold/script-sections.h | 13 +++ gold/script.cc | 28 +++++++ gold/script.h | 1 - gold/testsuite/Makefile.am | 8 ++ gold/testsuite/Makefile.in | 32 ++++++-- gold/testsuite/relro_script_test.t | 52 ++++++++++++ gold/testsuite/relro_test.cc | 11 +++ gold/yyscript.y | 10 ++- 14 files changed, 346 insertions(+), 25 deletions(-) create mode 100644 gold/testsuite/relro_script_test.t diff --git a/gold/ChangeLog b/gold/ChangeLog index db1a24f3111..aec50a59f01 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,59 @@ +2008-08-13 Ian Lance Taylor + + * layout.cc (Layout::attach_allocated_section_to_segment): Don't + set tls_segment_ or relro_segment_. + (Layout::make_output_segment): Set tls_segment_ and relro_segment_ + when appropriate. + * output.h (Output_section::clear_is_relro): New function. + * output.cc (Output_segment::add_output_section): Handle SHF_TLS + sections specially even when output_data_ is empty. + (Output_segment::maximum_alignment): When first section is relro, + only force alignment for PT_LOAD segments. + * script.cc (script_data_segment_align): New function. + (script_data_segment_relro_end): New function. + * script-c.h (script_data_segment_align): Declare. + (script_data_segment_relro_end): Declare. + * script-sections.h (class Script_sections): Declare + data_segment_align and data_segment_relro_end. Add fields + segment_align_index_ and saw_relro_end_. + * script-sections.cc (class Sections_element): Add set_is_relro + virtual function. Add new bool* parameter to place_orphan_here. + Add get_output_section virtual function. + (class Output_section_definition): Add set_is_relro. Add new + bool* parameter to place_orphan_here. Add get_output_section. + Add is_relro_ field. + (Output_section_definition::Output_section_definition): Initialize + evaluated_address_, evaluated_load_address, evaluated_addralign_, + and is_relro_ fields. + (Output_section_definition::place_orphan_here): Add is_relro + parameter. + (Output_section_definition::set_section_addresses): Set relro for + output section. + (Output_section_definition::alternate_constraint): Likewise. + (class Orphan_output_section): Add new bool* parameter to + place_orphan_here. Add get_output_section. + (Orphan_output_section::place_orphan_here): Add is_relro + parameter. + (Script_sections::Script_sections): Initialize + data_segment_align_index_ and saw_relro_end_. + (Script_sections::data_segment_align): New function. + (Script_sections::data_segment_relro_end): New function. + (Script_sections::place_orphan): Set or clear is_relro. + (Script_sections::set_section_addresses): Force alignment of first + TLS section. + * yyscript.y (exp): Call script_data_segment_align and + script_data_segment_relro_end. + * testsuite/relro_script_test.t: New file. + * testsuite/relro_test.cc (using_script): Declare. + (t1, t2): Test using_script. + * testsuite/Makefile.am (check_PROGRAMS): Add relro_script_test. + (relro_script_test_SOURCES): Define. + (relro_script_test_DEPENDENCIES): Define. + (relro_script_test_LDFLAGS): Define. + (relro_script_test_LDADD): Define. + (relro_script_test.so): New target. + * testsuite/Makefile.in: Rebuild. + 2008-08-06 Cary Coutant * archive.cc (Archive::total_archives, Archive::total_members) diff --git a/gold/layout.cc b/gold/layout.cc index a08ec721937..99819d6cfcd 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -921,8 +921,7 @@ Layout::attach_allocated_section_to_segment(Output_section* os) if ((flags & elfcpp::SHF_TLS) != 0) { if (this->tls_segment_ == NULL) - this->tls_segment_ = this->make_output_segment(elfcpp::PT_TLS, - seg_flags); + this->make_output_segment(elfcpp::PT_TLS, seg_flags); this->tls_segment_->add_output_section(os, seg_flags); } @@ -932,8 +931,7 @@ Layout::attach_allocated_section_to_segment(Output_section* os) { gold_assert(seg_flags == (elfcpp::PF_R | elfcpp::PF_W)); if (this->relro_segment_ == NULL) - this->relro_segment_ = this->make_output_segment(elfcpp::PT_GNU_RELRO, - seg_flags); + this->make_output_segment(elfcpp::PT_GNU_RELRO, seg_flags); this->relro_segment_->add_output_section(os, seg_flags); } } @@ -2999,6 +2997,12 @@ Layout::make_output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags) gold_assert(!parameters->options().relocatable()); Output_segment* oseg = new Output_segment(type, flags); this->segment_list_.push_back(oseg); + + if (type == elfcpp::PT_TLS) + this->tls_segment_ = oseg; + else if (type == elfcpp::PT_GNU_RELRO) + this->relro_segment_ = oseg; + return oseg; } diff --git a/gold/output.cc b/gold/output.cc index 145fca159df..2a46195b2ac 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -2651,8 +2651,7 @@ Output_segment::add_output_section(Output_section* os, // and the PT_TLS segment -- we do this grouping only for the // PT_LOAD segment. if (this->type_ != elfcpp::PT_TLS - && (os->flags() & elfcpp::SHF_TLS) != 0 - && !this->output_data_.empty()) + && (os->flags() & elfcpp::SHF_TLS) != 0) { pdl = &this->output_data_; bool nobits = os->type() == elfcpp::SHT_NOBITS; @@ -2777,7 +2776,9 @@ Output_segment::maximum_alignment() // segment is a relro section, then the segment must be aligned // to at least the common page size. This ensures that the // PT_GNU_RELRO segment will start at a page boundary. - if (parameters->options().relro() && this->is_first_section_relro()) + if (this->type_ == elfcpp::PT_LOAD + && parameters->options().relro() + && this->is_first_section_relro()) { addralign = parameters->target().common_pagesize(); if (addralign > this->max_align_) diff --git a/gold/output.h b/gold/output.h index e2c41c7d7da..1c95881739f 100644 --- a/gold/output.h +++ b/gold/output.h @@ -2177,6 +2177,11 @@ class Output_section : public Output_data set_is_relro() { this->is_relro_ = true; } + // Record that this section does not hold relro data. + void + clear_is_relro() + { this->is_relro_ = false; } + // True if this section holds relro local data--relro data for which // the dynamic relocations are all RELATIVE relocations. bool diff --git a/gold/script-c.h b/gold/script-c.h index 4f19b6353f4..d94ba51276b 100644 --- a/gold/script-c.h +++ b/gold/script-c.h @@ -364,6 +364,14 @@ script_add_phdr(void* closure, const char* name, size_t namelen, extern unsigned int script_phdr_string_to_type(void* closure, const char*, size_t); +/* Handle DATA_SEGMENT_ALIGN and DATA_SEGMENT_RELRO_END. */ + +extern void +script_data_segment_align(void* closure); + +extern void +script_data_segment_relro_end(void* closure); + /* Called by the bison parser for expressions. */ extern Expression_ptr diff --git a/gold/script-sections.cc b/gold/script-sections.cc index 13c97710d29..990a1a2c771 100644 --- a/gold/script-sections.cc +++ b/gold/script-sections.cc @@ -54,6 +54,11 @@ class Sections_element virtual ~Sections_element() { } + // Record that an output section is relro. + virtual void + set_is_relro() + { } + // Create any required output sections. The only real // implementation is in Output_section_definition. virtual void @@ -80,7 +85,7 @@ class Sections_element // Return whether to place an orphan output section after this // element. virtual bool - place_orphan_here(const Output_section *, bool*) const + place_orphan_here(const Output_section *, bool*, bool*) const { return false; } // Set section addresses. This includes applying assignments if the @@ -126,6 +131,11 @@ class Sections_element uint64_t*) const { return false; } + // Return the associated Output_section if there is one. + virtual Output_section* + get_output_section() const + { return NULL; } + // Print the element for debugging purposes. virtual void print(FILE* f) const = 0; @@ -1231,6 +1241,11 @@ class Output_section_definition : public Sections_element void add_input_section(const Input_section_spec* spec, bool keep); + // Record that the output section is relro. + void + set_is_relro() + { this->is_relro_ = true; } + // Create any required output sections. void create_sections(Layout*); @@ -1251,7 +1266,7 @@ class Output_section_definition : public Sections_element // Return whether to place an orphan section after this one. bool - place_orphan_here(const Output_section *os, bool* exact) const; + place_orphan_here(const Output_section *os, bool* exact, bool*) const; // Set the section address. void @@ -1284,6 +1299,11 @@ class Output_section_definition : public Sections_element get_output_section_info(const char*, uint64_t*, uint64_t*, uint64_t*, uint64_t*) const; + // Return the associated Output_section if there is one. + Output_section* + get_output_section() const + { return this->output_section_; } + // Print the contents to the FILE. This is for debugging. void print(FILE*) const; @@ -1319,6 +1339,8 @@ class Output_section_definition : public Sections_element uint64_t evaluated_load_address_; // The alignment after it has been evaluated. uint64_t evaluated_addralign_; + // The output section is relro. + bool is_relro_; }; // Constructor. @@ -1336,7 +1358,11 @@ Output_section_definition::Output_section_definition( fill_(NULL), phdrs_(NULL), elements_(), - output_section_(NULL) + output_section_(NULL), + evaluated_address_(0), + evaluated_load_address_(0), + evaluated_addralign_(0), + is_relro_(false) { } @@ -1517,8 +1543,11 @@ Output_section_definition::output_section_name(const char* file_name, bool Output_section_definition::place_orphan_here(const Output_section *os, - bool* exact) const + bool* exact, + bool* is_relro) const { + *is_relro = this->is_relro_; + // Check for the simple case first. if (this->output_section_ != NULL && this->output_section_->type() == os->type() @@ -1754,6 +1783,14 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab, else *load_address = (this->output_section_->load_address() + (*dot_value - start_address)); + + if (this->output_section_ != NULL) + { + if (this->is_relro_) + this->output_section_->set_is_relro(); + else + this->output_section_->clear_is_relro(); + } } // Check a constraint (ONLY_IF_RO, etc.) on an output section. If @@ -1835,6 +1872,11 @@ Output_section_definition::alternate_constraint( this->output_section_ = posd->output_section_; posd->output_section_ = NULL; + if (this->is_relro_) + this->output_section_->set_is_relro(); + else + this->output_section_->clear_is_relro(); + return true; } @@ -1968,7 +2010,7 @@ class Orphan_output_section : public Sections_element // Return whether to place an orphan section after this one. bool - place_orphan_here(const Output_section *os, bool* exact) const; + place_orphan_here(const Output_section *os, bool* exact, bool*) const; // Set section addresses. void @@ -1979,6 +2021,11 @@ class Orphan_output_section : public Sections_element Output_section* allocate_to_segment(String_list**, bool*); + // Return the associated Output_section. + Output_section* + get_output_section() const + { return this->os_; } + // Print for debugging. void print(FILE* f) const @@ -1995,12 +2042,14 @@ class Orphan_output_section : public Sections_element bool Orphan_output_section::place_orphan_here(const Output_section* os, - bool* exact) const + bool* exact, + bool* is_relro) const { if (this->os_->type() == os->type() && this->os_->flags() == os->flags()) { *exact = true; + *is_relro = this->os_->is_relro(); return true; } return false; @@ -2206,7 +2255,9 @@ Script_sections::Script_sections() in_sections_clause_(false), sections_elements_(NULL), output_section_(NULL), - phdrs_elements_(NULL) + phdrs_elements_(NULL), + data_segment_align_index_(-1U), + saw_relro_end_(false) { } @@ -2334,6 +2385,39 @@ Script_sections::add_input_section(const Input_section_spec* spec, bool keep) this->output_section_->add_input_section(spec, keep); } +// This is called when we see DATA_SEGMENT_ALIGN. It means that any +// subsequent output sections may be relro. + +void +Script_sections::data_segment_align() +{ + if (this->data_segment_align_index_ != -1U) + gold_error(_("DATA_SEGMENT_ALIGN may only appear once in a linker script")); + this->data_segment_align_index_ = this->sections_elements_->size(); +} + +// This is called when we see DATA_SEGMENT_RELRO_END. It means that +// any output sections seen since DATA_SEGMENT_ALIGN are relro. + +void +Script_sections::data_segment_relro_end() +{ + if (this->saw_relro_end_) + gold_error(_("DATA_SEGMENT_RELRO_END may only appear once " + "in a linker script")); + this->saw_relro_end_ = true; + + if (this->data_segment_align_index_ == -1U) + gold_error(_("DATA_SEGMENT_RELRO_END must follow DATA_SEGMENT_ALIGN")); + else + { + for (size_t i = this->data_segment_align_index_; + i < this->sections_elements_->size(); + ++i) + (*this->sections_elements_)[i]->set_is_relro(); + } +} + // Create any required sections. void @@ -2418,15 +2502,18 @@ Script_sections::place_orphan(Output_section* os) { // Look for an output section definition which matches the output // section. Put a marker after that section. + bool is_relro = false; Sections_elements::iterator place = this->sections_elements_->end(); for (Sections_elements::iterator p = this->sections_elements_->begin(); p != this->sections_elements_->end(); ++p) { bool exact = false; - if ((*p)->place_orphan_here(os, &exact)) + bool is_relro_here; + if ((*p)->place_orphan_here(os, &exact, &is_relro_here)) { place = p; + is_relro = is_relro_here; if (exact) break; } @@ -2437,6 +2524,11 @@ Script_sections::place_orphan(Output_section* os) ++place; this->sections_elements_->insert(place, new Orphan_output_section(os)); + + if (is_relro) + os->set_is_relro(); + else + os->clear_is_relro(); } // Set the addresses of all the output sections. Walk through all the @@ -2479,6 +2571,26 @@ Script_sections::set_section_addresses(Symbol_table* symtab, Layout* layout) } } + // Force the alignment of the first TLS section to be the maximum + // alignment of all TLS sections. + Output_section* first_tls = NULL; + uint64_t tls_align = 0; + for (Sections_elements::const_iterator p = this->sections_elements_->begin(); + p != this->sections_elements_->end(); + ++p) + { + Output_section *os = (*p)->get_output_section(); + if (os != NULL && (os->flags() & elfcpp::SHF_TLS) != 0) + { + if (first_tls == NULL) + first_tls = os; + if (os->addralign() > tls_align) + tls_align = os->addralign(); + } + } + if (first_tls != NULL) + first_tls->set_addralign(tls_align); + // For a relocatable link, we implicitly set dot to zero. uint64_t dot_value = 0; uint64_t load_address = 0; diff --git a/gold/script-sections.h b/gold/script-sections.h index 73bf33f42bb..465c24ea956 100644 --- a/gold/script-sections.h +++ b/gold/script-sections.h @@ -106,6 +106,14 @@ class Script_sections void add_input_section(const Input_section_spec* spec, bool keep); + // Saw DATA_SEGMENT_ALIGN. + void + data_segment_align(); + + // Saw DATA_SEGMENT_RELRO_END. + void + data_segment_relro_end(); + // Create any required sections. void create_sections(Layout*); @@ -224,6 +232,11 @@ class Script_sections Output_section_definition* output_section_; // The list of program headers in the PHDRS clause. Phdrs_elements* phdrs_elements_; + // The index of the next Sections_element when we see + // DATA_SEGMENT_ALIGN. + size_t data_segment_align_index_; + // Whether we have seen DATA_SEGMENT_RELRO_END. + bool saw_relro_end_; }; } // End namespace gold. diff --git a/gold/script.cc b/gold/script.cc index f6e4a396f2c..53fcf6685a4 100644 --- a/gold/script.cc +++ b/gold/script.cc @@ -2400,6 +2400,34 @@ script_add_input_section(void* closurev, closure->script_options()->script_sections()->add_input_section(spec, keep); } +// When we see DATA_SEGMENT_ALIGN we record that following output +// sections may be relro. + +extern "C" void +script_data_segment_align(void* closurev) +{ + Parser_closure* closure = static_cast(closurev); + if (!closure->script_options()->saw_sections_clause()) + gold_error(_("%s:%d:%d: DATA_SEGMENT_ALIGN not in SECTIONS clause"), + closure->filename(), closure->lineno(), closure->charpos()); + else + closure->script_options()->script_sections()->data_segment_align(); +} + +// When we see DATA_SEGMENT_RELRO_END we know that all output sections +// since DATA_SEGMENT_ALIGN should be relro. + +extern "C" void +script_data_segment_relro_end(void* closurev) +{ + Parser_closure* closure = static_cast(closurev); + if (!closure->script_options()->saw_sections_clause()) + gold_error(_("%s:%d:%d: DATA_SEGMENT_ALIGN not in SECTIONS clause"), + closure->filename(), closure->lineno(), closure->charpos()); + else + closure->script_options()->script_sections()->data_segment_relro_end(); +} + // Create a new list of string/sort pairs. extern "C" String_sort_list_ptr diff --git a/gold/script.h b/gold/script.h index e688a744e88..3397bf05eef 100644 --- a/gold/script.h +++ b/gold/script.h @@ -407,7 +407,6 @@ read_commandline_script(const char* filename, Command_line*); bool read_version_script(const char* filename, Command_line* cmdline); - } // End namespace gold. #endif // !defined(GOLD_SCRIPT_H) diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am index df986770a09..c9dd4703a78 100644 --- a/gold/testsuite/Makefile.am +++ b/gold/testsuite/Makefile.am @@ -835,6 +835,14 @@ relro_test.so: gcctestdir/ld relro_test_pic.o relro_test_pic.o: relro_test.cc $(CXXCOMPILE) -c -fpic -o $@ $< +check_PROGRAMS += relro_script_test +relro_script_test_SOURCES = relro_test_main.cc +relro_script_test_DEPENDENCIES = gcctestdir/ld relro_script_test.so +relro_script_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +relro_script_test_LDADD = relro_script_test.so +relro_script_test.so: gcctestdir/ld relro_script_test.t relro_test_pic.o + $(CXXLINK) -Bgcctestdir/ -shared -Wl,-z,relro -T $(srcdir)/relro_script_test.t relro_test_pic.o + check_PROGRAMS += script_test_1 script_test_1_SOURCES = script_test_1.cc script_test_1_DEPENDENCIES = gcctestdir/ld script_test_1.t diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in index c5e929a9cf3..9f72b887e94 100644 --- a/gold/testsuite/Makefile.in +++ b/gold/testsuite/Makefile.in @@ -229,9 +229,10 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_19 = ver_test ver_test_2 \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_6 ver_test_8 ver_test_9 \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ protected_1 protected_2 \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ relro_test script_test_1 \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_2 justsyms \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ binary_test script_test_3 +@GCC_TRUE@@NATIVE_LINKER_TRUE@ relro_test relro_script_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_1 script_test_2 \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ justsyms binary_test \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_3 @GCC_FALSE@script_test_1_DEPENDENCIES = libgoldtest.a ../libgold.a \ @GCC_FALSE@ ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \ @GCC_FALSE@ $(am__DEPENDENCIES_1) @@ -351,6 +352,7 @@ libgoldtest_a_OBJECTS = $(am_libgoldtest_a_OBJECTS) @GCC_TRUE@@NATIVE_LINKER_TRUE@ protected_1$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ protected_2$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ relro_test$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ relro_script_test$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_1$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ script_test_2$(EXEEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ justsyms$(EXEEXT) \ @@ -523,6 +525,10 @@ am__protected_2_SOURCES_DIST = protected_main_1.cc protected_3.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@ protected_main_1.$(OBJEXT) \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ protected_3.$(OBJEXT) protected_2_OBJECTS = $(am_protected_2_OBJECTS) +am__relro_script_test_SOURCES_DIST = relro_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_relro_script_test_OBJECTS = \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ relro_test_main.$(OBJEXT) +relro_script_test_OBJECTS = $(am_relro_script_test_OBJECTS) am__relro_test_SOURCES_DIST = relro_test_main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_relro_test_OBJECTS = \ @GCC_TRUE@@NATIVE_LINKER_TRUE@ relro_test_main.$(OBJEXT) @@ -783,9 +789,10 @@ SOURCES = $(libgoldtest_a_SOURCES) basic_pic_test.c \ $(initpri1_SOURCES) $(justsyms_SOURCES) many_sections_r_test.c \ $(many_sections_test_SOURCES) $(object_unittest_SOURCES) \ $(protected_1_SOURCES) $(protected_2_SOURCES) \ - $(relro_test_SOURCES) $(script_test_1_SOURCES) \ - $(script_test_2_SOURCES) script_test_3.c \ - $(tls_pic_test_SOURCES) $(tls_shared_gd_to_ie_test_SOURCES) \ + $(relro_script_test_SOURCES) $(relro_test_SOURCES) \ + $(script_test_1_SOURCES) $(script_test_2_SOURCES) \ + script_test_3.c $(tls_pic_test_SOURCES) \ + $(tls_shared_gd_to_ie_test_SOURCES) \ $(tls_shared_gnu2_gd_to_ie_test_SOURCES) \ $(tls_shared_gnu2_test_SOURCES) $(tls_shared_ie_test_SOURCES) \ $(tls_shared_nonpic_test_SOURCES) $(tls_shared_test_SOURCES) \ @@ -832,7 +839,9 @@ DIST_SOURCES = $(libgoldtest_a_SOURCES) basic_pic_test.c \ $(am__initpri1_SOURCES_DIST) $(am__justsyms_SOURCES_DIST) \ many_sections_r_test.c $(am__many_sections_test_SOURCES_DIST) \ $(object_unittest_SOURCES) $(am__protected_1_SOURCES_DIST) \ - $(am__protected_2_SOURCES_DIST) $(am__relro_test_SOURCES_DIST) \ + $(am__protected_2_SOURCES_DIST) \ + $(am__relro_script_test_SOURCES_DIST) \ + $(am__relro_test_SOURCES_DIST) \ $(am__script_test_1_SOURCES_DIST) \ $(am__script_test_2_SOURCES_DIST) script_test_3.c \ $(am__tls_pic_test_SOURCES_DIST) \ @@ -1341,6 +1350,10 @@ binary_unittest_SOURCES = binary_unittest.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@relro_test_DEPENDENCIES = gcctestdir/ld relro_test.so @GCC_TRUE@@NATIVE_LINKER_TRUE@relro_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. @GCC_TRUE@@NATIVE_LINKER_TRUE@relro_test_LDADD = relro_test.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@relro_script_test_SOURCES = relro_test_main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@relro_script_test_DEPENDENCIES = gcctestdir/ld relro_script_test.so +@GCC_TRUE@@NATIVE_LINKER_TRUE@relro_script_test_LDFLAGS = -Bgcctestdir/ -Wl,-R,. +@GCC_TRUE@@NATIVE_LINKER_TRUE@relro_script_test_LDADD = relro_script_test.so @GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_1_SOURCES = script_test_1.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_1_DEPENDENCIES = gcctestdir/ld script_test_1.t @GCC_TRUE@@NATIVE_LINKER_TRUE@script_test_1_LDFLAGS = -Bgcctestdir/ -Wl,-R,. -T $(srcdir)/script_test_1.t @@ -1508,6 +1521,9 @@ protected_1$(EXEEXT): $(protected_1_OBJECTS) $(protected_1_DEPENDENCIES) protected_2$(EXEEXT): $(protected_2_OBJECTS) $(protected_2_DEPENDENCIES) @rm -f protected_2$(EXEEXT) $(CXXLINK) $(protected_2_LDFLAGS) $(protected_2_OBJECTS) $(protected_2_LDADD) $(LIBS) +relro_script_test$(EXEEXT): $(relro_script_test_OBJECTS) $(relro_script_test_DEPENDENCIES) + @rm -f relro_script_test$(EXEEXT) + $(CXXLINK) $(relro_script_test_LDFLAGS) $(relro_script_test_OBJECTS) $(relro_script_test_LDADD) $(LIBS) relro_test$(EXEEXT): $(relro_test_OBJECTS) $(relro_test_DEPENDENCIES) @rm -f relro_test$(EXEEXT) $(CXXLINK) $(relro_test_LDFLAGS) $(relro_test_OBJECTS) $(relro_test_LDADD) $(LIBS) @@ -2274,6 +2290,8 @@ uninstall-am: uninstall-info-am @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared -Wl,-z,relro relro_test_pic.o @GCC_TRUE@@NATIVE_LINKER_TRUE@relro_test_pic.o: relro_test.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -fpic -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@relro_script_test.so: gcctestdir/ld relro_script_test.t relro_test_pic.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -shared -Wl,-z,relro -T $(srcdir)/relro_script_test.t relro_test_pic.o @GCC_TRUE@@NATIVE_LINKER_TRUE@justsyms_2.o: justsyms_2.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -o $@ $< @GCC_TRUE@@NATIVE_LINKER_TRUE@justsyms_2r.o: justsyms_2.o gcctestdir/ld $(srcdir)/justsyms.t diff --git a/gold/testsuite/relro_script_test.t b/gold/testsuite/relro_script_test.t new file mode 100644 index 00000000000..cacb84d7d21 --- /dev/null +++ b/gold/testsuite/relro_script_test.t @@ -0,0 +1,52 @@ +/* relro_test.t -- relro script test for gold + + Copyright 2008 Free Software Foundation, Inc. + Written by Ian Lance Taylor . + + 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. */ + +/* With luck this will work on all platforms. */ + +using_script = 1; + +SECTIONS +{ + . = SIZEOF_HEADERS; + + .text : { *(.text) } + + .eh_frame : ONLY_IF_RO { KEEP(*(.eh_frame)) } + + . = (ALIGN(CONSTANT(MAXPAGESIZE)) + - ((CONSTANT(MAXPAGESIZE) - .) & (CONSTANT(MAXPAGESIZE) - 1))); + . = DATA_SEGMENT_ALIGN(CONSTANT(MAXPAGESIZE), CONSTANT(COMMONPAGESIZE)); + + .eh_frame : ONLY_IF_RW { KEEP(*(.eh_frame)) } + .tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) } + .tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) } + .data.rel.ro : { *(.data.rel.ro.local* .gnu.linkonce.d.rel.ro.local.*) + *(.data.rel.ro* .gnu.linkonce.d.rel.ro.*) } + .dynamic : { *(.dynamic) } + .got : { *(.got) } + + . = DATA_SEGMENT_RELRO_END(0, .); + + .data : { *(.data .data.* .gnu.linkonce.d.*) } + + . = DATA_SEGMENT_END (.); +} diff --git a/gold/testsuite/relro_test.cc b/gold/testsuite/relro_test.cc index 1fc1b43887c..bc6c77b91eb 100644 --- a/gold/testsuite/relro_test.cc +++ b/gold/testsuite/relro_test.cc @@ -28,6 +28,11 @@ #include #include +// 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. @@ -45,6 +50,9 @@ int* const p2 = &i2; bool t1() { + if (using_script) + return true; + void* i1addr = static_cast(&i1); void* i2addr = static_cast(&i2); const void* p1addr = static_cast(&p1); @@ -129,6 +137,9 @@ f2() bool t2() { + if (using_script) + return true; + signal(SIGSEGV, sigsegv_handler); orig_terminate = std::set_terminate(terminate_handler); diff --git a/gold/yyscript.y b/gold/yyscript.y index ec2e8c0da2d..683273bf066 100644 --- a/gold/yyscript.y +++ b/gold/yyscript.y @@ -811,9 +811,15 @@ exp: | BLOCK '(' exp ')' { $$ = script_exp_function_align(script_exp_string(".", 1), $3); } | DATA_SEGMENT_ALIGN '(' exp ',' exp ')' - { $$ = script_exp_function_data_segment_align($3, $5); } + { + script_data_segment_align(closure); + $$ = script_exp_function_data_segment_align($3, $5); + } | DATA_SEGMENT_RELRO_END '(' exp ',' exp ')' - { $$ = script_exp_function_data_segment_relro_end($3, $5); } + { + script_data_segment_relro_end(closure); + $$ = script_exp_function_data_segment_relro_end($3, $5); + } | DATA_SEGMENT_END '(' exp ')' { $$ = script_exp_function_data_segment_end($3); } | SEGMENT_START '(' string ',' exp ')' -- 2.30.2