diff options
author | H.J. Lu <hjl@lucon.org> | 2002-08-08 03:50:17 +0000 |
---|---|---|
committer | H.J. Lu <hjl@lucon.org> | 2002-08-08 03:50:17 +0000 |
commit | 0260c6a720a61a1c49af6a032bb013cb0226da48 (patch) | |
tree | f9ce257f3de39ac4174cc7ee19f7ad1da6372350 | |
parent | 26ed692b6bec128b2b56e871520535d412b1e499 (diff) | |
download | gdb-0260c6a720a61a1c49af6a032bb013cb0226da48.tar.gz |
Check symbols with undefine version.
-rw-r--r-- | bfd/ChangeLog | 8 | ||||
-rw-r--r-- | bfd/elflink.h | 133 | ||||
-rw-r--r-- | include/ChangeLog | 5 | ||||
-rw-r--r-- | include/bfdlink.h | 7 |
4 files changed, 112 insertions, 41 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 41dc63ea619..40a824e683e 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 59cc397a209..b1732e43c2f 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 ea51a95c307..39f18740bd0 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 c36564f6948..4998fe3dbf7 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. */ |