From fd91d41947667d30f47b06c45cc57d4b4fcefade Mon Sep 17 00:00:00 2001 From: "H.J. Lu" Date: Fri, 16 Sep 2011 01:15:20 +0000 Subject: [PATCH] Check if a symbol is hidden by linker script. bfd/ 2011-09-15 H.J. Lu PR ld/12975 * bfd-in.h (bfd_elf_size_dynamic_sections): Remove pointer to struct bfd_elf_version_tree. * elflink.c (elf_info_failed): Remove verdefs. (_bfd_elf_export_symbol): Updated. _bfd_elf_link_assign_sym_version): Likewise. (bfd_elf_size_dynamic_sections): Remove pointer to struct bfd_elf_version_tree. Updated. (bfd_elf_gc_mark_dynamic_ref_symbol): Check if a symbol is hidden by linker script. * linker.c (bfd_hide_sym_by_version): New. * bfd-in2.h: Regenerated. include/ 2011-09-15 H.J. Lu PR ld/12975 * bfdlink.h (bfd_link_info): Add version_info. ld/ 2011-09-15 H.J. Lu PR ld/12975 * ldlang.c (lang_elf_version_info): Removed. (lang_register_vers_node): Replace lang_elf_version_info with link_info.version_info. (lang_add_vers_depend): Likewise. * pe-dll.c (process_def_file_and_drectve): Likewise. * emultempl/solaris2.em (elf_solaris2_before_allocation): Likewise. * ldlang.h (lang_elf_version_info): Removed. * plugin.c (is_visible_from_outside): Check if symbol is hidden by version script. * emultempl/elf32.em (gld${EMULATION_NAME}_before_allocation): Remove lang_elf_version_info. ld/testsuite/ 2011-09-15 H.J. Lu PR ld/12975 * ld-elf/pr12975.d: New. * ld-elf/pr12975.s: Likewise. * ld-elf/pr12975.t: Likewise. --- bfd/ChangeLog | 18 +++++++++++++ bfd/bfd-in.h | 3 +-- bfd/bfd-in2.h | 6 +++-- bfd/elflink.c | 51 +++++++++++++++++------------------ bfd/linker.c | 23 ++++++++++++++++ include/ChangeLog | 5 ++++ include/bfdlink.h | 4 +++ ld/ChangeLog | 18 +++++++++++++ ld/emultempl/elf32.em | 2 +- ld/emultempl/solaris2.em | 3 ++- ld/ldlang.c | 18 +++++-------- ld/ldlang.h | 2 -- ld/pe-dll.c | 11 +++----- ld/plugin.c | 4 +++ ld/testsuite/ChangeLog | 7 +++++ ld/testsuite/ld-elf/pr12975.d | 10 +++++++ ld/testsuite/ld-elf/pr12975.s | 10 +++++++ ld/testsuite/ld-elf/pr12975.t | 6 +++++ 18 files changed, 148 insertions(+), 53 deletions(-) create mode 100644 ld/testsuite/ld-elf/pr12975.d create mode 100644 ld/testsuite/ld-elf/pr12975.s create mode 100644 ld/testsuite/ld-elf/pr12975.t diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 9d63ff6f80c..b063de9ac93 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,21 @@ +2011-09-15 H.J. Lu + + PR ld/12975 + * bfd-in.h (bfd_elf_size_dynamic_sections): Remove pointer + to struct bfd_elf_version_tree. + + * elflink.c (elf_info_failed): Remove verdefs. + (_bfd_elf_export_symbol): Updated. + _bfd_elf_link_assign_sym_version): Likewise. + (bfd_elf_size_dynamic_sections): Remove pointer to struct + bfd_elf_version_tree. Updated. + (bfd_elf_gc_mark_dynamic_ref_symbol): Check if a symbol is hidden + by linker script. + + * linker.c (bfd_hide_sym_by_version): New. + + * bfd-in2.h: Regenerated. + 2011-09-12 H.J. Lu PR ld/13178 diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h index 718d72e51f3..a477b49e393 100644 --- a/bfd/bfd-in.h +++ b/bfd/bfd-in.h @@ -645,8 +645,7 @@ extern bfd_boolean bfd_elf_get_bfd_needed_list (bfd *, struct bfd_link_needed_list **); extern bfd_boolean bfd_elf_size_dynamic_sections (bfd *, const char *, const char *, const char *, const char *, const char *, - const char * const *, struct bfd_link_info *, struct bfd_section **, - struct bfd_elf_version_tree *); + const char * const *, struct bfd_link_info *, struct bfd_section **); extern bfd_boolean bfd_elf_size_dynsym_hash_dynstr (bfd *, struct bfd_link_info *); extern void bfd_elf_set_dt_needed_name diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 7cf3b7e60bc..22fcdf65bd8 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -652,8 +652,7 @@ extern bfd_boolean bfd_elf_get_bfd_needed_list (bfd *, struct bfd_link_needed_list **); extern bfd_boolean bfd_elf_size_dynamic_sections (bfd *, const char *, const char *, const char *, const char *, const char *, - const char * const *, struct bfd_link_info *, struct bfd_section **, - struct bfd_elf_version_tree *); + const char * const *, struct bfd_link_info *, struct bfd_section **); extern bfd_boolean bfd_elf_size_dynsym_hash_dynstr (bfd *, struct bfd_link_info *); extern void bfd_elf_set_dt_needed_name @@ -6199,6 +6198,9 @@ struct bfd_elf_version_tree * bfd_find_version_for_sym (struct bfd_elf_version_tree *verdefs, const char *sym_name, bfd_boolean *hide); +bfd_boolean bfd_hide_sym_by_version + (struct bfd_elf_version_tree *verdefs, const char *sym_name); + /* Extracted from simple.c. */ bfd_byte *bfd_simple_get_relocated_section_contents (bfd *abfd, asection *sec, bfd_byte *outbuf, asymbol **symbol_table); diff --git a/bfd/elflink.c b/bfd/elflink.c index 528f705e8a8..25601042401 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -36,7 +36,6 @@ struct elf_info_failed { struct bfd_link_info *info; - struct bfd_elf_version_tree *verdefs; bfd_boolean failed; }; @@ -1820,20 +1819,14 @@ _bfd_elf_export_symbol (struct elf_link_hash_entry *h, void *data) return TRUE; if (h->dynindx == -1 - && (h->def_regular - || h->ref_regular)) + && (h->def_regular || h->ref_regular) + && ! bfd_hide_sym_by_version (eif->info->version_info, + h->root.root.string)) { - bfd_boolean hide; - - if (eif->verdefs == NULL - || (bfd_find_version_for_sym (eif->verdefs, h->root.root.string, &hide) - && !hide)) + if (! bfd_elf_link_record_dynamic_symbol (eif->info, h)) { - if (! bfd_elf_link_record_dynamic_symbol (eif->info, h)) - { - eif->failed = TRUE; - return FALSE; - } + eif->failed = TRUE; + return FALSE; } } @@ -1981,7 +1974,7 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data) } /* Look for the version. If we find it, it is no longer weak. */ - for (t = sinfo->verdefs; t != NULL; t = t->next) + for (t = sinfo->info->version_info; t != NULL; t = t->next) { if (strcmp (t->name, p) == 0) { @@ -2050,9 +2043,12 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data) version_index = 1; /* Don't count anonymous version tag. */ - if (sinfo->verdefs != NULL && sinfo->verdefs->vernum == 0) + if (sinfo->info->version_info != NULL + && sinfo->info->version_info->vernum == 0) version_index = 0; - for (pp = &sinfo->verdefs; *pp != NULL; pp = &(*pp)->next) + for (pp = &sinfo->info->version_info; + *pp != NULL; + pp = &(*pp)->next) ++version_index; t->vernum = version_index; @@ -2078,12 +2074,13 @@ _bfd_elf_link_assign_sym_version (struct elf_link_hash_entry *h, void *data) /* If we don't have a version for this symbol, see if we can find something. */ - if (h->verinfo.vertree == NULL && sinfo->verdefs != NULL) + if (h->verinfo.vertree == NULL && sinfo->info->version_info != NULL) { bfd_boolean hide; - h->verinfo.vertree = bfd_find_version_for_sym (sinfo->verdefs, - h->root.root.string, &hide); + h->verinfo.vertree + = bfd_find_version_for_sym (sinfo->info->version_info, + h->root.root.string, &hide); if (h->verinfo.vertree != NULL && hide) (*bed->elf_backend_hide_symbol) (info, h, TRUE); } @@ -5493,8 +5490,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, const char *depaudit, const char * const *auxiliary_filters, struct bfd_link_info *info, - asection **sinterpptr, - struct bfd_elf_version_tree *verdefs) + asection **sinterpptr) { bfd_size_type soname_indx; bfd *dynobj; @@ -5671,7 +5667,6 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, } eif.info = info; - eif.verdefs = verdefs; eif.failed = FALSE; /* If we are supposed to export all symbols into the dynamic symbol @@ -5687,7 +5682,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, } /* Make all global versions with definition. */ - for (t = verdefs; t != NULL; t = t->next) + for (t = info->version_info; t != NULL; t = t->next) for (d = t->globals.list; d != NULL; d = d->next) if (!d->symver && d->literal) { @@ -5740,7 +5735,6 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, /* Attach all the symbols to their version information. */ asvinfo.info = info; - asvinfo.verdefs = verdefs; asvinfo.failed = FALSE; elf_link_hash_traverse (elf_hash_table (info), @@ -5753,7 +5747,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, { /* Check if all global versions have a definition. */ all_defined = TRUE; - for (t = verdefs; t != NULL; t = t->next) + for (t = info->version_info; t != NULL; t = t->next) for (d = t->globals.list; d != NULL; d = d->next) if (d->literal && !d->symver && !d->script) { @@ -5886,6 +5880,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, if (elf_hash_table (info)->dynamic_sections_created) { unsigned long section_sym_count; + struct bfd_elf_version_tree *verdefs; asection *s; /* Set up the version definition section. */ @@ -5894,7 +5889,7 @@ bfd_elf_size_dynamic_sections (bfd *output_bfd, /* We may have created additional version definitions if we are just linking a regular application. */ - verdefs = asvinfo.verdefs; + verdefs = info->version_info; /* Skip anonymous version tag. */ if (verdefs != NULL && verdefs->vernum == 0) @@ -11913,7 +11908,9 @@ bfd_elf_gc_mark_dynamic_ref_symbol (struct elf_link_hash_entry *h, void *inf) || (!info->executable && h->def_regular && ELF_ST_VISIBILITY (h->other) != STV_INTERNAL - && ELF_ST_VISIBILITY (h->other) != STV_HIDDEN))) + && ELF_ST_VISIBILITY (h->other) != STV_HIDDEN + && !bfd_hide_sym_by_version (info->version_info, + h->root.root.string)))) h->root.u.def.section->flags |= SEC_KEEP; return TRUE; diff --git a/bfd/linker.c b/bfd/linker.c index e44386232d3..7a01e114a21 100644 --- a/bfd/linker.c +++ b/bfd/linker.c @@ -3380,3 +3380,26 @@ bfd_find_version_for_sym (struct bfd_elf_version_tree *verdefs, return NULL; } + +/* +FUNCTION + bfd_hide_sym_by_version + +SYNOPSIS + bfd_boolean bfd_hide_sym_by_version + (struct bfd_elf_version_tree *verdefs, const char *sym_name); + +DESCRIPTION + Search an elf version script tree for symbol versioning + info for a given symbol. Return TRUE if the symbol is hidden. + +*/ + +bfd_boolean +bfd_hide_sym_by_version (struct bfd_elf_version_tree *verdefs, + const char *sym_name) +{ + bfd_boolean hidden = FALSE; + bfd_find_version_for_sym (verdefs, sym_name, &hidden); + return hidden; +} diff --git a/include/ChangeLog b/include/ChangeLog index 53984e1c01a..1a4680ed238 100644 --- a/include/ChangeLog +++ b/include/ChangeLog @@ -1,3 +1,8 @@ +2011-09-15 H.J. Lu + + PR ld/12975 + * bfdlink.h (bfd_link_info): Add version_info. + 2011-07-25 Rainer Orth * xregex.h (regoff_t): Define. diff --git a/include/bfdlink.h b/include/bfdlink.h index 71b1e253c69..c9e127c5c99 100644 --- a/include/bfdlink.h +++ b/include/bfdlink.h @@ -245,6 +245,7 @@ struct flag_info }; struct bfd_elf_dynamic_list; +struct bfd_elf_version_tree; /* This structure holds all the information needed to communicate between BFD and the linker when doing a link. */ @@ -496,6 +497,9 @@ struct bfd_link_info /* List of symbols should be dynamic. */ struct bfd_elf_dynamic_list *dynamic_list; + + /* The version information. */ + struct bfd_elf_version_tree *version_info; }; /* This structures holds a set of callback functions. These are called diff --git a/ld/ChangeLog b/ld/ChangeLog index 99ef7b167b1..cafca0ec988 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,3 +1,21 @@ +2011-09-15 H.J. Lu + + PR ld/12975 + * ldlang.c (lang_elf_version_info): Removed. + (lang_register_vers_node): Replace lang_elf_version_info with + link_info.version_info. + (lang_add_vers_depend): Likewise. + * pe-dll.c (process_def_file_and_drectve): Likewise. + * emultempl/solaris2.em (elf_solaris2_before_allocation): Likewise. + + * ldlang.h (lang_elf_version_info): Removed. + + * plugin.c (is_visible_from_outside): Check if symbol is hidden + by version script. + + * emultempl/elf32.em (gld${EMULATION_NAME}_before_allocation): + Remove lang_elf_version_info. + 2011-09-15 Dmitry Gorbachev PR ld/13183 diff --git a/ld/emultempl/elf32.em b/ld/emultempl/elf32.em index 9bc363f3331..7c8e55bb9aa 100644 --- a/ld/emultempl/elf32.em +++ b/ld/emultempl/elf32.em @@ -1535,7 +1535,7 @@ gld${EMULATION_NAME}_before_allocation (void) (link_info.output_bfd, command_line.soname, rpath, command_line.filter_shlib, audit, depaudit, (const char * const *) command_line.auxiliary_filters, - &link_info, &sinterp, lang_elf_version_info))) + &link_info, &sinterp))) einfo ("%P%F: failed to set dynamic section sizes: %E\n"); ${ELF_INTERPRETER_SET_DEFAULT} diff --git a/ld/emultempl/solaris2.em b/ld/emultempl/solaris2.em index 0b773751ef3..2c24467fd39 100644 --- a/ld/emultempl/solaris2.em +++ b/ld/emultempl/solaris2.em @@ -76,7 +76,8 @@ elf_solaris2_before_allocation (void) /* Only do this if emitting a shared object and versioning is in place. */ if (link_info.shared - && (lang_elf_version_info != NULL || link_info.create_default_symver)) + && (link_info.version_info != NULL + || link_info.create_default_symver)) { struct bfd_elf_version_expr *globals = NULL, *locals = NULL; struct bfd_elf_version_tree *basever; diff --git a/ld/ldlang.c b/ld/ldlang.c index 5b548d0b4a9..7251a86b88c 100644 --- a/ld/ldlang.c +++ b/ld/ldlang.c @@ -7458,10 +7458,6 @@ lang_leave_overlay (etree_type *lma_expr, /* Version handling. This is only useful for ELF. */ -/* This global variable holds the version tree that we build. */ - -struct bfd_elf_version_tree *lang_elf_version_info; - /* If PREV is NULL, return first version pattern matching particular symbol. If PREV is non-NULL, return first version pattern matching particular symbol after PREV (previously returned by lang_vers_match). */ @@ -7803,8 +7799,8 @@ lang_register_vers_node (const char *name, if (name == NULL) name = ""; - if ((name[0] == '\0' && lang_elf_version_info != NULL) - || (lang_elf_version_info && lang_elf_version_info->name[0] == '\0')) + if (link_info.version_info != NULL + && (name[0] == '\0' || link_info.version_info->name[0] == '\0')) { einfo (_("%X%P: anonymous version tag cannot be combined" " with other version tags\n")); @@ -7813,7 +7809,7 @@ lang_register_vers_node (const char *name, } /* Make sure this node has a unique name. */ - for (t = lang_elf_version_info; t != NULL; t = t->next) + for (t = link_info.version_info; t != NULL; t = t->next) if (strcmp (t->name, name) == 0) einfo (_("%X%P: duplicate version tag `%s'\n"), name); @@ -7825,7 +7821,7 @@ lang_register_vers_node (const char *name, for (e1 = version->globals.list; e1 != NULL; e1 = e1->next) { - for (t = lang_elf_version_info; t != NULL; t = t->next) + for (t = link_info.version_info; t != NULL; t = t->next) { struct bfd_elf_version_expr *e2; @@ -7852,7 +7848,7 @@ lang_register_vers_node (const char *name, for (e1 = version->locals.list; e1 != NULL; e1 = e1->next) { - for (t = lang_elf_version_info; t != NULL; t = t->next) + for (t = link_info.version_info; t != NULL; t = t->next) { struct bfd_elf_version_expr *e2; @@ -7888,7 +7884,7 @@ lang_register_vers_node (const char *name, else version->vernum = 0; - for (pp = &lang_elf_version_info; *pp != NULL; pp = &(*pp)->next) + for (pp = &link_info.version_info; *pp != NULL; pp = &(*pp)->next) ; *pp = version; } @@ -7904,7 +7900,7 @@ lang_add_vers_depend (struct bfd_elf_version_deps *list, const char *name) ret = (struct bfd_elf_version_deps *) xmalloc (sizeof *ret); ret->next = list; - for (t = lang_elf_version_info; t != NULL; t = t->next) + for (t = link_info.version_info; t != NULL; t = t->next) { if (strcmp (t->name, name) == 0) { diff --git a/ld/ldlang.h b/ld/ldlang.h index a6d22ce3045..533fe744386 100644 --- a/ld/ldlang.h +++ b/ld/ldlang.h @@ -628,8 +628,6 @@ extern void lang_leave_overlay (etree_type *, int, fill_type *, const char *, lang_output_section_phdr_list *, const char *); -extern struct bfd_elf_version_tree *lang_elf_version_info; - extern struct bfd_elf_version_expr *lang_new_vers_pattern (struct bfd_elf_version_expr *, const char *, const char *, bfd_boolean); extern struct bfd_elf_version_tree *lang_new_vers_node diff --git a/ld/pe-dll.c b/ld/pe-dll.c index 682ce46e65e..7848063f211 100644 --- a/ld/pe-dll.c +++ b/ld/pe-dll.c @@ -718,13 +718,10 @@ process_def_file_and_drectve (bfd *abfd ATTRIBUTE_UNUSED, struct bfd_link_info * bfd_boolean would_export = symbols[j]->section != &bfd_und_section && ((symbols[j]->flags & BSF_GLOBAL) || (symbols[j]->flags == 0)); - if (lang_elf_version_info && would_export) - { - bfd_boolean hide = 0; - (void) bfd_find_version_for_sym (lang_elf_version_info, - symbols[j]->name, &hide); - would_export = !hide; - } + if (link_info.version_info && would_export) + would_export + = !bfd_hide_sym_by_version (link_info.version_info, + symbols[j]->name); if (would_export) { const char *sn = symbols[j]->name; diff --git a/ld/plugin.c b/ld/plugin.c index 0be7fa3a6b5..b1721117286 100644 --- a/ld/plugin.c +++ b/ld/plugin.c @@ -454,6 +454,10 @@ is_visible_from_outside (struct ld_plugin_symbol *lsym, asection *section, return TRUE; if (link_info.export_dynamic || link_info.shared) { + /* Check if symbol is hidden by version script. */ + if (bfd_hide_sym_by_version (link_info.version_info, + blhe->root.string)) + return FALSE; /* Only ELF symbols really have visibility. */ if (bfd_get_flavour (link_info.output_bfd) == bfd_target_elf_flavour) { diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 3c00fe4a57c..7a90b261e83 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2011-09-15 H.J. Lu + + PR ld/12975 + * ld-elf/pr12975.d: New. + * ld-elf/pr12975.s: Likewise. + * ld-elf/pr12975.t: Likewise. + 2011-09-12 H.J. Lu PR ld/13178 diff --git a/ld/testsuite/ld-elf/pr12975.d b/ld/testsuite/ld-elf/pr12975.d new file mode 100644 index 00000000000..549e8d5eb1e --- /dev/null +++ b/ld/testsuite/ld-elf/pr12975.d @@ -0,0 +1,10 @@ +#ld: --gc-sections -shared -version-script pr12975.t +#readelf: -s --wide +#notarget: arc-*-* d30v-*-* dlx-*-* i960-*-* or32-*-* pj*-*-* +#notarget: hppa64-*-* i370-*-* i860-*-* ia64-*-* mep-*-* mn10200-*-* +# generic linker targets don't support --gc-sections, nor do a bunch of others + +#failif +#... + +[0-9]+: +[0-9a-f]+ +[0-9]+ +FUNC +LOCAL +DEFAULT +[1-9]+ bar +#... diff --git a/ld/testsuite/ld-elf/pr12975.s b/ld/testsuite/ld-elf/pr12975.s new file mode 100644 index 00000000000..74291212ff5 --- /dev/null +++ b/ld/testsuite/ld-elf/pr12975.s @@ -0,0 +1,10 @@ + .section .text.foo,"ax",%progbits + .globl foo + .type foo, %function +foo: + .byte 0 + .section .text.bar,"ax",%progbits + .type bar, %function + .globl bar +bar: + .byte 0 diff --git a/ld/testsuite/ld-elf/pr12975.t b/ld/testsuite/ld-elf/pr12975.t new file mode 100644 index 00000000000..902c1f70bf9 --- /dev/null +++ b/ld/testsuite/ld-elf/pr12975.t @@ -0,0 +1,6 @@ +{ +global: + foo; +local: + *; +}; -- 2.30.2