diff options
-rw-r--r-- | gold/ChangeLog | 16 | ||||
-rw-r--r-- | gold/layout.cc | 61 | ||||
-rw-r--r-- | gold/layout.h | 4 | ||||
-rw-r--r-- | gold/script-sections.cc | 15 |
4 files changed, 78 insertions, 18 deletions
diff --git a/gold/ChangeLog b/gold/ChangeLog index 9ade997..0501ec3 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,5 +1,21 @@ 2011-06-17 Ian Lance Taylor <iant@google.com> + PR gold/12880 + * layout.h (class Layout): Add interp_segment_ field. + * layout.cc (Layout::Layout): Initialize interp_segment_ field. + (Layout::attach_allocated_section_to_segment): If making shared + library, put .interp section in PT_INTERP segment. + (Layout::finalize): Also call create_interp if -dynamic-linker + option was used. + (Layout::create_interp): Assert that there is no PT_INTERP + segment. If not using a SECTIONS clause, use make_output_section. + (Layout::make_output_segment): Set interp_segment_ if PT_INTERP. + * script-sections.cc + (Script_sections::create_note_and_tls_segments): If making shared + library, put .interp section in PT_INTERP segment. + +2011-06-17 Ian Lance Taylor <iant@google.com> + * object.cc (Sized_relobj_file::do_layout): Keep warning sections when making a shared library. diff --git a/gold/layout.cc b/gold/layout.cc index 4c0f1f1..114fa26 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -360,6 +360,7 @@ Layout::Layout(int number_of_input_files, Script_options* script_options) section_headers_(NULL), tls_segment_(NULL), relro_segment_(NULL), + interp_segment_(NULL), increase_relro_(0), symtab_section_(NULL), symtab_xindex_(NULL), @@ -618,11 +619,8 @@ Layout::find_output_segment(elfcpp::PT type, elfcpp::Elf_Word set, // Return the output section to use for section NAME with type TYPE // and section flags FLAGS. NAME must be canonicalized in the string -// pool, and NAME_KEY is the key. IS_INTERP is true if this is the -// .interp section. IS_DYNAMIC_LINKER_SECTION is true if this section -// is used by the dynamic linker. IS_RELRO is true for a relro -// section. IS_LAST_RELRO is true for the last relro section. -// IS_FIRST_NON_RELRO is true for the first non-relro section. +// pool, and NAME_KEY is the key. ORDER is where this should appear +// in the output sections. IS_RELRO is true for a relro section. Output_section* Layout::get_output_section(const char* name, Stringpool::Key name_key, @@ -687,12 +685,9 @@ Layout::get_output_section(const char* name, Stringpool::Key name_key, // RELOBJ, with type TYPE and flags FLAGS. RELOBJ may be NULL for a // linker created section. IS_INPUT_SECTION is true if we are // choosing an output section for an input section found in a input -// file. IS_INTERP is true if this is the .interp section. -// IS_DYNAMIC_LINKER_SECTION is true if this section is used by the -// dynamic linker. IS_RELRO is true for a relro section. -// IS_LAST_RELRO is true for the last relro section. -// IS_FIRST_NON_RELRO is true for the first non-relro section. This -// will return NULL if the input section should be discarded. +// file. ORDER is where this section should appear in the output +// sections. IS_RELRO is true for a relro section. This will return +// NULL if the input section should be discarded. Output_section* Layout::choose_output_section(const Relobj* relobj, const char* name, @@ -1541,6 +1536,21 @@ Layout::attach_allocated_section_to_segment(Output_section* os) this->make_output_segment(elfcpp::PT_GNU_RELRO, seg_flags); this->relro_segment_->add_output_section_to_nonload(os, seg_flags); } + + // If we are making a shared library, and we see a section named + // .interp, and the -dynamic-linker option was not used, then put + // the .interp section into a PT_INTERP segment. This is for GNU ld + // compatibility. If making an executable, or if the + // -dynamic-linker option was used, we will create the section and + // segment in Layout::create_interp. + if (strcmp(os->name(), ".interp") == 0 + && parameters->options().shared() + && parameters->options().dynamic_linker() == NULL) + { + if (this->interp_segment_ == NULL) + this->make_output_segment(elfcpp::PT_INTERP, seg_flags); + this->interp_segment_->add_output_section_to_nonload(os, seg_flags); + } } // Make an output section for a script. @@ -2164,7 +2174,8 @@ Layout::finalize(const Input_objects* input_objects, Symbol_table* symtab, // Create the .interp section to hold the name of the // interpreter, and put it in a PT_INTERP segment. - if (!parameters->options().shared()) + if (!parameters->options().shared() + || parameters->options().dynamic_linker() != NULL) this->create_interp(target); // Finish the .dynamic section to hold the dynamic data, and put @@ -3845,6 +3856,8 @@ Layout::sized_create_version_sections( void Layout::create_interp(const Target* target) { + gold_assert(this->interp_segment_ == NULL); + const char* interp = parameters->options().dynamic_linker(); if (interp == NULL) { @@ -3856,11 +3869,23 @@ Layout::create_interp(const Target* target) Output_section_data* odata = new Output_data_const(interp, len, 1); - Output_section* osec = this->choose_output_section(NULL, ".interp", - elfcpp::SHT_PROGBITS, - elfcpp::SHF_ALLOC, - false, ORDER_INTERP, - false); + Output_section* osec; + + // If we are using a SECTIONS clause, let it decide where the + // .interp section should go. Otherwise always create a new section + // so that this .interp section does not get confused with any + // section of the same name in the program. + if (this->script_options_->saw_sections_clause()) + osec = this->choose_output_section(NULL, ".interp", elfcpp::SHT_PROGBITS, + elfcpp::SHF_ALLOC, false, ORDER_INTERP, + false); + else + { + const char* n = this->namepool_.add("interp", false, NULL); + osec = this->make_output_section(n, elfcpp::SHT_PROGBITS, + elfcpp::SHF_ALLOC, ORDER_INTERP, false); + } + osec->add_output_section_data(odata); if (!this->script_options_->saw_phdrs_clause()) @@ -4389,6 +4414,8 @@ Layout::make_output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags) this->tls_segment_ = oseg; else if (type == elfcpp::PT_GNU_RELRO) this->relro_segment_ = oseg; + else if (type == elfcpp::PT_INTERP) + this->interp_segment_ = oseg; return oseg; } diff --git a/gold/layout.h b/gold/layout.h index ced07b5..1afe913 100644 --- a/gold/layout.h +++ b/gold/layout.h @@ -1,6 +1,6 @@ // layout.h -- lay out output file sections for gold -*- C++ -*- -// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. +// Copyright 2006, 2007, 2008, 2009, 2010, 2011 Free Software Foundation, Inc. // Written by Ian Lance Taylor <iant@google.com>. // This file is part of gold. @@ -1168,6 +1168,8 @@ class Layout Output_segment* tls_segment_; // A pointer to the PT_GNU_RELRO segment if there is one. Output_segment* relro_segment_; + // A pointer to the PT_INTERP segment if there is one. + Output_segment* interp_segment_; // A backend may increase the size of the PT_GNU_RELRO segment if // there is one. This is the amount to increase it by. unsigned int increase_relro_; diff --git a/gold/script-sections.cc b/gold/script-sections.cc index 3bcc9e6..67e3d65 100644 --- a/gold/script-sections.cc +++ b/gold/script-sections.cc @@ -3936,6 +3936,21 @@ Script_sections::create_note_and_tls_segments( saw_tls = true; } + + // If we are making a shared library, and we see a section named + // .interp, and the -dynamic-linker option was not used, then + // put the .interp section in a PT_INTERP segment. This is for + // GNU ld compatibility. + if (strcmp((*p)->name(), ".interp") == 0 + && parameters->options().shared() + && parameters->options().dynamic_linker() == NULL) + { + elfcpp::Elf_Word seg_flags = + Layout::section_flags_to_segment((*p)->flags()); + Output_segment* oseg = layout->make_output_segment(elfcpp::PT_INTERP, + seg_flags); + oseg->add_output_section_to_nonload(*p, seg_flags); + } } } |