PR ld/10515
[binutils-gdb.git] / gold / symtab.cc
index 3d179ef035dbafa2959756d9e8eb0934525a2dca..292a26275dec2b3e224fe778019b2bbf256d678a 100644 (file)
@@ -280,6 +280,16 @@ Sized_symbol<size>::init_undefined(const char* name, const char* version,
   this->symsize_ = 0;
 }
 
+// Return true if SHNDX represents a common symbol.
+
+bool
+Symbol::is_common_shndx(unsigned int shndx)
+{
+  return (shndx == elfcpp::SHN_COMMON
+         || shndx == parameters->target().small_common_shndx()
+         || shndx == parameters->target().large_common_shndx());
+}
+
 // Allocate a common symbol.
 
 template<int size>
@@ -477,8 +487,9 @@ Symbol::set_output_section(Output_section* os)
 Symbol_table::Symbol_table(unsigned int count,
                            const Version_script_info& version_script)
   : saw_undefined_(0), offset_(0), table_(count), namepool_(),
-    forwarders_(), commons_(), tls_commons_(), forced_locals_(), warnings_(),
-    version_script_(version_script), gc_(NULL)
+    forwarders_(), commons_(), tls_commons_(), small_commons_(),
+    large_commons_(), forced_locals_(), warnings_(),
+    version_script_(version_script), gc_(NULL), icf_(NULL)
 {
   namepool_.reserve(count);
 }
@@ -505,6 +516,13 @@ Symbol_table::Symbol_table_eq::operator()(const Symbol_table_key& k1,
   return k1.first == k2.first && k1.second == k2.second;
 }
 
+bool
+Symbol_table::is_section_folded(Object* obj, unsigned int shndx) const
+{
+  return (parameters->options().icf()
+          && this->icf_->is_section_folded(obj, shndx));
+}
+
 // For symbols that have been listed with -u option, add them to the
 // work list to avoid gc'ing them.
 
@@ -975,10 +993,16 @@ Symbol_table::add_from_object(Object* object,
   // allocation.
   if (!was_common && ret->is_common())
     {
-      if (ret->type() != elfcpp::STT_TLS)
-       this->commons_.push_back(ret);
-      else
+      if (ret->type() == elfcpp::STT_TLS)
        this->tls_commons_.push_back(ret);
+      else if (!is_ordinary
+              && st_shndx == parameters->target().small_common_shndx())
+       this->small_commons_.push_back(ret);
+      else if (!is_ordinary
+              && st_shndx == parameters->target().large_common_shndx())
+       this->large_commons_.push_back(ret);
+      else
+       this->commons_.push_back(ret);
     }
 
   // If we're not doing a relocatable link, then any symbol with
@@ -2370,10 +2394,9 @@ Symbol_table::sized_finalize_symbol(Symbol* unsized_sym)
        bool is_ordinary;
        unsigned int shndx = sym->shndx(&is_ordinary);
 
-       // FIXME: We need some target specific support here.
        if (!is_ordinary
            && shndx != elfcpp::SHN_ABS
-           && shndx != elfcpp::SHN_COMMON)
+           && !Symbol::is_common_shndx(shndx))
          {
            gold_error(_("%s: unsupported symbol section 0x%x"),
                       sym->demangled_name().c_str(), shndx);
@@ -2394,14 +2417,29 @@ Symbol_table::sized_finalize_symbol(Symbol* unsized_sym)
        else if (shndx == elfcpp::SHN_UNDEF)
          value = 0;
        else if (!is_ordinary
-                && (shndx == elfcpp::SHN_ABS || shndx == elfcpp::SHN_COMMON))
+                && (shndx == elfcpp::SHN_ABS
+                    || Symbol::is_common_shndx(shndx)))
          value = sym->value();
        else
          {
            Relobj* relobj = static_cast<Relobj*>(symobj);
            Output_section* os = relobj->output_section(shndx);
+            uint64_t secoff64 = relobj->output_section_offset(shndx);
 
-           if (os == NULL)
+            if (this->is_section_folded(relobj, shndx))
+              {
+                gold_assert(os == NULL);
+                // Get the os of the section it is folded onto.
+                Section_id folded = this->icf_->get_folded_section(relobj,
+                                                                   shndx);
+                gold_assert(folded.first != NULL);
+                Relobj* folded_obj = reinterpret_cast<Relobj*>(folded.first);
+                os = folded_obj->output_section(folded.second);  
+                gold_assert(os != NULL);
+                secoff64 = folded_obj->output_section_offset(folded.second);
+              }
+
+           if (os == NULL)
              {
                sym->set_symtab_index(-1U);
                 bool static_or_reloc = (parameters->doing_static_link() ||
@@ -2411,10 +2449,10 @@ Symbol_table::sized_finalize_symbol(Symbol* unsized_sym)
                return false;
              }
 
-            uint64_t secoff64 = relobj->output_section_offset(shndx);
             if (secoff64 == -1ULL)
               {
                 // The section needs special handling (e.g., a merge section).
+
                value = os->output_address(relobj, shndx, sym->value());
              }
             else
@@ -2597,10 +2635,9 @@ Symbol_table::sized_write_globals(const Stringpool* sympool,
            bool is_ordinary;
            unsigned int in_shndx = sym->shndx(&is_ordinary);
 
-           // FIXME: We need some target specific support here.
            if (!is_ordinary
                && in_shndx != elfcpp::SHN_ABS
-               && in_shndx != elfcpp::SHN_COMMON)
+               && !Symbol::is_common_shndx(in_shndx))
              {
                gold_error(_("%s: unsupported symbol section 0x%x"),
                           sym->demangled_name().c_str(), in_shndx);
@@ -2620,12 +2657,25 @@ Symbol_table::sized_write_globals(const Stringpool* sympool,
                else if (in_shndx == elfcpp::SHN_UNDEF
                         || (!is_ordinary
                             && (in_shndx == elfcpp::SHN_ABS
-                                || in_shndx == elfcpp::SHN_COMMON)))
+                                || Symbol::is_common_shndx(in_shndx))))
                  shndx = in_shndx;
                else
                  {
                    Relobj* relobj = static_cast<Relobj*>(symobj);
                    Output_section* os = relobj->output_section(in_shndx);
+                    if (this->is_section_folded(relobj, in_shndx))
+                      {
+                        // This global symbol must be written out even though
+                        // it is folded.
+                        // Get the os of the section it is folded onto.
+                        Section_id folded =
+                             this->icf_->get_folded_section(relobj, in_shndx);
+                        gold_assert(folded.first !=NULL);
+                        Relobj* folded_obj = 
+                          reinterpret_cast<Relobj*>(folded.first);
+                        os = folded_obj->output_section(folded.second);  
+                        gold_assert(os != NULL);
+                      }
                    gold_assert(os != NULL);
                    shndx = os->out_shndx();