mirror of
https://sourceware.org/git/binutils-gdb.git
synced 2024-11-21 01:12:32 +08:00
bfd/
* elflink.c (_bfd_elf_export_symbol): Adjust for globals and locals field changes. (_bfd_elf_link_assign_sym_version): Likewise. * elflink.h (size_dynamic_sections): Likewise. include/ * bfdlink.h (struct bfd_elf_version_expr): Remove match field. Add wildcard and mask fields. (BFD_ELF_VERSION_C_TYPE): Define. (BFD_ELF_VERSION_CXX_TYPE): Likewise. (BFD_ELF_VERSION_JAVA_TYPE): Likewise. (struct bfd_elf_version_expr_head): New. (struct bfd_elf_version_tree): Add match field. Change type of globals and locals fields to struct bfd_elf_version_expr_head. ld/ * ldlang.c: Include hashtab.h. (lang_vers_match_lang_c, lang_vers_match_lang_cplusplus, lang_vers_match_lang_java): Remove. (lang_vers_match): New function. (lang_new_vers_pattern): Initialize wildcard and mask fields, don't initialize match. (lang_new_vers_node): Use xcalloc. Adjust for globals and locals field type changes. Set match field. (version_expr_head_hash, version_expr_head_eq): New functions. (lang_finalize_version_expr_head): New function. (lang_register_vers_node): Call lang_finalize_version_expr_head. Search in hash table if not wildcard when looking for duplicates. * emultempl/ppc64elf.em (new_vers_pattern): Don't bother with duplicate checking. Initialize all fields of dot_entry from entry with the exception of pattern and next.
This commit is contained in:
parent
a9b7fca23b
commit
108ba30509
@ -1,3 +1,10 @@
|
||||
2003-10-22 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* elflink.c (_bfd_elf_export_symbol): Adjust for globals and locals
|
||||
field changes.
|
||||
(_bfd_elf_link_assign_sym_version): Likewise.
|
||||
* elflink.h (size_dynamic_sections): Likewise.
|
||||
|
||||
2003-10-21 Alexandre Oliva <aoliva@redhat.com>,
|
||||
Michael Snyder <msnyder@redhat.com>
|
||||
|
||||
|
111
bfd/elflink.c
111
bfd/elflink.c
@ -1505,22 +1505,18 @@ _bfd_elf_export_symbol (struct elf_link_hash_entry *h, void *data)
|
||||
|
||||
for (t = eif->verdefs; t != NULL; t = t->next)
|
||||
{
|
||||
if (t->globals != NULL)
|
||||
if (t->globals.list != NULL)
|
||||
{
|
||||
for (d = t->globals; d != NULL; d = d->next)
|
||||
{
|
||||
if ((*d->match) (d, h->root.root.string))
|
||||
goto doit;
|
||||
}
|
||||
d = (*t->match) (&t->globals, NULL, h->root.root.string);
|
||||
if (d != NULL)
|
||||
goto doit;
|
||||
}
|
||||
|
||||
if (t->locals != NULL)
|
||||
if (t->locals.list != NULL)
|
||||
{
|
||||
for (d = t->locals ; d != NULL; d = d->next)
|
||||
{
|
||||
if ((*d->match) (d, h->root.root.string))
|
||||
return TRUE;
|
||||
}
|
||||
d = (*t->match) (&t->locals, NULL, h->root.root.string);
|
||||
if (d != NULL)
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1699,31 +1695,19 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
|
||||
t->used = TRUE;
|
||||
d = NULL;
|
||||
|
||||
if (t->globals != NULL)
|
||||
{
|
||||
for (d = t->globals; d != NULL; d = d->next)
|
||||
if ((*d->match) (d, alc))
|
||||
break;
|
||||
}
|
||||
if (t->globals.list != NULL)
|
||||
d = (*t->match) (&t->globals, NULL, alc);
|
||||
|
||||
/* See if there is anything to force this symbol to
|
||||
local scope. */
|
||||
if (d == NULL && t->locals != NULL)
|
||||
if (d == NULL && t->locals.list != NULL)
|
||||
{
|
||||
for (d = t->locals; d != NULL; d = d->next)
|
||||
{
|
||||
if ((*d->match) (d, alc))
|
||||
{
|
||||
if (h->dynindx != -1
|
||||
&& info->shared
|
||||
&& ! info->export_dynamic)
|
||||
{
|
||||
(*bed->elf_backend_hide_symbol) (info, h, TRUE);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
d = (*t->match) (&t->locals, NULL, alc);
|
||||
if (d != NULL
|
||||
&& h->dynindx != -1
|
||||
&& info->shared
|
||||
&& ! info->export_dynamic)
|
||||
(*bed->elf_backend_hide_symbol) (info, h, TRUE);
|
||||
}
|
||||
|
||||
free (alc);
|
||||
@ -1744,18 +1728,14 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
|
||||
return TRUE;
|
||||
|
||||
amt = sizeof *t;
|
||||
t = bfd_alloc (sinfo->output_bfd, amt);
|
||||
t = bfd_zalloc (sinfo->output_bfd, amt);
|
||||
if (t == NULL)
|
||||
{
|
||||
sinfo->failed = TRUE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
t->next = NULL;
|
||||
t->name = p;
|
||||
t->globals = NULL;
|
||||
t->locals = NULL;
|
||||
t->deps = NULL;
|
||||
t->name_indx = (unsigned int) -1;
|
||||
t->used = TRUE;
|
||||
|
||||
@ -1801,30 +1781,26 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
|
||||
local_ver = NULL;
|
||||
for (t = sinfo->verdefs; t != NULL; t = t->next)
|
||||
{
|
||||
if (t->globals != NULL)
|
||||
if (t->globals.list != NULL)
|
||||
{
|
||||
bfd_boolean matched;
|
||||
|
||||
matched = FALSE;
|
||||
for (d = t->globals; d != NULL; d = d->next)
|
||||
{
|
||||
if ((*d->match) (d, h->root.root.string))
|
||||
{
|
||||
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;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
break;
|
||||
}
|
||||
if (d != NULL)
|
||||
break;
|
||||
else if (matched)
|
||||
@ -1833,19 +1809,18 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data)
|
||||
(*bed->elf_backend_hide_symbol) (info, h, TRUE);
|
||||
}
|
||||
|
||||
if (t->locals != NULL)
|
||||
if (t->locals.list != NULL)
|
||||
{
|
||||
for (d = t->locals; d != NULL; d = d->next)
|
||||
d = NULL;
|
||||
while ((d = (*t->match) (&t->locals, d,
|
||||
h->root.root.string)) != NULL)
|
||||
{
|
||||
local_ver = t;
|
||||
/* If the match is "*", keep looking for a more
|
||||
explicit, perhaps even global, match. */
|
||||
if (d->pattern[0] == '*' && d->pattern[1] == '\0')
|
||||
local_ver = t;
|
||||
else if ((*d->match) (d, h->root.root.string))
|
||||
{
|
||||
local_ver = t;
|
||||
break;
|
||||
}
|
||||
explicit, perhaps even global, match.
|
||||
XXX: Shouldn't this be !d->wildcard instead? */
|
||||
if (d->pattern[0] != '*' || d->pattern[1] != '\0')
|
||||
break;
|
||||
}
|
||||
|
||||
if (d != NULL)
|
||||
|
@ -2058,7 +2058,9 @@ NAME(bfd_elf,size_dynamic_sections) (bfd *output_bfd,
|
||||
|
||||
/* Make all global versions with definiton. */
|
||||
for (t = verdefs; t != NULL; t = t->next)
|
||||
for (d = t->globals; d != NULL; d = d->next)
|
||||
for (d = t->globals.list; d != NULL; d = d->next)
|
||||
/* FIXME: Shouldn't this be !d->symver && d->wildcard == 0
|
||||
instead? */
|
||||
if (!d->symver && strchr (d->pattern, '*') == NULL)
|
||||
{
|
||||
const char *verstr, *name;
|
||||
@ -2124,7 +2126,7 @@ NAME(bfd_elf,size_dynamic_sections) (bfd *output_bfd,
|
||||
/* Check if all global versions have a definiton. */
|
||||
all_defined = TRUE;
|
||||
for (t = verdefs; t != NULL; t = t->next)
|
||||
for (d = t->globals; d != NULL; d = d->next)
|
||||
for (d = t->globals.list; d != NULL; d = d->next)
|
||||
if (!d->symver && !d->script)
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
@ -2372,7 +2374,7 @@ NAME(bfd_elf,size_dynamic_sections) (bfd *output_bfd,
|
||||
|
||||
def.vd_version = VER_DEF_CURRENT;
|
||||
def.vd_flags = 0;
|
||||
if (t->globals == NULL && t->locals == NULL && ! t->used)
|
||||
if (t->globals.list == NULL && t->locals.list == NULL && ! t->used)
|
||||
def.vd_flags |= VER_FLG_WEAK;
|
||||
def.vd_ndx = t->vernum + 1;
|
||||
def.vd_cnt = cdeps + 1;
|
||||
|
@ -1,3 +1,15 @@
|
||||
2003-10-22 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* bfdlink.h (struct bfd_elf_version_expr): Remove match field.
|
||||
Add wildcard and mask fields.
|
||||
(BFD_ELF_VERSION_C_TYPE): Define.
|
||||
(BFD_ELF_VERSION_CXX_TYPE): Likewise.
|
||||
(BFD_ELF_VERSION_JAVA_TYPE): Likewise.
|
||||
(struct bfd_elf_version_expr_head): New.
|
||||
(struct bfd_elf_version_tree): Add match field.
|
||||
Change type of globals and locals fields
|
||||
to struct bfd_elf_version_expr_head.
|
||||
|
||||
2003-10-14 Bob Wilson <bob.wilson@acm.org>
|
||||
|
||||
* elf/xtensa.h: Formatting. Fix comments about property section
|
||||
|
@ -617,20 +617,37 @@ extern struct bfd_link_order *bfd_new_link_order (bfd *, asection *);
|
||||
BFD, but it would be a pain. Instead, the regular linker sets up
|
||||
these structures, and then passes them into BFD. */
|
||||
|
||||
/* Regular expressions for a version. */
|
||||
/* Glob pattern for a version. */
|
||||
|
||||
struct bfd_elf_version_expr
|
||||
{
|
||||
/* Next regular expression for this version. */
|
||||
/* Next glob pattern for this version. */
|
||||
struct bfd_elf_version_expr *next;
|
||||
/* Regular expression. */
|
||||
/* Glob pattern. */
|
||||
const char *pattern;
|
||||
/* Matching function. */
|
||||
int (*match) (struct bfd_elf_version_expr *, const char *);
|
||||
/* Defined by ".symver". */
|
||||
unsigned int symver: 1;
|
||||
unsigned int symver : 1;
|
||||
/* Defined by version script. */
|
||||
unsigned int script : 1;
|
||||
/* Is this a wildcard?. */
|
||||
unsigned int wildcard : 1;
|
||||
/* Pattern type. */
|
||||
#define BFD_ELF_VERSION_C_TYPE 1
|
||||
#define BFD_ELF_VERSION_CXX_TYPE 2
|
||||
#define BFD_ELF_VERSION_JAVA_TYPE 4
|
||||
unsigned int mask : 3;
|
||||
};
|
||||
|
||||
struct bfd_elf_version_expr_head
|
||||
{
|
||||
/* List of all patterns, both wildcards and non-wildcards. */
|
||||
struct bfd_elf_version_expr *list;
|
||||
/* Hash table for non-wildcards. */
|
||||
void *htab;
|
||||
/* Remaining patterns. */
|
||||
struct bfd_elf_version_expr *remaining;
|
||||
/* What kind of pattern types are present in list (bitmask). */
|
||||
unsigned int mask;
|
||||
};
|
||||
|
||||
/* Version dependencies. */
|
||||
@ -654,15 +671,19 @@ struct bfd_elf_version_tree
|
||||
/* Version number. */
|
||||
unsigned int vernum;
|
||||
/* Regular expressions for global symbols in this version. */
|
||||
struct bfd_elf_version_expr *globals;
|
||||
struct bfd_elf_version_expr_head globals;
|
||||
/* Regular expressions for local symbols in this version. */
|
||||
struct bfd_elf_version_expr *locals;
|
||||
struct bfd_elf_version_expr_head locals;
|
||||
/* List of versions which this version depends upon. */
|
||||
struct bfd_elf_version_deps *deps;
|
||||
/* Index of the version name. This is used within BFD. */
|
||||
unsigned int name_indx;
|
||||
/* Whether this version tree was used. This is used within BFD. */
|
||||
int used;
|
||||
/* Matching hook. */
|
||||
struct bfd_elf_version_expr *(*match)
|
||||
(struct bfd_elf_version_expr_head *head,
|
||||
struct bfd_elf_version_expr *prev, const char *sym);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
18
ld/ChangeLog
18
ld/ChangeLog
@ -1,3 +1,21 @@
|
||||
2003-10-22 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* ldlang.c: Include hashtab.h.
|
||||
(lang_vers_match_lang_c, lang_vers_match_lang_cplusplus,
|
||||
lang_vers_match_lang_java): Remove.
|
||||
(lang_vers_match): New function.
|
||||
(lang_new_vers_pattern): Initialize wildcard and mask
|
||||
fields, don't initialize match.
|
||||
(lang_new_vers_node): Use xcalloc. Adjust for globals and
|
||||
locals field type changes. Set match field.
|
||||
(version_expr_head_hash, version_expr_head_eq): New functions.
|
||||
(lang_finalize_version_expr_head): New function.
|
||||
(lang_register_vers_node): Call lang_finalize_version_expr_head.
|
||||
Search in hash table if not wildcard when looking for duplicates.
|
||||
* emultempl/ppc64elf.em (new_vers_pattern): Don't bother with
|
||||
duplicate checking. Initialize all fields of dot_entry from entry
|
||||
with the exception of pattern and next.
|
||||
|
||||
2003-10-21 Nick Clifton <nickc@redhat.com>
|
||||
|
||||
* ldlang.c (lang_memory_region_lookup): Add second parameter -
|
||||
|
@ -405,46 +405,17 @@ gld${EMULATION_NAME}_new_vers_pattern (struct bfd_elf_version_expr *entry)
|
||||
unsigned int len;
|
||||
char *dot_pat;
|
||||
|
||||
if (!dotsyms || entry->pattern[0] == '*')
|
||||
if (!dotsyms || entry->pattern[0] == '*' || entry->pattern[0] == '.')
|
||||
return entry;
|
||||
|
||||
/* Is the script adding ".foo" explicitly? */
|
||||
if (entry->pattern[0] == '.')
|
||||
{
|
||||
/* We may have added this pattern automatically. Don't add it
|
||||
again. Quadratic behaviour here is acceptable as the list
|
||||
may be traversed for each input bfd symbol. */
|
||||
for (next = entry->next; next != NULL; next = next->next)
|
||||
{
|
||||
if (strcmp (next->pattern, entry->pattern) == 0
|
||||
&& next->match == entry->match)
|
||||
{
|
||||
next = entry->next;
|
||||
free ((char *) entry->pattern);
|
||||
free (entry);
|
||||
return next;
|
||||
}
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
/* Don't add ".foo" if the script has already done so. */
|
||||
for (next = entry->next; next != NULL; next = next->next)
|
||||
{
|
||||
if (next->pattern[0] == '.'
|
||||
&& strcmp (next->pattern + 1, entry->pattern) == 0
|
||||
&& next->match == entry->match)
|
||||
return entry;
|
||||
}
|
||||
|
||||
dot_entry = xmalloc (sizeof *dot_entry);
|
||||
*dot_entry = *entry;
|
||||
dot_entry->next = entry;
|
||||
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;
|
||||
dot_entry->match = entry->match;
|
||||
return dot_entry;
|
||||
}
|
||||
|
||||
|
310
ld/ldlang.c
310
ld/ldlang.c
@ -39,6 +39,7 @@
|
||||
#include "ldemul.h"
|
||||
#include "fnmatch.h"
|
||||
#include "demangle.h"
|
||||
#include "hashtab.h"
|
||||
|
||||
#ifndef offsetof
|
||||
#define offsetof(TYPE, MEMBER) ((size_t) & (((TYPE*) 0)->MEMBER))
|
||||
@ -4973,65 +4974,108 @@ lang_leave_overlay (etree_type *lma_expr,
|
||||
|
||||
struct bfd_elf_version_tree *lang_elf_version_info;
|
||||
|
||||
static int
|
||||
lang_vers_match_lang_c (struct bfd_elf_version_expr *expr,
|
||||
const char *sym)
|
||||
/* If PREV is NULL, return first version pattern matching particular symbol.
|
||||
If PREV is non-NULL, return first version pattern matching particular
|
||||
symbol after PREV (previously returned by lang_vers_match). */
|
||||
|
||||
static struct bfd_elf_version_expr *
|
||||
lang_vers_match (struct bfd_elf_version_expr_head *head,
|
||||
struct bfd_elf_version_expr *prev,
|
||||
const char *sym)
|
||||
{
|
||||
if (expr->pattern[0] == '*' && expr->pattern[1] == '\0')
|
||||
return 1;
|
||||
return fnmatch (expr->pattern, sym, 0) == 0;
|
||||
}
|
||||
const char *cxx_sym = sym;
|
||||
const char *java_sym = sym;
|
||||
struct bfd_elf_version_expr *expr = NULL;
|
||||
|
||||
static int
|
||||
lang_vers_match_lang_cplusplus (struct bfd_elf_version_expr *expr,
|
||||
const char *sym)
|
||||
{
|
||||
char *alt_sym;
|
||||
int result;
|
||||
|
||||
if (expr->pattern[0] == '*' && expr->pattern[1] == '\0')
|
||||
return 1;
|
||||
|
||||
alt_sym = cplus_demangle (sym, /* DMGL_NO_TPARAMS */ 0);
|
||||
if (!alt_sym)
|
||||
if (head->mask & BFD_ELF_VERSION_CXX_TYPE)
|
||||
{
|
||||
/* cplus_demangle (also) returns NULL when it is not a C++ symbol.
|
||||
Should we early out FALSE in this case? */
|
||||
result = fnmatch (expr->pattern, sym, 0) == 0;
|
||||
cxx_sym = cplus_demangle (sym, /* DMGL_NO_TPARAMS */ 0);
|
||||
if (!cxx_sym)
|
||||
cxx_sym = sym;
|
||||
}
|
||||
if (head->mask & BFD_ELF_VERSION_JAVA_TYPE)
|
||||
{
|
||||
java_sym = cplus_demangle (sym, DMGL_JAVA);
|
||||
if (!java_sym)
|
||||
java_sym = sym;
|
||||
}
|
||||
|
||||
if (head->htab && (prev == NULL || prev->wildcard == 0))
|
||||
{
|
||||
struct bfd_elf_version_expr e;
|
||||
|
||||
switch (prev ? prev->mask : 0)
|
||||
{
|
||||
case 0:
|
||||
if (head->mask & BFD_ELF_VERSION_C_TYPE)
|
||||
{
|
||||
e.pattern = sym;
|
||||
expr = htab_find (head->htab, &e);
|
||||
while (expr && strcmp (expr->pattern, sym) == 0)
|
||||
if (expr->mask == BFD_ELF_VERSION_C_TYPE)
|
||||
goto out_ret;
|
||||
else
|
||||
expr = expr->next;
|
||||
}
|
||||
/* Fallthrough */
|
||||
case BFD_ELF_VERSION_C_TYPE:
|
||||
if (head->mask & BFD_ELF_VERSION_CXX_TYPE)
|
||||
{
|
||||
e.pattern = cxx_sym;
|
||||
expr = htab_find (head->htab, &e);
|
||||
while (expr && strcmp (expr->pattern, sym) == 0)
|
||||
if (expr->mask == BFD_ELF_VERSION_CXX_TYPE)
|
||||
goto out_ret;
|
||||
else
|
||||
expr = expr->next;
|
||||
}
|
||||
/* Fallthrough */
|
||||
case BFD_ELF_VERSION_CXX_TYPE:
|
||||
if (head->mask & BFD_ELF_VERSION_JAVA_TYPE)
|
||||
{
|
||||
e.pattern = java_sym;
|
||||
expr = htab_find (head->htab, &e);
|
||||
while (expr && strcmp (expr->pattern, sym) == 0)
|
||||
if (expr->mask == BFD_ELF_VERSION_JAVA_TYPE)
|
||||
goto out_ret;
|
||||
else
|
||||
expr = expr->next;
|
||||
}
|
||||
/* Fallthrough */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Finally, try the wildcards. */
|
||||
if (prev == NULL || prev->wildcard == 0)
|
||||
expr = head->remaining;
|
||||
else
|
||||
expr = prev->next;
|
||||
while (expr)
|
||||
{
|
||||
result = fnmatch (expr->pattern, alt_sym, 0) == 0;
|
||||
free (alt_sym);
|
||||
const char *s;
|
||||
|
||||
if (expr->pattern[0] == '*' && expr->pattern[1] == '\0')
|
||||
break;
|
||||
|
||||
if (expr->mask == BFD_ELF_VERSION_JAVA_TYPE)
|
||||
s = java_sym;
|
||||
else if (expr->mask == BFD_ELF_VERSION_CXX_TYPE)
|
||||
s = cxx_sym;
|
||||
else
|
||||
s = sym;
|
||||
if (fnmatch (expr->pattern, sym, 0) == 0)
|
||||
break;
|
||||
expr = expr->next;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int
|
||||
lang_vers_match_lang_java (struct bfd_elf_version_expr *expr,
|
||||
const char *sym)
|
||||
{
|
||||
char *alt_sym;
|
||||
int result;
|
||||
|
||||
if (expr->pattern[0] == '*' && expr->pattern[1] == '\0')
|
||||
return 1;
|
||||
|
||||
alt_sym = cplus_demangle (sym, DMGL_JAVA);
|
||||
if (!alt_sym)
|
||||
{
|
||||
/* cplus_demangle (also) returns NULL when it is not a Java symbol.
|
||||
Should we early out FALSE in this case? */
|
||||
result = fnmatch (expr->pattern, sym, 0) == 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
result = fnmatch (expr->pattern, alt_sym, 0) == 0;
|
||||
free (alt_sym);
|
||||
}
|
||||
|
||||
return result;
|
||||
out_ret:
|
||||
if (cxx_sym != sym)
|
||||
free ((char *) cxx_sym);
|
||||
if (java_sym != sym)
|
||||
free ((char *) java_sym);
|
||||
return expr;
|
||||
}
|
||||
|
||||
/* This is called for each variable name or match expression. */
|
||||
@ -5048,18 +5092,19 @@ lang_new_vers_pattern (struct bfd_elf_version_expr *orig,
|
||||
ret->pattern = new;
|
||||
ret->symver = 0;
|
||||
ret->script = 0;
|
||||
ret->wildcard = wildcardp (new);
|
||||
|
||||
if (lang == NULL || strcasecmp (lang, "C") == 0)
|
||||
ret->match = lang_vers_match_lang_c;
|
||||
ret->mask = BFD_ELF_VERSION_C_TYPE;
|
||||
else if (strcasecmp (lang, "C++") == 0)
|
||||
ret->match = lang_vers_match_lang_cplusplus;
|
||||
ret->mask = BFD_ELF_VERSION_CXX_TYPE;
|
||||
else if (strcasecmp (lang, "Java") == 0)
|
||||
ret->match = lang_vers_match_lang_java;
|
||||
ret->mask = BFD_ELF_VERSION_JAVA_TYPE;
|
||||
else
|
||||
{
|
||||
einfo (_("%X%P: unknown language `%s' in version information\n"),
|
||||
lang);
|
||||
ret->match = lang_vers_match_lang_c;
|
||||
ret->mask = BFD_ELF_VERSION_C_TYPE;
|
||||
}
|
||||
|
||||
return ldemul_new_vers_pattern (ret);
|
||||
@ -5074,15 +5119,11 @@ lang_new_vers_node (struct bfd_elf_version_expr *globals,
|
||||
{
|
||||
struct bfd_elf_version_tree *ret;
|
||||
|
||||
ret = xmalloc (sizeof *ret);
|
||||
ret->next = NULL;
|
||||
ret->name = NULL;
|
||||
ret->vernum = 0;
|
||||
ret->globals = globals;
|
||||
ret->locals = locals;
|
||||
ret->deps = NULL;
|
||||
ret = xcalloc (1, sizeof *ret);
|
||||
ret->globals.list = globals;
|
||||
ret->locals.list = locals;
|
||||
ret->match = lang_vers_match;
|
||||
ret->name_indx = (unsigned int) -1;
|
||||
ret->used = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -5090,6 +5131,102 @@ lang_new_vers_node (struct bfd_elf_version_expr *globals,
|
||||
|
||||
static int version_index;
|
||||
|
||||
static hashval_t
|
||||
version_expr_head_hash (const void *p)
|
||||
{
|
||||
const struct bfd_elf_version_expr *e = p;
|
||||
|
||||
return htab_hash_string (e->pattern);
|
||||
}
|
||||
|
||||
static int
|
||||
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->pattern, e2->pattern) == 0;
|
||||
}
|
||||
|
||||
static void
|
||||
lang_finalize_version_expr_head (struct bfd_elf_version_expr_head *head)
|
||||
{
|
||||
size_t count = 0;
|
||||
struct bfd_elf_version_expr *e, *next;
|
||||
struct bfd_elf_version_expr **list_loc, **remaining_loc;
|
||||
|
||||
for (e = head->list; e; e = e->next)
|
||||
{
|
||||
if (!e->wildcard)
|
||||
count++;
|
||||
head->mask |= e->mask;
|
||||
}
|
||||
|
||||
if (count)
|
||||
{
|
||||
head->htab = htab_create (count * 2, version_expr_head_hash,
|
||||
version_expr_head_eq, NULL);
|
||||
list_loc = &head->list;
|
||||
remaining_loc = &head->remaining;
|
||||
for (e = head->list; e; e = next)
|
||||
{
|
||||
next = e->next;
|
||||
if (e->wildcard)
|
||||
{
|
||||
*remaining_loc = e;
|
||||
remaining_loc = &e->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
void **loc = htab_find_slot (head->htab, e, INSERT);
|
||||
|
||||
if (*loc)
|
||||
{
|
||||
struct bfd_elf_version_expr *e1, *last;
|
||||
|
||||
e1 = *loc;
|
||||
last = NULL;
|
||||
do
|
||||
{
|
||||
if (e1->mask == e->mask)
|
||||
{
|
||||
last = NULL;
|
||||
break;
|
||||
}
|
||||
last = e1;
|
||||
e1 = e1->next;
|
||||
}
|
||||
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->pattern); */
|
||||
free (e);
|
||||
}
|
||||
else
|
||||
{
|
||||
e->next = last->next;
|
||||
last->next = e;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
*loc = e;
|
||||
*list_loc = e;
|
||||
list_loc = &e->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
*remaining_loc = NULL;
|
||||
*list_loc = head->remaining;
|
||||
}
|
||||
else
|
||||
head->remaining = head->list;
|
||||
}
|
||||
|
||||
/* This is called when we know the name and dependencies of the
|
||||
version. */
|
||||
|
||||
@ -5117,32 +5254,59 @@ lang_register_vers_node (const char *name,
|
||||
if (strcmp (t->name, name) == 0)
|
||||
einfo (_("%X%P: duplicate version tag `%s'\n"), name);
|
||||
|
||||
lang_finalize_version_expr_head (&version->globals);
|
||||
lang_finalize_version_expr_head (&version->locals);
|
||||
|
||||
/* Check the global and local match names, and make sure there
|
||||
aren't any duplicates. */
|
||||
|
||||
for (e1 = version->globals; e1 != NULL; e1 = e1->next)
|
||||
for (e1 = version->globals.list; e1 != NULL; e1 = e1->next)
|
||||
{
|
||||
for (t = lang_elf_version_info; t != NULL; t = t->next)
|
||||
{
|
||||
struct bfd_elf_version_expr *e2;
|
||||
|
||||
for (e2 = t->locals; e2 != NULL; e2 = e2->next)
|
||||
if (strcmp (e1->pattern, e2->pattern) == 0)
|
||||
einfo (_("%X%P: duplicate expression `%s' in version information\n"),
|
||||
e1->pattern);
|
||||
if (t->locals.htab && e1->wildcard == 0)
|
||||
{
|
||||
e2 = htab_find (t->locals.htab, e1);
|
||||
while (e2 && strcmp (e1->pattern, e2->pattern) == 0)
|
||||
{
|
||||
if (e1->mask == e2->mask)
|
||||
einfo (_("%X%P: duplicate expression `%s' in version information\n"),
|
||||
e1->pattern);
|
||||
e2 = e2->next;
|
||||
}
|
||||
}
|
||||
else if (e1->wildcard)
|
||||
for (e2 = t->locals.remaining; e2 != NULL; e2 = e2->next)
|
||||
if (strcmp (e1->pattern, e2->pattern) == 0 && e1->mask == e2->mask)
|
||||
einfo (_("%X%P: duplicate expression `%s' in version information\n"),
|
||||
e1->pattern);
|
||||
}
|
||||
}
|
||||
|
||||
for (e1 = version->locals; e1 != NULL; e1 = e1->next)
|
||||
for (e1 = version->locals.list; e1 != NULL; e1 = e1->next)
|
||||
{
|
||||
for (t = lang_elf_version_info; t != NULL; t = t->next)
|
||||
{
|
||||
struct bfd_elf_version_expr *e2;
|
||||
|
||||
for (e2 = t->globals; e2 != NULL; e2 = e2->next)
|
||||
if (strcmp (e1->pattern, e2->pattern) == 0)
|
||||
einfo (_("%X%P: duplicate expression `%s' in version information\n"),
|
||||
e1->pattern);
|
||||
if (t->globals.htab && e1->wildcard == 0)
|
||||
{
|
||||
e2 = htab_find (t->globals.htab, e1);
|
||||
while (e2 && strcmp (e1->pattern, e2->pattern) == 0)
|
||||
{
|
||||
if (e1->mask == e2->mask)
|
||||
einfo (_("%X%P: duplicate expression `%s' in version information\n"),
|
||||
e1->pattern);
|
||||
e2 = e2->next;
|
||||
}
|
||||
}
|
||||
else if (e1->wildcard)
|
||||
for (e2 = t->globals.remaining; e2 != NULL; e2 = e2->next)
|
||||
if (strcmp (e1->pattern, e2->pattern) == 0 && e1->mask == e2->mask)
|
||||
einfo (_("%X%P: duplicate expression `%s' in version information\n"),
|
||||
e1->pattern);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user