diff options
author | Ian Lance Taylor <ian@airs.com> | 2010-08-03 14:07:13 +0000 |
---|---|---|
committer | Ian Lance Taylor <ian@airs.com> | 2010-08-03 14:07:13 +0000 |
commit | 22f0da72ea2fc99e409548ce883b751aa822c2c3 (patch) | |
tree | 29f8b535bf96223cf9150606e977ff8ef924a8c6 /gold | |
parent | e4d9f07834de9797e18e4810d985764a23c00dcc (diff) | |
download | gdb-22f0da72ea2fc99e409548ce883b751aa822c2c3.zip gdb-22f0da72ea2fc99e409548ce883b751aa822c2c3.tar.gz gdb-22f0da72ea2fc99e409548ce883b751aa822c2c3.tar.bz2 |
2010-08-03 Ian Lance Taylor <iant@google.com>
PR 11805
* layout.h (enum Output_section_order): Define.
(class Layout): Update declarations.
* layout.cc (Layout::get_output_section): Add order parameter.
Remove is_interp, is_dynamic_linker_section, is_last_relro, and
is_first_non_relro parameters. Change all callers.
(Layout::choose_output_section): Likewise.
(Layout::add_output_section_data): Likewise.
(Layout::make_output_section): Likewise. Set order.
(Layout::default_section_order): New function.
(Layout::layout_eh_frame): Call add_output_section_to_nonload.
* output.cc (Output_section::Output_section): Initialize order_.
Don't initialize deleted fields.
(Output_segment::Output_segment): Don't initialize deleted
fields.
(Output_segment::add_output_section_to_load): New function
replacing add_output_section. Change all callers to call this or
add_output_section_to_nonload.
(Output_segment::add_output_section_to_nonload): New function.
(Output_segment::remove_output_section): Rewrite.
(Output_segment::add_initial_output_data): Likewise.
(Output_segment::has_any_data_sections): Likewise.
(Output_segment::is_first_section_relro): Likewise.
(Output_segment::maximum_alignment): Likewise.
(Output_segment::has_dynamic_reloc): New function replacing
dynamic_reloc_count. Change all callers.
(Output_segment::has_dynamic_reloc_list): New function replacing
dynamic_reloc_count_list. Change all callers.
(Output_segment::set_section_addresses): Rewrite.
(Output_segment::set_offset): Rewrite.
(Output_segment::find_first_and_last_list): Remove.
(Output_segment::set_tls_offsets): Rewrite.
(Output_segment::first_section_load_address): Likewise.
(Output_segment::output_section_count): Likewise.
(Output_segment::section_with_lowest_load_address): Likewise.
(Output_segment::write_section_headers): Likewise.
(Output_segment::print_sections_to_map): Likewise.
* output.h (class Output_data): Remove dynamic_reloc_count_
field. Add has_dynamic_reloc_ field. Make bools into bitfields.
(Output_data::add_dynamic_reloc): Rewrite.
(Output_data::has_dynamic_reloc): New function.
(Output_data::dynamic_reloc_count): Remove.
(class Output_section): Add order_ field. Remvoe is_relro_local_,
is_last_relro_, is_first_non_relro_, is_interp_,
is_dynamic_linker_section_ fields. Add order and set_order
functions. Remove is_relro_local, set_is_relro_local,
is_last_relro, set_is_last_relro, is_first_non_relro,
set_is_first_non_relro functions, is_interp, set_is_interp,
is_dynamic_linker_section, and set_is_dynamic_linker_section
functions.
(class Output_segment): Change Output_data_list from std::list to
std:;vector. Add output_lists_ field. Remove output_data_ and
output_bss_ fields. Update declarations.
Diffstat (limited to 'gold')
-rw-r--r-- | gold/ChangeLog | 56 | ||||
-rw-r--r-- | gold/arm.cc | 22 | ||||
-rw-r--r-- | gold/common.cc | 5 | ||||
-rw-r--r-- | gold/copy-relocs.cc | 3 | ||||
-rw-r--r-- | gold/i386.cc | 22 | ||||
-rw-r--r-- | gold/layout.cc | 319 | ||||
-rw-r--r-- | gold/layout.h | 133 | ||||
-rw-r--r-- | gold/output.cc | 588 | ||||
-rw-r--r-- | gold/output.h | 149 | ||||
-rw-r--r-- | gold/powerpc.cc | 23 | ||||
-rw-r--r-- | gold/script-sections.cc | 16 | ||||
-rw-r--r-- | gold/sparc.cc | 12 | ||||
-rw-r--r-- | gold/x86_64.cc | 23 |
13 files changed, 654 insertions, 717 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog index a9612ba..a56d3ac 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,59 @@ +2010-08-03 Ian Lance Taylor <iant@google.com> + + PR 11805 + * layout.h (enum Output_section_order): Define. + (class Layout): Update declarations. + * layout.cc (Layout::get_output_section): Add order parameter. + Remove is_interp, is_dynamic_linker_section, is_last_relro, and + is_first_non_relro parameters. Change all callers. + (Layout::choose_output_section): Likewise. + (Layout::add_output_section_data): Likewise. + (Layout::make_output_section): Likewise. Set order. + (Layout::default_section_order): New function. + (Layout::layout_eh_frame): Call add_output_section_to_nonload. + * output.cc (Output_section::Output_section): Initialize order_. + Don't initialize deleted fields. + (Output_segment::Output_segment): Don't initialize deleted + fields. + (Output_segment::add_output_section_to_load): New function + replacing add_output_section. Change all callers to call this or + add_output_section_to_nonload. + (Output_segment::add_output_section_to_nonload): New function. + (Output_segment::remove_output_section): Rewrite. + (Output_segment::add_initial_output_data): Likewise. + (Output_segment::has_any_data_sections): Likewise. + (Output_segment::is_first_section_relro): Likewise. + (Output_segment::maximum_alignment): Likewise. + (Output_segment::has_dynamic_reloc): New function replacing + dynamic_reloc_count. Change all callers. + (Output_segment::has_dynamic_reloc_list): New function replacing + dynamic_reloc_count_list. Change all callers. + (Output_segment::set_section_addresses): Rewrite. + (Output_segment::set_offset): Rewrite. + (Output_segment::find_first_and_last_list): Remove. + (Output_segment::set_tls_offsets): Rewrite. + (Output_segment::first_section_load_address): Likewise. + (Output_segment::output_section_count): Likewise. + (Output_segment::section_with_lowest_load_address): Likewise. + (Output_segment::write_section_headers): Likewise. + (Output_segment::print_sections_to_map): Likewise. + * output.h (class Output_data): Remove dynamic_reloc_count_ + field. Add has_dynamic_reloc_ field. Make bools into bitfields. + (Output_data::add_dynamic_reloc): Rewrite. + (Output_data::has_dynamic_reloc): New function. + (Output_data::dynamic_reloc_count): Remove. + (class Output_section): Add order_ field. Remvoe is_relro_local_, + is_last_relro_, is_first_non_relro_, is_interp_, + is_dynamic_linker_section_ fields. Add order and set_order + functions. Remove is_relro_local, set_is_relro_local, + is_last_relro, set_is_last_relro, is_first_non_relro, + set_is_first_non_relro functions, is_interp, set_is_interp, + is_dynamic_linker_section, and set_is_dynamic_linker_section + functions. + (class Output_segment): Change Output_data_list from std::list to + std:;vector. Add output_lists_ field. Remove output_data_ and + output_bss_ fields. Update declarations. + 2010-08-02 Ian Lance Taylor <iant@google.com> * arm.cc (Target_arm::gc_process_relocs): Use typename. diff --git a/gold/arm.cc b/gold/arm.cc index 780b7df..5d25533 100644 --- a/gold/arm.cc +++ b/gold/arm.cc @@ -4156,7 +4156,8 @@ Target_arm<big_endian>::got_section(Symbol_table* symtab, Layout* layout) layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE), - this->got_, false, false, false, true); + this->got_, ORDER_RELRO, true); + // The old GNU linker creates a .got.plt section. We just // create another set of data in the .got section. Note that we // always create a PLT if we create a GOT, although the PLT @@ -4165,8 +4166,7 @@ Target_arm<big_endian>::got_section(Symbol_table* symtab, Layout* layout) layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE), - this->got_plt_, false, false, false, - false); + this->got_plt_, ORDER_DATA, false); // The first three entries are reserved. this->got_plt_->set_current_data_size(3 * 4); @@ -4194,8 +4194,8 @@ Target_arm<big_endian>::rel_dyn_section(Layout* layout) 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_, true, - false, false, false); + elfcpp::SHF_ALLOC, this->rel_dyn_, + ORDER_DYNAMIC_RELOCS, false); } return this->rel_dyn_; } @@ -7158,8 +7158,8 @@ Output_data_plt_arm<big_endian>::Output_data_plt_arm(Layout* layout, { this->rel_ = new Reloc_section(false); layout->add_output_section_data(".rel.plt", elfcpp::SHT_REL, - elfcpp::SHF_ALLOC, this->rel_, true, false, - false, false); + elfcpp::SHF_ALLOC, this->rel_, + ORDER_DYNAMIC_PLT_RELOCS, false); } template<bool big_endian> @@ -7321,7 +7321,7 @@ Target_arm<big_endian>::make_plt_entry(Symbol_table* symtab, Layout* layout, layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS, (elfcpp::SHF_ALLOC | elfcpp::SHF_EXECINSTR), - this->plt_, false, false, false, false); + this->plt_, ORDER_PLT, false); } this->plt_->add_entry(gsym); } @@ -8382,8 +8382,8 @@ Target_arm<big_endian>::do_finalize_sections( == 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, - false); + exidx_segment->add_output_section_to_nonload(exidx_section, + elfcpp::PF_R); } } @@ -8395,7 +8395,7 @@ Target_arm<big_endian>::do_finalize_sections( new Output_attributes_section_data(*this->attributes_section_data_); layout->add_output_section_data(".ARM.attributes", elfcpp::SHT_ARM_ATTRIBUTES, 0, - attributes_section, false, false, false, + attributes_section, ORDER_INVALID, false); } diff --git a/gold/common.cc b/gold/common.cc index 8346c0b..d5046e5 100644 --- a/gold/common.cc +++ b/gold/common.cc @@ -298,8 +298,9 @@ Symbol_table::do_allocate_commons_list( 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, false, - false, false, false); + flags, poc, + ORDER_INVALID, + false); if (os != NULL) { if (commons_section_type == COMMONS_SMALL) diff --git a/gold/copy-relocs.cc b/gold/copy-relocs.cc index 1ff7ffe..9544c81 100644 --- a/gold/copy-relocs.cc +++ b/gold/copy-relocs.cc @@ -141,8 +141,7 @@ Copy_relocs<sh_type, size, big_endian>::emit_copy_reloc( layout->add_output_section_data(".bss", elfcpp::SHT_NOBITS, elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE, - this->dynbss_, false, false, false, - false); + this->dynbss_, ORDER_BSS, false); } Output_data_space* dynbss = this->dynbss_; diff --git a/gold/i386.cc b/gold/i386.cc index ce07588..b4040c1 100644 --- a/gold/i386.cc +++ b/gold/i386.cc @@ -508,14 +508,14 @@ Target_i386::got_section(Symbol_table* symtab, Layout* layout) layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE), - this->got_, false, true, true, false); + this->got_, ORDER_RELRO_LAST, true); this->got_plt_ = new Output_data_space(4, "** GOT PLT"); layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS, (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE), - this->got_plt_, false, false, false, - true); + this->got_plt_, ORDER_NON_RELRO_FIRST, + false); // The first three entries are reserved. this->got_plt_->set_current_data_size(3 * 4); @@ -539,8 +539,8 @@ Target_i386::got_section(Symbol_table* symtab, Layout* layout) layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS, (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE), - this->got_tlsdesc_, false, false, false, - true); + this->got_tlsdesc_, + ORDER_NON_RELRO_FIRST, false); } return this->got_; @@ -556,8 +556,8 @@ Target_i386::rel_dyn_section(Layout* layout) 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_, true, - false, false, false); + elfcpp::SHF_ALLOC, this->rel_dyn_, + ORDER_DYNAMIC_RELOCS, false); } return this->rel_dyn_; } @@ -639,8 +639,8 @@ Output_data_plt_i386::Output_data_plt_i386(Layout* layout, { this->rel_ = new Reloc_section(false); layout->add_output_section_data(".rel.plt", elfcpp::SHT_REL, - elfcpp::SHF_ALLOC, this->rel_, true, - false, false, false); + elfcpp::SHF_ALLOC, this->rel_, + ORDER_DYNAMIC_PLT_RELOCS, false); } void @@ -692,7 +692,7 @@ Output_data_plt_i386::rel_tls_desc(Layout* layout) this->tls_desc_rel_ = new Reloc_section(false); layout->add_output_section_data(".rel.plt", elfcpp::SHT_REL, elfcpp::SHF_ALLOC, this->tls_desc_rel_, - true, false, false, false); + ORDER_DYNAMIC_PLT_RELOCS, false); gold_assert(this->tls_desc_rel_->output_section() == this->rel_->output_section()); } @@ -843,7 +843,7 @@ Target_i386::make_plt_entry(Symbol_table* symtab, Layout* layout, Symbol* gsym) layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS, (elfcpp::SHF_ALLOC | elfcpp::SHF_EXECINSTR), - this->plt_, false, false, false, false); + this->plt_, ORDER_PLT, false); } this->plt_->add_entry(gsym); diff --git a/gold/layout.cc b/gold/layout.cc index b22a3bd..1107fa6 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -409,9 +409,7 @@ Layout::find_output_segment(elfcpp::PT type, elfcpp::Elf_Word set, Output_section* Layout::get_output_section(const char* name, Stringpool::Key name_key, elfcpp::Elf_Word type, elfcpp::Elf_Xword flags, - bool is_interp, bool is_dynamic_linker_section, - bool is_relro, bool is_last_relro, - bool is_first_non_relro) + Output_section_order order, bool is_relro) { elfcpp::Elf_Xword lookup_flags = flags; @@ -460,9 +458,8 @@ Layout::get_output_section(const char* name, Stringpool::Key name_key, } if (os == NULL) - os = this->make_output_section(name, type, flags, is_interp, - is_dynamic_linker_section, is_relro, - is_last_relro, is_first_non_relro); + os = this->make_output_section(name, type, flags, order, is_relro); + ins.first->second = os; return os; } @@ -482,9 +479,8 @@ Layout::get_output_section(const char* name, Stringpool::Key name_key, 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_interp, - bool is_dynamic_linker_section, bool is_relro, - bool is_last_relro, bool is_first_non_relro) + bool is_input_section, Output_section_order order, + bool is_relro) { // We should not see any input sections after we have attached // sections to segments. @@ -546,10 +542,9 @@ Layout::choose_output_section(const Relobj* relobj, const char* name, name = this->namepool_.add(name, false, NULL); - Output_section* os = - this->make_output_section(name, type, flags, is_interp, - is_dynamic_linker_section, is_relro, - is_last_relro, is_first_non_relro); + Output_section* os = this->make_output_section(name, type, flags, + order, is_relro); + os->set_found_in_sections_clause(); // Special handling for NOLOAD sections. @@ -591,9 +586,7 @@ Layout::choose_output_section(const Relobj* relobj, const char* name, // 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, is_interp, - is_dynamic_linker_section, is_relro, - is_last_relro, is_first_non_relro); + return this->get_output_section(name, name_key, type, flags, order, is_relro); } // Return the output section to use for input section SHNDX, with name @@ -647,14 +640,14 @@ Layout::layout(Sized_relobj<size, big_endian>* object, unsigned int shndx, && (shdr.get_sh_flags() & elfcpp::SHF_GROUP) != 0) { name = this->namepool_.add(name, true, NULL); - os = this->make_output_section(name, sh_type, shdr.get_sh_flags(), false, - false, false, false, false); + os = this->make_output_section(name, sh_type, shdr.get_sh_flags(), + ORDER_INVALID, false); } else { os = this->choose_output_section(object, name, sh_type, - shdr.get_sh_flags(), true, false, - false, false, false, false); + shdr.get_sh_flags(), true, + ORDER_INVALID, false); if (os == NULL) return NULL; } @@ -709,13 +702,13 @@ Layout::layout_reloc(Sized_relobj<size, big_endian>* object, 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, false, - false, false, false, false); + shdr.get_sh_flags(), false, + ORDER_INVALID, false); else { const char* n = this->namepool_.add(name.c_str(), true, NULL); os = this->make_output_section(n, sh_type, shdr.get_sh_flags(), - false, false, false, false, false); + ORDER_INVALID, false); } os->set_should_link_to_symtab(); @@ -764,8 +757,7 @@ Layout::layout_group(Symbol_table* symtab, Output_section* os = this->make_output_section(group_section_name, elfcpp::SHT_GROUP, shdr.get_sh_flags(), - false, false, false, - false, false); + ORDER_INVALID, 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. @@ -815,12 +807,10 @@ Layout::layout_eh_frame(Sized_relobj<size, big_endian>* object, gold_assert((shdr.get_sh_flags() & elfcpp::SHF_ALLOC) != 0); const char* const name = ".eh_frame"; - Output_section* os = this->choose_output_section(object, - name, + Output_section* os = this->choose_output_section(object, name, elfcpp::SHT_PROGBITS, - elfcpp::SHF_ALLOC, - false, false, false, - false, false, false); + elfcpp::SHF_ALLOC, false, + ORDER_EHFRAME, false); if (os == NULL) return NULL; @@ -832,12 +822,10 @@ Layout::layout_eh_frame(Sized_relobj<size, big_endian>* object, if (parameters->options().eh_frame_hdr()) { Output_section* hdr_os = - this->choose_output_section(NULL, - ".eh_frame_hdr", + this->choose_output_section(NULL, ".eh_frame_hdr", elfcpp::SHT_PROGBITS, - elfcpp::SHF_ALLOC, - false, false, false, - false, false, false); + elfcpp::SHF_ALLOC, false, + ORDER_EHFRAME, false); if (hdr_os != NULL) { @@ -852,7 +840,8 @@ Layout::layout_eh_frame(Sized_relobj<size, big_endian>* object, 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, false); + hdr_oseg->add_output_section_to_nonload(hdr_os, + elfcpp::PF_R); } this->eh_frame_data_->set_eh_frame_hdr(hdr_posd); @@ -905,15 +894,10 @@ Output_section* Layout::add_output_section_data(const char* name, elfcpp::Elf_Word type, elfcpp::Elf_Xword flags, Output_section_data* posd, - bool is_dynamic_linker_section, - bool is_relro, bool is_last_relro, - bool is_first_non_relro) + Output_section_order order, bool is_relro) { Output_section* os = this->choose_output_section(NULL, name, type, flags, - false, false, - is_dynamic_linker_section, - is_relro, is_last_relro, - is_first_non_relro); + false, order, is_relro); if (os != NULL) os->add_output_section_data(posd); return os; @@ -957,17 +941,14 @@ is_compressed_debug_section(const char* secname) } // Make a new Output_section, and attach it to segments as -// 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. IS_RELRO is true if this is a relro section. -// IS_LAST_RELRO is true if this is the last relro section. -// IS_FIRST_NON_RELRO is true if this is the first non relro section. +// appropriate. ORDER is the order in which this section should +// appear in the output segment. IS_RELRO is true if this is a relro +// (read-only after relocations) section. Output_section* Layout::make_output_section(const char* name, elfcpp::Elf_Word type, - elfcpp::Elf_Xword flags, bool is_interp, - bool is_dynamic_linker_section, bool is_relro, - bool is_last_relro, bool is_first_non_relro) + elfcpp::Elf_Xword flags, + Output_section_order order, bool is_relro) { Output_section* os; if ((flags & elfcpp::SHF_ALLOC) == 0 @@ -1000,16 +981,39 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type, 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(); + // With -z relro, we have to recognize the special sections by name. + // There is no other way. + bool is_relro_local = false; + if (!this->script_options_->saw_sections_clause() + && parameters->options().relro() + && type == elfcpp::SHT_PROGBITS + && (flags & elfcpp::SHF_ALLOC) != 0 + && (flags & elfcpp::SHF_WRITE) != 0) + { + if (strcmp(name, ".data.rel.ro") == 0) + is_relro = true; + else if (strcmp(name, ".data.rel.ro.local") == 0) + { + is_relro = true; + is_relro_local = true; + } + else if (type == elfcpp::SHT_INIT_ARRAY + || type == elfcpp::SHT_FINI_ARRAY + || type == elfcpp::SHT_PREINIT_ARRAY) + is_relro = true; + else if (strcmp(name, ".ctors") == 0 + || strcmp(name, ".dtors") == 0 + || strcmp(name, ".jcr") == 0) + is_relro = true; + } + if (is_relro) os->set_is_relro(); - if (is_last_relro) - os->set_is_last_relro(); - if (is_first_non_relro) - os->set_is_first_non_relro(); + + if (order == ORDER_INVALID && (flags & elfcpp::SHF_ALLOC) != 0) + order = this->default_section_order(os, is_relro_local); + + os->set_order(order); parameters->target().new_output_section(os); @@ -1025,23 +1029,6 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type, || strcmp(name, ".fini_array") == 0)) os->set_may_sort_attached_input_sections(); - // With -z relro, we have to recognize the special sections by name. - // There is no other way. - if (!this->script_options_->saw_sections_clause() - && parameters->options().relro() - && type == elfcpp::SHT_PROGBITS - && (flags & elfcpp::SHF_ALLOC) != 0 - && (flags & elfcpp::SHF_WRITE) != 0) - { - if (strcmp(name, ".data.rel.ro") == 0) - os->set_is_relro(); - else if (strcmp(name, ".data.rel.ro.local") == 0) - { - os->set_is_relro(); - os->set_is_relro_local(); - } - } - // Check for .stab*str sections, as .stab* sections need to link to // them. if (type == elfcpp::SHT_STRTAB @@ -1059,6 +1046,74 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type, return os; } +// Return the default order in which a section should be placed in an +// output segment. This function captures a lot of the ideas in +// ld/scripttempl/elf.sc in the GNU linker. Note that the order of a +// linker created section is normally set when the section is created; +// this function is used for input sections. + +Output_section_order +Layout::default_section_order(Output_section* os, bool is_relro_local) +{ + gold_assert((os->flags() & elfcpp::SHF_ALLOC) != 0); + bool is_write = (os->flags() & elfcpp::SHF_WRITE) != 0; + bool is_execinstr = (os->flags() & elfcpp::SHF_EXECINSTR) != 0; + bool is_bss = false; + + switch (os->type()) + { + default: + case elfcpp::SHT_PROGBITS: + break; + case elfcpp::SHT_NOBITS: + is_bss = true; + break; + case elfcpp::SHT_RELA: + case elfcpp::SHT_REL: + if (!is_write) + return ORDER_DYNAMIC_RELOCS; + break; + case elfcpp::SHT_HASH: + case elfcpp::SHT_DYNAMIC: + case elfcpp::SHT_SHLIB: + case elfcpp::SHT_DYNSYM: + case elfcpp::SHT_GNU_HASH: + case elfcpp::SHT_GNU_verdef: + case elfcpp::SHT_GNU_verneed: + case elfcpp::SHT_GNU_versym: + if (!is_write) + return ORDER_DYNAMIC_LINKER; + break; + case elfcpp::SHT_NOTE: + return is_write ? ORDER_RW_NOTE : ORDER_RO_NOTE; + } + + if ((os->flags() & elfcpp::SHF_TLS) != 0) + return is_bss ? ORDER_TLS_BSS : ORDER_TLS_DATA; + + if (!is_bss && !is_write) + { + if (is_execinstr) + { + if (strcmp(os->name(), ".init") == 0) + return ORDER_INIT; + else if (strcmp(os->name(), ".fini") == 0) + return ORDER_FINI; + } + return is_execinstr ? ORDER_TEXT : ORDER_READONLY; + } + + if (os->is_relro()) + return is_relro_local ? ORDER_RELRO_LOCAL : ORDER_RELRO; + + if (os->is_small_section()) + return is_bss ? ORDER_SMALL_BSS : ORDER_SMALL_DATA; + if (os->is_large_section()) + return is_bss ? ORDER_LARGE_BSS : ORDER_LARGE_DATA; + + return is_bss ? ORDER_BSS : ORDER_DATA; +} + // Attach output sections to segments. This is called after we have // seen all the input sections. @@ -1148,7 +1203,7 @@ Layout::attach_allocated_section_to_segment(Output_section* os) break; } - (*p)->add_output_section(os, seg_flags, true); + (*p)->add_output_section_to_load(this, os, seg_flags); break; } @@ -1158,7 +1213,7 @@ Layout::attach_allocated_section_to_segment(Output_section* os) seg_flags); if (os->is_large_data_section()) oseg->set_is_large_data_segment(); - oseg->add_output_section(os, seg_flags, true); + oseg->add_output_section_to_load(this, os, seg_flags); if (is_address_set) oseg->set_addresses(addr, addr); } @@ -1176,7 +1231,7 @@ Layout::attach_allocated_section_to_segment(Output_section* os) && (((*p)->flags() & elfcpp::PF_W) == (seg_flags & elfcpp::PF_W))) { - (*p)->add_output_section(os, seg_flags, false); + (*p)->add_output_section_to_nonload(os, seg_flags); break; } } @@ -1185,7 +1240,7 @@ Layout::attach_allocated_section_to_segment(Output_section* os) { Output_segment* oseg = this->make_output_segment(elfcpp::PT_NOTE, seg_flags); - oseg->add_output_section(os, seg_flags, false); + oseg->add_output_section_to_nonload(os, seg_flags); } } @@ -1195,7 +1250,7 @@ Layout::attach_allocated_section_to_segment(Output_section* os) { if (this->tls_segment_ == NULL) this->make_output_segment(elfcpp::PT_TLS, seg_flags); - this->tls_segment_->add_output_section(os, seg_flags, false); + this->tls_segment_->add_output_section_to_nonload(os, seg_flags); } // If -z relro is in effect, and we see a relro section, we create a @@ -1205,7 +1260,7 @@ Layout::attach_allocated_section_to_segment(Output_section* os) 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, false); + this->relro_segment_->add_output_section_to_nonload(os, seg_flags); } } @@ -1221,8 +1276,8 @@ Layout::make_output_section_for_script( if (section_type == Script_sections::ST_NOLOAD) sh_flags = 0; Output_section* os = this->make_output_section(name, elfcpp::SHT_PROGBITS, - sh_flags, false, - false, false, false, false); + sh_flags, ORDER_INVALID, + false); os->set_found_in_sections_clause(); if (section_type == Script_sections::ST_NOLOAD) os->set_is_noload(); @@ -1294,8 +1349,8 @@ Layout::create_initial_dynamic_sections(Symbol_table* symtab) elfcpp::SHT_DYNAMIC, (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE), - false, false, true, - true, false, false); + false, ORDER_RELRO, + true); this->dynamic_symbol_ = symtab->define_in_output_data("_DYNAMIC", NULL, Symbol_table::PREDEFINED, @@ -1980,12 +2035,15 @@ Layout::create_note(const char* name, int note_type, memcpy(buffer + 3 * (size / 8), name, namesz); elfcpp::Elf_Xword flags = 0; + Output_section_order order = ORDER_INVALID; if (allocate) - flags = elfcpp::SHF_ALLOC; + { + flags = elfcpp::SHF_ALLOC; + order = ORDER_RO_NOTE; + } Output_section* os = this->choose_output_section(NULL, section_name, elfcpp::SHT_NOTE, - flags, false, false, - false, false, false, false); + flags, false, order, false); if (os == NULL) return NULL; @@ -2064,8 +2122,8 @@ Layout::create_executable_stack_info() elfcpp::Elf_Xword flags = 0; if (is_stack_executable) flags |= elfcpp::SHF_EXECINSTR; - this->make_output_section(name, elfcpp::SHT_PROGBITS, flags, false, - false, false, false, false); + this->make_output_section(name, elfcpp::SHT_PROGBITS, flags, + ORDER_INVALID, false); } else { @@ -2226,7 +2284,7 @@ Layout::create_incremental_info_sections() Output_section* inputs_os = this->make_output_section(incremental_inputs_name, elfcpp::SHT_GNU_INCREMENTAL_INPUTS, 0, - false, false, false, false, false); + ORDER_INVALID, false); Output_section_data* posd = this->incremental_inputs_->create_incremental_inputs_section_data(); inputs_os->add_output_section_data(posd); @@ -2236,8 +2294,8 @@ Layout::create_incremental_info_sections() this->namepool_.add(".gnu_incremental_strtab", false, NULL); Output_section* strtab_os = this->make_output_section(incremental_strtab_name, elfcpp::SHT_STRTAB, - 0, false, false, - false, false, false); + 0, ORDER_INVALID, + false); Output_data_strtab* strtab_data = new Output_data_strtab(this->incremental_inputs_->get_stringpool()); strtab_os->add_output_section_data(strtab_data); @@ -2857,8 +2915,8 @@ Layout::create_symtab_sections(const Input_objects* input_objects, const char* symtab_name = this->namepool_.add(".symtab", false, NULL); Output_section* osymtab = this->make_output_section(symtab_name, elfcpp::SHT_SYMTAB, - 0, false, false, - false, false, false); + 0, ORDER_INVALID, + false); this->symtab_section_ = osymtab; Output_section_data* pos = new Output_data_fixed_space(off - startoff, @@ -2879,8 +2937,8 @@ Layout::create_symtab_sections(const Input_objects* input_objects, false, NULL); Output_section* osymtab_xindex = this->make_output_section(symtab_xindex_name, - elfcpp::SHT_SYMTAB_SHNDX, 0, false, - false, false, false, false); + elfcpp::SHT_SYMTAB_SHNDX, 0, + ORDER_INVALID, false); size_t symcount = (off - startoff) / symsize; this->symtab_xindex_ = new Output_symtab_xindex(symcount); @@ -2902,8 +2960,8 @@ Layout::create_symtab_sections(const Input_objects* input_objects, const char* strtab_name = this->namepool_.add(".strtab", false, NULL); Output_section* ostrtab = this->make_output_section(strtab_name, elfcpp::SHT_STRTAB, - 0, false, false, - false, false, false); + 0, ORDER_INVALID, + false); Output_section_data* pstr = new Output_data_strtab(&this->sympool_); ostrtab->add_output_section_data(pstr); @@ -2931,8 +2989,7 @@ Layout::create_shstrtab() const char* name = this->namepool_.add(".shstrtab", false, NULL); Output_section* os = this->make_output_section(name, elfcpp::SHT_STRTAB, 0, - false, false, false, false, - false); + ORDER_INVALID, false); if (strcmp(parameters->options().compress_debug_sections(), "none") != 0) { @@ -3049,8 +3106,9 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects, Output_section* dynsym = this->choose_output_section(NULL, ".dynsym", elfcpp::SHT_DYNSYM, elfcpp::SHF_ALLOC, - false, false, true, - false, false, false); + false, + ORDER_DYNAMIC_LINKER, + false); Output_section_data* odata = new Output_data_fixed_space(index * symsize, align, @@ -3080,7 +3138,7 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects, this->choose_output_section(NULL, ".dynsym_shndx", elfcpp::SHT_SYMTAB_SHNDX, elfcpp::SHF_ALLOC, - false, false, true, false, false, false); + false, ORDER_DYNAMIC_LINKER, false); this->dynsym_xindex_ = new Output_symtab_xindex(index); @@ -3103,8 +3161,9 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects, Output_section* dynstr = this->choose_output_section(NULL, ".dynstr", elfcpp::SHT_STRTAB, elfcpp::SHF_ALLOC, - false, false, true, - false, false, false); + false, + ORDER_DYNAMIC_LINKER, + false); Output_section_data* strdata = new Output_data_strtab(&this->dynpool_); dynstr->add_output_section_data(strdata); @@ -3127,12 +3186,10 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects, Dynobj::create_elf_hash_table(*pdynamic_symbols, local_symcount, &phash, &hashlen); - Output_section* hashsec = this->choose_output_section(NULL, ".hash", - elfcpp::SHT_HASH, - elfcpp::SHF_ALLOC, - false, false, true, - false, false, - false); + Output_section* hashsec = + this->choose_output_section(NULL, ".hash", elfcpp::SHT_HASH, + elfcpp::SHF_ALLOC, false, + ORDER_DYNAMIC_LINKER, false); Output_section_data* hashdata = new Output_data_const_buffer(phash, hashlen, @@ -3154,12 +3211,10 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects, Dynobj::create_gnu_hash_table(*pdynamic_symbols, local_symcount, &phash, &hashlen); - Output_section* hashsec = this->choose_output_section(NULL, ".gnu.hash", - elfcpp::SHT_GNU_HASH, - elfcpp::SHF_ALLOC, - false, false, true, - false, false, - false); + Output_section* hashsec = + this->choose_output_section(NULL, ".gnu.hash", elfcpp::SHT_GNU_HASH, + elfcpp::SHF_ALLOC, false, + ORDER_DYNAMIC_LINKER, false); Output_section_data* hashdata = new Output_data_const_buffer(phash, hashlen, @@ -3262,8 +3317,9 @@ Layout::sized_create_version_sections( Output_section* vsec = this->choose_output_section(NULL, ".gnu.version", elfcpp::SHT_GNU_versym, elfcpp::SHF_ALLOC, - false, false, true, - false, false, false); + false, + ORDER_DYNAMIC_LINKER, + false); unsigned char* vbuf; unsigned int vsize; @@ -3288,8 +3344,7 @@ Layout::sized_create_version_sections( vdsec= this->choose_output_section(NULL, ".gnu.version_d", elfcpp::SHT_GNU_verdef, elfcpp::SHF_ALLOC, - false, false, true, false, false, - false); + false, ORDER_DYNAMIC_LINKER, false); unsigned char* vdbuf; unsigned int vdsize; @@ -3314,8 +3369,7 @@ Layout::sized_create_version_sections( vnsec = this->choose_output_section(NULL, ".gnu.version_r", elfcpp::SHT_GNU_verneed, elfcpp::SHF_ALLOC, - false, false, true, false, false, - false); + false, ORDER_DYNAMIC_LINKER, false); unsigned char* vnbuf; unsigned int vnsize; @@ -3355,15 +3409,15 @@ Layout::create_interp(const Target* target) Output_section* osec = this->choose_output_section(NULL, ".interp", elfcpp::SHT_PROGBITS, elfcpp::SHF_ALLOC, - false, true, true, - false, false, false); + false, ORDER_INTERP, + false); 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, false); + oseg->add_output_section_to_nonload(osec, elfcpp::PF_R); } } @@ -3471,9 +3525,8 @@ Layout::finish_dynamic_section(const Input_objects* input_objects, Output_segment* oseg = this->make_output_segment(elfcpp::PT_DYNAMIC, (elfcpp::PF_R | elfcpp::PF_W)); - oseg->add_output_section(this->dynamic_section_, - elfcpp::PF_R | elfcpp::PF_W, - false); + oseg->add_output_section_to_nonload(this->dynamic_section_, + elfcpp::PF_R | elfcpp::PF_W); } Output_data_dynamic* const odyn = this->dynamic_data_; @@ -3571,7 +3624,7 @@ Layout::finish_dynamic_section(const Input_objects* input_objects, ++p) { if (((*p)->flags() & elfcpp::PF_W) == 0 - && (*p)->dynamic_reloc_count() > 0) + && (*p)->has_dynamic_reloc()) { have_textrel = true; break; @@ -3590,7 +3643,7 @@ Layout::finish_dynamic_section(const Input_objects* input_objects, { if (((*p)->flags() & elfcpp::SHF_ALLOC) != 0 && ((*p)->flags() & elfcpp::SHF_WRITE) == 0 - && ((*p)->dynamic_reloc_count() > 0)) + && ((*p)->has_dynamic_reloc())) { have_textrel = true; break; diff --git a/gold/layout.h b/gold/layout.h index 60ae114..b5b266c 100644 --- a/gold/layout.h +++ b/gold/layout.h @@ -286,6 +286,107 @@ class Kept_section } u_; }; +// The ordering for output sections. This controls how output +// sections are ordered within a PT_LOAD output segment. + +enum Output_section_order +{ + // Unspecified. Used for non-load segments. Also used for the file + // and segment headers. + ORDER_INVALID, + + // The PT_INTERP section should come first, so that the dynamic + // linker can pick it up quickly. + ORDER_INTERP, + + // Loadable read-only note sections come next so that the PT_NOTE + // segment is on the first page of the executable. + ORDER_RO_NOTE, + + // Put read-only sections used by the dynamic linker early in the + // executable to minimize paging. + ORDER_DYNAMIC_LINKER, + + // Put reloc sections used by the dynamic linker after other + // sections used by the dynamic linker; otherwise, objcopy and strip + // get confused. + ORDER_DYNAMIC_RELOCS, + + // Put the PLT reloc section after the other dynamic relocs; + // otherwise, prelink gets foncused. + ORDER_DYNAMIC_PLT_RELOCS, + + // The .init section. + ORDER_INIT, + + // The PLT. + ORDER_PLT, + + // The regular text sections. + ORDER_TEXT, + + // The .fini section. + ORDER_FINI, + + // The read-only sections. + ORDER_READONLY, + + // The exception frame sections. + ORDER_EHFRAME, + + // The TLS sections come first in the data section. + ORDER_TLS_DATA, + ORDER_TLS_BSS, + + // Local RELRO (read-only after relocation) sections come before + // non-local RELRO sections. This data will be fully resolved by + // the prelinker. + ORDER_RELRO_LOCAL, + + // Non-local RELRO sections are grouped together after local RELRO + // sections. All RELRO sections must be adjacent so that they can + // all be put into a PT_GNU_RELRO segment. + ORDER_RELRO, + + // We permit marking exactly one output section as the last RELRO + // section. We do this so that the read-only GOT can be adjacent to + // the writable GOT. + ORDER_RELRO_LAST, + + // Similarly, we permit marking exactly one output section as the + // first non-RELRO section. + ORDER_NON_RELRO_FIRST, + + // The regular data sections come after the RELRO sections. + ORDER_DATA, + + // Large data sections normally go in large data segments. + ORDER_LARGE_DATA, + + // Group writable notes so that we can have a single PT_NOTE + // segment. + ORDER_RW_NOTE, + + // The small data sections must be at the end of the data sections, + // so that they can be adjacent to the small BSS sections. + ORDER_SMALL_DATA, + + // The BSS sections start here. + + // The small BSS sections must be at the start of the BSS sections, + // so that they can be adjacent to the small data sections. + ORDER_SMALL_BSS, + + // The regular BSS sections. + ORDER_BSS, + + // The large BSS sections come after the other BSS sections. + ORDER_LARGE_BSS, + + // Maximum value. + ORDER_MAX +}; + // This class handles the details of laying out input sections. class Layout @@ -371,18 +472,14 @@ class Layout 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. IS_DYNAMIC_LINKER_SECTION - // is true for sections which are used by the dynamic linker, such - // as dynamic reloc sections. IS_RELRO is true for relro sections. - // IS_LAST_RELRO is true for the last relro section. - // IS_FIRST_NON_RELRO is true for the first section after the relro - // sections. + // special sections like the GOT section. ORDER is where the + // section should wind up in the output segment. IS_RELRO is true + // for relro sections. Output_section* add_output_section_data(const char* name, elfcpp::Elf_Word type, elfcpp::Elf_Xword flags, - Output_section_data*, bool is_dynamic_linker_section, - bool is_relro, bool is_last_relro, - bool is_first_non_relro); + Output_section_data*, Output_section_order order, + bool is_relro); // Increase the size of the relro segment by this much. void @@ -788,29 +885,29 @@ class Layout Output_section* get_output_section(const char* name, Stringpool::Key name_key, elfcpp::Elf_Word type, elfcpp::Elf_Xword flags, - bool is_interp, bool is_dynamic_linker_section, - bool is_relro, bool is_last_relro, - bool is_first_non_relro); + Output_section_order order, bool is_relro); // 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_interp, - bool is_dynamic_linker_section, bool is_relro, - bool is_last_relro, bool is_first_non_relro); + bool is_input_section, Output_section_order order, + bool is_relro); // Create a new Output_section. Output_section* make_output_section(const char* name, elfcpp::Elf_Word type, - elfcpp::Elf_Xword flags, bool is_interp, - bool is_dynamic_linker_section, bool is_relro, - bool is_last_relro, bool is_first_non_relro); + elfcpp::Elf_Xword flags, Output_section_order order, + bool is_relro); // Attach a section to a segment. void attach_section_to_segment(Output_section*); + // Get section order. + Output_section_order + default_section_order(Output_section*, bool is_relro_local); + // Attach an allocated section to a segment. void attach_allocated_section_to_segment(Output_section*); diff --git a/gold/output.cc b/gold/output.cc index 506edf7..55080a1 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -1917,6 +1917,7 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type, info_(0), type_(type), flags_(flags), + order_(ORDER_INVALID), out_shndx_(-1U), symtab_index_(0), dynsym_index_(0), @@ -1938,13 +1939,8 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type, must_sort_attached_input_sections_(false), attached_input_sections_are_sorted_(false), is_relro_(false), - is_relro_local_(false), - is_last_relro_(false), - is_first_non_relro_(false), is_small_section_(false), is_large_section_(false), - is_interp_(false), - is_dynamic_linker_section_(false), generate_code_fills_at_write_(false), is_entsize_zero_(false), section_offsets_need_adjustment_(false), @@ -3409,9 +3405,7 @@ Output_section::print_merge_stats() // Output segment methods. Output_segment::Output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags) - : output_data_(), - output_bss_(), - vaddr_(0), + : vaddr_(0), paddr_(0), memsz_(0), max_align_(0), @@ -3430,293 +3424,64 @@ Output_segment::Output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags) this->flags_ = elfcpp::PF_R; } -// Add an Output_section to an Output_segment. +// Add an Output_section to a PT_LOAD Output_segment. void -Output_segment::add_output_section(Output_section* os, - elfcpp::Elf_Word seg_flags, - bool do_sort) +Output_segment::add_output_section_to_load(Layout* layout, + Output_section* os, + elfcpp::Elf_Word seg_flags) { + gold_assert(this->type() == elfcpp::PT_LOAD); gold_assert((os->flags() & elfcpp::SHF_ALLOC) != 0); gold_assert(!this->is_max_align_known_); gold_assert(os->is_large_data_section() == this->is_large_data_segment()); - gold_assert(this->type() == elfcpp::PT_LOAD || !do_sort); this->update_flags_for_output_section(seg_flags); - Output_segment::Output_data_list* pdl; - if (os->type() == elfcpp::SHT_NOBITS) - pdl = &this->output_bss_; + // We don't want to change the ordering if we have a linker script + // with a SECTIONS clause. + Output_section_order order = os->order(); + if (layout->script_options()->saw_sections_clause()) + order = static_cast<Output_section_order>(0); else - pdl = &this->output_data_; + gold_assert(order != ORDER_INVALID); - // 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. - if (os->type() == elfcpp::SHT_NOTE && !pdl->empty()) - { - Output_segment::Output_data_list::iterator p = pdl->end(); - do - { - --p; - if ((*p)->is_section_type(elfcpp::SHT_NOTE)) - { - ++p; - pdl->insert(p, os); - return; - } - } - while (p != pdl->begin()); - } - - // Similarly, so that PT_TLS segments will work, we need to group - // SHF_TLS sections. An SHF_TLS/SHT_NOBITS section is a special - // 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. - if (this->type_ != elfcpp::PT_TLS - && (os->flags() & elfcpp::SHF_TLS) != 0) - { - pdl = &this->output_data_; - if (!pdl->empty()) - { - bool nobits = os->type() == elfcpp::SHT_NOBITS; - bool sawtls = false; - Output_segment::Output_data_list::iterator p = pdl->end(); - gold_assert(p != pdl->begin()); - do - { - --p; - bool insert; - if ((*p)->is_section_flag_set(elfcpp::SHF_TLS)) - { - sawtls = true; - // Put a NOBITS section after the first TLS section. - // Put a PROGBITS section after the first - // TLS/PROGBITS section. - insert = nobits || !(*p)->is_section_type(elfcpp::SHT_NOBITS); - } - else - { - // If we've gone past the TLS sections, but we've - // seen a TLS section, then we need to insert this - // section now. - insert = sawtls; - } - - if (insert) - { - ++p; - pdl->insert(p, os); - return; - } - } - while (p != pdl->begin()); - } - - // There are no TLS sections yet; put this one at the requested - // location in the section list. - } - - if (do_sort) - { - // For the PT_GNU_RELRO segment, we need to group relro - // sections, and we need to put them before any non-relro - // sections. Any relro local sections go before relro non-local - // sections. One section may be marked as the last relro - // section. - if (os->is_relro()) - { - gold_assert(pdl == &this->output_data_); - Output_segment::Output_data_list::iterator p; - for (p = pdl->begin(); p != pdl->end(); ++p) - { - if (!(*p)->is_section()) - break; - - Output_section* pos = (*p)->output_section(); - if (!pos->is_relro() - || (os->is_relro_local() && !pos->is_relro_local()) - || (!os->is_last_relro() && pos->is_last_relro())) - break; - } - - pdl->insert(p, os); - return; - } + this->output_lists_[order].push_back(os); +} - // One section may be marked as the first section which follows - // the relro sections. - if (os->is_first_non_relro()) - { - gold_assert(pdl == &this->output_data_); - Output_segment::Output_data_list::iterator p; - for (p = pdl->begin(); p != pdl->end(); ++p) - { - if (!(*p)->is_section()) - break; +// Add an Output_section to a non-PT_LOAD Output_segment. - Output_section* pos = (*p)->output_section(); - if (!pos->is_relro()) - break; - } +void +Output_segment::add_output_section_to_nonload(Output_section* os, + elfcpp::Elf_Word seg_flags) +{ + gold_assert(this->type() != elfcpp::PT_LOAD); + gold_assert((os->flags() & elfcpp::SHF_ALLOC) != 0); + gold_assert(!this->is_max_align_known_); - pdl->insert(p, os); - return; - } - } + this->update_flags_for_output_section(seg_flags); - // Small data sections go at the end of the list of data sections. - // If OS is not small, and there are small sections, we have to - // insert it before the first small section. - if (os->type() != elfcpp::SHT_NOBITS - && !os->is_small_section() - && !pdl->empty() - && pdl->back()->is_section() - && pdl->back()->output_section()->is_small_section()) - { - for (Output_segment::Output_data_list::iterator p = pdl->begin(); - p != pdl->end(); - ++p) - { - if ((*p)->is_section() - && (*p)->output_section()->is_small_section()) - { - pdl->insert(p, os); - return; - } - } - gold_unreachable(); - } + this->output_lists_[0].push_back(os); +} - // A small BSS section goes at the start of the BSS sections, after - // other small BSS sections. - if (os->type() == elfcpp::SHT_NOBITS && os->is_small_section()) - { - for (Output_segment::Output_data_list::iterator p = pdl->begin(); - p != pdl->end(); - ++p) - { - if (!(*p)->is_section() - || !(*p)->output_section()->is_small_section()) - { - pdl->insert(p, os); - return; - } - } - } +// Remove an Output_section from this segment. It is an error if it +// is not present. - // A large BSS section goes at the end of the BSS sections, which - // means that one that is not large must come before the first large - // one. - if (os->type() == elfcpp::SHT_NOBITS - && !os->is_large_section() - && !pdl->empty() - && pdl->back()->is_section() - && pdl->back()->output_section()->is_large_section()) +void +Output_segment::remove_output_section(Output_section* os) +{ + for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i) { - for (Output_segment::Output_data_list::iterator p = pdl->begin(); - p != pdl->end(); - ++p) + Output_data_list* pdl = &this->output_lists_[i]; + for (Output_data_list::iterator p = pdl->begin(); p != pdl->end(); ++p) { - if ((*p)->is_section() - && (*p)->output_section()->is_large_section()) + if (*p == os) { - pdl->insert(p, os); + pdl->erase(p); return; } } - 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); - return; - } - - // 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); -} - -// Remove an Output_section from this segment. It is an error if it -// is not present. - -void -Output_segment::remove_output_section(Output_section* os) -{ - // We only need this for SHT_PROGBITS. - gold_assert(os->type() == elfcpp::SHT_PROGBITS); - for (Output_data_list::iterator p = this->output_data_.begin(); - p != this->output_data_.end(); - ++p) - { - if (*p == os) - { - this->output_data_.erase(p); - return; - } - } gold_unreachable(); } @@ -3727,7 +3492,30 @@ void Output_segment::add_initial_output_data(Output_data* od) { gold_assert(!this->is_max_align_known_); - this->output_data_.push_front(od); + Output_data_list::iterator p = this->output_lists_[0].begin(); + this->output_lists_[0].insert(p, od); +} + +// Return true if this segment has any sections which hold actual +// data, rather than being a BSS section. + +bool +Output_segment::has_any_data_sections() const +{ + for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i) + { + const Output_data_list* pdl = &this->output_lists_[i]; + for (Output_data_list::const_iterator p = pdl->begin(); + p != pdl->end(); + ++p) + { + if (!(*p)->is_section()) + return true; + if ((*p)->output_section()->type() != elfcpp::SHT_NOBITS) + return true; + } + } + return false; } // Return whether the first data section is a relro section. @@ -3735,9 +3523,16 @@ Output_segment::add_initial_output_data(Output_data* od) bool Output_segment::is_first_section_relro() const { - return (!this->output_data_.empty() - && this->output_data_.front()->is_section() - && this->output_data_.front()->output_section()->is_relro()); + for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i) + { + const Output_data_list* pdl = &this->output_lists_[i]; + if (!pdl->empty()) + { + Output_data* p = pdl->front(); + return p->is_section() && p->output_section()->is_relro(); + } + } + return false; } // Return the maximum alignment of the Output_data in Output_segment. @@ -3747,16 +3542,13 @@ Output_segment::maximum_alignment() { if (!this->is_max_align_known_) { - uint64_t addralign; - - addralign = Output_segment::maximum_alignment_list(&this->output_data_); - if (addralign > this->max_align_) - this->max_align_ = addralign; - - addralign = Output_segment::maximum_alignment_list(&this->output_bss_); - if (addralign > this->max_align_) - this->max_align_ = addralign; - + for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i) + { + const Output_data_list* pdl = &this->output_lists_[i]; + uint64_t addralign = Output_segment::maximum_alignment_list(pdl); + if (addralign > this->max_align_) + this->max_align_ = addralign; + } this->is_max_align_known_ = true; } @@ -3780,26 +3572,28 @@ Output_segment::maximum_alignment_list(const Output_data_list* pdl) return ret; } -// Return the number of dynamic relocs applied to this segment. +// Return whether this segment has any dynamic relocs. -unsigned int -Output_segment::dynamic_reloc_count() const +bool +Output_segment::has_dynamic_reloc() const { - return (this->dynamic_reloc_count_list(&this->output_data_) - + this->dynamic_reloc_count_list(&this->output_bss_)); + for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i) + if (this->has_dynamic_reloc_list(&this->output_lists_[i])) + return true; + return false; } -// Return the number of dynamic relocs applied to an Output_data_list. +// Return whether this Output_data_list has any dynamic relocs. -unsigned int -Output_segment::dynamic_reloc_count_list(const Output_data_list* pdl) const +bool +Output_segment::has_dynamic_reloc_list(const Output_data_list* pdl) const { - unsigned int count = 0; for (Output_data_list::const_iterator p = pdl->begin(); p != pdl->end(); ++p) - count += (*p)->dynamic_reloc_count(); - return count; + if ((*p)->has_dynamic_reloc()) + return true; + return false; } // Set the section addresses for an Output_segment. If RESET is true, @@ -3827,26 +3621,30 @@ Output_segment::set_section_addresses(const Layout* layout, bool reset, { uint64_t relro_size = 0; off_t off = *poff; - for (Output_data_list::iterator p = this->output_data_.begin(); - p != this->output_data_.end(); - ++p) + for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i) { - if (!(*p)->is_section()) - break; - Output_section* pos = (*p)->output_section(); - if (!pos->is_relro()) - break; - gold_assert(!(*p)->is_section_flag_set(elfcpp::SHF_TLS)); - if ((*p)->is_address_valid()) - relro_size += (*p)->data_size(); - else + Output_data_list* pdl = &this->output_lists_[i]; + Output_data_list::iterator p; + for (p = pdl->begin(); p != pdl->end(); ++p) { - // FIXME: This could be faster. - (*p)->set_address_and_file_offset(addr + relro_size, - off + relro_size); - relro_size += (*p)->data_size(); - (*p)->reset_address_and_file_offset(); + if (!(*p)->is_section()) + break; + Output_section* pos = (*p)->output_section(); + if (!pos->is_relro()) + break; + if ((*p)->is_address_valid()) + relro_size += (*p)->data_size(); + else + { + // FIXME: This could be faster. + (*p)->set_address_and_file_offset(addr + relro_size, + off + relro_size); + relro_size += (*p)->data_size(); + (*p)->reset_address_and_file_offset(); + } } + if (p != pdl->end()) + break; } relro_size += increase_relro; @@ -3877,16 +3675,21 @@ Output_segment::set_section_addresses(const Layout* layout, bool reset, this->offset_ = orig_off; - addr = this->set_section_list_addresses(layout, reset, &this->output_data_, - addr, poff, pshndx, &in_tls); - this->filesz_ = *poff - orig_off; - - off_t off = *poff; + off_t off = 0; + uint64_t ret; + for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i) + { + addr = this->set_section_list_addresses(layout, reset, + &this->output_lists_[i], + addr, poff, pshndx, &in_tls); + if (i < static_cast<int>(ORDER_SMALL_BSS)) + { + this->filesz_ = *poff - orig_off; + off = *poff; + } - uint64_t ret = this->set_section_list_addresses(layout, reset, - &this->output_bss_, - addr, poff, pshndx, - &in_tls); + ret = addr; + } // If the last section was a TLS section, align upward to the // alignment of the TLS segment, so that the overall size of the TLS @@ -4029,7 +3832,11 @@ Output_segment::set_offset(unsigned int increase) gold_assert(!this->are_addresses_set_); - if (this->output_data_.empty() && this->output_bss_.empty()) + // A non-load section only uses output_lists_[0]. + + Output_data_list* pdl = &this->output_lists_[0]; + + if (pdl->empty()) { gold_assert(increase == 0); this->vaddr_ = 0; @@ -4042,13 +3849,31 @@ Output_segment::set_offset(unsigned int increase) return; } - // Find the first and last section by address. The sections may - // have been sorted for the PT_LOAD segment. + // Find the first and last section by address. const Output_data* first = NULL; const Output_data* last_data = NULL; const Output_data* last_bss = NULL; - this->find_first_and_last_list(&this->output_data_, &first, &last_data); - this->find_first_and_last_list(&this->output_bss_, &first, &last_bss); + for (Output_data_list::const_iterator p = pdl->begin(); + p != pdl->end(); + ++p) + { + if (first == NULL + || (*p)->address() < first->address() + || ((*p)->address() == first->address() + && (*p)->data_size() < first->data_size())) + first = *p; + const Output_data** plast; + if ((*p)->is_section() + && (*p)->output_section()->type() == elfcpp::SHT_NOBITS) + plast = &last_bss; + else + plast = &last_data; + if (*plast == NULL + || (*p)->address() > (*plast)->address() + || ((*p)->address() == (*plast)->address() + && (*p)->data_size() > (*plast)->data_size())) + *plast = *p; + } this->vaddr_ = first->address(); this->paddr_ = (first->has_load_address() @@ -4057,7 +3882,7 @@ Output_segment::set_offset(unsigned int increase) this->are_addresses_set_ = true; this->offset_ = first->offset(); - if (this->output_data_.empty()) + if (last_data == NULL) this->filesz_ = 0; else this->filesz_ = (last_data->address() @@ -4083,37 +3908,6 @@ Output_segment::set_offset(unsigned int increase) } } -// Look through a list of Output_data objects and find the first and -// last by address. - -void -Output_segment::find_first_and_last_list(const Output_data_list* pdl, - const Output_data** pfirst, - const Output_data** plast) const -{ - const Output_data* first = *pfirst; - const Output_data* last = *plast; - for (Output_data_list::const_iterator p = pdl->begin(); p != pdl->end(); ++p) - { - if (first == NULL - || (*p)->address() < first->address() - || ((*p)->address() == first->address() - && (*p)->data_size() < first->data_size())) - { - first = *p; - *pfirst = first; - } - if (last == NULL - || (*p)->address() > last->address() - || ((*p)->address() == last->address() - && (*p)->data_size() > last->data_size())) - { - last = *p; - *plast = last; - } - } -} - // Set the TLS offsets of the sections in the PT_TLS segment. void @@ -4121,34 +3915,30 @@ Output_segment::set_tls_offsets() { gold_assert(this->type_ == elfcpp::PT_TLS); - for (Output_data_list::iterator p = this->output_data_.begin(); - p != this->output_data_.end(); - ++p) - (*p)->set_tls_offset(this->vaddr_); - - for (Output_data_list::iterator p = this->output_bss_.begin(); - p != this->output_bss_.end(); + for (Output_data_list::iterator p = this->output_lists_[0].begin(); + p != this->output_lists_[0].end(); ++p) (*p)->set_tls_offset(this->vaddr_); } -// Return the address of the first section. +// Return the load address of the first section. uint64_t Output_segment::first_section_load_address() const { - for (Output_data_list::const_iterator p = this->output_data_.begin(); - p != this->output_data_.end(); - ++p) - if ((*p)->is_section()) - return (*p)->has_load_address() ? (*p)->load_address() : (*p)->address(); - - for (Output_data_list::const_iterator p = this->output_bss_.begin(); - p != this->output_bss_.end(); - ++p) - if ((*p)->is_section()) - return (*p)->has_load_address() ? (*p)->load_address() : (*p)->address(); - + for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i) + { + const Output_data_list* pdl = &this->output_lists_[i]; + for (Output_data_list::const_iterator p = pdl->begin(); + p != pdl->end(); + ++p) + { + if ((*p)->is_section()) + return ((*p)->has_load_address() + ? (*p)->load_address() + : (*p)->address()); + } + } gold_unreachable(); } @@ -4157,8 +3947,10 @@ Output_segment::first_section_load_address() const unsigned int Output_segment::output_section_count() const { - return (this->output_section_count_list(&this->output_data_) - + this->output_section_count_list(&this->output_bss_)); + unsigned int ret = 0; + for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i) + ret += this->output_section_count_list(&this->output_lists_[i]); + return ret; } // Return the number of Output_sections in an Output_data_list. @@ -4186,18 +3978,9 @@ Output_segment::section_with_lowest_load_address() const { Output_section* found = NULL; uint64_t found_lma = 0; - this->lowest_load_address_in_list(&this->output_data_, &found, &found_lma); - - Output_section* found_data = found; - this->lowest_load_address_in_list(&this->output_bss_, &found, &found_lma); - if (found != found_data && found_data != NULL) - { - gold_error(_("nobits section %s may not precede progbits section %s " - "in same segment"), - found->name(), found_data->name()); - return NULL; - } - + for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i) + this->lowest_load_address_in_list(&this->output_lists_[i], &found, + &found_lma); return found; } @@ -4257,12 +4040,15 @@ Output_segment::write_section_headers(const Layout* layout, if (this->type_ != elfcpp::PT_LOAD) return v; - v = this->write_section_headers_list<size, big_endian>(layout, secnamepool, - &this->output_data_, - v, pshndx); - v = this->write_section_headers_list<size, big_endian>(layout, secnamepool, - &this->output_bss_, - v, pshndx); + for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i) + { + const Output_data_list* pdl = &this->output_lists_[i]; + v = this->write_section_headers_list<size, big_endian>(layout, + secnamepool, + pdl, + v, pshndx); + } + return v; } @@ -4299,8 +4085,8 @@ Output_segment::print_sections_to_mapfile(Mapfile* mapfile) const { if (this->type() != elfcpp::PT_LOAD) return; - this->print_section_list_to_mapfile(mapfile, &this->output_data_); - this->print_section_list_to_mapfile(mapfile, &this->output_bss_); + for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i) + this->print_section_list_to_mapfile(mapfile, &this->output_lists_[i]); } // Print an output section list to the map file. diff --git a/gold/output.h b/gold/output.h index b07c4ad3..78c51ce 100644 --- a/gold/output.h +++ b/gold/output.h @@ -56,7 +56,7 @@ class Output_data : address_(0), data_size_(0), offset_(-1), is_address_valid_(false), is_data_size_valid_(false), is_offset_valid_(false), is_data_size_fixed_(false), - dynamic_reloc_count_(0) + has_dynamic_reloc_(false) { } virtual @@ -233,15 +233,15 @@ class Output_data is_layout_complete() { return Output_data::allocated_sizes_are_fixed; } - // Count the number of dynamic relocations applied to this section. + // Note that a dynamic reloc has been applied to this data. void add_dynamic_reloc() - { ++this->dynamic_reloc_count_; } + { this->has_dynamic_reloc_ = true; } - // Return the number of dynamic relocations applied to this section. - unsigned int - dynamic_reloc_count() const - { return this->dynamic_reloc_count_; } + // Return whether a dynamic reloc has been applied. + bool + has_dynamic_reloc() const + { return this->has_dynamic_reloc_; } // Whether the address is valid. bool @@ -424,15 +424,15 @@ class Output_data // File offset of contents in output file. off_t offset_; // Whether address_ is valid. - bool is_address_valid_; + bool is_address_valid_ : 1; // Whether data_size_ is valid. - bool is_data_size_valid_; + bool is_data_size_valid_ : 1; // Whether offset_ is valid. - bool is_offset_valid_; + bool is_offset_valid_ : 1; // Whether data size is fixed. - bool is_data_size_fixed_; - // Count of dynamic relocations applied to this section. - unsigned int dynamic_reloc_count_; + bool is_data_size_fixed_ : 1; + // Whether any dynamic relocs have been applied to this section. + bool has_dynamic_reloc_ : 1; }; // Output the section headers. @@ -2761,6 +2761,17 @@ class Output_section : public Output_data set_must_sort_attached_input_sections() { this->must_sort_attached_input_sections_ = true; } + // Get the order in which this section appears in the PT_LOAD output + // segment. + Output_section_order + order() const + { return this->order_; } + + // Set the order for this section. + void + set_order(Output_section_order order) + { this->order_ = order; } + // Return whether this section holds relro data--data which has // dynamic relocations but which may be marked read-only after the // dynamic relocations have been completed. @@ -2778,46 +2789,6 @@ class Output_section : public Output_data clear_is_relro() { this->is_relro_ = false; } - // True if this section holds relro local data--relro data for which - // the dynamic relocations are all RELATIVE relocations. - bool - is_relro_local() const - { return this->is_relro_local_; } - - // Record that this section holds relro local data. - void - set_is_relro_local() - { this->is_relro_local_ = true; } - - // True if this must be the last relro section. - bool - is_last_relro() const - { return this->is_last_relro_; } - - // Record that this must be the last relro section. - void - set_is_last_relro() - { - gold_assert(this->is_relro_); - this->is_last_relro_ = true; - } - - // True if this must be the first section following the relro sections. - bool - is_first_non_relro() const - { - gold_assert(!this->is_relro_); - return this->is_first_non_relro_; - } - - // Record that this must be the first non-relro section. - void - set_is_first_non_relro() - { - gold_assert(!this->is_relro_); - this->is_first_non_relro_ = true; - } - // True if this is a small section: a section which holds small // variables. bool @@ -2845,27 +2816,6 @@ class Output_section : public Output_data 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 @@ -3707,6 +3657,8 @@ class Output_section : public Output_data const elfcpp::Elf_Word type_; // The section flags. elfcpp::Elf_Xword flags_; + // The order of this section in the output segment. + Output_section_order order_; // The section index. unsigned int out_shndx_; // If there is a STT_SECTION for this output section in the normal @@ -3774,21 +3726,10 @@ class Output_section : public Output_data bool attached_input_sections_are_sorted_ : 1; // True if this section holds relro data. bool is_relro_ : 1; - // True if this section holds relro local data. - bool is_relro_local_ : 1; - // True if this must be the last relro section. - bool is_last_relro_ : 1; - // True if this must be the first section after the relro sections. - bool is_first_non_relro_ : 1; // True if this is a small section. 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; // Whether the entry size field should be zero. @@ -3874,12 +3815,17 @@ class Output_segment uint64_t maximum_alignment(); - // 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. + // Add the Output_section OS to this PT_LOAD segment. SEG_FLAGS is + // the segment flags to use. + void + add_output_section_to_load(Layout* layout, Output_section* os, + elfcpp::Elf_Word seg_flags); + + // Add the Output_section OS to this non-PT_LOAD segment. SEG_FLAGS + // is the segment flags to use. void - add_output_section(Output_section* os, elfcpp::Elf_Word seg_flags, - bool do_sort); + add_output_section_to_nonload(Output_section* os, + elfcpp::Elf_Word seg_flags); // Remove an Output_section from this segment. It is an error if it // is not present. @@ -3894,12 +3840,11 @@ class Output_segment // Return true if this segment has any sections which hold actual // data, rather than being a BSS section. bool - has_any_data_sections() const - { return !this->output_data_.empty(); } + has_any_data_sections() const; - // Return the number of dynamic relocations applied to this segment. - unsigned int - dynamic_reloc_count() const; + // Whether this segment has a dynamic relocs. + bool + has_dynamic_reloc() const; // Return the address of the first section. uint64_t @@ -3992,7 +3937,7 @@ class Output_segment print_sections_to_mapfile(Mapfile*) const; private: - typedef std::list<Output_data*> Output_data_list; + typedef std::vector<Output_data*> Output_data_list; // Find the maximum alignment in an Output_data_list. static uint64_t @@ -4012,9 +3957,9 @@ class Output_segment unsigned int output_section_count_list(const Output_data_list*) const; - // Return the number of dynamic relocs in an Output_data_list. - unsigned int - dynamic_reloc_count_list(const Output_data_list*) const; + // Return whether an Output_data_list has a dynamic reloc. + bool + has_dynamic_reloc_list(const Output_data_list*) const; // Find the section with the lowest load address in an // Output_data_list. @@ -4043,10 +3988,8 @@ class Output_segment // NOTE: We want to use the copy constructor. Currently, shallow copy // works for us so we do not need to write our own copy constructor. - // The list of output data with contents attached to this segment. - Output_data_list output_data_; - // The list of output data without contents attached to this segment. - Output_data_list output_bss_; + // The list of output data attached to this segment. + Output_data_list output_lists_[ORDER_MAX]; // The segment virtual address. uint64_t vaddr_; // The segment physical address. diff --git a/gold/powerpc.cc b/gold/powerpc.cc index 0f0ced8..88bc378 100644 --- a/gold/powerpc.cc +++ b/gold/powerpc.cc @@ -738,7 +738,7 @@ Target_powerpc<size, big_endian>::got_section(Symbol_table* symtab, layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE, - this->got_, false, false, false, false); + this->got_, ORDER_DATA, false); // Create the GOT2 or TOC in the .got section. if (size == 32) @@ -747,8 +747,7 @@ Target_powerpc<size, big_endian>::got_section(Symbol_table* symtab, layout->add_output_section_data(".got2", elfcpp::SHT_PROGBITS, elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE, - this->got2_, false, false, false, - false); + this->got2_, ORDER_DATA, false); } else { @@ -756,8 +755,7 @@ Target_powerpc<size, big_endian>::got_section(Symbol_table* symtab, layout->add_output_section_data(".toc", elfcpp::SHT_PROGBITS, elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE, - this->toc_, false, false, false, - false); + this->toc_, ORDER_DATA, false); } // Define _GLOBAL_OFFSET_TABLE_ at the start of the .got section. @@ -784,8 +782,8 @@ Target_powerpc<size, big_endian>::rela_dyn_section(Layout* layout) 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_, true, - false, false, false); + elfcpp::SHF_ALLOC, this->rela_dyn_, + ORDER_DYNAMIC_RELOCS, false); } return this->rela_dyn_; } @@ -845,8 +843,8 @@ Output_data_plt_powerpc<size, big_endian>::Output_data_plt_powerpc(Layout* layou { this->rel_ = new Reloc_section(false); layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA, - elfcpp::SHF_ALLOC, this->rel_, true, false, - false, false); + elfcpp::SHF_ALLOC, this->rel_, + ORDER_DYNAMIC_PLT_RELOCS, false); } template<int size, bool big_endian> @@ -980,7 +978,7 @@ Target_powerpc<size, big_endian>::make_plt_entry(Symbol_table* symtab, (elfcpp::SHF_ALLOC | elfcpp::SHF_EXECINSTR | elfcpp::SHF_WRITE), - this->plt_, false, false, false, false); + this->plt_, ORDER_PLT, false); // Define _PROCEDURE_LINKAGE_TABLE_ at the start of the .plt section. symtab->define_in_output_data("_PROCEDURE_LINKAGE_TABLE_", NULL, @@ -1544,8 +1542,9 @@ Target_powerpc<size, big_endian>::scan_relocs( Output_section* os = layout->add_output_section_data(".sdata", 0, elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE, - sdata, false, - false, false, false); + sdata, + ORDER_SMALL_DATA, + false); symtab->define_in_output_data("_SDA_BASE_", NULL, Symbol_table::PREDEFINED, os, diff --git a/gold/script-sections.cc b/gold/script-sections.cc index 2988d10..978f84d 100644 --- a/gold/script-sections.cc +++ b/gold/script-sections.cc @@ -3212,7 +3212,7 @@ Script_sections::create_segments(Layout* layout, uint64_t dot_alignment) is_current_seg_readonly = true; } - current_seg->add_output_section(*p, seg_flags, false); + current_seg->add_output_section_to_load(layout, *p, seg_flags); if (((*p)->flags() & elfcpp::SHF_WRITE) != 0) is_current_seg_readonly = false; @@ -3291,7 +3291,7 @@ Script_sections::create_note_and_tls_segments( 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, false); + oseg->add_output_section_to_nonload(*p, seg_flags); // Incorporate any subsequent SHT_NOTE sections, in the // hopes that the script is sensible. @@ -3300,7 +3300,7 @@ Script_sections::create_note_and_tls_segments( && (*pnext)->type() == elfcpp::SHT_NOTE) { seg_flags = Layout::section_flags_to_segment((*pnext)->flags()); - oseg->add_output_section(*pnext, seg_flags, false); + oseg->add_output_section_to_nonload(*pnext, seg_flags); p = pnext; ++pnext; } @@ -3315,14 +3315,14 @@ Script_sections::create_note_and_tls_segments( 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, false); + oseg->add_output_section_to_nonload(*p, seg_flags); 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, false); + oseg->add_output_section_to_nonload(*pnext, seg_flags); p = pnext; ++pnext; } @@ -3477,10 +3477,12 @@ Script_sections::attach_sections_using_phdrs_clause(Layout* layout) elfcpp::Elf_Word seg_flags = Layout::section_flags_to_segment(os->flags()); - r->second->add_output_section(os, seg_flags, false); - if (r->second->type() == elfcpp::PT_LOAD) + if (r->second->type() != elfcpp::PT_LOAD) + r->second->add_output_section_to_nonload(os, seg_flags); + else { + r->second->add_output_section_to_load(layout, os, seg_flags); if (in_load_segment) gold_error(_("section in two PT_LOAD segments")); in_load_segment = true; diff --git a/gold/sparc.cc b/gold/sparc.cc index cbaa47e..1635f33 100644 --- a/gold/sparc.cc +++ b/gold/sparc.cc @@ -1048,7 +1048,7 @@ Target_sparc<size, big_endian>::got_section(Symbol_table* symtab, layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE), - this->got_, false, true, false, false); + this->got_, ORDER_RELRO, true); // Define _GLOBAL_OFFSET_TABLE_ at the start of the .got section. symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL, @@ -1074,8 +1074,8 @@ Target_sparc<size, big_endian>::rela_dyn_section(Layout* layout) 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_, true, - false, false, false); + elfcpp::SHF_ALLOC, this->rela_dyn_, + ORDER_DYNAMIC_RELOCS, false); } return this->rela_dyn_; } @@ -1177,8 +1177,8 @@ Output_data_plt_sparc<size, big_endian>::Output_data_plt_sparc(Layout* layout) { this->rel_ = new Reloc_section(false); layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA, - elfcpp::SHF_ALLOC, this->rel_, true, - false, false, false); + elfcpp::SHF_ALLOC, this->rel_, + ORDER_DYNAMIC_PLT_RELOCS, false); } template<int size, bool big_endian> @@ -1400,7 +1400,7 @@ Target_sparc<size, big_endian>::make_plt_entry(Symbol_table* symtab, (elfcpp::SHF_ALLOC | elfcpp::SHF_EXECINSTR | elfcpp::SHF_WRITE), - this->plt_, false, false, false, false); + this->plt_, ORDER_PLT, false); // Define _PROCEDURE_LINKAGE_TABLE_ at the start of the .plt section. symtab->define_in_output_data("_PROCEDURE_LINKAGE_TABLE_", NULL, diff --git a/gold/x86_64.cc b/gold/x86_64.cc index 54f07db..abeff04 100644 --- a/gold/x86_64.cc +++ b/gold/x86_64.cc @@ -561,14 +561,15 @@ Target_x86_64::got_section(Symbol_table* symtab, Layout* layout) layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS, (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE), - this->got_, false, true, true, false); + this->got_, ORDER_RELRO_LAST, + true); this->got_plt_ = new Output_data_space(8, "** GOT PLT"); layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS, (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE), - this->got_plt_, false, false, false, - true); + this->got_plt_, ORDER_NON_RELRO_FIRST, + false); // The first three entries are reserved. this->got_plt_->set_current_data_size(3 * 8); @@ -592,8 +593,8 @@ Target_x86_64::got_section(Symbol_table* symtab, Layout* layout) layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS, (elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE), - this->got_tlsdesc_, false, false, false, - true); + this->got_tlsdesc_, + ORDER_NON_RELRO_FIRST, false); } return this->got_; @@ -609,8 +610,8 @@ Target_x86_64::rela_dyn_section(Layout* layout) 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_, true, - false, false, false); + elfcpp::SHF_ALLOC, this->rela_dyn_, + ORDER_DYNAMIC_RELOCS, false); } return this->rela_dyn_; } @@ -717,8 +718,8 @@ Output_data_plt_x86_64::Output_data_plt_x86_64(Layout* layout, { this->rel_ = new Reloc_section(false); layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA, - elfcpp::SHF_ALLOC, this->rel_, true, - false, false, false); + elfcpp::SHF_ALLOC, this->rel_, + ORDER_DYNAMIC_PLT_RELOCS, false); } void @@ -768,7 +769,7 @@ Output_data_plt_x86_64::rela_tlsdesc(Layout* layout) this->tlsdesc_rel_ = new Reloc_section(false); layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA, elfcpp::SHF_ALLOC, this->tlsdesc_rel_, - true, false, false, false); + ORDER_DYNAMIC_PLT_RELOCS, false); gold_assert(this->tlsdesc_rel_->output_section() == this->rel_->output_section()); } @@ -932,7 +933,7 @@ Target_x86_64::make_plt_section(Symbol_table* symtab, Layout* layout) layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS, (elfcpp::SHF_ALLOC | elfcpp::SHF_EXECINSTR), - this->plt_, false, false, false, false); + this->plt_, ORDER_PLT, false); } } |