[GOLD][PATCH] Fix -z relro bugs

Doug Kwan (關振德) dougkwan@google.com
Thu Mar 15 09:11:00 GMT 2012


Hi Ian,

   This patch fixes two problems related to the -z relro option.  The
first one is that .init_array, .fini_array and .preinit_array are not
handle properly in Layout::make_output_seciton.  The function only
force the relro flag if section type if SHT_PROGBITS.  The second
problem is that the ARM backend ignores the -z now option.  This patch
fixes this problem and also places the .got section at the RELRO
boundary.  This is tested on both ARM and x86_64.

-Doug


2012-03-15  Doug Kwan  <dougkwan@google.com>

        * arm.cc (Target_arm::got_section): Make .got section read-only
        if -z now is given. Also place .got section at RELRO boundary.
        * layout.cc (Layout::make_output_section): Fix a bug that causes
        .init_array, .fini_array and .preinit_array to be not included
        in the RELRO segment when -z now is given.
-------------- next part --------------
Index: gold/arm.cc
===================================================================
RCS file: /cvs/src/src/gold/arm.cc,v
retrieving revision 1.147
diff -u -u -p -r1.147 arm.cc
--- gold/arm.cc	14 Mar 2012 23:07:07 -0000	1.147
+++ gold/arm.cc	15 Mar 2012 08:22:25 -0000
@@ -4174,11 +4174,22 @@ Target_arm<big_endian>::got_section(Symb
     {
       gold_assert(symtab != NULL && layout != NULL);
 
+      // When using -z now, we can treat .got as a relro section.
+      // Without -z now, it is modified after program startup by lazy
+      // PLT relocations.
+      bool is_got_relro = parameters->options().now();
+      Output_section_order got_order = (is_got_relro
+					? ORDER_RELRO_LAST
+					: ORDER_NON_RELRO_FIRST);
+
+      // Unlike some targets (.e.g x86), ARM does not use separate .got and
+      // .got.plt sections in output.  The output .got section contains both
+      // PLT and non-PLT GOT entries.
       this->got_ = new Arm_output_data_got<big_endian>(symtab, layout);
 
       layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
 				      (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE),
-				      this->got_, ORDER_DATA, false);
+				      this->got_, got_order, is_got_relro);
 
       // The old GNU linker creates a .got.plt section.  We just
       // create another set of data in the .got section.  Note that we
@@ -4187,7 +4198,7 @@ Target_arm<big_endian>::got_section(Symb
       this->got_plt_ = new Output_data_space(4, "** GOT PLT");
       layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
 				      (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE),
-				      this->got_plt_, ORDER_DATA, false);
+				      this->got_plt_, got_order, is_got_relro);
 
       // The first three entries are reserved.
       this->got_plt_->set_current_data_size(3 * 4);
Index: gold/layout.cc
===================================================================
RCS file: /cvs/src/src/gold/layout.cc,v
retrieving revision 1.222
diff -u -u -p -r1.222 layout.cc
--- gold/layout.cc	19 Oct 2011 15:05:58 -0000	1.222
+++ gold/layout.cc	15 Mar 2012 08:22:25 -0000
@@ -1379,25 +1379,26 @@ Layout::make_output_section(const char* 
   bool is_relro_local = false;
   if (!this->script_options_->saw_sections_clause()
       && parameters->options().relro()
-      && type == elfcpp::SHT_PROGBITS
       && (flags & elfcpp::SHF_ALLOC) != 0
       && (flags & elfcpp::SHF_WRITE) != 0)
     {
-      if (strcmp(name, ".data.rel.ro") == 0)
-	is_relro = true;
-      else if (strcmp(name, ".data.rel.ro.local") == 0)
+      if (type == elfcpp::SHT_PROGBITS)
 	{
-	  is_relro = true;
-	  is_relro_local = true;
+	  if (strcmp(name, ".data.rel.ro") == 0
+	       || strcmp(name, ".ctors") == 0
+	       || strcmp(name, ".dtors") == 0
+	       || strcmp(name, ".jcr") == 0)
+	    is_relro = true;
+          else if (strcmp(name, ".data.rel.ro.local") == 0)
+	    {
+	      is_relro = true;
+	      is_relro_local = true;
+	    }
 	}
       else if (type == elfcpp::SHT_INIT_ARRAY
 	       || type == elfcpp::SHT_FINI_ARRAY
 	       || type == elfcpp::SHT_PREINIT_ARRAY)
 	is_relro = true;
-      else if (strcmp(name, ".ctors") == 0
-	       || strcmp(name, ".dtors") == 0
-	       || strcmp(name, ".jcr") == 0)
-	is_relro = true;
     }
 
   if (is_relro)


More information about the Binutils mailing list