| Index: binutils/gold/layout.cc
|
| diff --git a/binutils/gold/layout.cc b/binutils/gold/layout.cc
|
| index 028703ae1cec80a774f157a39c79ea88d4bda1be..f9f378e8932e2e899f04f121f918c5e1b0a53a08 100644
|
| --- a/binutils/gold/layout.cc
|
| +++ b/binutils/gold/layout.cc
|
| @@ -1,6 +1,6 @@
|
| // layout.cc -- lay out output file sections for gold
|
|
|
| -// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
|
| +// Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
|
| // Written by Ian Lance Taylor <iant@google.com>.
|
|
|
| // This file is part of gold.
|
| @@ -349,6 +349,11 @@ Layout::include_section(Sized_relobj<size, big_endian>*, const char* name,
|
| 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.
|
| + if (strcmp(name, ".gnu_debuglink") == 0)
|
| + return false;
|
| return true;
|
|
|
| default:
|
| @@ -388,11 +393,14 @@ Layout::find_output_segment(elfcpp::PT type, elfcpp::Elf_Word set,
|
|
|
| // Return the output section to use for section NAME with type TYPE
|
| // and section flags FLAGS. NAME must be canonicalized in the string
|
| -// pool, and NAME_KEY is the key.
|
| +// pool, and NAME_KEY is the key. IS_INTERP is true if this is the
|
| +// .interp section. IS_DYNAMIC_LINKER_SECTION is true if this section
|
| +// is used by the dynamic linker.
|
|
|
| Output_section*
|
| Layout::get_output_section(const char* name, Stringpool::Key name_key,
|
| - elfcpp::Elf_Word type, elfcpp::Elf_Xword flags)
|
| + elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
|
| + bool is_interp, bool is_dynamic_linker_section)
|
| {
|
| elfcpp::Elf_Xword lookup_flags = flags;
|
|
|
| @@ -441,7 +449,8 @@ Layout::get_output_section(const char* name, Stringpool::Key name_key,
|
| }
|
|
|
| if (os == NULL)
|
| - os = this->make_output_section(name, type, flags);
|
| + os = this->make_output_section(name, type, flags, is_interp,
|
| + is_dynamic_linker_section);
|
| ins.first->second = os;
|
| return os;
|
| }
|
| @@ -451,13 +460,16 @@ Layout::get_output_section(const char* name, Stringpool::Key name_key,
|
| // RELOBJ, with type TYPE and flags FLAGS. RELOBJ may be NULL for a
|
| // linker created section. IS_INPUT_SECTION is true if we are
|
| // choosing an output section for an input section found in a input
|
| -// file. This will return NULL if the input section should be
|
| -// discarded.
|
| +// file. IS_INTERP is true if this is the .interp section.
|
| +// IS_DYNAMIC_LINKER_SECTION is true if this section is used by the
|
| +// dynamic linker. This will return NULL if the input section should
|
| +// be discarded.
|
|
|
| Output_section*
|
| Layout::choose_output_section(const Relobj* relobj, const char* name,
|
| elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
|
| - bool is_input_section)
|
| + bool is_input_section, bool is_interp,
|
| + bool is_dynamic_linker_section)
|
| {
|
| // We should not see any input sections after we have attached
|
| // sections to segments.
|
| @@ -505,7 +517,9 @@ Layout::choose_output_section(const Relobj* relobj, const char* name,
|
|
|
| name = this->namepool_.add(name, false, NULL);
|
|
|
| - Output_section* os = this->make_output_section(name, type, flags);
|
| + Output_section* os =
|
| + this->make_output_section(name, type, flags, is_interp,
|
| + is_dynamic_linker_section);
|
| os->set_found_in_sections_clause();
|
| *output_section_slot = os;
|
| return os;
|
| @@ -528,7 +542,8 @@ Layout::choose_output_section(const Relobj* relobj, const char* name,
|
|
|
| // Find or make the output section. The output section is selected
|
| // based on the section name, type, and flags.
|
| - return this->get_output_section(name, name_key, type, flags);
|
| + return this->get_output_section(name, name_key, type, flags, is_interp,
|
| + is_dynamic_linker_section);
|
| }
|
|
|
| // Return the output section to use for input section SHNDX, with name
|
| @@ -561,12 +576,13 @@ Layout::layout(Sized_relobj<size, big_endian>* object, unsigned int shndx,
|
| {
|
| name = this->namepool_.add(name, true, NULL);
|
| os = this->make_output_section(name, shdr.get_sh_type(),
|
| - shdr.get_sh_flags());
|
| + shdr.get_sh_flags(), false, false);
|
| }
|
| else
|
| {
|
| os = this->choose_output_section(object, name, shdr.get_sh_type(),
|
| - shdr.get_sh_flags(), true);
|
| + shdr.get_sh_flags(), true, false,
|
| + false);
|
| if (os == NULL)
|
| return NULL;
|
| }
|
| @@ -617,7 +633,7 @@ Layout::layout_reloc(Sized_relobj<size, big_endian>* object,
|
| Output_section* os = this->choose_output_section(object, name.c_str(),
|
| sh_type,
|
| shdr.get_sh_flags(),
|
| - false);
|
| + false, false, false);
|
|
|
| os->set_should_link_to_symtab();
|
| os->set_info_section(data_section);
|
| @@ -664,7 +680,8 @@ Layout::layout_group(Symbol_table* symtab,
|
| group_section_name = this->namepool_.add(group_section_name, true, NULL);
|
| Output_section* os = this->make_output_section(group_section_name,
|
| elfcpp::SHT_GROUP,
|
| - shdr.get_sh_flags());
|
| + shdr.get_sh_flags(),
|
| + false, false);
|
|
|
| // We need to find a symbol with the signature in the symbol table.
|
| // If we don't find one now, we need to look again later.
|
| @@ -718,7 +735,7 @@ Layout::layout_eh_frame(Sized_relobj<size, big_endian>* object,
|
| name,
|
| elfcpp::SHT_PROGBITS,
|
| elfcpp::SHF_ALLOC,
|
| - false);
|
| + false, false, false);
|
| if (os == NULL)
|
| return NULL;
|
|
|
| @@ -734,7 +751,7 @@ Layout::layout_eh_frame(Sized_relobj<size, big_endian>* object,
|
| ".eh_frame_hdr",
|
| elfcpp::SHT_PROGBITS,
|
| elfcpp::SHF_ALLOC,
|
| - false);
|
| + false, false, false);
|
|
|
| if (hdr_os != NULL)
|
| {
|
| @@ -749,7 +766,7 @@ Layout::layout_eh_frame(Sized_relobj<size, big_endian>* object,
|
| Output_segment* hdr_oseg;
|
| hdr_oseg = this->make_output_segment(elfcpp::PT_GNU_EH_FRAME,
|
| elfcpp::PF_R);
|
| - hdr_oseg->add_output_section(hdr_os, elfcpp::PF_R);
|
| + hdr_oseg->add_output_section(hdr_os, elfcpp::PF_R, false);
|
| }
|
|
|
| this->eh_frame_data_->set_eh_frame_hdr(hdr_posd);
|
| @@ -800,10 +817,12 @@ Layout::layout_eh_frame(Sized_relobj<size, big_endian>* object,
|
| Output_section*
|
| Layout::add_output_section_data(const char* name, elfcpp::Elf_Word type,
|
| elfcpp::Elf_Xword flags,
|
| - Output_section_data* posd)
|
| + Output_section_data* posd,
|
| + bool is_dynamic_linker_section)
|
| {
|
| Output_section* os = this->choose_output_section(NULL, name, type, flags,
|
| - false);
|
| + false, false,
|
| + is_dynamic_linker_section);
|
| if (os != NULL)
|
| os->add_output_section_data(posd);
|
| return os;
|
| @@ -838,11 +857,14 @@ is_compressible_debug_section(const char* secname)
|
| }
|
|
|
| // Make a new Output_section, and attach it to segments as
|
| -// appropriate.
|
| +// appropriate. IS_INTERP is true if this is the .interp section.
|
| +// IS_DYNAMIC_LINKER_SECTION is true if this section is used by the
|
| +// dynamic linker.
|
|
|
| Output_section*
|
| Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
|
| - elfcpp::Elf_Xword flags)
|
| + elfcpp::Elf_Xword flags, bool is_interp,
|
| + bool is_dynamic_linker_section)
|
| {
|
| Output_section* os;
|
| if ((flags & elfcpp::SHF_ALLOC) == 0
|
| @@ -850,7 +872,6 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
|
| && is_compressible_debug_section(name))
|
| os = new Output_compressed_section(¶meters->options(), name, type,
|
| flags);
|
| -
|
| else if ((flags & elfcpp::SHF_ALLOC) == 0
|
| && parameters->options().strip_debug_non_line()
|
| && strcmp(".debug_abbrev", name) == 0)
|
| @@ -876,6 +897,11 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
|
| os = target->make_output_section(name, type, flags);
|
| }
|
|
|
| + if (is_interp)
|
| + os->set_is_interp();
|
| + if (is_dynamic_linker_section)
|
| + os->set_is_dynamic_linker_section();
|
| +
|
| parameters->target().new_output_section(os);
|
|
|
| this->section_list_.push_back(os);
|
| @@ -971,6 +997,8 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
|
|
|
| elfcpp::Elf_Word seg_flags = Layout::section_flags_to_segment(flags);
|
|
|
| + bool sort_sections = !this->script_options_->saw_sections_clause();
|
| +
|
| // In general the only thing we really care about for PT_LOAD
|
| // segments is whether or not they are writable, so that is how we
|
| // search for them. Large data sections also go into their own
|
| @@ -998,7 +1026,7 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
|
| if (os->is_large_data_section() && !(*p)->is_large_data_segment())
|
| continue;
|
|
|
| - (*p)->add_output_section(os, seg_flags);
|
| + (*p)->add_output_section(os, seg_flags, sort_sections);
|
| break;
|
| }
|
|
|
| @@ -1008,7 +1036,7 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
|
| seg_flags);
|
| if (os->is_large_data_section())
|
| oseg->set_is_large_data_segment();
|
| - oseg->add_output_section(os, seg_flags);
|
| + oseg->add_output_section(os, seg_flags, sort_sections);
|
| }
|
|
|
| // If we see a loadable SHT_NOTE section, we create a PT_NOTE
|
| @@ -1024,7 +1052,7 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
|
| && (((*p)->flags() & elfcpp::PF_W)
|
| == (seg_flags & elfcpp::PF_W)))
|
| {
|
| - (*p)->add_output_section(os, seg_flags);
|
| + (*p)->add_output_section(os, seg_flags, false);
|
| break;
|
| }
|
| }
|
| @@ -1033,7 +1061,7 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
|
| {
|
| Output_segment* oseg = this->make_output_segment(elfcpp::PT_NOTE,
|
| seg_flags);
|
| - oseg->add_output_section(os, seg_flags);
|
| + oseg->add_output_section(os, seg_flags, false);
|
| }
|
| }
|
|
|
| @@ -1043,7 +1071,7 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
|
| {
|
| if (this->tls_segment_ == NULL)
|
| this->make_output_segment(elfcpp::PT_TLS, seg_flags);
|
| - this->tls_segment_->add_output_section(os, seg_flags);
|
| + this->tls_segment_->add_output_section(os, seg_flags, false);
|
| }
|
|
|
| // If -z relro is in effect, and we see a relro section, we create a
|
| @@ -1053,7 +1081,7 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
|
| gold_assert(seg_flags == (elfcpp::PF_R | elfcpp::PF_W));
|
| if (this->relro_segment_ == NULL)
|
| this->make_output_segment(elfcpp::PT_GNU_RELRO, seg_flags);
|
| - this->relro_segment_->add_output_section(os, seg_flags);
|
| + this->relro_segment_->add_output_section(os, seg_flags, false);
|
| }
|
| }
|
|
|
| @@ -1064,7 +1092,8 @@ Layout::make_output_section_for_script(const char* name)
|
| {
|
| name = this->namepool_.add(name, false, NULL);
|
| Output_section* os = this->make_output_section(name, elfcpp::SHT_PROGBITS,
|
| - elfcpp::SHF_ALLOC);
|
| + elfcpp::SHF_ALLOC, false,
|
| + false);
|
| os->set_found_in_sections_clause();
|
| return os;
|
| }
|
| @@ -1134,7 +1163,7 @@ Layout::create_initial_dynamic_sections(Symbol_table* symtab)
|
| elfcpp::SHT_DYNAMIC,
|
| (elfcpp::SHF_ALLOC
|
| | elfcpp::SHF_WRITE),
|
| - false);
|
| + false, false, true);
|
| this->dynamic_section_->set_is_relro();
|
|
|
| symtab->define_in_output_data("_DYNAMIC", NULL, this->dynamic_section_, 0, 0,
|
| @@ -1732,7 +1761,8 @@ Layout::create_note(const char* name, int note_type,
|
| flags = elfcpp::SHF_ALLOC;
|
| Output_section* os = this->choose_output_section(NULL, section_name,
|
| elfcpp::SHT_NOTE,
|
| - flags, false);
|
| + flags, false, false,
|
| + false);
|
| if (os == NULL)
|
| return NULL;
|
|
|
| @@ -1811,7 +1841,8 @@ Layout::create_executable_stack_info()
|
| elfcpp::Elf_Xword flags = 0;
|
| if (is_stack_executable)
|
| flags |= elfcpp::SHF_EXECINSTR;
|
| - this->make_output_section(name, elfcpp::SHT_PROGBITS, flags);
|
| + this->make_output_section(name, elfcpp::SHT_PROGBITS, flags, false,
|
| + false);
|
| }
|
| else
|
| {
|
| @@ -1971,7 +2002,8 @@ Layout::create_incremental_info_sections()
|
| this->namepool_.add(".gnu_incremental_inputs", false, NULL);
|
| Output_section* inputs_os =
|
| this->make_output_section(incremental_inputs_name,
|
| - elfcpp::SHT_GNU_INCREMENTAL_INPUTS, 0);
|
| + elfcpp::SHT_GNU_INCREMENTAL_INPUTS, 0,
|
| + false, false);
|
| Output_section_data* posd =
|
| this->incremental_inputs_->create_incremental_inputs_section_data();
|
| inputs_os->add_output_section_data(posd);
|
| @@ -1981,7 +2013,7 @@ Layout::create_incremental_info_sections()
|
| this->namepool_.add(".gnu_incremental_strtab", false, NULL);
|
| Output_section* strtab_os = this->make_output_section(incremental_strtab_name,
|
| elfcpp::SHT_STRTAB,
|
| - 0);
|
| + 0, false, false);
|
| Output_data_strtab* strtab_data =
|
| new Output_data_strtab(this->incremental_inputs_->get_stringpool());
|
| strtab_os->add_output_section_data(strtab_data);
|
| @@ -2593,7 +2625,7 @@ Layout::create_symtab_sections(const Input_objects* input_objects,
|
| const char* symtab_name = this->namepool_.add(".symtab", false, NULL);
|
| Output_section* osymtab = this->make_output_section(symtab_name,
|
| elfcpp::SHT_SYMTAB,
|
| - 0);
|
| + 0, false, false);
|
| this->symtab_section_ = osymtab;
|
|
|
| Output_section_data* pos = new Output_data_fixed_space(off - startoff,
|
| @@ -2614,7 +2646,8 @@ Layout::create_symtab_sections(const Input_objects* input_objects,
|
| false, NULL);
|
| Output_section* osymtab_xindex =
|
| this->make_output_section(symtab_xindex_name,
|
| - elfcpp::SHT_SYMTAB_SHNDX, 0);
|
| + elfcpp::SHT_SYMTAB_SHNDX, 0, false,
|
| + false);
|
|
|
| size_t symcount = (off - startoff) / symsize;
|
| this->symtab_xindex_ = new Output_symtab_xindex(symcount);
|
| @@ -2636,7 +2669,7 @@ Layout::create_symtab_sections(const Input_objects* input_objects,
|
| const char* strtab_name = this->namepool_.add(".strtab", false, NULL);
|
| Output_section* ostrtab = this->make_output_section(strtab_name,
|
| elfcpp::SHT_STRTAB,
|
| - 0);
|
| + 0, false, false);
|
|
|
| Output_section_data* pstr = new Output_data_strtab(&this->sympool_);
|
| ostrtab->add_output_section_data(pstr);
|
| @@ -2663,7 +2696,8 @@ Layout::create_shstrtab()
|
|
|
| const char* name = this->namepool_.add(".shstrtab", false, NULL);
|
|
|
| - Output_section* os = this->make_output_section(name, elfcpp::SHT_STRTAB, 0);
|
| + Output_section* os = this->make_output_section(name, elfcpp::SHT_STRTAB, 0,
|
| + false, false);
|
|
|
| // We can't write out this section until we've set all the section
|
| // names, and we don't set the names of compressed output sections
|
| @@ -2776,7 +2810,7 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects,
|
| Output_section* dynsym = this->choose_output_section(NULL, ".dynsym",
|
| elfcpp::SHT_DYNSYM,
|
| elfcpp::SHF_ALLOC,
|
| - false);
|
| + false, false, true);
|
|
|
| Output_section_data* odata = new Output_data_fixed_space(index * symsize,
|
| align,
|
| @@ -2806,7 +2840,7 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects,
|
| this->choose_output_section(NULL, ".dynsym_shndx",
|
| elfcpp::SHT_SYMTAB_SHNDX,
|
| elfcpp::SHF_ALLOC,
|
| - false);
|
| + false, false, true);
|
|
|
| this->dynsym_xindex_ = new Output_symtab_xindex(index);
|
|
|
| @@ -2829,7 +2863,7 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects,
|
| Output_section* dynstr = this->choose_output_section(NULL, ".dynstr",
|
| elfcpp::SHT_STRTAB,
|
| elfcpp::SHF_ALLOC,
|
| - false);
|
| + false, false, true);
|
|
|
| Output_section_data* strdata = new Output_data_strtab(&this->dynpool_);
|
| dynstr->add_output_section_data(strdata);
|
| @@ -2855,7 +2889,7 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects,
|
| Output_section* hashsec = this->choose_output_section(NULL, ".hash",
|
| elfcpp::SHT_HASH,
|
| elfcpp::SHF_ALLOC,
|
| - false);
|
| + false, false, true);
|
|
|
| Output_section_data* hashdata = new Output_data_const_buffer(phash,
|
| hashlen,
|
| @@ -2880,7 +2914,7 @@ Layout::create_dynamic_symtab(const Input_objects* input_objects,
|
| Output_section* hashsec = this->choose_output_section(NULL, ".gnu.hash",
|
| elfcpp::SHT_GNU_HASH,
|
| elfcpp::SHF_ALLOC,
|
| - false);
|
| + false, false, true);
|
|
|
| Output_section_data* hashdata = new Output_data_const_buffer(phash,
|
| hashlen,
|
| @@ -2978,7 +3012,7 @@ Layout::sized_create_version_sections(
|
| Output_section* vsec = this->choose_output_section(NULL, ".gnu.version",
|
| elfcpp::SHT_GNU_versym,
|
| elfcpp::SHF_ALLOC,
|
| - false);
|
| + false, false, true);
|
|
|
| unsigned char* vbuf;
|
| unsigned int vsize;
|
| @@ -3003,7 +3037,7 @@ Layout::sized_create_version_sections(
|
| vdsec= this->choose_output_section(NULL, ".gnu.version_d",
|
| elfcpp::SHT_GNU_verdef,
|
| elfcpp::SHF_ALLOC,
|
| - false);
|
| + false, false, true);
|
|
|
| unsigned char* vdbuf;
|
| unsigned int vdsize;
|
| @@ -3028,7 +3062,7 @@ Layout::sized_create_version_sections(
|
| vnsec = this->choose_output_section(NULL, ".gnu.version_r",
|
| elfcpp::SHT_GNU_verneed,
|
| elfcpp::SHF_ALLOC,
|
| - false);
|
| + false, false, true);
|
|
|
| unsigned char* vnbuf;
|
| unsigned int vnsize;
|
| @@ -3068,14 +3102,14 @@ Layout::create_interp(const Target* target)
|
| Output_section* osec = this->choose_output_section(NULL, ".interp",
|
| elfcpp::SHT_PROGBITS,
|
| elfcpp::SHF_ALLOC,
|
| - false);
|
| + false, true, true);
|
| osec->add_output_section_data(odata);
|
|
|
| if (!this->script_options_->saw_phdrs_clause())
|
| {
|
| Output_segment* oseg = this->make_output_segment(elfcpp::PT_INTERP,
|
| elfcpp::PF_R);
|
| - oseg->add_output_section(osec, elfcpp::PF_R);
|
| + oseg->add_output_section(osec, elfcpp::PF_R, false);
|
| }
|
| }
|
|
|
| @@ -3091,7 +3125,8 @@ Layout::finish_dynamic_section(const Input_objects* input_objects,
|
| (elfcpp::PF_R
|
| | elfcpp::PF_W));
|
| oseg->add_output_section(this->dynamic_section_,
|
| - elfcpp::PF_R | elfcpp::PF_W);
|
| + elfcpp::PF_R | elfcpp::PF_W,
|
| + false);
|
| }
|
|
|
| Output_data_dynamic* const odyn = this->dynamic_data_;
|
| @@ -3100,7 +3135,14 @@ Layout::finish_dynamic_section(const Input_objects* input_objects,
|
| p != input_objects->dynobj_end();
|
| ++p)
|
| {
|
| - // FIXME: Handle --as-needed.
|
| + if (!(*p)->is_needed()
|
| + && (*p)->input_file()->options().as_needed())
|
| + {
|
| + // This dynamic object was linked with --as-needed, but it
|
| + // is not needed.
|
| + continue;
|
| + }
|
| +
|
| odyn->add_string(elfcpp::DT_NEEDED, (*p)->soname());
|
| }
|
|
|
|
|