Check symbols with undefine version.

This commit is contained in:
H.J. Lu 2002-08-08 03:50:18 +00:00
parent cb811fe799
commit 3194163592
14 changed files with 152 additions and 53 deletions

View File

@ -1,3 +1,11 @@
2002-08-07 H.J. Lu <hjl@gnu.org>
* elflink.h (NAME(bfd_elf,size_dynamic_sections)): Check symbol
with undefined version if needed.
(elf_link_assign_sym_version): Match a default symbol with a
version without definition. No need to hide the default
definition separately.
2002-08-08 Alan Modra <amodra@bigpond.net.au> 2002-08-08 Alan Modra <amodra@bigpond.net.au>
* elflink.h (elf_link_output_extsym): Don't output symbols from * elflink.h (elf_link_output_extsym): Don't output symbols from

View File

@ -2938,6 +2938,9 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
struct elf_info_failed eif; struct elf_info_failed eif;
struct elf_link_hash_entry *h; struct elf_link_hash_entry *h;
asection *dynstr; asection *dynstr;
struct bfd_elf_version_tree *t;
struct bfd_elf_version_expr *d;
boolean all_defined;
*sinterpptr = bfd_get_section_by_name (dynobj, ".interp"); *sinterpptr = bfd_get_section_by_name (dynobj, ".interp");
BFD_ASSERT (*sinterpptr != NULL || info->shared); BFD_ASSERT (*sinterpptr != NULL || info->shared);
@ -3018,6 +3021,54 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
return false; return false;
} }
/* Make all global versions with definiton. */
for (t = verdefs; t != NULL; t = t->next)
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 == NULL
|| (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 != NULL
&& (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. */ /* Attach all the symbols to their version information. */
asvinfo.output_bfd = output_bfd; asvinfo.output_bfd = output_bfd;
asvinfo.info = info; asvinfo.info = info;
@ -3030,6 +3081,28 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
if (asvinfo.failed) if (asvinfo.failed)
return false; return false;
if (!info->allow_undefined_version)
{
/* 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)
if (!d->symver && !d->script
&& strchr (d->pattern, '*') == NULL)
{
(*_bfd_error_handler)
(_("%s: undefined version: %s"),
d->pattern, t->name);
all_defined = false;
}
if (!all_defined)
{
bfd_set_error (bfd_error_bad_value);
return false;
}
}
/* Find all symbols which were defined in a dynamic object and make /* Find all symbols which were defined in a dynamic object and make
the backend pick a reasonable value for them. */ the backend pick a reasonable value for them. */
elf_link_hash_traverse (elf_hash_table (info), elf_link_hash_traverse (elf_hash_table (info),
@ -4258,7 +4331,6 @@ elf_link_assign_sym_version (h, data)
(_("%s: undefined versioned symbol name %s"), (_("%s: undefined versioned symbol name %s"),
bfd_get_filename (sinfo->output_bfd), h->root.root.string); bfd_get_filename (sinfo->output_bfd), h->root.root.string);
bfd_set_error (bfd_error_bad_value); bfd_set_error (bfd_error_bad_value);
error_return:
sinfo->failed = true; sinfo->failed = true;
return false; return false;
} }
@ -4283,18 +4355,34 @@ elf_link_assign_sym_version (h, data)
{ {
if (t->globals != NULL) if (t->globals != NULL)
{ {
boolean matched;
matched = false;
for (d = t->globals; d != NULL; d = d->next) for (d = t->globals; d != NULL; d = d->next)
{ {
if ((*d->match) (d, h->root.root.string)) if ((*d->match) (d, h->root.root.string))
{ {
h->verinfo.vertree = t; if (d->symver)
local_ver = NULL; matched = true;
break; 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) if (d != NULL)
break; 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) if (t->locals != NULL)
@ -4327,43 +4415,6 @@ elf_link_assign_sym_version (h, data)
(*bed->elf_backend_hide_symbol) (info, h, true); (*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; return true;

View File

@ -1,3 +1,8 @@
2002-08-07 H.J. Lu <hjl@gnu.org>
* bfdlink.h (bfd_link_info): Add allow_undefined_version.
(bfd_elf_version_expr): Add symver and script.
2002-07-31 Ian Dall <ian@sibyl.beware.dropbear.id.au> 2002-07-31 Ian Dall <ian@sibyl.beware.dropbear.id.au>
* bfdlink.h (bfd_link_common_skip_ar_symbols): New enum. * bfdlink.h (bfd_link_common_skip_ar_symbols): New enum.

View File

@ -262,6 +262,9 @@ struct bfd_link_info
/* true if ok to have multiple definition. */ /* true if ok to have multiple definition. */
boolean allow_multiple_definition; boolean allow_multiple_definition;
/* true if ok to have version with no definition. */
boolean allow_undefined_version;
/* Which symbols to strip. */ /* Which symbols to strip. */
enum bfd_link_strip strip; enum bfd_link_strip strip;
@ -602,6 +605,10 @@ struct bfd_elf_version_expr
const char *pattern; const char *pattern;
/* Matching function. */ /* Matching function. */
int (*match) PARAMS((struct bfd_elf_version_expr *, const char *)); 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. */ /* Version dependencies. */

View File

@ -1,3 +1,17 @@
2002-08-07 H.J. Lu <hjl@gnu.org>
* ld.texinfo: Document --no-undefined-version.
* ldlang.c (lang_new_vers_pattern): Set the `symver' and
`script.' fields to 0.
* ldmain.c (main): Initialize the allow_undefined_version to
true.
* lexsup.c (OPTION_NO_UNDEFINED_VERSION): New.
(ld_options): Add --no-undefined-version.
(parse_args): Support OPTION_NO_UNDEFINED_VERSION.
2002-08-07 Nick Clifton <nickc@redhat.com> 2002-08-07 Nick Clifton <nickc@redhat.com>
* emultempl/armelf.em (arm_elf_before_allocation): Only search for * emultempl/armelf.em (arm_elf_before_allocation): Only search for

View File

@ -1102,6 +1102,12 @@ select which function is most appropriate for the current architecture.
I.E. dynamically select an appropriate memset function. Apparently it I.E. dynamically select an appropriate memset function. Apparently it
is also normal for HPPA shared libraries to have undefined symbols. is also normal for HPPA shared libraries to have undefined symbols.
@kindex --no-undefined-version
@item --no-undefined-version
Normally when a symbol has an undefined version, the linker will ignore
it. This option disallows symbols with undefined version and a fatal error
will be issued instead.
@kindex --no-warn-mismatch @kindex --no-warn-mismatch
@item --no-warn-mismatch @item --no-warn-mismatch
Normally @command{ld} will give an error if you try to link together input Normally @command{ld} will give an error if you try to link together input

View File

@ -5132,6 +5132,8 @@ lang_new_vers_pattern (orig, new, lang)
ret = (struct bfd_elf_version_expr *) xmalloc (sizeof *ret); ret = (struct bfd_elf_version_expr *) xmalloc (sizeof *ret);
ret->next = orig; ret->next = orig;
ret->pattern = new; ret->pattern = new;
ret->symver = 0;
ret->script = 0;
if (lang == NULL || strcasecmp (lang, "C") == 0) if (lang == NULL || strcasecmp (lang, "C") == 0)
ret->match = lang_vers_match_lang_c; ret->match = lang_vers_match_lang_c;

View File

@ -240,6 +240,7 @@ main (argc, argv)
link_info.no_undefined = false; link_info.no_undefined = false;
link_info.allow_shlib_undefined = false; link_info.allow_shlib_undefined = false;
link_info.allow_multiple_definition = false; link_info.allow_multiple_definition = false;
link_info.allow_undefined_version = true;
link_info.strip = strip_none; link_info.strip = strip_none;
link_info.discard = discard_sec_merge; link_info.discard = discard_sec_merge;
link_info.keep_memory = true; link_info.keep_memory = true;

View File

@ -127,7 +127,8 @@ int parsing_defsym = 0;
#define OPTION_TARGET_HELP (OPTION_UNIQUE + 1) #define OPTION_TARGET_HELP (OPTION_UNIQUE + 1)
#define OPTION_ALLOW_SHLIB_UNDEFINED (OPTION_TARGET_HELP + 1) #define OPTION_ALLOW_SHLIB_UNDEFINED (OPTION_TARGET_HELP + 1)
#define OPTION_ALLOW_MULTIPLE_DEFINITION (OPTION_ALLOW_SHLIB_UNDEFINED + 1) #define OPTION_ALLOW_MULTIPLE_DEFINITION (OPTION_ALLOW_SHLIB_UNDEFINED + 1)
#define OPTION_DISCARD_NONE (OPTION_ALLOW_MULTIPLE_DEFINITION + 1) #define OPTION_NO_UNDEFINED_VERSION (OPTION_ALLOW_MULTIPLE_DEFINITION + 1)
#define OPTION_DISCARD_NONE (OPTION_NO_UNDEFINED_VERSION + 1)
#define OPTION_SPARE_DYNAMIC_TAGS (OPTION_DISCARD_NONE + 1) #define OPTION_SPARE_DYNAMIC_TAGS (OPTION_DISCARD_NONE + 1)
#define OPTION_NO_DEFINE_COMMON (OPTION_SPARE_DYNAMIC_TAGS + 1) #define OPTION_NO_DEFINE_COMMON (OPTION_SPARE_DYNAMIC_TAGS + 1)
#define OPTION_NOSTDLIB (OPTION_NO_DEFINE_COMMON + 1) #define OPTION_NOSTDLIB (OPTION_NO_DEFINE_COMMON + 1)
@ -322,6 +323,8 @@ static const struct ld_option ld_options[] =
'\0', NULL, N_("Allow undefined symbols in shared objects"), TWO_DASHES }, '\0', NULL, N_("Allow undefined symbols in shared objects"), TWO_DASHES },
{ {"allow-multiple-definition", no_argument, NULL, OPTION_ALLOW_MULTIPLE_DEFINITION}, { {"allow-multiple-definition", no_argument, NULL, OPTION_ALLOW_MULTIPLE_DEFINITION},
'\0', NULL, N_("Allow multiple definitions"), TWO_DASHES }, '\0', NULL, N_("Allow multiple definitions"), TWO_DASHES },
{ {"no-undefined-version", no_argument, NULL, OPTION_NO_UNDEFINED_VERSION},
'\0', NULL, N_("Disallow undefined version"), TWO_DASHES },
{ {"no-warn-mismatch", no_argument, NULL, OPTION_NO_WARN_MISMATCH}, { {"no-warn-mismatch", no_argument, NULL, OPTION_NO_WARN_MISMATCH},
'\0', NULL, N_("Don't warn about mismatched input files"), TWO_DASHES}, '\0', NULL, N_("Don't warn about mismatched input files"), TWO_DASHES},
{ {"no-whole-archive", no_argument, NULL, OPTION_NO_WHOLE_ARCHIVE}, { {"no-whole-archive", no_argument, NULL, OPTION_NO_WHOLE_ARCHIVE},
@ -767,6 +770,9 @@ parse_args (argc, argv)
case OPTION_ALLOW_MULTIPLE_DEFINITION: case OPTION_ALLOW_MULTIPLE_DEFINITION:
link_info.allow_multiple_definition = true; link_info.allow_multiple_definition = true;
break; break;
case OPTION_NO_UNDEFINED_VERSION:
link_info.allow_undefined_version = false;
break;
case OPTION_NO_WARN_MISMATCH: case OPTION_NO_WARN_MISMATCH:
command_line.warn_mismatch = false; command_line.warn_mismatch = false;
break; break;

View File

@ -1,3 +1,11 @@
2002-08-07 H.J. Lu <hjl@gnu.org>
* ld-elfvers/vers.exp: Add --no-undefined-version.
* ld-elfvers/vers1.map: Remove the unused foo1 and foo2.
* ld-elfvers/vers8.map: Likewise.
* ld-elfvers/vers18.map: Likewise.
2002-07-30 John David Anglin <dave@hiauly1.hia.nrc.ca> 2002-07-30 John David Anglin <dave@hiauly1.hia.nrc.ca>
* ld-discard/discard.exp, ld-scripts/phdrs.exp, ld-scripts/phdrs2.exp, * ld-discard/discard.exp, ld-scripts/phdrs.exp, ld-scripts/phdrs2.exp,

View File

@ -62,7 +62,7 @@ set tmpdir tmpdir
set VOBJDUMP_FLAGS --private-headers set VOBJDUMP_FLAGS --private-headers
set DOBJDUMP_FLAGS --dynamic-syms set DOBJDUMP_FLAGS --dynamic-syms
set SOBJDUMP_FLAGS --syms set SOBJDUMP_FLAGS --syms
set shared --shared set shared "--shared --no-undefined-version"
set script --version-script set script --version-script
proc test_ar { test lib object expect } { proc test_ar { test lib object expect } {
@ -643,7 +643,7 @@ proc build_exec { test source execname flags solibname verexp versymexp symexp }
global CC global CC
global CFLAGS global CFLAGS
set shared --shared set shared "--shared --no-undefined-version"
set script --version-script set script --version-script
if ![ld_compile "$CC -S $CFLAGS" $srcdir/$subdir/$source $tmpdir/$execname.s] { if ![ld_compile "$CC -S $CFLAGS" $srcdir/$subdir/$source $tmpdir/$execname.s] {
unresolved "$test" unresolved "$test"

View File

@ -1,6 +1,4 @@
VERS_1.1 { VERS_1.1 {
global:
foo1;
local: local:
hide_old*; hide_old*;
hide_original*; hide_original*;
@ -8,7 +6,6 @@ VERS_1.1 {
}; };
VERS_1.2 { VERS_1.2 {
foo2;
} VERS_1.1; } VERS_1.1;
VERS_2.0 { VERS_2.0 {

View File

@ -1,6 +1,4 @@
VERS_1.1 { VERS_1.1 {
global:
foo1;
local: local:
hide_old*; hide_old*;
hide_original*; hide_original*;
@ -8,7 +6,6 @@ VERS_1.1 {
}; };
VERS_1.2 { VERS_1.2 {
foo2;
} VERS_1.1; } VERS_1.1;
VERS_2.0 { VERS_2.0 {

View File

@ -1,7 +1,5 @@
VERSION { VERSION {
VERS_1.1 { VERS_1.1 {
global:
foo1;
local: local:
hide_old*; hide_old*;
hide_original*; hide_original*;
@ -9,7 +7,6 @@ VERSION {
}; };
VERS_1.2 { VERS_1.2 {
foo2;
} VERS_1.1; } VERS_1.1;
VERS_2.0 { VERS_2.0 {