diff options
author | Roland McGrath <roland@gnu.org> | 2012-05-02 21:37:24 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 2012-05-02 21:37:24 +0000 |
commit | 2e702c99c59f581594820852c607394c25bc9bd2 (patch) | |
tree | c3470ee3efb4025a07ff95b5135a5ec80febb849 /gold/layout.cc | |
parent | 1ef7171746433c3161d7d4b3c50a93f67d52c4a2 (diff) | |
download | gdb-2e702c99c59f581594820852c607394c25bc9bd2.zip gdb-2e702c99c59f581594820852c607394c25bc9bd2.tar.gz gdb-2e702c99c59f581594820852c607394c25bc9bd2.tar.bz2 |
* configure.ac (ENABLE_GOLD): Consider *-*-nacl* targets ELF.
* configure: Regenerate.
gold/
* nacl.cc: New file.
* nacl.h: New file.
* Makefile.am (CCFILES, HFILES): Add them.
* Makefile.in: Regenerate.
* i386.cc (Output_data_plt_i386_nacl): New class.
(Output_data_plt_i386_nacl_exec): New class.
(Output_data_plt_i386_nacl_dyn): New class.
(Target_i386_nacl): New class.
(Target_selector_i386_nacl): New class.
(target_selector_i386): Use it instead of Target_selector_i386.
* x86_64.cc (Output_data_plt_x86_64_nacl): New class.
(Target_x86_64_nacl): New class.
(Target_selector_x86_64_nacl): New class.
(target_selector_x86_64, target_selector_x32): Use it instead of
Target_selector_x86_64.
* arm.cc (Output_data_plt_arm_nacl): New class.
(Target_arm_nacl): New class.
(Target_selector_arm_nacl): New class.
(target_selector_arm, target_selector_armbe): Use it instead of
Target_selector_arm.
* target-select.cc (select_target): Take new Input_file* and off_t
arguments, pass them on to recognize method of selector.
* object.cc (make_elf_sized_object): Update caller.
* parameters.cc (parameters_force_valid_target): Likewise.
* incremental.cc (make_sized_incremental_binary): Likewise.
* target-select.h: Update decl.
(Target_selector::recognize): Take new Input_file* argument,
pass it on to do_recognize.
(Target_selector::do_recognize): Take new Input_file* argument.
* freebsd.h (Target_selector_freebsd::do_recognize): Likewise.
* powerpc.cc (Target_selector_powerpc::do_recognize): Likewise.
* sparc.cc (Target_selector_sparc::do_recognize): Likewise.
* testsuite/testfile.cc (Target_selector::do_recognize): Likewise.
* target.h (Target::Target_info): New members isolate_execinstr
and rosegment_gap.
(Target::isolate_execinstr, Target::rosegment_gap): New methods.
* arm.cc (Target_arm::arm_info): Update initializer.
* i386.cc (Target_i386::i386_info): Likewise.
* powerpc.cc (Target_powerpc::powerpc_info): Likewise.
* sparc.cc (Target_sparc::sparc_info): Likewise.
* x86_64.cc (Target_x86_64::x86_64_info): Likewise.
* testsuite/testfile.cc (Target_test::test_target_info): Likewise.
* layout.cc (Layout::attach_allocated_section_to_segment):
Take new const Target* argument. If target->isolate_execinstr(), act
like --rosegment.
(Layout::find_first_load_seg): Take new const Target* argument;
if target->isolate_execinstr(), reject PF_X segments.
(Layout::relaxation_loop_body): Update caller.
(Layout::set_segment_offsets): If target->isolate_execinstr(),
reset file offset to zero when we hit LOAD_SEG, and then do a second
loop over the segments before LOAD_SEG to reassign offsets after
addresses have been determined. Handle target->rosegment_gap().
(Layout::attach_section_to_segment): Take new const Target* argument;
pass it to attach_allocated_section_to_segment.
(Layout::make_output_section): Update caller.
(Layout::attach_sections_to_segments): Take new const Target* argument;
pass it to attach_section_to_segment.
* gold.cc (queue_middle_tasks): Update caller.
* layout.h (Layout): Update method decls with new arguments.
* arm.cc (Target_arm::Target_arm): Take optional argument for the
Target_info pointer to use.
(Target_arm::do_make_data_plt): New virtual method.
(Target_arm::make_data_plt): New method that calls it.
(Target_arm::make_plt_entry): Use it.
(Output_data_plt_arm::Output_data_plt_arm): Take additional argument
for the section alignment.
(Output_data_plt_arm::do_first_plt_entry_offset): New abstract virtual
method.
(Output_data_plt_arm::first_plt_entry_offset): Call it.
(Output_data_plt_arm::do_get_plt_entry_size): New abstract virtual
method.
(Output_data_plt_arm::get_plt_entry_size): Call it.
(Output_data_plt_arm::do_fill_plt_entry): New abstract virtual method.
(Output_data_plt_arm::fill_plt_entry): New method that calls it.
(Output_data_plt_arm::do_fill_first_plt_entry): New abstract virtual
method.
(Output_data_plt_arm::fill_first_plt_entry): New method that calls it.
(Output_data_plt_arm::set_final_data_size): Use get_plt_entry_size
method instead of sizeof(plt_entry).
(Output_data_plt_arm::add_entry): Likewise.
Use first_plt_entry_offset method instead of sizeof(first_plt_entry).
(Target_arm::first_plt_entry_offset): Call method on this->plt_ rather
than static method.
(Target_arm::plt_entry_size): Likewise.
(Output_data_plt_arm::first_plt_entry, Output_data_plt_arm::plt_entry):
Move to ...
(Output_data_plt_arm_standard): ... here, new class.
(Output_data_plt_arm::do_write): Move guts of PLT filling to...
(Output_data_plt_arm_standard::do_fill_first_plt_entry): ... here ...
(Output_data_plt_arm_standard::do_fill_plt_entry): ... and here.
* x86_64.cc (Output_data_plt_x86_64::Output_data_plt_x86_64):
Take additional argument for the PLT entry size.
(Output_data_plt_x86_64::get_tlsdesc_plt_offset):
Use get_plt_entry_size method rather than plt_entry_size variable.
(Output_data_plt_x86_64::reserve_slot): Likewise.
(Output_data_plt_x86_64::do_adjust_output_section): Likewise.
(Output_data_plt_x86_64::add_entry): Likewise.
(Output_data_plt_x86_64::add_local_ifunc_entry): Likewise.
(Output_data_plt_x86_64::address_for_global): Likewise.
(Output_data_plt_x86_64::address_for_local): Likewise.
(Output_data_plt_x86_64::set_final_data_size): Likewise.
(Output_data_plt_x86_64::first_plt_entry_offset): Likewise.
Make method non-static.
(Output_data_plt_x86_64::do_get_plt_entry_size): New abstract virtual
method.
(Output_data_plt_x86_64::get_plt_entry_size): Just call that.
(Output_data_plt_x86_64::do_add_eh_frame): New abstract virtual method.
(Output_data_plt_x86_64::add_eh_frame): New method to call it.
(Output_data_plt_x86_64::do_fill_first_plt_entry): New abstract
virtual method.
(Output_data_plt_x86_64::fill_first_plt_entry): New method to call it.
(Output_data_plt_x86_64::do_fill_plt_entry): New abstract
virtual method.
(Output_data_plt_x86_64::fill_plt_entry): New method to call it.
(Output_data_plt_x86_64::do_fill_tlsdesc_entry): New abstract
virtual method.
(Output_data_plt_x86_64::fill_tlsdesc_entry): New method to call it.
(Output_data_plt_x86_64::plt_entry_size)
(Output_data_plt_x86_64::first_plt_entry)
(Output_data_plt_x86_64::plt_entry)
(Output_data_plt_x86_64::tlsdesc_plt_entry)
(Output_data_plt_x86_64::plt_eh_frame_fde_size)
(Output_data_plt_x86_64::plt_eh_frame_fde): Move to ...
(Output_data_plt_x86_64_standard): ... here, new class.
(Target_x86_64::Target_x86_64): Take optional argument for the
Target_info pointer to use.
(Target_x86_64::do_make_data_plt): New virtual method.
(Target_x86_64::make_data_plt): New method to call it.
(Target_x86_64::init_got_plt_for_update): Use that.
Call this->plt_->add_eh_frame method here.
(Output_data_plt_x86_64::init): Don't do add_eh_frame_for_plt here.
(Target_x86_64::first_plt_entry_offset): Call method on this->plt_
rather than static method.
(Target_x86_64::plt_entry_size): Likewise.
(Output_data_plt_x86_64::do_write): Use get_plt_entry_size method
rather than plt_entry_size variable. Move guts of PLT filling to...
(Output_data_plt_x86_64_standard::do_fill_first_plt_entry): ... here ...
(Output_data_plt_x86_64_standard::do_fill_plt_entry): ... and here ...
(Output_data_plt_x86_64_standard::do_fill_tlsdesc_entry): ... and here.
* i386.cc (Output_data_plt_i386::Output_data_plt_i386): Take
additional argument for the section alignment.
Don't do add_eh_frame_for_plt here.
(Output_data_plt_i386::first_plt_entry_offset): Make the method
non-static. Use get_plt_entry_size method rather than plt_entry_size
variable.
(Output_data_plt_i386::do_get_plt_entry_size): New abstract virtual
method.
(Output_data_plt_i386::get_plt_entry_size): Call it.
(Output_data_plt_i386::do_add_eh_frame): New abstract virtual method.
(Output_data_plt_i386::add_eh_frame): New method to call it.
(Output_data_plt_i386::do_fill_first_plt_entry): New abstract virtual
method.
(Output_data_plt_i386::fill_first_plt_entry): New method to call it.
(Output_data_plt_i386::do_fill_plt_entry): New abstract virtual
method.
(Output_data_plt_i386::fill_plt_entry): New method to call it.
(Output_data_plt_i386::set_final_data_size): Use get_plt_entry_size
method instead of plt_entry_size.
(Output_data_plt_i386::plt_entry_size)
(Output_data_plt_i386::plt_eh_frame_fde_size)
(Output_data_plt_i386::plt_eh_frame_fde): Move to ...
(Output_data_plt_i386_standard): ... here, new class.
(Output_data_plt_i386_exec): New class.
(Output_data_plt_i386::exec_first_plt_entry): Move to ...
(Output_data_plt_i386_exec::first_plt_entry): ... here.
(Output_data_plt_i386::exec_plt_entry): Move to ...
(Output_data_plt_i386_exec::plt_entry): ... here.
(Output_data_plt_i386_dyn): New class.
(Output_data_plt_i386::first_plt_entry): Move to ...
(Output_data_plt_i386_dyn::first_plt_entry): ... here.
(Output_data_plt_i386::dyn_plt_entry): Move to ...
(Output_data_plt_i386_dyn::plt_entry): ... here.
(Target_i386::Target_i386): Take optional argument for the Target_info
pointer to use.
(Target_i386::do_make_data_plt): New virtual method.
(Target_i386::make_data_plt): New method to call it.
(Target_i386::make_plt_section): Use that.
Call this->plt_->add_eh_frame method here.
(Output_data_plt_i386::add_entry): Use get_plt_entry_size method
rather than plt_entry_size variable.
(Output_data_plt_i386::add_local_ifunc_entry): Likewise.
(Output_data_plt_i386::address_for_local): Likewise.
(Output_data_plt_i386::do_write): Likewise.
Move guts of PLT filling to...
(Output_data_plt_i386_exec::do_fill_first_plt_entry): ... here ...
(Output_data_plt_i386_exec::do_fill_plt_entry): ... and here ...
(Output_data_plt_i386_dyn::do_fill_first_plt_entry): ... and here ...
(Output_data_plt_i386_dyn::do_fill_plt_entry): ... and here.
Change-Id: Id24b95600489835ff5e860a39c147203d4380c2b
Diffstat (limited to 'gold/layout.cc')
-rw-r--r-- | gold/layout.cc | 463 |
1 files changed, 273 insertions, 190 deletions
diff --git a/gold/layout.cc b/gold/layout.cc index 65d1432..7155f22 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -1,6 +1,7 @@ // layout.cc -- lay out output file sections for gold -// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010, 2011, 2012 +// Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -155,9 +156,9 @@ off_t Free_list::allocate(off_t len, uint64_t align, off_t minoff) { gold_debug(DEBUG_INCREMENTAL, - "Free_list::allocate(%08lx, %d, %08lx)", - static_cast<long>(len), static_cast<int>(align), - static_cast<long>(minoff)); + "Free_list::allocate(%08lx, %d, %08lx)", + static_cast<long>(len), static_cast<int>(align), + static_cast<long>(minoff)); if (len == 0) return align_address(minoff, align); @@ -222,17 +223,17 @@ void Free_list::print_stats() { fprintf(stderr, _("%s: total free lists: %u\n"), - program_name, Free_list::num_lists); + program_name, Free_list::num_lists); fprintf(stderr, _("%s: total free list nodes: %u\n"), - program_name, Free_list::num_nodes); + program_name, Free_list::num_nodes); fprintf(stderr, _("%s: calls to Free_list::remove: %u\n"), - program_name, Free_list::num_removes); + program_name, Free_list::num_removes); fprintf(stderr, _("%s: nodes visited: %u\n"), - program_name, Free_list::num_remove_visits); + program_name, Free_list::num_remove_visits); fprintf(stderr, _("%s: calls to Free_list::allocate: %u\n"), - program_name, Free_list::num_allocates); + program_name, Free_list::num_allocates); fprintf(stderr, _("%s: nodes visited: %u\n"), - program_name, Free_list::num_allocate_visits); + program_name, Free_list::num_allocate_visits); } // Layout::Relaxation_debug_check methods. @@ -256,7 +257,7 @@ Layout::Relaxation_debug_check::check_output_data_for_reset_values( ++p) gold_assert((*p)->address_and_file_offset_have_reset_values()); } - + // Save information of SECTIONS for checking later. void @@ -319,7 +320,7 @@ Layout_task_runner::run(Workqueue* workqueue, const Task* task) Layout* layout = this->layout_; off_t file_size = layout->finalize(this->input_objects_, this->symtab_, - this->target_, + this->target_, task); // Now we know the final size of the output file and we know where @@ -349,8 +350,8 @@ Layout_task_runner::run(Workqueue* workqueue, const Task* task) // incremental information from the file before (possibly) // overwriting it. if (parameters->incremental_update()) - layout->incremental_base()->apply_incremental_relocs(this->symtab_, - this->layout_, + layout->incremental_base()->apply_incremental_relocs(this->symtab_, + this->layout_, of); of->resize(file_size); @@ -579,7 +580,7 @@ Layout::include_section(Sized_relobj_file<size, big_endian>*, const char* name, { // Debugging sections can only be recognized by name. if (is_prefix_of(".debug", name) - && !is_lines_only_debug_section(name)) + && !is_lines_only_debug_section(name)) return false; } if (parameters->options().strip_debug_gdb() @@ -587,17 +588,17 @@ Layout::include_section(Sized_relobj_file<size, big_endian>*, const char* name, { // Debugging sections can only be recognized by name. if (is_prefix_of(".debug", name) - && !is_gdb_debug_section(name)) + && !is_gdb_debug_section(name)) return false; } if (parameters->options().strip_lto_sections() - && !parameters->options().relocatable() - && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0) - { - // Ignore LTO sections containing intermediate code. - if (is_prefix_of(".gnu.lto_", name)) - return false; - } + && !parameters->options().relocatable() + && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0) + { + // Ignore LTO sections containing intermediate code. + if (is_prefix_of(".gnu.lto_", name)) + return false; + } // The GNU linker strips .gnu_debuglink sections, so we do too. // This is a feature used to keep debugging information in // separate files. @@ -713,27 +714,27 @@ Layout::get_output_section(const char* name, Stringpool::Key name_key, if (lookup_type == elfcpp::SHT_PROGBITS) { - if (flags == 0) - { - Output_section* same_name = this->find_output_section(name); - if (same_name != NULL - && (same_name->type() == elfcpp::SHT_PROGBITS + if (flags == 0) + { + Output_section* same_name = this->find_output_section(name); + if (same_name != NULL + && (same_name->type() == elfcpp::SHT_PROGBITS || same_name->type() == elfcpp::SHT_INIT_ARRAY || same_name->type() == elfcpp::SHT_FINI_ARRAY || same_name->type() == elfcpp::SHT_PREINIT_ARRAY) - && (same_name->flags() & elfcpp::SHF_TLS) == 0) - os = same_name; - } - else if ((flags & elfcpp::SHF_TLS) == 0) - { - elfcpp::Elf_Xword zero_flags = 0; - const Key zero_key(name_key, std::make_pair(lookup_type, + && (same_name->flags() & elfcpp::SHF_TLS) == 0) + os = same_name; + } + else if ((flags & elfcpp::SHF_TLS) == 0) + { + elfcpp::Elf_Xword zero_flags = 0; + const Key zero_key(name_key, std::make_pair(lookup_type, zero_flags)); - Section_name_map::iterator p = - this->section_name_map_.find(zero_key); - if (p != this->section_name_map_.end()) + Section_name_map::iterator p = + this->section_name_map_.find(zero_key); + if (p != this->section_name_map_.end()) os = p->second; - } + } } if (os == NULL) @@ -925,7 +926,7 @@ Layout::init_fixed_output_section(const char* name, Stringpool::Key name_key; name = this->namepool_.add(name, true, &name_key); Output_section* os = this->get_output_section(name, name_key, sh_type, - sh_flags, ORDER_INVALID, false); + sh_flags, ORDER_INVALID, false); os->set_fixed_layout(sh_addr, sh_offset, sh_size, sh_addralign); if (sh_type != elfcpp::SHT_NOBITS) this->free_list_.remove(sh_offset, sh_offset + sh_size); @@ -1321,7 +1322,7 @@ Layout::add_to_gdb_index(bool is_type_unit, false, ORDER_INVALID, false); if (os == NULL) - return; + return; this->gdb_index_data_ = new Gdb_index(os); os->add_output_section_data(this->gdb_index_data_); @@ -1379,22 +1380,22 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type, 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) + && parameters->options().strip_debug_non_line() + && strcmp(".debug_abbrev", name) == 0) { os = this->debug_abbrev_ = new Output_reduced_debug_abbrev_section( - name, type, flags); + name, type, flags); if (this->debug_info_) - this->debug_info_->set_abbreviations(this->debug_abbrev_); + this->debug_info_->set_abbreviations(this->debug_abbrev_); } else if ((flags & elfcpp::SHF_ALLOC) == 0 - && parameters->options().strip_debug_non_line() - && strcmp(".debug_info", name) == 0) + && parameters->options().strip_debug_non_line() + && strcmp(".debug_info", name) == 0) { os = this->debug_info_ = new Output_reduced_debug_info_section( - name, type, flags); + name, type, flags); if (this->debug_abbrev_) - this->debug_info_->set_abbreviations(this->debug_abbrev_); + this->debug_info_->set_abbreviations(this->debug_abbrev_); } else { @@ -1497,18 +1498,18 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type, // a minimum size, so we must prevent allocations from the // free list that leave a hole smaller than the minimum. if (strcmp(name, ".debug_info") == 0) - os->set_free_space_fill(new Output_fill_debug_info(false)); + os->set_free_space_fill(new Output_fill_debug_info(false)); else if (strcmp(name, ".debug_types") == 0) - os->set_free_space_fill(new Output_fill_debug_info(true)); + os->set_free_space_fill(new Output_fill_debug_info(true)); else if (strcmp(name, ".debug_line") == 0) - os->set_free_space_fill(new Output_fill_debug_line()); + os->set_free_space_fill(new Output_fill_debug_line()); } // If we have already attached the sections to segments, then we // need to attach this one now. This happens for sections created // directly by the linker. if (this->sections_are_attached_) - this->attach_section_to_segment(os); + this->attach_section_to_segment(¶meters->target(), os); return os; } @@ -1585,12 +1586,12 @@ Layout::default_section_order(Output_section* os, bool is_relro_local) // seen all the input sections. void -Layout::attach_sections_to_segments() +Layout::attach_sections_to_segments(const Target* target) { for (Section_list::iterator p = this->section_list_.begin(); p != this->section_list_.end(); ++p) - this->attach_section_to_segment(*p); + this->attach_section_to_segment(target, *p); this->sections_are_attached_ = true; } @@ -1598,18 +1599,19 @@ Layout::attach_sections_to_segments() // Attach an output section to a segment. void -Layout::attach_section_to_segment(Output_section* os) +Layout::attach_section_to_segment(const Target* target, Output_section* os) { if ((os->flags() & elfcpp::SHF_ALLOC) == 0) this->unattached_section_list_.push_back(os); else - this->attach_allocated_section_to_segment(os); + this->attach_allocated_section_to_segment(target, os); } // Attach an allocated output section to a segment. void -Layout::attach_allocated_section_to_segment(Output_section* os) +Layout::attach_allocated_section_to_segment(const Target* target, + Output_section* os) { elfcpp::Elf_Xword flags = os->flags(); gold_assert((flags & elfcpp::SHF_ALLOC) != 0); @@ -1649,9 +1651,9 @@ Layout::attach_allocated_section_to_segment(Output_section* os) if (!parameters->options().omagic() && ((*p)->flags() & elfcpp::PF_W) != (seg_flags & elfcpp::PF_W)) continue; - if (parameters->options().rosegment() - && ((*p)->flags() & elfcpp::PF_X) != (seg_flags & elfcpp::PF_X)) - continue; + if ((target->isolate_execinstr() || parameters->options().rosegment()) + && ((*p)->flags() & elfcpp::PF_X) != (seg_flags & elfcpp::PF_X)) + continue; // If -Tbss was specified, we need to separate the data and BSS // segments. if (parameters->options().user_set_Tbss()) @@ -1681,7 +1683,7 @@ Layout::attach_allocated_section_to_segment(Output_section* os) if (p == this->segment_list_.end()) { Output_segment* oseg = this->make_output_segment(elfcpp::PT_LOAD, - seg_flags); + seg_flags); if (os->is_large_data_section()) oseg->set_is_large_data_segment(); oseg->add_output_section_to_load(this, os, seg_flags); @@ -1695,24 +1697,24 @@ Layout::attach_allocated_section_to_segment(Output_section* os) { // See if we already have an equivalent PT_NOTE segment. for (p = this->segment_list_.begin(); - p != segment_list_.end(); - ++p) - { - if ((*p)->type() == elfcpp::PT_NOTE - && (((*p)->flags() & elfcpp::PF_W) - == (seg_flags & elfcpp::PF_W))) - { - (*p)->add_output_section_to_nonload(os, seg_flags); - break; - } - } + p != segment_list_.end(); + ++p) + { + if ((*p)->type() == elfcpp::PT_NOTE + && (((*p)->flags() & elfcpp::PF_W) + == (seg_flags & elfcpp::PF_W))) + { + (*p)->add_output_section_to_nonload(os, seg_flags); + break; + } + } if (p == this->segment_list_.end()) - { - Output_segment* oseg = this->make_output_segment(elfcpp::PT_NOTE, - seg_flags); - oseg->add_output_section_to_nonload(os, seg_flags); - } + { + Output_segment* oseg = this->make_output_segment(elfcpp::PT_NOTE, + seg_flags); + oseg->add_output_section_to_nonload(os, seg_flags); + } } // If we see a loadable SHF_TLS section, we create a PT_TLS @@ -1883,9 +1885,9 @@ Layout::define_section_symbols(Symbol_table* symtab) { const std::string name_string(name); const std::string start_name(cident_section_start_prefix - + name_string); + + name_string); const std::string stop_name(cident_section_stop_prefix - + name_string); + + name_string); symtab->define_in_output_data(start_name.c_str(), NULL, // version @@ -1951,7 +1953,7 @@ Layout::define_group_signatures(Symbol_table* symtab) // necessary. Output_segment* -Layout::find_first_load_seg() +Layout::find_first_load_seg(const Target* target) { Output_segment* best = NULL; for (Segment_list::const_iterator p = this->segment_list_.begin(); @@ -1961,11 +1963,13 @@ Layout::find_first_load_seg() if ((*p)->type() == elfcpp::PT_LOAD && ((*p)->flags() & elfcpp::PF_R) != 0 && (parameters->options().omagic() - || ((*p)->flags() & elfcpp::PF_W) == 0)) - { - if (best == NULL || this->segment_precedes(*p, best)) - best = *p; - } + || ((*p)->flags() & elfcpp::PF_W) == 0) + && (!target->isolate_execinstr() + || ((*p)->flags() & elfcpp::PF_X) == 0)) + { + if (best == NULL || this->segment_precedes(*p, best)) + best = *p; + } } if (best != NULL) return best; @@ -2023,10 +2027,10 @@ Layout::restore_segments(const Segment_states* segment_states) this->relro_segment_ = segment; ++list_iter; - } + } else { - list_iter = this->segment_list_.erase(list_iter); + list_iter = this->segment_list_.erase(list_iter); // This is a segment created during section layout. It should be // safe to remove it since we should have removed all pointers to it. delete segment; @@ -2059,7 +2063,7 @@ Layout::clean_up_after_relaxation() (*p)->reset_address_and_file_offset(); } - + // Reset special output object address and file offsets. for (Data_list::iterator p = this->special_output_list_.begin(); p != this->special_output_list_.end(); @@ -2073,7 +2077,7 @@ Layout::clean_up_after_relaxation() p != this->script_output_section_data_list_.end(); ++p) delete *p; - this->script_output_section_data_list_.clear(); + this->script_output_section_data_list_.clear(); } // Prepare for relaxation. @@ -2096,7 +2100,7 @@ Layout::prepare_for_relaxation() if (is_debugging_enabled(DEBUG_RELAXATION)) this->relaxation_debug_check_->check_output_data_for_reset_values( - this->section_list_, this->special_output_list_); + this->section_list_, this->special_output_list_); // Also enable recording of output section data from scripts. this->record_output_section_data_from_script_ = true; @@ -2105,7 +2109,7 @@ Layout::prepare_for_relaxation() // Relaxation loop body: If target has no relaxation, this runs only once // Otherwise, the target relaxation hook is called at the end of // each iteration. If the hook returns true, it means re-layout of -// section is required. +// section is required. // // The number of segments created by a linking script without a PHDRS // clause may be affected by section sizes and alignments. There is @@ -2115,8 +2119,8 @@ Layout::prepare_for_relaxation() // layout. In order to be able to restart the section layout, we keep // a copy of the segment list right before the relaxation loop and use // that to restore the segments. -// -// PASS is the current relaxation pass number. +// +// PASS is the current relaxation pass number. // SYMTAB is a symbol table. // PLOAD_SEG is the address of a pointer for the load segment. // PHDR_SEG is a pointer to the PHDR segment. @@ -2148,7 +2152,7 @@ Layout::relaxation_loop_body( else if (parameters->options().relocatable()) load_seg = NULL; else - load_seg = this->find_first_load_seg(); + load_seg = this->find_first_load_seg(target); if (parameters->options().oformat_enum() != General_options::OBJECT_FORMAT_ELF) @@ -2205,9 +2209,9 @@ Layout::relaxation_loop_body( load_seg->add_initial_output_data(z); } if (load_seg != NULL) - load_seg->add_initial_output_data(segment_headers); + load_seg->add_initial_output_data(segment_headers); if (phdr_seg != NULL) - phdr_seg->add_initial_output_data(segment_headers); + phdr_seg->add_initial_output_data(segment_headers); } // Lay out the file header. @@ -2268,11 +2272,11 @@ Layout::find_section_order_index(const std::string& section_name) ++it) { if (fnmatch((*it).c_str(), section_name.c_str(), FNM_NOESCAPE) == 0) - { - map_it = this->input_section_position_.find(*it); - gold_assert(map_it != this->input_section_position_.end()); - return map_it->second; - } + { + map_it = this->input_section_position_.find(*it); + gold_assert(map_it != this->input_section_position_.end()); + return map_it->second; + } } return 0; } @@ -2290,7 +2294,7 @@ Layout::read_layout_from_file() in.open(filename); if (!in) gold_fatal(_("unable to open --section-ordering-file file %s: %s"), - filename, strerror(errno)); + filename, strerror(errno)); std::getline(in, line); // this chops off the trailing \n, if any unsigned int position = 1; @@ -2299,17 +2303,17 @@ Layout::read_layout_from_file() while (in) { if (!line.empty() && line[line.length() - 1] == '\r') // Windows - line.resize(line.length() - 1); + line.resize(line.length() - 1); // Ignore comments, beginning with '#' if (line[0] == '#') - { - std::getline(in, line); - continue; - } + { + std::getline(in, line); + continue; + } this->input_section_position_[line] = position; // Store all glob patterns in a vector. if (is_wildcard_string(line.c_str())) - this->input_section_glob_.push_back(line); + this->input_section_glob_.push_back(line); position++; std::getline(in, line); } @@ -2373,7 +2377,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab, std::vector<Symbol*> dynamic_symbols; unsigned int local_dynamic_count; Versions versions(*this->script_options()->version_script_info(), - &this->dynpool_); + &this->dynpool_); this->create_dynamic_symtab(input_objects, symtab, &dynstr, &local_dynamic_count, &dynamic_symbols, &versions); @@ -2384,7 +2388,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab, if ((!parameters->options().shared() || parameters->options().dynamic_linker() != NULL) && this->interp_segment_ == NULL) - this->create_interp(target); + this->create_interp(target); // Finish the .dynamic section to hold the dynamic data, and put // it in a PT_DYNAMIC segment. @@ -2403,7 +2407,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab, // after we call create_version_sections. this->set_dynamic_symbol_size(symtab); } - + // Create segment headers. Output_segment_headers* segment_headers = (parameters->options().relocatable() @@ -2422,7 +2426,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab, // a linker script. if (this->script_options_->saw_sections_clause()) this->place_orphan_sections_in_script(); - + Output_segment* load_seg; off_t off; unsigned int shndx; @@ -2431,7 +2435,7 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab, // Take a snapshot of the section layout as needed. if (target->may_relax()) this->prepare_for_relaxation(); - + // Run the relaxation loop to lay out sections. do { @@ -2873,8 +2877,8 @@ Layout::create_incremental_info_sections(Symbol_table* symtab) const char* incremental_strtab_name = this->namepool_.add(".gnu_incremental_strtab", false, NULL); Output_section* incremental_strtab_os = this->make_output_section(incremental_strtab_name, - elfcpp::SHT_STRTAB, 0, - ORDER_INVALID, false); + elfcpp::SHT_STRTAB, 0, + ORDER_INVALID, false); Output_data_strtab* strtab_data = new Output_data_strtab(incr->get_stringpool()); incremental_strtab_os->add_output_section_data(strtab_data); @@ -3054,13 +3058,15 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg, // Find the PT_LOAD segments, and set their addresses and offsets // and their section's addresses and offsets. - uint64_t addr; + uint64_t start_addr; if (parameters->options().user_set_Ttext()) - addr = parameters->options().Ttext(); + start_addr = parameters->options().Ttext(); else if (parameters->options().output_is_position_independent()) - addr = 0; + start_addr = 0; else - addr = target->default_text_segment_address(); + start_addr = target->default_text_segment_address(); + + uint64_t addr = start_addr; off_t off = 0; // If LOAD_SEG is NULL, then the file header and segment headers @@ -3085,15 +3091,39 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg, const bool check_sections = parameters->options().check_sections(); Output_segment* last_load_segment = NULL; + unsigned int shndx_begin = *pshndx; + unsigned int shndx_load_seg = *pshndx; + for (Segment_list::iterator p = this->segment_list_.begin(); p != this->segment_list_.end(); ++p) { if ((*p)->type() == elfcpp::PT_LOAD) { - if (load_seg != NULL && load_seg != *p) - gold_unreachable(); - load_seg = NULL; + if (target->isolate_execinstr()) + { + // When we hit the segment that should contain the + // file headers, reset the file offset so we place + // it and subsequent segments appropriately. + // We'll fix up the preceding segments below. + if (load_seg == *p) + { + if (off == 0) + load_seg = NULL; + else + { + off = 0; + shndx_load_seg = *pshndx; + } + } + } + else + { + // Verify that the file headers fall into the first segment. + if (load_seg != NULL && load_seg != *p) + gold_unreachable(); + load_seg = NULL; + } bool are_addresses_set = (*p)->are_addresses_set(); if (are_addresses_set) @@ -3145,16 +3175,37 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg, addr = align_address(addr, (*p)->maximum_alignment()); aligned_addr = addr; - if ((addr & (abi_pagesize - 1)) != 0) - addr = addr + abi_pagesize; + if (load_seg == *p) + { + // This is the segment that will contain the file + // headers, so its offset will have to be exactly zero. + gold_assert(orig_off == 0); + + // If the target wants a fixed minimum distance from the + // text segment to the read-only segment, move up now. + uint64_t min_addr = start_addr + target->rosegment_gap(); + if (addr < min_addr) + addr = min_addr; + + // But this is not the first segment! To make its + // address congruent with its offset, that address better + // be aligned to the ABI-mandated page size. + addr = align_address(addr, abi_pagesize); + aligned_addr = addr; + } + else + { + if ((addr & (abi_pagesize - 1)) != 0) + addr = addr + abi_pagesize; - off = orig_off + ((addr - orig_addr) & (abi_pagesize - 1)); + off = orig_off + ((addr - orig_addr) & (abi_pagesize - 1)); + } } if (!parameters->options().nmagic() && !parameters->options().omagic()) off = align_file_offset(off, addr, abi_pagesize); - else if (load_seg == NULL) + else { // This is -N or -n with a section script which prevents // us from using a load segment. We need to ensure that @@ -3173,7 +3224,7 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg, uint64_t new_addr = (*p)->set_section_addresses(this, false, addr, &increase_relro, &has_relro, - &off, pshndx); + &off, pshndx); // Now that we know the size of this segment, we may be able // to save a page in memory, at the cost of wasting some @@ -3212,7 +3263,7 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg, new_addr = (*p)->set_section_addresses(this, true, addr, &increase_relro, &has_relro, - &off, pshndx); + &off, pshndx); } } @@ -3239,6 +3290,38 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg, } } + if (load_seg != NULL && target->isolate_execinstr()) + { + // Process the early segments again, setting their file offsets + // so they land after the segments starting at LOAD_SEG. + off = align_file_offset(off, 0, target->abi_pagesize()); + + for (Segment_list::iterator p = this->segment_list_.begin(); + *p != load_seg; + ++p) + { + if ((*p)->type() == elfcpp::PT_LOAD) + { + // We repeat the whole job of assigning addresses and + // offsets, but we really only want to change the offsets and + // must ensure that the addresses all come out the same as + // they did the first time through. + bool has_relro = false; + const uint64_t old_addr = (*p)->vaddr(); + const uint64_t old_end = old_addr + (*p)->memsz(); + uint64_t new_addr = (*p)->set_section_addresses(this, true, + old_addr, + &increase_relro, + &has_relro, + &off, + &shndx_begin); + gold_assert(new_addr == old_end); + } + } + + gold_assert(shndx_begin == shndx_load_seg); + } + // Handle the non-PT_LOAD segments, setting their offsets from their // section's offsets. for (Segment_list::iterator p = this->segment_list_.begin(); @@ -3326,16 +3409,16 @@ Layout::set_section_offsets(off_t off, Layout::Section_offset_pass pass) } if (pass == BEFORE_INPUT_SECTIONS_PASS - && (*p)->after_input_sections()) - continue; + && (*p)->after_input_sections()) + continue; else if (pass == POSTPROCESSING_SECTIONS_PASS - && (!(*p)->after_input_sections() - || (*p)->type() == elfcpp::SHT_STRTAB)) - continue; + && (!(*p)->after_input_sections() + || (*p)->type() == elfcpp::SHT_STRTAB)) + continue; else if (pass == STRTAB_AFTER_POSTPROCESSING_SECTIONS_PASS - && (!(*p)->after_input_sections() - || (*p)->type() != elfcpp::SHT_STRTAB)) - continue; + && (!(*p)->after_input_sections() + || (*p)->type() != elfcpp::SHT_STRTAB)) + continue; if (!parameters->incremental_update()) { @@ -3352,7 +3435,7 @@ Layout::set_section_offsets(off_t off, Layout::Section_offset_pass pass) if (off == -1) { if (is_debugging_enabled(DEBUG_INCREMENTAL)) - this->free_list_.dump(); + this->free_list_.dump(); gold_assert((*p)->output_section() != NULL); gold_fallback(_("out of patch space for section %s; " "relink with --incremental-full"), @@ -3377,7 +3460,7 @@ Layout::set_section_offsets(off_t off, Layout::Section_offset_pass pass) off += (*p)->data_size(); if (off > maxoff) - maxoff = off; + maxoff = off; // At this point the name must be set. if (pass != STRTAB_AFTER_POSTPROCESSING_SECTIONS_PASS) @@ -3525,7 +3608,7 @@ Layout::create_symtab_sections(const Input_objects* input_objects, ++p) { unsigned int index = (*p)->finalize_local_symbols(local_symbol_index, - off, symtab); + off, symtab); off += (index - local_symbol_index) * symsize; local_symbol_index = index; } @@ -3619,7 +3702,7 @@ Layout::create_symtab_sections(const Input_objects* input_objects, else { symtab_off = this->allocate(off, align, *poff); - if (off == -1) + if (off == -1) gold_fallback(_("out of patch space for symbol table; " "relink with --incremental-full")); gold_debug(DEBUG_INCREMENTAL, @@ -3722,7 +3805,7 @@ Layout::allocated_output_section_count() const void Layout::create_dynamic_symtab(const Input_objects* input_objects, - Symbol_table* symtab, + Symbol_table* symtab, Output_section** pdynstr, unsigned int* plocal_dynamic_count, std::vector<Symbol*>* pdynamic_symbols, @@ -4301,45 +4384,45 @@ Layout::finish_dynamic_section(const Input_objects* input_objects, { case elfcpp::SHT_FINI_ARRAY: odyn->add_section_address(elfcpp::DT_FINI_ARRAY, *p); - odyn->add_section_size(elfcpp::DT_FINI_ARRAYSZ, *p); + odyn->add_section_size(elfcpp::DT_FINI_ARRAYSZ, *p); break; case elfcpp::SHT_INIT_ARRAY: odyn->add_section_address(elfcpp::DT_INIT_ARRAY, *p); - odyn->add_section_size(elfcpp::DT_INIT_ARRAYSZ, *p); + odyn->add_section_size(elfcpp::DT_INIT_ARRAYSZ, *p); break; case elfcpp::SHT_PREINIT_ARRAY: odyn->add_section_address(elfcpp::DT_PREINIT_ARRAY, *p); - odyn->add_section_size(elfcpp::DT_PREINIT_ARRAYSZ, *p); + odyn->add_section_size(elfcpp::DT_PREINIT_ARRAYSZ, *p); break; default: break; } - + // Add a DT_RPATH entry if needed. const General_options::Dir_list& rpath(parameters->options().rpath()); if (!rpath.empty()) { std::string rpath_val; for (General_options::Dir_list::const_iterator p = rpath.begin(); - p != rpath.end(); - ++p) - { - if (rpath_val.empty()) - rpath_val = p->name(); - else - { - // Eliminate duplicates. - General_options::Dir_list::const_iterator q; - for (q = rpath.begin(); q != p; ++q) + p != rpath.end(); + ++p) + { + if (rpath_val.empty()) + rpath_val = p->name(); + else + { + // Eliminate duplicates. + General_options::Dir_list::const_iterator q; + for (q = rpath.begin(); q != p; ++q) if (q->name() == p->name()) - break; - if (q == p) - { - rpath_val += ':'; - rpath_val += p->name(); - } - } - } + break; + if (q == p) + { + rpath_val += ':'; + rpath_val += p->name(); + } + } + } odyn->add_string(elfcpp::DT_RPATH, rpath_val); if (parameters->options().enable_new_dtags()) @@ -4351,17 +4434,17 @@ Layout::finish_dynamic_section(const Input_objects* input_objects, if (!this->script_options_->saw_sections_clause()) { for (Segment_list::const_iterator p = this->segment_list_.begin(); - p != this->segment_list_.end(); - ++p) - { - if ((*p)->type() == elfcpp::PT_LOAD + p != this->segment_list_.end(); + ++p) + { + if ((*p)->type() == elfcpp::PT_LOAD && ((*p)->flags() & elfcpp::PF_W) == 0 - && (*p)->has_dynamic_reloc()) - { - have_textrel = true; - break; - } - } + && (*p)->has_dynamic_reloc()) + { + have_textrel = true; + break; + } + } } else { @@ -4370,17 +4453,17 @@ Layout::finish_dynamic_section(const Input_objects* input_objects, // relocations. If those sections wind up in writable segments, // then we have created an unnecessary DT_TEXTREL entry. for (Section_list::const_iterator p = this->section_list_.begin(); - p != this->section_list_.end(); - ++p) - { - if (((*p)->flags() & elfcpp::SHF_ALLOC) != 0 - && ((*p)->flags() & elfcpp::SHF_WRITE) == 0 - && (*p)->has_dynamic_reloc()) - { - have_textrel = true; - break; - } - } + p != this->section_list_.end(); + ++p) + { + if (((*p)->flags() & elfcpp::SHF_ALLOC) != 0 + && ((*p)->flags() & elfcpp::SHF_WRITE) == 0 + && (*p)->has_dynamic_reloc()) + { + have_textrel = true; + break; + } + } } if (parameters->options().filter() != NULL) @@ -4652,7 +4735,7 @@ Layout::find_or_add_kept_section(const std::string& name, unsigned int shndx, bool is_comdat, bool is_group_name, - Kept_section** kept_section) + Kept_section** kept_section) { // It's normal to see a couple of entries here, for the x86 thunk // sections. If we see more than a few, we're linking a C++ @@ -4691,12 +4774,12 @@ Layout::find_or_add_kept_section(const std::string& name, // If the kept group is from a plugin object, and we're in the // replacement phase, accept the new one as a replacement. if (ins.first->second.object() == NULL - && parameters->options().plugins()->in_replacement_phase()) - { + && parameters->options().plugins()->in_replacement_phase()) + { ins.first->second.set_object(object); ins.first->second.set_shndx(shndx); - return true; - } + return true; + } return false; } else if (is_group_name) |