bfd/
authorH.J. Lu <hjl.tools@gmail.com>
Fri, 2 Jan 2009 19:29:38 +0000 (19:29 +0000)
committerH.J. Lu <hjl.tools@gmail.com>
Fri, 2 Jan 2009 19:29:38 +0000 (19:29 +0000)
2009-01-02  H.J. Lu  <hongjiu.lu@intel.com>

PR ld/9679
* elflink.c (elf_merge_st_other): New.
(_bfd_elf_merge_symbol): Use it on skipped weak definitions and
hide them if needed.
(elf_link_add_object_symbols): Updated.

ld/testsuite/

2009-01-02  H.J. Lu  <hongjiu.lu@intel.com>

PR ld/9679
* ld-elf/pr9679-1.c: New.
* ld-elf/pr9679-2.c: Likewise.
* ld-elf/pr9679.rd: Likewise.

* ld-elf/shared.exp (build_tests): Add test for libpr9679.so.

bfd/ChangeLog
bfd/elflink.c
ld/testsuite/ChangeLog
ld/testsuite/ld-elf/pr9679-1.c [new file with mode: 0644]
ld/testsuite/ld-elf/pr9679-2.c [new file with mode: 0644]
ld/testsuite/ld-elf/pr9679.rd [new file with mode: 0644]
ld/testsuite/ld-elf/shared.exp

index a896f01d48643d758152b1ccc7397c208007f6e7..79fb7b2ef45c9f41886e8ef367062e9dfbaa0e8b 100644 (file)
@@ -1,3 +1,11 @@
+2009-01-02  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/9679
+       * elflink.c (elf_merge_st_other): New.
+       (_bfd_elf_merge_symbol): Use it on skipped weak definitions and
+       hide them if needed.
+       (elf_link_add_object_symbols): Updated.
+
 2009-01-02  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/9676
index 2b246bd9ad1eb9b52a22d02aae33d6e91f3ec0bf..95d12199e310d6845377953f63390c96254b43b2 100644 (file)
@@ -822,6 +822,54 @@ _bfd_elf_link_renumber_dynsyms (bfd *output_bfd,
   return dynsymcount;
 }
 
+/* Merge st_other field.  */
+
+static void
+elf_merge_st_other (bfd *abfd, struct elf_link_hash_entry *h,
+                   Elf_Internal_Sym *isym, bfd_boolean definition,
+                   bfd_boolean dynamic)
+{
+  const struct elf_backend_data *bed = get_elf_backend_data (abfd);
+
+  /* If st_other has a processor-specific meaning, specific
+     code might be needed here. We never merge the visibility
+     attribute with the one from a dynamic object.  */
+  if (bed->elf_backend_merge_symbol_attribute)
+    (*bed->elf_backend_merge_symbol_attribute) (h, isym, definition,
+                                               dynamic);
+
+  /* If this symbol has default visibility and the user has requested
+     we not re-export it, then mark it as hidden.  */
+  if (definition
+      && !dynamic
+      && (abfd->no_export
+         || (abfd->my_archive && abfd->my_archive->no_export))
+      && ELF_ST_VISIBILITY (isym->st_other) != STV_INTERNAL)
+    isym->st_other = (STV_HIDDEN
+                     | (isym->st_other & ~ELF_ST_VISIBILITY (-1)));
+
+  if (!dynamic && ELF_ST_VISIBILITY (isym->st_other) != 0)
+    {
+      unsigned char hvis, symvis, other, nvis;
+
+      /* Only merge the visibility. Leave the remainder of the
+        st_other field to elf_backend_merge_symbol_attribute.  */
+      other = h->other & ~ELF_ST_VISIBILITY (-1);
+
+      /* Combine visibilities, using the most constraining one.  */
+      hvis = ELF_ST_VISIBILITY (h->other);
+      symvis = ELF_ST_VISIBILITY (isym->st_other);
+      if (! hvis)
+       nvis = symvis;
+      else if (! symvis)
+       nvis = hvis;
+      else
+       nvis = hvis < symvis ? hvis : symvis;
+
+      h->other = other | nvis;
+    }
+}
+
 /* This function is called when we want to define a new symbol.  It
    handles the various cases which arise when we find a definition in
    a dynamic object, or when there is already a definition in a
@@ -1347,7 +1395,22 @@ _bfd_elf_merge_symbol (bfd *abfd,
 
   /* Skip weak definitions of symbols that are already defined.  */
   if (newdef && olddef && newweak)
-    *skip = TRUE;
+    {
+      *skip = TRUE;
+
+      /* Merge st_other.  If the symbol already has a dynamic index,
+        but visibility says it should not be visible, turn it into a
+        local symbol.  */
+      elf_merge_st_other (abfd, h, sym, newdef, newdyn);
+      if (h->dynindx != -1)
+       switch (ELF_ST_VISIBILITY (h->other))
+         {
+         case STV_INTERNAL:
+         case STV_HIDDEN:
+           (*bed->elf_backend_hide_symbol) (info, h, TRUE);
+           break;
+         }
+    }
 
   /* If the old symbol is from a dynamic object, and the new symbol is
      a definition which is not from a dynamic object, then the new
@@ -4244,42 +4307,8 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
              h->type = ELF_ST_TYPE (isym->st_info);
            }
 
-         /* If st_other has a processor-specific meaning, specific
-            code might be needed here. We never merge the visibility
-            attribute with the one from a dynamic object.  */
-         if (bed->elf_backend_merge_symbol_attribute)
-           (*bed->elf_backend_merge_symbol_attribute) (h, isym, definition,
-                                                       dynamic);
-
-         /* If this symbol has default visibility and the user has requested
-            we not re-export it, then mark it as hidden.  */
-         if (definition && !dynamic
-             && (abfd->no_export
-                 || (abfd->my_archive && abfd->my_archive->no_export))
-             && ELF_ST_VISIBILITY (isym->st_other) != STV_INTERNAL)
-           isym->st_other = (STV_HIDDEN
-                             | (isym->st_other & ~ELF_ST_VISIBILITY (-1)));
-
-         if (ELF_ST_VISIBILITY (isym->st_other) != 0 && !dynamic)
-           {
-             unsigned char hvis, symvis, other, nvis;
-
-             /* Only merge the visibility. Leave the remainder of the
-                st_other field to elf_backend_merge_symbol_attribute.  */
-             other = h->other & ~ELF_ST_VISIBILITY (-1);
-
-             /* Combine visibilities, using the most constraining one.  */
-             hvis   = ELF_ST_VISIBILITY (h->other);
-             symvis = ELF_ST_VISIBILITY (isym->st_other);
-             if (! hvis)
-               nvis = symvis;
-             else if (! symvis)
-               nvis = hvis;
-             else
-               nvis = hvis < symvis ? hvis : symvis;
-
-             h->other = other | nvis;
-           }
+         /* Merge st_other field.  */
+         elf_merge_st_other (abfd, h, isym, definition, dynamic);
 
          /* Set a flag in the hash table entry indicating the type of
             reference or definition we just found.  Keep a count of
index 7936368711d1dbb2f79b6ffa958a9a3d0237f36b..30be1ed27c0106ef8c19e6441672e1006dd15f99 100644 (file)
@@ -1,3 +1,12 @@
+2009-01-02  H.J. Lu  <hongjiu.lu@intel.com>
+
+       PR ld/9679
+       * ld-elf/pr9679-1.c: New.
+       * ld-elf/pr9679-2.c: Likewise.
+       * ld-elf/pr9679.rd: Likewise.
+
+       * ld-elf/shared.exp (build_tests): Add test for libpr9679.so.
+
 2009-01-02  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR ld/9676
diff --git a/ld/testsuite/ld-elf/pr9679-1.c b/ld/testsuite/ld-elf/pr9679-1.c
new file mode 100644 (file)
index 0000000..cf7abbb
--- /dev/null
@@ -0,0 +1,5 @@
+int
+foo (void)
+{
+  return 1;
+}
diff --git a/ld/testsuite/ld-elf/pr9679-2.c b/ld/testsuite/ld-elf/pr9679-2.c
new file mode 100644 (file)
index 0000000..e125a6b
--- /dev/null
@@ -0,0 +1,13 @@
+extern int foo (void) __attribute__((weak,__visibility__ ("hidden")));
+
+int
+foo (void)
+{
+  return 1;
+}
+
+int
+bar (void)
+{
+  return foo ();
+}
diff --git a/ld/testsuite/ld-elf/pr9679.rd b/ld/testsuite/ld-elf/pr9679.rd
new file mode 100644 (file)
index 0000000..0585b1c
--- /dev/null
@@ -0,0 +1,5 @@
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+#...
+ +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +FUNC +LOCAL +HIDDEN +[0-9]+ +foo
+#...
index ff8bc8ffbbac8ef02f15179c9183b05a16dd71a5..4f45bdd6569ed9c080ba46bd6fbc1abe1417dd0f 100644 (file)
@@ -145,6 +145,9 @@ set build_tests {
    "-shared tmpdir/pr9676-4.o -Ltmpdir -lpr9676-3 -Wl,--start-group -lpr9676-1 -lpr9676-2 -Wl,--end-group"
    "-fPIC"
    {dummy.c} {{readelf {-s} pr9676.rd}} "libpr9676-4a.so"}
+  {"Build libpr9679.so"
+   "-shared" "-fPIC -O0"
+   {pr9679-1.c pr9679-2.c} {{readelf {-s} pr9679.rd}} "libpr9679.so"}
 }
 
 set run_tests {