From: Ian Lance Taylor Date: Wed, 6 Feb 2008 19:32:32 +0000 (+0000) Subject: Fix group signature handling for relocatable link, add bootstrap X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=755ab8af10558c40e5090e92c46bbbd89815c292;p=binutils-gdb.git Fix group signature handling for relocatable link, add bootstrap relocatable test. --- diff --git a/gold/Makefile.am b/gold/Makefile.am index cef759ed55a..0f09afad60b 100644 --- a/gold/Makefile.am +++ b/gold/Makefile.am @@ -175,15 +175,41 @@ ld2_DEPENDENCIES = $(deps_var) gcctestdir2/ld ld2_LDADD = $(ldadd_var) ld2_LDFLAGS = -Bgcctestdir2/ -check_PROGRAMS = ld1 ld2 - bootstrap-test: ld2 rm -f $@ echo "#!/bin/sh" > $@ echo "cmp ld1 ld2" > $@ chmod +x $@ -TESTS = bootstrap-test +libgold-1-r.o: gcctestdir1/ld libgold.a + gcctestdir1/ld -o $@ -r --whole-archive libgold.a + +ld1_r_SOURCES = $(sources_var) +ld1_r_DEPENDENCIES = libgold-1-r.o $(deps_var) gcctestdir1/ld +ld1_r_LDADD = libgold-1-r.o $(ldadd_var) +ld1_r_LDFLAGS = -Bgcctestdir1/ + +gcctestdir2-r/ld: ld1-r + test -d gcctestdir2-r || mkdir -p gcctestdir2-r + rm -f gcctestdir2-r/ld + (cd gcctestdir2-r && $(LN_S) ../ld1-r ld) + +libgold-2-r.o: gcctestdir2-r/ld libgold.a + gcctestdir2-r/ld -o $@ -r --whole-archive libgold.a + +ld2_r_SOURCES = $(sources_var) +ld2_r_DEPENDENCIES = libgold-2-r.o $(deps_var) gcctestdir2-r/ld +ld2_r_LDADD = libgold-2-r.o $(ldadd_var) +ld2_r_LDFLAGS = -Bgcctestdir2-r/ + +bootstrap-test-r: ld2-r + rm -f $@ + echo "#!/bin/sh" > $@ + echo "cmp ld1-r ld2-r" > $@ + chmod +x $@ + +check_PROGRAMS = ld1 ld2 ld1-r ld2-r +TESTS = bootstrap-test bootstrap-test-r endif endif diff --git a/gold/Makefile.in b/gold/Makefile.in index 22bae570c80..a315718e627 100644 --- a/gold/Makefile.in +++ b/gold/Makefile.in @@ -42,7 +42,8 @@ host_triplet = @host@ target_triplet = @target@ noinst_PROGRAMS = ld-new$(EXEEXT) @GCC_TRUE@@NATIVE_LINKER_TRUE@check_PROGRAMS = ld1$(EXEEXT) \ -@GCC_TRUE@@NATIVE_LINKER_TRUE@ ld2$(EXEEXT) +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ld2$(EXEEXT) ld1-r$(EXEEXT) \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ ld2-r$(EXEEXT) DIST_COMMON = README $(am__configure_deps) $(srcdir)/../config.guess \ $(srcdir)/../config.sub $(srcdir)/../depcomp \ $(srcdir)/../install-sh $(srcdir)/../missing \ @@ -100,9 +101,15 @@ am__DEPENDENCIES_4 = @LIBOBJS@ am__ld1_SOURCES_DIST = main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_ld1_OBJECTS = $(am__objects_4) ld1_OBJECTS = $(am_ld1_OBJECTS) +am__ld1_r_SOURCES_DIST = main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_ld1_r_OBJECTS = $(am__objects_4) +ld1_r_OBJECTS = $(am_ld1_r_OBJECTS) am__ld2_SOURCES_DIST = main.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@am_ld2_OBJECTS = $(am__objects_4) ld2_OBJECTS = $(am_ld2_OBJECTS) +am__ld2_r_SOURCES_DIST = main.cc +@GCC_TRUE@@NATIVE_LINKER_TRUE@am_ld2_r_OBJECTS = $(am__objects_4) +ld2_r_OBJECTS = $(am_ld2_r_OBJECTS) DEFAULT_INCLUDES = -I. -I$(srcdir) -I. depcomp = $(SHELL) $(top_srcdir)/../depcomp am__depfiles_maybe = depfiles @@ -117,10 +124,12 @@ CXXLINK = $(CXXLD) $(AM_CXXFLAGS) $(CXXFLAGS) $(AM_LDFLAGS) $(LDFLAGS) \ -o $@ YACCCOMPILE = $(YACC) $(YFLAGS) $(AM_YFLAGS) SOURCES = $(libgold_a_SOURCES) $(ld_new_SOURCES) \ - $(EXTRA_ld_new_SOURCES) $(ld1_SOURCES) $(ld2_SOURCES) + $(EXTRA_ld_new_SOURCES) $(ld1_SOURCES) $(ld1_r_SOURCES) \ + $(ld2_SOURCES) $(ld2_r_SOURCES) DIST_SOURCES = $(libgold_a_SOURCES) $(ld_new_SOURCES) \ $(EXTRA_ld_new_SOURCES) $(am__ld1_SOURCES_DIST) \ - $(am__ld2_SOURCES_DIST) + $(am__ld1_r_SOURCES_DIST) $(am__ld2_SOURCES_DIST) \ + $(am__ld2_r_SOURCES_DIST) RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-exec-recursive install-info-recursive \ @@ -382,7 +391,15 @@ POTFILES = $(CCFILES) $(HFILES) $(TARGETSOURCES) @GCC_TRUE@@NATIVE_LINKER_TRUE@ld2_DEPENDENCIES = $(deps_var) gcctestdir2/ld @GCC_TRUE@@NATIVE_LINKER_TRUE@ld2_LDADD = $(ldadd_var) @GCC_TRUE@@NATIVE_LINKER_TRUE@ld2_LDFLAGS = -Bgcctestdir2/ -@GCC_TRUE@@NATIVE_LINKER_TRUE@TESTS = bootstrap-test +@GCC_TRUE@@NATIVE_LINKER_TRUE@ld1_r_SOURCES = $(sources_var) +@GCC_TRUE@@NATIVE_LINKER_TRUE@ld1_r_DEPENDENCIES = libgold-1-r.o $(deps_var) gcctestdir1/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ld1_r_LDADD = libgold-1-r.o $(ldadd_var) +@GCC_TRUE@@NATIVE_LINKER_TRUE@ld1_r_LDFLAGS = -Bgcctestdir1/ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ld2_r_SOURCES = $(sources_var) +@GCC_TRUE@@NATIVE_LINKER_TRUE@ld2_r_DEPENDENCIES = libgold-2-r.o $(deps_var) gcctestdir2-r/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ld2_r_LDADD = libgold-2-r.o $(ldadd_var) +@GCC_TRUE@@NATIVE_LINKER_TRUE@ld2_r_LDFLAGS = -Bgcctestdir2-r/ +@GCC_TRUE@@NATIVE_LINKER_TRUE@TESTS = bootstrap-test bootstrap-test-r all: config.h $(MAKE) $(AM_MAKEFLAGS) all-recursive @@ -464,9 +481,15 @@ ld-new$(EXEEXT): $(ld_new_OBJECTS) $(ld_new_DEPENDENCIES) ld1$(EXEEXT): $(ld1_OBJECTS) $(ld1_DEPENDENCIES) @rm -f ld1$(EXEEXT) $(CXXLINK) $(ld1_LDFLAGS) $(ld1_OBJECTS) $(ld1_LDADD) $(LIBS) +ld1-r$(EXEEXT): $(ld1_r_OBJECTS) $(ld1_r_DEPENDENCIES) + @rm -f ld1-r$(EXEEXT) + $(CXXLINK) $(ld1_r_LDFLAGS) $(ld1_r_OBJECTS) $(ld1_r_LDADD) $(LIBS) ld2$(EXEEXT): $(ld2_OBJECTS) $(ld2_DEPENDENCIES) @rm -f ld2$(EXEEXT) $(CXXLINK) $(ld2_LDFLAGS) $(ld2_OBJECTS) $(ld2_LDADD) $(LIBS) +ld2-r$(EXEEXT): $(ld2_r_OBJECTS) $(ld2_r_DEPENDENCIES) + @rm -f ld2-r$(EXEEXT) + $(CXXLINK) $(ld2_r_LDFLAGS) $(ld2_r_OBJECTS) $(ld2_r_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -1060,6 +1083,23 @@ po/POTFILES.in: @MAINT@ Makefile @GCC_TRUE@@NATIVE_LINKER_TRUE@ echo "#!/bin/sh" > $@ @GCC_TRUE@@NATIVE_LINKER_TRUE@ echo "cmp ld1 ld2" > $@ @GCC_TRUE@@NATIVE_LINKER_TRUE@ chmod +x $@ + +@GCC_TRUE@@NATIVE_LINKER_TRUE@libgold-1-r.o: gcctestdir1/ld libgold.a +@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir1/ld -o $@ -r --whole-archive libgold.a + +@GCC_TRUE@@NATIVE_LINKER_TRUE@gcctestdir2-r/ld: ld1-r +@GCC_TRUE@@NATIVE_LINKER_TRUE@ test -d gcctestdir2-r || mkdir -p gcctestdir2-r +@GCC_TRUE@@NATIVE_LINKER_TRUE@ rm -f gcctestdir2-r/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ (cd gcctestdir2-r && $(LN_S) ../ld1-r ld) + +@GCC_TRUE@@NATIVE_LINKER_TRUE@libgold-2-r.o: gcctestdir2-r/ld libgold.a +@GCC_TRUE@@NATIVE_LINKER_TRUE@ gcctestdir2-r/ld -o $@ -r --whole-archive libgold.a + +@GCC_TRUE@@NATIVE_LINKER_TRUE@bootstrap-test-r: ld2-r +@GCC_TRUE@@NATIVE_LINKER_TRUE@ rm -f $@ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ echo "#!/bin/sh" > $@ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ echo "cmp ld1-r ld2-r" > $@ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ chmod +x $@ # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: diff --git a/gold/gold.cc b/gold/gold.cc index 2aee1b76c81..71dac861798 100644 --- a/gold/gold.cc +++ b/gold/gold.cc @@ -214,6 +214,9 @@ queue_middle_tasks(const General_options& options, layout->define_section_symbols(symtab); } + // Make sure we have symbols for any required group signatures. + layout->define_group_signatures(symtab); + // Read the relocations of the input files. We do this to find // which symbols are used by relocations which require a GOT and/or // a PLT entry, or a COPY reloc. When we implement garbage diff --git a/gold/layout.cc b/gold/layout.cc index 006a3842daf..8b17f83ab4f 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -73,7 +73,7 @@ Layout::Layout(const General_options& options, Script_options* script_options) 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), output_file_size_(-1), + eh_frame_section_(NULL), group_signatures_(), output_file_size_(-1), input_requires_executable_stack_(false), input_with_gnu_stack_note_(false), input_without_gnu_stack_note_(false), @@ -433,16 +433,19 @@ Layout::layout_group(Symbol_table* symtab, shdr.get_sh_flags()); // We need to find a symbol with the signature in the symbol table. - // This is a hack to force that to happen. + // If we don't find one now, we need to look again later. Symbol* sym = symtab->lookup(signature, NULL); - if (sym == NULL) - sym = symtab->define_as_constant(signature, NULL, 0, 0, - elfcpp::STT_NOTYPE, - elfcpp::STB_WEAK, - elfcpp::STV_HIDDEN, 0, false); + if (sym != NULL) + os->set_info_symndx(sym); + else + { + // We will wind up using a symbol whose name is the signature. + // So just put the signature in the symbol name pool to save it. + signature = symtab->canonicalize_name(signature); + this->group_signatures_.push_back(Group_signature(os, signature)); + } os->set_should_link_to_symtab(); - os->set_info_symndx(sym); os->set_entsize(4); section_size_type entry_count = @@ -798,6 +801,37 @@ Layout::define_section_symbols(Symbol_table* symtab) } } +// Define symbols for group signatures. + +void +Layout::define_group_signatures(Symbol_table* symtab) +{ + for (Group_signatures::iterator p = this->group_signatures_.begin(); + p != this->group_signatures_.end(); + ++p) + { + Symbol* sym = symtab->lookup(p->signature, NULL); + if (sym != NULL) + p->section->set_info_symndx(sym); + else + { + // Force the name of the group section to the group + // signature, and use the group's section symbol as the + // signature symbol. + if (strcmp(p->section->name(), p->signature) != 0) + { + const char* name = this->namepool_.add(p->signature, + true, NULL); + p->section->set_name(name); + } + p->section->set_needs_symtab_index(); + p->section->set_info_section_symndx(p->section); + } + } + + this->group_signatures_.clear(); +} + // Find the first read-only PT_LOAD segment, creating one if // necessary. diff --git a/gold/layout.h b/gold/layout.h index e050df36b92..674956e6889 100644 --- a/gold/layout.h +++ b/gold/layout.h @@ -171,6 +171,10 @@ class Layout define_script_symbols(Symbol_table* symtab) { this->script_options_->add_symbols_to_table(symtab); } + // Define symbols for group signatures. + void + define_group_signatures(Symbol_table*); + // Return the Stringpool used for symbol names. const Stringpool* sympool() const @@ -332,6 +336,25 @@ class Layout static const Linkonce_mapping linkonce_mapping[]; static const int linkonce_mapping_count; + // During a relocatable link, a list of group sections and + // signatures. + struct Group_signature + { + // The group section. + Output_section* section; + // The signature. + const char* signature; + + Group_signature() + : section(NULL), signature(NULL) + { } + + Group_signature(Output_section* sectiona, const char* signaturea) + : section(sectiona), signature(signaturea) + { } + }; + typedef std::vector Group_signatures; + // Create a .note section for gold. void create_gold_note(); @@ -537,6 +560,8 @@ class Layout Eh_frame* eh_frame_data_; // The exception frame header output section if there is one. Output_section* eh_frame_hdr_section_; + // A list of group sections and their signatures. + Group_signatures group_signatures_; // The size of the output file. off_t output_file_size_; // Whether we have seen an object file marked to require an diff --git a/gold/output.cc b/gold/output.cc index 0e05ff778ea..332aa2cf2c6 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -1610,6 +1610,7 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type, requires_postprocessing_(false), found_in_sections_clause_(false), has_load_address_(false), + info_uses_section_index_(false), tls_offset_(0) { // An unallocated section has no address. Forcing this means that @@ -2005,7 +2006,7 @@ Output_section::write_header(const Layout* layout, oshdr->put_sh_type(this->type_); elfcpp::Elf_Xword flags = this->flags_; - if (this->info_section_ != NULL) + if (this->info_section_ != NULL && this->info_uses_section_index_) flags |= elfcpp::SHF_INFO_LINK; oshdr->put_sh_flags(flags); @@ -2020,12 +2021,21 @@ Output_section::write_header(const Layout* layout, oshdr->put_sh_link(layout->dynsym_section()->out_shndx()); else oshdr->put_sh_link(this->link_); + + elfcpp::Elf_Word info; if (this->info_section_ != NULL) - oshdr->put_sh_info(this->info_section_->out_shndx()); + { + if (this->info_uses_section_index_) + info = this->info_section_->out_shndx(); + else + info = this->info_section_->symtab_index(); + } else if (this->info_symndx_ != NULL) - oshdr->put_sh_info(this->info_symndx_->symtab_index()); + info = this->info_symndx_->symtab_index(); else - oshdr->put_sh_info(this->info_); + info = this->info_; + oshdr->put_sh_info(info); + oshdr->put_sh_addralign(this->addralign_); oshdr->put_sh_entsize(this->entsize_); } diff --git a/gold/output.h b/gold/output.h index b327eb2b7d1..7333513d6e1 100644 --- a/gold/output.h +++ b/gold/output.h @@ -1669,31 +1669,56 @@ class Output_section : public Output_data unsigned int info() const { - gold_assert(this->info_section_ == NULL); + gold_assert(this->info_section_ == NULL + && this->info_symndx_ == NULL); return this->info_; } // Set the info field to the output section index of a section. void - set_info_section(const Output_data* od) + set_info_section(const Output_section* os) { - gold_assert(this->info_symndx_ == NULL && this->info_ == 0); - this->info_section_ = od; + gold_assert((this->info_section_ == NULL + || (this->info_section_ == os + && this->info_uses_section_index_)) + && this->info_symndx_ == NULL + && this->info_ == 0); + this->info_section_ = os; + this->info_uses_section_index_= true; } // Set the info field to the symbol table index of a symbol. void set_info_symndx(const Symbol* sym) { - gold_assert(this->info_section_ == NULL && this->info_ == 0); + gold_assert(this->info_section_ == NULL + && (this->info_symndx_ == NULL + || this->info_symndx_ == sym) + && this->info_ == 0); this->info_symndx_ = sym; } + // Set the info field to the symbol table index of a section symbol. + void + set_info_section_symndx(const Output_section* os) + { + gold_assert((this->info_section_ == NULL + || (this->info_section_ == os + && !this->info_uses_section_index_)) + && this->info_symndx_ == NULL + && this->info_ == 0); + this->info_section_ = os; + this->info_uses_section_index_ = false; + } + // Set the info field to a constant. void set_info(unsigned int v) { - gold_assert(this->info_section_ == NULL && this->info_symndx_ == NULL); + gold_assert(this->info_section_ == NULL + && this->info_symndx_ == NULL + && (this->info_ == 0 + || this->info_ == v)); this->info_ = v; } @@ -1790,6 +1815,17 @@ class Output_section : public Output_data postprocessing_buffer_size() const { return this->current_data_size_for_child(); } + // Modify the section name. This is only permitted for an + // unallocated section, and only before the size has been finalized. + // Otherwise the name will not get into Layout::namepool_. + void + set_name(const char* newname) + { + gold_assert((this->flags_ & elfcpp::SHF_ALLOC) == 0); + gold_assert(!this->is_data_size_valid()); + this->name_ = newname; + } + // Return whether the offset OFFSET in the input section SHNDX in // object OBJECT is being included in the link. bool @@ -1944,17 +1980,6 @@ class Output_section : public Output_data do_tls_offset() const { return this->tls_offset_; } - // Modify the section name. This is only permitted for an - // unallocated section, and only before the size has been finalized. - // Otherwise the name will not get into Layout::namepool_. - void - set_name(const char* newname) - { - gold_assert((this->flags_ & elfcpp::SHF_ALLOC) == 0); - gold_assert(!this->is_data_size_valid()); - this->name_ = newname; - } - // This may be implemented by a child class. virtual void do_finalize_name(Layout*) @@ -2259,7 +2284,7 @@ class Output_section : public Output_data // If link_section_ is NULL, this is the link field. unsigned int link_; // Set the section info field to the index of this section. - const Output_data* info_section_; + const Output_section* info_section_; // If info_section_ is NULL, set the info field to the symbol table // index of this symbol. const Symbol* info_symndx_; @@ -2319,6 +2344,10 @@ class Output_section : public Output_data bool found_in_sections_clause_ : 1; // Whether this section has an explicitly specified load address. bool has_load_address_ : 1; + // True if the info_section_ field means the section index of the + // section, false if it means the symbol index of the corresponding + // section symbol. + bool info_uses_section_index_ : 1; // For SHT_TLS sections, the offset of this section relative to the base // of the TLS segment. uint64_t tls_offset_;