Avoid multiple definition errors from linkonce sections.
authorIan Lance Taylor <iant@google.com>
Tue, 10 Oct 2006 18:54:06 +0000 (18:54 +0000)
committerIan Lance Taylor <iant@google.com>
Tue, 10 Oct 2006 18:54:06 +0000 (18:54 +0000)
gold/object.cc
gold/object.h
gold/po/gold.pot
gold/symtab.cc
gold/target-reloc.h

index d8658e920c9284ff4e9e5af95ae7013be81c87bd..8f1241ad879612b4d9d414449a15e2eb3c0f021e 100644 (file)
@@ -346,9 +346,9 @@ Sized_object<size, big_endian>::include_linkonce_section(
     const elfcpp::Shdr<size, big_endian>&)
 {
   const char* symname = strrchr(name, '.') + 1;
-  bool omit1 = layout->add_comdat(symname, false);
-  bool omit2 = layout->add_comdat(name, true);
-  return omit1 || omit2;
+  bool include1 = layout->add_comdat(symname, false);
+  bool include2 = layout->add_comdat(name, true);
+  return include1 && include2;
 }
 
 // Lay out the input sections.  We walk through the sections and check
index dfcb94410d10b281fc8874c44a4fa61bced61913..ca227c5d88025bc52f0d7bb8e3216902b5d47f7e 100644 (file)
@@ -127,6 +127,21 @@ class Object
           const Stringpool* sympool, Output_file* of)
   { return this->do_relocate(options, symtab, sympool, of); }
 
+  // Return whether an input section is being included in the link.
+  bool
+  is_section_included(unsigned int shnum) const
+  {
+    assert(shnum < this->map_to_output_.size());
+    return this->map_to_output_[shnum].output_section != NULL;
+  }
+
+  // Given a section index, return the corresponding Output_section
+  // (which will be NULL if the section is not included in the link)
+  // and set *POFF to the offset within that section.
+  inline Output_section*
+  output_section(unsigned int shnum, off_t* poff);
+
+ protected:
   // What we need to know to map an input section to an output
   // section.  We keep an array of these, one for each input section,
   // indexed by the input section number.
@@ -139,16 +154,6 @@ class Object
     off_t offset;
   };
 
-  // Given a section index, return the corresponding Map_to_output
-  // information.
-  const Map_to_output*
-  section_output_info(unsigned int shnum) const
-  {
-    assert(shnum < this->map_to_output_.size());
-    return &this->map_to_output_[shnum];
-  }
-
- protected:
   // Read the symbols--implemented by child class.
   virtual void
   do_read_symbols(Read_symbols_data*) = 0;
@@ -248,6 +253,16 @@ Object::sized_target(ACCEPT_SIZE_ENDIAN_ONLY)
   return static_cast<Sized_target<size, big_endian>*>(this->target_);
 }
 
+// Implement Object::output_section inline for efficiency.
+inline Output_section*
+Object::output_section(unsigned int shnum, off_t* poff)
+{
+  assert(shnum < this->map_to_output_.size());
+  const Map_to_output& mo(this->map_to_output_[shnum]);
+  *poff = mo.offset;
+  return mo.output_section;
+}
+
 // A regular object file.  This is size and endian specific.
 
 template<int size, bool big_endian>
index 48bc987867a79c65be3081d3b0dea5f9b415c69e..f086e6d40ccd2583ae450f53aa7f17946ec2bbd9 100644 (file)
@@ -8,7 +8,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2006-10-04 08:37-0700\n"
+"POT-Creation-Date: 2006-10-10 11:40-0700\n"
 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
@@ -403,7 +403,7 @@ msgstr ""
 msgid "%s: %s: mixing 32-bit and 64-bit ELF objects\n"
 msgstr ""
 
-#: symtab.cc:317
+#: symtab.cc:320
 #, c-format
 msgid "%s: %s: bad global symbol name offset %u at %lu\n"
 msgstr ""
@@ -413,7 +413,7 @@ msgstr ""
 msgid "%s: %s: reloc %zu has bad offset %lu\n"
 msgstr ""
 
-#: target-reloc.h:106
+#: target-reloc.h:107
 #, c-format
 msgid "%s: %s: undefined reference to '%s'\n"
 msgstr ""
index 2251ea76c7d1f3dc64d1aad428033d712f1064d5..748218d843fdceef9faa144437c38816631f7d60 100644 (file)
@@ -305,12 +305,15 @@ Symbol_table::add_from_object(
       gold_exit(false);
     }
 
+  const int sym_size = elfcpp::Elf_sizes<size>::sym_size;
+
   const unsigned char* p = reinterpret_cast<const unsigned char*>(syms);
-  for (size_t i = 0; i < count; ++i)
+  for (size_t i = 0; i < count; ++i, p += sym_size)
     {
       elfcpp::Sym<size, big_endian> sym(p);
+      elfcpp::Sym<size, big_endian>* psym = &sym;
 
-      unsigned int st_name = sym.get_st_name();
+      unsigned int st_name = psym->get_st_name();
       if (st_name >= sym_name_size)
        {
          fprintf(stderr,
@@ -320,6 +323,21 @@ Symbol_table::add_from_object(
          gold_exit(false);
        }
 
+      // A symbol defined in a section which we are not including must
+      // be treated as an undefined symbol.
+      unsigned char symbuf[sym_size];
+      elfcpp::Sym<size, big_endian> sym2(symbuf);
+      unsigned int st_shndx = psym->get_st_shndx();
+      if (st_shndx != elfcpp::SHN_UNDEF
+         && st_shndx < elfcpp::SHN_LORESERVE
+         && !object->is_section_included(st_shndx))
+       {
+         memcpy(symbuf, p, sym_size);
+         elfcpp::Sym_write<size, big_endian> sw(symbuf);
+         sw.put_st_shndx(elfcpp::SHN_UNDEF);
+         psym = &sym2;
+       }
+
       const char* name = sym_names + st_name;
 
       // In an object file, an '@' in the name separates the symbol
@@ -331,7 +349,7 @@ Symbol_table::add_from_object(
       if (ver == NULL)
        {
          name = this->namepool_.add(name);
-         res = this->add_from_object(object, name, NULL, false, sym);
+         res = this->add_from_object(object, name, NULL, false, *psym);
        }
       else
        {
@@ -344,12 +362,10 @@ Symbol_table::add_from_object(
              ++ver;
            }
          ver = this->namepool_.add(ver);
-         res = this->add_from_object(object, name, ver, def, sym);
+         res = this->add_from_object(object, name, ver, def, *psym);
        }
 
       *sympointers++ = res;
-
-      p += elfcpp::Elf_sizes<size>::sym_size;
     }
 }
 
@@ -393,10 +409,11 @@ Symbol_table::sized_finalize(off_t off, Stringpool* pool)
          continue;
        }
 
-      const Object::Map_to_output* mo =
-       sym->object()->section_output_info(sym->shnum());
+      off_t secoff;
+      Output_section* os = sym->object()->output_section(sym->shnum(),
+                                                        &secoff);
 
-      if (mo->output_section == NULL)
+      if (os == NULL)
        {
          // We should be able to erase this symbol from the symbol
          // table, but at least with gcc 4.0.2
@@ -407,9 +424,7 @@ Symbol_table::sized_finalize(off_t off, Stringpool* pool)
        }
       else
        {
-         sym->set_value(sym->value()
-                        + mo->output_section->address()
-                        + mo->offset);
+         sym->set_value(sym->value() + os->address() + secoff);
          pool->add(sym->name());
          ++p;
          ++count;
@@ -470,10 +485,10 @@ Symbol_table::sized_write_globals(const Target*,
       if (sym->shnum() >= elfcpp::SHN_LORESERVE)
        continue;
 
-      const Object::Map_to_output* mo =
-       sym->object()->section_output_info(sym->shnum());
-
-      if (mo->output_section == NULL)
+      off_t secoff;
+      Output_section* os = sym->object()->output_section(sym->shnum(),
+                                                        &secoff);
+      if (os == NULL)
        continue;
 
       elfcpp::Sym_write<size, big_endian> osym(ps);
@@ -482,7 +497,7 @@ Symbol_table::sized_write_globals(const Target*,
       osym.put_st_size(sym->symsize());
       osym.put_st_info(elfcpp::elf_st_info(sym->binding(), sym->type()));
       osym.put_st_other(elfcpp::elf_st_other(sym->visibility(), sym->other()));
-      osym.put_st_shndx(mo->output_section->shndx());
+      osym.put_st_shndx(os->shndx());
 
       ps += sym_size;
     }
index 66ff78cf101cd9473f02458657c4c9a7a083d52d..f972b117d9afa049a11dee6b727674448ade68cb 100644 (file)
@@ -94,6 +94,7 @@ relocate_section(
       else
        {
          Symbol* gsym = global_syms[r_sym - local_count];
+         assert(gsym != NULL);
          if (gsym->is_forwarder())
            gsym = symtab->resolve_forwards(gsym);