diff options
-rw-r--r-- | gold/ChangeLog | 13 | ||||
-rw-r--r-- | gold/object.cc | 127 | ||||
-rw-r--r-- | gold/object.h | 11 |
3 files changed, 113 insertions, 38 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog index ae21427..62ee3ca 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,5 +1,18 @@ 2011-06-29 Ian Lance Taylor <iant@google.com> + PR gold/12629 + * object.cc (Sized_relobj_file::layout_section): Change shdr + parameter to be const. + (Sized_relobj_file::layout_eh_frame_section): New function, broken + out of do_layout. + (Sized_relobj_file::do_layout): Defer .eh_frame sections if + appropriate. Call layout_eh_frame_section. + (Sized_relobj_file::do_layout_deferred_sections): Handle .eh_frame + sections. + * object.h (class Sized_relobj_file): Update declarations. + +2011-06-29 Ian Lance Taylor <iant@google.com> + PR gold/12652 * script.cc (Token::integer_value): Accept trailing M/m/K/k modifier. diff --git a/gold/object.cc b/gold/object.cc index 322f56e..d3835df 100644 --- a/gold/object.cc +++ b/gold/object.cc @@ -1018,12 +1018,13 @@ Sized_relobj_file<size, big_endian>::include_linkonce_section( template<int size, bool big_endian> inline void -Sized_relobj_file<size, big_endian>::layout_section(Layout* layout, - unsigned int shndx, - const char* name, - typename This::Shdr& shdr, - unsigned int reloc_shndx, - unsigned int reloc_type) +Sized_relobj_file<size, big_endian>::layout_section( + Layout* layout, + unsigned int shndx, + const char* name, + const typename This::Shdr& shdr, + unsigned int reloc_shndx, + unsigned int reloc_type) { off_t offset; Output_section* os = layout->layout(this, shndx, name, shdr, @@ -1042,6 +1043,53 @@ Sized_relobj_file<size, big_endian>::layout_section(Layout* layout, this->set_relocs_must_follow_section_writes(); } +// Layout an input .eh_frame section. + +template<int size, bool big_endian> +void +Sized_relobj_file<size, big_endian>::layout_eh_frame_section( + Layout* layout, + const unsigned char* symbols_data, + section_size_type symbols_size, + const unsigned char* symbol_names_data, + section_size_type symbol_names_size, + unsigned int shndx, + const typename This::Shdr& shdr, + unsigned int reloc_shndx, + unsigned int reloc_type) +{ + gold_assert(this->has_eh_frame_); + + off_t offset; + Output_section* os = layout->layout_eh_frame(this, + symbols_data, + symbols_size, + symbol_names_data, + symbol_names_size, + shndx, + shdr, + reloc_shndx, + reloc_type, + &offset); + this->output_sections()[shndx] = os; + if (os == NULL || offset == -1) + { + // An object can contain at most one section holding exception + // frame information. + gold_assert(this->discarded_eh_frame_shndx_ == -1U); + this->discarded_eh_frame_shndx_ = shndx; + this->section_offsets()[shndx] = invalid_address; + } + else + this->section_offsets()[shndx] = convert_types<Address, off_t>(offset); + + // If this section requires special handling, and if there are + // relocs that aply to it, then we must do the special handling + // before we apply the relocs. + if (os != NULL && offset == -1 && reloc_shndx != 0) + this->set_relocs_must_follow_section_writes(); +} + // Lay out the input sections. We walk through the sections and check // whether they should be included in the link. If they should, we // pass them to the Layout object, which will return an output section @@ -1367,7 +1415,12 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab, out_sections[i] = reinterpret_cast<Output_section*>(1); out_section_offsets[i] = invalid_address; } - else + else if (should_defer_layout) + this->deferred_layout_.push_back(Deferred_layout(i, name, + pshdrs, + reloc_shndx[i], + reloc_type[i])); + else eh_frame_sections.push_back(i); continue; } @@ -1527,7 +1580,6 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab, p != eh_frame_sections.end(); ++p) { - gold_assert(this->has_eh_frame_); gold_assert(external_symbols_offset != 0); unsigned int i = *p; @@ -1535,33 +1587,15 @@ Sized_relobj_file<size, big_endian>::do_layout(Symbol_table* symtab, pshdr = section_headers_data + i * This::shdr_size; typename This::Shdr shdr(pshdr); - off_t offset; - Output_section* os = layout->layout_eh_frame(this, - symbols_data, - symbols_size, - symbol_names_data, - symbol_names_size, - i, shdr, - reloc_shndx[i], - reloc_type[i], - &offset); - out_sections[i] = os; - if (os == NULL || offset == -1) - { - // An object can contain at most one section holding exception - // frame information. - gold_assert(this->discarded_eh_frame_shndx_ == -1U); - this->discarded_eh_frame_shndx_ = i; - out_section_offsets[i] = invalid_address; - } - else - out_section_offsets[i] = convert_types<Address, off_t>(offset); - - // If this section requires special handling, and if there are - // relocs that apply to it, then we must do the special handling - // before we apply the relocs. - if (os != NULL && offset == -1 && reloc_shndx[i] != 0) - this->set_relocs_must_follow_section_writes(); + this->layout_eh_frame_section(layout, + symbols_data, + symbols_size, + symbol_names_data, + symbol_names_size, + i, + shdr, + reloc_shndx[i], + reloc_type[i]); } if (is_gc_pass_two) @@ -1600,8 +1634,27 @@ Sized_relobj_file<size, big_endian>::do_layout_deferred_sections(Layout* layout) if (!this->is_section_included(deferred->shndx_)) continue; - this->layout_section(layout, deferred->shndx_, deferred->name_.c_str(), - shdr, deferred->reloc_shndx_, deferred->reloc_type_); + if (parameters->options().relocatable() + || deferred->name_ != ".eh_frame" + || !this->check_eh_frame_flags(&shdr)) + this->layout_section(layout, deferred->shndx_, deferred->name_.c_str(), + shdr, deferred->reloc_shndx_, + deferred->reloc_type_); + else + { + // Reading the symbols again here may be slow. + Read_symbols_data sd; + this->read_symbols(&sd); + this->layout_eh_frame_section(layout, + sd.symbols->data(), + sd.symbols_size, + sd.symbol_names->data(), + sd.symbol_names_size, + deferred->shndx_, + shdr, + deferred->reloc_shndx_, + deferred->reloc_type_); + } } this->deferred_layout_.clear(); diff --git a/gold/object.h b/gold/object.h index 8735f9e..9c363cd 100644 --- a/gold/object.h +++ b/gold/object.h @@ -2306,9 +2306,18 @@ class Sized_relobj_file : public Sized_relobj<size, big_endian> // Layout an input section. void layout_section(Layout* layout, unsigned int shndx, const char* name, - typename This::Shdr& shdr, unsigned int reloc_shndx, + const typename This::Shdr& shdr, unsigned int reloc_shndx, unsigned int reloc_type); + // Layout an input .eh_frame section. + void + layout_eh_frame_section(Layout* layout, const unsigned char* symbols_data, + section_size_type symbols_size, + const unsigned char* symbol_names_data, + section_size_type symbol_names_size, + unsigned int shndx, const typename This::Shdr&, + unsigned int reloc_shndx, unsigned int reloc_type); + // Write section data to the output file. Record the views and // sizes in VIEWS for use when relocating. void |