gdb: add target_ops::supports_displaced_step
[deliverable/binutils-gdb.git] / gold / symtab.h
index b89fd6641316667f7679637fcb04ffbc438818ec..913ccdebca1c64d19bdd36cd53e68c3b3140632f 100644 (file)
@@ -1,6 +1,6 @@
 // symtab.h -- the gold symbol table   -*- C++ -*-
 
-// Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
+// Copyright (C) 2006-2020 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
 // Symbol_table
 //   The symbol table.
 
+#ifndef GOLD_SYMTAB_H
+#define GOLD_SYMTAB_H
+
 #include <string>
 #include <utility>
 #include <vector>
 
-#include "gc.h"
-#include "icf.h"
 #include "elfcpp.h"
 #include "parameters.h"
 #include "stringpool.h"
 #include "object.h"
 
-#ifndef GOLD_SYMTAB_H
-#define GOLD_SYMTAB_H
-
 namespace gold
 {
 
@@ -44,12 +42,14 @@ class Mapfile;
 class Object;
 class Relobj;
 template<int size, bool big_endian>
-class Sized_relobj;
+class Sized_relobj_file;
 template<int size, bool big_endian>
 class Sized_pluginobj;
 class Dynobj;
 template<int size, bool big_endian>
 class Sized_dynobj;
+template<int size, bool big_endian>
+class Sized_incrobj;
 class Versions;
 class Version_script_info;
 class Input_objects;
@@ -62,7 +62,7 @@ class Garbage_collection;
 class Icf;
 
 // The base class of an entry in the symbol table.  The symbol table
-// can have a lot of entries, so we don't want this class to big.
+// can have a lot of entries, so we don't want this class too big.
 // Size dependent fields can be found in the template class
 // Sized_symbol.  Targets may support their own derived classes.
 
@@ -121,6 +121,10 @@ class Symbol
   version() const
   { return this->version_; }
 
+  void
+  clear_version()
+  { this->version_ = NULL; }
+
   // Return whether this version is the default for this symbol name
   // (eg, "foo@@V2" is a default version; "foo@V1" is not).  Only
   // meaningful for versioned symbols.
@@ -136,6 +140,15 @@ class Symbol
   set_is_default()
   { this->is_def_ = true; }
 
+  // Set that this version is not the default for this symbol name.
+  void
+  set_is_not_default()
+  { this->is_def_ = false; }
+
+  // Return the symbol's name as name@version (or name@@version).
+  std::string
+  versioned_name() const;
+
   // Return the symbol source.
   Source
   source() const
@@ -146,7 +159,7 @@ class Symbol
   object() const
   {
     gold_assert(this->source_ == FROM_OBJECT);
-    return this->u_.from_object.object;
+    return this->u1_.object;
   }
 
   // Return the index of the section in the input relocatable or
@@ -156,7 +169,7 @@ class Symbol
   {
     gold_assert(this->source_ == FROM_OBJECT);
     *is_ordinary = this->is_ordinary_shndx_;
-    return this->u_.from_object.shndx;
+    return this->u2_.shndx;
   }
 
   // Return the output data section with which this symbol is
@@ -166,7 +179,7 @@ class Symbol
   output_data() const
   {
     gold_assert(this->source_ == IN_OUTPUT_DATA);
-    return this->u_.in_output_data.output_data;
+    return this->u1_.output_data;
   }
 
   // If this symbol was defined with respect to an output data
@@ -175,7 +188,7 @@ class Symbol
   offset_is_from_end() const
   {
     gold_assert(this->source_ == IN_OUTPUT_DATA);
-    return this->u_.in_output_data.offset_is_from_end;
+    return this->u2_.offset_is_from_end;
   }
 
   // Return the output segment with which this symbol is associated,
@@ -185,7 +198,7 @@ class Symbol
   output_segment() const
   {
     gold_assert(this->source_ == IN_OUTPUT_SEGMENT);
-    return this->u_.in_output_segment.output_segment;
+    return this->u1_.output_segment;
   }
 
   // If this symbol was defined with respect to an output segment,
@@ -194,7 +207,7 @@ class Symbol
   offset_base() const
   {
     gold_assert(this->source_ == IN_OUTPUT_SEGMENT);
-    return this->u_.in_output_segment.offset_base;
+    return this->u2_.offset_base;
   }
 
   // Return the symbol binding.
@@ -207,6 +220,19 @@ class Symbol
   type() const
   { return this->type_; }
 
+  // Set the symbol type.
+  void
+  set_type(elfcpp::STT type)
+  { this->type_ = type; }
+
+  // Return true for function symbol.
+  bool
+  is_func() const
+  {
+    return (this->type_ == elfcpp::STT_FUNC
+           || this->type_ == elfcpp::STT_GNU_IFUNC);
+  }
+
   // Return the symbol visibility.
   elfcpp::STV
   visibility() const
@@ -221,11 +247,34 @@ class Symbol
   void
   override_visibility(elfcpp::STV);
 
+  // Set whether the symbol was originally a weak undef or a regular undef
+  // when resolved by a dynamic def or by a special symbol.
+  inline void
+  set_undef_binding(elfcpp::STB bind)
+  {
+    if (!this->undef_binding_set_ || this->undef_binding_weak_)
+      {
+        this->undef_binding_weak_ = bind == elfcpp::STB_WEAK;
+        this->undef_binding_set_ = true;
+      }
+  }
+
+  // Return TRUE if a weak undef was resolved by a dynamic def or
+  // by a special symbol.
+  inline bool
+  is_undef_binding_weak() const
+  { return this->undef_binding_weak_; }
+
   // Return the non-visibility part of the st_other field.
   unsigned char
   nonvis() const
   { return this->nonvis_; }
 
+  // Set the non-visibility part of the st_other field.
+  void
+  set_nonvis(unsigned int nonvis)
+  { this->nonvis_ = nonvis; }
+
   // Return whether this symbol is a forwarder.  This will never be
   // true of a symbol found in the hash table, but may be true of
   // symbol pointers attached to object files.
@@ -255,7 +304,9 @@ class Symbol
   needs_dynsym_entry() const
   {
     return (this->needs_dynsym_entry_
-            || (this->in_reg() && this->in_dyn()));
+            || (this->in_reg()
+               && this->in_dyn()
+               && this->is_externally_visible()));
   }
 
   // Mark this symbol as needing an entry in the dynamic symbol table.
@@ -266,7 +317,7 @@ class Symbol
   // Return whether this symbol should be added to the dynamic symbol
   // table.
   bool
-  should_add_dynsym_entry() const;
+  should_add_dynsym_entry(Symbol_table*) const;
 
   // Return whether this symbol has been seen in a regular object.
   bool
@@ -278,6 +329,11 @@ class Symbol
   set_in_reg()
   { this->in_reg_ = true; }
 
+  // Forget this symbol was seen in a regular object.
+  void
+  clear_in_reg()
+  { this->in_reg_ = false; }
+
   // Return whether this symbol has been seen in a dynamic object.
   bool
   in_dyn() const
@@ -288,6 +344,11 @@ class Symbol
   set_in_dyn()
   { this->in_dyn_ = true; }
 
+  // Return whether this symbol is defined in a dynamic object.
+  bool
+  from_dyn() const
+  { return this->source_ == FROM_OBJECT && this->object()->is_dynamic(); }
+
   // Return whether this symbol has been seen in a real ELF object.
   // (IN_REG will return TRUE if the symbol has been seen in either
   // a real ELF object or an object claimed by a plugin.)
@@ -300,6 +361,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
@@ -372,10 +445,15 @@ class Symbol
   set_got_offset(unsigned int got_type, unsigned int got_offset)
   { this->got_offsets_.set_offset(got_type, got_offset); }
 
+  // Return the GOT offset list.
+  const Got_offset_list*
+  got_offset_list() const
+  { return this->got_offsets_.get_list(); }
+
   // 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
@@ -389,7 +467,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;
   }
 
@@ -439,6 +517,13 @@ class Symbol
     return this->source_ == FROM_OBJECT && this->object()->is_dynamic();
   }
 
+  // Return whether this is a placeholder symbol from a plugin object.
+  bool
+  is_placeholder() const
+  {
+    return this->source_ == FROM_OBJECT && this->object()->pluginobj() != NULL;
+  }
+
   // Return whether this is an undefined symbol.
   bool
   is_undefined() const
@@ -453,7 +538,22 @@ class Symbol
   // Return whether this is a weak undefined symbol.
   bool
   is_weak_undefined() const
-  { return this->is_undefined() && this->binding() == elfcpp::STB_WEAK; }
+  {
+    return (this->is_undefined()
+           && (this->binding() == elfcpp::STB_WEAK
+               || this->is_undef_binding_weak()
+               || parameters->options().weak_unresolved_symbols()));
+  }
+
+  // Return whether this is a strong undefined symbol.
+  bool
+  is_strong_undefined() const
+  {
+    return (this->is_undefined()
+           && this->binding() != elfcpp::STB_WEAK
+           && !this->is_undef_binding_weak()
+           && !parameters->options().weak_unresolved_symbols());
+  }
 
   // Return whether this is an absolute symbol.
   bool
@@ -470,8 +570,6 @@ class Symbol
   bool
   is_common() const
   {
-    if (this->type_ == elfcpp::STT_COMMON)
-      return true;
     if (this->source_ != FROM_OBJECT)
       return false;
     bool is_ordinary;
@@ -483,8 +581,9 @@ class Symbol
   bool
   is_externally_visible() const
   {
-    return (this->visibility_ == elfcpp::STV_DEFAULT
-            || this->visibility_ == elfcpp::STV_PROTECTED);
+    return ((this->visibility_ == elfcpp::STV_DEFAULT
+             || this->visibility_ == elfcpp::STV_PROTECTED)
+           && !this->is_forced_local_);
   }
 
   // Return true if this symbol can be preempted by a definition in
@@ -516,7 +615,11 @@ class Symbol
     if (!parameters->options().shared())
       return false;
 
-    // If the user used -Bsymbolic, then nothing is preemptible.
+    // If the symbol was named in a --dynamic-list script, it is preemptible.
+    if (parameters->options().in_dynamic_list(this->name()))
+      return true;
+
+    // If the user used -Bsymbolic, then nothing (else) is preemptible.
     if (parameters->options().Bsymbolic())
       return false;
 
@@ -533,9 +636,6 @@ class Symbol
   }
 
   // Return true if this symbol is a function that needs a PLT entry.
-  // If the symbol is defined in a dynamic object or if it is subject
-  // to pre-emption, we need to make a PLT entry. If we're doing a
-  // static link, we don't create PLT entries.
   bool
   needs_plt_entry() const
   {
@@ -543,24 +643,48 @@ class Symbol
     if (this->is_undefined() && !parameters->options().shared())
       return false;
 
-    return (!parameters->doing_static_link()
-            && this->type() == elfcpp::STT_FUNC
-            && (this->is_from_dynobj()
-                || this->is_undefined()
-                || this->is_preemptible()));
+    // An STT_GNU_IFUNC symbol always needs a PLT entry, even when
+    // doing a static link.
+    if (this->type() == elfcpp::STT_GNU_IFUNC)
+      return true;
+
+    // We only need a PLT entry for a function.
+    if (!this->is_func())
+      return false;
+
+    // If we're doing a static link or a -pie link, we don't create
+    // PLT entries.
+    if (parameters->doing_static_link()
+       || parameters->options().pie())
+      return false;
+
+    // We need a PLT entry if the function is defined in a dynamic
+    // object, or is undefined when building a shared object, or if it
+    // is subject to pre-emption.
+    return (this->is_from_dynobj()
+           || this->is_undefined()
+           || this->is_preemptible());
   }
 
   // When determining whether a reference to a symbol needs a dynamic
   // relocation, we need to know several things about the reference.
-  // These flags may be or'ed together.
+  // These flags may be or'ed together.  0 means that the symbol
+  // isn't referenced at all.
   enum Reference_flags
   {
-    // Reference to the symbol's absolute address.
+    // A reference to the symbol's absolute address.  This includes
+    // references that cause an absolute address to be stored in the GOT.
     ABSOLUTE_REF = 1,
-    // A non-PIC reference.
-    NON_PIC_REF = 2,
-    // A function call.
-    FUNCTION_CALL = 4
+    // A reference that calculates the offset of the symbol from some
+    // anchor point, such as the PC or GOT.
+    RELATIVE_REF = 2,
+    // A TLS-related reference.
+    TLS_REF = 4,
+    // A reference that can always be treated as a function call.
+    FUNCTION_CALL = 8,
+    // When set, says that dynamic relocations are needed even if a
+    // symbol has a plt entry.
+    FUNC_DESC_ABI = 16,
   };
 
   // Given a direct absolute or pc-relative static relocation against
@@ -591,16 +715,14 @@ class Symbol
       return true;
 
     // A function call that can branch to a local PLT entry does not need
-    // a dynamic relocation.  A non-pic pc-relative function call in a
-    // shared library cannot use a PLT entry.
-    if ((flags & FUNCTION_CALL)
-        && this->has_plt_offset()
-        && !((flags & NON_PIC_REF) && parameters->options().shared()))
+    // a dynamic relocation.
+    if ((flags & FUNCTION_CALL) && this->has_plt_offset())
       return false;
 
     // A reference to any PLT entry in a non-position-independent executable
     // does not need a dynamic relocation.
-    if (!parameters->options().output_is_position_independent()
+    if (!(flags & FUNC_DESC_ABI)
+       && !parameters->options().output_is_position_independent()
         && this->has_plt_offset())
       return false;
 
@@ -616,24 +738,23 @@ class Symbol
   }
 
   // Whether we should use the PLT offset associated with a symbol for
-  // a relocation.  IS_NON_PIC_REFERENCE is true if this is a non-PIC
-  // reloc--the same set of relocs for which we would pass NON_PIC_REF
-  // to the needs_dynamic_reloc function.
+  // a relocation.  FLAGS is a set of Reference_flags.
 
   bool
-  use_plt_offset(bool is_non_pic_reference) const
+  use_plt_offset(int flags) const
   {
     // If the symbol doesn't have a PLT offset, then naturally we
     // don't want to use it.
     if (!this->has_plt_offset())
       return false;
 
+    // For a STT_GNU_IFUNC symbol we always have to use the PLT entry.
+    if (this->type() == elfcpp::STT_GNU_IFUNC)
+      return true;
+
     // If we are going to generate a dynamic relocation, then we will
     // wind up using that, so no need to use the PLT entry.
-    if (this->needs_dynamic_reloc(FUNCTION_CALL
-                                 | (is_non_pic_reference
-                                    ? NON_PIC_REF
-                                    : 0)))
+    if (this->needs_dynamic_reloc(flags))
       return false;
 
     // If the symbol is from a dynamic object, we need to use the PLT
@@ -647,10 +768,10 @@ class Symbol
        && (this->is_undefined() || this->is_preemptible()))
       return true;
 
-    // If this is a weak undefined symbol, we need to use the PLT
-    // entry; the symbol may be defined by a library loaded at
-    // runtime.
-    if (this->is_weak_undefined())
+    // If this is a call to a weak undefined symbol, we need to use
+    // the PLT entry; the symbol may be defined by a library loaded
+    // at runtime.
+    if ((flags & FUNCTION_CALL) && this->is_weak_undefined())
       return true;
 
     // Otherwise we can use the regular definition.
@@ -672,7 +793,7 @@ class Symbol
       return true;
 
     // A reference to a symbol defined in a dynamic object or to a
-    // symbol that is preemptible can not use a RELATIVE relocaiton.
+    // symbol that is preemptible can not use a RELATIVE relocation.
     if (this->is_from_dynobj()
         || this->is_undefined()
         || this->is_preemptible())
@@ -693,6 +814,18 @@ class Symbol
   void
   set_output_section(Output_section*);
 
+  // Set the symbol's output segment.  This is used for pre-defined
+  // symbols whose segments aren't known until after layout is done
+  // (e.g., __ehdr_start).
+  void
+  set_output_segment(Output_segment*, Segment_offset_base);
+
+  // Set the symbol to undefined.  This is used for pre-defined
+  // symbols whose segments aren't known until after layout is done
+  // (e.g., __ehdr_start).
+  void
+  set_undefined();
+
   // Return whether there should be a warning for references to this
   // symbol.
   bool
@@ -726,11 +859,62 @@ class Symbol
   set_is_forced_local()
   { this->is_forced_local_ = true; }
 
+  // Return true if this may need a COPY relocation.
+  // References from an executable object to non-function symbols
+  // defined in a dynamic object may need a COPY relocation.
+  bool
+  may_need_copy_reloc() const
+  {
+    return (parameters->options().copyreloc()
+           && this->is_from_dynobj()
+           && !this->is_func());
+  }
+
+  // Return true if this symbol was predefined by the linker.
+  bool
+  is_predefined() const
+  { return this->is_predefined_; }
+
+  // Return true if this is a C++ vtable symbol.
+  bool
+  is_cxx_vtable() const
+  { return is_prefix_of("_ZTV", this->name_); }
+
+  // Return true if this symbol is protected in a shared object.
+  // This is not the same as checking if visibility() == elfcpp::STV_PROTECTED,
+  // because the visibility_ field reflects the symbol's visibility from
+  // outside the shared object.
+  bool
+  is_protected() const
+  { return this->is_protected_; }
+
+  // Mark this symbol as protected in a shared object.
+  void
+  set_is_protected()
+  { this->is_protected_ = true; }
+
+  // Return state of PowerPC64 ELFv2 specific flag.
+  bool
+  non_zero_localentry() const
+  { return this->non_zero_localentry_; }
+
+  // Set PowerPC64 ELFv2 specific flag.
+  void
+  set_non_zero_localentry()
+  { this->non_zero_localentry_ = true; }
+
+  // Completely override existing symbol.  Everything bar name_,
+  // version_, and is_forced_local_ flag are copied.  version_ is
+  // cleared if from->version_ is clear.  Returns true if this symbol
+  // should be forced local.
+  bool
+  clone(const Symbol* from);
+
  protected:
   // Instances of this class should always be created at a specific
   // size.
   Symbol()
-  { memset(this, 0, sizeof *this); }
+  { memset(static_cast<void*>(this), 0, sizeof *this); }
 
   // Initialize the general fields.
   void
@@ -743,7 +927,7 @@ class Symbol
   // index rather than a special code.
   template<int size, bool big_endian>
   void
-  init_base_object(const char *name, const char* version, Object* object,
+  init_base_object(const charname, const char* version, Object* object,
                   const elfcpp::Sym<size, big_endian>&, unsigned int st_shndx,
                   bool is_ordinary);
 
@@ -751,7 +935,8 @@ class Symbol
   void
   init_base_output_data(const char* name, const char* version, Output_data*,
                        elfcpp::STT, elfcpp::STB, elfcpp::STV,
-                       unsigned char nonvis, bool offset_is_from_end);
+                       unsigned char nonvis, bool offset_is_from_end,
+                       bool is_predefined);
 
   // Initialize fields for an Output_segment.
   void
@@ -759,13 +944,14 @@ class Symbol
                           Output_segment* os, elfcpp::STT type,
                           elfcpp::STB binding, elfcpp::STV visibility,
                           unsigned char nonvis,
-                          Segment_offset_base offset_base);
+                          Segment_offset_base offset_base,
+                          bool is_predefined);
 
   // Initialize fields for a constant.
   void
   init_base_constant(const char* name, const char* version, elfcpp::STT type,
                     elfcpp::STB binding, elfcpp::STV visibility,
-                    unsigned char nonvis);
+                    unsigned char nonvis, bool is_predefined);
 
   // Initialize fields for an undefined symbol.
   void
@@ -804,38 +990,38 @@ class Symbol
 
   union
   {
-    // This struct is used if SOURCE_ == FROM_OBJECT.
-    struct
-    {
-      // Object in which symbol is defined, or in which it was first
-      // seen.
-      Object* object;
-      // Section number in object_ in which symbol is defined.
-      unsigned int shndx;
-    } from_object;
-
-    // This struct is used if SOURCE_ == IN_OUTPUT_DATA.
-    struct
-    {
-      // Output_data in which symbol is defined.  Before
-      // Layout::finalize the symbol's value is an offset within the
-      // Output_data.
-      Output_data* output_data;
-      // True if the offset is from the end, false if the offset is
-      // from the beginning.
-      bool offset_is_from_end;
-    } in_output_data;
-
-    // This struct is used if SOURCE_ == IN_OUTPUT_SEGMENT.
-    struct
-    {
-      // Output_segment in which the symbol is defined.  Before
-      // Layout::finalize the symbol's value is an offset.
-      Output_segment* output_segment;
-      // The base to use for the offset before Layout::finalize.
-      Segment_offset_base offset_base;
-    } in_output_segment;
-  } u_;
+    // This is used if SOURCE_ == FROM_OBJECT.
+    // Object in which symbol is defined, or in which it was first
+    // seen.
+    Object* object;
+
+    // This is used if SOURCE_ == IN_OUTPUT_DATA.
+    // Output_data in which symbol is defined.  Before
+    // Layout::finalize the symbol's value is an offset within the
+    // Output_data.
+    Output_data* output_data;
+
+    // This is used if SOURCE_ == IN_OUTPUT_SEGMENT.
+    // Output_segment in which the symbol is defined.  Before
+    // Layout::finalize the symbol's value is an offset.
+    Output_segment* output_segment;
+  } u1_;
+
+  union
+  {
+    // This is used if SOURCE_ == FROM_OBJECT.
+    // Section number in object in which symbol is defined.
+    unsigned int shndx;
+
+    // This is used if SOURCE_ == IN_OUTPUT_DATA.
+    // True if the offset is from the end, false if the offset is
+    // from the beginning.
+    bool offset_is_from_end;
+
+    // This is used if SOURCE_ == IN_OUTPUT_SEGMENT.
+    // The base to use for the offset before Layout::finalize.
+    Segment_offset_base offset_base;
+  } u2_;
 
   // The index of this symbol in the output file.  If the symbol is
   // not going into the output file, this value is -1U.  This field
@@ -849,18 +1035,16 @@ 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.
-  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_;
 
+  // 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_;
+
   // Symbol type (bits 0 to 3).
   elfcpp::STT type_ : 4;
   // Symbol binding (bits 4 to 7).
@@ -871,10 +1055,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
@@ -882,37 +1063,56 @@ 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
+  // True if the field u2_.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).
+  // If the symbol has been seen in a relocatable, non-IR, object file,
+  // it's known to be referenced from outside the IR.  A reference from
+  // a dynamic object doesn't count as a "real" ELF, and we'll simply
+  // mark the symbol as "visible" from outside the IR.  The compiler
+  // can use this distinction to guide its handling of COMDAT symbols.
   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;
+  // True if UNDEF_BINDING_WEAK_ has been set (bit 32).
+  bool undef_binding_set_ : 1;
+  // True if this symbol was a weak undef resolved by a dynamic def
+  // or by a special symbol (bit 33).
+  bool undef_binding_weak_ : 1;
+  // True if this symbol is a predefined linker symbol (bit 34).
+  bool is_predefined_ : 1;
+  // True if this symbol has protected visibility in a shared object (bit 35).
+  // The visibility_ field will be STV_DEFAULT in this case because we
+  // must treat it as such from outside the shared object.
+  bool is_protected_  : 1;
+  // Used by PowerPC64 ELFv2 to track st_other localentry (bit 36).
+  bool non_zero_localentry_ : 1;
 };
 
 // The parts of a symbol which are size specific.  Using a template
@@ -933,7 +1133,7 @@ class Sized_symbol : public Symbol
   // index rather than a special code.
   template<bool big_endian>
   void
-  init_object(const char *name, const char* version, Object* object,
+  init_object(const charname, const char* version, Object* object,
              const elfcpp::Sym<size, big_endian>&, unsigned int st_shndx,
              bool is_ordinary);
 
@@ -942,25 +1142,25 @@ class Sized_symbol : public Symbol
   init_output_data(const char* name, const char* version, Output_data*,
                   Value_type value, Size_type symsize, elfcpp::STT,
                   elfcpp::STB, elfcpp::STV, unsigned char nonvis,
-                  bool offset_is_from_end);
+                  bool offset_is_from_end, bool is_predefined);
 
   // Initialize fields for an Output_segment.
   void
   init_output_segment(const char* name, const char* version, Output_segment*,
                      Value_type value, Size_type symsize, elfcpp::STT,
                      elfcpp::STB, elfcpp::STV, unsigned char nonvis,
-                     Segment_offset_base offset_base);
+                     Segment_offset_base offset_base, bool is_predefined);
 
   // Initialize fields for a constant.
   void
   init_constant(const char* name, const char* version, Value_type value,
                Size_type symsize, elfcpp::STT, elfcpp::STB, elfcpp::STV,
-               unsigned char nonvis);
+               unsigned char nonvis, bool is_predefined);
 
   // Initialize fields for an undefined symbol.
   void
-  init_undefined(const char* name, const char* version, elfcpp::STT,
-                elfcpp::STB, elfcpp::STV, unsigned char nonvis);
+  init_undefined(const char* name, const char* version, Value_type value,
+                elfcpp::STT, elfcpp::STB, elfcpp::STV, unsigned char nonvis);
 
   // Override existing symbol.
   template<bool big_endian>
@@ -999,6 +1199,13 @@ class Sized_symbol : public Symbol
   void
   allocate_common(Output_data*, Value_type value);
 
+  // Completely override existing symbol.  Everything bar name_,
+  // version_, and is_forced_local_ flag are copied.  version_ is
+  // cleared if from->version_ is clear.  Returns true if this symbol
+  // should be forced local.
+  bool
+  clone(const Sized_symbol<size>* from);
+
  private:
   Sized_symbol(const Sized_symbol&);
   Sized_symbol& operator=(const Sized_symbol&);
@@ -1083,6 +1290,35 @@ struct Define_symbol_in_segment
   bool only_if_ref;
 };
 
+// Specify an object/section/offset location.  Used by ODR code.
+
+struct Symbol_location
+{
+  // Object where the symbol is defined.
+  Object* object;
+  // Section-in-object where the symbol is defined.
+  unsigned int shndx;
+  // For relocatable objects, offset-in-section where the symbol is defined.
+  // For dynamic objects, address where the symbol is defined.
+  off_t offset;
+  bool operator==(const Symbol_location& that) const
+  {
+    return (this->object == that.object
+           && this->shndx == that.shndx
+           && this->offset == that.offset);
+  }
+};
+
+// A map from symbol name (as a pointer into the namepool) to all
+// the locations the symbols is (weakly) defined (and certain other
+// conditions are met).  This map will be used later to detect
+// possible One Definition Rule (ODR) violations.
+struct Symbol_location_hash
+{
+  size_t operator()(const Symbol_location& loc) const
+  { return reinterpret_cast<uintptr_t>(loc.object) ^ loc.offset ^ loc.shndx; }
+};
+
 // This class manages warnings.  Warnings are a GNU extension.  When
 // we see a section named .gnu.warning.SYM in an object file, and if
 // we wind using the definition of SYM from that object file, then we
@@ -1157,7 +1393,35 @@ class Warnings
 class Symbol_table
 {
  public:
-  // COUNT is an estimate of how many symbosl will be inserted in the
+  // The different places where a symbol definition can come from.
+  enum Defined
+  {
+    // Defined in an object file--the normal case.
+    OBJECT,
+    // Defined for a COPY reloc.
+    COPY,
+    // Defined on the command line using --defsym.
+    DEFSYM,
+    // Defined (so to speak) on the command line using -u.
+    UNDEFINED,
+    // Defined in a linker script.
+    SCRIPT,
+    // Predefined by the linker.
+    PREDEFINED,
+    // Defined by the linker during an incremental base link, but not
+    // a predefined symbol (e.g., common, defined in script).
+    INCREMENTAL_BASE,
+  };
+
+  // The order in which we sort common symbols.
+  enum Sort_commons_order
+  {
+    SORT_COMMONS_BY_SIZE_DESCENDING,
+    SORT_COMMONS_BY_ALIGNMENT_DESCENDING,
+    SORT_COMMONS_BY_ALIGNMENT_ASCENDING
+  };
+
+  // COUNT is an estimate of how many symbols will be inserted in the
   // symbol table.  It's ok to put 0 if you don't know; a correct
   // guess will just save some CPU by reducing hashtable resizes.
   Symbol_table(unsigned int count, const Version_script_info& version_script);
@@ -1174,7 +1438,7 @@ class Symbol_table
  
   // Returns true if ICF determined that this is a duplicate section. 
   bool
-  is_section_folded(Object* obj, unsigned int shndx) const;
+  is_section_folded(Relobj* obj, unsigned int shndx) const;
 
   void
   set_gc(Garbage_collection* gc)
@@ -1186,12 +1450,11 @@ class Symbol_table
 
   // During garbage collection, this keeps undefined symbols.
   void
-  gc_mark_undef_symbols(); 
+  gc_mark_undef_symbols(Layout*);
 
-  // During garbage collection, this ensures externally visible symbols
-  // are not treated as garbage while building shared objects.
+  // This tells garbage collection that this symbol is referenced.
   void
-  gc_mark_symbol_for_shlib(Symbol* sym);
+  gc_mark_symbol(Symbol* sym);
 
   // During garbage collection, this keeps sections that correspond to 
   // symbols seen in dynamic objects.
@@ -1206,11 +1469,11 @@ class Symbol_table
   // *DEFINED to the number of defined symbols.
   template<int size, bool big_endian>
   void
-  add_from_relobj(Sized_relobj<size, big_endian>* relobj,
+  add_from_relobj(Sized_relobj_file<size, big_endian>* relobj,
                  const unsigned char* syms, size_t count,
                  size_t symndx_offset, const char* sym_names,
                  size_t sym_name_size,
-                 typename Sized_relobj<size, big_endian>::Symbols*,
+                 typename Sized_relobj_file<size, big_endian>::Symbols*,
                  size_t* defined);
 
   // Add one external symbol from the plugin object OBJ to the symbol table.
@@ -1232,13 +1495,20 @@ class Symbol_table
                  const char* sym_names, size_t sym_name_size,
                  const unsigned char* versym, size_t versym_size,
                  const std::vector<const char*>*,
-                 typename Sized_relobj<size, big_endian>::Symbols*,
+                 typename Sized_relobj_file<size, big_endian>::Symbols*,
                  size_t* defined);
 
+  // Add one external symbol from the incremental object OBJ to the symbol
+  // table.  Returns a pointer to the resolved symbol in the symbol table.
+  template<int size, bool big_endian>
+  Sized_symbol<size>*
+  add_from_incrobj(Object* obj, const char* name,
+                  const char* ver, elfcpp::Sym<size, big_endian>* sym);
+
   // Define a special symbol based on an Output_data.  It is a
   // multiple definition error if this symbol is already defined.
   Symbol*
-  define_in_output_data(const char* name, const char* version,
+  define_in_output_data(const char* name, const char* version, Defined,
                        Output_data*, uint64_t value, uint64_t symsize,
                        elfcpp::STT type, elfcpp::STB binding,
                        elfcpp::STV visibility, unsigned char nonvis,
@@ -1247,7 +1517,7 @@ class Symbol_table
   // Define a special symbol based on an Output_segment.  It is a
   // multiple definition error if this symbol is already defined.
   Symbol*
-  define_in_output_segment(const char* name, const char* version,
+  define_in_output_segment(const char* name, const char* version, Defined,
                           Output_segment*, uint64_t value, uint64_t symsize,
                           elfcpp::STT type, elfcpp::STB binding,
                           elfcpp::STV visibility, unsigned char nonvis,
@@ -1256,7 +1526,7 @@ class Symbol_table
   // Define a special symbol with a constant value.  It is a multiple
   // definition error if this symbol is already defined.
   Symbol*
-  define_as_constant(const char* name, const char* version,
+  define_as_constant(const char* name, const char* version, Defined,
                     uint64_t value, uint64_t symsize, elfcpp::STT type,
                     elfcpp::STB binding, elfcpp::STV visibility,
                     unsigned char nonvis, bool only_if_ref,
@@ -1274,6 +1544,12 @@ class Symbol_table
   define_symbols(const Layout*, int count, const Define_symbol_in_segment*,
                 bool only_if_ref);
 
+  // Add a target-specific global symbol.
+  // (Used by SPARC backend to add STT_SPARC_REGISTER symbols.)
+  void
+  add_target_global_symbol(Symbol* sym)
+  { this->target_symbols_.push_back(sym); }
+
   // Define SYM using a COPY reloc.  POSD is the Output_data where the
   // symbol should be defined--typically a .dyn.bss section.  VALUE is
   // the offset within POSD.
@@ -1300,10 +1576,14 @@ class Symbol_table
   get_sized_symbol(const Symbol*) const;
 
   // Return the count of undefined symbols seen.
-  int
+  size_t
   saw_undefined() const
   { return this->saw_undefined_; }
 
+  void
+  set_has_gnu_output()
+  { this->has_gnu_output_ = true; }
+
   // Allocate the common symbols
   void
   allocate_commons(Layout*, Mapfile*);
@@ -1336,7 +1616,7 @@ class Symbol_table
   // Add any undefined symbols named on the command line to the symbol
   // table.
   void
-  add_undefined_symbols_from_command_line();
+  add_undefined_symbols_from_command_line(Layout*);
 
   // SYM is defined using a COPY reloc.  Return the dynamic object
   // where the original definition was found.
@@ -1344,12 +1624,13 @@ class Symbol_table
   get_copy_source(const Symbol* sym) const;
 
   // Set the dynamic symbol indexes.  INDEX is the index of the first
-  // global dynamic symbol.  Pointers to the symbols are stored into
+  // global dynamic symbol.  Return the count of forced-local symbols in
+  // *PFORCED_LOCAL_COUNT.  Pointers to the symbols are stored into
   // the vector.  The names are stored into the Stringpool.  This
   // returns an updated dynamic symbol index.
   unsigned int
-  set_dynsym_indexes(unsigned int index, std::vector<Symbol*>*,
-                    Stringpool*, Versions*);
+  set_dynsym_indexes(unsigned int index, unsigned int* pforced_local_count,
+                    std::vector<Symbol*>*, Stringpool*, Versions*);
 
   // Finalize the symbol table after we have set the final addresses
   // of all the input sections.  This sets the final symbol indexes,
@@ -1363,7 +1644,42 @@ class Symbol_table
   // local symbols.
   off_t
   finalize(off_t off, off_t dynoff, size_t dyn_global_index, size_t dyncount,
-          Stringpool* pool, unsigned int *plocal_symcount);
+          Stringpool* pool, unsigned int* plocal_symcount);
+
+  // Set the final file offset of the symbol table.
+  void
+  set_file_offset(off_t off)
+  { this->offset_ = off; }
+
+  // Status code of Symbol_table::compute_final_value.
+  enum Compute_final_value_status
+  {
+    // No error.
+    CFVS_OK,
+    // Unsupported symbol section.
+    CFVS_UNSUPPORTED_SYMBOL_SECTION,
+    // No output section.
+    CFVS_NO_OUTPUT_SECTION
+  };
+
+  // Compute the final value of SYM and store status in location PSTATUS.
+  // During relaxation, this may be called multiple times for a symbol to 
+  // compute its would-be final value in each relaxation pass.
+
+  template<int size>
+  typename Sized_symbol<size>::Value_type
+  compute_final_value(const Sized_symbol<size>* sym,
+                     Compute_final_value_status* pstatus) const;
+
+  // Return the index of the first global symbol.
+  unsigned int
+  first_global_index() const
+  { return this->first_global_index_; }
+
+  // Return the total number of symbols in the symbol table.
+  unsigned int
+  output_count() const
+  { return this->output_count_; }
 
   // Write out the global symbols.
   void
@@ -1376,6 +1692,20 @@ class Symbol_table
   write_section_symbol(const Output_section*, Output_symtab_xindex*,
                       Output_file*, off_t) const;
 
+  // Loop over all symbols, applying the function F to each.
+  template<int size, typename F>
+  void
+  for_all_symbols(F f) const
+  {
+    for (Symbol_table_type::const_iterator p = this->table_.begin();
+         p != this->table_.end();
+         ++p)
+      {
+       Sized_symbol<size>* sym = static_cast<Sized_symbol<size>*>(p->second);
+       f(sym);
+      }
+  }
+
   // Dump statistical information to stderr.
   void
   print_stats() const;
@@ -1385,6 +1715,15 @@ class Symbol_table
   version_script() const
   { return version_script_; }
 
+  // Completely override existing symbol.
+  template<int size>
+  void
+  clone(Sized_symbol<size>* to, const Sized_symbol<size>* from)
+  {
+    if (to->clone(from))
+      this->force_local(to);
+  }
+
  private:
   Symbol_table(const Symbol_table&);
   Symbol_table& operator=(const Symbol_table&);
@@ -1396,10 +1735,14 @@ class Symbol_table
 
   typedef std::pair<Stringpool::Key, Stringpool::Key> Symbol_table_key;
 
+  // The hash function.  The key values are Stringpool keys.
   struct Symbol_table_hash
   {
-    size_t
-    operator()(const Symbol_table_key&) const;
+    inline size_t
+    operator()(const Symbol_table_key& key) const
+    {
+      return key.first ^ key.second;
+    }
   };
 
   struct Symbol_table_eq
@@ -1411,6 +1754,10 @@ class Symbol_table
   typedef Unordered_map<Symbol_table_key, Symbol*, Symbol_table_hash,
                        Symbol_table_eq> Symbol_table_type;
 
+  typedef Unordered_map<const char*,
+                        Unordered_set<Symbol_location, Symbol_location_hash> >
+  Odr_map;
+
   // Make FROM a forwarder symbol to TO.
   void
   make_forwarder(Symbol* from, Symbol* to);
@@ -1418,8 +1765,8 @@ class Symbol_table
   // Add a symbol.
   template<int size, bool big_endian>
   Sized_symbol<size>*
-  add_from_object(Object*, const char *name, Stringpool::Key name_key,
-                 const char *version, Stringpool::Key version_key,
+  add_from_object(Object*, const charname, Stringpool::Key name_key,
+                 const charversion, Stringpool::Key version_key,
                  bool def, const elfcpp::Sym<size, big_endian>& sym,
                  unsigned int st_shndx, bool is_ordinary,
                  unsigned int orig_st_shndx);
@@ -1437,7 +1784,8 @@ class Symbol_table
          const elfcpp::Sym<size, big_endian>& sym,
          unsigned int st_shndx, bool is_ordinary,
          unsigned int orig_st_shndx,
-         Object*, const char* version);
+         Object*, const char* version,
+         bool is_default_version);
 
   template<int size, bool big_endian>
   void
@@ -1450,12 +1798,18 @@ class Symbol_table
 
   // Adjust NAME and *NAME_KEY for wrapping.
   const char*
-  wrap_symbol(Object* object, const char*, Stringpool::Key* name_key);
+  wrap_symbol(const char* name, Stringpool::Key* name_key);
 
   // Whether we should override a symbol, based on flags in
   // resolve.cc.
   static bool
-  should_override(const Symbol*, unsigned int, Object*, bool*);
+  should_override(const Symbol*, unsigned int, elfcpp::STT, Defined,
+                 Object*, bool*, bool*, bool);
+
+  // Report a problem in symbol resolution.
+  static void
+  report_resolve_problem(bool is_error, const char* msg, const Symbol* to,
+                        Defined, Object* object);
 
   // Override a symbol.
   template<int size, bool big_endian>
@@ -1468,7 +1822,7 @@ class Symbol_table
   // Whether we should override a symbol with a special symbol which
   // is automatically defined by the linker.
   static bool
-  should_override_with_special(const Symbol*);
+  should_override_with_special(const Symbol*, elfcpp::STT, Defined);
 
   // Override a symbol with a special symbol.
   template<int size>
@@ -1485,13 +1839,15 @@ class Symbol_table
   template<int size, bool big_endian>
   Sized_symbol<size>*
   define_special_symbol(const char** pname, const char** pversion,
-                       bool only_if_ref, Sized_symbol<size>** poldsym,
-                       bool* resolve_oldsym);
+                       bool only_if_ref, elfcpp::STV visibility,
+                       Sized_symbol<size>** poldsym,
+                       bool* resolve_oldsym, bool is_forced_local);
 
   // Define a symbol in an Output_data, sized version.
   template<int size>
   Sized_symbol<size>*
-  do_define_in_output_data(const char* name, const char* version, Output_data*,
+  do_define_in_output_data(const char* name, const char* version, Defined,
+                          Output_data*,
                           typename elfcpp::Elf_types<size>::Elf_Addr value,
                           typename elfcpp::Elf_types<size>::Elf_WXword ssize,
                           elfcpp::STT type, elfcpp::STB binding,
@@ -1502,7 +1858,7 @@ class Symbol_table
   template<int size>
   Sized_symbol<size>*
   do_define_in_output_segment(
-    const char* name, const char* version, Output_segment* os,
+    const char* name, const char* version, Defined, Output_segment* os,
     typename elfcpp::Elf_types<size>::Elf_Addr value,
     typename elfcpp::Elf_types<size>::Elf_WXword ssize,
     elfcpp::STT type, elfcpp::STB binding,
@@ -1513,7 +1869,7 @@ class Symbol_table
   template<int size>
   Sized_symbol<size>*
   do_define_as_constant(
-    const char* name, const char* version,
+    const char* name, const char* version, Defined,
     typename elfcpp::Elf_types<size>::Elf_Addr value,
     typename elfcpp::Elf_types<size>::Elf_WXword ssize,
     elfcpp::STT type, elfcpp::STB binding,
@@ -1524,7 +1880,12 @@ class Symbol_table
   // table, sized version.
   template<int size>
   void
-  do_add_undefined_symbols_from_command_line();
+  do_add_undefined_symbols_from_command_line(Layout*);
+
+  // Add one undefined symbol.
+  template<int size>
+  void
+  add_undefined_symbol_from_command_line(const char* name);
 
   // Types of common symbols.
 
@@ -1539,13 +1900,19 @@ class Symbol_table
   // Allocate the common symbols, sized version.
   template<int size>
   void
-  do_allocate_commons(Layout*, Mapfile*);
+  do_allocate_commons(Layout*, Mapfile*, Sort_commons_order);
 
   // Allocate the common symbols from one list.
   template<int size>
   void
   do_allocate_commons_list(Layout*, Commons_section_type, Commons_type*,
-                          Mapfile*);
+                          Mapfile*, Sort_commons_order);
+
+  // Returns all of the lines attached to LOC, not just the one the
+  // instruction actually came from.  This helps the ODR checker avoid
+  // false positives.
+  static std::vector<std::string>
+  linenos_from_loc(const Task* task, const Symbol_location& loc);
 
   // Implement detect_odr_violations.
   template<int size, bool big_endian>
@@ -1580,7 +1947,7 @@ class Symbol_table
   void
   sized_write_symbol(Sized_symbol<size>*,
                     typename elfcpp::Elf_types<size>::Elf_Addr value,
-                    unsigned int shndx,
+                    unsigned int shndx, elfcpp::STB,
                     const Stringpool*, unsigned char* p) const;
 
   // Possibly warn about an undefined symbol from a dynamic object.
@@ -1600,36 +1967,9 @@ class Symbol_table
   // they are defined.
   typedef Unordered_map<const Symbol*, Dynobj*> Copied_symbol_dynobjs;
 
-  // A map from symbol name (as a pointer into the namepool) to all
-  // the locations the symbols is (weakly) defined (and certain other
-  // conditions are met).  This map will be used later to detect
-  // possible One Definition Rule (ODR) violations.
-  struct Symbol_location
-  {
-    Object* object;         // Object where the symbol is defined.
-    unsigned int shndx;     // Section-in-object where the symbol is defined.
-    off_t offset;           // Offset-in-section where the symbol is defined.
-    bool operator==(const Symbol_location& that) const
-    {
-      return (this->object == that.object
-              && this->shndx == that.shndx
-              && this->offset == that.offset);
-    }
-  };
-
-  struct Symbol_location_hash
-  {
-    size_t operator()(const Symbol_location& loc) const
-    { return reinterpret_cast<uintptr_t>(loc.object) ^ loc.offset ^ loc.shndx; }
-  };
-
-  typedef Unordered_map<const char*,
-                        Unordered_set<Symbol_location, Symbol_location_hash> >
-  Odr_map;
-
   // We increment this every time we see a new undefined symbol, for
   // use in archive groups.
-  int saw_undefined_;
+  size_t saw_undefined_;
   // The index of the first global symbol in the output file.
   unsigned int first_global_index_;
   // The file offset within the output symtab section where we should
@@ -1639,10 +1979,14 @@ class Symbol_table
   unsigned int output_count_;
   // The file offset of the global dynamic symbols, or 0 if none.
   off_t dynamic_offset_;
-  // The index of the first global dynamic symbol.
+  // The index of the first global dynamic symbol (including
+  // forced-local symbols).
   unsigned int first_dynamic_global_index_;
-  // The number of global dynamic symbols, or 0 if none.
+  // The number of global dynamic symbols (including forced-local symbols),
+  // or 0 if none.
   unsigned int dynamic_count_;
+  // Set if a STT_GNU_IFUNC or STB_GNU_UNIQUE symbol will be output.
+  bool has_gnu_output_;
   // The symbol hash table.
   Symbol_table_type table_;
   // A pool of symbol names.  This is used for all global symbols.
@@ -1685,6 +2029,8 @@ class Symbol_table
   const Version_script_info& version_script_;
   Garbage_collection* gc_;
   Icf* icf_;
+  // Target-specific symbols, if any.
+  std::vector<Symbol*> target_symbols_;
 };
 
 // We inline get_sized_symbol for efficiency.
This page took 0.040039 seconds and 4 git commands to generate.