PR 7047
	* bfdlink.h (struct bfd_elf_version_expr): Delete "symbol".
	Add "literal".
bfd/
	PR 7047
	* configure.in: Bump version.
	* configure: Regenerate.
	* elflink.c (_bfd_elf_link_assign_sym_version): Continue matching
	against version nodes when a global match is a wildcard.  Similarly
	continue matching on local wildcard matches, rather than only
	continuing for "*".  Have any global wildcard match override a
	local wildcard match.  Correct logic hiding unversioned symbol.
	(bfd_elf_size_dynamic_sections): Update for changes to struct
	bfd_elf_version_expr.
ld/
	PR 7047
	* emultempl/ppc64elf.em (gld${EMULATION_NAME}_new_vers_pattern): Update
	for changes to struct bfd_elf_version_expr.
	* ldlang.c (lang_vers_match, version_expr_head_hash): Likewise.
	(version_expr_head_eq, lang_finalize_version_expr_head): Likewise.
	(lang_register_vers_node): Likewise.
	(lang_new_vers_pattern): Likewise.  Ensure "literal" is set when
	no glob chars found in "pattern".
	(realsymbol): Correct backslash quote logic.
	* ld.texinfo (VERSION): Warn about global wildcards.
This commit is contained in:
Alan Modra 2008-11-26 01:04:17 +00:00
parent 6cf7d91b7e
commit ae5a359786
10 changed files with 127 additions and 89 deletions

View File

@ -1,3 +1,16 @@
2008-11-26 Alan Modra <amodra@bigpond.net.au>
PR 7047
* configure.in: Bump version.
* configure: Regenerate.
* elflink.c (_bfd_elf_link_assign_sym_version): Continue matching
against version nodes when a global match is a wildcard. Similarly
continue matching on local wildcard matches, rather than only
continuing for "*". Have any global wildcard match override a
local wildcard match. Correct logic hiding unversioned symbol.
(bfd_elf_size_dynamic_sections): Update for changes to struct
bfd_elf_version_expr.
2008-11-25 Joel Brobecker <brobecker@adacore.com>
* configure.in: Deactivate large-file support on native x86-solaris

2
bfd/configure vendored
View File

@ -3033,7 +3033,7 @@ fi
# Define the identity of the package.
PACKAGE=bfd
VERSION=2.19.50
VERSION=2.19.51
cat >>confdefs.h <<_ACEOF

View File

@ -8,7 +8,7 @@ AC_CONFIG_SRCDIR([libbfd.c])
AC_CANONICAL_TARGET
AC_ISC_POSIX
AM_INIT_AUTOMAKE(bfd, 2.19.50)
AM_INIT_AUTOMAKE(bfd, 2.19.51)
dnl These must be called before LT_INIT, because it may want
dnl to call AC_CHECK_PROG.

View File

@ -2010,41 +2010,36 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
if (h->verinfo.vertree == NULL && sinfo->verdefs != NULL)
{
struct bfd_elf_version_tree *t;
struct bfd_elf_version_tree *local_ver;
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)
{
bfd_boolean matched;
matched = FALSE;
d = NULL;
while ((d = (*t->match) (&t->globals, d,
h->root.root.string)) != NULL)
if (d->symver)
matched = TRUE;
else
{
/* There is a version without definition. Make
the symbol the default definition for this
version. */
h->verinfo.vertree = t;
local_ver = NULL;
d->script = 1;
{
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;
else if (matched)
/* There is no undefined version for this symbol. Hide the
default one. */
(*bed->elf_backend_hide_symbol) (info, h, TRUE);
}
if (t->locals.list != NULL)
@ -2054,11 +2049,14 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
h->root.root.string)) != NULL)
{
local_ver = t;
/* If the match is "*", keep looking for a more
explicit, perhaps even global, match.
XXX: Shouldn't this be !d->wildcard instead? */
if (d->pattern[0] != '*' || d->pattern[1] != '\0')
break;
/* 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)
@ -2066,14 +2064,22 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
}
}
if (local_ver != NULL)
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 (h->dynindx != -1
&& ! info->export_dynamic)
{
(*bed->elf_backend_hide_symbol) (info, h, TRUE);
}
if (!info->export_dynamic
|| exist_ver == local_ver)
(*bed->elf_backend_hide_symbol) (info, h, TRUE);
}
}
@ -5566,14 +5572,14 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
/* Make all global versions with definition. */
for (t = verdefs; t != NULL; t = t->next)
for (d = t->globals.list; d != NULL; d = d->next)
if (!d->symver && d->symbol)
if (!d->symver && d->literal)
{
const char *verstr, *name;
size_t namelen, verlen, newlen;
char *newname, *p;
struct elf_link_hash_entry *newh;
name = d->symbol;
name = d->pattern;
namelen = strlen (name);
verstr = t->name;
verlen = strlen (verstr);
@ -5631,7 +5637,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd,
all_defined = TRUE;
for (t = verdefs; t != NULL; t = t->next)
for (d = t->globals.list; d != NULL; d = d->next)
if (!d->symver && !d->script)
if (d->literal && !d->symver && !d->script)
{
(*_bfd_error_handler)
(_("%s: undefined version: %s"),

View File

@ -1,3 +1,9 @@
2008-11-26 Alan Modra <amodra@bigpond.net.au>
PR 7047
* bfdlink.h (struct bfd_elf_version_expr): Delete "symbol".
Add "literal".
2008-11-21 Sterling Augustine <sterling@tensilica.com>
* xtensa-isa-internal.h (XTENSA_STATE_IS_SHARED_OR): New flag.

View File

@ -707,8 +707,8 @@ struct bfd_elf_version_expr
struct bfd_elf_version_expr *next;
/* Glob pattern. */
const char *pattern;
/* NULL for a glob pattern, otherwise a straight symbol. */
const char *symbol;
/* Set if pattern is not a glob. */
unsigned int literal : 1;
/* Defined by ".symver". */
unsigned int symver : 1;
/* Defined by version script. */

View File

@ -1,3 +1,16 @@
2008-11-26 Alan Modra <amodra@bigpond.net.au>
PR 7047
* emultempl/ppc64elf.em (gld${EMULATION_NAME}_new_vers_pattern): Update
for changes to struct bfd_elf_version_expr.
* ldlang.c (lang_vers_match, version_expr_head_hash): Likewise.
(version_expr_head_eq, lang_finalize_version_expr_head): Likewise.
(lang_register_vers_node): Likewise.
(lang_new_vers_pattern): Likewise. Ensure "literal" is set when
no glob chars found in "pattern".
(realsymbol): Correct backslash quote logic.
* ld.texinfo (VERSION): Warn about global wildcards.
2008-11-24 Alan Modra <amodra@bigpond.net.au>
* ldlang.c (lang_record_phdrs): Don't add orphans to PT_INTERP header.

View File

@ -416,29 +416,18 @@ gld${EMULATION_NAME}_new_vers_pattern (struct bfd_elf_version_expr *entry)
char *dot_pat;
if (!dotsyms
|| (entry->pattern != NULL
&& (entry->pattern[0] == '*' || entry->pattern[0] == '.')))
|| entry->pattern[0] == '.'
|| (!entry->literal && entry->pattern[0] == '*'))
return entry;
dot_entry = xmalloc (sizeof *dot_entry);
*dot_entry = *entry;
dot_entry->next = entry;
if (entry->pattern != NULL)
{
len = strlen (entry->pattern) + 2;
dot_pat = xmalloc (len);
dot_pat[0] = '.';
memcpy (dot_pat + 1, entry->pattern, len - 1);
dot_entry->pattern = dot_pat;
}
if (entry->symbol != NULL)
{
len = strlen (entry->symbol) + 2;
dot_pat = xmalloc (len);
dot_pat[0] = '.';
memcpy (dot_pat + 1, entry->symbol, len - 1);
dot_entry->symbol = dot_pat;
}
len = strlen (entry->pattern) + 2;
dot_pat = xmalloc (len);
dot_pat[0] = '.';
memcpy (dot_pat + 1, entry->pattern, len - 1);
dot_entry->pattern = dot_pat;
return dot_entry;
}

View File

@ -4561,7 +4561,11 @@ When the linker finds a symbol defined in a library which is not
specifically bound to a version node, it will effectively bind it to an
unspecified base version of the library. You can bind all otherwise
unspecified symbols to a given version node by using @samp{global: *;}
somewhere in the version script.
somewhere in the version script. Note that it's slightly crazy to use
wildcards in a global spec except on the last version node. Global
wildcards elsewhere run the risk of accidentally adding symbols to the
set exported for an old version. That's wrong since older versions
ought to have a fixed set of symbols.
The names of the version nodes have no specific meaning other than what
they might suggest to the person reading them. The @samp{2.0} version

View File

@ -6989,7 +6989,7 @@ lang_vers_match (struct bfd_elf_version_expr_head *head,
java_sym = sym;
}
if (head->htab && (prev == NULL || prev->symbol))
if (head->htab && (prev == NULL || prev->literal))
{
struct bfd_elf_version_expr e;
@ -6998,9 +6998,9 @@ lang_vers_match (struct bfd_elf_version_expr_head *head,
case 0:
if (head->mask & BFD_ELF_VERSION_C_TYPE)
{
e.symbol = sym;
e.pattern = sym;
expr = htab_find (head->htab, &e);
while (expr && strcmp (expr->symbol, sym) == 0)
while (expr && strcmp (expr->pattern, sym) == 0)
if (expr->mask == BFD_ELF_VERSION_C_TYPE)
goto out_ret;
else
@ -7010,9 +7010,9 @@ lang_vers_match (struct bfd_elf_version_expr_head *head,
case BFD_ELF_VERSION_C_TYPE:
if (head->mask & BFD_ELF_VERSION_CXX_TYPE)
{
e.symbol = cxx_sym;
e.pattern = cxx_sym;
expr = htab_find (head->htab, &e);
while (expr && strcmp (expr->symbol, cxx_sym) == 0)
while (expr && strcmp (expr->pattern, cxx_sym) == 0)
if (expr->mask == BFD_ELF_VERSION_CXX_TYPE)
goto out_ret;
else
@ -7022,9 +7022,9 @@ lang_vers_match (struct bfd_elf_version_expr_head *head,
case BFD_ELF_VERSION_CXX_TYPE:
if (head->mask & BFD_ELF_VERSION_JAVA_TYPE)
{
e.symbol = java_sym;
e.pattern = java_sym;
expr = htab_find (head->htab, &e);
while (expr && strcmp (expr->symbol, java_sym) == 0)
while (expr && strcmp (expr->pattern, java_sym) == 0)
if (expr->mask == BFD_ELF_VERSION_JAVA_TYPE)
goto out_ret;
else
@ -7037,7 +7037,7 @@ lang_vers_match (struct bfd_elf_version_expr_head *head,
}
/* Finally, try the wildcards. */
if (prev == NULL || prev->symbol)
if (prev == NULL || prev->literal)
expr = head->remaining;
else
expr = prev->next;
@ -7070,7 +7070,7 @@ lang_vers_match (struct bfd_elf_version_expr_head *head,
}
/* Return NULL if the PATTERN argument is a glob pattern, otherwise,
return a string pointing to the symbol name. */
return a pointer to the symbol name with any backslash quotes removed. */
static const char *
realsymbol (const char *pattern)
@ -7083,22 +7083,24 @@ realsymbol (const char *pattern)
{
/* It is a glob pattern only if there is no preceding
backslash. */
if (! backslash && (*p == '?' || *p == '*' || *p == '['))
{
free (symbol);
return NULL;
}
if (backslash)
{
/* Remove the preceding backslash. */
*(s - 1) = *p;
backslash = FALSE;
changed = TRUE;
}
else
*s++ = *p;
{
if (*p == '?' || *p == '*' || *p == '[')
{
free (symbol);
return NULL;
}
backslash = *p == '\\';
*s++ = *p;
backslash = *p == '\\';
}
}
if (changed)
@ -7127,10 +7129,15 @@ lang_new_vers_pattern (struct bfd_elf_version_expr *orig,
ret = xmalloc (sizeof *ret);
ret->next = orig;
ret->pattern = literal_p ? NULL : new;
ret->symver = 0;
ret->script = 0;
ret->symbol = literal_p ? new : realsymbol (new);
ret->literal = TRUE;
ret->pattern = literal_p ? new : realsymbol (new);
if (ret->pattern == NULL)
{
ret->pattern = new;
ret->literal = FALSE;
}
if (lang == NULL || strcasecmp (lang, "C") == 0)
ret->mask = BFD_ELF_VERSION_C_TYPE;
@ -7174,7 +7181,7 @@ version_expr_head_hash (const void *p)
{
const struct bfd_elf_version_expr *e = p;
return htab_hash_string (e->symbol);
return htab_hash_string (e->pattern);
}
static int
@ -7183,7 +7190,7 @@ version_expr_head_eq (const void *p1, const void *p2)
const struct bfd_elf_version_expr *e1 = p1;
const struct bfd_elf_version_expr *e2 = p2;
return strcmp (e1->symbol, e2->symbol) == 0;
return strcmp (e1->pattern, e2->pattern) == 0;
}
static void
@ -7195,7 +7202,7 @@ lang_finalize_version_expr_head (struct bfd_elf_version_expr_head *head)
for (e = head->list; e; e = e->next)
{
if (e->symbol)
if (e->literal)
count++;
head->mask |= e->mask;
}
@ -7209,7 +7216,7 @@ lang_finalize_version_expr_head (struct bfd_elf_version_expr_head *head)
for (e = head->list; e; e = next)
{
next = e->next;
if (!e->symbol)
if (!e->literal)
{
*remaining_loc = e;
remaining_loc = &e->next;
@ -7234,14 +7241,14 @@ lang_finalize_version_expr_head (struct bfd_elf_version_expr_head *head)
last = e1;
e1 = e1->next;
}
while (e1 && strcmp (e1->symbol, e->symbol) == 0);
while (e1 && strcmp (e1->pattern, e->pattern) == 0);
if (last == NULL)
{
/* This is a duplicate. */
/* FIXME: Memory leak. Sometimes pattern is not
xmalloced alone, but in larger chunk of memory. */
/* free (e->symbol); */
/* free (e->pattern); */
free (e);
}
else
@ -7305,18 +7312,18 @@ lang_register_vers_node (const char *name,
{
struct bfd_elf_version_expr *e2;
if (t->locals.htab && e1->symbol)
if (t->locals.htab && e1->literal)
{
e2 = htab_find (t->locals.htab, e1);
while (e2 && strcmp (e1->symbol, e2->symbol) == 0)
while (e2 && strcmp (e1->pattern, e2->pattern) == 0)
{
if (e1->mask == e2->mask)
einfo (_("%X%P: duplicate expression `%s'"
" in version information\n"), e1->symbol);
" in version information\n"), e1->pattern);
e2 = e2->next;
}
}
else if (!e1->symbol)
else if (!e1->literal)
for (e2 = t->locals.remaining; e2 != NULL; e2 = e2->next)
if (strcmp (e1->pattern, e2->pattern) == 0
&& e1->mask == e2->mask)
@ -7331,19 +7338,19 @@ lang_register_vers_node (const char *name,
{
struct bfd_elf_version_expr *e2;
if (t->globals.htab && e1->symbol)
if (t->globals.htab && e1->literal)
{
e2 = htab_find (t->globals.htab, e1);
while (e2 && strcmp (e1->symbol, e2->symbol) == 0)
while (e2 && strcmp (e1->pattern, e2->pattern) == 0)
{
if (e1->mask == e2->mask)
einfo (_("%X%P: duplicate expression `%s'"
" in version information\n"),
e1->symbol);
e1->pattern);
e2 = e2->next;
}
}
else if (!e1->symbol)
else if (!e1->literal)
for (e2 = t->globals.remaining; e2 != NULL; e2 = e2->next)
if (strcmp (e1->pattern, e2->pattern) == 0
&& e1->mask == e2->mask)