// layout.cc -- lay out output file sections for gold
-// Copyright (C) 2006-2017 Free Software Foundation, Inc.
+// Copyright (C) 2006-2018 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
Output_section*
Layout::layout(Sized_relobj_file<size, big_endian>* object, unsigned int shndx,
const char* name, const elfcpp::Shdr<size, big_endian>& shdr,
- unsigned int reloc_shndx, unsigned int, off_t* off)
+ unsigned int sh_type, unsigned int reloc_shndx,
+ unsigned int, off_t* off)
{
*off = 0;
if (!this->include_section(object, name, shdr))
return NULL;
- elfcpp::Elf_Word sh_type = shdr.get_sh_type();
-
// In a relocatable link a grouped section must not be combined with
// any other sections.
Output_section* os;
}
else
{
- // Plugins can choose to place one or more subsets of sections in
- // unique segments and this is done by mapping these section subsets
- // to unique output sections. Check if this section needs to be
- // remapped to a unique output section.
- Section_segment_map::iterator it
- = this->section_segment_map_.find(Const_section_id(object, shndx));
- if (it == this->section_segment_map_.end())
- {
- os = this->choose_output_section(object, name, sh_type,
- shdr.get_sh_flags(), true,
- ORDER_INVALID, false, false,
- true);
- }
- else
- {
- // We know the name of the output section, directly call
- // get_output_section here by-passing choose_output_section.
+ // All ".text.unlikely.*" sections can be moved to a unique
+ // segment with --text-unlikely-segment option.
+ bool text_unlikely_segment
+ = (parameters->options().text_unlikely_segment()
+ && is_prefix_of(".text.unlikely",
+ object->section_name(shndx).c_str()));
+ if (text_unlikely_segment)
+ {
elfcpp::Elf_Xword flags
= this->get_output_section_flags(shdr.get_sh_flags());
- const char* os_name = it->second->name;
Stringpool::Key name_key;
- os_name = this->namepool_.add(os_name, true, &name_key);
+ const char* os_name = this->namepool_.add(".text.unlikely", true,
+ &name_key);
os = this->get_output_section(os_name, name_key, sh_type, flags,
ORDER_INVALID, false);
- if (!os->is_unique_segment())
+ // Map this output section to a unique segment. This is done to
+ // separate "text" that is not likely to be executed from "text"
+ // that is likely executed.
+ os->set_is_unique_segment();
+ }
+ else
+ {
+ // Plugins can choose to place one or more subsets of sections in
+ // unique segments and this is done by mapping these section subsets
+ // to unique output sections. Check if this section needs to be
+ // remapped to a unique output section.
+ Section_segment_map::iterator it
+ = this->section_segment_map_.find(Const_section_id(object, shndx));
+ if (it == this->section_segment_map_.end())
{
- os->set_is_unique_segment();
- os->set_extra_segment_flags(it->second->flags);
- os->set_segment_alignment(it->second->align);
+ os = this->choose_output_section(object, name, sh_type,
+ shdr.get_sh_flags(), true,
+ ORDER_INVALID, false, false,
+ true);
}
- }
+ else
+ {
+ // We know the name of the output section, directly call
+ // get_output_section here by-passing choose_output_section.
+ elfcpp::Elf_Xword flags
+ = this->get_output_section_flags(shdr.get_sh_flags());
+
+ const char* os_name = it->second->name;
+ Stringpool::Key name_key;
+ os_name = this->namepool_.add(os_name, true, &name_key);
+ os = this->get_output_section(os_name, name_key, sh_type, flags,
+ ORDER_INVALID, false);
+ if (!os->is_unique_segment())
+ {
+ os->set_is_unique_segment();
+ os->set_extra_segment_flags(it->second->flags);
+ os->set_segment_alignment(it->second->align);
+ }
+ }
+ }
if (os == NULL)
return NULL;
}
template<int size, bool big_endian>
Output_section*
-Layout::layout_reloc(Sized_relobj_file<size, big_endian>* object,
+Layout::layout_reloc(Sized_relobj_file<size, big_endian>*,
unsigned int,
const elfcpp::Shdr<size, big_endian>& shdr,
Output_section* data_section,
gold_unreachable();
name += data_section->name();
- // In a relocatable link relocs for a grouped section must not be
- // combined with other reloc sections.
- Output_section* os;
- if (!parameters->options().relocatable()
- || (data_section->flags() & elfcpp::SHF_GROUP) == 0)
- os = this->choose_output_section(object, name.c_str(), sh_type,
- shdr.get_sh_flags(), false,
- ORDER_INVALID, false, true, false);
- else
+ // If the output data section already has a reloc section, use that;
+ // otherwise, make a new one.
+ Output_section* os = data_section->reloc_section();
+ if (os == NULL)
{
const char* n = this->namepool_.add(name.c_str(), true, NULL);
os = this->make_output_section(n, sh_type, shdr.get_sh_flags(),
ORDER_INVALID, false);
+ os->set_should_link_to_symtab();
+ os->set_info_section(data_section);
+ data_section->set_reloc_section(os);
}
- os->set_should_link_to_symtab();
- os->set_info_section(data_section);
-
Output_section_data* posd;
if (sh_type == elfcpp::SHT_REL)
{
unsigned int reloc_shndx, unsigned int reloc_type,
off_t* off)
{
+ const unsigned int unwind_section_type =
+ parameters->target().unwind_section_type();
+
gold_assert(shdr.get_sh_type() == elfcpp::SHT_PROGBITS
- || shdr.get_sh_type() == elfcpp::SHT_X86_64_UNWIND);
+ || shdr.get_sh_type() == unwind_section_type);
gold_assert((shdr.get_sh_flags() & elfcpp::SHF_ALLOC) != 0);
Output_section* os = this->make_eh_frame_section(object);
Output_section*
Layout::make_eh_frame_section(const Relobj* object)
{
- // FIXME: On x86_64, this could use SHT_X86_64_UNWIND rather than
- // SHT_PROGBITS.
+ const unsigned int unwind_section_type =
+ parameters->target().unwind_section_type();
+
Output_section* os = this->choose_output_section(object, ".eh_frame",
- elfcpp::SHT_PROGBITS,
+ unwind_section_type,
elfcpp::SHF_ALLOC, false,
ORDER_EHFRAME, false, false,
false);
{
Output_section* hdr_os =
this->choose_output_section(NULL, ".eh_frame_hdr",
- elfcpp::SHT_PROGBITS,
+ unwind_section_type,
elfcpp::SHF_ALLOC, false,
ORDER_EHFRAME, false, false,
false);
}
}
+// Remove .eh_frame information for a PLT. FDEs using the CIE must
+// be removed in reverse order to the order they were added.
+
+void
+Layout::remove_eh_frame_for_plt(Output_data* plt, const unsigned char* cie_data,
+ size_t cie_length, const unsigned char* fde_data,
+ size_t fde_length)
+{
+ if (parameters->incremental())
+ {
+ // FIXME: Maybe this could work some day....
+ return;
+ }
+ this->eh_frame_data_->remove_ehframe_for_plt(plt, cie_data, cie_length,
+ fde_data, fde_length);
+}
+
// Scan a .debug_info or .debug_types section, and add summary
// information to the .gdb_index section.
return ORDER_INIT;
else if (strcmp(os->name(), ".fini") == 0)
return ORDER_FINI;
+ else if (parameters->options().keep_text_section_prefix())
+ {
+ // -z,keep-text-section-prefix introduces additional
+ // output sections.
+ if (strcmp(os->name(), ".text.hot") == 0)
+ return ORDER_TEXT_HOT;
+ else if (strcmp(os->name(), ".text.startup") == 0)
+ return ORDER_TEXT_STARTUP;
+ else if (strcmp(os->name(), ".text.exit") == 0)
+ return ORDER_TEXT_EXIT;
+ else if (strcmp(os->name(), ".text.unlikely") == 0)
+ return ORDER_TEXT_UNLIKELY;
+ }
}
return is_execinstr ? ORDER_TEXT : ORDER_READONLY;
}
0, // symsize
elfcpp::STT_NOTYPE,
elfcpp::STB_GLOBAL,
- elfcpp::STV_DEFAULT,
+ elfcpp::STV_PROTECTED,
0, // nonvis
false, // offset_is_from_end
true); // only_if_ref
0, // symsize
elfcpp::STT_NOTYPE,
elfcpp::STB_GLOBAL,
- elfcpp::STV_DEFAULT,
+ elfcpp::STV_PROTECTED,
0, // nonvis
true, // offset_is_from_end
true); // only_if_ref
Layout::segment_precedes(const Output_segment* seg1,
const Output_segment* seg2)
{
+ // In order to produce a stable ordering if we're called with the same pointer
+ // return false.
+ if (seg1 == seg2)
+ return false;
+
elfcpp::Elf_Word type1 = seg1->type();
elfcpp::Elf_Word type2 = seg2->type();
// here if plugins want unique segments for subsets of sections.
gold_assert(this->script_options_->saw_phdrs_clause()
|| parameters->options().any_section_start()
- || this->is_unique_segment_for_sections_specified());
+ || this->is_unique_segment_for_sections_specified()
+ || parameters->options().text_unlikely_segment());
return false;
}
}
// 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
+// contain. They have all been created. LOAD_SEG must be laid out
// first. Return the offset of the data to follow.
off_t
MAPPING_INIT(".ARM.exidx", ".ARM.exidx"),
MAPPING_INIT(".gnu.linkonce.armexidx.", ".ARM.exidx"),
};
+
+// Mapping for ".text" section prefixes with -z,keep-text-section-prefix.
+const Layout::Section_name_mapping Layout::text_section_name_mapping[] =
+{
+ MAPPING_INIT(".text.hot.", ".text.hot"),
+ MAPPING_INIT_EXACT(".text.hot", ".text.hot"),
+ MAPPING_INIT(".text.unlikely.", ".text.unlikely"),
+ MAPPING_INIT_EXACT(".text.unlikely", ".text.unlikely"),
+ MAPPING_INIT(".text.startup.", ".text.startup"),
+ MAPPING_INIT_EXACT(".text.startup", ".text.startup"),
+ MAPPING_INIT(".text.exit.", ".text.exit"),
+ MAPPING_INIT_EXACT(".text.exit", ".text.exit"),
+ MAPPING_INIT(".text.", ".text"),
+};
#undef MAPPING_INIT
#undef MAPPING_INIT_EXACT
(sizeof(Layout::section_name_mapping)
/ sizeof(Layout::section_name_mapping[0]));
+const int Layout::text_section_name_mapping_count =
+ (sizeof(Layout::text_section_name_mapping)
+ / sizeof(Layout::text_section_name_mapping[0]));
+
+// Find section name NAME in PSNM and return the mapped name if found
+// with the length set in PLEN.
+const char *
+Layout::match_section_name(const Layout::Section_name_mapping* psnm,
+ const int count,
+ const char* name, size_t* plen)
+{
+ for (int i = 0; i < count; ++i, ++psnm)
+ {
+ if (psnm->fromlen > 0)
+ {
+ if (strncmp(name, psnm->from, psnm->fromlen) == 0)
+ {
+ *plen = psnm->tolen;
+ return psnm->to;
+ }
+ }
+ else
+ {
+ if (strcmp(name, psnm->from) == 0)
+ {
+ *plen = psnm->tolen;
+ return psnm->to;
+ }
+ }
+ }
+ return NULL;
+}
+
// 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
// length of NAME.
// not found in the table, we simply use it as the output section
// name.
- const Section_name_mapping* psnm = section_name_mapping;
- for (int i = 0; i < section_name_mapping_count; ++i, ++psnm)
+ if (parameters->options().keep_text_section_prefix()
+ && is_prefix_of(".text", name))
{
- if (psnm->fromlen > 0)
- {
- if (strncmp(name, psnm->from, psnm->fromlen) == 0)
- {
- *plen = psnm->tolen;
- return psnm->to;
- }
- }
- else
- {
- if (strcmp(name, psnm->from) == 0)
- {
- *plen = psnm->tolen;
- return psnm->to;
- }
- }
+ const char* match = match_section_name(text_section_name_mapping,
+ text_section_name_mapping_count,
+ name, plen);
+ if (match != NULL)
+ return match;
}
+ const char* match = match_section_name(section_name_mapping,
+ section_name_mapping_count, name, plen);
+ if (match != NULL)
+ return match;
+
// As an additional complication, .ctors sections are output in
// either .ctors or .init_array sections, and .dtors sections are
// output in either .dtors or .fini_array sections.
unsigned int shndx,
const char* name,
const elfcpp::Shdr<32, false>& shdr,
- unsigned int, unsigned int, off_t*);
+ unsigned int, unsigned int, unsigned int, off_t*);
#endif
#ifdef HAVE_TARGET_32_BIG
unsigned int shndx,
const char* name,
const elfcpp::Shdr<32, true>& shdr,
- unsigned int, unsigned int, off_t*);
+ unsigned int, unsigned int, unsigned int, off_t*);
#endif
#ifdef HAVE_TARGET_64_LITTLE
unsigned int shndx,
const char* name,
const elfcpp::Shdr<64, false>& shdr,
- unsigned int, unsigned int, off_t*);
+ unsigned int, unsigned int, unsigned int, off_t*);
#endif
#ifdef HAVE_TARGET_64_BIG
unsigned int shndx,
const char* name,
const elfcpp::Shdr<64, true>& shdr,
- unsigned int, unsigned int, off_t*);
+ unsigned int, unsigned int, unsigned int, off_t*);
#endif
#ifdef HAVE_TARGET_32_LITTLE