* 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.
This commit is contained in:
Daniel Jacobowitz 2008-07-28 22:14:53 +00:00
parent bae98fe013
commit 9a59ad6b6f
2 changed files with 89 additions and 18 deletions

View file

@ -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> 2008-07-28 Alexandre Oliva <aoliva@redhat.com>
* elf32-i386.c (struct elf_i386_link_hash_table): Added field * elf32-i386.c (struct elf_i386_link_hash_table): Added field

View file

@ -4509,6 +4509,9 @@ mips_elf_calculate_relocation (bfd *abfd, bfd *input_bfd,
&& h->root.def_dynamic && h->root.def_dynamic
&& !h->root.def_regular)) && !h->root.def_regular))
&& r_symndx != 0 && 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) && (input_section->flags & SEC_ALLOC) != 0)
{ {
/* If we're creating a shared library, or this relocation is /* 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) if (sreloc == NULL)
return FALSE; return FALSE;
} }
if (info->shared) if (info->shared && h == NULL)
{ {
/* When creating a shared object, we must copy these /* When creating a shared object, we must copy these
reloc types into the output file as R_MIPS_REL32 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; struct mips_elf_link_hash_entry *hmips;
/* We only need to copy this reloc if the symbol is /* For a shared object, we must copy this relocation
defined in a dynamic object. */ 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 = (struct mips_elf_link_hash_entry *) h;
++hmips->possibly_dynamic_relocs; ++hmips->possibly_dynamic_relocs;
if (MIPS_ELF_READONLY_SECTION (sec)) if (MIPS_ELF_READONLY_SECTION (sec))
@ -7289,6 +7301,66 @@ _bfd_mips_relax_section (bfd *abfd, asection *sec,
return FALSE; 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 /* Adjust a symbol defined by a dynamic object and referenced by a
regular object. The current definition is in some section of the regular object. The current definition is in some section of the
dynamic object, but we're not including those sections. We have to 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->ref_regular
&& !h->def_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; 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. */ /* For a function, create a stub, if allowed. */
if (! hmips->no_fn_stub 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 /* The check_relocs and adjust_dynamic_symbol entry points have
determined the sizes of the various dynamic sections. Allocate determined the sizes of the various dynamic sections. Allocate
memory for them. */ memory for them. */