2012-04-23 David S. Miller   Cary Coutant * 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 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 Inputs_reader; + static const unsigned int global_sym_entry_size = + Incremental_inputs_reader::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 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::header_size; + static const int input_entry_size = + Incremental_inputs_reader::input_entry_size; + static const unsigned int object_info_size = + Incremental_inputs_reader::object_info_size; + static const unsigned int input_section_entry_size = + Incremental_inputs_reader::input_section_entry_size; + static const unsigned int global_sym_entry_size = + Incremental_inputs_reader::global_sym_entry_size; + static const unsigned int incr_reloc_size = + Incremental_relocs_reader::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::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::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::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::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* target = @@ -1442,6 +1462,7 @@ Output_section_incremental_inputs::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::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::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::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::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::write_info_blocks( default: gold_unreachable(); } + + // Pad the info block to a multiple of 8 bytes. + if (static_cast(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::object_info_size; + static const unsigned int input_section_entry_size = + Incremental_inputs_reader::input_section_entry_size; + static const unsigned int global_sym_entry_size = + Incremental_inputs_reader::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(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); }