diff options
author | Ben Cheng <bccheng@google.com> | 2012-11-01 14:19:35 -0700 |
---|---|---|
committer | Ben Cheng <bccheng@google.com> | 2012-11-01 14:27:04 -0700 |
commit | 6d5ce99288a663253fd2cde30516257f754cc776 (patch) | |
tree | d57b8b65cf7b807324908da748ba1845b8e2941a /binutils-2.22/gold/layout.cc | |
parent | 6b95f5ef54a29597409e24d7fe6670238d58ff04 (diff) | |
download | toolchain_binutils-6d5ce99288a663253fd2cde30516257f754cc776.tar.gz toolchain_binutils-6d5ce99288a663253fd2cde30516257f754cc776.tar.bz2 toolchain_binutils-6d5ce99288a663253fd2cde30516257f754cc776.zip |
Refresh binutils to 2.22.90.
Missing local patches will be added after.
Change-Id: I7e5f7529f165a48db48a07f08b85f36c2faa8d4a
Diffstat (limited to 'binutils-2.22/gold/layout.cc')
-rw-r--r-- | binutils-2.22/gold/layout.cc | 737 |
1 files changed, 500 insertions, 237 deletions
diff --git a/binutils-2.22/gold/layout.cc b/binutils-2.22/gold/layout.cc index 1c32bcfd..ad667ab8 100644 --- a/binutils-2.22/gold/layout.cc +++ b/binutils-2.22/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. @@ -44,6 +45,7 @@ #include "symtab.h" #include "dynobj.h" #include "ehframe.h" +#include "gdb-index.h" #include "compressed_output.h" #include "reduced_debug_output.h" #include "object.h" @@ -154,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); @@ -221,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. @@ -255,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 @@ -318,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 @@ -348,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); @@ -390,6 +392,7 @@ Layout::Layout(int number_of_input_files, Script_options* script_options) eh_frame_data_(NULL), added_eh_frame_data_(false), eh_frame_hdr_section_(NULL), + gdb_index_data_(NULL), build_id_note_(NULL), debug_abbrev_(NULL), debug_info_(NULL), @@ -410,6 +413,7 @@ Layout::Layout(int number_of_input_files, Script_options* script_options) script_output_section_data_list_(), segment_states_(NULL), relaxation_debug_check_(NULL), + section_order_map_(), input_section_position_(), input_section_glob_(), incremental_base_(NULL), @@ -449,56 +453,98 @@ Layout::Hash_key::operator()(const Layout::Key& k) const return k.first + k.second.first + k.second.second; } -// Returns whether the given section is in the list of -// debug-sections-used-by-some-version-of-gdb. Currently, -// we've checked versions of gdb up to and including 6.7.1. +// These are the debug sections that are actually used by gdb. +// Currently, we've checked versions of gdb up to and including 7.4. +// We only check the part of the name that follows ".debug_" or +// ".zdebug_". static const char* gdb_sections[] = -{ ".debug_abbrev", - // ".debug_aranges", // not used by gdb as of 6.7.1 - ".debug_frame", - ".debug_info", - ".debug_types", - ".debug_line", - ".debug_loc", - ".debug_macinfo", - // ".debug_pubnames", // not used by gdb as of 6.7.1 - ".debug_ranges", - ".debug_str", +{ + "abbrev", + "addr", // Fission extension + // "aranges", // not used by gdb as of 7.4 + "frame", + "info", + "types", + "line", + "loc", + "macinfo", + "macro", + // "pubnames", // not used by gdb as of 7.4 + // "pubtypes", // not used by gdb as of 7.4 + "ranges", + "str", }; +// This is the minimum set of sections needed for line numbers. + static const char* lines_only_debug_sections[] = -{ ".debug_abbrev", - // ".debug_aranges", // not used by gdb as of 6.7.1 - // ".debug_frame", - ".debug_info", - // ".debug_types", - ".debug_line", - // ".debug_loc", - // ".debug_macinfo", - // ".debug_pubnames", // not used by gdb as of 6.7.1 - // ".debug_ranges", - ".debug_str", +{ + "abbrev", + // "addr", // Fission extension + // "aranges", // not used by gdb as of 7.4 + // "frame", + "info", + // "types", + "line", + // "loc", + // "macinfo", + // "macro", + // "pubnames", // not used by gdb as of 7.4 + // "pubtypes", // not used by gdb as of 7.4 + // "ranges", + "str", }; +// These sections are the DWARF fast-lookup tables, and are not needed +// when building a .gdb_index section. + +static const char* gdb_fast_lookup_sections[] = +{ + "aranges", + "pubnames", + "pubtypes", +}; + +// Returns whether the given debug section is in the list of +// debug-sections-used-by-some-version-of-gdb. SUFFIX is the +// portion of the name following ".debug_" or ".zdebug_". + static inline bool -is_gdb_debug_section(const char* str) +is_gdb_debug_section(const char* suffix) { // We can do this faster: binary search or a hashtable. But why bother? for (size_t i = 0; i < sizeof(gdb_sections)/sizeof(*gdb_sections); ++i) - if (strcmp(str, gdb_sections[i]) == 0) + if (strcmp(suffix, gdb_sections[i]) == 0) return true; return false; } +// Returns whether the given section is needed for lines-only debugging. + static inline bool -is_lines_only_debug_section(const char* str) +is_lines_only_debug_section(const char* suffix) { // We can do this faster: binary search or a hashtable. But why bother? for (size_t i = 0; i < sizeof(lines_only_debug_sections)/sizeof(*lines_only_debug_sections); ++i) - if (strcmp(str, lines_only_debug_sections[i]) == 0) + if (strcmp(suffix, lines_only_debug_sections[i]) == 0) + return true; + return false; +} + +// Returns whether the given section is a fast-lookup section that +// will not be needed when building a .gdb_index section. + +static inline bool +is_gdb_fast_lookup_section(const char* suffix) +{ + // We can do this faster: binary search or a hashtable. But why bother? + for (size_t i = 0; + i < sizeof(gdb_fast_lookup_sections)/sizeof(*gdb_fast_lookup_sections); + ++i) + if (strcmp(suffix, gdb_fast_lookup_sections[i]) == 0) return true; return false; } @@ -575,26 +621,44 @@ Layout::include_section(Sized_relobj_file<size, big_endian>*, const char* name, && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0) { // Debugging sections can only be recognized by name. - if (is_prefix_of(".debug", name) - && !is_lines_only_debug_section(name)) + if (is_prefix_of(".debug_", name) + && !is_lines_only_debug_section(name + 7)) + return false; + if (is_prefix_of(".zdebug_", name) + && !is_lines_only_debug_section(name + 8)) return false; } if (parameters->options().strip_debug_gdb() && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0) { // Debugging sections can only be recognized by name. - if (is_prefix_of(".debug", name) - && !is_gdb_debug_section(name)) + if (is_prefix_of(".debug_", name) + && !is_gdb_debug_section(name + 7)) + return false; + if (is_prefix_of(".zdebug_", name) + && !is_gdb_debug_section(name + 8)) + return false; + } + if (parameters->options().gdb_index() + && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0) + { + // When building .gdb_index, we can strip .debug_pubnames, + // .debug_pubtypes, and .debug_aranges sections. + if (is_prefix_of(".debug_", name) + && is_gdb_fast_lookup_section(name + 7)) + return false; + if (is_prefix_of(".zdebug_", name) + && is_gdb_fast_lookup_section(name + 8)) 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. @@ -710,27 +774,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) @@ -904,6 +968,13 @@ Layout::init_fixed_output_section(const char* name, if (!can_incremental_update(sh_type)) return NULL; + // If we're generating a .gdb_index section, we need to regenerate + // it from scratch. + if (parameters->options().gdb_index() + && sh_type == elfcpp::SHT_PROGBITS + && strcmp(name, ".gdb_index") == 0) + return NULL; + typename elfcpp::Elf_types<size>::Elf_Addr sh_addr = shdr.get_sh_addr(); typename elfcpp::Elf_types<size>::Elf_Off sh_offset = shdr.get_sh_offset(); typename elfcpp::Elf_types<size>::Elf_WXword sh_size = shdr.get_sh_size(); @@ -915,7 +986,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); @@ -1291,6 +1362,38 @@ Layout::add_eh_frame_for_plt(Output_data* plt, const unsigned char* cie_data, } } +// Scan a .debug_info or .debug_types section, and add summary +// information to the .gdb_index section. + +template<int size, bool big_endian> +void +Layout::add_to_gdb_index(bool is_type_unit, + Sized_relobj<size, big_endian>* object, + const unsigned char* symbols, + off_t symbols_size, + unsigned int shndx, + unsigned int reloc_shndx, + unsigned int reloc_type) +{ + if (this->gdb_index_data_ == NULL) + { + Output_section* os = this->choose_output_section(NULL, ".gdb_index", + elfcpp::SHT_PROGBITS, 0, + false, ORDER_INVALID, + false); + if (os == NULL) + return; + + this->gdb_index_data_ = new Gdb_index(os); + os->add_output_section_data(this->gdb_index_data_); + os->set_after_input_sections(); + } + + this->gdb_index_data_->scan_debug_info(is_type_unit, object, symbols, + symbols_size, shndx, reloc_shndx, + reloc_type); +} + // Add POSD to an output section using NAME, TYPE, and FLAGS. Return // the output section. @@ -1337,22 +1440,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 { @@ -1378,25 +1481,29 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type, 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) + if (type == elfcpp::SHT_PROGBITS) { - is_relro = true; - is_relro_local = true; + if ((flags & elfcpp::SHF_TLS) != 0) + is_relro = true; + else 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 (strcmp(name, ".ctors") == 0 + || strcmp(name, ".dtors") == 0 + || strcmp(name, ".jcr") == 0) + is_relro = 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) @@ -1453,18 +1560,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; } @@ -1541,12 +1648,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; } @@ -1554,18 +1661,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); @@ -1605,9 +1713,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()) @@ -1637,7 +1745,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); @@ -1651,24 +1759,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 @@ -1839,9 +1947,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 @@ -1907,7 +2015,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(); @@ -1917,11 +2025,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; @@ -1979,10 +2089,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; @@ -2015,7 +2125,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(); @@ -2029,7 +2139,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. @@ -2052,7 +2162,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; @@ -2061,7 +2171,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 @@ -2071,8 +2181,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. @@ -2104,7 +2214,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) @@ -2161,9 +2271,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. @@ -2224,11 +2334,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; } @@ -2246,7 +2356,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; @@ -2255,17 +2365,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); } @@ -2329,7 +2439,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); @@ -2340,7 +2450,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. @@ -2359,7 +2469,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() @@ -2378,7 +2488,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; @@ -2387,7 +2497,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 { @@ -2399,6 +2509,16 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab, while (target->may_relax() && target->relax(pass, input_objects, symtab, this, task)); + // If there is a load segment that contains the file and program headers, + // provide a symbol __ehdr_start pointing there. + // A program can use this to examine itself robustly. + if (load_seg != NULL) + symtab->define_in_output_segment("__ehdr_start", NULL, + Symbol_table::PREDEFINED, load_seg, 0, 0, + elfcpp::STT_NOTYPE, elfcpp::STB_GLOBAL, + elfcpp::STV_DEFAULT, 0, + Symbol::SEGMENT_START, true); + // Set the file offsets of all the non-data sections we've seen so // far which don't have to wait for the input sections. We need // this in order to finalize local symbols in non-allocated @@ -2829,8 +2949,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); @@ -2975,8 +3095,9 @@ Layout::segment_precedes(const Output_segment* seg1, // We shouldn't get here--we shouldn't create segments which we // can't distinguish. Unless of course we are using a weird linker - // script. - gold_assert(this->script_options_->saw_phdrs_clause()); + // script or overlapping --section-start options. + gold_assert(this->script_options_->saw_phdrs_clause() + || parameters->options().any_section_start()); return false; } @@ -3009,13 +3130,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 @@ -3040,15 +3163,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) @@ -3100,16 +3247,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 @@ -3128,7 +3296,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 @@ -3167,7 +3335,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); } } @@ -3194,6 +3362,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(); @@ -3281,16 +3481,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()) { @@ -3307,7 +3507,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"), @@ -3332,7 +3532,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) @@ -3480,7 +3680,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; } @@ -3574,7 +3774,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, @@ -3677,7 +3877,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, @@ -4256,45 +4456,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()) @@ -4306,17 +4506,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 { @@ -4325,17 +4525,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) @@ -4435,12 +4635,15 @@ Layout::set_dynamic_symbol_size(const Symbol_table* symtab) // based on the GNU linker default ELF linker script. #define MAPPING_INIT(f, t) { f, sizeof(f) - 1, t, sizeof(t) - 1 } +#define MAPPING_INIT_EXACT(f, t) { f, 0, t, sizeof(t) - 1 } const Layout::Section_name_mapping Layout::section_name_mapping[] = { MAPPING_INIT(".text.", ".text"), MAPPING_INIT(".rodata.", ".rodata"), - MAPPING_INIT(".data.rel.ro.local", ".data.rel.ro.local"), - MAPPING_INIT(".data.rel.ro", ".data.rel.ro"), + MAPPING_INIT(".data.rel.ro.local.", ".data.rel.ro.local"), + MAPPING_INIT_EXACT(".data.rel.ro.local", ".data.rel.ro.local"), + MAPPING_INIT(".data.rel.ro.", ".data.rel.ro"), + MAPPING_INIT_EXACT(".data.rel.ro", ".data.rel.ro"), MAPPING_INIT(".data.", ".data"), MAPPING_INIT(".bss.", ".bss"), MAPPING_INIT(".tdata.", ".tdata"), @@ -4479,6 +4682,7 @@ const Layout::Section_name_mapping Layout::section_name_mapping[] = MAPPING_INIT(".gnu.linkonce.armexidx.", ".ARM.exidx"), }; #undef MAPPING_INIT +#undef MAPPING_INIT_EXACT const int Layout::section_name_mapping_count = (sizeof(Layout::section_name_mapping) @@ -4530,10 +4734,21 @@ Layout::output_section_name(const Relobj* relobj, const char* name, const Section_name_mapping* psnm = section_name_mapping; for (int i = 0; i < section_name_mapping_count; ++i, ++psnm) { - if (strncmp(name, psnm->from, psnm->fromlen) == 0) + if (psnm->fromlen > 0) + { + if (strncmp(name, psnm->from, psnm->fromlen) == 0) + { + *plen = psnm->tolen; + return psnm->to; + } + } + else { - *plen = psnm->tolen; - return psnm->to; + if (strcmp(name, psnm->from) == 0) + { + *plen = psnm->tolen; + return psnm->to; + } } } @@ -4607,7 +4822,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++ @@ -4646,12 +4861,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) @@ -5293,4 +5508,52 @@ Layout::layout_eh_frame<64, true>(Sized_relobj_file<64, true>* object, off_t* off); #endif +#ifdef HAVE_TARGET_32_LITTLE +template +void +Layout::add_to_gdb_index(bool is_type_unit, + Sized_relobj<32, false>* object, + const unsigned char* symbols, + off_t symbols_size, + unsigned int shndx, + unsigned int reloc_shndx, + unsigned int reloc_type); +#endif + +#ifdef HAVE_TARGET_32_BIG +template +void +Layout::add_to_gdb_index(bool is_type_unit, + Sized_relobj<32, true>* object, + const unsigned char* symbols, + off_t symbols_size, + unsigned int shndx, + unsigned int reloc_shndx, + unsigned int reloc_type); +#endif + +#ifdef HAVE_TARGET_64_LITTLE +template +void +Layout::add_to_gdb_index(bool is_type_unit, + Sized_relobj<64, false>* object, + const unsigned char* symbols, + off_t symbols_size, + unsigned int shndx, + unsigned int reloc_shndx, + unsigned int reloc_type); +#endif + +#ifdef HAVE_TARGET_64_BIG +template +void +Layout::add_to_gdb_index(bool is_type_unit, + Sized_relobj<64, true>* object, + const unsigned char* symbols, + off_t symbols_size, + unsigned int shndx, + unsigned int reloc_shndx, + unsigned int reloc_type); +#endif + } // End namespace gold. |