This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

gold patch committed: Change handling for globals in discarded sections


The GNU linker has special handling for symbols defined in discarded
sections.  If the reference is from a debugging section, the GNU
linker does not warn.  I believe that this was initially introduced
for comdat aka linkonce sections, where one can assume that there will
be another definition somewhere.  However, it turns out that it also
applies to sections explicitly discarded by the linker script.

The Linux kernel build currently relies on this behaviour.  The kernel
build defines a bunch of per-cpu symbols in a section which is later
discarded.  This is fine except that references to the symbols remain
in the debug info.  The GNU linker said nothing about this, but gold
gave errors.

I've committed this patch to gold to make it act like the GNU linker
with regard to not warning about references from debugging sections to
global symbols defined in discarded sections.  This should fix the
kernel build.

When I worked on this I also took the opportunity to eliminate a flag
from the Symbol structure, making it 4 bytes smaller on a 32-bit host.

Ian


2010-01-08  Ian Lance Taylor  <iant@google.com>

	PR 11108
	* symtab.h (class Symbol): Remove fields is_target_special_ and
	has_plt_offset_.  Add field is_defined_in_discarded_section_.
	(Symbol::is_defined_in_discarded_section): New function.
	(Symbol::set_is_defined_in_discarded_section): New function.
	(Symbol::has_plt_offset): Rewrite.
	(Symbol::set_plt_offset): Verify that new offset is not -1U.
	* symtab.cc (Symbol::init_fields): Initialize plt_offset_ to -1U.
	Don't initialize is_target_special_ or has_plt_offset_.
	Initialize is_defined_in_discarded_section_.
	(Symbol_table::add_from_relobj): If appropriate, set
	is_defined_in_discarded_section.
	* resolve.cc (Symbol::override_base_with_special): Don't test
	is_target_special_.  Change has_plt_offset_ to has_plt_offset().
	* target-reloc.h (relocate_section): Do special handling for
	symbols defined in discarded sections for global symbols as well
	as local symbols.


Index: resolve.cc
===================================================================
RCS file: /cvs/src/src/gold/resolve.cc,v
retrieving revision 1.50
diff -p -u -r1.50 resolve.cc
--- resolve.cc	5 Jan 2010 22:55:08 -0000	1.50
+++ resolve.cc	9 Jan 2010 00:08:54 -0000
@@ -859,9 +859,8 @@ Symbol::override_base_with_special(const
 
   // We shouldn't see these flags.  If we do, we need to handle them
   // somehow.
-  gold_assert(!from->is_target_special_ || this->is_target_special_);
   gold_assert(!from->is_forwarder_);
-  gold_assert(!from->has_plt_offset_);
+  gold_assert(!from->has_plt_offset());
   gold_assert(!from->has_warning_);
   gold_assert(!from->is_copied_from_dynobj_);
   gold_assert(!from->is_forced_local_);
Index: symtab.cc
===================================================================
RCS file: /cvs/src/src/gold/symtab.cc,v
retrieving revision 1.136
diff -p -u -r1.136 symtab.cc
--- symtab.cc	5 Jan 2010 19:29:15 -0000	1.136
+++ symtab.cc	9 Jan 2010 00:08:54 -0000
@@ -59,24 +59,23 @@ Symbol::init_fields(const char* name, co
   this->symtab_index_ = 0;
   this->dynsym_index_ = 0;
   this->got_offsets_.init();
-  this->plt_offset_ = 0;
+  this->plt_offset_ = -1U;
   this->type_ = type;
   this->binding_ = binding;
   this->visibility_ = visibility;
   this->nonvis_ = nonvis;
-  this->is_target_special_ = false;
   this->is_def_ = false;
   this->is_forwarder_ = false;
   this->has_alias_ = false;
   this->needs_dynsym_entry_ = false;
   this->in_reg_ = false;
   this->in_dyn_ = false;
-  this->has_plt_offset_ = false;
   this->has_warning_ = false;
   this->is_copied_from_dynobj_ = false;
   this->is_forced_local_ = false;
   this->is_ordinary_shndx_ = false;
   this->in_real_elf_ = false;
+  this->is_defined_in_discarded_section_ = false;
 }
 
 // Return the demangled version of the symbol's name, but only
@@ -1070,10 +1069,14 @@ Symbol_table::add_from_relobj(
 
       // A symbol defined in a section which we are not including must
       // be treated as an undefined symbol.
+      bool is_defined_in_discarded_section = false;
       if (st_shndx != elfcpp::SHN_UNDEF
 	  && is_ordinary
 	  && !relobj->is_section_included(st_shndx))
-	st_shndx = elfcpp::SHN_UNDEF;
+	{
+	  st_shndx = elfcpp::SHN_UNDEF;
+	  is_defined_in_discarded_section = true;
+	}
 
       // In an object file, an '@' in the name separates the symbol
       // name from the version name.  If there are two '@' characters,
@@ -1190,6 +1193,9 @@ Symbol_table::add_from_relobj(
       if (is_forced_local)
 	this->force_local(res);
 
+      if (is_defined_in_discarded_section)
+	res->set_is_defined_in_discarded_section();
+
       (*sympointers)[i] = res;
     }
 }
Index: symtab.h
===================================================================
RCS file: /cvs/src/src/gold/symtab.h,v
retrieving revision 1.103
diff -p -u -r1.103 symtab.h
--- symtab.h	31 Dec 2009 05:07:21 -0000	1.103
+++ symtab.h	9 Jan 2010 00:08:54 -0000
@@ -1,6 +1,6 @@
 // symtab.h -- the gold symbol table   -*- C++ -*-
 
-// 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.
@@ -308,6 +308,18 @@ class Symbol
   set_in_real_elf()
   { this->in_real_elf_ = true; }
 
+  // Return whether this symbol was defined in a section that was
+  // discarded from the link.  This is used to control some error
+  // reporting.
+  bool
+  is_defined_in_discarded_section() const
+  { return this->is_defined_in_discarded_section_; }
+
+  // Mark this symbol as having been defined in a discarded section.
+  void
+  set_is_defined_in_discarded_section()
+  { this->is_defined_in_discarded_section_ = true; }
+
   // Return the index of this symbol in the output file symbol table.
   // A value of -1U means that this symbol is not going into the
   // output file.  This starts out as zero, and is set to a non-zero
@@ -383,7 +395,7 @@ class Symbol
   // Return whether this symbol has an entry in the PLT section.
   bool
   has_plt_offset() const
-  { return this->has_plt_offset_; }
+  { return this->plt_offset_ != -1U; }
 
   // Return the offset into the PLT section of this symbol.
   unsigned int
@@ -397,7 +409,7 @@ class Symbol
   void
   set_plt_offset(unsigned int plt_offset)
   {
-    this->has_plt_offset_ = true;
+    gold_assert(plt_offset != -1U);
     this->plt_offset_ = plt_offset;
   }
 
@@ -870,16 +882,14 @@ class Symbol
   // non-zero value during Layout::finalize.
   unsigned int dynsym_index_;
 
-  // If this symbol has an entry in the GOT section (has_got_offset_
-  // is true), this holds the offset from the start of the GOT section.
-  // A symbol may have more than one GOT offset (e.g., when mixing
-  // modules compiled with two different TLS models), but will usually
-  // have at most one.
+  // The GOT section entries for this symbol.  A symbol may have more
+  // than one GOT offset (e.g., when mixing modules compiled with two
+  // different TLS models), but will usually have at most one.
   Got_offset_list got_offsets_;
 
-  // If this symbol has an entry in the PLT section (has_plt_offset_
-  // is true), then this is the offset from the start of the PLT
-  // section.
+  // If this symbol has an entry in the PLT section, then this is the
+  // offset from the start of the PLT section.  This is -1U if there
+  // is no PLT entry.
   unsigned int plt_offset_;
 
   // Symbol type (bits 0 to 3).
@@ -892,10 +902,7 @@ class Symbol
   unsigned int nonvis_ : 6;
   // The type of symbol (bits 16 to 18).
   Source source_ : 3;
-  // True if this symbol always requires special target-specific
-  // handling (bit 19).
-  bool is_target_special_ : 1;
-  // True if this is the default version of the symbol (bit 20).
+  // True if this is the default version of the symbol (bit 19).
   bool is_def_ : 1;
   // True if this symbol really forwards to another symbol.  This is
   // used when we discover after the fact that two different entries
@@ -903,37 +910,38 @@ class Symbol
   // never be set for a symbol found in the hash table, but may be set
   // for a symbol found in the list of symbols attached to an Object.
   // It forwards to the symbol found in the forwarders_ map of
-  // Symbol_table (bit 21).
+  // Symbol_table (bit 20).
   bool is_forwarder_ : 1;
   // True if the symbol has an alias in the weak_aliases table in
-  // Symbol_table (bit 22).
+  // Symbol_table (bit 21).
   bool has_alias_ : 1;
   // True if this symbol needs to be in the dynamic symbol table (bit
-  // 23).
+  // 22).
   bool needs_dynsym_entry_ : 1;
-  // True if we've seen this symbol in a regular object (bit 24).
+  // True if we've seen this symbol in a regular object (bit 23).
   bool in_reg_ : 1;
-  // True if we've seen this symbol in a dynamic object (bit 25).
+  // True if we've seen this symbol in a dynamic object (bit 24).
   bool in_dyn_ : 1;
-  // True if the symbol has an entry in the PLT section (bit 26).
-  bool has_plt_offset_ : 1;
   // True if this is a dynamic symbol which needs a special value in
-  // the dynamic symbol table (bit 27).
+  // the dynamic symbol table (bit 25).
   bool needs_dynsym_value_ : 1;
-  // True if there is a warning for this symbol (bit 28).
+  // True if there is a warning for this symbol (bit 26).
   bool has_warning_ : 1;
   // True if we are using a COPY reloc for this symbol, so that the
-  // real definition lives in a dynamic object (bit 29).
+  // real definition lives in a dynamic object (bit 27).
   bool is_copied_from_dynobj_ : 1;
   // True if this symbol was forced to local visibility by a version
-  // script (bit 30).
+  // script (bit 28).
   bool is_forced_local_ : 1;
   // True if the field u_.from_object.shndx is an ordinary section
   // index, not one of the special codes from SHN_LORESERVE to
-  // SHN_HIRESERVE (bit 31).
+  // SHN_HIRESERVE (bit 29).
   bool is_ordinary_shndx_ : 1;
-  // True if we've seen this symbol in a real ELF object.
+  // True if we've seen this symbol in a real ELF object (bit 30).
   bool in_real_elf_ : 1;
+  // True if this symbol is defined in a section which was discarded
+  // (bit 31).
+  bool is_defined_in_discarded_section_ : 1;
 };
 
 // The parts of a symbol which are size specific.  Using a template
Index: target-reloc.h
===================================================================
RCS file: /cvs/src/src/gold/target-reloc.h,v
retrieving revision 1.37
diff -p -u -r1.37 target-reloc.h
--- target-reloc.h	30 Dec 2009 20:35:52 -0000	1.37
+++ target-reloc.h	9 Jan 2010 00:08:54 -0000
@@ -1,6 +1,6 @@
 // target-reloc.h -- target specific relocation support  -*- C++ -*-
 
-// 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.
@@ -217,6 +217,8 @@ relocate_section(
 
       Symbol_value<size> symval;
       const Symbol_value<size> *psymval;
+      bool is_defined_in_discarded_section;
+      unsigned int shndx;
       if (r_sym < local_count
 	  && (reloc_symbol_changes == NULL
 	      || (*reloc_symbol_changes)[i] == NULL))
@@ -230,38 +232,12 @@ relocate_section(
           // counterpart in the kept section.  The symbol must not 
           // correspond to a section we are folding.
 	  bool is_ordinary;
-	  unsigned int shndx = psymval->input_shndx(&is_ordinary);
-	  if (is_ordinary
-	      && shndx != elfcpp::SHN_UNDEF
-	      && !object->is_section_included(shndx) 
-              && !(relinfo->symtab->is_section_folded(object, shndx)))
-	    {
-	      if (comdat_behavior == CB_UNDETERMINED)
-	        {
-	          std::string name = object->section_name(relinfo->data_shndx);
-	          comdat_behavior = get_comdat_behavior(name.c_str());
-	        }
-	      if (comdat_behavior == CB_PRETEND)
-	        {
-                  bool found;
-	          typename elfcpp::Elf_types<size>::Elf_Addr value =
-	            object->map_to_kept_section(shndx, &found);
-	          if (found)
-	            symval.set_output_value(value + psymval->input_value());
-                  else
-                    symval.set_output_value(0);
-	        }
-	      else
-	        {
-	          if (comdat_behavior == CB_WARNING)
-                    gold_warning_at_location(relinfo, i, offset,
-                                             _("relocation refers to discarded "
-                                               "comdat section"));
-                  symval.set_output_value(0);
-	        }
-	      symval.set_no_output_symtab_entry();
-	      psymval = &symval;
-	    }
+	  shndx = psymval->input_shndx(&is_ordinary);
+	  is_defined_in_discarded_section =
+	    (is_ordinary
+	     && shndx != elfcpp::SHN_UNDEF
+	     && !object->is_section_included(shndx)
+	     && !relinfo->symtab->is_section_folded(object, shndx));
 	}
       else
 	{
@@ -284,6 +260,46 @@ relocate_section(
 	    symval.set_no_output_symtab_entry();
 	  symval.set_output_value(sym->value());
 	  psymval = &symval;
+
+	  is_defined_in_discarded_section =
+	    (gsym->is_defined_in_discarded_section()
+	     && gsym->is_undefined());
+	  shndx = 0;
+	}
+
+      Symbol_value<size> symval2;
+      if (is_defined_in_discarded_section)
+	{
+	  if (comdat_behavior == CB_UNDETERMINED)
+	    {
+	      std::string name = object->section_name(relinfo->data_shndx);
+	      comdat_behavior = get_comdat_behavior(name.c_str());
+	    }
+	  if (comdat_behavior == CB_PRETEND)
+	    {
+	      // FIXME: This case does not work for global symbols.
+	      // We have no place to store the original section index.
+	      // Fortunately this does not matter for comdat sections,
+	      // only for sections explicitly discarded by a linker
+	      // script.
+	      bool found;
+	      typename elfcpp::Elf_types<size>::Elf_Addr value =
+		object->map_to_kept_section(shndx, &found);
+	      if (found)
+		symval2.set_output_value(value + psymval->input_value());
+	      else
+		symval2.set_output_value(0);
+	    }
+	  else
+	    {
+	      if (comdat_behavior == CB_WARNING)
+		gold_warning_at_location(relinfo, i, offset,
+					 _("relocation refers to discarded "
+					   "section"));
+	      symval2.set_output_value(0);
+	    }
+	  symval2.set_no_output_symtab_entry();
+	  psymval = &symval2;
 	}
 
       if (!relocate.relocate(relinfo, target, output_section, i, reloc,
@@ -302,6 +318,7 @@ relocate_section(
       if (sym != NULL
 	  && sym->is_undefined()
 	  && sym->binding() != elfcpp::STB_WEAK
+	  && !is_defined_in_discarded_section
           && !target->is_defined_by_abi(sym)
 	  && (!parameters->options().shared()       // -shared
               || parameters->options().defs()))     // -z defs

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]