gas: run the hwcaps-bump tests with 64-bit sparc objects only.
[deliverable/binutils-gdb.git] / gold / symtab.cc
index c1972210d67600d49705679dcb035e51d1758576..c872f47d38638540278e1dcc05caee1195d88f5d 100644 (file)
@@ -1,6 +1,6 @@
 // symtab.cc -- the gold symbol table
 
-// Copyright (C) 2006-2015 Free Software Foundation, Inc.
+// Copyright (C) 2006-2016 Free Software Foundation, Inc.
 // Written by Ian Lance Taylor <iant@google.com>.
 
 // This file is part of gold.
@@ -80,6 +80,7 @@ Symbol::init_fields(const char* name, const char* version,
   this->undef_binding_set_ = false;
   this->undef_binding_weak_ = false;
   this->is_predefined_ = false;
+  this->is_protected_ = false;
 }
 
 // Return the demangled version of the symbol's name, but only
@@ -285,11 +286,12 @@ Sized_symbol<size>::init_constant(const char* name, const char* version,
 template<int size>
 void
 Sized_symbol<size>::init_undefined(const char* name, const char* version,
-                                  elfcpp::STT type, elfcpp::STB binding,
-                                  elfcpp::STV visibility, unsigned char nonvis)
+                                  Value_type value, elfcpp::STT type,
+                                  elfcpp::STB binding, elfcpp::STV visibility,
+                                  unsigned char nonvis)
 {
   this->init_base_undefined(name, version, type, binding, visibility, nonvis);
-  this->value_ = 0;
+  this->value_ = value;
   this->symsize_ = 0;
 }
 
@@ -565,7 +567,8 @@ Symbol_table::Symbol_table(unsigned int count,
   : saw_undefined_(0), offset_(0), table_(count), namepool_(),
     forwarders_(), commons_(), tls_commons_(), small_commons_(),
     large_commons_(), forced_locals_(), warnings_(),
-    version_script_(version_script), gc_(NULL), icf_(NULL)
+    version_script_(version_script), gc_(NULL), icf_(NULL),
+    target_symbols_()
 {
   namepool_.reserve(count);
 }
@@ -585,7 +588,7 @@ Symbol_table::Symbol_table_eq::operator()(const Symbol_table_key& k1,
 }
 
 bool
-Symbol_table::is_section_folded(Object* obj, unsigned int shndx) const
+Symbol_table::is_section_folded(Relobj* obj, unsigned int shndx) const
 {
   return (parameters->options().icf_enabled()
           && this->icf_->is_section_folded(obj, shndx));
@@ -650,10 +653,11 @@ Symbol_table::gc_mark_symbol(Symbol* sym)
   // Add the object and section to the work list.
   bool is_ordinary;
   unsigned int shndx = sym->shndx(&is_ordinary);
-  if (is_ordinary && shndx != elfcpp::SHN_UNDEF)
+  if (is_ordinary && shndx != elfcpp::SHN_UNDEF && !sym->object()->is_dynamic())
     {
       gold_assert(this->gc_!= NULL);
-      this->gc_->worklist().push_back(Section_id(sym->object(), shndx));
+      Relobj* relobj = static_cast<Relobj*>(sym->object());
+      this->gc_->worklist().push_back(Section_id(relobj, shndx));
     }
   parameters->target().gc_mark_symbol(this, sym);
 }
@@ -736,7 +740,7 @@ Symbol_table::resolve(Sized_symbol<size>* to, const Sized_symbol<size>* from)
   bool is_ordinary;
   unsigned int shndx = from->shndx(&is_ordinary);
   this->resolve(to, esym.sym(), shndx, is_ordinary, shndx, from->object(),
-               from->version());
+               from->version(), true);
   if (from->in_reg())
     to->set_in_reg();
   if (from->in_dyn())
@@ -862,6 +866,9 @@ Symbol_table::define_default_version(Sized_symbol<size>* sym,
       // other is defined in a shared object, then they are different
       // symbols.
 
+      // If the two symbols are from different shared objects,
+      // they are different symbols.
+
       // Otherwise, we just resolve the symbols as though they were
       // the same.
 
@@ -873,6 +880,11 @@ Symbol_table::define_default_version(Sized_symbol<size>* sym,
       else if (pdef->second->visibility() != elfcpp::STV_DEFAULT
               && sym->is_from_dynobj())
        ;
+      else if (pdef->second->is_from_dynobj()
+              && sym->is_from_dynobj()
+              && pdef->second->is_defined()
+              && pdef->second->object() != sym->object())
+        ;
       else
        {
          const Sized_symbol<size>* symdef;
@@ -990,13 +1002,40 @@ Symbol_table::add_from_object(Object* object,
       was_common = ret->is_common() && ret->object()->pluginobj() == NULL;
 
       this->resolve(ret, sym, st_shndx, is_ordinary, orig_st_shndx, object,
-                   version);
+                   version, is_default_version);
       if (parameters->options().gc_sections())
         this->gc_mark_dyn_syms(ret);
 
       if (is_default_version)
        this->define_default_version<size, big_endian>(ret, insdefault.second,
                                                       insdefault.first);
+      else
+       {
+         bool dummy;
+         if (version != NULL
+             && ret->source() == Symbol::FROM_OBJECT
+             && ret->object() == object
+             && is_ordinary
+             && ret->shndx(&dummy) == st_shndx
+             && ret->is_default())
+           {
+             // We have seen NAME/VERSION already, and marked it as the
+             // default version, but now we see a definition for
+             // NAME/VERSION that is not the default version. This can
+             // happen when the assembler generates two symbols for
+             // a symbol as a result of a ".symver foo,foo@VER"
+             // directive. We see the first unversioned symbol and
+             // we may mark it as the default version (from a
+             // version script); then we see the second versioned
+             // symbol and we need to override the first.
+             // In any other case, the two symbols should have generated
+             // a multiple definition error.
+             // (See PR gold/18703.)
+             ret->set_is_not_default();
+             const Stringpool::Key vnull_key = 0;
+             this->table_.erase(std::make_pair(name_key, vnull_key));
+           }
+       }
     }
   else
     {
@@ -1014,7 +1053,7 @@ Symbol_table::add_from_object(Object* object,
          was_common = ret->is_common() && ret->object()->pluginobj() == NULL;
 
          this->resolve(ret, sym, st_shndx, is_ordinary, orig_st_shndx, object,
-                       version);
+                       version, is_default_version);
           if (parameters->options().gc_sections())
             this->gc_mark_dyn_syms(ret);
          ins.first->second = ret;
@@ -1030,7 +1069,8 @@ Symbol_table::add_from_object(Object* object,
            ret = new Sized_symbol<size>();
          else
            {
-             ret = target->make_symbol();
+             ret = target->make_symbol(name, sym.get_st_type(), object,
+                                       st_shndx, sym.get_st_value());
              if (ret == NULL)
                {
                  // This means that we don't want a symbol table
@@ -1143,7 +1183,8 @@ Symbol_table::add_from_relobj(
 
       const char* name = sym_names + st_name;
 
-      if (strcmp (name, "__gnu_lto_slim") == 0)
+      if (!parameters->options().relocatable()
+         && strcmp (name, "__gnu_lto_slim") == 0)
         gold_info(_("%s: plugin needed to handle lto object"),
                  relobj->name().c_str());
 
@@ -1285,6 +1326,9 @@ Symbol_table::add_from_relobj(
       res = this->add_from_object(relobj, name, name_key, ver, ver_key,
                                  is_default_version, *psym, st_shndx,
                                  is_ordinary, orig_st_shndx);
+
+      if (res == NULL)
+       continue;
       
       if (is_forced_local)
        this->force_local(res);
@@ -1366,6 +1410,9 @@ Symbol_table::add_from_pluginobj(
                              is_default_version, *sym, st_shndx,
                              is_ordinary, st_shndx);
 
+  if (res == NULL)
+    return NULL;
+
   if (is_forced_local)
     this->force_local(res);
 
@@ -1440,14 +1487,20 @@ Symbol_table::add_from_dynobj(
       // A protected symbol in a shared library must be treated as a
       // normal symbol when viewed from outside the shared library.
       // Implement this by overriding the visibility here.
+      // Likewise, an IFUNC symbol in a shared library must be treated
+      // as a normal FUNC symbol.
       elfcpp::Sym<size, big_endian>* psym = &sym;
       unsigned char symbuf[sym_size];
       elfcpp::Sym<size, big_endian> sym2(symbuf);
-      if (sym.get_st_visibility() == elfcpp::STV_PROTECTED)
+      if (sym.get_st_visibility() == elfcpp::STV_PROTECTED
+         || sym.get_st_type() == elfcpp::STT_GNU_IFUNC)
        {
          memcpy(symbuf, p, sym_size);
          elfcpp::Sym_write<size, big_endian> sw(symbuf);
-         sw.put_st_other(elfcpp::STV_DEFAULT, sym.get_st_nonvis());
+         if (sym.get_st_visibility() == elfcpp::STV_PROTECTED)
+           sw.put_st_other(elfcpp::STV_DEFAULT, sym.get_st_nonvis());
+         if (sym.get_st_type() == elfcpp::STT_GNU_IFUNC)
+           sw.put_st_info(sym.get_st_bind(), elfcpp::STT_FUNC);
          psym = &sym2;
        }
 
@@ -1556,6 +1609,9 @@ Symbol_table::add_from_dynobj(
            }
        }
 
+      if (res == NULL)
+       continue;
+
       // Note that it is possible that RES was overridden by an
       // earlier object, in which case it can't be aliased here.
       if (st_shndx != elfcpp::SHN_UNDEF
@@ -1565,6 +1621,13 @@ Symbol_table::add_from_dynobj(
          && res->object() == dynobj)
        object_symbols.push_back(res);
 
+      // If the symbol has protected visibility in the dynobj,
+      // mark it as such if it was not overridden.
+      if (res->source() == Symbol::FROM_OBJECT
+          && res->object() == dynobj
+          && sym.get_st_visibility() == elfcpp::STV_PROTECTED)
+        res->set_is_protected();
+
       if (sympointers != NULL)
        (*sympointers)[i] = res;
     }
@@ -1587,7 +1650,6 @@ Symbol_table::add_from_incrobj(
 
   Stringpool::Key ver_key = 0;
   bool is_default_version = false;
-  bool is_forced_local = false;
 
   Stringpool::Key name_key;
   name = this->namepool_.add(name, true, &name_key);
@@ -1597,9 +1659,6 @@ Symbol_table::add_from_incrobj(
                              is_default_version, *sym, st_shndx,
                              is_ordinary, st_shndx);
 
-  if (is_forced_local)
-    this->force_local(res);
-
   return res;
 }
 
@@ -1823,7 +1882,8 @@ Symbol_table::define_special_symbol(const char** pname, const char** pversion,
     {
       Sized_target<size, big_endian>* sized_target =
        parameters->sized_target<size, big_endian>();
-      sym = sized_target->make_symbol();
+      sym = sized_target->make_symbol(*pname, elfcpp::STT_NOTYPE,
+                                     NULL, elfcpp::SHN_UNDEF, 0);
       if (sym == NULL)
         return NULL;
     }
@@ -1952,6 +2012,10 @@ Symbol_table::do_define_in_output_data(
     return sym;
   else
     {
+      if (defined == PREDEFINED
+         && (binding == elfcpp::STB_LOCAL
+             || this->version_script_.symbol_is_local(name)))
+       this->force_local(oldsym);
       delete sym;
       return oldsym;
     }
@@ -2066,6 +2130,9 @@ Symbol_table::do_define_in_output_segment(
     return sym;
   else
     {
+      if (binding == elfcpp::STB_LOCAL
+         || this->version_script_.symbol_is_local(name))
+       this->force_local(oldsym);
       delete sym;
       return oldsym;
     }
@@ -2185,6 +2252,9 @@ Symbol_table::do_define_as_constant(
     return sym;
   else
     {
+      if (binding == elfcpp::STB_LOCAL
+         || this->version_script_.symbol_is_local(name))
+       this->force_local(oldsym);
       delete sym;
       return oldsym;
     }
@@ -2392,7 +2462,7 @@ Symbol_table::add_undefined_symbol_from_command_line(const char* name)
 
   gold_assert(oldsym == NULL);
 
-  sym->init_undefined(name, version, elfcpp::STT_NOTYPE, elfcpp::STB_GLOBAL,
+  sym->init_undefined(name, version, 0, elfcpp::STT_NOTYPE, elfcpp::STB_GLOBAL,
                      elfcpp::STV_DEFAULT, 0);
   ++this->saw_undefined_;
 }
@@ -2489,6 +2559,17 @@ Symbol_table::set_dynsym_indexes(unsigned int index,
   // symbols.
   index = versions->finalize(this, index, syms);
 
+  // Process target-specific symbols.
+  for (std::vector<Symbol*>::iterator p = this->target_symbols_.begin();
+       p != this->target_symbols_.end();
+       ++p)
+    {
+      (*p)->set_dynsym_index(index);
+      ++index;
+      syms->push_back(*p);
+      dynpool->add((*p)->name(), false, NULL);
+    }
+
   return index;
 }
 
@@ -2594,6 +2675,14 @@ Symbol_table::sized_finalize(off_t off, Stringpool* pool,
        this->add_to_final_symtab<size>(sym, pool, &index, &off);
     }
 
+  // Now do target-specific symbols.
+  for (std::vector<Symbol*>::iterator p = this->target_symbols_.begin();
+       p != this->target_symbols_.end();
+       ++p)
+    {
+      this->add_to_final_symtab<size>(*p, pool, &index, &off);
+    }
+
   this->output_count_ = index - orig_index;
 
   return off;
@@ -2920,6 +3009,13 @@ Symbol_table::sized_write_globals(const Stringpool* sympool,
       typename elfcpp::Elf_types<size>::Elf_Addr dynsym_value = sym_value;
       elfcpp::STB binding = sym->binding();
 
+      // If --weak-unresolved-symbols is set, change binding of unresolved
+      // global symbols to STB_WEAK.
+      if (parameters->options().weak_unresolved_symbols()
+         && binding == elfcpp::STB_GLOBAL
+         && sym->is_undefined())
+       binding = elfcpp::STB_WEAK;
+
       // If --no-gnu-unique is set, change STB_GNU_UNIQUE to STB_GLOBAL.
       if (binding == elfcpp::STB_GNU_UNIQUE
          && !parameters->options().gnu_unique())
@@ -3056,6 +3152,54 @@ Symbol_table::sized_write_globals(const Stringpool* sympool,
        }
     }
 
+  // Write the target-specific symbols.
+  for (std::vector<Symbol*>::const_iterator p = this->target_symbols_.begin();
+       p != this->target_symbols_.end();
+       ++p)
+    {
+      Sized_symbol<size>* sym = static_cast<Sized_symbol<size>*>(*p);
+
+      unsigned int sym_index = sym->symtab_index();
+      unsigned int dynsym_index;
+      if (dynamic_view == NULL)
+       dynsym_index = -1U;
+      else
+       dynsym_index = sym->dynsym_index();
+
+      unsigned int shndx;
+      switch (sym->source())
+       {
+       case Symbol::IS_CONSTANT:
+         shndx = elfcpp::SHN_ABS;
+         break;
+       case Symbol::IS_UNDEFINED:
+         shndx = elfcpp::SHN_UNDEF;
+         break;
+       default:
+         gold_unreachable();
+       }
+
+      if (sym_index != -1U)
+       {
+         sym_index -= first_global_index;
+         gold_assert(sym_index < output_count);
+         unsigned char* ps = psyms + (sym_index * sym_size);
+         this->sized_write_symbol<size, big_endian>(sym, sym->value(), shndx,
+                                                    sym->binding(), sympool,
+                                                    ps);
+       }
+
+      if (dynsym_index != -1U)
+       {
+         dynsym_index -= first_dynamic_global_index;
+         gold_assert(dynsym_index < dynamic_count);
+         unsigned char* pd = dynamic_view + (dynsym_index * sym_size);
+         this->sized_write_symbol<size, big_endian>(sym, sym->value(), shndx,
+                                                    sym->binding(), dynpool,
+                                                    pd);
+       }
+    }
+
   of->write_output_view(this->offset_, oview_size, psyms);
   if (dynamic_view != NULL)
     of->write_output_view(this->dynamic_offset_, dynamic_size, dynamic_view);
@@ -3086,10 +3230,7 @@ Symbol_table::sized_write_symbol(
   else
     osym.put_st_size(sym->symsize());
   elfcpp::STT type = sym->type();
-  // Turn IFUNC symbols from shared libraries into normal FUNC symbols.
-  if (type == elfcpp::STT_GNU_IFUNC
-      && sym->is_from_dynobj())
-    type = elfcpp::STT_FUNC;
+  gold_assert(type != elfcpp::STT_GNU_IFUNC || !sym->is_from_dynobj());
   // A version script may have overridden the default binding.
   if (sym->is_forced_local())
     osym.put_st_info(elfcpp::elf_st_info(elfcpp::STB_LOCAL, type));
@@ -3697,6 +3838,21 @@ Sized_symbol<32>::init_output_data(const char* name, const char* version,
                                   unsigned char nonvis,
                                   bool offset_is_from_end,
                                   bool is_predefined);
+
+template
+void
+Sized_symbol<32>::init_constant(const char* name, const char* version,
+                               Value_type value, Size_type symsize,
+                               elfcpp::STT type, elfcpp::STB binding,
+                               elfcpp::STV visibility, unsigned char nonvis,
+                               bool is_predefined);
+
+template
+void
+Sized_symbol<32>::init_undefined(const char* name, const char* version,
+                                Value_type value, elfcpp::STT type,
+                                elfcpp::STB binding, elfcpp::STV visibility,
+                                unsigned char nonvis);
 #endif
 
 #if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
@@ -3710,6 +3866,21 @@ Sized_symbol<64>::init_output_data(const char* name, const char* version,
                                   unsigned char nonvis,
                                   bool offset_is_from_end,
                                   bool is_predefined);
+
+template
+void
+Sized_symbol<64>::init_constant(const char* name, const char* version,
+                               Value_type value, Size_type symsize,
+                               elfcpp::STT type, elfcpp::STB binding,
+                               elfcpp::STV visibility, unsigned char nonvis,
+                               bool is_predefined);
+
+template
+void
+Sized_symbol<64>::init_undefined(const char* name, const char* version,
+                                Value_type value, elfcpp::STT type,
+                                elfcpp::STB binding, elfcpp::STV visibility,
+                                unsigned char nonvis);
 #endif
 
 #ifdef HAVE_TARGET_32_LITTLE
This page took 0.031012 seconds and 4 git commands to generate.