From ae5a359786fb21bf95678a4e9eebf2ff90114c7a Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Wed, 26 Nov 2008 01:04:17 +0000 Subject: [PATCH] include/ PR 7047 * bfdlink.h (struct bfd_elf_version_expr): Delete "symbol". Add "literal". bfd/ PR 7047 * configure.in: Bump version. * configure: Regenerate. * elflink.c (_bfd_elf_link_assign_sym_version): Continue matching against version nodes when a global match is a wildcard. Similarly continue matching on local wildcard matches, rather than only continuing for "*". Have any global wildcard match override a local wildcard match. Correct logic hiding unversioned symbol. (bfd_elf_size_dynamic_sections): Update for changes to struct bfd_elf_version_expr. ld/ PR 7047 * emultempl/ppc64elf.em (gld${EMULATION_NAME}_new_vers_pattern): Update for changes to struct bfd_elf_version_expr. * ldlang.c (lang_vers_match, version_expr_head_hash): Likewise. (version_expr_head_eq, lang_finalize_version_expr_head): Likewise. (lang_register_vers_node): Likewise. (lang_new_vers_pattern): Likewise. Ensure "literal" is set when no glob chars found in "pattern". (realsymbol): Correct backslash quote logic. * ld.texinfo (VERSION): Warn about global wildcards. --- bfd/ChangeLog | 13 +++++++ bfd/configure | 2 +- bfd/configure.in | 2 +- bfd/elflink.c | 72 +++++++++++++++++++++------------------ include/ChangeLog | 6 ++++ include/bfdlink.h | 4 +-- ld/ChangeLog | 13 +++++++ ld/emultempl/ppc64elf.em | 25 ++++---------- ld/ld.texinfo | 6 +++- ld/ldlang.c | 73 ++++++++++++++++++++++------------------ 10 files changed, 127 insertions(+), 89 deletions(-) diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 9d4a323dd7f..e0602882c9d 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,16 @@ +2008-11-26 Alan Modra + + PR 7047 + * configure.in: Bump version. + * configure: Regenerate. + * elflink.c (_bfd_elf_link_assign_sym_version): Continue matching + against version nodes when a global match is a wildcard. Similarly + continue matching on local wildcard matches, rather than only + continuing for "*". Have any global wildcard match override a + local wildcard match. Correct logic hiding unversioned symbol. + (bfd_elf_size_dynamic_sections): Update for changes to struct + bfd_elf_version_expr. + 2008-11-25 Joel Brobecker * configure.in: Deactivate large-file support on native x86-solaris diff --git a/bfd/configure b/bfd/configure index 042f5d1f74c..8ff1234a1a7 100755 --- a/bfd/configure +++ b/bfd/configure @@ -3033,7 +3033,7 @@ fi # Define the identity of the package. PACKAGE=bfd - VERSION=2.19.50 + VERSION=2.19.51 cat >>confdefs.h <<_ACEOF diff --git a/bfd/configure.in b/bfd/configure.in index 7297ee0e709..47ef10ccdfa 100644 --- a/bfd/configure.in +++ b/bfd/configure.in @@ -8,7 +8,7 @@ AC_CONFIG_SRCDIR([libbfd.c]) AC_CANONICAL_TARGET AC_ISC_POSIX -AM_INIT_AUTOMAKE(bfd, 2.19.50) +AM_INIT_AUTOMAKE(bfd, 2.19.51) dnl These must be called before LT_INIT, because it may want dnl to call AC_CHECK_PROG. diff --git a/bfd/elflink.c b/bfd/elflink.c index ce1dff7d012..43379c71a6e 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -2010,41 +2010,36 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data) if (h->verinfo.vertree == NULL && sinfo->verdefs != NULL) { struct bfd_elf_version_tree *t; - struct bfd_elf_version_tree *local_ver; + struct bfd_elf_version_tree *local_ver, *global_ver, *exist_ver; struct bfd_elf_version_expr *d; /* See if can find what version this symbol is in. If the symbol is supposed to be local, then don't actually register it. */ local_ver = NULL; + global_ver = NULL; + exist_ver = NULL; for (t = sinfo->verdefs; t != NULL; t = t->next) { if (t->globals.list != NULL) { - bfd_boolean matched; - - matched = FALSE; 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; + { + global_ver = t; + local_ver = NULL; + if (d->symver) + exist_ver = t; + d->script = 1; + /* If the match is a wildcard pattern, keep looking for + a more explicit, perhaps even local, match. */ + if (d->literal) 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.list != NULL) @@ -2054,11 +2049,14 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data) h->root.root.string)) != NULL) { local_ver = t; - /* If the match is "*", keep looking for a more - explicit, perhaps even global, match. - XXX: Shouldn't this be !d->wildcard instead? */ - if (d->pattern[0] != '*' || d->pattern[1] != '\0') - break; + /* If the match is a wildcard pattern, keep looking for + a more explicit, perhaps even global, match. */ + if (d->literal) + { + /* An exact match overrides a global wildcard. */ + global_ver = NULL; + break; + } } if (d != NULL) @@ -2066,14 +2064,22 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data) } } - if (local_ver != NULL) + if (global_ver != NULL) + { + h->verinfo.vertree = global_ver; + /* If we already have a versioned symbol that matches the + node for this symbol, then we don't want to create a + duplicate from the unversioned symbol. Instead hide the + unversioned symbol. */ + if (exist_ver == global_ver) + (*bed->elf_backend_hide_symbol) (info, h, TRUE); + } + else if (local_ver != NULL) { h->verinfo.vertree = local_ver; - if (h->dynindx != -1 - && ! info->export_dynamic) - { - (*bed->elf_backend_hide_symbol) (info, h, TRUE); - } + if (!info->export_dynamic + || exist_ver == local_ver) + (*bed->elf_backend_hide_symbol) (info, h, TRUE); } } @@ -5566,14 +5572,14 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, /* Make all global versions with definition. */ for (t = verdefs; t != NULL; t = t->next) for (d = t->globals.list; d != NULL; d = d->next) - if (!d->symver && d->symbol) + if (!d->symver && d->literal) { const char *verstr, *name; size_t namelen, verlen, newlen; char *newname, *p; struct elf_link_hash_entry *newh; - name = d->symbol; + name = d->pattern; namelen = strlen (name); verstr = t->name; verlen = strlen (verstr); @@ -5631,7 +5637,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, all_defined = TRUE; for (t = verdefs; t != NULL; t = t->next) for (d = t->globals.list; d != NULL; d = d->next) - if (!d->symver && !d->script) + if (d->literal && !d->symver && !d->script) { (*_bfd_error_handler) (_("%s: undefined version: %s"), diff --git a/include/ChangeLog b/include/ChangeLog index c6a6caef481..96c84746e20 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,9 @@ +2008-11-26 Alan Modra + + PR 7047 + * bfdlink.h (struct bfd_elf_version_expr): Delete "symbol". + Add "literal". + 2008-11-21 Sterling Augustine * xtensa-isa-internal.h (XTENSA_STATE_IS_SHARED_OR): New flag. diff --git a/include/bfdlink.h b/include/bfdlink.h index d27b5388d3b..51c5b15cd68 100644 --- a/include/bfdlink.h +++ b/include/bfdlink.h @@ -707,8 +707,8 @@ struct bfd_elf_version_expr struct bfd_elf_version_expr *next; /* Glob pattern. */ const char *pattern; - /* NULL for a glob pattern, otherwise a straight symbol. */ - const char *symbol; + /* Set if pattern is not a glob. */ + unsigned int literal : 1; /* Defined by ".symver". */ unsigned int symver : 1; /* Defined by version script. */ diff --git a/ld/ChangeLog b/ld/ChangeLog index 4e93eb233b5..e9cf92dd199 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,16 @@ +2008-11-26 Alan Modra + + PR 7047 + * emultempl/ppc64elf.em (gld${EMULATION_NAME}_new_vers_pattern): Update + for changes to struct bfd_elf_version_expr. + * ldlang.c (lang_vers_match, version_expr_head_hash): Likewise. + (version_expr_head_eq, lang_finalize_version_expr_head): Likewise. + (lang_register_vers_node): Likewise. + (lang_new_vers_pattern): Likewise. Ensure "literal" is set when + no glob chars found in "pattern". + (realsymbol): Correct backslash quote logic. + * ld.texinfo (VERSION): Warn about global wildcards. + 2008-11-24 Alan Modra * ldlang.c (lang_record_phdrs): Don't add orphans to PT_INTERP header. diff --git a/ld/emultempl/ppc64elf.em b/ld/emultempl/ppc64elf.em index 9a49fa5a341..eff8dff4a56 100644 --- a/ld/emultempl/ppc64elf.em +++ b/ld/emultempl/ppc64elf.em @@ -416,29 +416,18 @@ gld${EMULATION_NAME}_new_vers_pattern (struct bfd_elf_version_expr *entry) char *dot_pat; if (!dotsyms - || (entry->pattern != NULL - && (entry->pattern[0] == '*' || entry->pattern[0] == '.'))) + || entry->pattern[0] == '.' + || (!entry->literal && entry->pattern[0] == '*')) return entry; dot_entry = xmalloc (sizeof *dot_entry); *dot_entry = *entry; dot_entry->next = entry; - if (entry->pattern != NULL) - { - 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; - } - if (entry->symbol != NULL) - { - len = strlen (entry->symbol) + 2; - dot_pat = xmalloc (len); - dot_pat[0] = '.'; - memcpy (dot_pat + 1, entry->symbol, len - 1); - dot_entry->symbol = dot_pat; - } + 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; return dot_entry; } diff --git a/ld/ld.texinfo b/ld/ld.texinfo index 83c8ac4f0e7..4e8cf8a6f82 100644 --- a/ld/ld.texinfo +++ b/ld/ld.texinfo @@ -4561,7 +4561,11 @@ When the linker finds a symbol defined in a library which is not specifically bound to a version node, it will effectively bind it to an unspecified base version of the library. You can bind all otherwise unspecified symbols to a given version node by using @samp{global: *;} -somewhere in the version script. +somewhere in the version script. Note that it's slightly crazy to use +wildcards in a global spec except on the last version node. Global +wildcards elsewhere run the risk of accidentally adding symbols to the +set exported for an old version. That's wrong since older versions +ought to have a fixed set of symbols. The names of the version nodes have no specific meaning other than what they might suggest to the person reading them. The @samp{2.0} version diff --git a/ld/ldlang.c b/ld/ldlang.c index 6668c59e523..855e7951f4d 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -6989,7 +6989,7 @@ lang_vers_match (struct bfd_elf_version_expr_head *head, java_sym = sym; } - if (head->htab && (prev == NULL || prev->symbol)) + if (head->htab && (prev == NULL || prev->literal)) { struct bfd_elf_version_expr e; @@ -6998,9 +6998,9 @@ lang_vers_match (struct bfd_elf_version_expr_head *head, case 0: if (head->mask & BFD_ELF_VERSION_C_TYPE) { - e.symbol = sym; + e.pattern = sym; expr = htab_find (head->htab, &e); - while (expr && strcmp (expr->symbol, sym) == 0) + while (expr && strcmp (expr->pattern, sym) == 0) if (expr->mask == BFD_ELF_VERSION_C_TYPE) goto out_ret; else @@ -7010,9 +7010,9 @@ lang_vers_match (struct bfd_elf_version_expr_head *head, case BFD_ELF_VERSION_C_TYPE: if (head->mask & BFD_ELF_VERSION_CXX_TYPE) { - e.symbol = cxx_sym; + e.pattern = cxx_sym; expr = htab_find (head->htab, &e); - while (expr && strcmp (expr->symbol, cxx_sym) == 0) + while (expr && strcmp (expr->pattern, cxx_sym) == 0) if (expr->mask == BFD_ELF_VERSION_CXX_TYPE) goto out_ret; else @@ -7022,9 +7022,9 @@ lang_vers_match (struct bfd_elf_version_expr_head *head, case BFD_ELF_VERSION_CXX_TYPE: if (head->mask & BFD_ELF_VERSION_JAVA_TYPE) { - e.symbol = java_sym; + e.pattern = java_sym; expr = htab_find (head->htab, &e); - while (expr && strcmp (expr->symbol, java_sym) == 0) + while (expr && strcmp (expr->pattern, java_sym) == 0) if (expr->mask == BFD_ELF_VERSION_JAVA_TYPE) goto out_ret; else @@ -7037,7 +7037,7 @@ lang_vers_match (struct bfd_elf_version_expr_head *head, } /* Finally, try the wildcards. */ - if (prev == NULL || prev->symbol) + if (prev == NULL || prev->literal) expr = head->remaining; else expr = prev->next; @@ -7070,7 +7070,7 @@ lang_vers_match (struct bfd_elf_version_expr_head *head, } /* Return NULL if the PATTERN argument is a glob pattern, otherwise, - return a string pointing to the symbol name. */ + return a pointer to the symbol name with any backslash quotes removed. */ static const char * realsymbol (const char *pattern) @@ -7083,22 +7083,24 @@ realsymbol (const char *pattern) { /* It is a glob pattern only if there is no preceding backslash. */ - if (! backslash && (*p == '?' || *p == '*' || *p == '[')) - { - free (symbol); - return NULL; - } - if (backslash) { /* Remove the preceding backslash. */ *(s - 1) = *p; + backslash = FALSE; changed = TRUE; } else - *s++ = *p; + { + if (*p == '?' || *p == '*' || *p == '[') + { + free (symbol); + return NULL; + } - backslash = *p == '\\'; + *s++ = *p; + backslash = *p == '\\'; + } } if (changed) @@ -7127,10 +7129,15 @@ lang_new_vers_pattern (struct bfd_elf_version_expr *orig, ret = xmalloc (sizeof *ret); ret->next = orig; - ret->pattern = literal_p ? NULL : new; ret->symver = 0; ret->script = 0; - ret->symbol = literal_p ? new : realsymbol (new); + ret->literal = TRUE; + ret->pattern = literal_p ? new : realsymbol (new); + if (ret->pattern == NULL) + { + ret->pattern = new; + ret->literal = FALSE; + } if (lang == NULL || strcasecmp (lang, "C") == 0) ret->mask = BFD_ELF_VERSION_C_TYPE; @@ -7174,7 +7181,7 @@ version_expr_head_hash (const void *p) { const struct bfd_elf_version_expr *e = p; - return htab_hash_string (e->symbol); + return htab_hash_string (e->pattern); } static int @@ -7183,7 +7190,7 @@ 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->symbol, e2->symbol) == 0; + return strcmp (e1->pattern, e2->pattern) == 0; } static void @@ -7195,7 +7202,7 @@ lang_finalize_version_expr_head (struct bfd_elf_version_expr_head *head) for (e = head->list; e; e = e->next) { - if (e->symbol) + if (e->literal) count++; head->mask |= e->mask; } @@ -7209,7 +7216,7 @@ lang_finalize_version_expr_head (struct bfd_elf_version_expr_head *head) for (e = head->list; e; e = next) { next = e->next; - if (!e->symbol) + if (!e->literal) { *remaining_loc = e; remaining_loc = &e->next; @@ -7234,14 +7241,14 @@ lang_finalize_version_expr_head (struct bfd_elf_version_expr_head *head) last = e1; e1 = e1->next; } - while (e1 && strcmp (e1->symbol, e->symbol) == 0); + 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->symbol); */ + /* free (e->pattern); */ free (e); } else @@ -7305,18 +7312,18 @@ lang_register_vers_node (const char *name, { struct bfd_elf_version_expr *e2; - if (t->locals.htab && e1->symbol) + if (t->locals.htab && e1->literal) { e2 = htab_find (t->locals.htab, e1); - while (e2 && strcmp (e1->symbol, e2->symbol) == 0) + while (e2 && strcmp (e1->pattern, e2->pattern) == 0) { if (e1->mask == e2->mask) einfo (_("%X%P: duplicate expression `%s'" - " in version information\n"), e1->symbol); + " in version information\n"), e1->pattern); e2 = e2->next; } } - else if (!e1->symbol) + else if (!e1->literal) for (e2 = t->locals.remaining; e2 != NULL; e2 = e2->next) if (strcmp (e1->pattern, e2->pattern) == 0 && e1->mask == e2->mask) @@ -7331,19 +7338,19 @@ lang_register_vers_node (const char *name, { struct bfd_elf_version_expr *e2; - if (t->globals.htab && e1->symbol) + if (t->globals.htab && e1->literal) { e2 = htab_find (t->globals.htab, e1); - while (e2 && strcmp (e1->symbol, e2->symbol) == 0) + while (e2 && strcmp (e1->pattern, e2->pattern) == 0) { if (e1->mask == e2->mask) einfo (_("%X%P: duplicate expression `%s'" " in version information\n"), - e1->symbol); + e1->pattern); e2 = e2->next; } } - else if (!e1->symbol) + else if (!e1->literal) for (e2 = t->globals.remaining; e2 != NULL; e2 = e2->next) if (strcmp (e1->pattern, e2->pattern) == 0 && e1->mask == e2->mask) -- 2.30.2