From: Ian Lance Taylor Date: Wed, 4 Nov 2009 15:56:03 +0000 (+0000) Subject: * layout.cc (Layout::get_output_section): Add is_interp and X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=f5c870d25d59bc1e6fcb6a836b6bd1981788982c;p=binutils-gdb.git * 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. --- diff --git a/gold/ChangeLog b/gold/ChangeLog index 6a7d5e7400d..7cb8619cc49 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,21 @@ +2009-11-04 Ian Lance Taylor + + * 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 PR 10860 diff --git a/gold/arm.cc b/gold/arm.cc index f0db8999d7e..89980327b3c 100644 --- a/gold/arm.cc +++ b/gold/arm.cc @@ -2166,7 +2166,7 @@ Target_arm::got_section(Symbol_table* symtab, Layout* layout) 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 @@ -2177,7 +2177,7 @@ Target_arm::got_section(Symbol_table* symtab, Layout* layout) 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. @@ -2205,7 +2205,7 @@ Target_arm::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_); + elfcpp::SHF_ALLOC, this->rel_dyn_, true); } return this->rel_dyn_; } @@ -3588,7 +3588,7 @@ Output_data_plt_arm::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_); + elfcpp::SHF_ALLOC, this->rel_, true); } template @@ -3750,7 +3750,7 @@ Target_arm::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_); + this->plt_, false); } this->plt_->add_entry(gsym); } @@ -4300,7 +4300,8 @@ Target_arm::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); + exidx_segment->add_output_section(exidx_section, elfcpp::PF_R, + false); } } } diff --git a/gold/common.cc b/gold/common.cc index f90ae40e1b5..4bc6a51d698 100644 --- a/gold/common.cc +++ b/gold/common.cc @@ -239,7 +239,7 @@ 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); + flags, poc, false); if (os != NULL) { if (commons_section_type == COMMONS_SMALL) diff --git a/gold/copy-relocs.cc b/gold/copy-relocs.cc index 6ef72d3ed38..345c0c64ceb 100644 --- a/gold/copy-relocs.cc +++ b/gold/copy-relocs.cc @@ -138,7 +138,7 @@ Copy_relocs::emit_copy_reloc( 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_; diff --git a/gold/i386.cc b/gold/i386.cc index 2d7168b1252..d0ed561b239 100644 --- a/gold/i386.cc +++ b/gold/i386.cc @@ -459,7 +459,7 @@ Target_i386::got_section(Symbol_table* symtab, Layout* layout) 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 @@ -470,7 +470,7 @@ Target_i386::got_section(Symbol_table* symtab, Layout* layout) 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. @@ -498,7 +498,7 @@ 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_); + elfcpp::SHF_ALLOC, this->rel_dyn_, true); } return this->rel_dyn_; } @@ -573,7 +573,7 @@ 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_); + elfcpp::SHF_ALLOC, this->rel_, true); } void @@ -758,7 +758,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_); + this->plt_, false); } this->plt_->add_entry(gsym); diff --git a/gold/layout.cc b/gold/layout.cc index 07fa12fd7d4..f0a51b43e13 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -388,11 +388,14 @@ Layout::find_output_segment(elfcpp::PT type, elfcpp::Elf_Word set, // 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; @@ -441,7 +444,8 @@ Layout::get_output_section(const char* name, Stringpool::Key name_key, } 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; } @@ -451,13 +455,16 @@ Layout::get_output_section(const char* name, Stringpool::Key name_key, // 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. @@ -505,7 +512,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); + 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; @@ -528,7 +537,8 @@ 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); + 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 @@ -561,12 +571,13 @@ Layout::layout(Sized_relobj* object, unsigned int shndx, { 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; } @@ -617,7 +628,7 @@ Layout::layout_reloc(Sized_relobj* object, 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); @@ -664,7 +675,8 @@ Layout::layout_group(Symbol_table* symtab, 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. @@ -718,7 +730,7 @@ Layout::layout_eh_frame(Sized_relobj* object, name, elfcpp::SHT_PROGBITS, elfcpp::SHF_ALLOC, - false); + false, false, false); if (os == NULL) return NULL; @@ -734,7 +746,7 @@ Layout::layout_eh_frame(Sized_relobj* object, ".eh_frame_hdr", elfcpp::SHT_PROGBITS, elfcpp::SHF_ALLOC, - false); + false, false, false); if (hdr_os != NULL) { @@ -749,7 +761,7 @@ Layout::layout_eh_frame(Sized_relobj* 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); + hdr_oseg->add_output_section(hdr_os, elfcpp::PF_R, false); } this->eh_frame_data_->set_eh_frame_hdr(hdr_posd); @@ -800,10 +812,12 @@ Layout::layout_eh_frame(Sized_relobj* object, 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; @@ -838,11 +852,14 @@ is_compressible_debug_section(const char* secname) } // 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 @@ -850,7 +867,6 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type, && 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) @@ -876,6 +892,11 @@ 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(); + parameters->target().new_output_section(os); this->section_list_.push_back(os); @@ -971,6 +992,8 @@ Layout::attach_allocated_section_to_segment(Output_section* 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 @@ -998,7 +1021,7 @@ Layout::attach_allocated_section_to_segment(Output_section* os) 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; } @@ -1008,7 +1031,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); + oseg->add_output_section(os, seg_flags, sort_sections); } // If we see a loadable SHT_NOTE section, we create a PT_NOTE @@ -1024,7 +1047,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); + (*p)->add_output_section(os, seg_flags, false); break; } } @@ -1033,7 +1056,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); + oseg->add_output_section(os, seg_flags, false); } } @@ -1043,7 +1066,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); + 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 @@ -1053,7 +1076,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); + this->relro_segment_->add_output_section(os, seg_flags, false); } } @@ -1064,7 +1087,8 @@ Layout::make_output_section_for_script(const char* name) { 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; } @@ -1134,7 +1158,7 @@ Layout::create_initial_dynamic_sections(Symbol_table* symtab) 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, @@ -1732,7 +1756,8 @@ Layout::create_note(const char* name, int note_type, 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; @@ -1811,7 +1836,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); + this->make_output_section(name, elfcpp::SHT_PROGBITS, flags, false, + false); } else { @@ -1971,7 +1997,8 @@ Layout::create_incremental_info_sections() 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); @@ -1981,7 +2008,7 @@ 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); + 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); @@ -2593,7 +2620,7 @@ 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); + 0, false, false); this->symtab_section_ = osymtab; Output_section_data* pos = new Output_data_fixed_space(off - startoff, @@ -2614,7 +2641,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); + elfcpp::SHT_SYMTAB_SHNDX, 0, false, + false); size_t symcount = (off - startoff) / symsize; this->symtab_xindex_ = new Output_symtab_xindex(symcount); @@ -2636,7 +2664,7 @@ 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); + 0, false, false); Output_section_data* pstr = new Output_data_strtab(&this->sympool_); ostrtab->add_output_section_data(pstr); @@ -2663,7 +2691,8 @@ Layout::create_shstrtab() 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 @@ -2776,7 +2805,7 @@ 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, false, true); Output_section_data* odata = new Output_data_fixed_space(index * symsize, align, @@ -2806,7 +2835,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, false, true); this->dynsym_xindex_ = new Output_symtab_xindex(index); @@ -2829,7 +2858,7 @@ 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, false, true); Output_section_data* strdata = new Output_data_strtab(&this->dynpool_); dynstr->add_output_section_data(strdata); @@ -2855,7 +2884,7 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects, 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, @@ -2880,7 +2909,7 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects, 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, @@ -2978,7 +3007,7 @@ Layout::sized_create_version_sections( 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; @@ -3003,7 +3032,7 @@ Layout::sized_create_version_sections( 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; @@ -3028,7 +3057,7 @@ Layout::sized_create_version_sections( 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; @@ -3068,14 +3097,14 @@ Layout::create_interp(const Target* target) 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); } } @@ -3091,7 +3120,8 @@ Layout::finish_dynamic_section(const Input_objects* input_objects, (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_; diff --git a/gold/layout.h b/gold/layout.h index 675c65813b8..71afa966f59 100644 --- a/gold/layout.h +++ b/gold/layout.h @@ -360,11 +360,13 @@ 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. + // 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 @@ -745,18 +747,21 @@ class Layout // 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 diff --git a/gold/output.cc b/gold/output.cc index 61e5c875049..5e9b8137dd7 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); } diff --git a/gold/output.h b/gold/output.h index 841efd3a04a..7e1c73bb54f 100644 --- a/gold/output.h +++ b/gold/output.h @@ -2378,6 +2378,27 @@ 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 @@ -3318,6 +3339,13 @@ class Output_section : public Output_data 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_; @@ -3328,13 +3356,11 @@ class Output_section : public Output_data // 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 @@ -3403,9 +3429,12 @@ class Output_segment 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. diff --git a/gold/powerpc.cc b/gold/powerpc.cc index 081a8f5cd8c..0475f8ee7b4 100644 --- a/gold/powerpc.cc +++ b/gold/powerpc.cc @@ -708,7 +708,7 @@ Target_powerpc::got_section(Symbol_table* symtab, 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) @@ -717,7 +717,7 @@ Target_powerpc::got_section(Symbol_table* symtab, layout->add_output_section_data(".got2", elfcpp::SHT_PROGBITS, elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE, - this->got2_); + this->got2_, false); } else { @@ -725,7 +725,7 @@ Target_powerpc::got_section(Symbol_table* symtab, 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. @@ -751,7 +751,7 @@ Target_powerpc::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_); + elfcpp::SHF_ALLOC, this->rela_dyn_, true); } return this->rela_dyn_; } @@ -811,7 +811,7 @@ Output_data_plt_powerpc::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_); + elfcpp::SHF_ALLOC, this->rel_, true); } template @@ -940,7 +940,7 @@ Target_powerpc::make_plt_entry(Symbol_table* symtab, (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, @@ -1502,7 +1502,7 @@ Target_powerpc::scan_relocs( 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, diff --git a/gold/script-sections.cc b/gold/script-sections.cc index 8fb9a735971..f38cbd0f0fc 100644 --- a/gold/script-sections.cc +++ b/gold/script-sections.cc @@ -3094,7 +3094,7 @@ Script_sections::create_segments(Layout* layout) 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; @@ -3173,7 +3173,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); + oseg->add_output_section(*p, seg_flags, false); // Incorporate any subsequent SHT_NOTE sections, in the // hopes that the script is sensible. @@ -3182,7 +3182,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); + oseg->add_output_section(*pnext, seg_flags, false); p = pnext; ++pnext; } @@ -3197,14 +3197,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); + 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; } @@ -3358,7 +3358,7 @@ 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); + r->second->add_output_section(os, seg_flags, false); if (r->second->type() == elfcpp::PT_LOAD) { diff --git a/gold/sparc.cc b/gold/sparc.cc index dc825f72d30..25f03d19625 100644 --- a/gold/sparc.cc +++ b/gold/sparc.cc @@ -1022,7 +1022,7 @@ Target_sparc::got_section(Symbol_table* symtab, 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. @@ -1048,7 +1048,7 @@ Target_sparc::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_); + elfcpp::SHF_ALLOC, this->rela_dyn_, true); } return this->rela_dyn_; } @@ -1150,7 +1150,7 @@ Output_data_plt_sparc::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_); + elfcpp::SHF_ALLOC, this->rel_, true); } template @@ -1367,7 +1367,7 @@ Target_sparc::make_plt_entry(Symbol_table* symtab, (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, diff --git a/gold/x86_64.cc b/gold/x86_64.cc index 249d1f4cc05..c325fc00daa 100644 --- a/gold/x86_64.cc +++ b/gold/x86_64.cc @@ -467,7 +467,7 @@ Target_x86_64::got_section(Symbol_table* symtab, Layout* layout) 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 @@ -478,7 +478,7 @@ Target_x86_64::got_section(Symbol_table* symtab, Layout* layout) 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. @@ -506,7 +506,7 @@ 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_); + elfcpp::SHF_ALLOC, this->rela_dyn_, true); } return this->rela_dyn_; } @@ -606,7 +606,7 @@ 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_); + elfcpp::SHF_ALLOC, this->rel_, true); } void @@ -802,7 +802,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_); + this->plt_, false); } }