diff options
-rw-r--r-- | bfd/ChangeLog | 8 | ||||
-rw-r--r-- | bfd/elflink.c | 175 |
2 files changed, 91 insertions, 92 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 3efcb94..7fe0dce 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,11 @@ +2009-01-24 Alan Modra <amodra@bigpond.net.au> + + PR 6022 + * elflink.c (find_version_for_sym): New function split out from, + but without export_dynamic test, .. + (_bfd_elf_link_assign_sym_version): ..here. + (_bfd_elf_export_symbol): Use it. + 2009-01-23 Alan Modra <amodra@bigpond.net.au> * elf-bfd.h (struct elf_assign_sym_version_info): Delete. diff --git a/bfd/elflink.c b/bfd/elflink.c index 5bbe820..badbe9e 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -1798,6 +1798,80 @@ nondefault: return TRUE; } +static struct bfd_elf_version_tree * +find_version_for_sym (struct bfd_elf_version_tree *verdefs, + const char *sym_name, + bfd_boolean *hide) +{ + struct bfd_elf_version_tree *t; + struct bfd_elf_version_tree *local_ver, *global_ver, *exist_ver; + + local_ver = NULL; + global_ver = NULL; + exist_ver = NULL; + for (t = verdefs; t != NULL; t = t->next) + { + if (t->globals.list != NULL) + { + struct bfd_elf_version_expr *d = NULL; + + while ((d = (*t->match) (&t->globals, d, sym_name)) != NULL) + { + global_ver = t; + if (d->symver) + exist_ver = t; + d->script = 1; + /* If the match is a wildcard pattern, keep looking for + a more explicit, perhaps even local, match. */ + if (d->literal) + break; + } + + if (d != NULL) + break; + } + + if (t->locals.list != NULL) + { + struct bfd_elf_version_expr *d = NULL; + + while ((d = (*t->match) (&t->locals, d, sym_name)) != NULL) + { + local_ver = t; + /* If the match is a wildcard pattern, keep looking for + a more explicit, perhaps even global, match. */ + if (d->literal) + { + /* An exact match overrides a global wildcard. */ + global_ver = NULL; + break; + } + } + + if (d != NULL) + break; + } + } + + if (global_ver != NULL) + { + /* If we already have a versioned symbol that matches the + node for this symbol, then we don't want to create a + duplicate from the unversioned symbol. Instead hide the + unversioned symbol. */ + *hide = exist_ver == global_ver; + return global_ver; + } + + if (local_ver != NULL) + { + *hide = TRUE; + return local_ver; + } + + return NULL; +} + /* This routine is used to export all defined symbols into the dynamic symbol table. It is called via elf_link_hash_traverse. */ @@ -1821,29 +1895,12 @@ _bfd_elf_export_symbol (struct elf_link_hash_entry *h, void *data) && (h->def_regular || h->ref_regular)) { - struct bfd_elf_version_tree *t; - struct bfd_elf_version_expr *d; + bfd_boolean hide; - for (t = eif->verdefs; t != NULL; t = t->next) + if (eif->verdefs == NULL + || (find_version_for_sym (eif->verdefs, h->root.root.string, &hide) + && !hide)) { - if (t->globals.list != NULL) - { - d = (*t->match) (&t->globals, NULL, h->root.root.string); - if (d != NULL) - goto doit; - } - - if (t->locals.list != NULL) - { - d = (*t->match) (&t->locals, NULL, h->root.root.string); - if (d != NULL) - return TRUE; - } - } - - if (!eif->verdefs) - { - doit: if (! bfd_elf_link_record_dynamic_symbol (eif->info, h)) { eif->failed = TRUE; @@ -2101,78 +2158,12 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data) something. */ if (h->verinfo.vertree == NULL && sinfo->verdefs != NULL) { - struct bfd_elf_version_tree *t; - struct bfd_elf_version_tree *local_ver, *global_ver, *exist_ver; - struct bfd_elf_version_expr *d; - - /* See if can find what version this symbol is in. If the - symbol is supposed to be local, then don't actually register - it. */ - local_ver = NULL; - global_ver = NULL; - exist_ver = NULL; - for (t = sinfo->verdefs; t != NULL; t = t->next) - { - if (t->globals.list != NULL) - { - d = NULL; - while ((d = (*t->match) (&t->globals, d, - h->root.root.string)) != NULL) - { - global_ver = t; - local_ver = NULL; - if (d->symver) - exist_ver = t; - d->script = 1; - /* If the match is a wildcard pattern, keep looking for - a more explicit, perhaps even local, match. */ - if (d->literal) - break; - } - - if (d != NULL) - break; - } + bfd_boolean hide; - if (t->locals.list != NULL) - { - d = NULL; - while ((d = (*t->match) (&t->locals, d, - h->root.root.string)) != NULL) - { - local_ver = t; - /* If the match is a wildcard pattern, keep looking for - a more explicit, perhaps even global, match. */ - if (d->literal) - { - /* An exact match overrides a global wildcard. */ - global_ver = NULL; - break; - } - } - - if (d != NULL) - break; - } - } - - if (global_ver != NULL) - { - h->verinfo.vertree = global_ver; - /* If we already have a versioned symbol that matches the - node for this symbol, then we don't want to create a - duplicate from the unversioned symbol. Instead hide the - unversioned symbol. */ - if (exist_ver == global_ver) - (*bed->elf_backend_hide_symbol) (info, h, TRUE); - } - else if (local_ver != NULL) - { - h->verinfo.vertree = local_ver; - if (!info->export_dynamic - || exist_ver == local_ver) - (*bed->elf_backend_hide_symbol) (info, h, TRUE); - } + h->verinfo.vertree = find_version_for_sym (sinfo->verdefs, + h->root.root.string, &hide); + if (h->verinfo.vertree != NULL && hide) + (*bed->elf_backend_hide_symbol) (info, h, TRUE); } return TRUE; |