diff options
-rw-r--r-- | bfd/ChangeLog | 11 | ||||
-rw-r--r-- | bfd/elfxx-mips.c | 96 |
2 files changed, 89 insertions, 18 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 8eae490..d9797c7 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,14 @@ +2008-07-28 Daniel Jacobowitz <dan@codesourcery.com> + + * elfxx-mips.c (mips_elf_calculate_relocation): Avoid generating + relocations for undefined weak symbols with non-default visibility. + (_bfd_mips_elf_check_relocs): Use possibly_dynamic_relocs for + global symbols in shared libraries. + (allocate_dynrelocs): New function. + (_bfd_mips_elf_adjust_dynamic_symbol): Do not handle + possibly_dynamic_relocs here. + (_bfd_mips_elf_size_dynamic_sections): Call allocate_dynrelocs. + 2008-07-28 Alexandre Oliva <aoliva@redhat.com> * elf32-i386.c (struct elf_i386_link_hash_table): Added field diff --git a/bfd/elfxx-mips.c b/bfd/elfxx-mips.c index a67663d..827915c 100644 --- a/bfd/elfxx-mips.c +++ b/bfd/elfxx-mips.c @@ -4509,6 +4509,9 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd, && h->root.def_dynamic && !h->root.def_regular)) && r_symndx != 0 + && (h == NULL + || h->root.root.type != bfd_link_hash_undefweak + || ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT) && (input_section->flags & SEC_ALLOC) != 0) { /* If we're creating a shared library, or this relocation is @@ -7008,7 +7011,7 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, if (sreloc == NULL) return FALSE; } - if (info->shared) + if (info->shared && h == NULL) { /* When creating a shared object, we must copy these reloc types into the output file as R_MIPS_REL32 @@ -7023,8 +7026,17 @@ _bfd_mips_elf_check_relocs (bfd *abfd, struct bfd_link_info *info, { struct mips_elf_link_hash_entry *hmips; - /* We only need to copy this reloc if the symbol is - defined in a dynamic object. */ + /* For a shared object, we must copy this relocation + unless the symbol turns out to be undefined and + weak with non-default visibility, in which case + it will be left as zero. + + We could elide R_MIPS_REL32 for locally binding symbols + in shared libraries, but do not yet do so. + + For an executable, we only need to copy this + reloc if the symbol is defined in a dynamic + object. */ hmips = (struct mips_elf_link_hash_entry *) h; ++hmips->possibly_dynamic_relocs; if (MIPS_ELF_READONLY_SECTION (sec)) @@ -7289,6 +7301,66 @@ _bfd_mips_relax_section (bfd *abfd, asection *sec, return FALSE; } +/* Allocate space for global sym dynamic relocs. */ + +static bfd_boolean +allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf) +{ + struct bfd_link_info *info = inf; + bfd *dynobj; + struct mips_elf_link_hash_entry *hmips; + struct mips_elf_link_hash_table *htab; + + htab = mips_elf_hash_table (info); + dynobj = elf_hash_table (info)->dynobj; + hmips = (struct mips_elf_link_hash_entry *) h; + + /* VxWorks executables are handled elsewhere; we only need to + allocate relocations in shared objects. */ + if (htab->is_vxworks && !info->shared) + return TRUE; + + /* If this symbol is defined in a dynamic object, or we are creating + a shared library, we will need to copy any R_MIPS_32 or + R_MIPS_REL32 relocs against it into the output file. */ + if (! info->relocatable + && hmips->possibly_dynamic_relocs != 0 + && (h->root.type == bfd_link_hash_defweak + || !h->def_regular + || info->shared)) + { + bfd_boolean do_copy = TRUE; + + if (h->root.type == bfd_link_hash_undefweak) + { + /* Do not copy relocations for undefined weak symbols with + non-default visibility. */ + if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT) + do_copy = FALSE; + + /* Make sure undefined weak symbols are output as a dynamic + symbol in PIEs. */ + else if (h->dynindx == -1 && !h->forced_local) + { + if (! bfd_elf_link_record_dynamic_symbol (info, h)) + return FALSE; + } + } + + if (do_copy) + { + mips_elf_allocate_dynamic_relocations + (dynobj, info, hmips->possibly_dynamic_relocs); + if (hmips->readonly_reloc) + /* We tell the dynamic linker that there are relocations + against the text segment. */ + info->flags |= DF_TEXTREL; + } + } + + return TRUE; +} + /* Adjust a symbol defined by a dynamic object and referenced by a regular object. The current definition is in some section of the dynamic object, but we're not including those sections. We have to @@ -7315,22 +7387,7 @@ _bfd_mips_elf_adjust_dynamic_symbol (struct bfd_link_info *info, && h->ref_regular && !h->def_regular))); - /* If this symbol is defined in a dynamic object, we need to copy - any R_MIPS_32 or R_MIPS_REL32 relocs against it into the output - file. */ hmips = (struct mips_elf_link_hash_entry *) h; - if (! info->relocatable - && hmips->possibly_dynamic_relocs != 0 - && (h->root.type == bfd_link_hash_defweak - || !h->def_regular)) - { - mips_elf_allocate_dynamic_relocations - (dynobj, info, hmips->possibly_dynamic_relocs); - if (hmips->readonly_reloc) - /* We tell the dynamic linker that there are relocations - against the text segment. */ - info->flags |= DF_TEXTREL; - } /* For a function, create a stub, if allowed. */ if (! hmips->no_fn_stub @@ -7724,6 +7781,9 @@ _bfd_mips_elf_size_dynamic_sections (bfd *output_bfd, } } + /* Allocate space for global sym dynamic relocs. */ + elf_link_hash_traverse (&htab->root, allocate_dynrelocs, (PTR) info); + /* The check_relocs and adjust_dynamic_symbol entry points have determined the sizes of the various dynamic sections. Allocate memory for them. */ |