aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog8
-rw-r--r--bfd/elflink.c36
2 files changed, 43 insertions, 1 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index e9a5dba..411f704 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,11 @@
+2006-07-12 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR ld/2884
+ * elflink.c (_bfd_elf_merge_symbol): Copy the symbol info from
+ the old versioned dynamic definition to the new one with
+ non-default visibility. Hide the symbol if it is hidden or
+ internal.
+
2006-07-12 Matthew R. Dempsky <mrd@alkemio.org>
* cpu-m68k.c (bfd_m68k_compatible): Handle CPU32.
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 9d65b5f..84d9d1f 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -1025,7 +1025,41 @@ _bfd_elf_merge_symbol (bfd *abfd,
relocatable file and the old definition comes from a dynamic
object, we remove the old definition. */
if ((*sym_hash)->root.type == bfd_link_hash_indirect)
- h = *sym_hash;
+ {
+ /* Handle the case where the old dynamic definition is
+ default versioned. We need to copy the symbol info from
+ the symbol with default version to the normal one if it
+ was referenced before. */
+ if (h->ref_regular)
+ {
+ const struct elf_backend_data *bed
+ = get_elf_backend_data (abfd);
+ struct elf_link_hash_entry *vh = *sym_hash;
+ vh->root.type = h->root.type;
+ h->root.type = bfd_link_hash_indirect;
+ (*bed->elf_backend_copy_indirect_symbol) (info, vh, h);
+ /* Protected symbols will override the dynamic definition
+ with default version. */
+ if (ELF_ST_VISIBILITY (sym->st_other) == STV_PROTECTED)
+ {
+ h->root.u.i.link = (struct bfd_link_hash_entry *) vh;
+ vh->dynamic_def = 1;
+ vh->ref_dynamic = 1;
+ }
+ else
+ {
+ h->root.type = vh->root.type;
+ vh->ref_dynamic = 0;
+ /* We have to hide it here since it was made dynamic
+ global with extra bits when the symbol info was
+ copied from the old dynamic definition. */
+ (*bed->elf_backend_hide_symbol) (info, vh, TRUE);
+ }
+ h = vh;
+ }
+ else
+ h = *sym_hash;
+ }
if ((h->root.u.undef.next || info->hash->undefs_tail == &h->root)
&& bfd_is_und_section (sec))