is_dynamic_linker_section parameters. Change all callers.
(Layout::choose_output_section): Likewise.
(Layout::make_output_section): Likewise.
(Layout::add_output_section_data): Add is_dynamic_linker_section
parameter. Change all callers.
* layout.h (class Layout): Update declarations.
* output.h (class Output_section): Add is_interp, set_is_interp,
is_dynamic_linker_section, set_is_dynamic_linker_section methods.
Add is_interp_, is_dynamic_linker_section_ fields. Change
generate_code_fills_at_write_ to a bitfield.
* output.cc (Output_section::Output_sections): Initialize new
fields.
(Output_segment::add_output_section): Add do_sort parameter.
Change all callers.
+2009-11-04 Ian Lance Taylor <iant@google.com>
+
+ * layout.cc (Layout::get_output_section): Add is_interp and
+ is_dynamic_linker_section parameters. Change all callers.
+ (Layout::choose_output_section): Likewise.
+ (Layout::make_output_section): Likewise.
+ (Layout::add_output_section_data): Add is_dynamic_linker_section
+ parameter. Change all callers.
+ * layout.h (class Layout): Update declarations.
+ * output.h (class Output_section): Add is_interp, set_is_interp,
+ is_dynamic_linker_section, set_is_dynamic_linker_section methods.
+ Add is_interp_, is_dynamic_linker_section_ fields. Change
+ generate_code_fills_at_write_ to a bitfield.
+ * output.cc (Output_section::Output_sections): Initialize new
+ fields.
+ (Output_segment::add_output_section): Add do_sort parameter.
+ Change all callers.
+
2009-11-03 Ian Lance Taylor <iant@google.com>
PR 10860
os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
(elfcpp::SHF_ALLOC
| elfcpp::SHF_WRITE),
- this->got_);
+ this->got_, false);
os->set_is_relro();
// The old GNU linker creates a .got.plt section. We just
os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
(elfcpp::SHF_ALLOC
| elfcpp::SHF_WRITE),
- this->got_plt_);
+ this->got_plt_, false);
os->set_is_relro();
// The first three entries are reserved.
gold_assert(layout != NULL);
this->rel_dyn_ = new Reloc_section(parameters->options().combreloc());
layout->add_output_section_data(".rel.dyn", elfcpp::SHT_REL,
- elfcpp::SHF_ALLOC, this->rel_dyn_);
+ elfcpp::SHF_ALLOC, this->rel_dyn_, true);
}
return this->rel_dyn_;
}
{
this->rel_ = new Reloc_section(false);
layout->add_output_section_data(".rel.plt", elfcpp::SHT_REL,
- elfcpp::SHF_ALLOC, this->rel_);
+ elfcpp::SHF_ALLOC, this->rel_, true);
}
template<bool big_endian>
layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
(elfcpp::SHF_ALLOC
| elfcpp::SHF_EXECINSTR),
- this->plt_);
+ this->plt_, false);
}
this->plt_->add_entry(gsym);
}
== NULL);
Output_segment* exidx_segment =
layout->make_output_segment(elfcpp::PT_ARM_EXIDX, elfcpp::PF_R);
- exidx_segment->add_output_section(exidx_section, elfcpp::PF_R);
+ exidx_segment->add_output_section(exidx_section, elfcpp::PF_R,
+ false);
}
}
}
Output_data_space *poc = new Output_data_space(addralign, ds_name);
Output_section *os = layout->add_output_section_data(name,
elfcpp::SHT_NOBITS,
- flags, poc);
+ flags, poc, false);
if (os != NULL)
{
if (commons_section_type == COMMONS_SMALL)
layout->add_output_section_data(".bss",
elfcpp::SHT_NOBITS,
elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
- this->dynbss_);
+ this->dynbss_, false);
}
Output_data_space* dynbss = this->dynbss_;
os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
(elfcpp::SHF_ALLOC
| elfcpp::SHF_WRITE),
- this->got_);
+ this->got_, false);
os->set_is_relro();
// The old GNU linker creates a .got.plt section. We just
os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
(elfcpp::SHF_ALLOC
| elfcpp::SHF_WRITE),
- this->got_plt_);
+ this->got_plt_, false);
os->set_is_relro();
// The first three entries are reserved.
gold_assert(layout != NULL);
this->rel_dyn_ = new Reloc_section(parameters->options().combreloc());
layout->add_output_section_data(".rel.dyn", elfcpp::SHT_REL,
- elfcpp::SHF_ALLOC, this->rel_dyn_);
+ elfcpp::SHF_ALLOC, this->rel_dyn_, true);
}
return this->rel_dyn_;
}
{
this->rel_ = new Reloc_section(false);
layout->add_output_section_data(".rel.plt", elfcpp::SHT_REL,
- elfcpp::SHF_ALLOC, this->rel_);
+ elfcpp::SHF_ALLOC, this->rel_, true);
}
void
layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
(elfcpp::SHF_ALLOC
| elfcpp::SHF_EXECINSTR),
- this->plt_);
+ this->plt_, false);
}
this->plt_->add_entry(gsym);
// Return the output section to use for section NAME with type TYPE
// and section flags FLAGS. NAME must be canonicalized in the string
-// pool, and NAME_KEY is the key.
+// pool, and NAME_KEY is the key. IS_INTERP is true if this is the
+// .interp section. IS_DYNAMIC_LINKER_SECTION is true if this section
+// is used by the dynamic linker.
Output_section*
Layout::get_output_section(const char* name, Stringpool::Key name_key,
- elfcpp::Elf_Word type, elfcpp::Elf_Xword flags)
+ elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
+ bool is_interp, bool is_dynamic_linker_section)
{
elfcpp::Elf_Xword lookup_flags = flags;
}
if (os == NULL)
- os = this->make_output_section(name, type, flags);
+ os = this->make_output_section(name, type, flags, is_interp,
+ is_dynamic_linker_section);
ins.first->second = os;
return os;
}
// RELOBJ, with type TYPE and flags FLAGS. RELOBJ may be NULL for a
// 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.
+// file. IS_INTERP is true if this is the .interp section.
+// IS_DYNAMIC_LINKER_SECTION is true if this section is used by the
+// dynamic linker. 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 is_input_section)
+ bool is_input_section, bool is_interp,
+ bool is_dynamic_linker_section)
{
// We should not see any input sections after we have attached
// sections to segments.
name = this->namepool_.add(name, false, NULL);
- Output_section* os = this->make_output_section(name, type, flags);
+ Output_section* os =
+ this->make_output_section(name, type, flags, is_interp,
+ is_dynamic_linker_section);
os->set_found_in_sections_clause();
*output_section_slot = os;
return os;
// 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 this->get_output_section(name, name_key, type, flags, is_interp,
+ is_dynamic_linker_section);
}
// Return the output section to use for input section SHNDX, with name
{
name = this->namepool_.add(name, true, NULL);
os = this->make_output_section(name, shdr.get_sh_type(),
- shdr.get_sh_flags());
+ shdr.get_sh_flags(), false, false);
}
else
{
os = this->choose_output_section(object, name, shdr.get_sh_type(),
- shdr.get_sh_flags(), true);
+ shdr.get_sh_flags(), true, false,
+ false);
if (os == NULL)
return NULL;
}
Output_section* os = this->choose_output_section(object, name.c_str(),
sh_type,
shdr.get_sh_flags(),
- false);
+ false, false, false);
os->set_should_link_to_symtab();
os->set_info_section(data_section);
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());
+ shdr.get_sh_flags(),
+ false, false);
// 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.
name,
elfcpp::SHT_PROGBITS,
elfcpp::SHF_ALLOC,
- false);
+ false, false, false);
if (os == NULL)
return NULL;
".eh_frame_hdr",
elfcpp::SHT_PROGBITS,
elfcpp::SHF_ALLOC,
- false);
+ false, false, false);
if (hdr_os != NULL)
{
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);
+ hdr_oseg->add_output_section(hdr_os, elfcpp::PF_R, false);
}
this->eh_frame_data_->set_eh_frame_hdr(hdr_posd);
Output_section*
Layout::add_output_section_data(const char* name, elfcpp::Elf_Word type,
elfcpp::Elf_Xword flags,
- Output_section_data* posd)
+ Output_section_data* posd,
+ bool is_dynamic_linker_section)
{
Output_section* os = this->choose_output_section(NULL, name, type, flags,
- false);
+ false, false,
+ is_dynamic_linker_section);
if (os != NULL)
os->add_output_section_data(posd);
return os;
}
// Make a new Output_section, and attach it to segments as
-// appropriate.
+// appropriate. IS_INTERP is true if this is the .interp section.
+// IS_DYNAMIC_LINKER_SECTION is true if this section is used by the
+// dynamic linker.
Output_section*
Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
- elfcpp::Elf_Xword flags)
+ elfcpp::Elf_Xword flags, bool is_interp,
+ bool is_dynamic_linker_section)
{
Output_section* os;
if ((flags & elfcpp::SHF_ALLOC) == 0
&& is_compressible_debug_section(name))
os = new Output_compressed_section(¶meters->options(), name, type,
flags);
-
else if ((flags & elfcpp::SHF_ALLOC) == 0
&& parameters->options().strip_debug_non_line()
&& strcmp(".debug_abbrev", name) == 0)
os = target->make_output_section(name, type, flags);
}
+ if (is_interp)
+ os->set_is_interp();
+ if (is_dynamic_linker_section)
+ os->set_is_dynamic_linker_section();
+
parameters->target().new_output_section(os);
this->section_list_.push_back(os);
elfcpp::Elf_Word seg_flags = Layout::section_flags_to_segment(flags);
+ bool sort_sections = !this->script_options_->saw_sections_clause();
+
// 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. Large data sections also go into their own
if (os->is_large_data_section() && !(*p)->is_large_data_segment())
continue;
- (*p)->add_output_section(os, seg_flags);
+ (*p)->add_output_section(os, seg_flags, sort_sections);
break;
}
seg_flags);
if (os->is_large_data_section())
oseg->set_is_large_data_segment();
- oseg->add_output_section(os, seg_flags);
+ oseg->add_output_section(os, seg_flags, sort_sections);
}
// If we see a loadable SHT_NOTE section, we create a PT_NOTE
&& (((*p)->flags() & elfcpp::PF_W)
== (seg_flags & elfcpp::PF_W)))
{
- (*p)->add_output_section(os, seg_flags);
+ (*p)->add_output_section(os, seg_flags, false);
break;
}
}
{
Output_segment* oseg = this->make_output_segment(elfcpp::PT_NOTE,
seg_flags);
- oseg->add_output_section(os, seg_flags);
+ oseg->add_output_section(os, seg_flags, false);
}
}
{
if (this->tls_segment_ == NULL)
this->make_output_segment(elfcpp::PT_TLS, seg_flags);
- this->tls_segment_->add_output_section(os, seg_flags);
+ this->tls_segment_->add_output_section(os, seg_flags, false);
}
// If -z relro is in effect, and we see a relro section, we create a
gold_assert(seg_flags == (elfcpp::PF_R | elfcpp::PF_W));
if (this->relro_segment_ == NULL)
this->make_output_segment(elfcpp::PT_GNU_RELRO, seg_flags);
- this->relro_segment_->add_output_section(os, seg_flags);
+ this->relro_segment_->add_output_section(os, seg_flags, false);
}
}
{
name = this->namepool_.add(name, false, NULL);
Output_section* os = this->make_output_section(name, elfcpp::SHT_PROGBITS,
- elfcpp::SHF_ALLOC);
+ elfcpp::SHF_ALLOC, false,
+ false);
os->set_found_in_sections_clause();
return os;
}
elfcpp::SHT_DYNAMIC,
(elfcpp::SHF_ALLOC
| elfcpp::SHF_WRITE),
- false);
+ false, false, true);
this->dynamic_section_->set_is_relro();
symtab->define_in_output_data("_DYNAMIC", NULL, this->dynamic_section_, 0, 0,
flags = elfcpp::SHF_ALLOC;
Output_section* os = this->choose_output_section(NULL, section_name,
elfcpp::SHT_NOTE,
- flags, false);
+ flags, false, false,
+ false);
if (os == NULL)
return NULL;
elfcpp::Elf_Xword flags = 0;
if (is_stack_executable)
flags |= elfcpp::SHF_EXECINSTR;
- this->make_output_section(name, elfcpp::SHT_PROGBITS, flags);
+ this->make_output_section(name, elfcpp::SHT_PROGBITS, flags, false,
+ false);
}
else
{
this->namepool_.add(".gnu_incremental_inputs", false, NULL);
Output_section* inputs_os =
this->make_output_section(incremental_inputs_name,
- elfcpp::SHT_GNU_INCREMENTAL_INPUTS, 0);
+ elfcpp::SHT_GNU_INCREMENTAL_INPUTS, 0,
+ false, false);
Output_section_data* posd =
this->incremental_inputs_->create_incremental_inputs_section_data();
inputs_os->add_output_section_data(posd);
this->namepool_.add(".gnu_incremental_strtab", false, NULL);
Output_section* strtab_os = this->make_output_section(incremental_strtab_name,
elfcpp::SHT_STRTAB,
- 0);
+ 0, false, false);
Output_data_strtab* strtab_data =
new Output_data_strtab(this->incremental_inputs_->get_stringpool());
strtab_os->add_output_section_data(strtab_data);
const char* symtab_name = this->namepool_.add(".symtab", false, NULL);
Output_section* osymtab = this->make_output_section(symtab_name,
elfcpp::SHT_SYMTAB,
- 0);
+ 0, false, false);
this->symtab_section_ = osymtab;
Output_section_data* pos = new Output_data_fixed_space(off - startoff,
false, NULL);
Output_section* osymtab_xindex =
this->make_output_section(symtab_xindex_name,
- elfcpp::SHT_SYMTAB_SHNDX, 0);
+ elfcpp::SHT_SYMTAB_SHNDX, 0, false,
+ false);
size_t symcount = (off - startoff) / symsize;
this->symtab_xindex_ = new Output_symtab_xindex(symcount);
const char* strtab_name = this->namepool_.add(".strtab", false, NULL);
Output_section* ostrtab = this->make_output_section(strtab_name,
elfcpp::SHT_STRTAB,
- 0);
+ 0, false, false);
Output_section_data* pstr = new Output_data_strtab(&this->sympool_);
ostrtab->add_output_section_data(pstr);
const char* name = this->namepool_.add(".shstrtab", false, NULL);
- Output_section* os = this->make_output_section(name, elfcpp::SHT_STRTAB, 0);
+ Output_section* os = this->make_output_section(name, elfcpp::SHT_STRTAB, 0,
+ false, false);
// We can't write out this section until we've set all the section
// names, and we don't set the names of compressed output sections
Output_section* dynsym = this->choose_output_section(NULL, ".dynsym",
elfcpp::SHT_DYNSYM,
elfcpp::SHF_ALLOC,
- false);
+ false, false, true);
Output_section_data* odata = new Output_data_fixed_space(index * symsize,
align,
this->choose_output_section(NULL, ".dynsym_shndx",
elfcpp::SHT_SYMTAB_SHNDX,
elfcpp::SHF_ALLOC,
- false);
+ false, false, true);
this->dynsym_xindex_ = new Output_symtab_xindex(index);
Output_section* dynstr = this->choose_output_section(NULL, ".dynstr",
elfcpp::SHT_STRTAB,
elfcpp::SHF_ALLOC,
- false);
+ false, false, true);
Output_section_data* strdata = new Output_data_strtab(&this->dynpool_);
dynstr->add_output_section_data(strdata);
Output_section* hashsec = this->choose_output_section(NULL, ".hash",
elfcpp::SHT_HASH,
elfcpp::SHF_ALLOC,
- false);
+ false, false, true);
Output_section_data* hashdata = new Output_data_const_buffer(phash,
hashlen,
Output_section* hashsec = this->choose_output_section(NULL, ".gnu.hash",
elfcpp::SHT_GNU_HASH,
elfcpp::SHF_ALLOC,
- false);
+ false, false, true);
Output_section_data* hashdata = new Output_data_const_buffer(phash,
hashlen,
Output_section* vsec = this->choose_output_section(NULL, ".gnu.version",
elfcpp::SHT_GNU_versym,
elfcpp::SHF_ALLOC,
- false);
+ false, false, true);
unsigned char* vbuf;
unsigned int vsize;
vdsec= this->choose_output_section(NULL, ".gnu.version_d",
elfcpp::SHT_GNU_verdef,
elfcpp::SHF_ALLOC,
- false);
+ false, false, true);
unsigned char* vdbuf;
unsigned int vdsize;
vnsec = this->choose_output_section(NULL, ".gnu.version_r",
elfcpp::SHT_GNU_verneed,
elfcpp::SHF_ALLOC,
- false);
+ false, false, true);
unsigned char* vnbuf;
unsigned int vnsize;
Output_section* osec = this->choose_output_section(NULL, ".interp",
elfcpp::SHT_PROGBITS,
elfcpp::SHF_ALLOC,
- false);
+ false, true, true);
osec->add_output_section_data(odata);
if (!this->script_options_->saw_phdrs_clause())
{
Output_segment* oseg = this->make_output_segment(elfcpp::PT_INTERP,
elfcpp::PF_R);
- oseg->add_output_section(osec, elfcpp::PF_R);
+ oseg->add_output_section(osec, elfcpp::PF_R, false);
}
}
(elfcpp::PF_R
| elfcpp::PF_W));
oseg->add_output_section(this->dynamic_section_,
- elfcpp::PF_R | elfcpp::PF_W);
+ elfcpp::PF_R | elfcpp::PF_W,
+ false);
}
Output_data_dynamic* const odyn = this->dynamic_data_;
layout_gnu_stack(bool seen_gnu_stack, uint64_t gnu_stack_flags);
// Add an Output_section_data to the layout. This is used for
- // special sections like the GOT section.
+ // special sections like the GOT section. IS_DYNAMIC_LINKER_SECTION
+ // is true for sections which are used by the dynamic linker, such
+ // as dynamic reloc sections.
Output_section*
add_output_section_data(const char* name, elfcpp::Elf_Word type,
elfcpp::Elf_Xword flags,
- Output_section_data*);
+ Output_section_data*, bool is_dynamic_linker_section);
// Create dynamic sections if necessary.
void
// Return the output section for NAME, TYPE and FLAGS.
Output_section*
get_output_section(const char* name, Stringpool::Key name_key,
- elfcpp::Elf_Word type, elfcpp::Elf_Xword flags);
+ elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
+ bool is_interp, bool is_dynamic_linker_section);
// Choose the output section for NAME in RELOBJ.
Output_section*
choose_output_section(const Relobj* relobj, const char* name,
elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
- bool is_input_section);
+ bool is_input_section, bool is_interp,
+ bool is_dynamic_linker_section);
// Create a new Output_section.
Output_section*
make_output_section(const char* name, elfcpp::Elf_Word type,
- elfcpp::Elf_Xword flags);
+ elfcpp::Elf_Xword flags, bool is_interp,
+ bool is_dynamic_linker_section);
// Attach a section to a segment.
void
is_relro_local_(false),
is_small_section_(false),
is_large_section_(false),
+ is_interp_(false),
+ is_dynamic_linker_section_(false),
+ generate_code_fills_at_write_(false),
tls_offset_(0),
checkpoint_(NULL),
merge_section_map_(),
merge_section_by_properties_map_(),
relaxed_input_section_map_(),
- is_relaxed_input_section_map_valid_(true),
- generate_code_fills_at_write_(false)
+ is_relaxed_input_section_map_valid_(true)
{
// An unallocated section has no address. Forcing this means that
// we don't need special treatment for symbols defined in debug
void
Output_segment::add_output_section(Output_section* os,
- elfcpp::Elf_Word seg_flags)
+ elfcpp::Elf_Word seg_flags,
+ bool do_sort)
{
gold_assert((os->flags() & elfcpp::SHF_ALLOC) != 0);
gold_assert(!this->is_max_align_known_);
else
pdl = &this->output_data_;
+ // Note that while there may be many input sections in an output
+ // section, there are normally only a few output sections in an
+ // output segment. The loops below are expected to be fast.
+
// So that PT_NOTE segments will work correctly, we need to ensure
// that all SHT_NOTE sections are adjacent. This will normally
// happen automatically, because all the SHT_NOTE input sections
// flags, and thus be in different output sections, but for the
// different section flags to map into the same segment flags and
// thus the same output segment.
-
- // Note that while there may be many input sections in an output
- // section, there are normally only a few output sections in an
- // output segment. This loop is expected to be fast.
-
if (os->type() == elfcpp::SHT_NOTE && !pdl->empty())
{
Output_segment::Output_data_list::iterator p = pdl->end();
// case: we group the SHF_TLS/SHT_NOBITS sections right after the
// SHF_TLS/SHT_PROGBITS sections. This lets us set up PT_TLS
// correctly. SHF_TLS sections get added to both a PT_LOAD segment
- // and the PT_TLS segment -- we do this grouping only for the
- // PT_LOAD segment.
+ // and the PT_TLS segment; we do this grouping only for the PT_LOAD
+ // segment.
if (this->type_ != elfcpp::PT_TLS
&& (os->flags() & elfcpp::SHF_TLS) != 0)
{
gold_unreachable();
}
+ // We do some further output section sorting in order to make the
+ // generated program run more efficiently. We should only do this
+ // when not using a linker script, so it is controled by the DO_SORT
+ // parameter.
+ if (do_sort)
+ {
+ // FreeBSD requires the .interp section to be in the first page
+ // of the executable. That is a more efficient location anyhow
+ // for any OS, since it means that the kernel will have the data
+ // handy after it reads the program headers.
+ if (os->is_interp() && !pdl->empty())
+ {
+ pdl->insert(pdl->begin(), os);
+ return;
+ }
+
+ // Put loadable non-writable notes immediately after the .interp
+ // sections, so that the PT_NOTE segment is on the first page of
+ // the executable.
+ if (os->type() == elfcpp::SHT_NOTE
+ && (os->flags() & elfcpp::SHF_WRITE) == 0
+ && !pdl->empty())
+ {
+ Output_segment::Output_data_list::iterator p = pdl->begin();
+ if ((*p)->is_section() && (*p)->output_section()->is_interp())
+ ++p;
+ pdl->insert(p, os);
+ }
+
+ // If this section is used by the dynamic linker, and it is not
+ // writable, then put it first, after the .interp section and
+ // any loadable notes. This makes it more likely that the
+ // dynamic linker will have to read less data from the disk.
+ if (os->is_dynamic_linker_section()
+ && !pdl->empty()
+ && (os->flags() & elfcpp::SHF_WRITE) == 0)
+ {
+ bool is_reloc = (os->type() == elfcpp::SHT_REL
+ || os->type() == elfcpp::SHT_RELA);
+ Output_segment::Output_data_list::iterator p = pdl->begin();
+ while (p != pdl->end()
+ && (*p)->is_section()
+ && ((*p)->output_section()->is_dynamic_linker_section()
+ || (*p)->output_section()->type() == elfcpp::SHT_NOTE))
+ {
+ // Put reloc sections after the other ones. Putting the
+ // dynamic reloc sections first confuses BFD, notably
+ // objcopy and strip.
+ if (!is_reloc
+ && ((*p)->output_section()->type() == elfcpp::SHT_REL
+ || (*p)->output_section()->type() == elfcpp::SHT_RELA))
+ break;
+ ++p;
+ }
+ pdl->insert(p, os);
+ return;
+ }
+ }
+
+ // If there were no constraints on the output section, just add it
+ // to the end of the list.
pdl->push_back(os);
}
is_large_data_section()
{ return this->is_large_section_ && this->type_ != elfcpp::SHT_NOBITS; }
+ // True if this is the .interp section which goes into the PT_INTERP
+ // segment.
+ bool
+ is_interp() const
+ { return this->is_interp_; }
+
+ // Record that this is the interp section.
+ void
+ set_is_interp()
+ { this->is_interp_ = true; }
+
+ // True if this is a section used by the dynamic linker.
+ bool
+ is_dynamic_linker_section() const
+ { return this->is_dynamic_linker_section_; }
+
+ // Record that this is a section used by the dynamic linker.
+ void
+ set_is_dynamic_linker_section()
+ { this->is_dynamic_linker_section_ = true; }
+
// Return whether this section should be written after all the input
// sections are complete.
bool
bool is_small_section_ : 1;
// True if this is a large section.
bool is_large_section_ : 1;
+ // True if this is the .interp section going into the PT_INTERP
+ // segment.
+ bool is_interp_ : 1;
+ // True if this is section is read by the dynamic linker.
+ bool is_dynamic_linker_section_ : 1;
+ // Whether code-fills are generated at write.
+ bool generate_code_fills_at_write_ : 1;
// For SHT_TLS sections, the offset of this section relative to the base
// of the TLS segment.
uint64_t tls_offset_;
// Map from merge section properties to merge_sections;
Merge_section_by_properties_map merge_section_by_properties_map_;
// Map from input sections to relaxed input sections. This is mutable
- // beacause it is udpated lazily. We may need to update it in a
+ // because it is updated lazily. We may need to update it in a
// const qualified method.
mutable Output_section_data_by_input_section_map relaxed_input_section_map_;
// Whether relaxed_input_section_map_ is valid.
mutable bool is_relaxed_input_section_map_valid_;
- // Whether code-fills are generated at write.
- bool generate_code_fills_at_write_;
};
// An output segment. PT_LOAD segments are built from collections of
uint64_t
maximum_alignment();
- // Add an Output_section to this segment.
+ // Add the Output_section OS to this segment. SEG_FLAGS is the
+ // segment flags to use. DO_SORT is true if we should sort the
+ // placement of the input section for more efficient generated code.
void
- add_output_section(Output_section* os, elfcpp::Elf_Word seg_flags);
+ add_output_section(Output_section* os, elfcpp::Elf_Word seg_flags,
+ bool do_sort);
// Remove an Output_section from this segment. It is an error if it
// is not present.
layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
- this->got_);
+ this->got_, false);
// Create the GOT2 or TOC in the .got section.
if (size == 32)
layout->add_output_section_data(".got2", elfcpp::SHT_PROGBITS,
elfcpp::SHF_ALLOC
| elfcpp::SHF_WRITE,
- this->got2_);
+ this->got2_, false);
}
else
{
layout->add_output_section_data(".toc", elfcpp::SHT_PROGBITS,
elfcpp::SHF_ALLOC
| elfcpp::SHF_WRITE,
- this->toc_);
+ this->toc_, false);
}
// Define _GLOBAL_OFFSET_TABLE_ at the start of the .got section.
gold_assert(layout != NULL);
this->rela_dyn_ = new Reloc_section(parameters->options().combreloc());
layout->add_output_section_data(".rela.dyn", elfcpp::SHT_RELA,
- elfcpp::SHF_ALLOC, this->rela_dyn_);
+ elfcpp::SHF_ALLOC, this->rela_dyn_, true);
}
return this->rela_dyn_;
}
{
this->rel_ = new Reloc_section(false);
layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA,
- elfcpp::SHF_ALLOC, this->rel_);
+ elfcpp::SHF_ALLOC, this->rel_, true);
}
template<int size, bool big_endian>
(elfcpp::SHF_ALLOC
| elfcpp::SHF_EXECINSTR
| elfcpp::SHF_WRITE),
- this->plt_);
+ this->plt_, false);
// Define _PROCEDURE_LINKAGE_TABLE_ at the start of the .plt section.
symtab->define_in_output_data("_PROCEDURE_LINKAGE_TABLE_", NULL,
Output_section* os = layout->add_output_section_data(".sdata", 0,
elfcpp::SHF_ALLOC
| elfcpp::SHF_WRITE,
- sdata);
+ sdata, false);
symtab->define_in_output_data("_SDA_BASE_", NULL,
os,
32768, 0,
is_current_seg_readonly = true;
}
- current_seg->add_output_section(*p, seg_flags);
+ current_seg->add_output_section(*p, seg_flags, false);
if (((*p)->flags() & elfcpp::SHF_WRITE) != 0)
is_current_seg_readonly = false;
Layout::section_flags_to_segment((*p)->flags());
Output_segment* oseg = layout->make_output_segment(elfcpp::PT_NOTE,
seg_flags);
- oseg->add_output_section(*p, seg_flags);
+ oseg->add_output_section(*p, seg_flags, false);
// Incorporate any subsequent SHT_NOTE sections, in the
// hopes that the script is sensible.
&& (*pnext)->type() == elfcpp::SHT_NOTE)
{
seg_flags = Layout::section_flags_to_segment((*pnext)->flags());
- oseg->add_output_section(*pnext, seg_flags);
+ oseg->add_output_section(*pnext, seg_flags, false);
p = pnext;
++pnext;
}
Layout::section_flags_to_segment((*p)->flags());
Output_segment* oseg = layout->make_output_segment(elfcpp::PT_TLS,
seg_flags);
- oseg->add_output_section(*p, seg_flags);
+ oseg->add_output_section(*p, seg_flags, false);
Layout::Section_list::const_iterator pnext = p + 1;
while (pnext != sections->end()
&& ((*pnext)->flags() & elfcpp::SHF_TLS) != 0)
{
seg_flags = Layout::section_flags_to_segment((*pnext)->flags());
- oseg->add_output_section(*pnext, seg_flags);
+ oseg->add_output_section(*pnext, seg_flags, false);
p = pnext;
++pnext;
}
elfcpp::Elf_Word seg_flags =
Layout::section_flags_to_segment(os->flags());
- r->second->add_output_section(os, seg_flags);
+ r->second->add_output_section(os, seg_flags, false);
if (r->second->type() == elfcpp::PT_LOAD)
{
os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
(elfcpp::SHF_ALLOC
| elfcpp::SHF_WRITE),
- this->got_);
+ this->got_, false);
os->set_is_relro();
// Define _GLOBAL_OFFSET_TABLE_ at the start of the .got section.
gold_assert(layout != NULL);
this->rela_dyn_ = new Reloc_section(parameters->options().combreloc());
layout->add_output_section_data(".rela.dyn", elfcpp::SHT_RELA,
- elfcpp::SHF_ALLOC, this->rela_dyn_);
+ elfcpp::SHF_ALLOC, this->rela_dyn_, true);
}
return this->rela_dyn_;
}
{
this->rel_ = new Reloc_section(false);
layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA,
- elfcpp::SHF_ALLOC, this->rel_);
+ elfcpp::SHF_ALLOC, this->rel_, true);
}
template<int size, bool big_endian>
(elfcpp::SHF_ALLOC
| elfcpp::SHF_EXECINSTR
| elfcpp::SHF_WRITE),
- this->plt_);
+ this->plt_, false);
// Define _PROCEDURE_LINKAGE_TABLE_ at the start of the .plt section.
symtab->define_in_output_data("_PROCEDURE_LINKAGE_TABLE_", NULL,
os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
(elfcpp::SHF_ALLOC
| elfcpp::SHF_WRITE),
- this->got_);
+ this->got_, false);
os->set_is_relro();
// The old GNU linker creates a .got.plt section. We just
os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
(elfcpp::SHF_ALLOC
| elfcpp::SHF_WRITE),
- this->got_plt_);
+ this->got_plt_, false);
os->set_is_relro();
// The first three entries are reserved.
gold_assert(layout != NULL);
this->rela_dyn_ = new Reloc_section(parameters->options().combreloc());
layout->add_output_section_data(".rela.dyn", elfcpp::SHT_RELA,
- elfcpp::SHF_ALLOC, this->rela_dyn_);
+ elfcpp::SHF_ALLOC, this->rela_dyn_, true);
}
return this->rela_dyn_;
}
{
this->rel_ = new Reloc_section(false);
layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA,
- elfcpp::SHF_ALLOC, this->rel_);
+ elfcpp::SHF_ALLOC, this->rel_, true);
}
void
layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
(elfcpp::SHF_ALLOC
| elfcpp::SHF_EXECINSTR),
- this->plt_);
+ this->plt_, false);
}
}