aboutsummaryrefslogtreecommitdiff
path: root/gold/object.cc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>2011-06-30 00:50:13 +0000
committerIan Lance Taylor <ian@airs.com>2011-06-30 00:50:13 +0000
commit14788a3f86c56a4da38d8655b61e599a6dce7c12 (patch)
tree4e9de7fbfc578ff236481be4fceca8c387d02bba /gold/object.cc
parentb9c00dd73c6e56ec55a1b563b0f7a6d94da5f58f (diff)
downloadfsf-binutils-gdb-14788a3f86c56a4da38d8655b61e599a6dce7c12.zip
fsf-binutils-gdb-14788a3f86c56a4da38d8655b61e599a6dce7c12.tar.gz
fsf-binutils-gdb-14788a3f86c56a4da38d8655b61e599a6dce7c12.tar.bz2
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.
Diffstat (limited to 'gold/object.cc')
-rw-r--r--gold/object.cc127
1 files changed, 90 insertions, 37 deletions
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();