2004-09-30 H.J. Lu <hongjiu.lu@intel.com>
authorH.J. Lu <hjl.tools@gmail.com>
Thu, 30 Sep 2004 16:43:41 +0000 (16:43 +0000)
committerH.J. Lu <hjl.tools@gmail.com>
Thu, 30 Sep 2004 16:43:41 +0000 (16:43 +0000)
PR 414
* elflink.c (_bfd_elf_merge_symbol): Check TLS symbol.

bfd/ChangeLog
bfd/elflink.c

index 231242b485af91f0d84c2fbd00814b6628a0d551..bb4d5e3e44a8e115a2e40feab9ac150685f0e666 100644 (file)
@@ -1,3 +1,8 @@
+2004-09-30  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR 414
+       * elflink.c (_bfd_elf_merge_symbol): Check TLS symbol.
+
 2004-09-30  Paul Brook  <paul@codesourcery.com>
 
        * reloc.c: Add BFD_RELOC_ARM_SMI.
index 8320fd87831e8d7cbc30c189a7611f7cac816e3c..e93145d6c24aef9f715a6c99df3b67eeb09fb296 100644 (file)
@@ -709,7 +709,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
                       bfd_boolean *type_change_ok,
                       bfd_boolean *size_change_ok)
 {
-  asection *sec;
+  asection *sec, *oldsec;
   struct elf_link_hash_entry *h;
   struct elf_link_hash_entry *flip;
   int bind;
@@ -753,26 +753,31 @@ _bfd_elf_merge_symbol (bfd *abfd,
       return TRUE;
     }
 
-  /* OLDBFD is a BFD associated with the existing symbol.  */
+  /* OLDBFD and OLDSEC are a BFD and an ASECTION associated with the
+     existing symbol.  */
 
   switch (h->root.type)
     {
     default:
       oldbfd = NULL;
+      oldsec = NULL;
       break;
 
     case bfd_link_hash_undefined:
     case bfd_link_hash_undefweak:
       oldbfd = h->root.u.undef.abfd;
+      oldsec = NULL;
       break;
 
     case bfd_link_hash_defined:
     case bfd_link_hash_defweak:
       oldbfd = h->root.u.def.section->owner;
+      oldsec = h->root.u.def.section;
       break;
 
     case bfd_link_hash_common:
       oldbfd = h->root.u.c.p->section->owner;
+      oldsec = h->root.u.c.p->section;
       break;
     }
 
@@ -840,6 +845,54 @@ _bfd_elf_merge_symbol (bfd *abfd,
   else
     olddef = TRUE;
 
+  /* Check TLS symbol.  */
+  if ((ELF_ST_TYPE (sym->st_info) == STT_TLS || h->type == STT_TLS)
+      && ELF_ST_TYPE (sym->st_info) != h->type)
+    {
+      bfd *ntbfd, *tbfd;
+      bfd_boolean ntdef, tdef;
+      asection *ntsec, *tsec;
+
+      if (h->type == STT_TLS)
+       {
+         ntbfd = abfd; 
+         ntsec = sec;
+         ntdef = newdef;
+         tbfd = oldbfd;
+         tsec = oldsec;
+         tdef = olddef;
+       }
+      else
+       {
+         ntbfd = oldbfd;
+         ntsec = oldsec;
+         ntdef = olddef;
+         tbfd = abfd;
+         tsec = sec;
+         tdef = newdef;
+       }
+
+      if (tdef && ntdef)
+       (*_bfd_error_handler)
+         (_("%s: TLS definition in %B section %A mismatches non-TLS definition in %B section %A"),
+          tbfd, tsec, ntbfd, ntsec, h->root.root.string);
+      else if (!tdef && !ntdef)
+       (*_bfd_error_handler)
+         (_("%s: TLS reference in %B mismatches non-TLS reference in %B"),
+          tbfd, ntbfd, h->root.root.string);
+      else if (tdef)
+       (*_bfd_error_handler)
+         (_("%s: TLS definition in %B section %A mismatches non-TLS reference in %B"),
+          tbfd, tsec, ntbfd, h->root.root.string);
+      else
+       (*_bfd_error_handler)
+         (_("%s: TLS reference in %B mismatches non-TLS definition in %B section %A"),
+          tbfd, ntbfd, ntsec, h->root.root.string);
+
+      bfd_set_error (bfd_error_bad_value);
+      return FALSE;
+    }
+
   /* We need to remember if a symbol has a definition in a dynamic
      object or is weak in all dynamic objects. Internal and hidden
      visibility will make it unavailable to dynamic objects.  */