diff options
author | Ian Lance Taylor <ian@airs.com> | 2009-11-04 15:56:03 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 2009-11-04 15:56:03 +0000 |
commit | f5c870d25d59bc1e6fcb6a836b6bd1981788982c (patch) | |
tree | 5f0302e3a7df3fabd48233a453fdeca714c8116d /gold/output.cc | |
parent | c7cbc7a8c26acd91b498167e3a2b8625d5eaa109 (diff) | |
download | gdb-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.cc | 83 |
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); } |