diff options
author | Alan Modra <amodra@gmail.com> | 2009-01-24 03:10:43 +0000 |
---|---|---|
committer | Alan Modra <amodra@gmail.com> | 2009-01-24 03:10:43 +0000 |
commit | 1e8fa21e6d006b81fb331c5efc009b96a1502bac (patch) | |
tree | 7cccd0f01d3a76f0f31f1ee381f73cc96405d975 /bfd/elflink.c | |
parent | 2e15dc9095ffe0a4b2839c65d0e23722cf602b1d (diff) | |
download | gdb-1e8fa21e6d006b81fb331c5efc009b96a1502bac.zip gdb-1e8fa21e6d006b81fb331c5efc009b96a1502bac.tar.gz gdb-1e8fa21e6d006b81fb331c5efc009b96a1502bac.tar.bz2 |
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.
Diffstat (limited to 'bfd/elflink.c')
-rw-r--r-- | bfd/elflink.c | 175 |
1 files changed, 83 insertions, 92 deletions
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; |