// layout.cc -- lay out output file sections for gold
-// Copyright (C) 2006-2019 Free Software Foundation, Inc.
+// Copyright (C) 2006-2021 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
typename elfcpp::Elf_types<size>::Elf_Addr sh_addr = shdr.get_sh_addr();
typename elfcpp::Elf_types<size>::Elf_Off sh_offset = shdr.get_sh_offset();
typename elfcpp::Elf_types<size>::Elf_WXword sh_size = shdr.get_sh_size();
- typename elfcpp::Elf_types<size>::Elf_WXword sh_flags = shdr.get_sh_flags();
+ typename elfcpp::Elf_types<size>::Elf_WXword sh_flags =
+ this->get_output_section_flags(shdr.get_sh_flags());
typename elfcpp::Elf_types<size>::Elf_WXword sh_addralign =
shdr.get_sh_addralign();
".text.unlikely",
".text.exit",
".text.startup",
- ".text.hot"
+ ".text.hot",
+ ".text.sorted"
};
for (size_t i = 0;
{
// Some flags in the input section should not be automatically
// copied to the output section.
- elfcpp::Elf_Xword flags = (shdr.get_sh_flags()
- & ~ elfcpp::SHF_COMPRESSED);
+ elfcpp::Elf_Xword sh_flags = (shdr.get_sh_flags()
+ & ~ elfcpp::SHF_COMPRESSED);
name = this->namepool_.add(name, true, NULL);
- os = this->make_output_section(name, sh_type, flags,
- ORDER_INVALID, false);
+ os = this->make_output_section(name, sh_type, sh_flags, ORDER_INVALID,
+ false);
}
else
{
+ // Get the section flags and mask out any flags that do not
+ // take part in section matching.
+ elfcpp::Elf_Xword sh_flags
+ = (this->get_output_section_flags(shdr.get_sh_flags())
+ & ~object->osabi().ignored_sh_flags());
+
// 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()));
+ = (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());
-
+ {
Stringpool::Key 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,
+ os = this->get_output_section(os_name, name_key, sh_type, sh_flags,
ORDER_INVALID, false);
- // 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.
+ // 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
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);
+ 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);
+ os = this->get_output_section(os_name, name_key, sh_type,
+ sh_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);
- }
+ {
+ os->set_is_unique_segment();
+ os->set_extra_segment_flags(it->second->flags);
+ os->set_segment_alignment(it->second->align);
+ }
}
}
if (os == NULL)
// segment.
if (os->type() == elfcpp::SHT_NOTE)
{
+ uint64_t os_align = os->addralign();
+
// See if we already have an equivalent PT_NOTE segment.
for (p = this->segment_list_.begin();
p != segment_list_.end();
++p)
{
if ((*p)->type() == elfcpp::PT_NOTE
+ && (*p)->align() == os_align
&& (((*p)->flags() & elfcpp::PF_W)
== (seg_flags & elfcpp::PF_W)))
{
Output_segment* oseg = this->make_output_segment(elfcpp::PT_NOTE,
seg_flags);
oseg->add_output_section_to_nonload(os, seg_flags);
+ oseg->set_align(os_align);
}
}
const int size = parameters->target().get_size();
const bool is_big_endian = parameters->target().is_big_endian();
if (size == 32)
- {
- if (is_big_endian)
- {
+ {
+ if (is_big_endian)
+ {
#ifdef HAVE_TARGET_32_BIG
parameters->sized_target<32, true>()->
record_gnu_property(note_type, pr_type, pr_datasz, pr_data,
#else
gold_unreachable();
#endif
- }
- else
- {
+ }
+ else
+ {
#ifdef HAVE_TARGET_32_LITTLE
parameters->sized_target<32, false>()->
record_gnu_property(note_type, pr_type, pr_datasz, pr_data,
#else
gold_unreachable();
#endif
- }
- }
+ }
+ }
else if (size == 64)
- {
- if (is_big_endian)
- {
+ {
+ if (is_big_endian)
+ {
#ifdef HAVE_TARGET_64_BIG
parameters->sized_target<64, true>()->
record_gnu_property(note_type, pr_type, pr_datasz, pr_data,
#else
gold_unreachable();
#endif
- }
- else
- {
+ }
+ else
+ {
#ifdef HAVE_TARGET_64_LITTLE
parameters->sized_target<64, false>()->
record_gnu_property(note_type, pr_type, pr_datasz, pr_data,
#else
gold_unreachable();
#endif
- }
- }
+ }
+ }
else
- gold_unreachable();
+ gold_unreachable();
return;
}
void
Layout::define_section_symbols(Symbol_table* symtab)
{
+ const elfcpp::STV visibility = parameters->options().start_stop_visibility_enum();
for (Section_list::const_iterator p = this->section_list_.begin();
p != this->section_list_.end();
++p)
0, // symsize
elfcpp::STT_NOTYPE,
elfcpp::STB_GLOBAL,
- elfcpp::STV_PROTECTED,
+ visibility,
0, // nonvis
false, // offset_is_from_end
true); // only_if_ref
0, // symsize
elfcpp::STT_NOTYPE,
elfcpp::STB_GLOBAL,
- elfcpp::STV_PROTECTED,
+ visibility,
0, // nonvis
true, // offset_is_from_end
true); // only_if_ref
gold_fatal(_("unable to open --section-ordering-file file %s: %s"),
filename, strerror(errno));
+ File_read::record_file_read(filename);
+
std::getline(in, line); // this chops off the trailing \n, if any
unsigned int position = 1;
this->set_section_ordering_specified();
#else
const int size = 32;
#endif
+ // The NT_GNU_PROPERTY_TYPE_0 note is aligned to the pointer size.
+ const int addralign = ((note_type == elfcpp::NT_GNU_PROPERTY_TYPE_0
+ ? parameters->target().get_size()
+ : size) / 8);
// The contents of the .note section.
size_t namesz = strlen(name) + 1;
return NULL;
Output_section_data* posd = new Output_data_const_buffer(buffer, notehdrsz,
- size / 8,
+ addralign,
"** note header");
os->add_output_section_data(posd);
write_sized_value(datasz, 4, p + 4, is_big_endian);
memcpy(p + 8, prop->second.pr_data, datasz);
if (aligned_datasz > datasz)
- memset(p + 8 + datasz, 0, aligned_datasz - datasz);
+ memset(p + 8 + datasz, 0, aligned_datasz - datasz);
p += 8 + aligned_datasz;
}
Output_section_data* posd = new Output_data_const(desc, descsz, 4);
{
if (type1 != type2)
return type1 < type2;
+ uint64_t align1 = seg1->align();
+ uint64_t align2 = seg2->align();
+ // Place segments with larger alignments first.
+ if (align1 != align2)
+ return align1 > align2;
gold_assert(flags1 != flags2
|| this->script_options_->saw_phdrs_clause());
return flags1 < flags2;
flags |= elfcpp::DF_1_NOW;
if (parameters->options().Bgroup())
flags |= elfcpp::DF_1_GROUP;
+ if (parameters->options().pie())
+ flags |= elfcpp::DF_1_PIE;
if (flags != 0)
odyn->add_constant(elfcpp::DT_FLAGS_1, flags);
+
+ flags = 0;
+ if (parameters->options().unique())
+ flags |= elfcpp::DF_GNU_1_UNIQUE;
+ if (flags != 0)
+ odyn->add_constant(elfcpp::DT_GNU_FLAGS_1, flags);
}
// Set the size of the _DYNAMIC symbol table to be the size of the
if (this->options_->oformat_enum() != General_options::OBJECT_FORMAT_ELF)
this->layout_->write_binary(this->of_);
+ if (this->options_->dependency_file())
+ File_read::write_dependency_file(this->options_->dependency_file(),
+ this->options_->output_file_name());
+
this->of_->close();
}