[gold patch] Fix incremental linking problems with .init_array and .eh_frame sections

Cary Coutant ccoutant@google.com
Sat Sep 17 01:12:00 GMT 2011


This patch fixes a couple of bugs in incremental linking.

(1) During an incremental update, the linker was failing to reserve
the space used by .init/.preinit/.fini_array sections, causing an
internal error when processing an input section from an unchanged
file. (This showed up because of .ctors input sections mapped to
.init_array sections via the new --ctors-in-init-array option.)

(2) During an incremental full link, the linker is adding padding to
the .eh_frame section, confusing the unwinder. I plan to correct this
later by supporting the .eh_frame_hdr section during an incremental
update.

Tested on x86_64. OK to commit?

-cary


	* incremental.cc (can_incremental_update): New function.
	* incremental.h (can_incremental_update): New function.
	* layout.cc (Layout::init_fixed_output_section): Call it.
	(Layout::make_output_section): Don't allow patch space in .eh_frame.
	* object.cc (Sized_relobj_file::do_layout): Call
	can_incremental_update.
-------------- next part --------------
2011-09-16  Cary Coutant  <ccoutant@google.com>

	* incremental.cc (can_incremental_update): New function.
	* incremental.h (can_incremental_update): New function.
	* layout.cc (Layout::init_fixed_output_section): Call it.
	(Layout::make_output_section): Don't allow patch space in .eh_frame.
	* object.cc (Sized_relobj_file::do_layout): Call
	can_incremental_update.


commit 4c039a65c7edc85f1401160e912eaf164fb970ef
Author: Cary Coutant <ccoutant@google.com>
Date:   Fri Sep 16 16:07:29 2011 -0700

    Fix incremental linking to handle .init/.fini_array and .eh_frame properly.

diff --git a/gold/incremental.cc b/gold/incremental.cc
index 4c4483d..998c04d 100644
--- a/gold/incremental.cc
+++ b/gold/incremental.cc
@@ -161,6 +161,22 @@ Incremental_binary::error(const char* format, ...) const
   va_end(args);
 }
 
+// Return TRUE if a section of type SH_TYPE will can be updated in place
+// during an incremental update.  We can update sections of type PROGBITS,
+// NOBITS, INIT_ARRAY, FINI_ARRAY, PREINIT_ARRAY, and NOTE.  All others
+// will be regenerated.
+
+bool
+can_incremental_update(unsigned int sh_type)
+{
+  return (sh_type == elfcpp::SHT_PROGBITS
+	  || sh_type == elfcpp::SHT_NOBITS
+	  || sh_type == elfcpp::SHT_INIT_ARRAY
+	  || sh_type == elfcpp::SHT_FINI_ARRAY
+	  || sh_type == elfcpp::SHT_PREINIT_ARRAY
+	  || sh_type == elfcpp::SHT_NOTE);
+}
+
 // Find the .gnu_incremental_inputs section and related sections.
 
 template<int size, bool big_endian>
diff --git a/gold/incremental.h b/gold/incremental.h
index 1e4d9f5..5d1ebda 100644
--- a/gold/incremental.h
+++ b/gold/incremental.h
@@ -81,6 +81,11 @@ enum Incremental_shlib_symbol_flags
 
 static const int INCREMENTAL_SHLIB_SYM_FLAGS_SHIFT = 30;
 
+// Return TRUE if a section of type SH_TYPE will can be updated in place
+// during an incremental update.
+bool
+can_incremental_update(unsigned int sh_type);
+
 // Create an Incremental_binary object for FILE. Returns NULL is this is not
 // possible, e.g. FILE is not an ELF file or has an unsupported target.
 
diff --git a/gold/layout.cc b/gold/layout.cc
index afb5b6a..1c32bcf 100644
--- a/gold/layout.cc
+++ b/gold/layout.cc
@@ -898,11 +898,10 @@ Layout::init_fixed_output_section(const char* name,
 {
   unsigned int sh_type = shdr.get_sh_type();
 
-  // We preserve the layout of PROGBITS, NOBITS, and NOTE sections.
+  // We preserve the layout of PROGBITS, NOBITS, INIT_ARRAY, FINI_ARRAY,
+  // PRE_INIT_ARRAY, and NOTE sections.
   // All others will be created from scratch and reallocated.
-  if (sh_type != elfcpp::SHT_PROGBITS
-      && sh_type != elfcpp::SHT_NOBITS
-      && sh_type != elfcpp::SHT_NOTE)
+  if (!can_incremental_update(sh_type))
     return NULL;
 
   typename elfcpp::Elf_types<size>::Elf_Addr sh_addr = shdr.get_sh_addr();
@@ -1442,6 +1441,7 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
       && order != ORDER_FINI
       && order != ORDER_RELRO_LAST
       && order != ORDER_NON_RELRO_FIRST
+      && strcmp(name, ".eh_frame") != 0
       && strcmp(name, ".ctors") != 0
       && strcmp(name, ".dtors") != 0
       && strcmp(name, ".jcr") != 0)
diff --git a/gold/object.cc b/gold/object.cc
index 99c2ca7..84a9646 100644
--- a/gold/object.cc
+++ b/gold/object.cc
@@ -1344,9 +1344,7 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab,
 	  Incremental_inputs* incremental_inputs = layout->incremental_inputs();
 	  if (incremental_inputs != NULL
 	      && !discard
-	      && (shdr.get_sh_type() == elfcpp::SHT_PROGBITS
-	          || shdr.get_sh_type() == elfcpp::SHT_NOBITS
-	          || shdr.get_sh_type() == elfcpp::SHT_NOTE))
+	      && can_incremental_update(shdr.get_sh_type()))
 	    {
 	      off_t sh_size = shdr.get_sh_size();
 	      section_size_type uncompressed_size;


More information about the Binutils mailing list