* gold incremental file format on 64-bit @ 2012-04-20 22:33 David Miller 2012-04-20 22:55 ` Cary Coutant 0 siblings, 1 reply; 13+ messages in thread From: David Miller @ 2012-04-20 22:33 UTC (permalink / raw) To: binutils One naggling issue with a native 64-bit sparc GOLD is that the incremental linking file format leads to many unaligned accesses which SIGBUS on sparc. Actually, much care has already been taken in the file format to put potentially 64-bit values into 8-byte sized and offsetted locations. But the individual sub-sections of the incremental linking file can end up not being 8-byte aligned. I intend to fix this by padding up each sub-section by enough to 8-byte align each one, when necessary, to fix this problem. What is the state of the incremental file format version? I need to increment it when I make this layout change, right? Or are we still at a point where we can just adjust things with impunity and without a version bump? Also, it would have been nice for the gdb-index file format to not have the unaligned cases I ran into on 64-bit sparc the other week and fixed by using Swap_unaligned. How much flexibility exists to rearrange the gdb-index file layout? Thanks. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: gold incremental file format on 64-bit 2012-04-20 22:33 gold incremental file format on 64-bit David Miller @ 2012-04-20 22:55 ` Cary Coutant 2012-04-20 23:02 ` David Miller 0 siblings, 1 reply; 13+ messages in thread From: Cary Coutant @ 2012-04-20 22:55 UTC (permalink / raw) To: David Miller; +Cc: binutils > One naggling issue with a native 64-bit sparc GOLD is that the > incremental linking file format leads to many unaligned accesses which > SIGBUS on sparc. > > Actually, much care has already been taken in the file format to put > potentially 64-bit values into 8-byte sized and offsetted locations. > > But the individual sub-sections of the incremental linking file can > end up not being 8-byte aligned. > > I intend to fix this by padding up each sub-section by enough to > 8-byte align each one, when necessary, to fix this problem. > > What is the state of the incremental file format version? I need > to increment it when I make this layout change, right? Or are we > still at a point where we can just adjust things with impunity and > without a version bump? You should be able to align the supplemental info blocks without an incompatible format change, since we find those via offsets stored in the input file entries. All you'd need to do to preserve 8-byte alignment is add 4 bytes of zeroes to each INCREMENTAL_INPUT_SCRIPT, INCREMENTAL_INPUT_OBJECT, and INCREMENTAL_INPUT_ARCHIVE_MEMBER supplemental info block. Is there anything else that's unaligned? > Also, it would have been nice for the gdb-index file format to not > have the unaligned cases I ran into on 64-bit sparc the other week and > fixed by using Swap_unaligned. How much flexibility exists to > rearrange the gdb-index file layout? The gdb index format is pretty experimental at the moment, so there is flexibility, but I'd guess that it's probably going to get replaced with something a bit more compact. The DWARF committee is about to look at a similar index that Apple is using, so we'll probably end up standardizing on something different from .gdb_index eventually. Thus, it may not be worth bothering with it until then -- you'll have to change binutils, gdb, and gold if you change the format. The gdb-discuss mailing list would be the place to discuss changes to that format. That said, the only unaligned pieces are the 64-bit values in the address area, right? The only way to align that would be to extend the third field from 32 bits to 64 bits. I think those pieces should always be 4-byte aligned as is, though, so maybe it would be better to have a version of Swap_unaligned that can handle 8-byte reads and writes to 4-byte-aligned addresses. That should be considerably faster than the pure unaligned version you're using now. -cary ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: gold incremental file format on 64-bit 2012-04-20 22:55 ` Cary Coutant @ 2012-04-20 23:02 ` David Miller 2012-04-20 23:23 ` Cary Coutant 0 siblings, 1 reply; 13+ messages in thread From: David Miller @ 2012-04-20 23:02 UTC (permalink / raw) To: ccoutant; +Cc: binutils From: Cary Coutant <ccoutant@google.com> Date: Fri, 20 Apr 2012 15:52:21 -0700 > Is there anything else that's unaligned? Yes, some of the other sections can end up with an unaligned ending if there is an odd number of entries because the individual objects are a multiple of 4 bytes in size, but not a multiple of 8. > That said, the only unaligned pieces are the 64-bit values in the > address area, right? The only way to align that would be to extend the > third field from 32 bits to 64 bits. I think those pieces should > always be 4-byte aligned as is, though, so maybe it would be better to > have a version of Swap_unaligned that can handle 8-byte reads and > writes to 4-byte-aligned addresses. That should be considerably faster > than the pure unaligned version you're using now. Makes sense. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: gold incremental file format on 64-bit 2012-04-20 23:02 ` David Miller @ 2012-04-20 23:23 ` Cary Coutant 2012-04-20 23:30 ` David Miller 0 siblings, 1 reply; 13+ messages in thread From: Cary Coutant @ 2012-04-20 23:23 UTC (permalink / raw) To: David Miller; +Cc: binutils >> Is there anything else that's unaligned? > > Yes, some of the other sections can end up with an unaligned ending if > there is an odd number of entries because the individual objects are a > multiple of 4 bytes in size, but not a multiple of 8. As far as I can tell, besides .gnu_incremental_inputs, the only other section that has any address-sized items in it is .gnu_incremental_relocs. That would probably be a bug in Incremental_inputs::create_data_sections(): this->relocs_section_ = new Output_data_space(4, "** incremental_relocs"); That "4" should be "size/8", where we'd determine "size" in the switch statement above. That'll make sure the relocs section is properly aligned. -cary ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: gold incremental file format on 64-bit 2012-04-20 23:23 ` Cary Coutant @ 2012-04-20 23:30 ` David Miller 2012-04-21 0:37 ` Cary Coutant 0 siblings, 1 reply; 13+ messages in thread From: David Miller @ 2012-04-20 23:30 UTC (permalink / raw) To: ccoutant; +Cc: binutils From: Cary Coutant <ccoutant@google.com> Date: Fri, 20 Apr 2012 16:16:12 -0700 >>> Is there anything else that's unaligned? >> >> Yes, some of the other sections can end up with an unaligned ending if >> there is an odd number of entries because the individual objects are a >> multiple of 4 bytes in size, but not a multiple of 8. > > As far as I can tell, besides .gnu_incremental_inputs, the only other > section that has any address-sized items in it is > .gnu_incremental_relocs. That would probably be a bug in > Incremental_inputs::create_data_sections(): > > this->relocs_section_ = new Output_data_space(4, "** incremental_relocs"); > > That "4" should be "size/8", where we'd determine "size" in the switch > statement above. That'll make sure the relocs section is properly > aligned. Yes, it's only the incremental inputs it seems. For input objects and archive members, the global symbol entries consume 20 bytes each and comdat groups consume 4 bytes each. For input shared objects, global symbol entries consume 4 bytes each. For input archives members and global symbols each consume 4 bytes each. So at the end of each of these incremental input sub-parts we may need to emit a 4-byte alignment pad. ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: gold incremental file format on 64-bit 2012-04-20 23:30 ` David Miller @ 2012-04-21 0:37 ` Cary Coutant 2012-04-21 0:49 ` David Miller 0 siblings, 1 reply; 13+ messages in thread From: Cary Coutant @ 2012-04-21 0:37 UTC (permalink / raw) To: David Miller; +Cc: binutils > For input objects and archive members, the global symbol entries > consume 20 bytes each and comdat groups consume 4 bytes each. > > For input shared objects, global symbol entries consume 4 bytes > each. > > For input archives members and global symbols each consume 4 bytes > each. > > So at the end of each of these incremental input sub-parts we may > need to emit a 4-byte alignment pad. Agreed. Sorry, I missed those other cases on my quick scan. It would be reasonable to do align info_offset inside the loop after the switch statement in Output_section_incremental_inputs::set_final_data_size. Then in Output_section_incremental_inputs::write_info_blocks, we'd have to fill the padding with zeroes. I can make this and the .gnu_incremental_relocs alignment fix next week, unless you want to submit a patch yourself. -cary ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: gold incremental file format on 64-bit 2012-04-21 0:37 ` Cary Coutant @ 2012-04-21 0:49 ` David Miller 2012-04-22 5:39 ` David Miller 0 siblings, 1 reply; 13+ messages in thread From: David Miller @ 2012-04-21 0:49 UTC (permalink / raw) To: ccoutant; +Cc: binutils From: Cary Coutant <ccoutant@google.com> Date: Fri, 20 Apr 2012 17:36:40 -0700 > It would be reasonable to do align info_offset inside the loop after > the switch statement in > Output_section_incremental_inputs::set_final_data_size. Then in > Output_section_incremental_inputs::write_info_blocks, we'd have to > fill the padding with zeroes. I can make this and the > .gnu_incremental_relocs alignment fix next week, unless you want to > submit a patch yourself. I plan to take care of this tonight if not over the weekend, besides I have the crummy cpu by which one can test this fully. :-) ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: gold incremental file format on 64-bit 2012-04-21 0:49 ` David Miller @ 2012-04-22 5:39 ` David Miller 2012-04-23 21:07 ` Cary Coutant 0 siblings, 1 reply; 13+ messages in thread From: David Miller @ 2012-04-22 5:39 UTC (permalink / raw) To: ccoutant; +Cc: binutils From: David Miller <davem@davemloft.net> Date: Fri, 20 Apr 2012 20:47:33 -0400 (EDT) > From: Cary Coutant <ccoutant@google.com> > Date: Fri, 20 Apr 2012 17:36:40 -0700 > >> It would be reasonable to do align info_offset inside the loop after >> the switch statement in >> Output_section_incremental_inputs::set_final_data_size. Then in >> Output_section_incremental_inputs::write_info_blocks, we'd have to >> fill the padding with zeroes. I can make this and the >> .gnu_incremental_relocs alignment fix next week, unless you want to >> submit a patch yourself. > > I plan to take care of this tonight if not over the weekend, besides > I have the crummy cpu by which one can test this fully. :-) Ok, here's what I came up with. Tested on sparc, sparc64, and x86-64. 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. diff --git a/gold/incremental.cc b/gold/incremental.cc index 60097a8..1d2bbf1 100644 --- a/gold/incremental.cc +++ b/gold/incremental.cc @@ -1223,7 +1223,7 @@ Incremental_inputs::create_data_sections(Symbol_table* symtab) 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(8, "** incremental_relocs"); this->got_plt_section_ = new Output_data_space(4, "** incremental_got_plt"); } @@ -1289,7 +1289,7 @@ 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 += 32; // Each input section. info_offset += (entry->get_input_section_count() * (8 + 2 * sizeof_addr)); @@ -1341,6 +1341,10 @@ Output_section_incremental_inputs<size, big_endian>::set_final_data_size() default: gold_unreachable(); } + + // Padding to get 8-byte alignment + if (info_offset & 4) + info_offset += 4; } this->set_data_size(info_offset); @@ -1549,7 +1553,8 @@ 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); + pov += 32; // Build a temporary array to map input section indexes // from the original object file index to the index in the @@ -1745,6 +1750,13 @@ Output_section_incremental_inputs<size, big_endian>::write_info_blocks( default: gold_unreachable(); } + + // Add padding word if necessary. + 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..1c3a833 100644 --- a/gold/incremental.h +++ b/gold/incremental.h @@ -866,7 +866,7 @@ class Incremental_inputs_reader || this->type() == INCREMENTAL_INPUT_ARCHIVE_MEMBER); unsigned int section_count = this->get_input_section_count(); - return (this->info_offset_ + 28 + return (this->info_offset_ + 32 + section_count * input_section_entry_size + symndx * 20); } @@ -1001,7 +1001,7 @@ class Incremental_inputs_reader { Input_section_info info; const unsigned char* p = (this->inputs_->p_ - + this->info_offset_ + 28 + + this->info_offset_ + 32 + n * input_section_entry_size); unsigned int name_offset = Swap32::readval(p); info.name = this->inputs_->get_string(name_offset); @@ -1019,7 +1019,7 @@ 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 + + this->info_offset_ + 32 + section_count * input_section_entry_size + n * 20); return Incremental_global_symbol_reader<big_endian>(p); @@ -1032,7 +1032,7 @@ 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 + + this->info_offset_ + 32 + section_count * input_section_entry_size + symbol_count * 20 + n * 4); ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: gold incremental file format on 64-bit 2012-04-22 5:39 ` David Miller @ 2012-04-23 21:07 ` Cary Coutant 2012-04-23 21:11 ` David Miller 2012-04-24 21:58 ` Ian Lance Taylor 0 siblings, 2 replies; 13+ messages in thread From: Cary Coutant @ 2012-04-23 21:07 UTC (permalink / raw) To: David Miller; +Cc: binutils, Ian Lance Taylor [-- Attachment #1: Type: text/plain, Size: 2476 bytes --] > 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. [-- Attachment #2: padding-patch.txt --] [-- Type: text/plain, Size: 15413 bytes --] 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); } ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: gold incremental file format on 64-bit 2012-04-23 21:07 ` Cary Coutant @ 2012-04-23 21:11 ` David Miller 2012-04-23 21:14 ` Cary Coutant 2012-04-24 21:58 ` Ian Lance Taylor 1 sibling, 1 reply; 13+ messages in thread From: David Miller @ 2012-04-23 21:11 UTC (permalink / raw) To: ccoutant; +Cc: binutils, iant From: Cary Coutant <ccoutant@google.com> Date: Mon, 23 Apr 2012 13:41:28 -0700 > Tested on x86_64. David, can you test it on Sparc? Works. > + > + // Pad the info block to a multiple of 8 bytes. > + if (static_cast<unsigned int>(pov - oview) & 4) > + { > + Swap32::writeval(pov, 0); > + pov += 4; > + } Maybe this could be indented better :-) ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: gold incremental file format on 64-bit 2012-04-23 21:11 ` David Miller @ 2012-04-23 21:14 ` Cary Coutant 2012-04-23 21:18 ` David Miller 0 siblings, 1 reply; 13+ messages in thread From: Cary Coutant @ 2012-04-23 21:14 UTC (permalink / raw) To: David Miller; +Cc: binutils, iant >> Tested on x86_64. David, can you test it on Sparc? > > Works. Thanks! >> + // Pad the info block to a multiple of 8 bytes. >> + if (static_cast<unsigned int>(pov - oview) & 4) >> + { >> + Swap32::writeval(pov, 0); >> + pov += 4; >> + } > > Maybe this could be indented better :-) Those two lines are indented by tabs. Looks fine in my editor. -cary ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: gold incremental file format on 64-bit 2012-04-23 21:14 ` Cary Coutant @ 2012-04-23 21:18 ` David Miller 0 siblings, 0 replies; 13+ messages in thread From: David Miller @ 2012-04-23 21:18 UTC (permalink / raw) To: ccoutant; +Cc: binutils, iant From: Cary Coutant <ccoutant@google.com> Date: Mon, 23 Apr 2012 14:11:28 -0700 >> Maybe this could be indented better :-) > > Those two lines are indented by tabs. Looks fine in my editor. Ok, I'm continually fooled by this :-) ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: gold incremental file format on 64-bit 2012-04-23 21:07 ` Cary Coutant 2012-04-23 21:11 ` David Miller @ 2012-04-24 21:58 ` Ian Lance Taylor 1 sibling, 0 replies; 13+ messages in thread From: Ian Lance Taylor @ 2012-04-24 21:58 UTC (permalink / raw) To: Cary Coutant; +Cc: David Miller, binutils Cary Coutant <ccoutant@google.com> writes: > 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. This is OK. Thanks. Ian ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2012-04-24 21:45 UTC | newest] Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2012-04-20 22:33 gold incremental file format on 64-bit David Miller 2012-04-20 22:55 ` Cary Coutant 2012-04-20 23:02 ` David Miller 2012-04-20 23:23 ` Cary Coutant 2012-04-20 23:30 ` David Miller 2012-04-21 0:37 ` Cary Coutant 2012-04-21 0:49 ` David Miller 2012-04-22 5:39 ` David Miller 2012-04-23 21:07 ` Cary Coutant 2012-04-23 21:11 ` David Miller 2012-04-23 21:14 ` Cary Coutant 2012-04-23 21:18 ` David Miller 2012-04-24 21:58 ` Ian Lance Taylor
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).