This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

gold patch committed: Rework relro handling


This patch reworks the relro handling in gold so that a non-relro
section can immediately follow a relro section.  Space is inserted
before the relro section to make the relro contents end on a page
boundary.  This is what the GNU linker does through some linker script
magic.  I then changed the i386 and x86_64 backends to do this for the
GOT section: the .got section can go on the relro page, whereas the
.got.plt section must not.  The code used to call set_is_relro, but it
was ineffective because of when the sections are created.  I fixed
that by adding some parameters to the section creation functions.  A
lot of this patch is just passing those parameters in and around.

Committed to mainline.

Ian


2009-12-29  Ian Lance Taylor  <iant@google.com>

	* layout.cc (Layout::Layout): Initialize increase_relro_.
	(Layout::get_output_section): Add is_relro, is_last_relro, and
	is_first_non_relro parameters.  Change all callers.
	(Layout::choose_output_section): Likewise.
	(Layout::add_output_section_data): Likewise.
	(Layout::make_output_section): Likewise.
	(Layout::set_segment_offsets): Clear increase_relro when using a
	linker script.
	* layout.h (class Layout): Add increase_relro method.  Add
	increase_relro_ field.  Update declarations.
	* output.cc (Output_section::Output_section): Initialize
	is_last_relro_ and is_first_non_relro_.
	(Output_segment::add_output_section): Group relro sections is
	do_sort is true.  Handle is_last_relro and is_first_non_relro.
	(Output_segment::maximum_alignment): Remove relro handling.
	(Output_segment::set_section_addresses): Add increase_relro
	parameter.  Change all callers.  Add initial alignment to align
	relro sections on separate page.  Remove old relro handling.
	(Output_segment::set_section_list_addresses): Remove in_relro
	parameter.  Change all callers.
	(Output_segment::set_offset): Add increase parameter.  Change all
	callers.  Remove old relro handling.
	* output.h (class Output_section): Add new methods: is_last_relro,
	set_is_last_relro, is_first_non_relro, set_is_first_non_relro.
	Add is_last_relro_ and is_first_non_relro_ fields.
	* i386.cc (Target_i386::got_section): Don't call set_is_relro.
	Create separate .got.plt section.  Call increase_relro.
	* x86_64.cc (Target_x86_64::got_section): Likewise.
	* testsuite/relro_script_test.t: Add .got.plt.


Index: arm.cc
===================================================================
RCS file: /cvs/src/src/gold/arm.cc,v
retrieving revision 1.45
diff -p -u -r1.45 arm.cc
--- arm.cc	29 Dec 2009 00:31:48 -0000	1.45
+++ arm.cc	30 Dec 2009 06:47:43 -0000
@@ -2592,8 +2592,8 @@ Target_arm<big_endian>::got_section(Symb
       os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
 					   (elfcpp::SHF_ALLOC
 					    | elfcpp::SHF_WRITE),
-					   this->got_, false);
-      os->set_is_relro();
+					   this->got_, false, true, true,
+					   false);
 
       // The old GNU linker creates a .got.plt section.  We just
       // create another set of data in the .got section.  Note that we
@@ -2603,8 +2603,8 @@ Target_arm<big_endian>::got_section(Symb
       os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
 					   (elfcpp::SHF_ALLOC
 					    | elfcpp::SHF_WRITE),
-					   this->got_plt_, false);
-      os->set_is_relro();
+					   this->got_plt_, false, false,
+					   false, true);
 
       // The first three entries are reserved.
       this->got_plt_->set_current_data_size(3 * 4);
@@ -2632,7 +2632,8 @@ Target_arm<big_endian>::rel_dyn_section(
       gold_assert(layout != NULL);
       this->rel_dyn_ = new Reloc_section(parameters->options().combreloc());
       layout->add_output_section_data(".rel.dyn", elfcpp::SHT_REL,
-				      elfcpp::SHF_ALLOC, this->rel_dyn_, true);
+				      elfcpp::SHF_ALLOC, this->rel_dyn_, true,
+				      false, false, false);
     }
   return this->rel_dyn_;
 }
@@ -4052,7 +4053,8 @@ Output_data_plt_arm<big_endian>::Output_
 {
   this->rel_ = new Reloc_section(false);
   layout->add_output_section_data(".rel.plt", elfcpp::SHT_REL,
-				  elfcpp::SHF_ALLOC, this->rel_, true);
+				  elfcpp::SHF_ALLOC, this->rel_, true, false,
+				  false, false);
 }
 
 template<bool big_endian>
@@ -4214,7 +4216,7 @@ Target_arm<big_endian>::make_plt_entry(S
       layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
 				      (elfcpp::SHF_ALLOC
 				       | elfcpp::SHF_EXECINSTR),
-				      this->plt_, false);
+				      this->plt_, false, false, false, false);
     }
   this->plt_->add_entry(gsym);
 }
@@ -4793,7 +4795,8 @@ Target_arm<big_endian>::do_finalize_sect
     new Output_attributes_section_data(*this->attributes_section_data_);
   layout->add_output_section_data(".ARM.attributes",
 				  elfcpp::SHT_ARM_ATTRIBUTES, 0,
-				  attributes_section, false);
+				  attributes_section, false, false, false,
+				  false);
 }
 
 // Return whether a direct absolute static relocation needs to be applied.
Index: common.cc
===================================================================
RCS file: /cvs/src/src/gold/common.cc,v
retrieving revision 1.19
diff -p -u -r1.19 common.cc
--- common.cc	4 Nov 2009 15:56:03 -0000	1.19
+++ common.cc	30 Dec 2009 06:47:43 -0000
@@ -239,7 +239,8 @@ Symbol_table::do_allocate_commons_list(
   Output_data_space *poc = new Output_data_space(addralign, ds_name);
   Output_section *os = layout->add_output_section_data(name,
 						       elfcpp::SHT_NOBITS,
-						       flags, poc, false);
+						       flags, poc, false,
+						       false, false, false);
   if (os != NULL)
     {
       if (commons_section_type == COMMONS_SMALL)
Index: copy-relocs.cc
===================================================================
RCS file: /cvs/src/src/gold/copy-relocs.cc,v
retrieving revision 1.6
diff -p -u -r1.6 copy-relocs.cc
--- copy-relocs.cc	4 Nov 2009 15:56:03 -0000	1.6
+++ copy-relocs.cc	30 Dec 2009 06:47:43 -0000
@@ -138,7 +138,8 @@ Copy_relocs<sh_type, size, big_endian>::
       layout->add_output_section_data(".bss",
 				      elfcpp::SHT_NOBITS,
 				      elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
-				      this->dynbss_, false);
+				      this->dynbss_, false, false, false,
+				      false);
     }
 
   Output_data_space* dynbss = this->dynbss_;
Index: i386.cc
===================================================================
RCS file: /cvs/src/src/gold/i386.cc,v
retrieving revision 1.107
diff -p -u -r1.107 i386.cc
--- i386.cc	29 Dec 2009 00:31:48 -0000	1.107
+++ i386.cc	30 Dec 2009 06:47:44 -0000
@@ -461,23 +461,22 @@ Target_i386::got_section(Symbol_table* s
       os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
 					   (elfcpp::SHF_ALLOC
 					    | elfcpp::SHF_WRITE),
-					   this->got_, false);
-      os->set_is_relro();
+					   this->got_, false, true, true,
+					   false);
 
-      // The old GNU linker creates a .got.plt section.  We just
-      // create another set of data in the .got section.  Note that we
-      // always create a PLT if we create a GOT, although the PLT
-      // might be empty.
       this->got_plt_ = new Output_data_space(4, "** GOT PLT");
-      os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
+      os = layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS,
 					   (elfcpp::SHF_ALLOC
 					    | elfcpp::SHF_WRITE),
-					   this->got_plt_, false);
-      os->set_is_relro();
+					   this->got_plt_, false, false, false,
+					   true);
 
       // The first three entries are reserved.
       this->got_plt_->set_current_data_size(3 * 4);
 
+      // Those bytes can go into the relro segment.
+      layout->increase_relro(3 * 4);
+
       // Define _GLOBAL_OFFSET_TABLE_ at the start of the PLT.
       symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL,
 				    Symbol_table::PREDEFINED,
@@ -501,7 +500,8 @@ Target_i386::rel_dyn_section(Layout* lay
       gold_assert(layout != NULL);
       this->rel_dyn_ = new Reloc_section(parameters->options().combreloc());
       layout->add_output_section_data(".rel.dyn", elfcpp::SHT_REL,
-				      elfcpp::SHF_ALLOC, this->rel_dyn_, true);
+				      elfcpp::SHF_ALLOC, this->rel_dyn_, true,
+				      false, false, false);
     }
   return this->rel_dyn_;
 }
@@ -576,7 +576,8 @@ Output_data_plt_i386::Output_data_plt_i3
 {
   this->rel_ = new Reloc_section(false);
   layout->add_output_section_data(".rel.plt", elfcpp::SHT_REL,
-				  elfcpp::SHF_ALLOC, this->rel_, true);
+				  elfcpp::SHF_ALLOC, this->rel_, true,
+				  false, false, false);
 }
 
 void
@@ -761,7 +762,7 @@ Target_i386::make_plt_entry(Symbol_table
       layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
 				      (elfcpp::SHF_ALLOC
 				       | elfcpp::SHF_EXECINSTR),
-				      this->plt_, false);
+				      this->plt_, false, false, false, false);
     }
 
   this->plt_->add_entry(gsym);
Index: layout.cc
===================================================================
RCS file: /cvs/src/src/gold/layout.cc,v
retrieving revision 1.151
diff -p -u -r1.151 layout.cc
--- layout.cc	30 Dec 2009 04:16:50 -0000	1.151
+++ layout.cc	30 Dec 2009 06:47:45 -0000
@@ -175,6 +175,7 @@ Layout::Layout(int number_of_input_files
     section_headers_(NULL),
     tls_segment_(NULL),
     relro_segment_(NULL),
+    increase_relro_(0),
     symtab_section_(NULL),
     symtab_xindex_(NULL),
     dynsym_section_(NULL),
@@ -391,12 +392,16 @@ Layout::find_output_segment(elfcpp::PT t
 // and section flags FLAGS.  NAME must be canonicalized in the string
 // pool, and NAME_KEY is the key.  IS_INTERP is true if this is the
 // .interp section.  IS_DYNAMIC_LINKER_SECTION is true if this section
-// is used by the dynamic linker.
+// is used by the dynamic linker.  IS_RELRO is true for a relro
+// section.  IS_LAST_RELRO is true for the last relro section.
+// IS_FIRST_NON_RELRO is true for the first non-relro section.
 
 Output_section*
 Layout::get_output_section(const char* name, Stringpool::Key name_key,
 			   elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
-			   bool is_interp, bool is_dynamic_linker_section)
+			   bool is_interp, bool is_dynamic_linker_section,
+			   bool is_relro, bool is_last_relro,
+			   bool is_first_non_relro)
 {
   elfcpp::Elf_Xword lookup_flags = flags;
 
@@ -446,7 +451,8 @@ Layout::get_output_section(const char* n
 
       if (os == NULL)
 	os = this->make_output_section(name, type, flags, is_interp,
-				       is_dynamic_linker_section);
+				       is_dynamic_linker_section, is_relro,
+				       is_last_relro, is_first_non_relro);
       ins.first->second = os;
       return os;
     }
@@ -458,14 +464,17 @@ Layout::get_output_section(const char* n
 // choosing an output section for an input section found in a input
 // file.  IS_INTERP is true if this is the .interp section.
 // IS_DYNAMIC_LINKER_SECTION is true if this section is used by the
-// dynamic linker.  This will return NULL if the input section should
-// be discarded.
+// dynamic linker.  IS_RELRO is true for a relro section.
+// IS_LAST_RELRO is true for the last relro section.
+// IS_FIRST_NON_RELRO is true for the first non-relro section.  This
+// will return NULL if the input section should be discarded.
 
 Output_section*
 Layout::choose_output_section(const Relobj* relobj, const char* name,
 			      elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
 			      bool is_input_section, bool is_interp,
-			      bool is_dynamic_linker_section)
+			      bool is_dynamic_linker_section, bool is_relro,
+			      bool is_last_relro, bool is_first_non_relro)
 {
   // We should not see any input sections after we have attached
   // sections to segments.
@@ -515,7 +524,8 @@ Layout::choose_output_section(const Relo
 
 	  Output_section* os =
 	    this->make_output_section(name, type, flags, is_interp,
-				      is_dynamic_linker_section);
+				      is_dynamic_linker_section, is_relro,
+				      is_last_relro, is_first_non_relro);
 	  os->set_found_in_sections_clause();
 	  *output_section_slot = os;
 	  return os;
@@ -539,7 +549,8 @@ Layout::choose_output_section(const Relo
   // Find or make the output section.  The output section is selected
   // based on the section name, type, and flags.
   return this->get_output_section(name, name_key, type, flags, is_interp,
-				  is_dynamic_linker_section);
+				  is_dynamic_linker_section, is_relro,
+				  is_last_relro, is_first_non_relro);
 }
 
 // Return the output section to use for input section SHNDX, with name
@@ -572,13 +583,14 @@ Layout::layout(Sized_relobj<size, big_en
     {
       name = this->namepool_.add(name, true, NULL);
       os = this->make_output_section(name, shdr.get_sh_type(),
-				     shdr.get_sh_flags(), false, false);
+				     shdr.get_sh_flags(), false, false,
+				     false, false, false);
     }
   else
     {
       os = this->choose_output_section(object, name, shdr.get_sh_type(),
 				       shdr.get_sh_flags(), true, false,
-				       false);
+				       false, false, false, false);
       if (os == NULL)
 	return NULL;
     }
@@ -629,6 +641,7 @@ Layout::layout_reloc(Sized_relobj<size, 
   Output_section* os = this->choose_output_section(object, name.c_str(),
 						   sh_type,
 						   shdr.get_sh_flags(),
+						   false, false, false,
 						   false, false, false);
 
   os->set_should_link_to_symtab();
@@ -677,6 +690,7 @@ Layout::layout_group(Symbol_table* symta
   Output_section* os = this->make_output_section(group_section_name,
 						 elfcpp::SHT_GROUP,
 						 shdr.get_sh_flags(),
+						 false, false, false,
 						 false, false);
 
   // We need to find a symbol with the signature in the symbol table.
@@ -731,6 +745,7 @@ Layout::layout_eh_frame(Sized_relobj<siz
 						   name,
 						   elfcpp::SHT_PROGBITS,
 						   elfcpp::SHF_ALLOC,
+						   false, false, false,
 						   false, false, false);
   if (os == NULL)
     return NULL;
@@ -747,6 +762,7 @@ Layout::layout_eh_frame(Sized_relobj<siz
 					".eh_frame_hdr",
 					elfcpp::SHT_PROGBITS,
 					elfcpp::SHF_ALLOC,
+					false, false, false,
 					false, false, false);
 
 	  if (hdr_os != NULL)
@@ -814,11 +830,15 @@ Output_section*
 Layout::add_output_section_data(const char* name, elfcpp::Elf_Word type,
 				elfcpp::Elf_Xword flags,
 				Output_section_data* posd,
-				bool is_dynamic_linker_section)
+				bool is_dynamic_linker_section,
+				bool is_relro, bool is_last_relro,
+				bool is_first_non_relro)
 {
   Output_section* os = this->choose_output_section(NULL, name, type, flags,
 						   false, false,
-						   is_dynamic_linker_section);
+						   is_dynamic_linker_section,
+						   is_relro, is_last_relro,
+						   is_first_non_relro);
   if (os != NULL)
     os->add_output_section_data(posd);
   return os;
@@ -855,12 +875,15 @@ is_compressible_debug_section(const char
 // Make a new Output_section, and attach it to segments as
 // appropriate.  IS_INTERP is true if this is the .interp section.
 // IS_DYNAMIC_LINKER_SECTION is true if this section is used by the
-// dynamic linker.
+// dynamic linker.  IS_RELRO is true if this is a relro section.
+// IS_LAST_RELRO is true if this is the last relro section.
+// IS_FIRST_NON_RELRO is true if this is the first non relro section.
 
 Output_section*
 Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
 			    elfcpp::Elf_Xword flags, bool is_interp,
-			    bool is_dynamic_linker_section)
+			    bool is_dynamic_linker_section, bool is_relro,
+			    bool is_last_relro, bool is_first_non_relro)
 {
   Output_section* os;
   if ((flags & elfcpp::SHF_ALLOC) == 0
@@ -897,6 +920,12 @@ Layout::make_output_section(const char* 
     os->set_is_interp();
   if (is_dynamic_linker_section)
     os->set_is_dynamic_linker_section();
+  if (is_relro)
+    os->set_is_relro();
+  if (is_last_relro)
+    os->set_is_last_relro();
+  if (is_first_non_relro)
+    os->set_is_first_non_relro();
 
   parameters->target().new_output_section(os);
 
@@ -1089,7 +1118,7 @@ Layout::make_output_section_for_script(c
   name = this->namepool_.add(name, false, NULL);
   Output_section* os = this->make_output_section(name, elfcpp::SHT_PROGBITS,
 						 elfcpp::SHF_ALLOC, false,
-						 false);
+						 false, false, false, false);
   os->set_found_in_sections_clause();
   return os;
 }
@@ -1159,8 +1188,8 @@ Layout::create_initial_dynamic_sections(
 						       elfcpp::SHT_DYNAMIC,
 						       (elfcpp::SHF_ALLOC
 							| elfcpp::SHF_WRITE),
-						       false, false, true);
-  this->dynamic_section_->set_is_relro();
+						       false, false, true,
+						       true, false, false);
 
   this->dynamic_symbol_ =
     symtab->define_in_output_data("_DYNAMIC", NULL, Symbol_table::PREDEFINED,
@@ -1766,7 +1795,7 @@ Layout::create_note(const char* name, in
   Output_section* os = this->choose_output_section(NULL, section_name,
 						   elfcpp::SHT_NOTE,
 						   flags, false, false,
-						   false);
+						   false, false, false, false);
   if (os == NULL)
     return NULL;
 
@@ -1846,7 +1875,7 @@ Layout::create_executable_stack_info()
       if (is_stack_executable)
 	flags |= elfcpp::SHF_EXECINSTR;
       this->make_output_section(name, elfcpp::SHT_PROGBITS, flags, false,
-				false);
+				false, false, false, false);
     }
   else
     {
@@ -2007,7 +2036,7 @@ Layout::create_incremental_info_sections
   Output_section* inputs_os =
     this->make_output_section(incremental_inputs_name,
 			      elfcpp::SHT_GNU_INCREMENTAL_INPUTS, 0,
-			      false, false);
+			      false, false, false, false, false);
   Output_section_data* posd =
       this->incremental_inputs_->create_incremental_inputs_section_data();
   inputs_os->add_output_section_data(posd);
@@ -2017,7 +2046,8 @@ Layout::create_incremental_info_sections
     this->namepool_.add(".gnu_incremental_strtab", false, NULL);
   Output_section* strtab_os = this->make_output_section(incremental_strtab_name,
                                                         elfcpp::SHT_STRTAB,
-                                                        0, false, false);
+                                                        0, false, false,
+							false, false, false);
   Output_data_strtab* strtab_data =
     new Output_data_strtab(this->incremental_inputs_->get_stringpool());
   strtab_os->add_output_section_data(strtab_data);
@@ -2203,6 +2233,10 @@ Layout::set_segment_offsets(const Target
 	}
     }
 
+  unsigned int increase_relro = this->increase_relro_;
+  if (this->script_options_->saw_sections_clause())
+    increase_relro = 0;
+
   const bool check_sections = parameters->options().check_sections();
   Output_segment* last_load_segment = NULL;
 
@@ -2291,6 +2325,7 @@ Layout::set_segment_offsets(const Target
 
 	  unsigned int shndx_hold = *pshndx;
 	  uint64_t new_addr = (*p)->set_section_addresses(this, false, addr,
+							  increase_relro,
                                                           &off, pshndx);
 
 	  // Now that we know the size of this segment, we may be able
@@ -2317,6 +2352,7 @@ Layout::set_segment_offsets(const Target
 		  off = orig_off + ((addr - orig_addr) & (abi_pagesize - 1));
 		  off = align_file_offset(off, addr, abi_pagesize);
 		  new_addr = (*p)->set_section_addresses(this, true, addr,
+							 increase_relro,
                                                          &off, pshndx);
 		}
 	    }
@@ -2354,7 +2390,9 @@ Layout::set_segment_offsets(const Target
        ++p)
     {
       if ((*p)->type() != elfcpp::PT_LOAD)
-	(*p)->set_offset();
+	(*p)->set_offset((*p)->type() == elfcpp::PT_GNU_RELRO
+			 ? increase_relro
+			 : 0);
     }
 
   // Set the TLS offsets for each section in the PT_TLS segment.
@@ -2629,7 +2667,8 @@ Layout::create_symtab_sections(const Inp
       const char* symtab_name = this->namepool_.add(".symtab", false, NULL);
       Output_section* osymtab = this->make_output_section(symtab_name,
 							  elfcpp::SHT_SYMTAB,
-							  0, false, false);
+							  0, false, false,
+							  false, false, false);
       this->symtab_section_ = osymtab;
 
       Output_section_data* pos = new Output_data_fixed_space(off - startoff,
@@ -2651,7 +2690,7 @@ Layout::create_symtab_sections(const Inp
 	  Output_section* osymtab_xindex =
 	    this->make_output_section(symtab_xindex_name,
 				      elfcpp::SHT_SYMTAB_SHNDX, 0, false,
-				      false);
+				      false, false, false, false);
 
 	  size_t symcount = (off - startoff) / symsize;
 	  this->symtab_xindex_ = new Output_symtab_xindex(symcount);
@@ -2673,7 +2712,8 @@ Layout::create_symtab_sections(const Inp
       const char* strtab_name = this->namepool_.add(".strtab", false, NULL);
       Output_section* ostrtab = this->make_output_section(strtab_name,
 							  elfcpp::SHT_STRTAB,
-							  0, false, false);
+							  0, false, false,
+							  false, false, false);
 
       Output_section_data* pstr = new Output_data_strtab(&this->sympool_);
       ostrtab->add_output_section_data(pstr);
@@ -2701,7 +2741,8 @@ Layout::create_shstrtab()
   const char* name = this->namepool_.add(".shstrtab", false, NULL);
 
   Output_section* os = this->make_output_section(name, elfcpp::SHT_STRTAB, 0,
-						 false, false);
+						 false, false, false, false,
+						 false);
 
   if (strcmp(parameters->options().compress_debug_sections(), "none") != 0)
     {
@@ -2818,7 +2859,8 @@ Layout::create_dynamic_symtab(const Inpu
   Output_section* dynsym = this->choose_output_section(NULL, ".dynsym",
 						       elfcpp::SHT_DYNSYM,
 						       elfcpp::SHF_ALLOC,
-						       false, false, true);
+						       false, false, true,
+						       false, false, false);
 
   Output_section_data* odata = new Output_data_fixed_space(index * symsize,
 							   align,
@@ -2848,7 +2890,7 @@ Layout::create_dynamic_symtab(const Inpu
 	this->choose_output_section(NULL, ".dynsym_shndx",
 				    elfcpp::SHT_SYMTAB_SHNDX,
 				    elfcpp::SHF_ALLOC,
-				    false, false, true);
+				    false, false, true, false, false, false);
 
       this->dynsym_xindex_ = new Output_symtab_xindex(index);
 
@@ -2871,7 +2913,8 @@ Layout::create_dynamic_symtab(const Inpu
   Output_section* dynstr = this->choose_output_section(NULL, ".dynstr",
 						       elfcpp::SHT_STRTAB,
 						       elfcpp::SHF_ALLOC,
-						       false, false, true);
+						       false, false, true,
+						       false, false, false);
 
   Output_section_data* strdata = new Output_data_strtab(&this->dynpool_);
   dynstr->add_output_section_data(strdata);
@@ -2897,7 +2940,9 @@ Layout::create_dynamic_symtab(const Inpu
       Output_section* hashsec = this->choose_output_section(NULL, ".hash",
 							    elfcpp::SHT_HASH,
 							    elfcpp::SHF_ALLOC,
-							    false, false, true);
+							    false, false, true,
+							    false, false,
+							    false);
 
       Output_section_data* hashdata = new Output_data_const_buffer(phash,
 								   hashlen,
@@ -2922,7 +2967,9 @@ Layout::create_dynamic_symtab(const Inpu
       Output_section* hashsec = this->choose_output_section(NULL, ".gnu.hash",
 							    elfcpp::SHT_GNU_HASH,
 							    elfcpp::SHF_ALLOC,
-							    false, false, true);
+							    false, false, true,
+							    false, false,
+							    false);
 
       Output_section_data* hashdata = new Output_data_const_buffer(phash,
 								   hashlen,
@@ -3020,7 +3067,8 @@ Layout::sized_create_version_sections(
   Output_section* vsec = this->choose_output_section(NULL, ".gnu.version",
 						     elfcpp::SHT_GNU_versym,
 						     elfcpp::SHF_ALLOC,
-						     false, false, true);
+						     false, false, true,
+						     false, false, false);
 
   unsigned char* vbuf;
   unsigned int vsize;
@@ -3045,7 +3093,8 @@ Layout::sized_create_version_sections(
       vdsec= this->choose_output_section(NULL, ".gnu.version_d",
 					 elfcpp::SHT_GNU_verdef,
 					 elfcpp::SHF_ALLOC,
-					 false, false, true);
+					 false, false, true, false, false,
+					 false);
 
       unsigned char* vdbuf;
       unsigned int vdsize;
@@ -3070,7 +3119,8 @@ Layout::sized_create_version_sections(
       vnsec = this->choose_output_section(NULL, ".gnu.version_r",
 					  elfcpp::SHT_GNU_verneed,
 					  elfcpp::SHF_ALLOC,
-					  false, false, true);
+					  false, false, true, false, false,
+					  false);
 
       unsigned char* vnbuf;
       unsigned int vnsize;
@@ -3110,7 +3160,8 @@ Layout::create_interp(const Target* targ
   Output_section* osec = this->choose_output_section(NULL, ".interp",
 						     elfcpp::SHT_PROGBITS,
 						     elfcpp::SHF_ALLOC,
-						     false, true, true);
+						     false, true, true,
+						     false, false, false);
   osec->add_output_section_data(odata);
 
   if (!this->script_options_->saw_phdrs_clause())
Index: layout.h
===================================================================
RCS file: /cvs/src/src/gold/layout.h,v
retrieving revision 1.74
diff -p -u -r1.74 layout.h
--- layout.h	30 Dec 2009 04:16:50 -0000	1.74
+++ layout.h	30 Dec 2009 06:47:45 -0000
@@ -362,11 +362,21 @@ class Layout
   // Add an Output_section_data to the layout.  This is used for
   // special sections like the GOT section.  IS_DYNAMIC_LINKER_SECTION
   // is true for sections which are used by the dynamic linker, such
-  // as dynamic reloc sections.
+  // as dynamic reloc sections.  IS_RELRO is true for relro sections.
+  // IS_LAST_RELRO is true for the last relro section.
+  // IS_FIRST_NON_RELRO is true for the first section after the relro
+  // sections.
   Output_section*
   add_output_section_data(const char* name, elfcpp::Elf_Word type,
 			  elfcpp::Elf_Xword flags,
-			  Output_section_data*, bool is_dynamic_linker_section);
+			  Output_section_data*, bool is_dynamic_linker_section,
+			  bool is_relro, bool is_last_relro,
+			  bool is_first_non_relro);
+
+  // Increase the size of the relro segment by this much.
+  void
+  increase_relro(unsigned int s)
+  { this->increase_relro_ += s; }
 
   // Create dynamic sections if necessary.
   void
@@ -752,20 +762,24 @@ class Layout
   Output_section*
   get_output_section(const char* name, Stringpool::Key name_key,
 		     elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
-		     bool is_interp, bool is_dynamic_linker_section);
+		     bool is_interp, bool is_dynamic_linker_section,
+		     bool is_relro, bool is_last_relro,
+		     bool is_first_non_relro);
 
   // Choose the output section for NAME in RELOBJ.
   Output_section*
   choose_output_section(const Relobj* relobj, const char* name,
 			elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
 			bool is_input_section, bool is_interp,
-			bool is_dynamic_linker_section);
+			bool is_dynamic_linker_section, bool is_relro,
+			bool is_last_relro, bool is_first_non_relro);
 
   // Create a new Output_section.
   Output_section*
   make_output_section(const char* name, elfcpp::Elf_Word type,
 		      elfcpp::Elf_Xword flags, bool is_interp,
-		      bool is_dynamic_linker_section);
+		      bool is_dynamic_linker_section, bool is_relro,
+		      bool is_last_relro, bool is_first_non_relro);
 
   // Attach a section to a segment.
   void
@@ -941,6 +955,9 @@ class Layout
   Output_segment* tls_segment_;
   // A pointer to the PT_GNU_RELRO segment if there is one.
   Output_segment* relro_segment_;
+  // A backend may increase the size of the PT_GNU_RELRO segment if
+  // there is one.  This is the amount to increase it by.
+  unsigned int increase_relro_;
   // The SHT_SYMTAB output section.
   Output_section* symtab_section_;
   // The SHT_SYMTAB_SHNDX for the regular symbol table if there is one.
Index: output.cc
===================================================================
RCS file: /cvs/src/src/gold/output.cc,v
retrieving revision 1.109
diff -p -u -r1.109 output.cc
--- output.cc	30 Dec 2009 04:00:21 -0000	1.109
+++ output.cc	30 Dec 2009 06:47:45 -0000
@@ -1795,6 +1795,8 @@ Output_section::Output_section(const cha
     attached_input_sections_are_sorted_(false),
     is_relro_(false),
     is_relro_local_(false),
+    is_last_relro_(false),
+    is_first_non_relro_(false),
     is_small_section_(false),
     is_large_section_(false),
     is_interp_(false),
@@ -3157,26 +3159,52 @@ Output_segment::add_output_section(Outpu
       // location in the section list.
     }
 
-  // For the PT_GNU_RELRO segment, we need to group relro sections,
-  // and we need to put them before any non-relro sections.  Also,
-  // relro local sections go before relro non-local sections.
-  if (parameters->options().relro() && os->is_relro())
-    {
-      gold_assert(pdl == &this->output_data_);
-      Output_segment::Output_data_list::iterator p;
-      for (p = pdl->begin(); p != pdl->end(); ++p)
-	{
-	  if (!(*p)->is_section())
-	    break;
+  if (do_sort)
+    {
+      // For the PT_GNU_RELRO segment, we need to group relro
+      // sections, and we need to put them before any non-relro
+      // sections.  Any relro local sections go before relro non-local
+      // sections.  One section may be marked as the last relro
+      // section.
+      if (os->is_relro())
+	{
+	  gold_assert(pdl == &this->output_data_);
+	  Output_segment::Output_data_list::iterator p;
+	  for (p = pdl->begin(); p != pdl->end(); ++p)
+	    {
+	      if (!(*p)->is_section())
+		break;
 
-	  Output_section* pos = (*p)->output_section();
-	  if (!pos->is_relro()
-	      || (os->is_relro_local() && !pos->is_relro_local()))
-	    break;
+	      Output_section* pos = (*p)->output_section();
+	      if (!pos->is_relro()
+		  || (os->is_relro_local() && !pos->is_relro_local())
+		  || (!os->is_last_relro() && pos->is_last_relro()))
+		break;
+	    }
+
+	  pdl->insert(p, os);
+	  return;
 	}
 
-      pdl->insert(p, os);
-      return;
+      // One section may be marked as the first section which follows
+      // the relro sections.
+      if (os->is_first_non_relro())
+	{
+	  gold_assert(pdl == &this->output_data_);
+	  Output_segment::Output_data_list::iterator p;
+	  for (p = pdl->begin(); p != pdl->end(); ++p)
+	    {
+	      if (!(*p)->is_section())
+		break;
+
+	      Output_section* pos = (*p)->output_section();
+	      if (!pos->is_relro())
+		break;
+	    }
+
+	  pdl->insert(p, os);
+	  return;
+	}
     }
 
   // Small data sections go at the end of the list of data sections.
@@ -3365,19 +3393,6 @@ Output_segment::maximum_alignment()
       if (addralign > this->max_align_)
 	this->max_align_ = addralign;
 
-      // If -z relro is in effect, and the first section in this
-      // 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 (this->type_ == elfcpp::PT_LOAD
-	  && parameters->options().relro()
-	  && this->is_first_section_relro())
-	{
-	  addralign = parameters->target().common_pagesize();
-	  if (addralign > this->max_align_)
-	    this->max_align_ = addralign;
-	}
-
       this->is_max_align_known_ = true;
     }
 
@@ -3431,11 +3446,57 @@ Output_segment::dynamic_reloc_count_list
 
 uint64_t
 Output_segment::set_section_addresses(const Layout* layout, bool reset,
-                                      uint64_t addr, off_t* poff,
+                                      uint64_t addr,
+				      unsigned int increase_relro,
+				      off_t* poff,
 				      unsigned int* pshndx)
 {
   gold_assert(this->type_ == elfcpp::PT_LOAD);
 
+  off_t orig_off = *poff;
+
+  // If we have relro sections, we need to pad forward now so that the
+  // relro sections plus INCREASE_RELRO end on a common page boundary.
+  if (parameters->options().relro()
+      && this->is_first_section_relro()
+      && (!this->are_addresses_set_ || reset))
+    {
+      uint64_t relro_size = 0;
+      off_t off = *poff;
+      for (Output_data_list::iterator p = this->output_data_.begin();
+	   p != this->output_data_.end();
+	   ++p)
+	{
+	  if (!(*p)->is_section())
+	    break;
+	  Output_section* pos = (*p)->output_section();
+	  if (!pos->is_relro())
+	    break;
+	  gold_assert(!(*p)->is_section_flag_set(elfcpp::SHF_TLS));
+	  if ((*p)->is_address_valid())
+	    relro_size += (*p)->data_size();
+	  else
+	    {
+	      // FIXME: This could be faster.
+	      (*p)->set_address_and_file_offset(addr + relro_size,
+						off + relro_size);
+	      relro_size += (*p)->data_size();
+	      (*p)->reset_address_and_file_offset();
+	    }
+	}
+      relro_size += increase_relro;
+
+      uint64_t page_align = parameters->target().common_pagesize();
+
+      // Align to offset N such that (N + RELRO_SIZE) % PAGE_ALIGN == 0.
+      uint64_t desired_align = page_align - (relro_size % page_align);
+      if (desired_align < *poff % page_align)
+	*poff += page_align - *poff % page_align;
+      *poff += desired_align - *poff % page_align;
+      addr += *poff - orig_off;
+      orig_off = *poff;
+    }
+
   if (!reset && this->are_addresses_set_)
     {
       gold_assert(this->paddr_ == addr);
@@ -3450,15 +3511,10 @@ Output_segment::set_section_addresses(co
 
   bool in_tls = false;
 
-  bool in_relro = (parameters->options().relro()
-		   && this->is_first_section_relro());
-
-  off_t orig_off = *poff;
   this->offset_ = orig_off;
 
   addr = this->set_section_list_addresses(layout, reset, &this->output_data_,
-					  addr, poff, pshndx, &in_tls,
-					  &in_relro);
+					  addr, poff, pshndx, &in_tls);
   this->filesz_ = *poff - orig_off;
 
   off_t off = *poff;
@@ -3466,7 +3522,7 @@ Output_segment::set_section_addresses(co
   uint64_t ret = this->set_section_list_addresses(layout, reset,
                                                   &this->output_bss_,
 						  addr, poff, pshndx,
-                                                  &in_tls, &in_relro);
+                                                  &in_tls);
 
   // If the last section was a TLS section, align upward to the
   // alignment of the TLS segment, so that the overall size of the TLS
@@ -3477,14 +3533,6 @@ Output_segment::set_section_addresses(co
       *poff = align_address(*poff, segment_align);
     }
 
-  // If all the sections were relro sections, align upward to the
-  // common page size.
-  if (in_relro)
-    {
-      uint64_t page_align = parameters->target().common_pagesize();
-      *poff = align_address(*poff, page_align);
-    }
-
   this->memsz_ = *poff - orig_off;
 
   // Ignore the file offset adjustments made by the BSS Output_data
@@ -3502,7 +3550,7 @@ Output_segment::set_section_list_address
                                            Output_data_list* pdl,
 					   uint64_t addr, off_t* poff,
 					   unsigned int* pshndx,
-                                           bool* in_tls, bool* in_relro)
+                                           bool* in_tls)
 {
   off_t startoff = *poff;
 
@@ -3553,19 +3601,6 @@ Output_segment::set_section_list_address
                 }
             }
 
-	  // If this is a non-relro section after a relro section,
-	  // align it to a common page boundary so that the dynamic
-	  // linker has a page to mark as read-only.
-	  if (*in_relro
-	      && (!(*p)->is_section()
-		  || !(*p)->output_section()->is_relro()))
-	    {
-	      uint64_t page_align = parameters->target().common_pagesize();
-	      if (page_align > align)
-		align = page_align;
-	      *in_relro = false;
-	    }
-
 	  off = align_address(off, align);
 	  (*p)->set_address_and_file_offset(addr + (off - startoff), off);
 	}
@@ -3621,10 +3656,10 @@ Output_segment::set_section_list_address
 }
 
 // For a non-PT_LOAD segment, set the offset from the sections, if
-// any.
+// any.  Add INCREASE to the file size and the memory size.
 
 void
-Output_segment::set_offset()
+Output_segment::set_offset(unsigned int increase)
 {
   gold_assert(this->type_ != elfcpp::PT_LOAD);
 
@@ -3632,6 +3667,7 @@ Output_segment::set_offset()
 
   if (this->output_data_.empty() && this->output_bss_.empty())
     {
+      gold_assert(increase == 0);
       this->vaddr_ = 0;
       this->paddr_ = 0;
       this->are_addresses_set_ = true;
@@ -3673,6 +3709,9 @@ Output_segment::set_offset()
 		  + last->data_size()
 		  - this->vaddr_);
 
+  this->filesz_ += increase;
+  this->memsz_ += increase;
+
   // If this is a TLS segment, align the memory size.  The code in
   // set_section_list ensures that the section after the TLS segment
   // is aligned to give us room.
@@ -3682,16 +3721,6 @@ Output_segment::set_offset()
       gold_assert(this->vaddr_ == align_address(this->vaddr_, segment_align));
       this->memsz_ = align_address(this->memsz_, segment_align);
     }
-
-  // If this is a RELRO segment, align the memory size.  The code in
-  // set_section_list ensures that the section after the RELRO segment
-  // is aligned to give us room.
-  if (this->type_ == elfcpp::PT_GNU_RELRO)
-    {
-      uint64_t page_align = parameters->target().common_pagesize();
-      gold_assert(this->vaddr_ == align_address(this->vaddr_, page_align));
-      this->memsz_ = align_address(this->memsz_, page_align);
-    }
 }
 
 // Set the TLS offsets of the sections in the PT_TLS segment.
Index: output.h
===================================================================
RCS file: /cvs/src/src/gold/output.h,v
retrieving revision 1.92
diff -p -u -r1.92 output.h
--- output.h	30 Dec 2009 04:00:21 -0000	1.92
+++ output.h	30 Dec 2009 06:47:46 -0000
@@ -2351,6 +2351,35 @@ class Output_section : public Output_dat
   set_is_relro_local()
   { this->is_relro_local_ = true; }
 
+  // True if this must be the last relro section.
+  bool
+  is_last_relro() const
+  { return this->is_last_relro_; }
+
+  // Record that this must be the last relro section.
+  void
+  set_is_last_relro()
+  {
+    gold_assert(this->is_relro_);
+    this->is_last_relro_ = true;
+  }
+
+  // True if this must be the first section following the relro sections.
+  bool
+  is_first_non_relro() const
+  {
+    gold_assert(!this->is_relro_);
+    return this->is_first_non_relro_;
+  }
+
+  // Record that this must be the first non-relro section.
+  void
+  set_is_first_non_relro()
+  {
+    gold_assert(!this->is_relro_);
+    this->is_first_non_relro_ = true;
+  }
+
   // True if this is a small section: a section which holds small
   // variables.
   bool
@@ -3341,6 +3370,10 @@ class Output_section : public Output_dat
   bool is_relro_ : 1;
   // True if this section holds relro local data.
   bool is_relro_local_ : 1;
+  // True if this must be the last relro section.
+  bool is_last_relro_ : 1;
+  // True if this must be the first section after the relro sections.
+  bool is_first_non_relro_ : 1;
   // True if this is a small section.
   bool is_small_section_ : 1;
   // True if this is a large section.
@@ -3497,7 +3530,8 @@ class Output_segment
   // address of the immediately following segment.  Update *POFF and
   // *PSHNDX.  This should only be called for a PT_LOAD segment.
   uint64_t
-  set_section_addresses(const Layout*, bool reset, uint64_t addr, off_t* poff,
+  set_section_addresses(const Layout*, bool reset, uint64_t addr,
+			unsigned int increase_relro, off_t* poff,
 			unsigned int* pshndx);
 
   // Set the minimum alignment of this segment.  This may be adjusted
@@ -3509,7 +3543,7 @@ class Output_segment
   // Set the offset of this segment based on the section.  This should
   // only be called for a non-PT_LOAD segment.
   void
-  set_offset();
+  set_offset(unsigned int increase);
 
   // Set the TLS offsets of the sections contained in the PT_TLS segment.
   void
@@ -3555,7 +3589,7 @@ class Output_segment
   uint64_t
   set_section_list_addresses(const Layout*, bool reset, Output_data_list*,
                              uint64_t addr, off_t* poff, unsigned int* pshndx,
-                             bool* in_tls, bool* in_relro);
+                             bool* in_tls);
 
   // Return the number of Output_sections in an Output_data_list.
   unsigned int
Index: powerpc.cc
===================================================================
RCS file: /cvs/src/src/gold/powerpc.cc,v
retrieving revision 1.25
diff -p -u -r1.25 powerpc.cc
--- powerpc.cc	29 Dec 2009 00:31:48 -0000	1.25
+++ powerpc.cc	30 Dec 2009 06:47:46 -0000
@@ -716,7 +716,7 @@ Target_powerpc<size, big_endian>::got_se
 
       layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
 				      elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
-				      this->got_, false);
+				      this->got_, false, false, false, false);
 
       // Create the GOT2 or TOC in the .got section.
       if (size == 32)
@@ -725,7 +725,8 @@ Target_powerpc<size, big_endian>::got_se
 	  layout->add_output_section_data(".got2", elfcpp::SHT_PROGBITS,
 					  elfcpp::SHF_ALLOC
 					  | elfcpp::SHF_WRITE,
-					  this->got2_, false);
+					  this->got2_, false, false, false,
+					  false);
 	}
       else
 	{
@@ -733,7 +734,8 @@ Target_powerpc<size, big_endian>::got_se
 	  layout->add_output_section_data(".toc", elfcpp::SHT_PROGBITS,
 					  elfcpp::SHF_ALLOC
 					  | elfcpp::SHF_WRITE,
-					  this->toc_, false);
+					  this->toc_, false, false, false,
+					  false);
 	}
 
       // Define _GLOBAL_OFFSET_TABLE_ at the start of the .got section.
@@ -760,7 +762,8 @@ Target_powerpc<size, big_endian>::rela_d
       gold_assert(layout != NULL);
       this->rela_dyn_ = new Reloc_section(parameters->options().combreloc());
       layout->add_output_section_data(".rela.dyn", elfcpp::SHT_RELA,
-				      elfcpp::SHF_ALLOC, this->rela_dyn_, true);
+				      elfcpp::SHF_ALLOC, this->rela_dyn_, true,
+				      false, false, false);
     }
   return this->rela_dyn_;
 }
@@ -820,7 +823,8 @@ Output_data_plt_powerpc<size, big_endian
 {
   this->rel_ = new Reloc_section(false);
   layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA,
-				  elfcpp::SHF_ALLOC, this->rel_, true);
+				  elfcpp::SHF_ALLOC, this->rel_, true, false,
+				  false, false);
 }
 
 template<int size, bool big_endian>
@@ -949,7 +953,7 @@ Target_powerpc<size, big_endian>::make_p
 				      (elfcpp::SHF_ALLOC
 				       | elfcpp::SHF_EXECINSTR
 				       | elfcpp::SHF_WRITE),
-				      this->plt_, false);
+				      this->plt_, false, false, false, false);
 
       // Define _PROCEDURE_LINKAGE_TABLE_ at the start of the .plt section.
       symtab->define_in_output_data("_PROCEDURE_LINKAGE_TABLE_", NULL,
@@ -1512,7 +1516,8 @@ Target_powerpc<size, big_endian>::scan_r
     Output_section* os = layout->add_output_section_data(".sdata", 0,
 							 elfcpp::SHF_ALLOC
 							 | elfcpp::SHF_WRITE,
-							 sdata, false);
+							 sdata, false,
+							 false, false, false);
     symtab->define_in_output_data("_SDA_BASE_", NULL,
 				  Symbol_table::PREDEFINED,
 				  os,
Index: sparc.cc
===================================================================
RCS file: /cvs/src/src/gold/sparc.cc,v
retrieving revision 1.29
diff -p -u -r1.29 sparc.cc
--- sparc.cc	29 Dec 2009 00:31:48 -0000	1.29
+++ sparc.cc	30 Dec 2009 06:47:46 -0000
@@ -1026,8 +1026,8 @@ Target_sparc<size, big_endian>::got_sect
       os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
 					   (elfcpp::SHF_ALLOC
 					    | elfcpp::SHF_WRITE),
-					   this->got_, false);
-      os->set_is_relro();
+					   this->got_, false, true, false,
+					   false);
 
       // Define _GLOBAL_OFFSET_TABLE_ at the start of the .got section.
       symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL,
@@ -1053,7 +1053,8 @@ Target_sparc<size, big_endian>::rela_dyn
       gold_assert(layout != NULL);
       this->rela_dyn_ = new Reloc_section(parameters->options().combreloc());
       layout->add_output_section_data(".rela.dyn", elfcpp::SHT_RELA,
-				      elfcpp::SHF_ALLOC, this->rela_dyn_, true);
+				      elfcpp::SHF_ALLOC, this->rela_dyn_, true,
+				      false, false, false);
     }
   return this->rela_dyn_;
 }
@@ -1155,7 +1156,8 @@ Output_data_plt_sparc<size, big_endian>:
 {
   this->rel_ = new Reloc_section(false);
   layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA,
-				  elfcpp::SHF_ALLOC, this->rel_, true);
+				  elfcpp::SHF_ALLOC, this->rel_, true,
+				  false, false, false);
 }
 
 template<int size, bool big_endian>
@@ -1372,7 +1374,7 @@ Target_sparc<size, big_endian>::make_plt
 				      (elfcpp::SHF_ALLOC
 				       | elfcpp::SHF_EXECINSTR
 				       | elfcpp::SHF_WRITE),
-				      this->plt_, false);
+				      this->plt_, false, false, false, false);
 
       // Define _PROCEDURE_LINKAGE_TABLE_ at the start of the .plt section.
       symtab->define_in_output_data("_PROCEDURE_LINKAGE_TABLE_", NULL,
Index: x86_64.cc
===================================================================
RCS file: /cvs/src/src/gold/x86_64.cc,v
retrieving revision 1.100
diff -p -u -r1.100 x86_64.cc
--- x86_64.cc	29 Dec 2009 00:31:48 -0000	1.100
+++ x86_64.cc	30 Dec 2009 06:47:47 -0000
@@ -469,8 +469,8 @@ Target_x86_64::got_section(Symbol_table*
       os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
 					   (elfcpp::SHF_ALLOC
 					    | elfcpp::SHF_WRITE),
-					   this->got_, false);
-      os->set_is_relro();
+					   this->got_, false, true, true,
+					   false);
 
       // The old GNU linker creates a .got.plt section.  We just
       // create another set of data in the .got section.  Note that we
@@ -480,12 +480,15 @@ Target_x86_64::got_section(Symbol_table*
       os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
 					   (elfcpp::SHF_ALLOC
 					    | elfcpp::SHF_WRITE),
-					   this->got_plt_, false);
-      os->set_is_relro();
+					   this->got_plt_, false, false,
+					   false, true);
 
       // The first three entries are reserved.
       this->got_plt_->set_current_data_size(3 * 8);
 
+      // Those bytes can go into the relro segment.
+      layout->increase_relro(3 * 8);
+
       // Define _GLOBAL_OFFSET_TABLE_ at the start of the PLT.
       symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL,
 				    Symbol_table::PREDEFINED,
@@ -509,7 +512,8 @@ Target_x86_64::rela_dyn_section(Layout* 
       gold_assert(layout != NULL);
       this->rela_dyn_ = new Reloc_section(parameters->options().combreloc());
       layout->add_output_section_data(".rela.dyn", elfcpp::SHT_RELA,
-				      elfcpp::SHF_ALLOC, this->rela_dyn_, true);
+				      elfcpp::SHF_ALLOC, this->rela_dyn_, true,
+				      false, false, false);
     }
   return this->rela_dyn_;
 }
@@ -609,7 +613,8 @@ Output_data_plt_x86_64::Output_data_plt_
 {
   this->rel_ = new Reloc_section(false);
   layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA,
-				  elfcpp::SHF_ALLOC, this->rel_, true);
+				  elfcpp::SHF_ALLOC, this->rel_, true,
+				  false, false, false);
 }
 
 void
@@ -805,7 +810,7 @@ Target_x86_64::make_plt_section(Symbol_t
       layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
 				      (elfcpp::SHF_ALLOC
 				       | elfcpp::SHF_EXECINSTR),
-				      this->plt_, false);
+				      this->plt_, false, false, false, false);
     }
 }
 
Index: testsuite/relro_script_test.t
===================================================================
RCS file: /cvs/src/src/gold/testsuite/relro_script_test.t,v
retrieving revision 1.1
diff -p -u -r1.1 relro_script_test.t
--- testsuite/relro_script_test.t	13 Aug 2008 07:37:46 -0000	1.1
+++ testsuite/relro_script_test.t	30 Dec 2009 06:47:47 -0000
@@ -46,6 +46,8 @@ SECTIONS
 
   . = DATA_SEGMENT_RELRO_END(0, .);
 
+  .got.plt : { *(.got.plt) }
+
   .data : { *(.data .data.* .gnu.linkonce.d.*) }
 
   . = DATA_SEGMENT_END (.);

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]