forked from Imagelibrary/binutils-gdb
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.
This commit is contained in:
@@ -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.
|
||||
|
||||
175
bfd/elflink.c
175
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;
|
||||
bfd_boolean hide;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user