aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorH.J. Lu <hjl.tools@gmail.com>2002-08-08 03:50:18 +0000
committerH.J. Lu <hjl.tools@gmail.com>2002-08-08 03:50:18 +0000
commit3194163592008a9e575d577921647ab91b09c77b (patch)
tree4c4fa4fb54d632b2db20f90e84d881f337cc66c3
parentcb811fe799b18a559b53b719e40dd65504db57c0 (diff)
downloadgdb-3194163592008a9e575d577921647ab91b09c77b.zip
gdb-3194163592008a9e575d577921647ab91b09c77b.tar.gz
gdb-3194163592008a9e575d577921647ab91b09c77b.tar.bz2
Check symbols with undefine version.
-rw-r--r--bfd/ChangeLog8
-rw-r--r--bfd/elflink.h133
-rw-r--r--include/ChangeLog5
-rw-r--r--include/bfdlink.h7
-rw-r--r--ld/ChangeLog14
-rw-r--r--ld/ld.texinfo6
-rw-r--r--ld/ldlang.c2
-rw-r--r--ld/ldmain.c1
-rw-r--r--ld/lexsup.c8
-rw-r--r--ld/testsuite/ChangeLog8
-rw-r--r--ld/testsuite/ld-elfvers/vers.exp4
-rw-r--r--ld/testsuite/ld-elfvers/vers1.map3
-rw-r--r--ld/testsuite/ld-elfvers/vers18.map3
-rw-r--r--ld/testsuite/ld-elfvers/vers8.map3
14 files changed, 152 insertions, 53 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 41dc63e..40a824e 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -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>
* elflink.h (elf_link_output_extsym): Don't output symbols from
diff --git a/bfd/elflink.h b/bfd/elflink.h
index 59cc397..b1732e4 100644
--- a/bfd/elflink.h
+++ b/bfd/elflink.h
@@ -2938,6 +2938,9 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
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;
+ boolean all_defined;
*sinterpptr = bfd_get_section_by_name (dynobj, ".interp");
BFD_ASSERT (*sinterpptr != NULL || info->shared);
@@ -3018,6 +3021,54 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
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. */
asvinfo.output_bfd = output_bfd;
asvinfo.info = info;
@@ -3030,6 +3081,28 @@ NAME(bfd_elf,size_dynamic_sections) (output_bfd, soname, rpath,
if (asvinfo.failed)
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
the backend pick a reasonable value for them. */
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"),
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 +4355,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 +4415,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;
diff --git a/include/ChangeLog b/include/ChangeLog
index ea51a95..39f1874 100644
--- a/include/ChangeLog
+++ b/include/ChangeLog
@@ -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>
* bfdlink.h (bfd_link_common_skip_ar_symbols): New enum.
diff --git a/include/bfdlink.h b/include/bfdlink.h
index c36564f..4998fe3 100644
--- a/include/bfdlink.h
+++ b/include/bfdlink.h
@@ -262,6 +262,9 @@ struct bfd_link_info
/* true if ok to have multiple definition. */
boolean allow_multiple_definition;
+ /* true if ok to have version with no definition. */
+ boolean allow_undefined_version;
+
/* Which symbols to strip. */
enum bfd_link_strip strip;
@@ -602,6 +605,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. */
diff --git a/ld/ChangeLog b/ld/ChangeLog
index a587652..1afde2a 100644
--- a/ld/ChangeLog
+++ b/ld/ChangeLog
@@ -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>
* emultempl/armelf.em (arm_elf_before_allocation): Only search for
diff --git a/ld/ld.texinfo b/ld/ld.texinfo
index dadc75b..12030c0 100644
--- a/ld/ld.texinfo
+++ b/ld/ld.texinfo
@@ -1102,6 +1102,12 @@ select which function is most appropriate for the current architecture.
I.E. dynamically select an appropriate memset function. Apparently it
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
@item --no-warn-mismatch
Normally @command{ld} will give an error if you try to link together input
diff --git a/ld/ldlang.c b/ld/ldlang.c
index c260829..a777e5a 100644
--- a/ld/ldlang.c
+++ b/ld/ldlang.c
@@ -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;
diff --git a/ld/ldmain.c b/ld/ldmain.c
index b50ef43..84baa4d 100644
--- a/ld/ldmain.c
+++ b/ld/ldmain.c
@@ -240,6 +240,7 @@ main (argc, argv)
link_info.no_undefined = false;
link_info.allow_shlib_undefined = false;
link_info.allow_multiple_definition = false;
+ link_info.allow_undefined_version = true;
link_info.strip = strip_none;
link_info.discard = discard_sec_merge;
link_info.keep_memory = true;
diff --git a/ld/lexsup.c b/ld/lexsup.c
index ddaf692..4acb4fd 100644
--- a/ld/lexsup.c
+++ b/ld/lexsup.c
@@ -127,7 +127,8 @@ int parsing_defsym = 0;
#define OPTION_TARGET_HELP (OPTION_UNIQUE + 1)
#define OPTION_ALLOW_SHLIB_UNDEFINED (OPTION_TARGET_HELP + 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_NO_DEFINE_COMMON (OPTION_SPARE_DYNAMIC_TAGS + 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 },
{ {"allow-multiple-definition", no_argument, NULL, OPTION_ALLOW_MULTIPLE_DEFINITION},
'\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},
'\0', NULL, N_("Don't warn about mismatched input files"), TWO_DASHES},
{ {"no-whole-archive", no_argument, NULL, OPTION_NO_WHOLE_ARCHIVE},
@@ -767,6 +770,9 @@ parse_args (argc, argv)
case OPTION_ALLOW_MULTIPLE_DEFINITION:
link_info.allow_multiple_definition = true;
break;
+ case OPTION_NO_UNDEFINED_VERSION:
+ link_info.allow_undefined_version = false;
+ break;
case OPTION_NO_WARN_MISMATCH:
command_line.warn_mismatch = false;
break;
diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog
index b492850..0c2e3b9 100644
--- a/ld/testsuite/ChangeLog
+++ b/ld/testsuite/ChangeLog
@@ -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>
* ld-discard/discard.exp, ld-scripts/phdrs.exp, ld-scripts/phdrs2.exp,
diff --git a/ld/testsuite/ld-elfvers/vers.exp b/ld/testsuite/ld-elfvers/vers.exp
index 1acc0e6..7380729 100644
--- a/ld/testsuite/ld-elfvers/vers.exp
+++ b/ld/testsuite/ld-elfvers/vers.exp
@@ -62,7 +62,7 @@ set tmpdir tmpdir
set VOBJDUMP_FLAGS --private-headers
set DOBJDUMP_FLAGS --dynamic-syms
set SOBJDUMP_FLAGS --syms
-set shared --shared
+set shared "--shared --no-undefined-version"
set script --version-script
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 CFLAGS
- set shared --shared
+ set shared "--shared --no-undefined-version"
set script --version-script
if ![ld_compile "$CC -S $CFLAGS" $srcdir/$subdir/$source $tmpdir/$execname.s] {
unresolved "$test"
diff --git a/ld/testsuite/ld-elfvers/vers1.map b/ld/testsuite/ld-elfvers/vers1.map
index 8fc37bc..767915c 100644
--- a/ld/testsuite/ld-elfvers/vers1.map
+++ b/ld/testsuite/ld-elfvers/vers1.map
@@ -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 {
diff --git a/ld/testsuite/ld-elfvers/vers18.map b/ld/testsuite/ld-elfvers/vers18.map
index eac2b0e..8dcff39 100644
--- a/ld/testsuite/ld-elfvers/vers18.map
+++ b/ld/testsuite/ld-elfvers/vers18.map
@@ -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 {
diff --git a/ld/testsuite/ld-elfvers/vers8.map b/ld/testsuite/ld-elfvers/vers8.map
index 2635955..c24fb10 100644
--- a/ld/testsuite/ld-elfvers/vers8.map
+++ b/ld/testsuite/ld-elfvers/vers8.map
@@ -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 {