has_static_tls_(false),
any_postprocessing_sections_(false),
resized_signatures_(false),
+ have_stabstr_section_(false),
incremental_inputs_(NULL)
{
// Make space for more than enough segments for a typical file.
// Initialize structure needed for an incremental build.
if (parameters->options().incremental())
this->incremental_inputs_ = new Incremental_inputs;
+
+ // The section name pool is worth optimizing in all cases, because
+ // it is small, but there are often overlaps due to .rel sections.
+ this->namepool_.set_optimize();
}
// Hash a key we use to look up an output section mapping.
if (output_section_slot != NULL)
{
if (*output_section_slot != NULL)
- return *output_section_slot;
+ {
+ (*output_section_slot)->update_flags_for_input_section(flags);
+ return *output_section_slot;
+ }
// We don't put sections found in the linker script into
// SECTION_NAME_MAP_. That keeps us from getting confused
// Sometimes we compress sections. This is typically done for
// sections that are not part of normal program execution (such as
// .debug_* sections), and where the readers of these sections know
-// how to deal with compressed sections. (To make it easier for them,
-// we will rename the ouput section in such cases from .foo to
-// .foo.zlib.nnnn, where nnnn is the uncompressed size.) This routine
-// doesn't say for certain whether we'll compress -- it depends on
-// commandline options as well -- just whether this section is a
-// candidate for compression.
+// how to deal with compressed sections. This routine doesn't say for
+// certain whether we'll compress -- it depends on commandline options
+// as well -- just whether this section is a candidate for compression.
+// (The Output_compressed_section class decides whether to compress
+// a given section, and picks the name of the compressed section.)
static bool
is_compressible_debug_section(const char* secname)
else
os = new Output_section(name, type, flags);
+ parameters->target().new_output_section(os);
+
this->section_list_.push_back(os);
// The GNU linker by default sorts some sections by priority, so we
}
}
+ // Check for .stab*str sections, as .stab* sections need to link to
+ // them.
+ if (type == elfcpp::SHT_STRTAB
+ && !this->have_stabstr_section_
+ && strncmp(name, ".stab", 5) == 0
+ && strcmp(name + strlen(name) - 3, "str") == 0)
+ this->have_stabstr_section_ = true;
+
// 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.
// In general the only thing we really care about for PT_LOAD
// segments is whether or not they are writable, so that is how we
- // search for them. People who need segments sorted on some other
+ // search for them. Large data sections also go into their own
+ // PT_LOAD segment. People who need segments sorted on some other
// basis will have to use a linker script.
Segment_list::const_iterator p;
p != this->segment_list_.end();
++p)
{
- if ((*p)->type() == elfcpp::PT_LOAD
- && (parameters->options().omagic()
- || ((*p)->flags() & elfcpp::PF_W) == (seg_flags & elfcpp::PF_W)))
- {
- // If -Tbss was specified, we need to separate the data
- // and BSS segments.
- if (parameters->options().user_set_Tbss())
- {
- if ((os->type() == elfcpp::SHT_NOBITS)
- == (*p)->has_any_data_sections())
- continue;
- }
+ if ((*p)->type() != elfcpp::PT_LOAD)
+ continue;
+ if (!parameters->options().omagic()
+ && ((*p)->flags() & elfcpp::PF_W) != (seg_flags & elfcpp::PF_W))
+ continue;
+ // If -Tbss was specified, we need to separate the data and BSS
+ // segments.
+ if (parameters->options().user_set_Tbss())
+ {
+ if ((os->type() == elfcpp::SHT_NOBITS)
+ == (*p)->has_any_data_sections())
+ continue;
+ }
+ if (os->is_large_data_section() && !(*p)->is_large_data_segment())
+ continue;
- (*p)->add_output_section(os, seg_flags);
- break;
- }
+ (*p)->add_output_section(os, seg_flags);
+ break;
}
if (p == this->segment_list_.end())
{
Output_segment* oseg = this->make_output_segment(elfcpp::PT_LOAD,
seg_flags);
+ if (os->is_large_data_section())
+ oseg->set_is_large_data_segment();
oseg->add_output_section(os, seg_flags);
}
}
}
+// Create automatic note sections.
+
+void
+Layout::create_notes()
+{
+ this->create_gold_note();
+ this->create_executable_stack_info();
+ this->create_build_id();
+}
+
// Create the dynamic sections which are needed before we read the
// relocs.
this->count_local_symbols(task, input_objects);
- this->create_gold_note();
- this->create_executable_stack_info(target);
- this->create_build_id();
+ this->link_stabs_sections();
Output_segment* phdr_seg = NULL;
if (!parameters->options().relocatable() && !parameters->doing_static_link())
}
// Create a note header following the format defined in the ELF ABI.
-// NAME is the name, NOTE_TYPE is the type, DESCSZ is the size of the
-// descriptor. ALLOCATE is true if the section should be allocated in
-// memory. This returns the new note section. It sets
-// *TRAILING_PADDING to the number of trailing zero bytes required.
+// NAME is the name, NOTE_TYPE is the type, SECTION_NAME is the name
+// of the section to create, DESCSZ is the size of the descriptor.
+// ALLOCATE is true if the section should be allocated in memory.
+// This returns the new note section. It sets *TRAILING_PADDING to
+// the number of trailing zero bytes required.
Output_section*
Layout::create_note(const char* name, int note_type,
memcpy(buffer + 3 * (size / 8), name, namesz);
- const char *note_name = this->namepool_.add(section_name, false, NULL);
elfcpp::Elf_Xword flags = 0;
if (allocate)
flags = elfcpp::SHF_ALLOC;
- Output_section* os = this->make_output_section(note_name,
- elfcpp::SHT_NOTE,
- flags);
+ Output_section* os = this->choose_output_section(NULL, section_name,
+ elfcpp::SHT_NOTE,
+ flags, false);
+ if (os == NULL)
+ return NULL;
+
Output_section_data* posd = new Output_data_const_buffer(buffer, notehdrsz,
size / 8,
"** note header");
Output_section *os = this->create_note("GNU", elfcpp::NT_GNU_GOLD_VERSION,
".note.gnu.gold-version", desc.size(),
false, &trailing_padding);
+ if (os == NULL)
+ return;
Output_section_data* posd = new Output_data_const(desc, 4);
os->add_output_section_data(posd);
// library, we create a PT_GNU_STACK segment.
void
-Layout::create_executable_stack_info(const Target* target)
+Layout::create_executable_stack_info()
{
bool is_stack_executable;
if (parameters->options().is_execstack_set())
if (this->input_requires_executable_stack_)
is_stack_executable = true;
else if (this->input_without_gnu_stack_note_)
- is_stack_executable = target->is_default_stack_executable();
+ is_stack_executable =
+ parameters->target().is_default_stack_executable();
else
is_stack_executable = false;
}
Output_section* os = this->create_note("GNU", elfcpp::NT_GNU_BUILD_ID,
".note.gnu.build-id", descsz, true,
&trailing_padding);
+ if (os == NULL)
+ return;
if (!desc.empty())
{
gold_assert(trailing_padding == 0);
this->build_id_note_ = new Output_data_zero_fill(descsz, 4);
os->add_output_section_data(this->build_id_note_);
- os->set_after_input_sections();
+ }
+}
+
+// If we have both .stabXX and .stabXXstr sections, then the sh_link
+// field of the former should point to the latter. I'm not sure who
+// started this, but the GNU linker does it, and some tools depend
+// upon it.
+
+void
+Layout::link_stabs_sections()
+{
+ if (!this->have_stabstr_section_)
+ return;
+
+ for (Section_list::iterator p = this->section_list_.begin();
+ p != this->section_list_.end();
+ ++p)
+ {
+ if ((*p)->type() != elfcpp::SHT_STRTAB)
+ continue;
+
+ const char* name = (*p)->name();
+ if (strncmp(name, ".stab", 5) != 0)
+ continue;
+
+ size_t len = strlen(name);
+ if (strcmp(name + len - 3, "str") != 0)
+ continue;
+
+ std::string stab_name(name, len - 3);
+ Output_section* stab_sec;
+ stab_sec = this->find_output_section(stab_name.c_str());
+ if (stab_sec != NULL)
+ stab_sec->set_link_section(*p);
}
}
else if (seg2->are_addresses_set())
return false;
- // We sort PT_LOAD segments based on the flags. Readonly segments
- // come before writable segments. Then writable segments with data
- // come before writable segments without data. Then executable
- // segments come before non-executable segments. Then the unlikely
- // case of a non-readable segment comes before the normal case of a
- // readable segment. If there are multiple segments with the same
- // type and flags, we require that the address be set, and we sort
- // by virtual address and then physical address.
+ // A segment which holds large data comes after a segment which does
+ // not hold large data.
+ if (seg1->is_large_data_segment())
+ {
+ if (!seg2->is_large_data_segment())
+ return false;
+ }
+ else if (seg2->is_large_data_segment())
+ return true;
+
+ // Otherwise, we sort PT_LOAD segments based on the flags. Readonly
+ // segments come before writable segments. Then writable segments
+ // with data come before writable segments without data. Then
+ // executable segments come before non-executable segments. Then
+ // the unlikely case of a non-readable segment comes before the
+ // normal case of a readable segment. If there are multiple
+ // segments with the same type and flags, we require that the
+ // address be set, and we sort by virtual address and then physical
+ // address.
if ((flags1 & elfcpp::PF_W) != (flags2 & elfcpp::PF_W))
return (flags1 & elfcpp::PF_W) == 0;
if ((flags1 & elfcpp::PF_W) != 0
gold_unreachable();
}
+// Increase OFF so that it is congruent to ADDR modulo ABI_PAGESIZE.
+
+static off_t
+align_file_offset(off_t off, uint64_t addr, uint64_t abi_pagesize)
+{
+ 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;
+ return aligned_off;
+}
+
// Set the file offsets of all the segments, and all the sections they
// contain. They have all been created. LOAD_SEG must be be laid out
// first. Return the offset of the data to follow.
&& !parameters->options().omagic())
(*p)->set_minimum_p_align(common_pagesize);
- if (are_addresses_set)
- {
- if (!parameters->options().nmagic()
- && !parameters->options().omagic())
- {
- // 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 (!are_addresses_set)
{
// If the last segment was readonly, and this one is
// not, then skip the address forward one page,
off = orig_off + ((addr - orig_addr) & (abi_pagesize - 1));
}
+ if (!parameters->options().nmagic()
+ && !parameters->options().omagic())
+ off = align_file_offset(off, addr, abi_pagesize);
+
unsigned int shndx_hold = *pshndx;
uint64_t new_addr = (*p)->set_section_addresses(this, false, addr,
&off, pshndx);
addr = align_address(aligned_addr, common_pagesize);
addr = align_address(addr, (*p)->maximum_alignment());
off = orig_off + ((addr - orig_addr) & (abi_pagesize - 1));
+ off = align_file_offset(off, addr, abi_pagesize);
new_addr = (*p)->set_section_addresses(this, true, addr,
&off, pshndx);
}
++p)
{
unsigned int index = (*p)->finalize_local_symbols(local_symbol_index,
- off);
+ off, symtab);
off += (index - local_symbol_index) * symsize;
local_symbol_index = index;
}
flags |= elfcpp::DF_STATIC_TLS;
if (parameters->options().origin())
flags |= elfcpp::DF_ORIGIN;
+ if (parameters->options().now())
+ flags |= elfcpp::DF_BIND_NOW;
odyn->add_constant(elfcpp::DT_FLAGS, flags);
flags = 0;
| elfcpp::DF_1_NOOPEN);
if (parameters->options().origin())
flags |= elfcpp::DF_1_ORIGIN;
+ if (parameters->options().now())
+ flags |= elfcpp::DF_1_NOW;
if (flags)
odyn->add_constant(elfcpp::DT_FLAGS_1, flags);
}
-// The mapping of .gnu.linkonce section names to real section names.
+// The mapping of input section name prefixes to output section names.
+// In some cases one prefix is itself a prefix of another prefix; in
+// such a case the longer prefix must come first. These prefixes are
+// based on the GNU linker default ELF linker script.
#define MAPPING_INIT(f, t) { f, sizeof(f) - 1, t, sizeof(t) - 1 }
-const Layout::Linkonce_mapping Layout::linkonce_mapping[] =
-{
- MAPPING_INIT("d.rel.ro.local", ".data.rel.ro.local"), // Before "d.rel.ro".
- MAPPING_INIT("d.rel.ro", ".data.rel.ro"), // Before "d".
- MAPPING_INIT("t", ".text"),
- MAPPING_INIT("r", ".rodata"),
- MAPPING_INIT("d", ".data"),
- MAPPING_INIT("b", ".bss"),
- MAPPING_INIT("s", ".sdata"),
- MAPPING_INIT("sb", ".sbss"),
- MAPPING_INIT("s2", ".sdata2"),
- MAPPING_INIT("sb2", ".sbss2"),
- MAPPING_INIT("wi", ".debug_info"),
- MAPPING_INIT("td", ".tdata"),
- MAPPING_INIT("tb", ".tbss"),
- MAPPING_INIT("lr", ".lrodata"),
- MAPPING_INIT("l", ".ldata"),
- MAPPING_INIT("lb", ".lbss"),
+const Layout::Section_name_mapping Layout::section_name_mapping[] =
+{
+ MAPPING_INIT(".text.", ".text"),
+ MAPPING_INIT(".ctors.", ".ctors"),
+ MAPPING_INIT(".dtors.", ".dtors"),
+ MAPPING_INIT(".rodata.", ".rodata"),
+ MAPPING_INIT(".data.rel.ro.local", ".data.rel.ro.local"),
+ MAPPING_INIT(".data.rel.ro", ".data.rel.ro"),
+ MAPPING_INIT(".data.", ".data"),
+ MAPPING_INIT(".bss.", ".bss"),
+ MAPPING_INIT(".tdata.", ".tdata"),
+ MAPPING_INIT(".tbss.", ".tbss"),
+ MAPPING_INIT(".init_array.", ".init_array"),
+ MAPPING_INIT(".fini_array.", ".fini_array"),
+ MAPPING_INIT(".sdata.", ".sdata"),
+ MAPPING_INIT(".sbss.", ".sbss"),
+ // FIXME: In the GNU linker, .sbss2 and .sdata2 are handled
+ // differently depending on whether it is creating a shared library.
+ MAPPING_INIT(".sdata2.", ".sdata"),
+ MAPPING_INIT(".sbss2.", ".sbss"),
+ MAPPING_INIT(".lrodata.", ".lrodata"),
+ MAPPING_INIT(".ldata.", ".ldata"),
+ MAPPING_INIT(".lbss.", ".lbss"),
+ MAPPING_INIT(".gcc_except_table.", ".gcc_except_table"),
+ MAPPING_INIT(".gnu.linkonce.d.rel.ro.local.", ".data.rel.ro.local"),
+ MAPPING_INIT(".gnu.linkonce.d.rel.ro.", ".data.rel.ro"),
+ MAPPING_INIT(".gnu.linkonce.t.", ".text"),
+ MAPPING_INIT(".gnu.linkonce.r.", ".rodata"),
+ MAPPING_INIT(".gnu.linkonce.d.", ".data"),
+ MAPPING_INIT(".gnu.linkonce.b.", ".bss"),
+ MAPPING_INIT(".gnu.linkonce.s.", ".sdata"),
+ MAPPING_INIT(".gnu.linkonce.sb.", ".sbss"),
+ MAPPING_INIT(".gnu.linkonce.s2.", ".sdata"),
+ MAPPING_INIT(".gnu.linkonce.sb2.", ".sbss"),
+ MAPPING_INIT(".gnu.linkonce.wi.", ".debug_info"),
+ MAPPING_INIT(".gnu.linkonce.td.", ".tdata"),
+ MAPPING_INIT(".gnu.linkonce.tb.", ".tbss"),
+ MAPPING_INIT(".gnu.linkonce.lr.", ".lrodata"),
+ MAPPING_INIT(".gnu.linkonce.l.", ".ldata"),
+ MAPPING_INIT(".gnu.linkonce.lb.", ".lbss"),
+ MAPPING_INIT(".ARM.extab.", ".ARM.extab"),
+ MAPPING_INIT(".gnu.linkonce.armextab.", ".ARM.extab"),
+ MAPPING_INIT(".ARM.exidx.", ".ARM.exidx"),
+ MAPPING_INIT(".gnu.linkonce.armexidx.", ".ARM.exidx"),
};
#undef MAPPING_INIT
-const int Layout::linkonce_mapping_count =
- sizeof(Layout::linkonce_mapping) / sizeof(Layout::linkonce_mapping[0]);
-
-// Return the name of the output section to use for a .gnu.linkonce
-// section. This is based on the default ELF linker script of the old
-// GNU linker. For example, we map a name like ".gnu.linkonce.t.foo"
-// to ".text". Set *PLEN to the length of the name. *PLEN is
-// initialized to the length of NAME.
-
-const char*
-Layout::linkonce_output_name(const char* name, size_t *plen)
-{
- const char* s = name + sizeof(".gnu.linkonce") - 1;
- if (*s != '.')
- return name;
- ++s;
- const Linkonce_mapping* plm = linkonce_mapping;
- for (int i = 0; i < linkonce_mapping_count; ++i, ++plm)
- {
- if (strncmp(s, plm->from, plm->fromlen) == 0 && s[plm->fromlen] == '.')
- {
- *plen = plm->tolen;
- return plm->to;
- }
- }
- return name;
-}
+const int Layout::section_name_mapping_count =
+ (sizeof(Layout::section_name_mapping)
+ / sizeof(Layout::section_name_mapping[0]));
// Choose the output section name to use given an input section name.
// Set *PLEN to the length of the name. *PLEN is initialized to the
const char*
Layout::output_section_name(const char* name, size_t* plen)
{
- if (Layout::is_linkonce(name))
- {
- // .gnu.linkonce sections are laid out as though they were named
- // for the sections are placed into.
- return Layout::linkonce_output_name(name, plen);
- }
-
// gcc 4.3 generates the following sorts of section names when it
// needs a section name specific to a function:
// .text.FN
// Also of interest: .rodata.strN.N, .rodata.cstN, both of which the
// GNU linker maps to .rodata.
- // The .data.rel.ro sections enable a security feature triggered by
- // the -z relro option. Section which need to be relocated at
- // program startup time but which may be readonly after startup are
- // grouped into .data.rel.ro. They are then put into a PT_GNU_RELRO
- // segment. The dynamic linker will make that segment writable,
- // perform relocations, and then make it read-only. FIXME: We do
- // not yet implement this optimization.
-
- // It is hard to handle this in a principled way.
-
- // These are the rules we follow:
-
- // If the section name has no initial '.', or no dot other than an
- // initial '.', we use the name unchanged (i.e., "mysection" and
- // ".text" are unchanged).
-
- // If the name starts with '.note', we keep it unchanged (e.g. to
- // avoid truncating '.note.ABI-tag' to '.note').
-
- // If the name starts with ".data.rel.ro.local" we use
- // ".data.rel.ro.local".
+ // The .data.rel.ro sections are used with -z relro. The sections
+ // are recognized by name. We use the same names that the GNU
+ // linker does for these sections.
- // If the name starts with ".data.rel.ro" we use ".data.rel.ro".
+ // It is hard to handle this in a principled way, so we don't even
+ // try. We use a table of mappings. If the input section name is
+ // not found in the table, we simply use it as the output section
+ // name.
- // Otherwise, we drop the second '.' and everything that comes after
- // it (i.e., ".text.XXX" becomes ".text").
-
- const char* s = name;
- if (*s != '.')
- return name;
- ++s;
- const char* sdot = strchr(s, '.');
- if (sdot == NULL)
- return name;
- if (strncmp(name, ".note.", 6) == 0)
- return name;
-
- const char* const data_rel_ro_local = ".data.rel.ro.local";
- if (strncmp(name, data_rel_ro_local, strlen(data_rel_ro_local)) == 0)
- {
- *plen = strlen(data_rel_ro_local);
- return data_rel_ro_local;
- }
-
- const char* const data_rel_ro = ".data.rel.ro";
- if (strncmp(name, data_rel_ro, strlen(data_rel_ro)) == 0)
+ const Section_name_mapping* psnm = section_name_mapping;
+ for (int i = 0; i < section_name_mapping_count; ++i, ++psnm)
{
- *plen = strlen(data_rel_ro);
- return data_rel_ro;
+ if (strncmp(name, psnm->from, psnm->fromlen) == 0)
+ {
+ *plen = psnm->tolen;
+ return psnm->to;
+ }
}
- *plen = sdot - name;
return name;
}
// Check if a comdat group or .gnu.linkonce section with the given
// NAME is selected for the link. If there is already a section,
-// *KEPT_SECTION is set to point to the signature and the function
-// returns false. Otherwise, the CANDIDATE signature is recorded for
-// this NAME in the layout object, *KEPT_SECTION is set to the
-// internal copy and the function return false. In some cases, with
-// CANDIDATE->GROUP_ being false, KEPT_SECTION can point back to
-// CANDIDATE.
+// *KEPT_SECTION is set to point to the existing section and the
+// function returns false. Otherwise, OBJECT, SHNDX, IS_COMDAT, and
+// IS_GROUP_NAME are recorded for this NAME in the layout object,
+// *KEPT_SECTION is set to the internal copy and the function returns
+// true.
bool
Layout::find_or_add_kept_section(const std::string& name,
- Kept_section* candidate,
+ Relobj* object,
+ unsigned int shndx,
+ bool is_comdat,
+ bool is_group_name,
Kept_section** kept_section)
{
// It's normal to see a couple of entries here, for the x86 thunk
this->resized_signatures_ = true;
}
- std::pair<Signatures::iterator, bool> ins(
- this->signatures_.insert(std::make_pair(name, *candidate)));
+ Kept_section candidate;
+ std::pair<Signatures::iterator, bool> ins =
+ this->signatures_.insert(std::make_pair(name, candidate));
- if (kept_section)
+ if (kept_section != NULL)
*kept_section = &ins.first->second;
if (ins.second)
{
// This is the first time we've seen this signature.
+ ins.first->second.set_object(object);
+ ins.first->second.set_shndx(shndx);
+ if (is_comdat)
+ ins.first->second.set_is_comdat();
+ if (is_group_name)
+ ins.first->second.set_is_group_name();
return true;
}
- if (ins.first->second.is_group)
+ // We have already seen this signature.
+
+ if (ins.first->second.is_group_name())
{
// We've already seen a real section group with this signature.
- // If the kept group is from a plugin object, and we're in
- // the replacement phase, accept the new one as a replacement.
- if (ins.first->second.object == NULL
+ // If the kept group is from a plugin object, and we're in the
+ // replacement phase, accept the new one as a replacement.
+ if (ins.first->second.object() == NULL
&& parameters->options().plugins()->in_replacement_phase())
{
- ins.first->second = *candidate;
+ ins.first->second.set_object(object);
+ ins.first->second.set_shndx(shndx);
return true;
}
return false;
}
- else if (candidate->is_group)
+ else if (is_group_name)
{
// 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.is_group = true;
+ ins.first->second.set_is_group_name();
return false;
}
else
// We've already seen a linkonce section and this is a linkonce
// section. These don't block each other--this may be the same
// symbol name with different section types.
- *kept_section = candidate;
return true;
}
}
-// 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