gold incremental file format on 64-bit

Cary Coutant ccoutant@google.com
Mon Apr 23 21:07:00 GMT 2012


> 2012-04-21  David S. Miller  <davem@davemloft.net>
>
>        * incremental.cc (Incremental_inputs::create_data_sections): Align
>        incremental reloc section to 8 bytes.
>        (Output_section_incremental_inputs::set_final_data_size): Pad out
>        offsets to ensure necessary 8-byte alignment.
>        (Output_section_incremental_inputs::write_info_block): Likewise.
>        * incremental.h (Incremental_inputs_reader::get_symbol_offset):
>        Adjust offset calculation.
>        (Incremental_inputs_reader::get_input_section): Likewise.
>        (Incremental_inputs_reader::get_global_symbol_reader): Likewise.
>        (Incremental_inputs_reader::get_comdat_group_signature): Likewise.

That patch should do fine for your purposes, but I wanted to take the
opportunity to replace some of those magic numbers with symbolic
constants, something I've been putting off for too long. The attached
patch does that, sets the relocation section alignment based on the
target size, and bumps the incremental info version number (because
this is, in fact, an incompatible change -- somehow, on Friday I
wasn't seeing the fact that this changes the layout of the info block
for object files).

Tested on x86_64. David, can you test it on Sparc?

Ian, OK to commit if it works for David?

-cary


2012-04-23  David S. Miller  <davem@davemloft.net>
	    Cary Coutant  <ccoutant@google.com>

	* incremental-dump.cc (find_input_containing_global): Replace
	magic number with symbolic constant.
	(dump_incremental_inputs): Update version number.
	* incremental.cc (Output_section_incremental_inputs): Update version
	number; import symbolic constants from Incremental_inputs_reader.
	(Incremental_inputs::create_data_sections): Align relocations
	section correctly for 64-bit targets.
	(Output_section_incremental_inputs::set_final_data_size): Use symbolic
	constants; add padding.
	(Output_section_incremental_inputs::write_header): Add assert for
	header_size.
	(Output_section_incremental_inputs::write_input_files): Add assert
	for input_entry_size.
	(Output_section_incremental_inputs::write_info_blocks): Add padding;
	add assert for object_info_size, input_section_entry_size,
	global_sym_entry_size.
	* incremental.h (Incremental_inputs_reader): Add symbolic constants
	for data structure sizes; use them.
	(Incremental_input_entry_reader): Import symbolic constants from
	Incremental_inputs_reader; use them.
-------------- next part --------------
2012-04-23  David S. Miller  <davem@davemloft.net>
	    Cary Coutant  <ccoutant@google.com>

	* incremental-dump.cc (find_input_containing_global): Replace
	magic number with symbolic constant.
	(dump_incremental_inputs): Update version number.
	* incremental.cc (Output_section_incremental_inputs): Update version
	number; import symbolic constants from Incremental_inputs_reader.
	(Incremental_inputs::create_data_sections): Align relocations
	section correctly for 64-bit targets.
	(Output_section_incremental_inputs::set_final_data_size): Use symbolic
	constants; add padding.
	(Output_section_incremental_inputs::write_header): Add assert for
	header_size.
	(Output_section_incremental_inputs::write_input_files): Add assert
	for input_entry_size.
	(Output_section_incremental_inputs::write_info_blocks): Add padding;
	add assert for object_info_size, input_section_entry_size,
	global_sym_entry_size.
	* incremental.h (Incremental_inputs_reader): Add symbolic constants
	for data structure sizes; use them.
	(Incremental_input_entry_reader): Import symbolic constants from
	Incremental_inputs_reader; use them.


commit 2e47d3156deec3c3e22e97103d3bbd83b67997ff
Author: Cary Coutant <ccoutant@google.com>
Date:   Mon Apr 23 13:20:44 2012 -0700

    Add padding where necessary; use symbolic constants.

diff --git a/gold/incremental-dump.cc b/gold/incremental-dump.cc
index fb3d25f..5365265 100644
--- a/gold/incremental-dump.cc
+++ b/gold/incremental-dump.cc
@@ -52,6 +52,9 @@ find_input_containing_global(
     unsigned int* symndx)
 {
   typedef Incremental_inputs_reader<size, big_endian> Inputs_reader;
+  static const unsigned int global_sym_entry_size =
+      Incremental_inputs_reader<size, big_endian>::global_sym_entry_size;
+
   for (unsigned int i = 0; i < incremental_inputs.input_file_count(); ++i)
     {
       typename Inputs_reader::Incremental_input_entry_reader input_file =
@@ -63,7 +66,8 @@ find_input_containing_global(
       if (offset >= input_file.get_symbol_offset(0)
           && offset < input_file.get_symbol_offset(nsyms))
 	{
-	  *symndx = (offset - input_file.get_symbol_offset(0)) / 20;
+	  *symndx = ((offset - input_file.get_symbol_offset(0))
+		     / global_sym_entry_size);
 	  return input_file;
 	}
     }
@@ -92,7 +96,7 @@ dump_incremental_inputs(const char* argv0, const char* filename,
   Incremental_inputs_reader<size, big_endian>
       incremental_inputs(inc->inputs_reader());
 
-  if (incremental_inputs.version() != 1)
+  if (incremental_inputs.version() != 2)
     {
       fprintf(stderr, "%s: %s: unknown incremental version %d\n", argv0,
               filename, incremental_inputs.version());
diff --git a/gold/incremental.cc b/gold/incremental.cc
index 60097a8..6436a35 100644
--- a/gold/incremental.cc
+++ b/gold/incremental.cc
@@ -41,9 +41,10 @@
 
 namespace gold {
 
-// Version information. Will change frequently during the development, later
-// we could think about backward (and forward?) compatibility.
-const unsigned int INCREMENTAL_LINK_VERSION = 1;
+// Version number for the .gnu_incremental_inputs section.
+// Version 1 was the initial checkin.
+// Version 2 adds some padding to ensure 8-byte alignment where necessary.
+const unsigned int INCREMENTAL_LINK_VERSION = 2;
 
 // This class manages the .gnu_incremental_inputs section, which holds
 // the header information, a directory of input files, and separate
@@ -112,8 +113,18 @@ class Output_section_incremental_inputs : public Output_section_data
 
   // Sizes of various structures.
   static const int sizeof_addr = size / 8;
-  static const int header_size = 16;
-  static const int input_entry_size = 24;
+  static const int header_size =
+      Incremental_inputs_reader<size, big_endian>::header_size;
+  static const int input_entry_size =
+      Incremental_inputs_reader<size, big_endian>::input_entry_size;
+  static const unsigned int object_info_size =
+      Incremental_inputs_reader<size, big_endian>::object_info_size;
+  static const unsigned int input_section_entry_size =
+      Incremental_inputs_reader<size, big_endian>::input_section_entry_size;
+  static const unsigned int global_sym_entry_size =
+      Incremental_inputs_reader<size, big_endian>::global_sym_entry_size;
+  static const unsigned int incr_reloc_size =
+      Incremental_relocs_reader<size, big_endian>::reloc_size;
 
   // The Incremental_inputs object.
   const Incremental_inputs* inputs_;
@@ -1193,37 +1204,44 @@ Incremental_inputs::finalize()
 void
 Incremental_inputs::create_data_sections(Symbol_table* symtab)
 {
+  int reloc_align = 4;
+
   switch (parameters->size_and_endianness())
     {
 #ifdef HAVE_TARGET_32_LITTLE
     case Parameters::TARGET_32_LITTLE:
       this->inputs_section_ =
           new Output_section_incremental_inputs<32, false>(this, symtab);
+      reloc_align = 4;
       break;
 #endif
 #ifdef HAVE_TARGET_32_BIG
     case Parameters::TARGET_32_BIG:
       this->inputs_section_ =
           new Output_section_incremental_inputs<32, true>(this, symtab);
+      reloc_align = 4;
       break;
 #endif
 #ifdef HAVE_TARGET_64_LITTLE
     case Parameters::TARGET_64_LITTLE:
       this->inputs_section_ =
           new Output_section_incremental_inputs<64, false>(this, symtab);
+      reloc_align = 8;
       break;
 #endif
 #ifdef HAVE_TARGET_64_BIG
     case Parameters::TARGET_64_BIG:
       this->inputs_section_ =
           new Output_section_incremental_inputs<64, true>(this, symtab);
+      reloc_align = 8;
       break;
 #endif
     default:
       gold_unreachable();
     }
   this->symtab_section_ = new Output_data_space(4, "** incremental_symtab");
-  this->relocs_section_ = new Output_data_space(4, "** incremental_relocs");
+  this->relocs_section_ = new Output_data_space(reloc_align,
+						"** incremental_relocs");
   this->got_plt_section_ = new Output_data_space(4, "** incremental_got_plt");
 }
 
@@ -1244,8 +1262,6 @@ void
 Output_section_incremental_inputs<size, big_endian>::set_final_data_size()
 {
   const Incremental_inputs* inputs = this->inputs_;
-  const unsigned int sizeof_addr = size / 8;
-  const unsigned int rel_size = 8 + 2 * sizeof_addr;
 
   // Offset of each input entry.
   unsigned int input_offset = this->header_size;
@@ -1289,13 +1305,13 @@ Output_section_incremental_inputs<size, big_endian>::set_final_data_size()
 	    // Input section count, global symbol count, local symbol offset,
 	    // local symbol count, first dynamic reloc, dynamic reloc count,
 	    // comdat group count.
-	    info_offset += 28;
+	    info_offset += this->object_info_size;
 	    // Each input section.
 	    info_offset += (entry->get_input_section_count()
-			    * (8 + 2 * sizeof_addr));
+			    * this->input_section_entry_size);
 	    // Each global symbol.
 	    const Object::Symbols* syms = entry->object()->get_global_symbols();
-	    info_offset += syms->size() * 20;
+	    info_offset += syms->size() * this->global_sym_entry_size;
 	    // Each comdat group.
 	    info_offset += entry->get_comdat_group_count() * 4;
 	  }
@@ -1341,7 +1357,11 @@ Output_section_incremental_inputs<size, big_endian>::set_final_data_size()
 	default:
 	  gold_unreachable();
 	}
-    }
+
+     // Pad so each supplemental info block begins at an 8-byte boundary.
+     if (info_offset & 4)
+       info_offset += 4;
+   }
 
   this->set_data_size(info_offset);
 
@@ -1351,7 +1371,7 @@ Output_section_incremental_inputs<size, big_endian>::set_final_data_size()
 
   // Set the size of the .gnu_incremental_relocs section.
   inputs->relocs_section()->set_current_data_size(inputs->get_reloc_count()
-						  * rel_size);
+						  * this->incr_reloc_size);
 
   // Set the size of the .gnu_incremental_got_plt section.
   Sized_target<size, big_endian>* target =
@@ -1442,6 +1462,7 @@ Output_section_incremental_inputs<size, big_endian>::write_header(
   Swap32::writeval(pov + 4, input_file_count);
   Swap32::writeval(pov + 8, command_line_offset);
   Swap32::writeval(pov + 12, 0);
+  gold_assert(this->header_size == 16);
   return pov + this->header_size;
 }
 
@@ -1476,6 +1497,7 @@ Output_section_incremental_inputs<size, big_endian>::write_input_files(
       Swap32::writeval(pov + 16, mtime.nanoseconds);
       Swap16::writeval(pov + 20, flags);
       Swap16::writeval(pov + 22, (*p)->arg_serial());
+      gold_assert(this->input_entry_size == 24);
       pov += this->input_entry_size;
     }
   return pov;
@@ -1549,7 +1571,9 @@ Output_section_incremental_inputs<size, big_endian>::write_info_blocks(
 	    Swap32::writeval(pov + 16, first_dynrel);
 	    Swap32::writeval(pov + 20, ndynrel);
 	    Swap32::writeval(pov + 24, ncomdat);
-	    pov += 28;
+	    Swap32::writeval(pov + 28, 0);
+	    gold_assert(this->object_info_size == 32);
+	    pov += this->object_info_size;
 
 	    // Build a temporary array to map input section indexes
 	    // from the original object file index to the index in the
@@ -1581,7 +1605,9 @@ Output_section_incremental_inputs<size, big_endian>::write_info_blocks(
 		Swap32::writeval(pov + 4, out_shndx);
 		Swap::writeval(pov + 8, out_offset);
 		Swap::writeval(pov + 8 + sizeof_addr, sh_size);
-		pov += 8 + 2 * sizeof_addr;
+		gold_assert(this->input_section_entry_size
+			    == 8 + 2 * sizeof_addr);
+		pov += this->input_section_entry_size;
 	      }
 
 	    // For each global symbol, write its associated relocations,
@@ -1634,7 +1660,8 @@ Output_section_incremental_inputs<size, big_endian>::write_info_blocks(
 		Swap32::writeval(pov + 12, nrelocs);
 		Swap32::writeval(pov + 16,
 				 first_reloc * (8 + 2 * sizeof_addr));
-		pov += 20;
+		gold_assert(this->global_sym_entry_size == 20);
+		pov += this->global_sym_entry_size;
 	      }
 
 	    // For each kept COMDAT group, write the group signature.
@@ -1745,6 +1772,13 @@ Output_section_incremental_inputs<size, big_endian>::write_info_blocks(
 	default:
 	  gold_unreachable();
 	}
+
+     // Pad the info block to a multiple of 8 bytes.
+     if (static_cast<unsigned int>(pov - oview) & 4)
+      {
+	Swap32::writeval(pov, 0);
+	pov += 4;
+      }
     }
   return pov;
 }
diff --git a/gold/incremental.h b/gold/incremental.h
index b631ae2..20ae772 100644
--- a/gold/incremental.h
+++ b/gold/incremental.h
@@ -758,6 +758,23 @@ class Incremental_inputs_reader
   typedef elfcpp::Swap<64, big_endian> Swap64;
 
  public:
+  // Size of the .gnu_incremental_inputs header.
+  // (3 x 4-byte fields, plus 4 bytes padding.)
+  static const unsigned int header_size = 16;
+  // Size of an input file entry.
+  // (2 x 4-byte fields, 1 x 12-byte field, 2 x 2-byte fields.)
+  static const unsigned int input_entry_size = 24;
+  // Size of the first part of the supplemental info block for
+  // relocatable objects and archive members.
+  // (7 x 4-byte fields, plus 4 bytes padding.)
+  static const unsigned int object_info_size = 32;
+  // Size of an input section entry.
+  // (2 x 4-byte fields, 2 x address-sized fields.)
+  static const unsigned int input_section_entry_size = 8 + 2 * size / 8;
+  // Size of a global symbol entry in the supplemental info block.
+  // (5 x 4-byte fields.)
+  static const unsigned int global_sym_entry_size = 20;
+
   Incremental_inputs_reader()
     : p_(NULL), strtab_(NULL, 0), input_file_count_(0)
   { }
@@ -788,6 +805,14 @@ class Incremental_inputs_reader
   // Reader class for an input file entry and its supplemental info.
   class Incremental_input_entry_reader
   {
+   private:
+    static const unsigned int object_info_size =
+	Incremental_inputs_reader<size, big_endian>::object_info_size;
+    static const unsigned int input_section_entry_size =
+	Incremental_inputs_reader<size, big_endian>::input_section_entry_size;
+    static const unsigned int global_sym_entry_size =
+	Incremental_inputs_reader<size, big_endian>::global_sym_entry_size;
+
    public:
     Incremental_input_entry_reader(const Incremental_inputs_reader* inputs,
 				   unsigned int offset)
@@ -866,9 +891,10 @@ class Incremental_inputs_reader
 		  || this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER);
 
       unsigned int section_count = this->get_input_section_count();
-      return (this->info_offset_ + 28
-	      + section_count * input_section_entry_size
-	      + symndx * 20);
+      return (this->info_offset_
+	      + this->object_info_size
+	      + section_count * this->input_section_entry_size
+	      + symndx * this->global_sym_entry_size);
     }
 
     // Return the global symbol count -- for objects & shared libraries only.
@@ -1001,8 +1027,9 @@ class Incremental_inputs_reader
     {
       Input_section_info info;
       const unsigned char* p = (this->inputs_->p_
-				+ this->info_offset_ + 28
-				+ n * input_section_entry_size);
+				+ this->info_offset_
+				+ this->object_info_size
+				+ n * this->input_section_entry_size);
       unsigned int name_offset = Swap32::readval(p);
       info.name = this->inputs_->get_string(name_offset);
       info.output_shndx = Swap32::readval(p + 4);
@@ -1019,9 +1046,10 @@ class Incremental_inputs_reader
 		  || this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER);
       unsigned int section_count = this->get_input_section_count();
       const unsigned char* p = (this->inputs_->p_
-				+ this->info_offset_ + 28
-				+ section_count * input_section_entry_size
-				+ n * 20);
+				+ this->info_offset_
+				+ this->object_info_size
+				+ section_count * this->input_section_entry_size
+				+ n * this->global_sym_entry_size);
       return Incremental_global_symbol_reader<big_endian>(p);
     }
 
@@ -1032,9 +1060,10 @@ class Incremental_inputs_reader
       unsigned int section_count = this->get_input_section_count();
       unsigned int symbol_count = this->get_global_symbol_count();
       const unsigned char* p = (this->inputs_->p_
-				+ this->info_offset_ + 28
-				+ section_count * input_section_entry_size
-				+ symbol_count * 20
+				+ this->info_offset_
+				+ this->object_info_size
+				+ section_count * this->input_section_entry_size
+				+ symbol_count * this->global_sym_entry_size
 				+ n * 4);
       unsigned int name_offset = Swap32::readval(p);
       return this->inputs_->get_string(name_offset);
@@ -1072,8 +1101,6 @@ class Incremental_inputs_reader
     }
 
    private:
-    // Size of an input section entry.
-    static const unsigned int input_section_entry_size = 8 + 2 * size / 8;
     // The reader instance for the containing section.
     const Incremental_inputs_reader* inputs_;
     // The flags, including the type of input file.
@@ -1089,14 +1116,14 @@ class Incremental_inputs_reader
   input_file_offset(unsigned int n) const
   {
     gold_assert(n < this->input_file_count_);
-    return 16 + n * 24;
+    return this->header_size + n * this->input_entry_size;
   }
 
   // Return the index of an input file entry given its OFFSET.
   unsigned int
   input_file_index(unsigned int offset) const
   {
-    int n = (offset - 16) / 24;
+    int n = ((offset - this->header_size) / this->input_entry_size);
     gold_assert(input_file_offset(n) == offset);
     return n;
   }
@@ -1110,7 +1137,8 @@ class Incremental_inputs_reader
   Incremental_input_entry_reader
   input_file_at_offset(unsigned int offset) const
   {
-    gold_assert(offset < 16 + this->input_file_count_ * 24);
+    gold_assert(offset < (this->header_size
+			  + this->input_file_count_ * this->input_entry_size));
     return Incremental_input_entry_reader(this, offset);
   }
 


More information about the Binutils mailing list