#include "parameters.h"
#include "options.h"
+#include "script.h"
+#include "script-sections.h"
#include "output.h"
#include "symtab.h"
#include "dynobj.h"
#include "ehframe.h"
#include "compressed_output.h"
+#include "reloc.h"
#include "layout.h"
namespace gold
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), output_file_size_(-1),
+ eh_frame_section_(NULL), group_signatures_(), output_file_size_(-1),
input_requires_executable_stack_(false),
input_with_gnu_stack_note_(false),
input_without_gnu_stack_note_(false),
Layout::include_section(Sized_relobj<size, big_endian>*, const char* name,
const elfcpp::Shdr<size, big_endian>& shdr)
{
- // Some section types are never linked. Some are only linked when
- // doing a relocateable link.
switch (shdr.get_sh_type())
{
case elfcpp::SHT_NULL:
case elfcpp::SHT_RELA:
case elfcpp::SHT_REL:
case elfcpp::SHT_GROUP:
- return parameters->output_is_object();
+ // For a relocatable link these should be handled elsewhere.
+ gold_assert(!parameters->output_is_object());
+ return false;
case elfcpp::SHT_PROGBITS:
if (parameters->strip_debug()
Output_section*
Layout::find_output_section(const char* name) const
{
- for (Section_name_map::const_iterator p = this->section_name_map_.begin();
- p != this->section_name_map_.end();
+ for (Section_list::const_iterator p = this->section_list_.begin();
+ p != this->section_list_.end();
++p)
- if (strcmp(p->second->name(), name) == 0)
- return p->second;
+ if (strcmp((*p)->name(), name) == 0)
+ return *p;
return NULL;
}
}
// Return the output section to use for section NAME with type TYPE
-// and section flags FLAGS.
+// and section flags FLAGS. NAME must be canonicalized in the string
+// pool, and NAME_KEY is the key.
Output_section*
Layout::get_output_section(const char* name, Stringpool::Key name_key,
elfcpp::Elf_Word type, elfcpp::Elf_Xword flags)
{
- // We should ignore some flags.
- flags &= ~ (elfcpp::SHF_INFO_LINK
- | elfcpp::SHF_LINK_ORDER
- | elfcpp::SHF_GROUP
- | elfcpp::SHF_MERGE
- | elfcpp::SHF_STRINGS);
-
const Key key(name_key, std::make_pair(type, flags));
const std::pair<Key, Output_section*> v(key, NULL);
std::pair<Section_name_map::iterator, bool> ins(
}
}
+// 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.
+
+Output_section*
+Layout::choose_output_section(const Relobj* relobj, const char* name,
+ elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
+ bool adjust_name)
+{
+ // We should ignore some flags. FIXME: This will need some
+ // adjustment for ld -r.
+ flags &= ~ (elfcpp::SHF_INFO_LINK
+ | elfcpp::SHF_LINK_ORDER
+ | elfcpp::SHF_GROUP
+ | elfcpp::SHF_MERGE
+ | elfcpp::SHF_STRINGS);
+
+ if (this->script_options_->saw_sections_clause())
+ {
+ // We are using a SECTIONS clause, so the output section is
+ // chosen based only on the name.
+
+ Script_sections* ss = this->script_options_->script_sections();
+ const char* file_name = relobj == NULL ? NULL : relobj->name().c_str();
+ Output_section** output_section_slot;
+ name = ss->output_section_name(file_name, name, &output_section_slot);
+ if (name == NULL)
+ {
+ // The SECTIONS clause says to discard this input section.
+ return NULL;
+ }
+
+ // If this is an orphan section--one not mentioned in the linker
+ // script--then OUTPUT_SECTION_SLOT will be NULL, and we do the
+ // default processing below.
+
+ if (output_section_slot != NULL)
+ {
+ if (*output_section_slot != NULL)
+ return *output_section_slot;
+
+ // We don't put sections found in the linker script into
+ // SECTION_NAME_MAP_. That keeps us from getting confused
+ // if an orphan section is mapped to a section with the same
+ // name as one in the linker script.
+
+ name = this->namepool_.add(name, false, NULL);
+
+ Output_section* os = this->make_output_section(name, type, flags);
+ os->set_found_in_sections_clause();
+ *output_section_slot = os;
+ return os;
+ }
+ }
+
+ // FIXME: Handle SHF_OS_NONCONFORMING somewhere.
+
+ // Turn NAME from the name of the input section into the name of the
+ // output section.
+
+ size_t len = strlen(name);
+ if (adjust_name && !parameters->output_is_object())
+ name = Layout::output_section_name(name, &len);
+
+ Stringpool::Key name_key;
+ name = this->namepool_.add_with_length(name, len, true, &name_key);
+
+ // Find or make the output section. The output section is selected
+ // based on the section name, type, and flags.
+ return this->get_output_section(name, name_key, type, flags);
+}
+
// Return the output section to use for input section SHNDX, with name
// NAME, with header HEADER, from object OBJECT. RELOC_SHNDX is the
// index of a relocation section which applies to this section, or 0
if (!this->include_section(object, name, shdr))
return NULL;
- // If we are not doing a relocateable link, choose the name to use
- // for the output section.
- size_t len = strlen(name);
- if (!parameters->output_is_object())
- name = Layout::output_section_name(name, &len);
+ Output_section* os;
- // FIXME: Handle SHF_OS_NONCONFORMING here.
+ // In a relocatable link a grouped section must not be combined with
+ // any other sections.
+ if (parameters->output_is_object()
+ && (shdr.get_sh_flags() & elfcpp::SHF_GROUP) != 0)
+ {
+ name = this->namepool_.add(name, true, NULL);
+ os = this->make_output_section(name, shdr.get_sh_type(),
+ shdr.get_sh_flags());
+ }
+ else
+ {
+ os = this->choose_output_section(object, name, shdr.get_sh_type(),
+ shdr.get_sh_flags(), true);
+ if (os == NULL)
+ return NULL;
+ }
- // Canonicalize the section name.
- Stringpool::Key name_key;
- name = this->namepool_.add_with_length(name, len, true, &name_key);
+ // FIXME: Handle SHF_LINK_ORDER somewhere.
- // Find the output section. The output section is selected based on
- // the section name, type, and flags.
- Output_section* os = this->get_output_section(name, name_key,
- shdr.get_sh_type(),
- shdr.get_sh_flags());
+ *off = os->add_input_section(object, shndx, name, shdr, reloc_shndx,
+ this->script_options_->saw_sections_clause());
- // FIXME: Handle SHF_LINK_ORDER somewhere.
+ return os;
+}
+
+// Handle a relocation section when doing a relocatable link.
+
+template<int size, bool big_endian>
+Output_section*
+Layout::layout_reloc(Sized_relobj<size, big_endian>* object,
+ unsigned int,
+ const elfcpp::Shdr<size, big_endian>& shdr,
+ Output_section* data_section,
+ Relocatable_relocs* rr)
+{
+ gold_assert(parameters->output_is_object());
+
+ int sh_type = shdr.get_sh_type();
+
+ std::string name;
+ if (sh_type == elfcpp::SHT_REL)
+ name = ".rel";
+ else if (sh_type == elfcpp::SHT_RELA)
+ name = ".rela";
+ else
+ gold_unreachable();
+ name += data_section->name();
+
+ Output_section* os = this->choose_output_section(object, name.c_str(),
+ sh_type,
+ shdr.get_sh_flags(),
+ false);
- *off = os->add_input_section(object, shndx, name, shdr, reloc_shndx);
+ os->set_should_link_to_symtab();
+ os->set_info_section(data_section);
+
+ Output_section_data* posd;
+ if (sh_type == elfcpp::SHT_REL)
+ {
+ os->set_entsize(elfcpp::Elf_sizes<size>::rel_size);
+ posd = new Output_relocatable_relocs<elfcpp::SHT_REL,
+ size,
+ big_endian>(rr);
+ }
+ else if (sh_type == elfcpp::SHT_RELA)
+ {
+ os->set_entsize(elfcpp::Elf_sizes<size>::rela_size);
+ posd = new Output_relocatable_relocs<elfcpp::SHT_RELA,
+ size,
+ big_endian>(rr);
+ }
+ else
+ gold_unreachable();
+
+ os->add_output_section_data(posd);
+ rr->set_output_data(posd);
return os;
}
+// Handle a group section when doing a relocatable link.
+
+template<int size, bool big_endian>
+void
+Layout::layout_group(Symbol_table* symtab,
+ Sized_relobj<size, big_endian>* object,
+ unsigned int,
+ const char* group_section_name,
+ const char* signature,
+ const elfcpp::Shdr<size, big_endian>& shdr,
+ const elfcpp::Elf_Word* contents)
+{
+ gold_assert(parameters->output_is_object());
+ gold_assert(shdr.get_sh_type() == elfcpp::SHT_GROUP);
+ group_section_name = this->namepool_.add(group_section_name, true, NULL);
+ Output_section* os = this->make_output_section(group_section_name,
+ elfcpp::SHT_GROUP,
+ shdr.get_sh_flags());
+
+ // We need to find a symbol with the signature in the symbol table.
+ // If we don't find one now, we need to look again later.
+ Symbol* sym = symtab->lookup(signature, NULL);
+ if (sym != NULL)
+ os->set_info_symndx(sym);
+ else
+ {
+ // We will wind up using a symbol whose name is the signature.
+ // So just put the signature in the symbol name pool to save it.
+ signature = symtab->canonicalize_name(signature);
+ this->group_signatures_.push_back(Group_signature(os, signature));
+ }
+
+ os->set_should_link_to_symtab();
+ os->set_entsize(4);
+
+ 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);
+ os->add_output_section_data(posd);
+}
+
// Special GNU handling of sections name .eh_frame. They will
// normally hold exception frame data as defined by the C++ ABI
// (http://codesourcery.com/cxx-abi/).
gold_assert(shdr.get_sh_type() == elfcpp::SHT_PROGBITS);
gold_assert(shdr.get_sh_flags() == elfcpp::SHF_ALLOC);
- Stringpool::Key name_key;
- const char* name = this->namepool_.add(".eh_frame", false, &name_key);
-
- Output_section* os = this->get_output_section(name, name_key,
- elfcpp::SHT_PROGBITS,
- elfcpp::SHF_ALLOC);
+ const char* const name = ".eh_frame";
+ Output_section* os = this->choose_output_section(object,
+ name,
+ elfcpp::SHT_PROGBITS,
+ elfcpp::SHF_ALLOC,
+ false);
+ if (os == NULL)
+ return NULL;
if (this->eh_frame_section_ == NULL)
{
if (this->options_.create_eh_frame_hdr())
{
- Stringpool::Key hdr_name_key;
- const char* hdr_name = this->namepool_.add(".eh_frame_hdr",
- false,
- &hdr_name_key);
Output_section* hdr_os =
- this->get_output_section(hdr_name, hdr_name_key,
- elfcpp::SHT_PROGBITS,
- elfcpp::SHF_ALLOC);
+ this->choose_output_section(NULL,
+ ".eh_frame_hdr",
+ elfcpp::SHT_PROGBITS,
+ elfcpp::SHF_ALLOC,
+ false);
- Eh_frame_hdr* hdr_posd = new Eh_frame_hdr(os, this->eh_frame_data_);
- hdr_os->add_output_section_data(hdr_posd);
+ if (hdr_os != NULL)
+ {
+ Eh_frame_hdr* hdr_posd = new Eh_frame_hdr(os,
+ this->eh_frame_data_);
+ hdr_os->add_output_section_data(hdr_posd);
- hdr_os->set_after_input_sections();
+ hdr_os->set_after_input_sections();
- Output_segment* hdr_oseg =
- new Output_segment(elfcpp::PT_GNU_EH_FRAME, elfcpp::PF_R);
- this->segment_list_.push_back(hdr_oseg);
- hdr_oseg->add_output_section(hdr_os, elfcpp::PF_R);
+ if (!this->script_options_->saw_phdrs_clause())
+ {
+ Output_segment* hdr_oseg;
+ hdr_oseg = this->make_output_segment(elfcpp::PT_GNU_EH_FRAME,
+ elfcpp::PF_R);
+ hdr_oseg->add_output_section(hdr_os, elfcpp::PF_R);
+ }
- this->eh_frame_data_->set_eh_frame_hdr(hdr_posd);
+ this->eh_frame_data_->set_eh_frame_hdr(hdr_posd);
+ }
}
}
{
// We couldn't handle this .eh_frame section for some reason.
// Add it as a normal section.
- *off = os->add_input_section(object, shndx, name, shdr, reloc_shndx);
+ bool saw_sections_clause = this->script_options_->saw_sections_clause();
+ *off = os->add_input_section(object, shndx, name, shdr, reloc_shndx,
+ saw_sections_clause);
}
return os;
elfcpp::Elf_Xword flags,
Output_section_data* posd)
{
- // Canonicalize the name.
- Stringpool::Key name_key;
- name = this->namepool_.add(name, true, &name_key);
-
- Output_section* os = this->get_output_section(name, name_key, type, flags);
- os->add_output_section_data(posd);
+ Output_section* os = this->choose_output_section(NULL, name, type, flags,
+ false);
+ if (os != NULL)
+ os->add_output_section_data(posd);
}
// Map section flags to segment flags.
this->unattached_section_list_.push_back(os);
else
{
+ if (parameters->output_is_object())
+ return os;
+
+ // If we have a SECTIONS clause, we can't handle the attachment
+ // to segments until after we've seen all the sections.
+ if (this->script_options_->saw_sections_clause())
+ return os;
+
+ gold_assert(!this->script_options_->saw_phdrs_clause());
+
// This output section goes into a PT_LOAD segment.
elfcpp::Elf_Word seg_flags = Layout::section_flags_to_segment(flags);
if (p == this->segment_list_.end())
{
- Output_segment* oseg = new Output_segment(elfcpp::PT_LOAD,
- seg_flags);
- this->segment_list_.push_back(oseg);
+ Output_segment* oseg = this->make_output_segment(elfcpp::PT_LOAD,
+ seg_flags);
oseg->add_output_section(os, seg_flags);
}
if (p == this->segment_list_.end())
{
- Output_segment* oseg = new Output_segment(elfcpp::PT_NOTE,
- seg_flags);
- this->segment_list_.push_back(oseg);
+ Output_segment* oseg = this->make_output_segment(elfcpp::PT_NOTE,
+ seg_flags);
oseg->add_output_section(os, seg_flags);
}
}
if ((flags & elfcpp::SHF_TLS) != 0)
{
if (this->tls_segment_ == NULL)
- {
- this->tls_segment_ = new Output_segment(elfcpp::PT_TLS,
- seg_flags);
- this->segment_list_.push_back(this->tls_segment_);
- }
+ this->tls_segment_ = this->make_output_segment(elfcpp::PT_TLS,
+ seg_flags);
this->tls_segment_->add_output_section(os, seg_flags);
}
}
return os;
}
+// Return the number of segments we expect to see.
+
+size_t
+Layout::expected_segment_count() const
+{
+ size_t ret = this->segment_list_.size();
+
+ // If we didn't see a SECTIONS clause in a linker script, we should
+ // already have the complete list of segments. Otherwise we ask the
+ // SECTIONS clause how many segments it expects, and add in the ones
+ // we already have (PT_GNU_STACK, PT_GNU_EH_FRAME, etc.)
+
+ if (!this->script_options_->saw_sections_clause())
+ return ret;
+ else
+ {
+ const Script_sections* ss = this->script_options_->script_sections();
+ return ret + ss->expected_segment_count(this);
+ }
+}
+
// Handle the .note.GNU-stack section at layout time. SEEN_GNU_STACK
// is whether we saw a .note.GNU-stack section in the object file.
// GNU_STACK_FLAGS is the section flags. The flags give the
// relocs.
void
-Layout::create_initial_dynamic_sections(const Input_objects* input_objects,
- Symbol_table* symtab)
+Layout::create_initial_dynamic_sections(Symbol_table* symtab)
{
if (parameters->doing_static_link())
return;
- const char* dynamic_name = this->namepool_.add(".dynamic", false, NULL);
- this->dynamic_section_ = this->make_output_section(dynamic_name,
- elfcpp::SHT_DYNAMIC,
- (elfcpp::SHF_ALLOC
- | elfcpp::SHF_WRITE));
+ this->dynamic_section_ = this->choose_output_section(NULL, ".dynamic",
+ elfcpp::SHT_DYNAMIC,
+ (elfcpp::SHF_ALLOC
+ | elfcpp::SHF_WRITE),
+ false);
- symtab->define_in_output_data(input_objects->target(), "_DYNAMIC", NULL,
- this->dynamic_section_, 0, 0,
+ symtab->define_in_output_data("_DYNAMIC", NULL, this->dynamic_section_, 0, 0,
elfcpp::STT_OBJECT, elfcpp::STB_LOCAL,
elfcpp::STV_HIDDEN, 0, false, false);
// extension.
void
-Layout::define_section_symbols(Symbol_table* symtab, const Target* target)
+Layout::define_section_symbols(Symbol_table* symtab)
{
for (Section_list::const_iterator p = this->section_list_.begin();
p != this->section_list_.end();
const std::string start_name("__start_" + name_string);
const std::string stop_name("__stop_" + name_string);
- symtab->define_in_output_data(target,
- start_name.c_str(),
+ symtab->define_in_output_data(start_name.c_str(),
NULL, // version
*p,
0, // value
elfcpp::STV_DEFAULT,
0, // nonvis
false, // offset_is_from_end
- false); // only_if_ref
+ true); // only_if_ref
- symtab->define_in_output_data(target,
- stop_name.c_str(),
+ symtab->define_in_output_data(stop_name.c_str(),
NULL, // version
*p,
0, // value
elfcpp::STV_DEFAULT,
0, // nonvis
true, // offset_is_from_end
- false); // only_if_ref
+ true); // only_if_ref
}
}
}
+// Define symbols for group signatures.
+
+void
+Layout::define_group_signatures(Symbol_table* symtab)
+{
+ for (Group_signatures::iterator p = this->group_signatures_.begin();
+ p != this->group_signatures_.end();
+ ++p)
+ {
+ Symbol* sym = symtab->lookup(p->signature, NULL);
+ if (sym != NULL)
+ p->section->set_info_symndx(sym);
+ else
+ {
+ // Force the name of the group section to the group
+ // signature, and use the group's section symbol as the
+ // signature symbol.
+ if (strcmp(p->section->name(), p->signature) != 0)
+ {
+ const char* name = this->namepool_.add(p->signature,
+ true, NULL);
+ p->section->set_name(name);
+ }
+ p->section->set_needs_symtab_index();
+ p->section->set_info_section_symndx(p->section);
+ }
+ }
+
+ this->group_signatures_.clear();
+}
+
// Find the first read-only PT_LOAD segment, creating one if
// necessary.
return *p;
}
- Output_segment* load_seg = new Output_segment(elfcpp::PT_LOAD, elfcpp::PF_R);
- this->segment_list_.push_back(load_seg);
+ gold_assert(!this->script_options_->saw_phdrs_clause());
+
+ Output_segment* load_seg = this->make_output_segment(elfcpp::PT_LOAD,
+ elfcpp::PF_R);
return load_seg;
}
this->create_executable_stack_info(target);
Output_segment* phdr_seg = NULL;
- if (!parameters->doing_static_link())
+ if (!parameters->output_is_object() && !parameters->doing_static_link())
{
// There was a dynamic object in the link. We need to create
// some information for the dynamic linker.
// Create the PT_PHDR segment which will hold the program
// headers.
- phdr_seg = new Output_segment(elfcpp::PT_PHDR, elfcpp::PF_R);
- this->segment_list_.push_back(phdr_seg);
+ if (!this->script_options_->saw_phdrs_clause())
+ phdr_seg = this->make_output_segment(elfcpp::PT_PHDR, elfcpp::PF_R);
// Create the dynamic symbol table, including the hash table.
Output_section* dynstr;
std::vector<Symbol*> dynamic_symbols;
unsigned int local_dynamic_count;
Versions versions(this->options_, &this->dynpool_);
- this->create_dynamic_symtab(input_objects, target, symtab, &dynstr,
+ this->create_dynamic_symtab(input_objects, symtab, &dynstr,
&local_dynamic_count, &dynamic_symbols,
&versions);
dynamic_symbols, dynstr);
}
- // FIXME: Handle PT_GNU_STACK.
+ // If there is a SECTIONS clause, put all the input sections into
+ // the required order.
+ Output_segment* load_seg;
+ if (parameters->output_is_object())
+ load_seg = NULL;
+ else if (this->script_options_->saw_sections_clause())
+ load_seg = this->set_section_addresses_from_script(symtab);
+ else
+ load_seg = this->find_first_load_seg();
- Output_segment* load_seg = this->find_first_load_seg();
+ gold_assert(phdr_seg == NULL || load_seg != NULL);
// Lay out the segment headers.
Output_segment_headers* segment_headers;
- segment_headers = new Output_segment_headers(this->segment_list_);
- load_seg->add_initial_output_data(segment_headers);
- this->special_output_list_.push_back(segment_headers);
- if (phdr_seg != NULL)
- phdr_seg->add_initial_output_data(segment_headers);
+ if (parameters->output_is_object())
+ segment_headers = NULL;
+ else
+ {
+ segment_headers = new Output_segment_headers(this->segment_list_);
+ if (load_seg != NULL)
+ load_seg->add_initial_output_data(segment_headers);
+ if (phdr_seg != NULL)
+ phdr_seg->add_initial_output_data(segment_headers);
+ }
// Lay out the file header.
Output_file_header* file_header;
file_header = new Output_file_header(target, symtab, segment_headers,
this->script_options_->entry());
- load_seg->add_initial_output_data(file_header);
+ if (load_seg != NULL)
+ load_seg->add_initial_output_data(file_header);
+
this->special_output_list_.push_back(file_header);
+ if (segment_headers != NULL)
+ this->special_output_list_.push_back(segment_headers);
+
+ if (this->script_options_->saw_phdrs_clause()
+ && !parameters->output_is_object())
+ {
+ // Support use of FILEHDRS and PHDRS attachments in a PHDRS
+ // clause in a linker script.
+ Script_sections* ss = this->script_options_->script_sections();
+ ss->put_headers_in_phdrs(file_header, segment_headers);
+ }
// We set the output section indexes in set_segment_offsets and
// set_section_indexes.
// Set the file offsets of all the segments, and all the sections
// they contain.
- off_t off = this->set_segment_offsets(target, load_seg, &shndx);
+ off_t off;
+ if (!parameters->output_is_object())
+ off = this->set_segment_offsets(target, load_seg, &shndx);
+ else
+ off = this->set_relocatable_section_offsets(file_header, &shndx);
// Set the file offsets of all the non-data sections we've seen so
// far which don't have to wait for the input sections. We need
}
else
{
+ if (this->script_options_->saw_phdrs_clause())
+ return;
int flags = elfcpp::PF_R | elfcpp::PF_W;
if (is_stack_executable)
flags |= elfcpp::PF_X;
- Output_segment* oseg = new Output_segment(elfcpp::PT_GNU_STACK, flags);
- this->segment_list_.push_back(oseg);
+ this->make_output_segment(elfcpp::PT_GNU_STACK, flags);
}
}
return flags1 < flags2;
}
+ // If the addresses are set already, sort by load address.
+ if (seg1->are_addresses_set())
+ {
+ if (!seg2->are_addresses_set())
+ return true;
+
+ unsigned int section_count1 = seg1->output_section_count();
+ unsigned int section_count2 = seg2->output_section_count();
+ if (section_count1 == 0 && section_count2 > 0)
+ return true;
+ if (section_count1 > 0 && section_count2 == 0)
+ return false;
+
+ uint64_t paddr1 = seg1->first_section_load_address();
+ uint64_t paddr2 = seg2->first_section_load_address();
+ if (paddr1 != paddr2)
+ return paddr1 < paddr2;
+ }
+ else if (seg2->are_addresses_set())
+ return false;
+
// We sort PT_LOAD segments based on the flags. Readonly segments
// come before writable segments. Then executable segments come
// before non-executable segments. Then the unlikely case of a
if ((flags1 & elfcpp::PF_R) != (flags2 & elfcpp::PF_R))
return (flags1 & elfcpp::PF_R) == 0;
- uint64_t vaddr1 = seg1->vaddr();
- uint64_t vaddr2 = seg2->vaddr();
- if (vaddr1 != vaddr2)
- return vaddr1 < vaddr2;
-
- uint64_t paddr1 = seg1->paddr();
- uint64_t paddr2 = seg2->paddr();
- gold_assert(paddr1 != paddr2);
- return paddr1 < paddr2;
+ // We shouldn't get here--we shouldn't create segments which we
+ // can't distinguish.
+ gold_unreachable();
}
// Set the file offsets of all the segments, and all the sections they
// Find the PT_LOAD segments, and set their addresses and offsets
// and their section's addresses and offsets.
uint64_t addr;
- if (parameters->output_is_shared())
- addr = 0;
- else if (options_.user_set_text_segment_address())
+ if (this->options_.user_set_text_segment_address())
addr = options_.text_segment_address();
+ else if (parameters->output_is_shared())
+ addr = 0;
else
addr = target->default_text_segment_address();
off_t off = 0;
+
+ // If LOAD_SEG is NULL, then the file header and segment headers
+ // will not be loadable. But they still need to be at offset 0 in
+ // the file. Set their offsets now.
+ if (load_seg == NULL)
+ {
+ for (Data_list::iterator p = this->special_output_list_.begin();
+ p != this->special_output_list_.end();
+ ++p)
+ {
+ off = align_address(off, (*p)->addralign());
+ (*p)->set_address_and_file_offset(0, off);
+ off += (*p)->data_size();
+ }
+ }
+
bool was_readonly = false;
for (Segment_list::iterator p = this->segment_list_.begin();
p != this->segment_list_.end();
gold_unreachable();
load_seg = NULL;
- // If the last segment was readonly, and this one is not,
- // then skip the address forward one page, maintaining the
- // same position within the page. This lets us store both
- // segments overlapping on a single page in the file, but
- // the loader will put them on different pages in memory.
-
uint64_t orig_addr = addr;
uint64_t orig_off = off;
- uint64_t aligned_addr = addr;
+ uint64_t aligned_addr = 0;
uint64_t abi_pagesize = target->abi_pagesize();
- // FIXME: This should depend on the -n and -N options.
- (*p)->set_minimum_addralign(target->common_pagesize());
+ // FIXME: This should depend on the -n and -N options.
+ (*p)->set_minimum_p_align(target->common_pagesize());
- if (was_readonly && ((*p)->flags() & elfcpp::PF_W) != 0)
+ bool are_addresses_set = (*p)->are_addresses_set();
+ if (are_addresses_set)
{
- uint64_t align = (*p)->addralign();
-
- addr = align_address(addr, align);
+ // When it comes to setting file offsets, we care about
+ // the physical address.
+ addr = (*p)->paddr();
+
+ // Adjust the file offset to the same address modulo the
+ // page size.
+ uint64_t unsigned_off = off;
+ uint64_t aligned_off = ((unsigned_off & ~(abi_pagesize - 1))
+ | (addr & (abi_pagesize - 1)));
+ if (aligned_off < unsigned_off)
+ aligned_off += abi_pagesize;
+ off = aligned_off;
+ }
+ else
+ {
+ // If the last segment was readonly, and this one is
+ // not, then skip the address forward one page,
+ // maintaining the same position within the page. This
+ // lets us store both segments overlapping on a single
+ // page in the file, but the loader will put them on
+ // different pages in memory.
+
+ addr = align_address(addr, (*p)->maximum_alignment());
aligned_addr = addr;
- if ((addr & (abi_pagesize - 1)) != 0)
- addr = addr + abi_pagesize;
+
+ if (was_readonly && ((*p)->flags() & elfcpp::PF_W) != 0)
+ {
+ if ((addr & (abi_pagesize - 1)) != 0)
+ addr = addr + abi_pagesize;
+ }
+
+ off = orig_off + ((addr - orig_addr) & (abi_pagesize - 1));
}
unsigned int shndx_hold = *pshndx;
- off = orig_off + ((addr - orig_addr) & (abi_pagesize - 1));
- uint64_t new_addr = (*p)->set_section_addresses(addr, &off, pshndx);
+ uint64_t new_addr = (*p)->set_section_addresses(false, addr, &off,
+ pshndx);
// Now that we know the size of this segment, we may be able
// to save a page in memory, at the cost of wasting some
// page. Here we use the real machine page size rather than
// the ABI mandated page size.
- if (aligned_addr != addr)
+ if (!are_addresses_set && aligned_addr != addr)
{
uint64_t common_pagesize = target->common_pagesize();
uint64_t first_off = (common_pagesize
{
*pshndx = shndx_hold;
addr = align_address(aligned_addr, common_pagesize);
+ addr = align_address(addr, (*p)->maximum_alignment());
off = orig_off + ((addr - orig_addr) & (abi_pagesize - 1));
- new_addr = (*p)->set_section_addresses(addr, &off, pshndx);
+ new_addr = (*p)->set_section_addresses(true, addr, &off,
+ pshndx);
}
}
return off;
}
+// Set the offsets of all the allocated sections when doing a
+// relocatable link. This does the same jobs as set_segment_offsets,
+// only for a relocatable link.
+
+off_t
+Layout::set_relocatable_section_offsets(Output_data* file_header,
+ unsigned int *pshndx)
+{
+ off_t off = 0;
+
+ file_header->set_address_and_file_offset(0, 0);
+ off += file_header->data_size();
+
+ for (Section_list::iterator p = this->section_list_.begin();
+ p != this->section_list_.end();
+ ++p)
+ {
+ // We skip unallocated sections here, except that group sections
+ // have to come first.
+ if (((*p)->flags() & elfcpp::SHF_ALLOC) == 0
+ && (*p)->type() != elfcpp::SHT_GROUP)
+ continue;
+
+ off = align_address(off, (*p)->addralign());
+
+ // The linker script might have set the address.
+ if (!(*p)->is_address_valid())
+ (*p)->set_address(0);
+ (*p)->set_file_offset(off);
+ (*p)->finalize_data_size();
+ off += (*p)->data_size();
+
+ (*p)->set_out_shndx(*pshndx);
+ ++*pshndx;
+ }
+
+ return off;
+}
+
// Set the file offset of all the sections not associated with a
// segment.
unsigned int
Layout::set_section_indexes(unsigned int shndx)
{
+ const bool output_is_object = parameters->output_is_object();
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;
}
return shndx;
}
+// Set the section addresses according to the linker script. This is
+// only called when we see a SECTIONS clause. This returns the
+// program segment which should hold the file header and segment
+// headers, if any. It will return NULL if they should not be in a
+// segment.
+
+Output_segment*
+Layout::set_section_addresses_from_script(Symbol_table* symtab)
+{
+ Script_sections* ss = this->script_options_->script_sections();
+ gold_assert(ss->saw_sections_clause());
+
+ // Place each orphaned output section in the script.
+ for (Section_list::iterator p = this->section_list_.begin();
+ p != this->section_list_.end();
+ ++p)
+ {
+ if (!(*p)->found_in_sections_clause())
+ ss->place_orphan(*p);
+ }
+
+ return this->script_options_->set_section_addresses(symtab, this);
+}
+
// Count the local symbols in the regular symbol table and the dynamic
// symbol table, and build the respective string pools.
Output_section_headers* oshdrs;
oshdrs = new Output_section_headers(this,
&this->segment_list_,
+ &this->section_list_,
&this->unattached_section_list_,
&this->namepool_);
off_t off = align_address(*poff, oshdrs->addralign());
void
Layout::create_dynamic_symtab(const Input_objects* input_objects,
- const Target* target, Symbol_table* symtab,
+ Symbol_table* symtab,
Output_section **pdynstr,
unsigned int* plocal_dynamic_count,
std::vector<Symbol*>* pdynamic_symbols,
// FIXME: We have to tell set_dynsym_indexes whether the
// -E/--export-dynamic option was used.
- index = symtab->set_dynsym_indexes(target, index, pdynamic_symbols,
+ index = symtab->set_dynsym_indexes(index, pdynamic_symbols,
&this->dynpool_, pversions);
int symsize;
// Create the dynamic symbol table section.
- const char* dynsym_name = this->namepool_.add(".dynsym", false, NULL);
- Output_section* dynsym = this->make_output_section(dynsym_name,
- elfcpp::SHT_DYNSYM,
- elfcpp::SHF_ALLOC);
+ Output_section* dynsym = this->choose_output_section(NULL, ".dynsym",
+ elfcpp::SHT_DYNSYM,
+ elfcpp::SHF_ALLOC,
+ false);
Output_section_data* odata = new Output_data_fixed_space(index * symsize,
align);
// Create the dynamic string table section.
- const char* dynstr_name = this->namepool_.add(".dynstr", false, NULL);
- Output_section* dynstr = this->make_output_section(dynstr_name,
- elfcpp::SHT_STRTAB,
- elfcpp::SHF_ALLOC);
+ Output_section* dynstr = this->choose_output_section(NULL, ".dynstr",
+ elfcpp::SHT_STRTAB,
+ elfcpp::SHF_ALLOC,
+ false);
Output_section_data* strdata = new Output_data_strtab(&this->dynpool_);
dynstr->add_output_section_data(strdata);
Dynobj::create_elf_hash_table(*pdynamic_symbols, local_symcount,
&phash, &hashlen);
- const char* hash_name = this->namepool_.add(".hash", false, NULL);
- Output_section* hashsec = this->make_output_section(hash_name,
- elfcpp::SHT_HASH,
- elfcpp::SHF_ALLOC);
+ Output_section* hashsec = this->choose_output_section(NULL, ".hash",
+ elfcpp::SHT_HASH,
+ elfcpp::SHF_ALLOC,
+ false);
Output_section_data* hashdata = new Output_data_const_buffer(phash,
hashlen,
const Output_section* dynstr
ACCEPT_SIZE_ENDIAN)
{
- const char* vname = this->namepool_.add(".gnu.version", false, NULL);
- Output_section* vsec = this->make_output_section(vname,
- elfcpp::SHT_GNU_versym,
- elfcpp::SHF_ALLOC);
+ Output_section* vsec = this->choose_output_section(NULL, ".gnu.version",
+ elfcpp::SHT_GNU_versym,
+ elfcpp::SHF_ALLOC,
+ false);
unsigned char* vbuf;
unsigned int vsize;
if (versions->any_defs())
{
- const char* vdname = this->namepool_.add(".gnu.version_d", false, NULL);
- Output_section *vdsec;
- vdsec = this->make_output_section(vdname, elfcpp::SHT_GNU_verdef,
- elfcpp::SHF_ALLOC);
+ Output_section* vdsec;
+ vdsec= this->choose_output_section(NULL, ".gnu.version_d",
+ elfcpp::SHT_GNU_verdef,
+ elfcpp::SHF_ALLOC,
+ false);
unsigned char* vdbuf;
unsigned int vdsize;
if (versions->any_needs())
{
- const char* vnname = this->namepool_.add(".gnu.version_r", false, NULL);
Output_section* vnsec;
- vnsec = this->make_output_section(vnname, elfcpp::SHT_GNU_verneed,
- elfcpp::SHF_ALLOC);
+ vnsec = this->choose_output_section(NULL, ".gnu.version_r",
+ elfcpp::SHT_GNU_verneed,
+ elfcpp::SHF_ALLOC,
+ false);
unsigned char* vnbuf;
unsigned int vnsize;
Output_section_data* odata = new Output_data_const(interp, len, 1);
- const char* interp_name = this->namepool_.add(".interp", false, NULL);
- Output_section* osec = this->make_output_section(interp_name,
- elfcpp::SHT_PROGBITS,
- elfcpp::SHF_ALLOC);
+ Output_section* osec = this->choose_output_section(NULL, ".interp",
+ elfcpp::SHT_PROGBITS,
+ elfcpp::SHF_ALLOC,
+ false);
osec->add_output_section_data(odata);
- Output_segment* oseg = new Output_segment(elfcpp::PT_INTERP, elfcpp::PF_R);
- this->segment_list_.push_back(oseg);
- oseg->add_initial_output_section(osec, elfcpp::PF_R);
+ if (!this->script_options_->saw_phdrs_clause())
+ {
+ Output_segment* oseg = this->make_output_segment(elfcpp::PT_INTERP,
+ elfcpp::PF_R);
+ oseg->add_initial_output_section(osec, elfcpp::PF_R);
+ }
}
// Finish the .dynamic section and PT_DYNAMIC segment.
Layout::finish_dynamic_section(const Input_objects* input_objects,
const Symbol_table* symtab)
{
- Output_segment* oseg = new Output_segment(elfcpp::PT_DYNAMIC,
- elfcpp::PF_R | elfcpp::PF_W);
- this->segment_list_.push_back(oseg);
- oseg->add_initial_output_section(this->dynamic_section_,
- elfcpp::PF_R | elfcpp::PF_W);
+ if (!this->script_options_->saw_phdrs_clause())
+ {
+ Output_segment* oseg = this->make_output_segment(elfcpp::PT_DYNAMIC,
+ (elfcpp::PF_R
+ | elfcpp::PF_W));
+ oseg->add_initial_output_section(this->dynamic_section_,
+ elfcpp::PF_R | elfcpp::PF_W);
+ }
Output_data_dynamic* const odyn = this->dynamic_data_;
}
}
+// Store the allocated sections into the section list.
+
+void
+Layout::get_allocated_sections(Section_list* section_list) const
+{
+ for (Section_list::const_iterator p = this->section_list_.begin();
+ p != this->section_list_.end();
+ ++p)
+ if (((*p)->flags() & elfcpp::SHF_ALLOC) != 0)
+ section_list->push_back(*p);
+}
+
+// Create an output segment.
+
+Output_segment*
+Layout::make_output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags)
+{
+ gold_assert(!parameters->output_is_object());
+ Output_segment* oseg = new Output_segment(type, flags);
+ this->segment_list_.push_back(oseg);
+ return oseg;
+}
+
// Write out the Output_sections. Most won't have anything to write,
// since most of the data will come from input sections which are
// handled elsewhere. But some Output_sections do have Output_data.
unsigned int, unsigned int, off_t*);
#endif
+#ifdef HAVE_TARGET_32_LITTLE
+template
+Output_section*
+Layout::layout_reloc<32, false>(Sized_relobj<32, false>* object,
+ unsigned int reloc_shndx,
+ const elfcpp::Shdr<32, false>& shdr,
+ Output_section* data_section,
+ Relocatable_relocs* rr);
+#endif
+
+#ifdef HAVE_TARGET_32_BIG
+template
+Output_section*
+Layout::layout_reloc<32, true>(Sized_relobj<32, true>* object,
+ unsigned int reloc_shndx,
+ const elfcpp::Shdr<32, true>& shdr,
+ Output_section* data_section,
+ Relocatable_relocs* rr);
+#endif
+
+#ifdef HAVE_TARGET_64_LITTLE
+template
+Output_section*
+Layout::layout_reloc<64, false>(Sized_relobj<64, false>* object,
+ unsigned int reloc_shndx,
+ const elfcpp::Shdr<64, false>& shdr,
+ Output_section* data_section,
+ Relocatable_relocs* rr);
+#endif
+
+#ifdef HAVE_TARGET_64_BIG
+template
+Output_section*
+Layout::layout_reloc<64, true>(Sized_relobj<64, true>* object,
+ unsigned int reloc_shndx,
+ const elfcpp::Shdr<64, true>& shdr,
+ Output_section* data_section,
+ Relocatable_relocs* rr);
+#endif
+
+#ifdef HAVE_TARGET_32_LITTLE
+template
+void
+Layout::layout_group<32, false>(Symbol_table* symtab,
+ Sized_relobj<32, false>* object,
+ unsigned int,
+ const char* group_section_name,
+ const char* signature,
+ const elfcpp::Shdr<32, false>& shdr,
+ const elfcpp::Elf_Word* contents);
+#endif
+
+#ifdef HAVE_TARGET_32_BIG
+template
+void
+Layout::layout_group<32, true>(Symbol_table* symtab,
+ Sized_relobj<32, true>* object,
+ unsigned int,
+ const char* group_section_name,
+ const char* signature,
+ const elfcpp::Shdr<32, true>& shdr,
+ const elfcpp::Elf_Word* contents);
+#endif
+
+#ifdef HAVE_TARGET_64_LITTLE
+template
+void
+Layout::layout_group<64, false>(Symbol_table* symtab,
+ Sized_relobj<64, false>* object,
+ unsigned int,
+ const char* group_section_name,
+ const char* signature,
+ const elfcpp::Shdr<64, false>& shdr,
+ const elfcpp::Elf_Word* contents);
+#endif
+
+#ifdef HAVE_TARGET_64_BIG
+template
+void
+Layout::layout_group<64, true>(Symbol_table* symtab,
+ Sized_relobj<64, true>* object,
+ unsigned int,
+ const char* group_section_name,
+ const char* signature,
+ const elfcpp::Shdr<64, true>& shdr,
+ const elfcpp::Elf_Word* contents);
+#endif
+
#ifdef HAVE_TARGET_32_LITTLE
template
Output_section*