aboutsummaryrefslogtreecommitdiff
path: root/gold/output.cc
diff options
context:
space:
mode:
authorIan Lance Taylor <ian@airs.com>2009-11-04 15:56:03 +0000
committerIan Lance Taylor <ian@airs.com>2009-11-04 15:56:03 +0000
commitf5c870d25d59bc1e6fcb6a836b6bd1981788982c (patch)
tree5f0302e3a7df3fabd48233a453fdeca714c8116d /gold/output.cc
parentc7cbc7a8c26acd91b498167e3a2b8625d5eaa109 (diff)
downloadgdb-f5c870d25d59bc1e6fcb6a836b6bd1981788982c.zip
gdb-f5c870d25d59bc1e6fcb6a836b6bd1981788982c.tar.gz
gdb-f5c870d25d59bc1e6fcb6a836b6bd1981788982c.tar.bz2
* 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.
Diffstat (limited to 'gold/output.cc')
-rw-r--r--gold/output.cc83
1 files changed, 73 insertions, 10 deletions
diff --git a/gold/output.cc b/gold/output.cc
index 61e5c87..5e9b813 100644
--- a/gold/output.cc
+++ b/gold/output.cc
@@ -1797,13 +1797,15 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type,
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
@@ -3042,7 +3044,8 @@ Output_segment::Output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags)
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_);
@@ -3057,6 +3060,10 @@ Output_segment::add_output_section(Output_section* os,
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
@@ -3065,11 +3072,6 @@ Output_segment::add_output_section(Output_section* os,
// 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();
@@ -3091,8 +3093,8 @@ Output_segment::add_output_section(Output_section* os,
// 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)
{
@@ -3222,6 +3224,67 @@ Output_segment::add_output_section(Output_section* os,
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);
}