PR 11108
authorIan Lance Taylor <ian@airs.com>
Sat, 9 Jan 2010 00:13:48 +0000 (00:13 +0000)
committerIan Lance Taylor <ian@airs.com>
Sat, 9 Jan 2010 00:13:48 +0000 (00:13 +0000)
* 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.

gold/ChangeLog
gold/resolve.cc
gold/symtab.cc
gold/symtab.h
gold/target-reloc.h

index 046d87aceaaf44c0de2631cdecb4595eaade2e2e..37a28f11e61a54a6e8a6e5d9bb3da4ad05298cb7 100644 (file)
@@ -1,3 +1,23 @@
+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.
+
 2010-01-08  Ian Lance Taylor  <iant@google.com>
 
        * dynobj.cc (big_endian>::find_dynsym_sections): Set pi to NULL in
index ca71264d4df429db454080ed75754db2d8195103..9a402f39277e97ccb6da798691336ffc9b74663a 100644 (file)
@@ -859,9 +859,8 @@ Symbol::override_base_with_special(const Symbol* from)
 
   // 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 984843863e8ab7f925ac94ec6a5e8855d611e8ae..92a91bc1012ebcc2c99cde3f5bda605a2ef6d9a0 100644 (file)
@@ -59,24 +59,23 @@ Symbol::init_fields(const char* name, const char* version,
   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 f79fc8d26533ea2def468abb4f2d475b4de5e267..c8aac26bd8e649e8a0f780c60d1e13958d7a7cce 100644 (file)
@@ -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 25b3ac435320ee03bf44c9a4841b2f8cf4f97b57..06597e2124fcab4154a1be8ea35dbf67a682fdd5 100644 (file)
@@ -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