#include "reloc.h"
#include "object.h"
#include "dynobj.h"
+#include "plugin.h"
namespace gold
{
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
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.
{
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)
{
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.
{
// Do not include this section in the link.
out_sections[i] = NULL;
- out_section_offsets[i] = -1U;
+ out_section_offsets[i] = invalid_address;
continue;
}
continue;
}
- off_t offset;
- Output_section* os = layout->layout(this, i, name, shdr,
- reloc_shndx[i], reloc_type[i],
- &offset);
-
- out_sections[i] = os;
- if (offset == -1)
- out_section_offsets[i] = -1U;
+ 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]));
+
+ // 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);
if (data_section == NULL)
{
out_sections[i] = NULL;
- out_section_offsets[i] = -1U;
+ out_section_offsets[i] = invalid_address;
continue;
}
Output_section* os = layout->layout_reloc(this, i, shdr, data_section,
rr);
out_sections[i] = os;
- out_section_offsets[i] = -1U;
+ out_section_offsets[i] = invalid_address;
}
// Handle the .eh_frame sections at the end.
&offset);
out_sections[i] = os;
if (offset == -1)
- out_section_offsets[i] = -1U;
+ out_section_offsets[i] = invalid_address;
else
out_section_offsets[i] = convert_types<Address, off_t>(offset);
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>
// so we leave the input value unchanged here.
continue;
}
- else if (out_offsets[shndx] == -1U)
+ else if (out_offsets[shndx] == invalid_address)
{
// This is a SHF_MERGE section or one which otherwise
// requires special handling. We get the output address
Output_symtab_xindex* symtab_xindex,
Output_symtab_xindex* dynsym_xindex)
{
- if (parameters->options().strip_all()
- && this->output_local_dynsym_count_ == 0)
- return;
+ const bool strip_all = parameters->options().strip_all();
+ if (strip_all)
+ {
+ if (this->output_local_dynsym_count_ == 0)
+ return;
+ this->output_local_symbol_count_ = 0;
+ }
gold_assert(this->symtab_shndx_ != -1U);
if (this->symtab_shndx_ == 0)
st_shndx = out_sections[st_shndx]->out_shndx();
if (st_shndx >= elfcpp::SHN_LORESERVE)
{
- if (lv.needs_output_symtab_entry())
+ if (lv.needs_output_symtab_entry() && !strip_all)
symtab_xindex->add(lv.output_symtab_index(), st_shndx);
if (lv.needs_output_dynsym_entry())
dynsym_xindex->add(lv.output_dynsym_index(), st_shndx);
}
// Write the symbol to the output symbol table.
- if (!parameters->options().strip_all()
- && lv.needs_output_symtab_entry())
+ if (!strip_all && lv.needs_output_symtab_entry())
{
elfcpp::Sym_write<size, big_endian> osym(ov);
*found = true;
Output_section* os = kept->object_->output_section(kept->shndx_);
Address offset = kept->object_->get_output_section_offset(kept->shndx_);
- gold_assert(os != NULL && offset != -1U);
+ gold_assert(os != NULL && offset != invalid_address);
return os->address() + offset;
}
*found = false;