PowerPC64le PLT reference counting

A fix for ELFv2 ABI garbage-collection.

	* elf64-ppc.c (ppc64_elf_gc_sweep_hook): Support ELFv2 PLT
	reference counting.
This commit is contained in:
Alan Modra 2017-04-05 12:47:41 +09:30
parent 4ac40124ee
commit 8dea77f025
2 changed files with 35 additions and 11 deletions

View File

@ -1,3 +1,8 @@
2017-04-05 Alan Modra <amodra@gmail.com>
* elf64-ppc.c (ppc64_elf_gc_sweep_hook): Support ELFv2 PLT
reference counting.
2017-04-02 Jon Turney <jon.turney@dronecode.org.uk>
(_bfd_XXi_swap_aouthdr_out): For clarity, use defines rather than

View File

@ -6595,7 +6595,7 @@ ppc64_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
unsigned long r_symndx;
enum elf_ppc64_reloc_type r_type;
struct elf_link_hash_entry *h = NULL;
struct plt_entry **plt_list;
struct plt_entry **plt_list = NULL;
unsigned char tls_type = 0;
r_symndx = ELF64_R_SYM (rel->r_info);
@ -6674,6 +6674,8 @@ ppc64_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
if (ent->got.refcount > 0)
ent->got.refcount -= 1;
}
if (h != NULL && !bfd_link_pic (info) && abiversion (abfd) != 1)
plt_list = &h->plt.plist;
break;
case R_PPC64_PLT16_HA:
@ -6685,7 +6687,6 @@ ppc64_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
case R_PPC64_REL14_BRNTAKEN:
case R_PPC64_REL14_BRTAKEN:
case R_PPC64_REL24:
plt_list = NULL;
if (h != NULL)
plt_list = &h->plt.plist;
else if (local_got_ents != NULL)
@ -6697,21 +6698,39 @@ ppc64_elf_gc_sweep_hook (bfd *abfd, struct bfd_link_info *info,
if ((local_got_tls_masks[r_symndx] & PLT_IFUNC) != 0)
plt_list = local_plt + r_symndx;
}
if (plt_list)
{
struct plt_entry *ent;
break;
for (ent = *plt_list; ent != NULL; ent = ent->next)
if (ent->addend == rel->r_addend)
break;
if (ent != NULL && ent->plt.refcount > 0)
ent->plt.refcount -= 1;
}
case R_PPC64_ADDR64:
case R_PPC64_ADDR16:
case R_PPC64_ADDR16_DS:
case R_PPC64_ADDR16_HA:
case R_PPC64_ADDR16_HI:
case R_PPC64_ADDR16_HIGH:
case R_PPC64_ADDR16_HIGHA:
case R_PPC64_ADDR16_HIGHER:
case R_PPC64_ADDR16_HIGHERA:
case R_PPC64_ADDR16_HIGHEST:
case R_PPC64_ADDR16_HIGHESTA:
case R_PPC64_ADDR16_LO:
case R_PPC64_ADDR16_LO_DS:
if (h != NULL && !bfd_link_pic (info) && abiversion (abfd) != 1
&& rel->r_addend == 0)
plt_list = &h->plt.plist;
break;
default:
break;
}
if (plt_list != NULL)
{
struct plt_entry *ent;
for (ent = *plt_list; ent != NULL; ent = ent->next)
if (ent->addend == rel->r_addend)
break;
if (ent != NULL && ent->plt.refcount > 0)
ent->plt.refcount -= 1;
}
}
return TRUE;
}