// Layout methods.
Layout::Layout(const General_options& options, Script_options* script_options)
- : options_(options), script_options_(script_options), namepool_(),
- sympool_(), dynpool_(), signatures_(),
- section_name_map_(), segment_list_(), section_list_(),
- unattached_section_list_(), special_output_list_(),
- section_headers_(NULL), tls_segment_(NULL), symtab_section_(NULL),
- dynsym_section_(NULL), dynamic_section_(NULL), dynamic_data_(NULL),
- eh_frame_section_(NULL), eh_frame_data_(NULL), eh_frame_hdr_section_(NULL),
- build_id_note_(NULL), group_signatures_(), output_file_size_(-1),
+ : options_(options),
+ script_options_(script_options),
+ namepool_(),
+ sympool_(),
+ dynpool_(),
+ signatures_(),
+ section_name_map_(),
+ segment_list_(),
+ section_list_(),
+ unattached_section_list_(),
+ sections_are_attached_(false),
+ special_output_list_(),
+ section_headers_(NULL),
+ tls_segment_(NULL),
+ symtab_section_(NULL),
+ symtab_xindex_(NULL),
+ dynsym_section_(NULL),
+ dynsym_xindex_(NULL),
+ dynamic_section_(NULL),
+ dynamic_data_(NULL),
+ eh_frame_section_(NULL),
+ eh_frame_data_(NULL),
+ added_eh_frame_data_(false),
+ eh_frame_hdr_section_(NULL),
+ build_id_note_(NULL),
+ group_signatures_(),
+ output_file_size_(-1),
input_requires_executable_stack_(false),
input_with_gnu_stack_note_(false),
input_without_gnu_stack_note_(false),
if (parameters->options().strip_debug()
&& (shdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0)
{
- // Debugging sections can only be recognized by name.
- if (is_prefix_of(".debug", name)
- || is_prefix_of(".gnu.linkonce.wi.", name)
- || is_prefix_of(".line", name)
- || is_prefix_of(".stab", name))
+ if (is_debug_info_section(name))
return false;
}
if (parameters->options().strip_debug_gdb()
Layout::get_output_section(const char* name, Stringpool::Key name_key,
elfcpp::Elf_Word type, elfcpp::Elf_Xword flags)
{
- const Key key(name_key, std::make_pair(type, flags));
+ elfcpp::Elf_Xword lookup_flags = flags;
+
+ // Ignoring SHF_WRITE and SHF_EXECINSTR here means that we combine
+ // read-write with read-only sections. Some other ELF linkers do
+ // not do this. FIXME: Perhaps there should be an option
+ // controlling this.
+ lookup_flags &= ~(elfcpp::SHF_WRITE | elfcpp::SHF_EXECINSTR);
+
+ const Key key(name_key, std::make_pair(type, lookup_flags));
const std::pair<Key, Output_section*> v(key, NULL);
std::pair<Section_name_map::iterator, bool> ins(
this->section_name_map_.insert(v));
Section_name_map::iterator p =
this->section_name_map_.find(zero_key);
if (p != this->section_name_map_.end())
- {
- os = p->second;
- if ((flags & elfcpp::SHF_ALLOC) != 0)
- this->allocate_output_section(os, flags);
- }
+ os = p->second;
}
}
// Pick the output section to use for section NAME, in input file
// RELOBJ, with type TYPE and flags FLAGS. RELOBJ may be NULL for a
-// linker created section. ADJUST_NAME is true if we should apply the
-// standard name mappings in Layout::output_section_name. This will
-// return NULL if the input section should be discarded.
+// linker created section. IS_INPUT_SECTION is true if we are
+// choosing an output section for an input section found in a input
+// file. This will return NULL if the input section should be
+// discarded.
Output_section*
Layout::choose_output_section(const Relobj* relobj, const char* name,
elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
- bool adjust_name)
+ bool is_input_section)
{
- // We should ignore some flags. FIXME: This will need some
- // adjustment for ld -r.
+ // We should not see any input sections after we have attached
+ // sections to segments.
+ gold_assert(!is_input_section || !this->sections_are_attached_);
+
+ // Some flags in the input section should not be automatically
+ // copied to the output section.
flags &= ~ (elfcpp::SHF_INFO_LINK
| elfcpp::SHF_LINK_ORDER
| elfcpp::SHF_GROUP
if (output_section_slot != NULL)
{
if (*output_section_slot != NULL)
- {
- // If the output section was created unallocated, and we
- // are now allocating it, then we need to clear the
- // address set in the constructor and remove it from the
- // unattached section list.
- if (((*output_section_slot)->flags() & elfcpp::SHF_ALLOC) == 0
- && (flags & elfcpp::SHF_ALLOC) != 0)
- this->allocate_output_section(*output_section_slot, flags);
-
- return *output_section_slot;
- }
+ return *output_section_slot;
// We don't put sections found in the linker script into
// SECTION_NAME_MAP_. That keeps us from getting confused
// output section.
size_t len = strlen(name);
- if (adjust_name && !parameters->options().relocatable())
+ if (is_input_section && !parameters->options().relocatable())
name = Layout::output_section_name(name, &len);
Stringpool::Key name_key;
const char* group_section_name,
const char* signature,
const elfcpp::Shdr<size, big_endian>& shdr,
- const elfcpp::Elf_Word* contents)
+ elfcpp::Elf_Word flags,
+ std::vector<unsigned int>* shndxes)
{
gold_assert(parameters->options().relocatable());
gold_assert(shdr.get_sh_type() == elfcpp::SHT_GROUP);
section_size_type entry_count =
convert_to_section_size_type(shdr.get_sh_size() / 4);
Output_section_data* posd =
- new Output_data_group<size, big_endian>(object, entry_count, contents);
+ new Output_data_group<size, big_endian>(object, entry_count, flags,
+ shndxes);
os->add_output_section_data(posd);
}
if (os == NULL)
return NULL;
- // On some targets gcc assumes that a read-only .eh_frame section
- // will be merged with a read-write .eh_frame section.
- if ((shdr.get_sh_flags() & elfcpp::SHF_WRITE) != 0
- && (os->flags() & elfcpp::SHF_WRITE) == 0)
- {
- elfcpp::Elf_Xword new_flags = os->flags() | elfcpp::SHF_WRITE;
- this->write_enable_output_section(os, new_flags);
- os->set_flags(new_flags);
- }
-
if (this->eh_frame_section_ == NULL)
{
this->eh_frame_section_ = os;
this->eh_frame_data_ = new Eh_frame();
- os->add_output_section_data(this->eh_frame_data_);
if (this->options_.eh_frame_hdr())
{
shndx,
reloc_shndx,
reloc_type))
- *off = -1;
+ {
+ os->update_flags_for_input_section(shdr.get_sh_flags());
+
+ // We found a .eh_frame section we are going to optimize, so now
+ // we can add the set of optimized sections to the output
+ // section. We need to postpone adding this until we've found a
+ // section we can optimize so that the .eh_frame section in
+ // crtbegin.o winds up at the start of the output section.
+ if (!this->added_eh_frame_data_)
+ {
+ os->add_output_section_data(this->eh_frame_data_);
+ this->added_eh_frame_data_ = true;
+ }
+ *off = -1;
+ }
else
{
// We couldn't handle this .eh_frame section for some reason.
this->section_list_.push_back(os);
- if ((flags & elfcpp::SHF_ALLOC) == 0)
- this->unattached_section_list_.push_back(os);
- else
- this->attach_to_segment(os, flags);
-
// The GNU linker by default sorts some sections by priority, so we
// do the same. We need to know that this might happen before we
// attach any input sections.
|| strcmp(name, ".fini_array") == 0))
os->set_may_sort_attached_input_sections();
+ // If we have already attached the sections to segments, then we
+ // need to attach this one now. This happens for sections created
+ // directly by the linker.
+ if (this->sections_are_attached_)
+ this->attach_section_to_segment(os);
+
return os;
}
+// Attach output sections to segments. This is called after we have
+// seen all the input sections.
+
+void
+Layout::attach_sections_to_segments()
+{
+ for (Section_list::iterator p = this->section_list_.begin();
+ p != this->section_list_.end();
+ ++p)
+ this->attach_section_to_segment(*p);
+
+ this->sections_are_attached_ = true;
+}
+
+// Attach an output section to a segment.
+
+void
+Layout::attach_section_to_segment(Output_section* os)
+{
+ if ((os->flags() & elfcpp::SHF_ALLOC) == 0)
+ this->unattached_section_list_.push_back(os);
+ else
+ this->attach_allocated_section_to_segment(os);
+}
+
// Attach an allocated output section to a segment.
void
-Layout::attach_to_segment(Output_section* os, elfcpp::Elf_Xword flags)
+Layout::attach_allocated_section_to_segment(Output_section* os)
{
+ elfcpp::Elf_Xword flags = os->flags();
gold_assert((flags & elfcpp::SHF_ALLOC) != 0);
if (parameters->options().relocatable())
return os;
}
-// We have to move an existing output section from the unallocated
-// list to the allocated list.
-
-void
-Layout::allocate_output_section(Output_section* os, elfcpp::Elf_Xword flags)
-{
- os->reset_address_and_file_offset();
-
- Section_list::iterator p = std::find(this->unattached_section_list_.begin(),
- this->unattached_section_list_.end(),
- os);
- gold_assert(p != this->unattached_section_list_.end());
- this->unattached_section_list_.erase(p);
-
- this->attach_to_segment(os, flags);
-}
-
-// We have to move an existing output section from the read-only
-// segment to the writable segment.
-
-void
-Layout::write_enable_output_section(Output_section* os,
- elfcpp::Elf_Xword flags)
-{
- gold_assert((os->flags() & elfcpp::SHF_WRITE) == 0);
- gold_assert(os->type() == elfcpp::SHT_PROGBITS);
- gold_assert((flags & elfcpp::SHF_WRITE) != 0);
- gold_assert((flags & elfcpp::SHF_ALLOC) != 0);
-
- if (parameters->options().relocatable())
- return;
-
- if (this->script_options_->saw_sections_clause())
- return;
-
- Segment_list::iterator p;
- for (p = this->segment_list_.begin();
- p != this->segment_list_.end();
- ++p)
- {
- if ((*p)->type() == elfcpp::PT_LOAD
- && ((*p)->flags() & elfcpp::PF_W) == 0)
- {
- (*p)->remove_output_section(os);
- break;
- }
- }
- gold_assert(p != this->segment_list_.end());
-
- this->attach_to_segment(os, flags);
-}
-
// Return the number of segments we expect to see.
size_t
// sections.
off = this->set_section_offsets(off, BEFORE_INPUT_SECTIONS_PASS);
+ // Set the section indexes of all unallocated sections seen so far,
+ // in case any of them are somehow referenced by a symbol.
+ shndx = this->set_section_indexes(shndx);
+
// Create the symbol table sections.
- this->create_symtab_sections(input_objects, symtab, &off);
+ this->create_symtab_sections(input_objects, symtab, shndx, &off);
if (!parameters->doing_static_link())
this->assign_local_dynsym_offsets(input_objects);
// don't have to wait for the input sections.
off = this->set_section_offsets(off, BEFORE_INPUT_SECTIONS_PASS);
- // Now that all sections have been created, set the section indexes.
+ // Now that all sections have been created, set the section indexes
+ // for any sections which haven't been done yet.
shndx = this->set_section_indexes(shndx);
// Create the section table header.
- this->create_shdrs(&off);
+ this->create_shdrs(shstrtab_section, &off);
// If there are no sections which require postprocessing, we can
// handle the section names now, and avoid a resize later.
unsigned int
Layout::set_section_indexes(unsigned int shndx)
{
- const bool output_is_object = parameters->options().relocatable();
for (Section_list::iterator p = this->unattached_section_list_.begin();
p != this->unattached_section_list_.end();
++p)
{
- // In a relocatable link, we already did group sections.
- if (output_is_object
- && (*p)->type() == elfcpp::SHT_GROUP)
- continue;
-
- (*p)->set_out_shndx(shndx);
- ++shndx;
+ if (!(*p)->has_out_shndx())
+ {
+ (*p)->set_out_shndx(shndx);
+ ++shndx;
+ }
}
return shndx;
}
// Create the symbol table sections. Here we also set the final
// values of the symbols. At this point all the loadable sections are
-// fully laid out.
+// fully laid out. SHNUM is the number of sections so far.
void
Layout::create_symtab_sections(const Input_objects* input_objects,
Symbol_table* symtab,
+ unsigned int shnum,
off_t* poff)
{
int symsize;
align);
osymtab->add_output_section_data(pos);
+ // We generate a .symtab_shndx section if we have more than
+ // SHN_LORESERVE sections. Technically it is possible that we
+ // don't need one, because it is possible that there are no
+ // symbols in any of sections with indexes larger than
+ // SHN_LORESERVE. That is probably unusual, though, and it is
+ // easier to always create one than to compute section indexes
+ // twice (once here, once when writing out the symbols).
+ if (shnum >= elfcpp::SHN_LORESERVE)
+ {
+ const char* symtab_xindex_name = this->namepool_.add(".symtab_shndx",
+ false, NULL);
+ Output_section* osymtab_xindex =
+ this->make_output_section(symtab_xindex_name,
+ elfcpp::SHT_SYMTAB_SHNDX, 0);
+
+ size_t symcount = (off - startoff) / symsize;
+ this->symtab_xindex_ = new Output_symtab_xindex(symcount);
+
+ osymtab_xindex->add_output_section_data(this->symtab_xindex_);
+
+ osymtab_xindex->set_link_section(osymtab);
+ osymtab_xindex->set_addralign(4);
+ osymtab_xindex->set_entsize(4);
+
+ osymtab_xindex->set_after_input_sections();
+
+ // This tells the driver code to wait until the symbol table
+ // has written out before writing out the postprocessing
+ // sections, including the .symtab_shndx section.
+ this->any_postprocessing_sections_ = true;
+ }
+
const char* strtab_name = this->namepool_.add(".strtab", false, NULL);
Output_section* ostrtab = this->make_output_section(strtab_name,
elfcpp::SHT_STRTAB,
// offset.
void
-Layout::create_shdrs(off_t* poff)
+Layout::create_shdrs(const Output_section* shstrtab_section, off_t* poff)
{
Output_section_headers* oshdrs;
oshdrs = new Output_section_headers(this,
&this->segment_list_,
&this->section_list_,
&this->unattached_section_list_,
- &this->namepool_);
+ &this->namepool_,
+ shstrtab_section);
off_t off = align_address(*poff, oshdrs->addralign());
oshdrs->set_address_and_file_offset(0, off);
off += oshdrs->data_size();
this->section_headers_ = oshdrs;
}
+// Count the allocated sections.
+
+size_t
+Layout::allocated_output_section_count() const
+{
+ size_t section_count = 0;
+ for (Segment_list::const_iterator p = this->segment_list_.begin();
+ p != this->segment_list_.end();
+ ++p)
+ section_count += (*p)->output_section_count();
+ return section_count;
+}
+
// Create the dynamic symbol table.
void
unsigned int local_symcount = index;
*plocal_dynamic_count = local_symcount;
- // FIXME: We have to tell set_dynsym_indexes whether the
- // -E/--export-dynamic option was used.
index = symtab->set_dynsym_indexes(index, pdynamic_symbols,
&this->dynpool_, pversions);
odyn->add_section_address(elfcpp::DT_SYMTAB, dynsym);
odyn->add_constant(elfcpp::DT_SYMENT, symsize);
+ // If there are more than SHN_LORESERVE allocated sections, we
+ // create a .dynsym_shndx section. It is possible that we don't
+ // need one, because it is possible that there are no dynamic
+ // symbols in any of the sections with indexes larger than
+ // SHN_LORESERVE. This is probably unusual, though, and at this
+ // time we don't know the actual section indexes so it is
+ // inconvenient to check.
+ if (this->allocated_output_section_count() >= elfcpp::SHN_LORESERVE)
+ {
+ Output_section* dynsym_xindex =
+ this->choose_output_section(NULL, ".dynsym_shndx",
+ elfcpp::SHT_SYMTAB_SHNDX,
+ elfcpp::SHF_ALLOC,
+ false);
+
+ this->dynsym_xindex_ = new Output_symtab_xindex(index);
+
+ dynsym_xindex->add_output_section_data(this->dynsym_xindex_);
+
+ dynsym_xindex->set_link_section(dynsym);
+ dynsym_xindex->set_addralign(4);
+ dynsym_xindex->set_entsize(4);
+
+ dynsym_xindex->set_after_input_sections();
+
+ // This tells the driver code to wait until the symbol table has
+ // written out before writing out the postprocessing sections,
+ // including the .dynsym_shndx section.
+ this->any_postprocessing_sections_ = true;
+ }
+
// Create the dynamic string table section.
Output_section* dynstr = this->choose_output_section(NULL, ".dynstr",
}
odyn->add_string(elfcpp::DT_RPATH, rpath_val);
+ if (parameters->options().enable_new_dtags())
+ odyn->add_string(elfcpp::DT_RUNPATH, rpath_val);
}
// Look for text segments that have dynamic relocations.
if (parameters->options().shared() && this->has_static_tls())
flags |= elfcpp::DF_STATIC_TLS;
odyn->add_constant(elfcpp::DT_FLAGS, flags);
+
+ flags = 0;
+ if (parameters->options().initfirst())
+ flags |= elfcpp::DF_1_INITFIRST;
+ if (parameters->options().interpose())
+ flags |= elfcpp::DF_1_INTERPOSE;
+ if (parameters->options().loadfltr())
+ flags |= elfcpp::DF_1_LOADFLTR;
+ if (parameters->options().nodefaultlib())
+ flags |= elfcpp::DF_1_NODEFLIB;
+ if (parameters->options().nodelete())
+ flags |= elfcpp::DF_1_NODELETE;
+ if (parameters->options().nodlopen())
+ flags |= elfcpp::DF_1_NOOPEN;
+ if (parameters->options().nodump())
+ flags |= elfcpp::DF_1_NODUMP;
+ if (!parameters->options().shared())
+ flags &= ~(elfcpp::DF_1_INITFIRST
+ | elfcpp::DF_1_NODELETE
+ | elfcpp::DF_1_NOOPEN);
+ if (flags)
+ odyn->add_constant(elfcpp::DT_FLAGS_1, flags);
}
// The mapping of .gnu.linkonce section names to real section names.
// want a linkonce signature to block another linkonce signature.
bool
-Layout::add_comdat(const char* signature, bool group)
+Layout::add_comdat(Relobj* object, unsigned int shndx,
+ const std::string& signature, bool group)
{
- std::string sig(signature);
+ Kept_section kept(object, shndx, group);
std::pair<Signatures::iterator, bool> ins(
- this->signatures_.insert(std::make_pair(sig, group)));
+ this->signatures_.insert(std::make_pair(signature, kept)));
if (ins.second)
{
return true;
}
- if (ins.first->second)
+ if (ins.first->second.group_)
{
// We've already seen a real section group with this signature.
return false;
// This is a real section group, and we've already seen a
// linkonce section with this signature. Record that we've seen
// a section group, and don't include this section group.
- ins.first->second = true;
+ ins.first->second.group_ = true;
return false;
}
else
}
}
+// Find the given comdat signature, and return the object and section
+// index of the kept group.
+Relobj*
+Layout::find_kept_object(const std::string& signature,
+ unsigned int* pshndx) const
+{
+ Signatures::const_iterator p = this->signatures_.find(signature);
+ if (p == this->signatures_.end())
+ return NULL;
+ if (pshndx != NULL)
+ *pshndx = p->second.shndx_;
+ return p->second.object_;
+}
+
// Store the allocated sections into the section list.
void
gold_assert(index > 0 && index != -1U);
off_t off = (symtab_section->offset()
+ index * symtab_section->entsize());
- symtab->write_section_symbol(*p, of, off);
+ symtab->write_section_symbol(*p, this->symtab_xindex_, of, off);
}
}
}
gold_assert(index > 0 && index != -1U);
off_t off = (dynsym_section->offset()
+ index * dynsym_section->entsize());
- symtab->write_section_symbol(*p, of, off);
+ symtab->write_section_symbol(*p, this->dynsym_xindex_, of, off);
}
}
Write_symbols_task::run(Workqueue*)
{
this->symtab_->write_globals(this->input_objects_, this->sympool_,
- this->dynpool_, this->of_);
+ this->dynpool_, this->layout_->symtab_xindex(),
+ this->layout_->dynsym_xindex(), this->of_);
}
// Write_after_input_sections_task methods.
const char* group_section_name,
const char* signature,
const elfcpp::Shdr<32, false>& shdr,
- const elfcpp::Elf_Word* contents);
+ elfcpp::Elf_Word flags,
+ std::vector<unsigned int>* shndxes);
#endif
#ifdef HAVE_TARGET_32_BIG
const char* group_section_name,
const char* signature,
const elfcpp::Shdr<32, true>& shdr,
- const elfcpp::Elf_Word* contents);
+ elfcpp::Elf_Word flags,
+ std::vector<unsigned int>* shndxes);
#endif
#ifdef HAVE_TARGET_64_LITTLE
const char* group_section_name,
const char* signature,
const elfcpp::Shdr<64, false>& shdr,
- const elfcpp::Elf_Word* contents);
+ elfcpp::Elf_Word flags,
+ std::vector<unsigned int>* shndxes);
#endif
#ifdef HAVE_TARGET_64_BIG
const char* group_section_name,
const char* signature,
const elfcpp::Shdr<64, true>& shdr,
- const elfcpp::Elf_Word* contents);
+ elfcpp::Elf_Word flags,
+ std::vector<unsigned int>* shndxes);
#endif
#ifdef HAVE_TARGET_32_LITTLE