* layout.cc (Layout::attach_allocated_section_to_segment): Don't
authorIan Lance Taylor <ian@airs.com>
Wed, 13 Aug 2008 07:37:46 +0000 (07:37 +0000)
committerIan Lance Taylor <ian@airs.com>
Wed, 13 Aug 2008 07:37:46 +0000 (07:37 +0000)
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.

14 files changed:
gold/ChangeLog
gold/layout.cc
gold/output.cc
gold/output.h
gold/script-c.h
gold/script-sections.cc
gold/script-sections.h
gold/script.cc
gold/script.h
gold/testsuite/Makefile.am
gold/testsuite/Makefile.in
gold/testsuite/relro_script_test.t [new file with mode: 0644]
gold/testsuite/relro_test.cc
gold/yyscript.y

index db1a24f..aec50a5 100644 (file)
@@ -1,3 +1,59 @@
+2008-08-13  Ian Lance Taylor  <iant@google.com>
+
+       * 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 <ccoutant@google.com>
 
        * archive.cc (Archive::total_archives, Archive::total_members)
index a08ec72..99819d6 100644 (file)
@@ -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;
 }
 
index 145fca1..2a46195 100644 (file)
@@ -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_)
index e2c41c7..1c95881 100644 (file)
@@ -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
index 4f19b63..d94ba51 100644 (file)
@@ -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
index 13c9771..990a1a2 100644 (file)
@@ -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;
index 73bf33f..465c24e 100644 (file)
@@ -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.
index f6e4a39..53fcf66 100644 (file)
@@ -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<Parser_closure*>(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<Parser_closure*>(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
index e688a74..3397bf0 100644 (file)
@@ -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)
index df98677..c9dd470 100644 (file)
@@ -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
index c5e929a..9f72b88 100644 (file)
@@ -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 (file)
index 0000000..cacb84d
--- /dev/null
@@ -0,0 +1,52 @@
+/* relro_test.t -- relro script test 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.  */
+
+/* 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 (.);
+}
index 1fc1b43..bc6c77b 100644 (file)
 #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.
@@ -45,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);
@@ -129,6 +137,9 @@ f2()
 bool
 t2()
 {
+  if (using_script)
+    return true;
+
   signal(SIGSEGV, sigsegv_handler);
   orig_terminate = std::set_terminate(terminate_handler);
 
index ec2e8c0..683273b 100644 (file)
@@ -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 ')'