From 154e0e9aa714f93206c01ab62920a8ce9220fd9c Mon Sep 17 00:00:00 2001 From: Ian Lance Taylor Date: Tue, 15 Apr 2008 04:06:41 +0000 Subject: [PATCH] * layout.cc (Layout::Layout): Initialize sections_are_attached_. (Layout::get_output_section): Ignore SHF_WRITE and SHF_EXECINSTR in the name/type/flags to section mapping. Don't call allocate_output_section. (Layout::choose_output_section): Change parameter from adjust_name to is_input_section. Don't permit input sections after sections are attached to segments. Don't call allocate_output_section. (Layout::layout_eh_frame): Call update_flags_for_input_section, not write_enable_output_section. (Layout::make_output_section): Don't push to unattached_section_list_ nor call attach_to_segment. Call attach_section_to_segment if sections are attached. (Layout::attach_sections_to_segments): New function. (Layout::attach_section_to_segment): New function. (Layout::attach_allocated_section_to_segment): Rename from attach_to_segment. Remove flags parameter. (Layout::allocate_output_section): Remove function. (Layout::write_enable_output_section): Remove function. * layout.h (class Layout): Update for above changes. Add new field sections_are_attached_. * output.h (Output_section::update_flags_for_input_section): New function. * output.cc (Output_section::add_input_section): Call update_flags_for_input_section. * gold.cc (queue_middle_tasks): Call attach_sections_to_segments. --- gold/ChangeLog | 28 +++++++++ gold/gold.cc | 3 + gold/layout.cc | 158 +++++++++++++++++++------------------------------ gold/layout.h | 18 +++--- gold/output.cc | 5 +- gold/output.h | 10 ++++ 6 files changed, 114 insertions(+), 108 deletions(-) diff --git a/gold/ChangeLog b/gold/ChangeLog index c07a70cc30d..a29e903fe1d 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,31 @@ +2008-04-14 Ian Lance Taylor + + * layout.cc (Layout::Layout): Initialize sections_are_attached_. + (Layout::get_output_section): Ignore SHF_WRITE and SHF_EXECINSTR + in the name/type/flags to section mapping. Don't call + allocate_output_section. + (Layout::choose_output_section): Change parameter from adjust_name + to is_input_section. Don't permit input sections after sections + are attached to segments. Don't call allocate_output_section. + (Layout::layout_eh_frame): Call update_flags_for_input_section, + not write_enable_output_section. + (Layout::make_output_section): Don't push to + unattached_section_list_ nor call attach_to_segment. Call + attach_section_to_segment if sections are attached. + (Layout::attach_sections_to_segments): New function. + (Layout::attach_section_to_segment): New function. + (Layout::attach_allocated_section_to_segment): Rename from + attach_to_segment. Remove flags parameter. + (Layout::allocate_output_section): Remove function. + (Layout::write_enable_output_section): Remove function. + * layout.h (class Layout): Update for above changes. Add new + field sections_are_attached_. + * output.h (Output_section::update_flags_for_input_section): New + function. + * output.cc (Output_section::add_input_section): Call + update_flags_for_input_section. + * gold.cc (queue_middle_tasks): Call attach_sections_to_segments. + 2008-04-11 Cary Coutant * i386.cc (Target_i386::got_mod_index_entry): Restore code previously diff --git a/gold/gold.cc b/gold/gold.cc index daa659634eb..27b93bb7605 100644 --- a/gold/gold.cc +++ b/gold/gold.cc @@ -212,6 +212,9 @@ queue_middle_tasks(const General_options& options, // Define symbols from any linker scripts. layout->define_script_symbols(symtab); + // Attach sections to segments. + layout->attach_sections_to_segments(); + if (!parameters->options().relocatable()) { // Predefine standard symbols. diff --git a/gold/layout.cc b/gold/layout.cc index efeaf659a4d..76b6b2be8d1 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -79,10 +79,10 @@ Layout::Layout(const General_options& options, Script_options* script_options) : options_(options), script_options_(script_options), namepool_(), sympool_(), dynpool_(), signatures_(), section_name_map_(), segment_list_(), section_list_(), - unattached_section_list_(), special_output_list_(), - section_headers_(NULL), tls_segment_(NULL), symtab_section_(NULL), - dynsym_section_(NULL), dynamic_section_(NULL), dynamic_data_(NULL), - eh_frame_section_(NULL), eh_frame_data_(NULL), + unattached_section_list_(), sections_are_attached_(false), + special_output_list_(), section_headers_(NULL), tls_segment_(NULL), + symtab_section_(NULL), dynsym_section_(NULL), dynamic_section_(NULL), + dynamic_data_(NULL), eh_frame_section_(NULL), eh_frame_data_(NULL), added_eh_frame_data_(false), eh_frame_hdr_section_(NULL), build_id_note_(NULL), group_signatures_(), output_file_size_(-1), input_requires_executable_stack_(false), @@ -234,7 +234,15 @@ Output_section* Layout::get_output_section(const char* name, Stringpool::Key name_key, elfcpp::Elf_Word type, elfcpp::Elf_Xword flags) { - const Key key(name_key, std::make_pair(type, flags)); + elfcpp::Elf_Xword lookup_flags = flags; + + // Ignoring SHF_WRITE and SHF_EXECINSTR here means that we combine + // read-write with read-only sections. Some other ELF linkers do + // not do this. FIXME: Perhaps there should be an option + // controlling this. + lookup_flags &= ~(elfcpp::SHF_WRITE | elfcpp::SHF_EXECINSTR); + + const Key key(name_key, std::make_pair(type, lookup_flags)); const std::pair v(key, NULL); std::pair ins( this->section_name_map_.insert(v)); @@ -268,11 +276,7 @@ Layout::get_output_section(const char* name, Stringpool::Key name_key, Section_name_map::iterator p = this->section_name_map_.find(zero_key); if (p != this->section_name_map_.end()) - { - os = p->second; - if ((flags & elfcpp::SHF_ALLOC) != 0) - this->allocate_output_section(os, flags); - } + os = p->second; } } @@ -285,17 +289,22 @@ Layout::get_output_section(const char* name, Stringpool::Key name_key, // Pick the output section to use for section NAME, in input file // RELOBJ, with type TYPE and flags FLAGS. RELOBJ may be NULL for a -// linker created section. ADJUST_NAME is true if we should apply the -// standard name mappings in Layout::output_section_name. This will -// return NULL if the input section should be discarded. +// 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. Output_section* Layout::choose_output_section(const Relobj* relobj, const char* name, elfcpp::Elf_Word type, elfcpp::Elf_Xword flags, - bool adjust_name) + bool is_input_section) { - // We should ignore some flags. FIXME: This will need some - // adjustment for ld -r. + // We should not see any input sections after we have attached + // sections to segments. + gold_assert(!is_input_section || !this->sections_are_attached_); + + // Some flags in the input section should not be automatically + // copied to the output section. flags &= ~ (elfcpp::SHF_INFO_LINK | elfcpp::SHF_LINK_ORDER | elfcpp::SHF_GROUP @@ -324,17 +333,7 @@ Layout::choose_output_section(const Relobj* relobj, const char* name, if (output_section_slot != NULL) { if (*output_section_slot != NULL) - { - // If the output section was created unallocated, and we - // are now allocating it, then we need to clear the - // address set in the constructor and remove it from the - // unattached section list. - if (((*output_section_slot)->flags() & elfcpp::SHF_ALLOC) == 0 - && (flags & elfcpp::SHF_ALLOC) != 0) - this->allocate_output_section(*output_section_slot, flags); - - return *output_section_slot; - } + return *output_section_slot; // We don't put sections found in the linker script into // SECTION_NAME_MAP_. That keeps us from getting confused @@ -356,7 +355,7 @@ Layout::choose_output_section(const Relobj* relobj, const char* name, // output section. size_t len = strlen(name); - if (adjust_name && !parameters->options().relocatable()) + if (is_input_section && !parameters->options().relocatable()) name = Layout::output_section_name(name, &len); Stringpool::Key name_key; @@ -550,16 +549,6 @@ Layout::layout_eh_frame(Sized_relobj* object, if (os == NULL) return NULL; - // On some targets gcc assumes that a read-only .eh_frame section - // will be merged with a read-write .eh_frame section. - if ((shdr.get_sh_flags() & elfcpp::SHF_WRITE) != 0 - && (os->flags() & elfcpp::SHF_WRITE) == 0) - { - elfcpp::Elf_Xword new_flags = os->flags() | elfcpp::SHF_WRITE; - this->write_enable_output_section(os, new_flags); - os->set_flags(new_flags); - } - if (this->eh_frame_section_ == NULL) { this->eh_frame_section_ = os; @@ -606,6 +595,8 @@ Layout::layout_eh_frame(Sized_relobj* object, reloc_shndx, reloc_type)) { + os->update_flags_for_input_section(shdr.get_sh_flags()); + // We found a .eh_frame section we are going to optimize, so now // we can add the set of optimized sections to the output // section. We need to postpone adding this until we've found a @@ -689,11 +680,6 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type, this->section_list_.push_back(os); - if ((flags & elfcpp::SHF_ALLOC) == 0) - this->unattached_section_list_.push_back(os); - else - this->attach_to_segment(os, flags); - // The GNU linker by default sorts some sections by priority, so we // do the same. We need to know that this might happen before we // attach any input sections. @@ -704,14 +690,46 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type, || strcmp(name, ".fini_array") == 0)) os->set_may_sort_attached_input_sections(); + // 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); + return os; } +// Attach output sections to segments. This is called after we have +// seen all the input sections. + +void +Layout::attach_sections_to_segments() +{ + for (Section_list::iterator p = this->section_list_.begin(); + p != this->section_list_.end(); + ++p) + this->attach_section_to_segment(*p); + + this->sections_are_attached_ = true; +} + +// Attach an output section to a segment. + +void +Layout::attach_section_to_segment(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); +} + // Attach an allocated output section to a segment. void -Layout::attach_to_segment(Output_section* os, elfcpp::Elf_Xword flags) +Layout::attach_allocated_section_to_segment(Output_section* os) { + elfcpp::Elf_Xword flags = os->flags(); gold_assert((flags & elfcpp::SHF_ALLOC) != 0); if (parameters->options().relocatable()) @@ -811,58 +829,6 @@ Layout::make_output_section_for_script(const char* name) return os; } -// We have to move an existing output section from the unallocated -// list to the allocated list. - -void -Layout::allocate_output_section(Output_section* os, elfcpp::Elf_Xword flags) -{ - os->reset_address_and_file_offset(); - - Section_list::iterator p = std::find(this->unattached_section_list_.begin(), - this->unattached_section_list_.end(), - os); - gold_assert(p != this->unattached_section_list_.end()); - this->unattached_section_list_.erase(p); - - this->attach_to_segment(os, flags); -} - -// We have to move an existing output section from the read-only -// segment to the writable segment. - -void -Layout::write_enable_output_section(Output_section* os, - elfcpp::Elf_Xword flags) -{ - gold_assert((os->flags() & elfcpp::SHF_WRITE) == 0); - gold_assert(os->type() == elfcpp::SHT_PROGBITS); - gold_assert((flags & elfcpp::SHF_WRITE) != 0); - gold_assert((flags & elfcpp::SHF_ALLOC) != 0); - - if (parameters->options().relocatable()) - return; - - if (this->script_options_->saw_sections_clause()) - return; - - Segment_list::iterator p; - for (p = this->segment_list_.begin(); - p != this->segment_list_.end(); - ++p) - { - if ((*p)->type() == elfcpp::PT_LOAD - && ((*p)->flags() & elfcpp::PF_W) == 0) - { - (*p)->remove_output_section(os); - break; - } - } - gold_assert(p != this->segment_list_.end()); - - this->attach_to_segment(os, flags); -} - // Return the number of segments we expect to see. size_t diff --git a/gold/layout.h b/gold/layout.h index edf64382ddb..13fafd60705 100644 --- a/gold/layout.h +++ b/gold/layout.h @@ -340,6 +340,10 @@ class Layout static elfcpp::Elf_Word section_flags_to_segment(elfcpp::Elf_Xword flags); + // Attach sections to segments. + void + attach_sections_to_segments(); + private: Layout(const Layout&); Layout& operator=(const Layout&); @@ -475,7 +479,7 @@ class Layout Output_section* choose_output_section(const Relobj* relobj, const char* name, elfcpp::Elf_Word type, elfcpp::Elf_Xword flags, - bool adjust_name); + bool is_input_section); // Create a new Output_section. Output_section* @@ -484,15 +488,11 @@ class Layout // Attach a section to a segment. void - attach_to_segment(Output_section*, elfcpp::Elf_Xword flags); - - // Allocate a previously unallocated output section. - void - allocate_output_section(Output_section*, elfcpp::Elf_Xword flags); + attach_section_to_segment(Output_section*); - // Turn a read-only output section into a read-write output section. + // Attach an allocated section to a segment. void - write_enable_output_section(Output_section*, elfcpp::Elf_Xword flags); + attach_allocated_section_to_segment(Output_section*); // Set the final file offsets of all the segments. off_t @@ -578,6 +578,8 @@ class Layout // The list of output sections which are not attached to any output // segment. Section_list unattached_section_list_; + // Whether we have attached the sections to the segments. + bool sections_are_attached_; // The list of unattached Output_data objects which require special // handling because they are not Output_sections. Data_list special_output_list_; diff --git a/gold/output.cc b/gold/output.cc index 48609a21eb7..09b7312de34 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -1673,10 +1673,7 @@ Output_section::add_input_section(Sized_relobj* object, this->addralign_ = addralign; typename elfcpp::Elf_types::Elf_WXword sh_flags = shdr.get_sh_flags(); - this->flags_ |= (sh_flags - & (elfcpp::SHF_WRITE - | elfcpp::SHF_ALLOC - | elfcpp::SHF_EXECINSTR)); + this->update_flags_for_input_section(sh_flags); uint64_t entsize = shdr.get_sh_entsize(); diff --git a/gold/output.h b/gold/output.h index 6221c6e5d70..81685e2cb34 100644 --- a/gold/output.h +++ b/gold/output.h @@ -1714,6 +1714,16 @@ class Output_section : public Output_data set_flags(elfcpp::Elf_Xword flags) { this->flags_ = flags; } + // Update the output section flags based on input section flags. + void + update_flags_for_input_section(elfcpp::Elf_Xword flags) + { + this->flags_ |= (flags + & (elfcpp::SHF_WRITE + | elfcpp::SHF_ALLOC + | elfcpp::SHF_EXECINSTR)); + } + // Return the entsize field. uint64_t entsize() const -- 2.30.2