non_got_ref after adjust_dynamic_relocs
authorAlan Modra <amodra@gmail.com>
Sun, 12 Nov 2017 07:14:15 +0000 (17:44 +1030)
committerAlan Modra <amodra@gmail.com>
Sun, 12 Nov 2017 07:15:23 +0000 (17:45 +1030)
commit529fe20eeb0030ea5d653d0ebec433f9e3145874
tree1915772ed022a482238d3fcd64d48e4db6d4af11
parentd95639024585ce43e8fe0557ac85e706452e1515
non_got_ref after adjust_dynamic_relocs

This patch was aimed at a FIXME in elf32-hppa.c, the ludicrous and
confusing fact that non_got_ref after adjust_dynamic_relocs in that
backend means precisely the inverse of what it means before
adjust_dynamic_relocs.  Before, when non_got_ref is set it means there
are dynamic relocs, after, if non_got_ref is clear it means "keep
dynamic relocs" and later, "has dynamic relocs".  There is a reason
why it was done that way..  Some symbols that may have dynamic
relocations pre-allocated in check_relocs turn out to not be dynamic,
and then are not seen by the backend adjust_dynamic_symbols.  We want
those symbols to lose their dynamic relocs when non-pic, so it's handy
that non_got_ref means the opposite after adjust_dynamic_relocs.  But
it's really confusing.

Most other targets, like ppc32, don't always set non_got_ref on
non-GOT references that have dynamic relocations.  This is because the
primary purpose of non_got_ref before adjust_dynamic_relocs is to flag
symbols that might need to be copied to .dynbss, and there are
relocation types that may require dyn_relocs but clearly cannot have
symbols copied into .dynbss, for example, TLS relocations.

Why do we need a flag after adjust_dynamic_relocs to say "keep
dynamic relocations"?  Well, you can discard most unwanted dyn_relocs
in the backend adjust_dynamic_relocs, and for those symbols that
aren't seen by the backend adjust_dynamic_relocs, in
allocate_dynrelocs based on a flag set by adjust_dynamic relocs,
dynamic_adjusted.  That doesn't solve all our difficulties though.
relocate_section needs to know whether a symbol has dyn_relocs, and
many targets transfer dyn_relocs to a weakdef if the symbol has one.
The transfer means relocate_section can't test dyn_relocs itself and
the weakdef field has been overwritten by that time.  So non_got_ref
is used to flag "this symbol has dynamic relocations" for
relocate_section.

Confused still?  Well, let's hope the comments I've added help clarify
things..  The patch also fixes a case where we might wrongly emit
dynamic relocations in an executable for common and undefined symbols.

* elf32-hppa.c (elf32_hppa_adjust_dynamic_symbol): Set non_got_ref
to keep dyn_relocs, clear to discard.  Comment.
(allocate_dynrelocs): Always clear non_got_ref when clearing
dyn_relocs in non-pic case.  Invert non_got_ref test.  Also test
dynamic_adjusted and ELF_COMMON_DEF_P.  Move code deleting
dyn_relocs on undefined syms to handle for non-pic too.
(elf32_hppa_relocate_section): Simplify test for non-pic dyn relocs.
* elf32-ppc.c (ppc_elf_adjust_dynamic_symbol): Set non_got_ref
to keep dyn_relocs, clear to discard.  Comment.
(allocate_dynrelocs): Always clear non_got_ref when clearing
dyn_relocs in non-pic case.  Invert non_got_ref test.  Also test
dynamic_adjusted and ELF_COMMON_DEF_P.  Move code deleting
dyn_relocs on undefined syms to handle for non-pic too.
(ppc_elf_relocate_section): Simplify test for non-pic dyn relocs.
* elf64-ppc.c (ppc64_elf_adjust_dynamic_symbol): Discard
dyn_relocs here.  Don't bother setting non_got_ref.  Comment.
(allocate_dynrelocs): Delete special handling of non-pic ELFv2
ifuncs.  Move code deleting dyn_relocs on undefined symbols to
handle for non-pic too.  Don't test non_got_ref.  Do test
dynamic_adjusted and ELF_COMMON_DEF_P.
bfd/ChangeLog
bfd/elf32-hppa.c
bfd/elf32-ppc.c
bfd/elf64-ppc.c