Fix group signature handling for relocatable link, add bootstrap
authorIan Lance Taylor <iant@google.com>
Wed, 6 Feb 2008 19:32:32 +0000 (19:32 +0000)
committerIan Lance Taylor <iant@google.com>
Wed, 6 Feb 2008 19:32:32 +0000 (19:32 +0000)
relocatable test.

gold/Makefile.am
gold/Makefile.in
gold/gold.cc
gold/layout.cc
gold/layout.h
gold/output.cc
gold/output.h

index cef759ed55a11f9ca8de1e3ace1f2fa333376892..0f09afad60b07c12484d6f8bd90773a0569dfe23 100644 (file)
@@ -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
index 22bae570c807812d5228fcb94e182038c5c1077e..a315718e6274688409c75fe30cd48c0664ff886b 100644 (file)
@@ -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:
index 2aee1b76c81ea9ab71ff0709a9fdcd51cbe0ac20..71dac861798453b3be3d3eacd32cd8d999ee7bc9 100644 (file)
@@ -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
index 006a3842daf6d9f188344f3fceefbb59429927f8..8b17f83ab4fe01b8aa911506a8e6913a8dbbd758 100644 (file)
@@ -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.
 
index e050df36b925380215b0ce8e891a5897ecb7520e..674956e68891751fac9a47569897b33ad0016370 100644 (file)
@@ -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_signature> 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
index 0e05ff778ea12d9856464917f569c6427968a116..332aa2cf2c687be9d284b24fdf1449d377a58dd2 100644 (file)
@@ -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_);
 }
index b327eb2b7d1c2147a8d567d9e9da2206d8064a92..7333513d6e1e43915c1a1a376a168b454f23dc8a 100644 (file)
@@ -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_;