PATCH: Update on symbol versioning
H. J. Lu
hjl@lucon.org
Tue Aug 6 10:07:00 GMT 2002
This patch adds checking for symbol with undefined version. As a bonus,
we don't need to hide the default definition separately. I also updated
the testsuite. I have one concern that there may be some broken vesion
maps.
H.J.
-------------- next part --------------
bfd/
2002-08-06 H.J. Lu <hjl@gnu.org>
* elflink.h (NAME(bfd_elf,size_dynamic_sections)): Check symbol
with undefined version.
(elf_link_assign_sym_version): Match a default symbol with a
version without definition. No need to hide the default
definition separately.
include/
2002-08-06 H.J. Lu <hjl@gnu.org>
* bfdlink.h (bfd_elf_version_expr): Add 2 new fields, symver
and script.
ld/
2002-08-06 H.J. Lu <hjl@gnu.org>
* ldlang.c (lang_new_vers_pattern): Set the `symver' and
`script.' fields to 0.
ld/testsuite
2002-08-06 H.J. Lu <hjl@gnu.org>
* ld-elfvers/vers1.map: Remove the unused foo1 and foo2.
* ld-elfvers/vers8.map: Likewise.
* ld-elfvers/vers18.map: Likewise.
--- binutils/bfd/elflink.h.defver Fri Jul 26 23:41:26 2002
+++ binutils/bfd/elflink.h Tue Aug 6 09:12:17 2002
@@ -2938,6 +2938,8 @@ NAME(bfd_elf,size_dynamic_sections) (out
struct elf_info_failed eif;
struct elf_link_hash_entry *h;
asection *dynstr;
+ struct bfd_elf_version_tree *t;
+ struct bfd_elf_version_expr *d;
*sinterpptr = bfd_get_section_by_name (dynobj, ".interp");
BFD_ASSERT (*sinterpptr != NULL || info->shared);
@@ -3018,6 +3020,62 @@ NAME(bfd_elf,size_dynamic_sections) (out
return false;
}
+ /* Make all global versions with definiton. */
+ for (t = verdefs; t != NULL; t = t->next)
+ {
+ if (t->globals != NULL)
+ {
+ for (d = t->globals; d != NULL; d = d->next)
+ {
+ if (!d->symver && strchr (d->pattern, '*') == NULL)
+ {
+ const char *verstr, *name;
+ size_t namelen, verlen, newlen;
+ char *newname, *p;
+ struct elf_link_hash_entry *newh;
+
+ name = d->pattern;
+ namelen = strlen (name);
+ verstr = t->name;
+ verlen = strlen (verstr);
+ newlen = namelen + verlen + 3;
+
+ newname = (char *) bfd_malloc
+ ((bfd_size_type) newlen);
+ if (newname == NULL)
+ return false;
+ memcpy (newname, name, namelen);
+
+ /* Check the hidden versioned definition. */
+ p = newname + namelen;
+ *p++ = ELF_VER_CHR;
+ memcpy (p, verstr, verlen + 1);
+ newh = elf_link_hash_lookup
+ (elf_hash_table (info), newname, false,
+ false, false);
+ if (!newh
+ || (newh->root.type != bfd_link_hash_defined
+ && newh->root.type != bfd_link_hash_defweak))
+ {
+ /* Check the default versioned definition. */
+ *p++ = ELF_VER_CHR;
+ memcpy (p, verstr, verlen + 1);
+ newh = elf_link_hash_lookup
+ (elf_hash_table (info), newname,
+ false, false, false);
+ }
+ free (newname);
+
+ /* Mark this version if there is a definition. */
+ if (newh
+ && (newh->root.type == bfd_link_hash_defined
+ || newh->root.type == bfd_link_hash_defweak))
+ d->symver = 1;
+ }
+ }
+ }
+ }
+
/* Attach all the symbols to their version information. */
asvinfo.output_bfd = output_bfd;
asvinfo.info = info;
@@ -3030,6 +3088,26 @@ NAME(bfd_elf,size_dynamic_sections) (out
if (asvinfo.failed)
return false;
+ /* Check if all global versions have a definiton. */
+ for (t = verdefs; t != NULL; t = t->next)
+ {
+ if (t->globals != NULL)
+ {
+ for (d = t->globals; d != NULL; d = d->next)
+ {
+ if (!d->symver && !d->script
+ && strchr (d->pattern, '*') == NULL)
+ {
+ (*_bfd_error_handler)
+ (_("%s: undefined version: %s"),
+ d->pattern, t->name);
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+ }
+ }
+ }
+
/* Find all symbols which were defined in a dynamic object and make
the backend pick a reasonable value for them. */
elf_link_hash_traverse (elf_hash_table (info),
@@ -4258,7 +4336,6 @@ elf_link_assign_sym_version (h, data)
(_("%s: undefined versioned symbol name %s"),
bfd_get_filename (sinfo->output_bfd), h->root.root.string);
bfd_set_error (bfd_error_bad_value);
- error_return:
sinfo->failed = true;
return false;
}
@@ -4283,18 +4360,34 @@ elf_link_assign_sym_version (h, data)
{
if (t->globals != NULL)
{
+ boolean matched;
+
+ matched = false;
for (d = t->globals; d != NULL; d = d->next)
{
if ((*d->match) (d, h->root.root.string))
{
- h->verinfo.vertree = t;
- local_ver = NULL;
- break;
+ 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)
+ /* There is no undefined version for this symbol. Hide the
+ default one. */
+ (*bed->elf_backend_hide_symbol) (info, h, true);
}
if (t->locals != NULL)
@@ -4327,43 +4420,6 @@ elf_link_assign_sym_version (h, data)
(*bed->elf_backend_hide_symbol) (info, h, true);
}
}
-
- /* We need to check if a hidden versioned definition should
- hide the default one. */
- if (h->dynindx != -1 && h->verinfo.vertree != NULL)
- {
- const char *verstr, *name;
- size_t namelen, verlen, newlen;
- char *newname;
- struct elf_link_hash_entry *newh;
-
- name = h->root.root.string;
- namelen = strlen (name);
- verstr = h->verinfo.vertree->name;
- verlen = strlen (verstr);
- newlen = namelen + verlen + 2;
-
- newname = (char *) bfd_malloc ((bfd_size_type) newlen);
- if (newname == NULL)
- goto error_return;
- memcpy (newname, name, namelen);
-
- /* Check the hidden versioned definition. */
- p = newname + namelen;
- *p++ = ELF_VER_CHR;
- memcpy (p, verstr, verlen + 1);
- newh = elf_link_hash_lookup (elf_hash_table (info), newname,
- false, false, false);
-
- if (newh
- && (newh->root.type == bfd_link_hash_defined
- || newh->root.type == bfd_link_hash_defweak))
- /* We found a hidden versioned definition. Hide the
- default one. */
- (*bed->elf_backend_hide_symbol) (info, h, true);
-
- free (newname);
- }
}
return true;
--- binutils/include/bfdlink.h.defver Wed Jul 31 08:54:09 2002
+++ binutils/include/bfdlink.h Tue Aug 6 08:09:22 2002
@@ -602,6 +602,10 @@ struct bfd_elf_version_expr
const char *pattern;
/* Matching function. */
int (*match) PARAMS((struct bfd_elf_version_expr *, const char *));
+ /* Defined by ".symver". */
+ unsigned int symver: 1;
+ /* Defined by version script. */
+ unsigned int script : 1;
};
/* Version dependencies. */
--- binutils/ld/ldlang.c.defver Tue Jul 30 14:38:18 2002
+++ binutils/ld/ldlang.c Tue Aug 6 08:09:44 2002
@@ -5132,6 +5132,8 @@ lang_new_vers_pattern (orig, new, lang)
ret = (struct bfd_elf_version_expr *) xmalloc (sizeof *ret);
ret->next = orig;
ret->pattern = new;
+ ret->symver = 0;
+ ret->script = 0;
if (lang == NULL || strcasecmp (lang, "C") == 0)
ret->match = lang_vers_match_lang_c;
--- binutils/ld/testsuite/ld-elfvers/vers1.map.defver Thu Jun 3 11:02:11 1999
+++ binutils/ld/testsuite/ld-elfvers/vers1.map Tue Aug 6 08:50:55 2002
@@ -1,6 +1,4 @@
VERS_1.1 {
- global:
- foo1;
local:
hide_old*;
hide_original*;
@@ -8,7 +6,6 @@ VERS_1.1 {
};
VERS_1.2 {
- foo2;
} VERS_1.1;
VERS_2.0 {
--- binutils/ld/testsuite/ld-elfvers/vers18.map.defver Tue Aug 6 09:06:44 2002
+++ binutils/ld/testsuite/ld-elfvers/vers18.map Tue Aug 6 09:04:19 2002
@@ -1,6 +1,4 @@
VERS_1.1 {
- global:
- foo1;
local:
hide_old*;
hide_original*;
@@ -8,7 +6,6 @@ VERS_1.1 {
};
VERS_1.2 {
- foo2;
} VERS_1.1;
VERS_2.0 {
--- binutils/ld/testsuite/ld-elfvers/vers8.map.defver Thu Jun 3 11:02:11 1999
+++ binutils/ld/testsuite/ld-elfvers/vers8.map Tue Aug 6 09:03:59 2002
@@ -1,7 +1,5 @@
VERSION {
VERS_1.1 {
- global:
- foo1;
local:
hide_old*;
hide_original*;
@@ -9,7 +7,6 @@ VERSION {
};
VERS_1.2 {
- foo2;
} VERS_1.1;
VERS_2.0 {
More information about the Binutils
mailing list