diff --git a/bfd/ChangeLog b/bfd/ChangeLog index a896f01d48..79fb7b2ef4 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,11 @@ +2009-01-02 H.J. Lu + + PR ld/9679 + * elflink.c (elf_merge_st_other): New. + (_bfd_elf_merge_symbol): Use it on skipped weak definitions and + hide them if needed. + (elf_link_add_object_symbols): Updated. + 2009-01-02 H.J. Lu PR ld/9676 diff --git a/bfd/elflink.c b/bfd/elflink.c index 2b246bd9ad..95d12199e3 100644 --- a/bfd/elflink.c +++ b/bfd/elflink.c @@ -822,6 +822,54 @@ _bfd_elf_link_renumber_dynsyms (bfd *output_bfd, return dynsymcount; } +/* Merge st_other field. */ + +static void +elf_merge_st_other (bfd *abfd, struct elf_link_hash_entry *h, + Elf_Internal_Sym *isym, bfd_boolean definition, + bfd_boolean dynamic) +{ + const struct elf_backend_data *bed = get_elf_backend_data (abfd); + + /* If st_other has a processor-specific meaning, specific + code might be needed here. We never merge the visibility + attribute with the one from a dynamic object. */ + if (bed->elf_backend_merge_symbol_attribute) + (*bed->elf_backend_merge_symbol_attribute) (h, isym, definition, + dynamic); + + /* If this symbol has default visibility and the user has requested + we not re-export it, then mark it as hidden. */ + if (definition + && !dynamic + && (abfd->no_export + || (abfd->my_archive && abfd->my_archive->no_export)) + && ELF_ST_VISIBILITY (isym->st_other) != STV_INTERNAL) + isym->st_other = (STV_HIDDEN + | (isym->st_other & ~ELF_ST_VISIBILITY (-1))); + + if (!dynamic && ELF_ST_VISIBILITY (isym->st_other) != 0) + { + unsigned char hvis, symvis, other, nvis; + + /* Only merge the visibility. Leave the remainder of the + st_other field to elf_backend_merge_symbol_attribute. */ + other = h->other & ~ELF_ST_VISIBILITY (-1); + + /* Combine visibilities, using the most constraining one. */ + hvis = ELF_ST_VISIBILITY (h->other); + symvis = ELF_ST_VISIBILITY (isym->st_other); + if (! hvis) + nvis = symvis; + else if (! symvis) + nvis = hvis; + else + nvis = hvis < symvis ? hvis : symvis; + + h->other = other | nvis; + } +} + /* This function is called when we want to define a new symbol. It handles the various cases which arise when we find a definition in a dynamic object, or when there is already a definition in a @@ -1347,7 +1395,22 @@ _bfd_elf_merge_symbol (bfd *abfd, /* Skip weak definitions of symbols that are already defined. */ if (newdef && olddef && newweak) - *skip = TRUE; + { + *skip = TRUE; + + /* Merge st_other. If the symbol already has a dynamic index, + but visibility says it should not be visible, turn it into a + local symbol. */ + elf_merge_st_other (abfd, h, sym, newdef, newdyn); + if (h->dynindx != -1) + switch (ELF_ST_VISIBILITY (h->other)) + { + case STV_INTERNAL: + case STV_HIDDEN: + (*bed->elf_backend_hide_symbol) (info, h, TRUE); + break; + } + } /* If the old symbol is from a dynamic object, and the new symbol is a definition which is not from a dynamic object, then the new @@ -4244,42 +4307,8 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info) h->type = ELF_ST_TYPE (isym->st_info); } - /* If st_other has a processor-specific meaning, specific - code might be needed here. We never merge the visibility - attribute with the one from a dynamic object. */ - if (bed->elf_backend_merge_symbol_attribute) - (*bed->elf_backend_merge_symbol_attribute) (h, isym, definition, - dynamic); - - /* If this symbol has default visibility and the user has requested - we not re-export it, then mark it as hidden. */ - if (definition && !dynamic - && (abfd->no_export - || (abfd->my_archive && abfd->my_archive->no_export)) - && ELF_ST_VISIBILITY (isym->st_other) != STV_INTERNAL) - isym->st_other = (STV_HIDDEN - | (isym->st_other & ~ELF_ST_VISIBILITY (-1))); - - if (ELF_ST_VISIBILITY (isym->st_other) != 0 && !dynamic) - { - unsigned char hvis, symvis, other, nvis; - - /* Only merge the visibility. Leave the remainder of the - st_other field to elf_backend_merge_symbol_attribute. */ - other = h->other & ~ELF_ST_VISIBILITY (-1); - - /* Combine visibilities, using the most constraining one. */ - hvis = ELF_ST_VISIBILITY (h->other); - symvis = ELF_ST_VISIBILITY (isym->st_other); - if (! hvis) - nvis = symvis; - else if (! symvis) - nvis = hvis; - else - nvis = hvis < symvis ? hvis : symvis; - - h->other = other | nvis; - } + /* Merge st_other field. */ + elf_merge_st_other (abfd, h, isym, definition, dynamic); /* Set a flag in the hash table entry indicating the type of reference or definition we just found. Keep a count of diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 7936368711..30be1ed27c 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,12 @@ +2009-01-02 H.J. Lu + + PR ld/9679 + * ld-elf/pr9679-1.c: New. + * ld-elf/pr9679-2.c: Likewise. + * ld-elf/pr9679.rd: Likewise. + + * ld-elf/shared.exp (build_tests): Add test for libpr9679.so. + 2009-01-02 H.J. Lu PR ld/9676 diff --git a/ld/testsuite/ld-elf/pr9679-1.c b/ld/testsuite/ld-elf/pr9679-1.c new file mode 100644 index 0000000000..cf7abbbf4e --- /dev/null +++ b/ld/testsuite/ld-elf/pr9679-1.c @@ -0,0 +1,5 @@ +int +foo (void) +{ + return 1; +} diff --git a/ld/testsuite/ld-elf/pr9679-2.c b/ld/testsuite/ld-elf/pr9679-2.c new file mode 100644 index 0000000000..e125a6b746 --- /dev/null +++ b/ld/testsuite/ld-elf/pr9679-2.c @@ -0,0 +1,13 @@ +extern int foo (void) __attribute__((weak,__visibility__ ("hidden"))); + +int +foo (void) +{ + return 1; +} + +int +bar (void) +{ + return foo (); +} diff --git a/ld/testsuite/ld-elf/pr9679.rd b/ld/testsuite/ld-elf/pr9679.rd new file mode 100644 index 0000000000..0585b1cb00 --- /dev/null +++ b/ld/testsuite/ld-elf/pr9679.rd @@ -0,0 +1,5 @@ +Symbol table '\.dynsym' contains [0-9]+ entries: + +Num: +Value +Size Type +Bind +Vis +Ndx Name +#... + +[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +FUNC +LOCAL +HIDDEN +[0-9]+ +foo +#... diff --git a/ld/testsuite/ld-elf/shared.exp b/ld/testsuite/ld-elf/shared.exp index ff8bc8ffbb..4f45bdd656 100644 --- a/ld/testsuite/ld-elf/shared.exp +++ b/ld/testsuite/ld-elf/shared.exp @@ -145,6 +145,9 @@ set build_tests { "-shared tmpdir/pr9676-4.o -Ltmpdir -lpr9676-3 -Wl,--start-group -lpr9676-1 -lpr9676-2 -Wl,--end-group" "-fPIC" {dummy.c} {{readelf {-s} pr9676.rd}} "libpr9676-4a.so"} + {"Build libpr9679.so" + "-shared" "-fPIC -O0" + {pr9679-1.c pr9679-2.c} {{readelf {-s} pr9679.rd}} "libpr9679.so"} } set run_tests {