* elf32-ppc.c (ppc_elf_check_relocs): Always set up sections
used by indirect function support. Count dynamic relocs for ifunc syms. (ppc_elf_adjust_dynamic_symbol): Tweak for ifunc. (allocate_dynrelocs): Allocate all non-dynamic ifunc plt entries in iplt and their relocs in reliplt. Don't make ifunc syms dynamic. Allocate got entry relocs for non-dynamic ifunc in reliplt. Handle other dynamic relocs for ifunc. (ppc_elf_size_dynamic_sections): Alloc dyn relocs for static ifunc in reliplt, likewise relocs for got against local ifunc. Typo fix on reliplt size adjust. (ppc_elf_relocate_section): Don't use plt scheme of allocating relocs 1-1 with entries for iplt, instead just add using reloc_count. Write got relocs and dyn relocs for ifunc to reliplt. Error on invalid ifunc dyn relocs. (ppc_elf_finish_dynamic_symbol): Adjust for non-dynamic ifunc plt in iplt/reliplt. * elf64-ppc.c (ppc64_elf_howto_raw): Add R_PPC64_JMP_IREL, R_PPC64_REL16, R_PPC64_REL16_LO, R_PPC64_REL16_HI, R_PPC64_REL16_HA. (ppc64_elf_reloc_type_lookup): Handle new relocs. (ppc64_elf_check_relocs): Likewise. Count dyn relocs for ifunc. (allocate_dynrelocs): As for elf32-ppc.c above. (ppc64_elf_size_dynamic_sections): Likewise. (ppc_build_one_stub): Put non-dynamic ifunc plt call stubs in iplt, and their relocs in reliplt. Use R_PPC64_JMP_IREL. (ppc_size_one_stub): Similarly. (ppc64_elf_relocate_section): As for elf32-ppc.c above. Handle new relocs too. (ppc64_elf_finish_dynamic_symbol): As for elf32-ppc.c above.
This commit is contained in:
parent
28ec585fea
commit
25f231068e
3 changed files with 408 additions and 153 deletions
|
@ -1,3 +1,35 @@
|
|||
2009-07-30 Alan Modra <amodra@bigpond.net.au>
|
||||
|
||||
* elf32-ppc.c (ppc_elf_check_relocs): Always set up sections
|
||||
used by indirect function support. Count dynamic relocs for
|
||||
ifunc syms.
|
||||
(ppc_elf_adjust_dynamic_symbol): Tweak for ifunc.
|
||||
(allocate_dynrelocs): Allocate all non-dynamic ifunc plt entries
|
||||
in iplt and their relocs in reliplt. Don't make ifunc syms
|
||||
dynamic. Allocate got entry relocs for non-dynamic ifunc in
|
||||
reliplt. Handle other dynamic relocs for ifunc.
|
||||
(ppc_elf_size_dynamic_sections): Alloc dyn relocs for static
|
||||
ifunc in reliplt, likewise relocs for got against local ifunc.
|
||||
Typo fix on reliplt size adjust.
|
||||
(ppc_elf_relocate_section): Don't use plt scheme of allocating
|
||||
relocs 1-1 with entries for iplt, instead just add using
|
||||
reloc_count. Write got relocs and dyn relocs for ifunc to reliplt.
|
||||
Error on invalid ifunc dyn relocs.
|
||||
(ppc_elf_finish_dynamic_symbol): Adjust for non-dynamic ifunc plt
|
||||
in iplt/reliplt.
|
||||
* elf64-ppc.c (ppc64_elf_howto_raw): Add R_PPC64_JMP_IREL,
|
||||
R_PPC64_REL16, R_PPC64_REL16_LO, R_PPC64_REL16_HI, R_PPC64_REL16_HA.
|
||||
(ppc64_elf_reloc_type_lookup): Handle new relocs.
|
||||
(ppc64_elf_check_relocs): Likewise. Count dyn relocs for ifunc.
|
||||
(allocate_dynrelocs): As for elf32-ppc.c above.
|
||||
(ppc64_elf_size_dynamic_sections): Likewise.
|
||||
(ppc_build_one_stub): Put non-dynamic ifunc plt call stubs in iplt,
|
||||
and their relocs in reliplt. Use R_PPC64_JMP_IREL.
|
||||
(ppc_size_one_stub): Similarly.
|
||||
(ppc64_elf_relocate_section): As for elf32-ppc.c above. Handle new
|
||||
relocs too.
|
||||
(ppc64_elf_finish_dynamic_symbol): As for elf32-ppc.c above.
|
||||
|
||||
2009-07-29 Hans-Peter Nilsson <hp@bitrange.com>
|
||||
|
||||
* elf64-mmix.c (mmix_elf_relax_section): Revert 2009-05-27
|
||||
|
|
208
bfd/elf32-ppc.c
208
bfd/elf32-ppc.c
|
@ -3408,6 +3408,13 @@ ppc_elf_check_relocs (bfd *abfd,
|
|||
ppc_elf_howto_init ();
|
||||
|
||||
htab = ppc_elf_hash_table (info);
|
||||
if (htab->glink == NULL)
|
||||
{
|
||||
if (htab->elf.dynobj == NULL)
|
||||
htab->elf.dynobj = abfd;
|
||||
if (!ppc_elf_create_glink (htab->elf.dynobj, info))
|
||||
return FALSE;
|
||||
}
|
||||
tga = elf_link_hash_lookup (&htab->elf, "__tls_get_addr",
|
||||
FALSE, FALSE, TRUE);
|
||||
symtab_hdr = &elf_symtab_hdr (abfd);
|
||||
|
@ -3451,23 +3458,8 @@ ppc_elf_check_relocs (bfd *abfd,
|
|||
|
||||
tls_type = 0;
|
||||
ifunc = NULL;
|
||||
r_type = ELF32_R_TYPE (rel->r_info);
|
||||
if (!htab->is_vxworks && is_branch_reloc (r_type))
|
||||
if (!htab->is_vxworks)
|
||||
{
|
||||
if (h != NULL && h == tga)
|
||||
{
|
||||
if (rel != relocs
|
||||
&& (ELF32_R_TYPE (rel[-1].r_info) == R_PPC_TLSGD
|
||||
|| ELF32_R_TYPE (rel[-1].r_info) == R_PPC_TLSLD))
|
||||
/* We have a new-style __tls_get_addr call with a marker
|
||||
reloc. */
|
||||
;
|
||||
else
|
||||
/* Mark this section as having an old-style call. */
|
||||
sec->has_tls_get_addr_call = 1;
|
||||
}
|
||||
|
||||
/* STT_GNU_IFUNC symbols must have a PLT entry. */
|
||||
if (h != NULL)
|
||||
{
|
||||
if (h->type == STT_GNU_IFUNC)
|
||||
|
@ -3491,6 +3483,25 @@ ppc_elf_check_relocs (bfd *abfd,
|
|||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
r_type = ELF32_R_TYPE (rel->r_info);
|
||||
if (!htab->is_vxworks && is_branch_reloc (r_type))
|
||||
{
|
||||
if (h != NULL && h == tga)
|
||||
{
|
||||
if (rel != relocs
|
||||
&& (ELF32_R_TYPE (rel[-1].r_info) == R_PPC_TLSGD
|
||||
|| ELF32_R_TYPE (rel[-1].r_info) == R_PPC_TLSLD))
|
||||
/* We have a new-style __tls_get_addr call with a marker
|
||||
reloc. */
|
||||
;
|
||||
else
|
||||
/* Mark this section as having an old-style call. */
|
||||
sec->has_tls_get_addr_call = 1;
|
||||
}
|
||||
|
||||
/* STT_GNU_IFUNC symbols must have a PLT entry. */
|
||||
if (ifunc != NULL)
|
||||
{
|
||||
bfd_vma addend = 0;
|
||||
|
@ -3503,14 +3514,6 @@ ppc_elf_check_relocs (bfd *abfd,
|
|||
if (!update_plt_info (abfd, ifunc,
|
||||
addend < 32768 ? NULL : got2, addend))
|
||||
return FALSE;
|
||||
|
||||
if (htab->glink == NULL)
|
||||
{
|
||||
if (htab->elf.dynobj == NULL)
|
||||
htab->elf.dynobj = abfd;
|
||||
if (!ppc_elf_create_glink (htab->elf.dynobj, info))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3938,7 +3941,9 @@ ppc_elf_check_relocs (bfd *abfd,
|
|||
&& !info->shared
|
||||
&& h != NULL
|
||||
&& (h->root.type == bfd_link_hash_defweak
|
||||
|| !h->def_regular)))
|
||||
|| !h->def_regular))
|
||||
|| (!info->shared
|
||||
&& ifunc != NULL))
|
||||
{
|
||||
struct ppc_elf_dyn_relocs *p;
|
||||
struct ppc_elf_dyn_relocs **head;
|
||||
|
@ -4859,8 +4864,10 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
|
|||
}
|
||||
else
|
||||
{
|
||||
/* After adjust_dynamic_symbol, non_got_ref set means that
|
||||
dyn_relocs for this symbol should be discarded.
|
||||
/* After adjust_dynamic_symbol, non_got_ref set in the
|
||||
non-shared case means that we have allocated space in
|
||||
.dynbss for the symbol and thus dyn_relocs for this
|
||||
symbol should be discarded.
|
||||
If we get here we know we are making a PLT entry for this
|
||||
symbol, and in an executable we'd normally resolve
|
||||
relocations against this symbol to the PLT entry. Allow
|
||||
|
@ -4868,6 +4875,7 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
|
|||
relocs will not cause text relocation. */
|
||||
if (!h->ref_regular_nonweak
|
||||
&& h->non_got_ref
|
||||
&& h->type != STT_GNU_IFUNC
|
||||
&& !htab->is_vxworks
|
||||
&& !ppc_elf_hash_entry (h)->has_sda_refs
|
||||
&& !readonly_dynrelocs (h))
|
||||
|
@ -5105,10 +5113,10 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||
|| WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h))
|
||||
{
|
||||
asection *s = htab->plt;
|
||||
if (!dyn)
|
||||
if (!dyn || h->dynindx == -1)
|
||||
s = htab->iplt;
|
||||
|
||||
if (htab->plt_type == PLT_NEW || !dyn)
|
||||
if (htab->plt_type == PLT_NEW || !dyn || h->dynindx == -1)
|
||||
{
|
||||
if (!doneone)
|
||||
{
|
||||
|
@ -5186,7 +5194,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||
/* We also need to make an entry in the .rela.plt section. */
|
||||
if (!doneone)
|
||||
{
|
||||
if (!htab->elf.dynamic_sections_created)
|
||||
if (!htab->elf.dynamic_sections_created
|
||||
|| h->dynindx == -1)
|
||||
htab->reliplt->size += sizeof (Elf32_External_Rela);
|
||||
else
|
||||
{
|
||||
|
@ -5246,7 +5255,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||
/* Make sure this symbol is output as a dynamic symbol. */
|
||||
if (eh->elf.dynindx == -1
|
||||
&& !eh->elf.forced_local
|
||||
&& !eh->elf.def_regular
|
||||
&& eh->elf.type != STT_GNU_IFUNC
|
||||
&& htab->elf.dynamic_sections_created)
|
||||
{
|
||||
if (!bfd_elf_link_record_dynamic_symbol (info, &eh->elf))
|
||||
|
@ -5279,19 +5288,24 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||
eh->elf.got.offset = (bfd_vma) -1;
|
||||
else
|
||||
{
|
||||
asection *rsec = NULL;
|
||||
eh->elf.got.offset = allocate_got (htab, need);
|
||||
dyn = htab->elf.dynamic_sections_created;
|
||||
if ((info->shared
|
||||
|| WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, &eh->elf))
|
||||
&& (ELF_ST_VISIBILITY (eh->elf.other) == STV_DEFAULT
|
||||
|| eh->elf.root.type != bfd_link_hash_undefweak))
|
||||
rsec = htab->relgot;
|
||||
else if (h->type == STT_GNU_IFUNC)
|
||||
rsec = htab->reliplt;
|
||||
if (rsec != NULL)
|
||||
{
|
||||
/* All the entries we allocated need relocs.
|
||||
Except LD only needs one. */
|
||||
if ((eh->tls_mask & TLS_LD) != 0
|
||||
&& eh->elf.def_dynamic)
|
||||
need -= 4;
|
||||
htab->relgot->size += need * (sizeof (Elf32_External_Rela) / 4);
|
||||
rsec->size += need * (sizeof (Elf32_External_Rela) / 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -5299,7 +5313,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||
eh->elf.got.offset = (bfd_vma) -1;
|
||||
|
||||
if (eh->dyn_relocs == NULL
|
||||
|| !htab->elf.dynamic_sections_created)
|
||||
|| (!htab->elf.dynamic_sections_created
|
||||
&& h->type != STT_GNU_IFUNC))
|
||||
return TRUE;
|
||||
|
||||
/* In the shared -Bsymbolic case, discard space allocated for
|
||||
|
@ -5370,6 +5385,11 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (h->type == STT_GNU_IFUNC)
|
||||
{
|
||||
if (!h->non_got_ref)
|
||||
eh->dyn_relocs = NULL;
|
||||
}
|
||||
else if (ELIMINATE_COPY_RELOCS)
|
||||
{
|
||||
/* For the non-shared case, discard space for relocs against
|
||||
|
@ -5382,8 +5402,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||
/* Make sure this symbol is output as a dynamic symbol.
|
||||
Undefined weak syms won't yet be marked as dynamic. */
|
||||
if (h->dynindx == -1
|
||||
&& !h->forced_local
|
||||
&& !h->def_regular)
|
||||
&& !h->forced_local)
|
||||
{
|
||||
if (! bfd_elf_link_record_dynamic_symbol (info, h))
|
||||
return FALSE;
|
||||
|
@ -5404,6 +5423,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||
for (p = eh->dyn_relocs; p != NULL; p = p->next)
|
||||
{
|
||||
asection *sreloc = elf_section_data (p->sec)->sreloc;
|
||||
if (!htab->elf.dynamic_sections_created)
|
||||
sreloc = htab->reliplt;
|
||||
sreloc->size += p->count * sizeof (Elf32_External_Rela);
|
||||
}
|
||||
|
||||
|
@ -5508,8 +5529,10 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
|||
}
|
||||
else if (p->count != 0)
|
||||
{
|
||||
elf_section_data (p->sec)->sreloc->size
|
||||
+= p->count * sizeof (Elf32_External_Rela);
|
||||
asection *sreloc = elf_section_data (p->sec)->sreloc;
|
||||
if (!htab->elf.dynamic_sections_created)
|
||||
sreloc = htab->reliplt;
|
||||
sreloc->size += p->count * sizeof (Elf32_External_Rela);
|
||||
if ((p->sec->output_section->flags
|
||||
& (SEC_READONLY | SEC_ALLOC))
|
||||
== (SEC_READONLY | SEC_ALLOC))
|
||||
|
@ -5553,6 +5576,9 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
|||
if (info->shared)
|
||||
htab->relgot->size += (need
|
||||
* (sizeof (Elf32_External_Rela) / 4));
|
||||
else if ((*lgot_masks & PLT_IFUNC) != 0)
|
||||
htab->reliplt->size += (need
|
||||
* (sizeof (Elf32_External_Rela) / 4));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -5590,7 +5616,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
|||
|
||||
if (!doneone)
|
||||
{
|
||||
htab->reliplt += sizeof (Elf32_External_Rela);
|
||||
htab->reliplt->size += sizeof (Elf32_External_Rela);
|
||||
doneone = TRUE;
|
||||
}
|
||||
}
|
||||
|
@ -6912,7 +6938,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||
}
|
||||
|
||||
ifunc = NULL;
|
||||
if (!htab->is_vxworks && is_branch_reloc (r_type))
|
||||
if (!htab->is_vxworks)
|
||||
{
|
||||
if (h != NULL)
|
||||
{
|
||||
|
@ -6929,7 +6955,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||
ifunc = local_plt + r_symndx;
|
||||
}
|
||||
}
|
||||
if (ifunc != NULL)
|
||||
if (ifunc != NULL && is_branch_reloc (r_type))
|
||||
{
|
||||
struct plt_entry *ent = find_plt_ent (ifunc, got2, rel->r_addend);
|
||||
|
||||
|
@ -6943,8 +6969,9 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||
+ ent->plt.offset);
|
||||
rela.r_info = ELF32_R_INFO (0, R_PPC_IRELATIVE);
|
||||
rela.r_addend = relocation;
|
||||
loc = (htab->reliplt->contents
|
||||
+ ent->plt.offset * sizeof (Elf32_External_Rela) / 4);
|
||||
loc = htab->reliplt->contents;
|
||||
loc += (htab->reliplt->reloc_count++
|
||||
* sizeof (Elf32_External_Rela));
|
||||
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
|
||||
|
||||
ent->plt.offset |= 1;
|
||||
|
@ -7081,6 +7108,7 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||
off &= ~1;
|
||||
else
|
||||
{
|
||||
asection *rsec;
|
||||
unsigned int tls_m = (tls_mask
|
||||
& (TLS_LD | TLS_GD | TLS_DTPREL
|
||||
| TLS_TPREL | TLS_TPRELGD));
|
||||
|
@ -7119,11 +7147,16 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||
}
|
||||
|
||||
/* Generate relocs for the dynamic linker. */
|
||||
rsec = NULL;
|
||||
if ((info->shared || indx != 0)
|
||||
&& (offp == &htab->tlsld_got.offset
|
||||
|| h == NULL
|
||||
|| ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|
||||
|| h->root.type != bfd_link_hash_undefweak))
|
||||
rsec = htab->relgot;
|
||||
else if (ifunc != NULL)
|
||||
rsec = htab->reliplt;
|
||||
if (rsec != NULL)
|
||||
{
|
||||
outrel.r_offset = (htab->got->output_section->vma
|
||||
+ htab->got->output_offset
|
||||
|
@ -7134,8 +7167,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||
outrel.r_info = ELF32_R_INFO (indx, R_PPC_DTPMOD32);
|
||||
if (tls_ty == (TLS_TLS | TLS_GD))
|
||||
{
|
||||
loc = htab->relgot->contents;
|
||||
loc += (htab->relgot->reloc_count++
|
||||
loc = rsec->contents;
|
||||
loc += (rsec->reloc_count++
|
||||
* sizeof (Elf32_External_Rela));
|
||||
bfd_elf32_swap_reloca_out (output_bfd,
|
||||
&outrel, loc);
|
||||
|
@ -7148,18 +7181,20 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||
outrel.r_info = ELF32_R_INFO (indx, R_PPC_DTPREL32);
|
||||
else if (tls_ty == (TLS_TLS | TLS_TPREL))
|
||||
outrel.r_info = ELF32_R_INFO (indx, R_PPC_TPREL32);
|
||||
else if (indx == 0)
|
||||
outrel.r_info = ELF32_R_INFO (indx, R_PPC_RELATIVE);
|
||||
else
|
||||
else if (indx != 0)
|
||||
outrel.r_info = ELF32_R_INFO (indx, R_PPC_GLOB_DAT);
|
||||
else if (ifunc != NULL)
|
||||
outrel.r_info = ELF32_R_INFO (0, R_PPC_IRELATIVE);
|
||||
else
|
||||
outrel.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE);
|
||||
if (indx == 0 && tls_ty != (TLS_TLS | TLS_LD))
|
||||
{
|
||||
outrel.r_addend += relocation;
|
||||
if (tls_ty & (TLS_GD | TLS_DTPREL | TLS_TPREL))
|
||||
outrel.r_addend -= htab->elf.tls_sec->vma;
|
||||
}
|
||||
loc = htab->relgot->contents;
|
||||
loc += (htab->relgot->reloc_count++
|
||||
loc = rsec->contents;
|
||||
loc += (rsec->reloc_count++
|
||||
* sizeof (Elf32_External_Rela));
|
||||
bfd_elf32_swap_reloca_out (output_bfd, &outrel, loc);
|
||||
}
|
||||
|
@ -7350,7 +7385,9 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||
&& h != NULL
|
||||
&& h->dynindx != -1
|
||||
&& !h->non_got_ref
|
||||
&& !h->def_regular))
|
||||
&& !h->def_regular)
|
||||
|| (!info->shared
|
||||
&& ifunc != NULL))
|
||||
{
|
||||
int skip;
|
||||
|
||||
|
@ -7366,8 +7403,9 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||
time. */
|
||||
if (sreloc == NULL)
|
||||
{
|
||||
sreloc = _bfd_elf_get_dynamic_reloc_section
|
||||
(input_bfd, input_section, /*rela?*/ TRUE);
|
||||
sreloc = elf_section_data (input_section)->sreloc;
|
||||
if (!htab->elf.dynamic_sections_created)
|
||||
sreloc = htab->reliplt;
|
||||
if (sreloc == NULL)
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -7397,13 +7435,35 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||
{
|
||||
outrel.r_addend = relocation + rel->r_addend;
|
||||
|
||||
if (r_type == R_PPC_ADDR32)
|
||||
outrel.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE);
|
||||
else
|
||||
if (r_type != R_PPC_ADDR32)
|
||||
{
|
||||
long indx = 0;
|
||||
|
||||
if (r_symndx == 0 || bfd_is_abs_section (sec))
|
||||
if (ifunc != NULL)
|
||||
{
|
||||
/* If we get here when building a static
|
||||
executable, then the libc startup function
|
||||
responsible for applying indirect function
|
||||
relocations is going to complain about
|
||||
the reloc type.
|
||||
If we get here when building a dynamic
|
||||
executable, it will be because we have
|
||||
a text relocation. The dynamic loader
|
||||
will set the text segment writable and
|
||||
non-executable to apply text relocations.
|
||||
So we'll segfault when trying to run the
|
||||
indirection function to resolve the reloc. */
|
||||
(*_bfd_error_handler)
|
||||
(_("%B(%A+0x%lx): relocation %s for indirect "
|
||||
"function %s unsupported"),
|
||||
input_bfd,
|
||||
input_section,
|
||||
(long) rel->r_offset,
|
||||
howto->name,
|
||||
sym_name);
|
||||
ret = FALSE;
|
||||
}
|
||||
else if (r_symndx == 0 || bfd_is_abs_section (sec))
|
||||
;
|
||||
else if (sec == NULL || sec->owner == NULL)
|
||||
{
|
||||
|
@ -7418,7 +7478,8 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||
against a section symbol. It would be
|
||||
proper to subtract the symbol's value,
|
||||
osec->vma, from the emitted reloc addend,
|
||||
but ld.so expects buggy relocs. */
|
||||
but ld.so expects buggy relocs.
|
||||
FIXME: Why not always use a zero index? */
|
||||
osec = sec->output_section;
|
||||
indx = elf_section_data (osec)->dynindx;
|
||||
if (indx == 0)
|
||||
|
@ -7437,6 +7498,10 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||
|
||||
outrel.r_info = ELF32_R_INFO (indx, r_type);
|
||||
}
|
||||
else if (ifunc != NULL)
|
||||
outrel.r_info = ELF32_R_INFO (0, R_PPC_IRELATIVE);
|
||||
else
|
||||
outrel.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE);
|
||||
}
|
||||
|
||||
loc = sreloc->contents;
|
||||
|
@ -7891,7 +7956,8 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
|
|||
bfd_vma reloc_index;
|
||||
|
||||
if (htab->plt_type == PLT_NEW
|
||||
|| !htab->elf.dynamic_sections_created)
|
||||
|| !htab->elf.dynamic_sections_created
|
||||
|| h->dynindx == -1)
|
||||
reloc_index = ent->plt.offset / 4;
|
||||
else
|
||||
{
|
||||
|
@ -7905,7 +7971,8 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
|
|||
/* This symbol has an entry in the procedure linkage table.
|
||||
Set it up. */
|
||||
if (htab->plt_type == PLT_VXWORKS
|
||||
&& htab->elf.dynamic_sections_created)
|
||||
&& htab->elf.dynamic_sections_created
|
||||
&& h->dynindx != -1)
|
||||
{
|
||||
bfd_vma got_offset;
|
||||
const bfd_vma *plt_entry;
|
||||
|
@ -8028,14 +8095,16 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
|
|||
else
|
||||
{
|
||||
asection *splt = htab->plt;
|
||||
if (!htab->elf.dynamic_sections_created)
|
||||
if (!htab->elf.dynamic_sections_created
|
||||
|| h->dynindx == -1)
|
||||
splt = htab->iplt;
|
||||
|
||||
rela.r_offset = (splt->output_section->vma
|
||||
+ splt->output_offset
|
||||
+ ent->plt.offset);
|
||||
if (htab->plt_type == PLT_OLD
|
||||
|| !htab->elf.dynamic_sections_created)
|
||||
|| !htab->elf.dynamic_sections_created
|
||||
|| h->dynindx == -1)
|
||||
{
|
||||
/* We don't need to fill in the .plt. The ppc dynamic
|
||||
linker will fill it in. */
|
||||
|
@ -8065,11 +8134,14 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
|
|||
else
|
||||
rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_JMP_SLOT);
|
||||
|
||||
if (!htab->elf.dynamic_sections_created)
|
||||
loc = htab->reliplt->contents;
|
||||
if (!htab->elf.dynamic_sections_created
|
||||
|| h->dynindx == -1)
|
||||
loc = (htab->reliplt->contents
|
||||
+ (htab->reliplt->reloc_count++
|
||||
* sizeof (Elf32_External_Rela)));
|
||||
else
|
||||
loc = htab->relplt->contents;
|
||||
loc += reloc_index * sizeof (Elf32_External_Rela);
|
||||
loc = (htab->relplt->contents
|
||||
+ reloc_index * sizeof (Elf32_External_Rela));
|
||||
bfd_elf32_swap_reloca_out (output_bfd, &rela, loc);
|
||||
|
||||
if (!h->def_regular)
|
||||
|
@ -8096,10 +8168,12 @@ ppc_elf_finish_dynamic_symbol (bfd *output_bfd,
|
|||
}
|
||||
|
||||
if (htab->plt_type == PLT_NEW
|
||||
|| !htab->elf.dynamic_sections_created)
|
||||
|| !htab->elf.dynamic_sections_created
|
||||
|| h->dynindx == -1)
|
||||
{
|
||||
asection *splt = htab->plt;
|
||||
if (!htab->elf.dynamic_sections_created)
|
||||
if (!htab->elf.dynamic_sections_created
|
||||
|| h->dynindx == -1)
|
||||
splt = htab->iplt;
|
||||
|
||||
write_glink_stub (ent, splt, info);
|
||||
|
|
321
bfd/elf64-ppc.c
321
bfd/elf64-ppc.c
|
@ -1874,6 +1874,20 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
|
|||
0xffff, /* dst_mask */
|
||||
FALSE), /* pcrel_offset */
|
||||
|
||||
HOWTO (R_PPC64_JMP_IREL, /* type */
|
||||
0, /* rightshift */
|
||||
0, /* size (0=byte, 1=short, 2=long, 4=64 bits) */
|
||||
0, /* bitsize */
|
||||
FALSE, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_dont, /* complain_on_overflow */
|
||||
ppc64_elf_unhandled_reloc, /* special_function */
|
||||
"R_PPC64_JMP_IREL", /* name */
|
||||
FALSE, /* partial_inplace */
|
||||
0, /* src_mask */
|
||||
0, /* dst_mask */
|
||||
FALSE), /* pcrel_offset */
|
||||
|
||||
HOWTO (R_PPC64_IRELATIVE, /* type */
|
||||
0, /* rightshift */
|
||||
4, /* size (0=byte, 1=short, 2=long, 4=64 bits) */
|
||||
|
@ -1888,6 +1902,67 @@ static reloc_howto_type ppc64_elf_howto_raw[] = {
|
|||
ONES (64), /* dst_mask */
|
||||
FALSE), /* pcrel_offset */
|
||||
|
||||
/* A 16 bit relative relocation. */
|
||||
HOWTO (R_PPC64_REL16, /* type */
|
||||
0, /* rightshift */
|
||||
1, /* size (0 = byte, 1 = short, 2 = long) */
|
||||
16, /* bitsize */
|
||||
TRUE, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_bitfield, /* complain_on_overflow */
|
||||
bfd_elf_generic_reloc, /* special_function */
|
||||
"R_PPC64_REL16", /* name */
|
||||
FALSE, /* partial_inplace */
|
||||
0, /* src_mask */
|
||||
0xffff, /* dst_mask */
|
||||
TRUE), /* pcrel_offset */
|
||||
|
||||
/* A 16 bit relative relocation without overflow. */
|
||||
HOWTO (R_PPC64_REL16_LO, /* type */
|
||||
0, /* rightshift */
|
||||
1, /* size (0 = byte, 1 = short, 2 = long) */
|
||||
16, /* bitsize */
|
||||
TRUE, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_dont,/* complain_on_overflow */
|
||||
bfd_elf_generic_reloc, /* special_function */
|
||||
"R_PPC64_REL16_LO", /* name */
|
||||
FALSE, /* partial_inplace */
|
||||
0, /* src_mask */
|
||||
0xffff, /* dst_mask */
|
||||
TRUE), /* pcrel_offset */
|
||||
|
||||
/* The high order 16 bits of a relative address. */
|
||||
HOWTO (R_PPC64_REL16_HI, /* type */
|
||||
16, /* rightshift */
|
||||
1, /* size (0 = byte, 1 = short, 2 = long) */
|
||||
16, /* bitsize */
|
||||
TRUE, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_dont, /* complain_on_overflow */
|
||||
bfd_elf_generic_reloc, /* special_function */
|
||||
"R_PPC64_REL16_HI", /* name */
|
||||
FALSE, /* partial_inplace */
|
||||
0, /* src_mask */
|
||||
0xffff, /* dst_mask */
|
||||
TRUE), /* pcrel_offset */
|
||||
|
||||
/* The high order 16 bits of a relative address, plus 1 if the contents of
|
||||
the low 16 bits, treated as a signed number, is negative. */
|
||||
HOWTO (R_PPC64_REL16_HA, /* type */
|
||||
16, /* rightshift */
|
||||
1, /* size (0 = byte, 1 = short, 2 = long) */
|
||||
16, /* bitsize */
|
||||
TRUE, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_dont, /* complain_on_overflow */
|
||||
ppc64_elf_ha_reloc, /* special_function */
|
||||
"R_PPC64_REL16_HA", /* name */
|
||||
FALSE, /* partial_inplace */
|
||||
0, /* src_mask */
|
||||
0xffff, /* dst_mask */
|
||||
TRUE), /* pcrel_offset */
|
||||
|
||||
/* GNU extension to record C++ vtable hierarchy. */
|
||||
HOWTO (R_PPC64_GNU_VTINHERIT, /* type */
|
||||
0, /* rightshift */
|
||||
|
@ -2156,6 +2231,14 @@ ppc64_elf_reloc_type_lookup (bfd *abfd ATTRIBUTE_UNUSED,
|
|||
break;
|
||||
case BFD_RELOC_PPC64_DTPREL16_HIGHESTA: r = R_PPC64_DTPREL16_HIGHESTA;
|
||||
break;
|
||||
case BFD_RELOC_16_PCREL: r = R_PPC64_REL16;
|
||||
break;
|
||||
case BFD_RELOC_LO16_PCREL: r = R_PPC64_REL16_LO;
|
||||
break;
|
||||
case BFD_RELOC_HI16_PCREL: r = R_PPC64_REL16_HI;
|
||||
break;
|
||||
case BFD_RELOC_HI16_S_PCREL: r = R_PPC64_REL16_HA;
|
||||
break;
|
||||
case BFD_RELOC_VTABLE_INHERIT: r = R_PPC64_GNU_VTINHERIT;
|
||||
break;
|
||||
case BFD_RELOC_VTABLE_ENTRY: r = R_PPC64_GNU_VTENTRY;
|
||||
|
@ -4763,6 +4846,29 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
|||
|
||||
tls_type = 0;
|
||||
ifunc = NULL;
|
||||
if (h != NULL)
|
||||
{
|
||||
if (h->type == STT_GNU_IFUNC)
|
||||
{
|
||||
h->needs_plt = 1;
|
||||
ifunc = &h->plt.plist;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Elf_Internal_Sym *isym = bfd_sym_from_r_symndx (&htab->sym_cache,
|
||||
abfd, r_symndx);
|
||||
if (isym == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
|
||||
{
|
||||
ifunc = update_local_sym_info (abfd, symtab_hdr, r_symndx,
|
||||
rel->r_addend, PLT_IFUNC);
|
||||
if (ifunc == NULL)
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
r_type = ELF64_R_TYPE (rel->r_info);
|
||||
if (is_branch_reloc (r_type))
|
||||
{
|
||||
|
@ -4780,29 +4886,6 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
|||
}
|
||||
|
||||
/* STT_GNU_IFUNC symbols must have a PLT entry. */
|
||||
if (h != NULL)
|
||||
{
|
||||
if (h->type == STT_GNU_IFUNC)
|
||||
{
|
||||
h->needs_plt = 1;
|
||||
ifunc = &h->plt.plist;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Elf_Internal_Sym *isym = bfd_sym_from_r_symndx (&htab->sym_cache,
|
||||
abfd, r_symndx);
|
||||
if (isym == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (ELF_ST_TYPE (isym->st_info) == STT_GNU_IFUNC)
|
||||
{
|
||||
ifunc = update_local_sym_info (abfd, symtab_hdr, r_symndx,
|
||||
rel->r_addend, PLT_IFUNC);
|
||||
if (ifunc == NULL)
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
if (ifunc != NULL
|
||||
&& !update_plt_info (abfd, ifunc, rel->r_addend))
|
||||
return FALSE;
|
||||
|
@ -4944,6 +5027,12 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
|||
break;
|
||||
|
||||
/* Nor do these. */
|
||||
case R_PPC64_REL16:
|
||||
case R_PPC64_REL16_LO:
|
||||
case R_PPC64_REL16_HI:
|
||||
case R_PPC64_REL16_HA:
|
||||
break;
|
||||
|
||||
case R_PPC64_TOC16:
|
||||
case R_PPC64_TOC16_LO:
|
||||
case R_PPC64_TOC16_HI:
|
||||
|
@ -5194,7 +5283,9 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
|||
&& !info->shared
|
||||
&& h != NULL
|
||||
&& (h->root.type == bfd_link_hash_defweak
|
||||
|| !h->def_regular)))
|
||||
|| !h->def_regular))
|
||||
|| (!info->shared
|
||||
&& ifunc != NULL))
|
||||
{
|
||||
struct ppc_dyn_relocs *p;
|
||||
struct ppc_dyn_relocs **head;
|
||||
|
@ -7990,7 +8081,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||
for (pent = h->plt.plist; pent != NULL; pent = pent->next)
|
||||
if (pent->plt.refcount > 0)
|
||||
{
|
||||
if (!htab->elf.dynamic_sections_created)
|
||||
if (!htab->elf.dynamic_sections_created
|
||||
|| h->dynindx == -1)
|
||||
{
|
||||
s = htab->iplt;
|
||||
pent->plt.offset = s->size;
|
||||
|
@ -8069,12 +8161,14 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||
if (gent->got.refcount > 0)
|
||||
{
|
||||
bfd_boolean dyn;
|
||||
asection *rsec;
|
||||
|
||||
/* Make sure this symbol is output as a dynamic symbol.
|
||||
Undefined weak syms won't yet be marked as dynamic,
|
||||
nor will all TLS symbols. */
|
||||
if (h->dynindx == -1
|
||||
&& !h->forced_local
|
||||
&& h->type != STT_GNU_IFUNC
|
||||
&& htab->elf.dynamic_sections_created)
|
||||
{
|
||||
if (! bfd_elf_link_record_dynamic_symbol (info, h))
|
||||
|
@ -8097,20 +8191,25 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||
s->size
|
||||
+= (gent->tls_type & eh->tls_mask & (TLS_GD | TLS_LD)) ? 16 : 8;
|
||||
dyn = htab->elf.dynamic_sections_created;
|
||||
rsec = NULL;
|
||||
if ((info->shared
|
||||
|| WILL_CALL_FINISH_DYNAMIC_SYMBOL (dyn, 0, h))
|
||||
&& (ELF_ST_VISIBILITY (h->other) == STV_DEFAULT
|
||||
|| h->root.type != bfd_link_hash_undefweak))
|
||||
ppc64_elf_tdata (gent->owner)->relgot->size
|
||||
+= (gent->tls_type & eh->tls_mask & TLS_GD
|
||||
? 2 * sizeof (Elf64_External_Rela)
|
||||
: sizeof (Elf64_External_Rela));
|
||||
rsec = ppc64_elf_tdata (gent->owner)->relgot;
|
||||
else if (h->type == STT_GNU_IFUNC)
|
||||
rsec = htab->reliplt;
|
||||
if (rsec != NULL)
|
||||
rsec->size += (gent->tls_type & eh->tls_mask & TLS_GD
|
||||
? 2 * sizeof (Elf64_External_Rela)
|
||||
: sizeof (Elf64_External_Rela));
|
||||
}
|
||||
else
|
||||
gent->got.offset = (bfd_vma) -1;
|
||||
|
||||
if (eh->dyn_relocs == NULL
|
||||
|| !htab->elf.dynamic_sections_created)
|
||||
|| (!htab->elf.dynamic_sections_created
|
||||
&& h->type != STT_GNU_IFUNC))
|
||||
return TRUE;
|
||||
|
||||
/* In the shared -Bsymbolic case, discard space allocated for
|
||||
|
@ -8160,6 +8259,11 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||
}
|
||||
}
|
||||
}
|
||||
else if (h->type == STT_GNU_IFUNC)
|
||||
{
|
||||
if (!h->non_got_ref)
|
||||
eh->dyn_relocs = NULL;
|
||||
}
|
||||
else if (ELIMINATE_COPY_RELOCS)
|
||||
{
|
||||
/* For the non-shared case, discard space for relocs against
|
||||
|
@ -8193,6 +8297,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||
for (p = eh->dyn_relocs; p != NULL; p = p->next)
|
||||
{
|
||||
asection *sreloc = elf_section_data (p->sec)->sreloc;
|
||||
if (!htab->elf.dynamic_sections_created)
|
||||
sreloc = htab->reliplt;
|
||||
sreloc->size += p->count * sizeof (Elf64_External_Rela);
|
||||
}
|
||||
|
||||
|
@ -8291,6 +8397,8 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
|||
else if (p->count != 0)
|
||||
{
|
||||
srel = elf_section_data (p->sec)->sreloc;
|
||||
if (!htab->elf.dynamic_sections_created)
|
||||
srel = htab->reliplt;
|
||||
srel->size += p->count * sizeof (Elf64_External_Rela);
|
||||
if ((p->sec->output_section->flags & SEC_READONLY) != 0)
|
||||
info->flags |= DF_TEXTREL;
|
||||
|
@ -8324,19 +8432,15 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
|||
}
|
||||
else
|
||||
{
|
||||
unsigned int num = 1;
|
||||
ent->got.offset = s->size;
|
||||
if ((ent->tls_type & *lgot_masks & TLS_GD) != 0)
|
||||
{
|
||||
s->size += 16;
|
||||
if (info->shared)
|
||||
srel->size += 2 * sizeof (Elf64_External_Rela);
|
||||
}
|
||||
else
|
||||
{
|
||||
s->size += 8;
|
||||
if (info->shared)
|
||||
srel->size += sizeof (Elf64_External_Rela);
|
||||
}
|
||||
num = 2;
|
||||
s->size += num * 8;
|
||||
if (info->shared)
|
||||
srel->size += num * sizeof (Elf64_External_Rela);
|
||||
else if ((*lgot_masks & PLT_IFUNC) != 0)
|
||||
htab->reliplt->size += num * sizeof (Elf64_External_Rela);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -8356,7 +8460,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd ATTRIBUTE_UNUSED,
|
|||
ent->plt.offset = s->size;
|
||||
s->size += PLT_ENTRY_SIZE;
|
||||
|
||||
htab->reliplt += sizeof (Elf64_External_Rela);
|
||||
htab->reliplt->size += sizeof (Elf64_External_Rela);
|
||||
}
|
||||
else
|
||||
ent->plt.offset = (bfd_vma) -1;
|
||||
|
@ -9029,7 +9133,9 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
|||
abort ();
|
||||
|
||||
plt = htab->plt;
|
||||
if (!htab->elf.dynamic_sections_created)
|
||||
if (!htab->elf.dynamic_sections_created
|
||||
|| stub_entry->h == NULL
|
||||
|| stub_entry->h->elf.dynindx == -1)
|
||||
plt = htab->iplt;
|
||||
|
||||
dest += plt->output_offset + plt->output_section->vma;
|
||||
|
@ -9041,20 +9147,15 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
|||
bfd_byte *rl;
|
||||
|
||||
rela.r_offset = dest;
|
||||
rela.r_info = ELF64_R_INFO (0, R_PPC64_IRELATIVE);
|
||||
rela.r_info = ELF64_R_INFO (0, R_PPC64_JMP_IREL);
|
||||
rela.r_addend = (stub_entry->target_value
|
||||
+ stub_entry->target_section->output_offset
|
||||
+ stub_entry->target_section->output_section->vma);
|
||||
|
||||
if (!htab->elf.dynamic_sections_created)
|
||||
rl = (htab->reliplt->contents
|
||||
+ (stub_entry->plt_ent->plt.offset
|
||||
/ (PLT_ENTRY_SIZE / sizeof (Elf64_External_Rela))));
|
||||
else
|
||||
rl = (htab->relplt->contents
|
||||
+ ((stub_entry->plt_ent->plt.offset - PLT_INITIAL_ENTRY_SIZE)
|
||||
/ (PLT_ENTRY_SIZE / sizeof (Elf64_External_Rela))));
|
||||
bfd_elf32_swap_reloca_out (info->output_bfd, &rela, rl);
|
||||
rl = (htab->reliplt->contents
|
||||
+ (htab->reliplt->reloc_count++
|
||||
* sizeof (Elf64_External_Rela)));
|
||||
bfd_elf64_swap_reloca_out (info->output_bfd, &rela, rl);
|
||||
stub_entry->plt_ent->plt.offset |= 1;
|
||||
}
|
||||
|
||||
|
@ -9162,7 +9263,9 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
|||
if (off >= (bfd_vma) -2)
|
||||
abort ();
|
||||
plt = htab->plt;
|
||||
if (!htab->elf.dynamic_sections_created)
|
||||
if (!htab->elf.dynamic_sections_created
|
||||
|| stub_entry->h == NULL
|
||||
|| stub_entry->h->elf.dynindx == -1)
|
||||
plt = htab->iplt;
|
||||
off += (plt->output_offset
|
||||
+ plt->output_section->vma
|
||||
|
@ -11093,7 +11196,9 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||
&& sec->output_section != NULL
|
||||
&& sec->id <= htab->top_id
|
||||
&& (htab->stub_group[sec->id].toc_off
|
||||
!= htab->stub_group[input_section->id].toc_off)))
|
||||
!= htab->stub_group[input_section->id].toc_off))
|
||||
|| (h == NULL
|
||||
&& ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC))
|
||||
&& (stub_entry = ppc_get_stub_entry (input_section, sec, fdh,
|
||||
rel, htab)) != NULL
|
||||
&& (stub_entry->stub_type == ppc_stub_plt_call
|
||||
|
@ -11377,14 +11482,23 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||
/* Generate relocs for the dynamic linker, except in
|
||||
the case of TLSLD where we'll use one entry per
|
||||
module. */
|
||||
asection *relgot = ppc64_elf_tdata (input_bfd)->relgot;
|
||||
asection *relgot;
|
||||
bfd_boolean ifunc;
|
||||
|
||||
*offp = off | 1;
|
||||
relgot = NULL;
|
||||
ifunc = (h != NULL
|
||||
? h->elf.type == STT_GNU_IFUNC
|
||||
: ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC);
|
||||
if ((info->shared || indx != 0)
|
||||
&& (offp == &ppc64_tlsld_got (input_bfd)->offset
|
||||
|| h == NULL
|
||||
|| ELF_ST_VISIBILITY (h->elf.other) == STV_DEFAULT
|
||||
|| h->elf.root.type != bfd_link_hash_undefweak))
|
||||
relgot = ppc64_elf_tdata (input_bfd)->relgot;
|
||||
else if (ifunc)
|
||||
relgot = htab->reliplt;
|
||||
if (relgot != NULL)
|
||||
{
|
||||
outrel.r_offset = (got->output_section->vma
|
||||
+ got->output_offset
|
||||
|
@ -11411,9 +11525,14 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||
outrel.r_info = ELF64_R_INFO (indx, R_PPC64_DTPREL64);
|
||||
else if (tls_type == (TLS_TLS | TLS_TPREL))
|
||||
outrel.r_info = ELF64_R_INFO (indx, R_PPC64_TPREL64);
|
||||
else if (indx == 0)
|
||||
else if (indx != 0)
|
||||
outrel.r_info = ELF64_R_INFO (indx, R_PPC64_GLOB_DAT);
|
||||
else
|
||||
{
|
||||
outrel.r_info = ELF64_R_INFO (indx, R_PPC64_RELATIVE);
|
||||
if (ifunc)
|
||||
outrel.r_info = ELF64_R_INFO (0, R_PPC64_IRELATIVE);
|
||||
else
|
||||
outrel.r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE);
|
||||
|
||||
/* Write the .got section contents for the sake
|
||||
of prelink. */
|
||||
|
@ -11421,8 +11540,6 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||
bfd_put_64 (output_bfd, outrel.r_addend + relocation,
|
||||
loc);
|
||||
}
|
||||
else
|
||||
outrel.r_info = ELF64_R_INFO (indx, R_PPC64_GLOB_DAT);
|
||||
|
||||
if (indx == 0 && tls_type != (TLS_TLS | TLS_LD))
|
||||
{
|
||||
|
@ -11541,6 +11658,12 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||
addend -= sec->output_section->vma;
|
||||
break;
|
||||
|
||||
case R_PPC64_REL16:
|
||||
case R_PPC64_REL16_LO:
|
||||
case R_PPC64_REL16_HI:
|
||||
case R_PPC64_REL16_HA:
|
||||
break;
|
||||
|
||||
case R_PPC64_REL14:
|
||||
case R_PPC64_REL14_BRNTAKEN:
|
||||
case R_PPC64_REL14_BRTAKEN:
|
||||
|
@ -11633,7 +11756,11 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||
&& h != NULL
|
||||
&& h->elf.dynindx != -1
|
||||
&& !h->elf.non_got_ref
|
||||
&& !h->elf.def_regular))
|
||||
&& !h->elf.def_regular)
|
||||
|| (!info->shared
|
||||
&& (h != NULL
|
||||
? h->elf.type == STT_GNU_IFUNC
|
||||
: ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)))
|
||||
{
|
||||
Elf_Internal_Rela outrel;
|
||||
bfd_boolean skip, relocate;
|
||||
|
@ -11698,19 +11825,42 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||
entry in this lib. */
|
||||
unresolved_reloc = FALSE;
|
||||
}
|
||||
outrel.r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE);
|
||||
if (!is_opd
|
||||
&& r_type == R_PPC64_ADDR64
|
||||
&& (h != NULL
|
||||
? h->elf.type == STT_GNU_IFUNC
|
||||
: ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC))
|
||||
outrel.r_info = ELF64_R_INFO (0, R_PPC64_IRELATIVE);
|
||||
else
|
||||
{
|
||||
outrel.r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE);
|
||||
|
||||
/* We need to relocate .opd contents for ld.so.
|
||||
Prelink also wants simple and consistent rules
|
||||
for relocs. This make all RELATIVE relocs have
|
||||
*r_offset equal to r_addend. */
|
||||
relocate = TRUE;
|
||||
/* We need to relocate .opd contents for ld.so.
|
||||
Prelink also wants simple and consistent rules
|
||||
for relocs. This make all RELATIVE relocs have
|
||||
*r_offset equal to r_addend. */
|
||||
relocate = TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
long indx = 0;
|
||||
|
||||
if (r_symndx == 0 || bfd_is_abs_section (sec))
|
||||
if (h != NULL
|
||||
? h->elf.type == STT_GNU_IFUNC
|
||||
: ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
|
||||
{
|
||||
(*_bfd_error_handler)
|
||||
(_("%B(%A+0x%lx): relocation %s for indirect "
|
||||
"function %s unsupported"),
|
||||
input_bfd,
|
||||
input_section,
|
||||
(long) rel->r_offset,
|
||||
ppc64_elf_howto_table[r_type]->name,
|
||||
sym_name);
|
||||
ret = FALSE;
|
||||
}
|
||||
else if (r_symndx == 0 || bfd_is_abs_section (sec))
|
||||
;
|
||||
else if (sec == NULL || sec->owner == NULL)
|
||||
{
|
||||
|
@ -11748,6 +11898,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||
}
|
||||
|
||||
sreloc = elf_section_data (input_section)->sreloc;
|
||||
if (!htab->elf.dynamic_sections_created)
|
||||
sreloc = htab->reliplt;
|
||||
if (sreloc == NULL)
|
||||
abort ();
|
||||
|
||||
|
@ -11789,6 +11941,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||
case R_PPC64_COPY:
|
||||
case R_PPC64_GLOB_DAT:
|
||||
case R_PPC64_JMP_SLOT:
|
||||
case R_PPC64_JMP_IREL:
|
||||
case R_PPC64_RELATIVE:
|
||||
/* We shouldn't ever see these dynamic relocs in relocatable
|
||||
files. */
|
||||
|
@ -11821,6 +11974,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||
break;
|
||||
|
||||
case R_PPC64_ADDR16_HA:
|
||||
case R_PPC64_REL16_HA:
|
||||
case R_PPC64_ADDR16_HIGHERA:
|
||||
case R_PPC64_ADDR16_HIGHESTA:
|
||||
case R_PPC64_TOC16_HA:
|
||||
|
@ -12037,14 +12191,6 @@ ppc64_elf_finish_dynamic_symbol (bfd *output_bfd,
|
|||
{
|
||||
/* This symbol has an entry in the procedure linkage
|
||||
table. Set it up. */
|
||||
asection *plt = htab->plt;
|
||||
if (!htab->elf.dynamic_sections_created)
|
||||
plt = htab->iplt;
|
||||
|
||||
rela.r_offset = (plt->output_section->vma
|
||||
+ plt->output_offset
|
||||
+ ent->plt.offset);
|
||||
|
||||
if (!htab->elf.dynamic_sections_created
|
||||
|| h->dynindx == -1)
|
||||
{
|
||||
|
@ -12052,26 +12198,29 @@ ppc64_elf_finish_dynamic_symbol (bfd *output_bfd,
|
|||
&& h->def_regular
|
||||
&& (h->root.type == bfd_link_hash_defined
|
||||
|| h->root.type == bfd_link_hash_defweak));
|
||||
rela.r_info = ELF64_R_INFO (0, R_PPC64_IRELATIVE);
|
||||
rela.r_offset = (htab->iplt->output_section->vma
|
||||
+ htab->iplt->output_offset
|
||||
+ ent->plt.offset);
|
||||
rela.r_info = ELF64_R_INFO (0, R_PPC64_JMP_IREL);
|
||||
rela.r_addend = (h->root.u.def.value
|
||||
+ h->root.u.def.section->output_offset
|
||||
+ h->root.u.def.section->output_section->vma
|
||||
+ ent->addend);
|
||||
loc = (htab->reliplt->contents
|
||||
+ (htab->reliplt->reloc_count++
|
||||
* sizeof (Elf64_External_Rela)));
|
||||
}
|
||||
else
|
||||
{
|
||||
rela.r_offset = (htab->plt->output_section->vma
|
||||
+ htab->plt->output_offset
|
||||
+ ent->plt.offset);
|
||||
rela.r_info = ELF64_R_INFO (h->dynindx, R_PPC64_JMP_SLOT);
|
||||
rela.r_addend = ent->addend;
|
||||
loc = (htab->relplt->contents
|
||||
+ ((ent->plt.offset - PLT_INITIAL_ENTRY_SIZE)
|
||||
/ (PLT_ENTRY_SIZE / sizeof (Elf64_External_Rela))));
|
||||
}
|
||||
|
||||
if (!htab->elf.dynamic_sections_created)
|
||||
loc = (htab->reliplt->contents
|
||||
+ (ent->plt.offset
|
||||
/ (PLT_ENTRY_SIZE / sizeof (Elf64_External_Rela))));
|
||||
else
|
||||
loc = (htab->relplt->contents
|
||||
+ ((ent->plt.offset - PLT_INITIAL_ENTRY_SIZE)
|
||||
/ (PLT_ENTRY_SIZE / sizeof (Elf64_External_Rela))));
|
||||
bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue