Fix hppa-linux pr22269-1 fail

Adds UNDEFWEAK_NO_DYNAMIC_RELOC in the rest of places needed in this
file, reduces dynamic relocations in a number of cases, and removes
some bogus code that was attempting to handle dynamic common symbols
specially.

	PR 22269
	* elf32-hppa.c (elf32_hppa_check_relocs): Move SEC_ALLOC test to
	ensure non_got_ref is not set due to debug references.
	(elf32_hppa_adjust_dynamic_symbol): Tidy plabel handling.  Use
	SYMBOL_CALLS_LOCAL and UNDEFWEAK_NO_DYNAMIC_RELOC when determining
	need for a plt entry.
	(allocate_dynrelocs): Similarly for got entries.  Tidy code discarding
	dynamic relocs when pic.  Remove bogus code attempting to handle
	commons.
	(elf32_hppa_relocate_section): Similarly.  Delete resolved_to_zero
	and simplify.
	(elf32_hppa_finish_dynamic_symbol): Use UNDEFWEAK_NO_DYNAMIC_RELOC
	and SYMBOL_REFERENCES_LOCAL in GOT handling.
This commit is contained in:
Alan Modra 2017-10-27 15:04:25 +10:30
parent 2b2d167607
commit d336fa6d82
2 changed files with 91 additions and 80 deletions

View File

@ -1,3 +1,19 @@
2017-10-30 Alan Modra <amodra@gmail.com>
PR 22269
* elf32-hppa.c (elf32_hppa_check_relocs): Move SEC_ALLOC test to
ensure non_got_ref is not set due to debug references.
(elf32_hppa_adjust_dynamic_symbol): Tidy plabel handling. Use
SYMBOL_CALLS_LOCAL and UNDEFWEAK_NO_DYNAMIC_RELOC when determining
need for a plt entry.
(allocate_dynrelocs): Similarly for got entries. Tidy code discarding
dynamic relocs when pic. Remove bogus code attempting to handle
commons.
(elf32_hppa_relocate_section): Similarly. Delete resolved_to_zero
and simplify.
(elf32_hppa_finish_dynamic_symbol): Use UNDEFWEAK_NO_DYNAMIC_RELOC
and SYMBOL_REFERENCES_LOCAL in GOT handling.
2017-10-28 Alan Modra <amodra@gmail.com>
PR 22300

View File

@ -1423,7 +1423,8 @@ elf32_hppa_check_relocs (bfd *abfd,
}
}
if (need_entry & NEED_DYNREL)
if ((need_entry & NEED_DYNREL) != 0
&& (sec->flags & SEC_ALLOC) != 0)
{
/* Flag this symbol as having a non-got, non-plt reference
so that we generate copy relocs if it turns out to be
@ -1460,7 +1461,6 @@ elf32_hppa_check_relocs (bfd *abfd,
dynamic library if we manage to avoid copy relocs for the
symbol. */
if ((bfd_link_pic (info)
&& (sec->flags & SEC_ALLOC) != 0
&& (IS_ABSOLUTE_RELOC (r_type)
|| (hh != NULL
&& (!SYMBOLIC_BIND (info, &hh->eh)
@ -1468,7 +1468,6 @@ elf32_hppa_check_relocs (bfd *abfd,
|| !hh->eh.def_regular))))
|| (ELIMINATE_COPY_RELOCS
&& !bfd_link_pic (info)
&& (sec->flags & SEC_ALLOC) != 0
&& hh != NULL
&& (hh->eh.root.type == bfd_link_hash_defweak
|| !hh->eh.def_regular)))
@ -1680,15 +1679,12 @@ elf32_hppa_adjust_dynamic_symbol (struct bfd_link_info *info,
/* If the symbol is used by a plabel, we must allocate a PLT slot.
The refcounts are not reliable when it has been hidden since
hide_symbol can be called before the plabel flag is set. */
if (hppa_elf_hash_entry (eh)->plabel
&& eh->plt.refcount <= 0)
if (hppa_elf_hash_entry (eh)->plabel)
eh->plt.refcount = 1;
if (eh->plt.refcount <= 0
|| (eh->def_regular
&& eh->root.type != bfd_link_hash_defweak
&& ! hppa_elf_hash_entry (eh)->plabel
&& (!bfd_link_pic (info) || SYMBOLIC_BIND (info, eh))))
else if (eh->plt.refcount <= 0
|| SYMBOL_CALLS_LOCAL (info, eh)
|| UNDEFWEAK_NO_DYNAMIC_RELOC (info, eh))
{
/* The .plt entry is not needed when:
a) Garbage collection has removed all references to the
@ -1929,7 +1925,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *eh, void *inf)
if (htab->etab.dynamic_sections_created
&& (bfd_link_pic (info)
|| (eh->dynindx != -1
&& !eh->forced_local)))
&& !SYMBOL_REFERENCES_LOCAL (info, eh)))
&& !UNDEFWEAK_NO_DYNAMIC_RELOC (info, eh))
{
htab->etab.srelgot->size += sizeof (Elf32_External_Rela);
if ((hh->tls_type & (GOT_TLS_GD | GOT_TLS_IE)) == (GOT_TLS_GD | GOT_TLS_IE))
@ -1941,6 +1938,10 @@ allocate_dynrelocs (struct elf_link_hash_entry *eh, void *inf)
else
eh->got.offset = (bfd_vma) -1;
/* If no dynamic sections we can't have dynamic relocs. */
if (!htab->etab.dynamic_sections_created)
hh->dyn_relocs = NULL;
if (hh->dyn_relocs == NULL)
return TRUE;
@ -1953,9 +1954,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *eh, void *inf)
{
/* Discard relocs on undefined syms with non-default visibility. */
if ((eh->root.type == bfd_link_hash_undefined
|| eh->root.type == bfd_link_hash_undefweak)
&& (ELF_ST_VISIBILITY (eh->other) != STV_DEFAULT
|| UNDEFWEAK_NO_DYNAMIC_RELOC (info, eh)))
&& ELF_ST_VISIBILITY (eh->other) != STV_DEFAULT)
|| UNDEFWEAK_NO_DYNAMIC_RELOC (info, eh))
hh->dyn_relocs = NULL;
#if RELATIVE_DYNRELOCS
@ -1981,19 +1981,14 @@ allocate_dynrelocs (struct elf_link_hash_entry *eh, void *inf)
return FALSE;
}
}
else
else if (ELIMINATE_COPY_RELOCS)
{
/* For the non-shared case, discard space for relocs against
symbols which turn out to need copy relocs or are not
dynamic. */
if (!eh->non_got_ref
&& ((ELIMINATE_COPY_RELOCS
&& eh->def_dynamic
&& !eh->def_regular)
|| (htab->etab.dynamic_sections_created
&& (eh->root.type == bfd_link_hash_undefweak
|| eh->root.type == bfd_link_hash_undefined))))
&& !eh->def_regular)
{
if (!ensure_undef_dynamic (info, eh))
return FALSE;
@ -3550,7 +3545,6 @@ elf32_hppa_relocate_section (bfd *output_bfd,
const char *sym_name;
bfd_boolean plabel;
bfd_boolean warned_undef;
bfd_boolean resolved_to_zero;
r_type = ELF32_R_TYPE (rela->r_info);
if (r_type >= (unsigned int) R_PARISC_UNIMPLEMENTED)
@ -3614,9 +3608,6 @@ elf32_hppa_relocate_section (bfd *output_bfd,
if (bfd_link_relocatable (info))
continue;
resolved_to_zero = (hh != NULL
&& UNDEFWEAK_NO_DYNAMIC_RELOC (info, &hh->eh));
/* Do any required modifications to the relocation value, and
determine what types of dynamic info we need to output, if
any. */
@ -3628,7 +3619,8 @@ elf32_hppa_relocate_section (bfd *output_bfd,
case R_PARISC_DLTIND21L:
{
bfd_vma off;
bfd_boolean do_got = 0;
bfd_boolean do_got = FALSE;
bfd_boolean reloc = bfd_link_pic (info);
/* Relocation is to the entry for this symbol in the
global offset table. */
@ -3638,9 +3630,14 @@ elf32_hppa_relocate_section (bfd *output_bfd,
off = hh->eh.got.offset;
dyn = htab->etab.dynamic_sections_created;
if (! WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn,
bfd_link_pic (info),
&hh->eh))
reloc = (!UNDEFWEAK_NO_DYNAMIC_RELOC (info, &hh->eh)
&& (reloc
|| (hh->eh.dynindx != -1
&& !SYMBOL_REFERENCES_LOCAL (info, &hh->eh))));
if (!reloc
|| !WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn,
bfd_link_pic (info),
&hh->eh))
{
/* If we aren't going to call finish_dynamic_symbol,
then we need to handle initialisation of the .got
@ -3653,7 +3650,7 @@ elf32_hppa_relocate_section (bfd *output_bfd,
else
{
hh->eh.got.offset |= 1;
do_got = 1;
do_got = TRUE;
}
}
}
@ -3673,13 +3670,13 @@ elf32_hppa_relocate_section (bfd *output_bfd,
else
{
local_got_offsets[r_symndx] |= 1;
do_got = 1;
do_got = TRUE;
}
}
if (do_got)
{
if (bfd_link_pic (info))
if (reloc)
{
/* Output a dynamic relocation for this GOT entry.
In this case it is relative to the base of the
@ -3838,29 +3835,20 @@ elf32_hppa_relocate_section (bfd *output_bfd,
allocate_dynrelocs. ie. We need exactly the same condition
as in ..check_relocs, with some extra conditions (dynindx
test in this case) to cater for relocs removed by
allocate_dynrelocs. If you squint, the non-shared test
here does indeed match the one in ..check_relocs, the
difference being that here we test DEF_DYNAMIC as well as
!DEF_REGULAR. All common syms end up with !DEF_REGULAR,
which is why we can't use just that test here.
Conversely, DEF_DYNAMIC can't be used in check_relocs as
there all files have not been loaded. */
allocate_dynrelocs. */
if ((bfd_link_pic (info)
&& (hh == NULL
|| (ELF_ST_VISIBILITY (hh->eh.other) == STV_DEFAULT
&& !resolved_to_zero)
|| hh->eh.root.type != bfd_link_hash_undefweak)
&& !(hh != NULL
&& ((hh->eh.root.type == bfd_link_hash_undefined
&& ELF_ST_VISIBILITY (hh->eh.other) != STV_DEFAULT)
|| UNDEFWEAK_NO_DYNAMIC_RELOC (info, &hh->eh)))
&& (IS_ABSOLUTE_RELOC (r_type)
|| !SYMBOL_CALLS_LOCAL (info, &hh->eh)))
|| (!bfd_link_pic (info)
|| (ELIMINATE_COPY_RELOCS
&& !bfd_link_pic (info)
&& hh != NULL
&& hh->eh.dynindx != -1
&& !hh->eh.non_got_ref
&& ((ELIMINATE_COPY_RELOCS
&& hh->eh.def_dynamic
&& !hh->eh.def_regular)
|| hh->eh.root.type == bfd_link_hash_undefweak
|| hh->eh.root.type == bfd_link_hash_undefined)))
&& !hh->eh.def_regular))
{
Elf_Internal_Rela outrel;
bfd_boolean skip;
@ -4258,42 +4246,49 @@ elf32_hppa_finish_dynamic_symbol (bfd *output_bfd,
if (eh->got.offset != (bfd_vma) -1
&& (hppa_elf_hash_entry (eh)->tls_type & GOT_TLS_GD) == 0
&& (hppa_elf_hash_entry (eh)->tls_type & GOT_TLS_IE) == 0)
&& (hppa_elf_hash_entry (eh)->tls_type & GOT_TLS_IE) == 0
&& !UNDEFWEAK_NO_DYNAMIC_RELOC (info, eh))
{
/* This symbol has an entry in the global offset table. Set it
up. */
bfd_boolean is_dyn = (eh->dynindx != -1
&& !SYMBOL_REFERENCES_LOCAL (info, eh));
rela.r_offset = ((eh->got.offset &~ (bfd_vma) 1)
+ htab->etab.sgot->output_offset
+ htab->etab.sgot->output_section->vma);
/* If this is a -Bsymbolic link and the symbol is defined
locally or was forced to be local because of a version file,
we just want to emit a RELATIVE reloc. The entry in the
global offset table will already have been initialized in the
relocate_section function. */
if (bfd_link_pic (info)
&& (SYMBOLIC_BIND (info, eh) || eh->dynindx == -1)
&& eh->def_regular)
if (is_dyn || bfd_link_pic (info))
{
rela.r_info = ELF32_R_INFO (0, R_PARISC_DIR32);
rela.r_addend = (eh->root.u.def.value
+ eh->root.u.def.section->output_offset
+ eh->root.u.def.section->output_section->vma);
}
else
{
if ((eh->got.offset & 1) != 0)
abort ();
/* This symbol has an entry in the global offset table. Set
it up. */
bfd_put_32 (output_bfd, 0, htab->etab.sgot->contents + (eh->got.offset & ~1));
rela.r_info = ELF32_R_INFO (eh->dynindx, R_PARISC_DIR32);
rela.r_addend = 0;
}
rela.r_offset = ((eh->got.offset &~ (bfd_vma) 1)
+ htab->etab.sgot->output_offset
+ htab->etab.sgot->output_section->vma);
loc = htab->etab.srelgot->contents;
loc += htab->etab.srelgot->reloc_count++ * sizeof (Elf32_External_Rela);
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
/* If this is a -Bsymbolic link and the symbol is defined
locally or was forced to be local because of a version
file, we just want to emit a RELATIVE reloc. The entry
in the global offset table will already have been
initialized in the relocate_section function. */
if (!is_dyn)
{
rela.r_info = ELF32_R_INFO (0, R_PARISC_DIR32);
rela.r_addend = (eh->root.u.def.value
+ eh->root.u.def.section->output_offset
+ eh->root.u.def.section->output_section->vma);
}
else
{
if ((eh->got.offset & 1) != 0)
abort ();
bfd_put_32 (output_bfd, 0,
htab->etab.sgot->contents + (eh->got.offset & ~1));
rela.r_info = ELF32_R_INFO (eh->dynindx, R_PARISC_DIR32);
rela.r_addend = 0;
}
loc = htab->etab.srelgot->contents;
loc += (htab->etab.srelgot->reloc_count++
* sizeof (Elf32_External_Rela));
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
}
}
if (eh->needs_copy)