diff options
Diffstat (limited to 'gold/object.cc')
-rw-r--r-- | gold/object.cc | 95 |
1 files changed, 81 insertions, 14 deletions
diff --git a/gold/object.cc b/gold/object.cc index f7dcda8..b1f83e7 100644 --- a/gold/object.cc +++ b/gold/object.cc @@ -37,6 +37,7 @@ #include "reloc.h" #include "object.h" #include "dynobj.h" +#include "plugin.h" namespace gold { @@ -784,6 +785,34 @@ Sized_relobj<size, big_endian>::include_linkonce_section( return include1 && include2; } +// Layout an input section. + +template<int size, bool big_endian> +inline void +Sized_relobj<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) +{ + off_t offset; + Output_section* os = layout->layout(this, shndx, name, shdr, + reloc_shndx, reloc_type, &offset); + + this->output_sections()[shndx] = os; + if (offset == -1) + 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 apply to it, then we must do the special handling + // before we apply the relocs. + if (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 @@ -807,6 +836,13 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab, const unsigned char* pnamesu = sd->section_names->data(); const char* pnames = reinterpret_cast<const char*>(pnamesu); + // If any input files have been claimed by plugins, we need to defer + // actual layout until the replacement files have arrived. + const bool should_defer_layout = + (parameters->options().has_plugins() + && parameters->options().plugins()->should_defer_layout()); + unsigned int num_sections_to_defer = 0; + // For each section, record the index of the reloc section if any. // Use 0 to mean that there is no reloc section, -1U to mean that // there is more than one. @@ -818,6 +854,10 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab, { typename This::Shdr shdr(pshdrs); + // Count the number of sections whose layout will be deferred. + if (should_defer_layout && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC)) + ++num_sections_to_defer; + unsigned int sh_type = shdr.get_sh_type(); if (sh_type == elfcpp::SHT_REL || sh_type == elfcpp::SHT_RELA) { @@ -856,6 +896,12 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab, return; } + if (num_sections_to_defer > 0) + { + parameters->options().plugins()->add_deferred_layout_object(this); + this->deferred_layout_.reserve(num_sections_to_defer); + } + // Whether we've seen a .note.GNU-stack section. bool seen_gnu_stack = false; // The flags of a .note.GNU-stack section. @@ -960,22 +1006,22 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab, continue; } - off_t offset; - Output_section* os = layout->layout(this, i, name, shdr, - reloc_shndx[i], reloc_type[i], - &offset); + if (should_defer_layout && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC)) + { + this->deferred_layout_.push_back(Deferred_layout(i, name, pshdrs, + reloc_shndx[i], + reloc_type[i])); - out_sections[i] = os; - if (offset == -1) - out_section_offsets[i] = invalid_address; + // Put dummy values here; real values will be supplied by + // do_layout_deferred_sections. + out_sections[i] = reinterpret_cast<Output_section*>(1); + 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 (offset == -1 && reloc_shndx[i] != 0) - this->set_relocs_must_follow_section_writes(); + { + this->layout_section(layout, i, name, shdr, reloc_shndx[i], + reloc_type[i]); + } } layout->layout_gnu_stack(seen_gnu_stack, gnu_stack_flags); @@ -1059,6 +1105,27 @@ Sized_relobj<size, big_endian>::do_layout(Symbol_table* symtab, sd->section_names = NULL; } +// Layout sections whose layout was deferred while waiting for +// input files from a plugin. + +template<int size, bool big_endian> +void +Sized_relobj<size, big_endian>::do_layout_deferred_sections(Layout* layout) +{ + typename std::vector<Deferred_layout>::iterator deferred; + + for (deferred = this->deferred_layout_.begin(); + deferred != this->deferred_layout_.end(); + ++deferred) + { + typename This::Shdr shdr(deferred->shdr_data_); + this->layout_section(layout, deferred->shndx_, deferred->name_.c_str(), + shdr, deferred->reloc_shndx_, deferred->reloc_type_); + } + + this->deferred_layout_.clear(); +} + // Add the symbols to the symbol table. template<int size, bool big_endian> |