Support PLT16 relocs against local symbols
Necessary if gcc is to use PLT16 relocs to implement -mlongcall, and there isn't a good technical reason why local symbols should be excluded from PLT16 support. Non-ifunc local symbol PLT entries go in a separate section to other PLT entries. In a fixed position executable they won't need to be relocated, and in a PIE or shared library I chose to not implement lazy relocation. bfd/ * elf64-ppc.c (LOCAL_PLT_ENTRY_SIZE): Define. (struct ppc_stub_hash_entry): Add symtype field. (PLT_KEEP): Define. (struct ppc_link_hash_table): Add pltlocal and relpltlocal. (create_linkage_sections): Create pltlocal and relpltlocal. (ppc64_elf_check_relocs): Allow PLT relocs on local symbols. Set PLT_KEEP. (ppc64_elf_adjust_dynamic_symbol): Keep PLT entries for inline calls. (allocate_dynrelocs): Allocate pltlocal and relpltlocal. (ppc64_elf_size_dynamic_sections): Size pltlocal and relpltlocal. Keep PLT entries for inline calls against locals. (ppc_build_one_stub): Use pltlocal as appropriate. (ppc_size_one_stub): Likewise. (ppc64_elf_size_stubs): Set symtype. (build_global_entry_stubs_and_plt): Init pltlocal and write relpltlocal for globals. (write_plt_relocs_for_local_syms): Likewise for local syms. (ppc64_elf_relocate_section): Support PLT for local syms. * elf32-ppc.c (PLT_KEEP): Define. (struct ppc_elf_link_hash_table): Add pltlocal and relpltlocal. (ppc_elf_create_glink): Create pltlocal and relpltlocal. (ppc_elf_check_relocs): Allow PLT relocs on local symbols. Set PLT_KEEP. Adjust update_local_sym_info call. (ppc_elf_adjust_dynamic_symbol): Keep PLT entries for inline calls. (allocate_dynrelocs): Allocate pltlocal and relpltlocal. (ppc_elf_size_dynamic_sections): Size pltlocal and relpltlocal. (ppc_elf_relocate_section): Support PLT16 relocs for local syms. (write_global_sym_plt): Init pltlocal and write relpltlocal. (ppc_finish_symbols): Likewise for locals. ld/ * emulparams/elf32ppc.sh (OTHER_RELRO_SECTIONS_2): Add .branch_lt. (OTHER_GOT_RELOC_SECTIONS): Add .rela.branch_lt. * testsuite/ld-powerpc/elfv2so.d: Update for symbol/stub reordering. * testsuite/ld-powerpc/relbrlt.d: Likewise. * testsuite/ld-powerpc/relbrlt.s: Likewise. * testsuite/ld-powerpc/tlsso.r: Likewise. * testsuite/ld-powerpc/tlstocso.r: Likewise. gold/ * powerpc.cc (Target_powerpc::lplt_): New variable. (Target_powerpc::lplt_section): Associated accessor. (Target_powerpc::plt_off): Handle local non-ifunc symbols. (Target_powerpc::make_lplt_section): New function. (Target_powerpc::make_local_plt_entry): New function. (Powerpc_relobj::do_relocate_sections): Write out lplt. (Output_data_plt_powerpc::first_plt_entry_offset): Zero for lplt. (Output_data_plt_powerpc::add_local_entry): New function. (Output_data_plt_powerpc::do_write): Ignore lplt. (Target_powerpc::make_iplt_section): Make lplt first. (Target_powerpc::make_brlt_section): Make .branch_lt relro. (Target_powerpc::Scan::local): Handle PLT16 relocs.
This commit is contained in:
parent
49c09209d0
commit
2d7ad24e87
@ -1,3 +1,35 @@
|
|||||||
|
2018-04-09 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
|
* elf64-ppc.c (LOCAL_PLT_ENTRY_SIZE): Define.
|
||||||
|
(struct ppc_stub_hash_entry): Add symtype field.
|
||||||
|
(PLT_KEEP): Define.
|
||||||
|
(struct ppc_link_hash_table): Add pltlocal and relpltlocal.
|
||||||
|
(create_linkage_sections): Create pltlocal and relpltlocal.
|
||||||
|
(ppc64_elf_check_relocs): Allow PLT relocs on local symbols.
|
||||||
|
Set PLT_KEEP.
|
||||||
|
(ppc64_elf_adjust_dynamic_symbol): Keep PLT entries for inline calls.
|
||||||
|
(allocate_dynrelocs): Allocate pltlocal and relpltlocal.
|
||||||
|
(ppc64_elf_size_dynamic_sections): Size pltlocal and relpltlocal.
|
||||||
|
Keep PLT entries for inline calls against locals.
|
||||||
|
(ppc_build_one_stub): Use pltlocal as appropriate.
|
||||||
|
(ppc_size_one_stub): Likewise.
|
||||||
|
(ppc64_elf_size_stubs): Set symtype.
|
||||||
|
(build_global_entry_stubs_and_plt): Init pltlocal and write
|
||||||
|
relpltlocal for globals.
|
||||||
|
(write_plt_relocs_for_local_syms): Likewise for local syms.
|
||||||
|
(ppc64_elf_relocate_section): Support PLT for local syms.
|
||||||
|
* elf32-ppc.c (PLT_KEEP): Define.
|
||||||
|
(struct ppc_elf_link_hash_table): Add pltlocal and relpltlocal.
|
||||||
|
(ppc_elf_create_glink): Create pltlocal and relpltlocal.
|
||||||
|
(ppc_elf_check_relocs): Allow PLT relocs on local symbols.
|
||||||
|
Set PLT_KEEP. Adjust update_local_sym_info call.
|
||||||
|
(ppc_elf_adjust_dynamic_symbol): Keep PLT entries for inline calls.
|
||||||
|
(allocate_dynrelocs): Allocate pltlocal and relpltlocal.
|
||||||
|
(ppc_elf_size_dynamic_sections): Size pltlocal and relpltlocal.
|
||||||
|
(ppc_elf_relocate_section): Support PLT16 relocs for local syms.
|
||||||
|
(write_global_sym_plt): Init pltlocal and write relpltlocal.
|
||||||
|
(ppc_finish_symbols): Likewise for locals.
|
||||||
|
|
||||||
2018-04-09 Alan Modra <amodra@gmail.com>
|
2018-04-09 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
* elf64-ppc.c (ppc_build_one_stub): Move output of PLT relocs
|
* elf64-ppc.c (ppc_build_one_stub): Move output of PLT relocs
|
||||||
|
388
bfd/elf32-ppc.c
388
bfd/elf32-ppc.c
@ -3248,6 +3248,7 @@ struct ppc_elf_link_hash_entry
|
|||||||
/* The above field is also used to mark function symbols. In which
|
/* The above field is also used to mark function symbols. In which
|
||||||
case TLS_TLS will be 0. */
|
case TLS_TLS will be 0. */
|
||||||
#define PLT_IFUNC 2 /* STT_GNU_IFUNC. */
|
#define PLT_IFUNC 2 /* STT_GNU_IFUNC. */
|
||||||
|
#define PLT_KEEP 4 /* inline plt call requires plt entry. */
|
||||||
#define NON_GOT 256 /* local symbol plt, not stored. */
|
#define NON_GOT 256 /* local symbol plt, not stored. */
|
||||||
|
|
||||||
/* Nonzero if we have seen a small data relocation referring to this
|
/* Nonzero if we have seen a small data relocation referring to this
|
||||||
@ -3277,6 +3278,8 @@ struct ppc_elf_link_hash_table
|
|||||||
elf_linker_section_t sdata[2];
|
elf_linker_section_t sdata[2];
|
||||||
asection *sbss;
|
asection *sbss;
|
||||||
asection *glink_eh_frame;
|
asection *glink_eh_frame;
|
||||||
|
asection *pltlocal;
|
||||||
|
asection *relpltlocal;
|
||||||
|
|
||||||
/* The (unloaded but important) .rela.plt.unloaded on VxWorks. */
|
/* The (unloaded but important) .rela.plt.unloaded on VxWorks. */
|
||||||
asection *srelplt2;
|
asection *srelplt2;
|
||||||
@ -3526,6 +3529,26 @@ ppc_elf_create_glink (bfd *abfd, struct bfd_link_info *info)
|
|||||||
|| ! bfd_set_section_alignment (abfd, s, 2))
|
|| ! bfd_set_section_alignment (abfd, s, 2))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
/* Local plt entries. */
|
||||||
|
flags = (SEC_ALLOC | SEC_LOAD
|
||||||
|
| SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
|
||||||
|
htab->pltlocal = bfd_make_section_anyway_with_flags (abfd, ".branch_lt",
|
||||||
|
flags);
|
||||||
|
if (htab->pltlocal == NULL
|
||||||
|
|| ! bfd_set_section_alignment (abfd, htab->pltlocal, 2))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (bfd_link_pic (info))
|
||||||
|
{
|
||||||
|
flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
|
||||||
|
| SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
|
||||||
|
htab->relpltlocal
|
||||||
|
= bfd_make_section_anyway_with_flags (abfd, ".rela.branch_lt", flags);
|
||||||
|
if (htab->relpltlocal == NULL
|
||||||
|
|| ! bfd_set_section_alignment (abfd, htab->relpltlocal, 2))
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
if (!ppc_elf_create_linker_section (abfd, info, 0,
|
if (!ppc_elf_create_linker_section (abfd, info, 0,
|
||||||
&htab->sdata[0]))
|
&htab->sdata[0]))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -4008,6 +4031,8 @@ ppc_elf_check_relocs (bfd *abfd,
|
|||||||
struct elf_link_hash_entry *h;
|
struct elf_link_hash_entry *h;
|
||||||
int tls_type;
|
int tls_type;
|
||||||
struct plt_entry **ifunc;
|
struct plt_entry **ifunc;
|
||||||
|
struct plt_entry **pltent;
|
||||||
|
bfd_vma addend;
|
||||||
|
|
||||||
r_symndx = ELF32_R_SYM (rel->r_info);
|
r_symndx = ELF32_R_SYM (rel->r_info);
|
||||||
if (r_symndx < symtab_hdr->sh_info)
|
if (r_symndx < symtab_hdr->sh_info)
|
||||||
@ -4061,7 +4086,7 @@ ppc_elf_check_relocs (bfd *abfd,
|
|||||||
|| r_type == R_PPC_PLT16_HI
|
|| r_type == R_PPC_PLT16_HI
|
||||||
|| r_type == R_PPC_PLT16_HA)
|
|| r_type == R_PPC_PLT16_HA)
|
||||||
{
|
{
|
||||||
bfd_vma addend = 0;
|
addend = 0;
|
||||||
if (r_type == R_PPC_PLTREL24)
|
if (r_type == R_PPC_PLTREL24)
|
||||||
ppc_elf_tdata (abfd)->makes_plt_call = 1;
|
ppc_elf_tdata (abfd)->makes_plt_call = 1;
|
||||||
if (bfd_link_pic (info)
|
if (bfd_link_pic (info)
|
||||||
@ -4296,33 +4321,27 @@ ppc_elf_check_relocs (bfd *abfd,
|
|||||||
/* This symbol requires a procedure linkage table entry. */
|
/* This symbol requires a procedure linkage table entry. */
|
||||||
if (h == NULL)
|
if (h == NULL)
|
||||||
{
|
{
|
||||||
if (ifunc == NULL)
|
pltent = update_local_sym_info (abfd, symtab_hdr, r_symndx,
|
||||||
{
|
NON_GOT | PLT_KEEP);
|
||||||
/* It does not make sense to have a procedure linkage
|
if (pltent == NULL)
|
||||||
table entry for a non-ifunc local symbol. */
|
return FALSE;
|
||||||
info->callbacks->einfo
|
|
||||||
/* xgettext:c-format */
|
|
||||||
(_("%H: %s reloc against local symbol\n"),
|
|
||||||
abfd, sec, rel->r_offset,
|
|
||||||
ppc_elf_howto_table[r_type]->name);
|
|
||||||
bfd_set_error (bfd_error_bad_value);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bfd_vma addend = 0;
|
if (r_type != R_PPC_PLTREL24)
|
||||||
|
ppc_elf_hash_entry (h)->tls_mask |= PLT_KEEP;
|
||||||
if (bfd_link_pic (info)
|
|
||||||
&& (r_type == R_PPC_PLTREL24
|
|
||||||
|| r_type == R_PPC_PLT16_LO
|
|
||||||
|| r_type == R_PPC_PLT16_HI
|
|
||||||
|| r_type == R_PPC_PLT16_HA))
|
|
||||||
addend = rel->r_addend;
|
|
||||||
h->needs_plt = 1;
|
h->needs_plt = 1;
|
||||||
if (!update_plt_info (abfd, &h->plt.plist, got2, addend))
|
pltent = &h->plt.plist;
|
||||||
return FALSE;
|
|
||||||
}
|
}
|
||||||
|
addend = 0;
|
||||||
|
if (bfd_link_pic (info)
|
||||||
|
&& (r_type == R_PPC_PLTREL24
|
||||||
|
|| r_type == R_PPC_PLT16_LO
|
||||||
|
|| r_type == R_PPC_PLT16_HI
|
||||||
|
|| r_type == R_PPC_PLT16_HA))
|
||||||
|
addend = rel->r_addend;
|
||||||
|
if (!update_plt_info (abfd, pltent, got2, addend))
|
||||||
|
return FALSE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
/* The following relocations don't need to propagate the
|
/* The following relocations don't need to propagate the
|
||||||
@ -5617,7 +5636,10 @@ ppc_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
|
|||||||
if (ent->plt.refcount > 0)
|
if (ent->plt.refcount > 0)
|
||||||
break;
|
break;
|
||||||
if (ent == NULL
|
if (ent == NULL
|
||||||
|| (h->type != STT_GNU_IFUNC && local))
|
|| (h->type != STT_GNU_IFUNC
|
||||||
|
&& local
|
||||||
|
&& ((ppc_elf_hash_entry (h)->tls_mask & (TLS_TLS | PLT_KEEP))
|
||||||
|
!= PLT_KEEP)))
|
||||||
{
|
{
|
||||||
/* A PLT entry is not required/allowed when:
|
/* A PLT entry is not required/allowed when:
|
||||||
|
|
||||||
@ -6103,13 +6125,25 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||||||
sreloc->size += p->count * sizeof (Elf32_External_Rela);
|
sreloc->size += p->count * sizeof (Elf32_External_Rela);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle PLT relocs. Done last, after dynindx has settled. */
|
/* Handle PLT relocs. Done last, after dynindx has settled.
|
||||||
|
We might need a PLT entry when the symbol
|
||||||
|
a) is dynamic, or
|
||||||
|
b) is an ifunc, or
|
||||||
|
c) has plt16 relocs and has been processed by adjust_dynamic_symbol, or
|
||||||
|
d) has plt16 relocs and we are linking statically. */
|
||||||
dyn = htab->elf.dynamic_sections_created && h->dynindx != -1;
|
dyn = htab->elf.dynamic_sections_created && h->dynindx != -1;
|
||||||
if (dyn || h->type == STT_GNU_IFUNC)
|
if (dyn
|
||||||
|
|| h->type == STT_GNU_IFUNC
|
||||||
|
|| (h->needs_plt && h->dynamic_adjusted)
|
||||||
|
|| (h->needs_plt
|
||||||
|
&& h->def_regular
|
||||||
|
&& !htab->elf.dynamic_sections_created
|
||||||
|
&& (ppc_elf_hash_entry (h)->tls_mask
|
||||||
|
& (TLS_TLS | PLT_KEEP)) == PLT_KEEP))
|
||||||
{
|
{
|
||||||
struct plt_entry *ent;
|
struct plt_entry *ent;
|
||||||
bfd_boolean doneone = FALSE;
|
bfd_boolean doneone = FALSE;
|
||||||
bfd_vma plt_offset = 0, glink_offset = 0;
|
bfd_vma plt_offset = 0, glink_offset = (bfd_vma) -1;
|
||||||
|
|
||||||
for (ent = h->plt.plist; ent != NULL; ent = ent->next)
|
for (ent = h->plt.plist; ent != NULL; ent = ent->next)
|
||||||
if (ent->plt.refcount > 0)
|
if (ent->plt.refcount > 0)
|
||||||
@ -6117,7 +6151,12 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||||||
asection *s = htab->elf.splt;
|
asection *s = htab->elf.splt;
|
||||||
|
|
||||||
if (!dyn)
|
if (!dyn)
|
||||||
s = htab->elf.iplt;
|
{
|
||||||
|
if (h->type == STT_GNU_IFUNC)
|
||||||
|
s = htab->elf.iplt;
|
||||||
|
else
|
||||||
|
s = htab->pltlocal;
|
||||||
|
}
|
||||||
|
|
||||||
if (htab->plt_type == PLT_NEW || !dyn)
|
if (htab->plt_type == PLT_NEW || !dyn)
|
||||||
{
|
{
|
||||||
@ -6128,25 +6167,30 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||||||
}
|
}
|
||||||
ent->plt.offset = plt_offset;
|
ent->plt.offset = plt_offset;
|
||||||
|
|
||||||
s = htab->glink;
|
if (s == htab->pltlocal)
|
||||||
if (!doneone || bfd_link_pic (info))
|
ent->glink_offset = glink_offset;
|
||||||
|
else
|
||||||
{
|
{
|
||||||
glink_offset = s->size;
|
s = htab->glink;
|
||||||
s->size += GLINK_ENTRY_SIZE (htab, h);
|
if (!doneone || bfd_link_pic (info))
|
||||||
}
|
{
|
||||||
if (!doneone
|
glink_offset = s->size;
|
||||||
&& !bfd_link_pic (info)
|
s->size += GLINK_ENTRY_SIZE (htab, h);
|
||||||
&& h->def_dynamic
|
}
|
||||||
&& !h->def_regular)
|
if (!doneone
|
||||||
{
|
&& !bfd_link_pic (info)
|
||||||
h->root.u.def.section = s;
|
&& h->def_dynamic
|
||||||
h->root.u.def.value = glink_offset;
|
&& !h->def_regular)
|
||||||
}
|
{
|
||||||
ent->glink_offset = glink_offset;
|
h->root.u.def.section = s;
|
||||||
|
h->root.u.def.value = glink_offset;
|
||||||
|
}
|
||||||
|
ent->glink_offset = glink_offset;
|
||||||
|
|
||||||
if (htab->params->emit_stub_syms
|
if (htab->params->emit_stub_syms
|
||||||
&& !add_stub_sym (ent, h, info))
|
&& !add_stub_sym (ent, h, info))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -6199,7 +6243,18 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||||||
if (!doneone)
|
if (!doneone)
|
||||||
{
|
{
|
||||||
if (!dyn)
|
if (!dyn)
|
||||||
htab->elf.irelplt->size += sizeof (Elf32_External_Rela);
|
{
|
||||||
|
if (h->type == STT_GNU_IFUNC)
|
||||||
|
{
|
||||||
|
s = htab->elf.irelplt;
|
||||||
|
s->size += sizeof (Elf32_External_Rela);
|
||||||
|
}
|
||||||
|
else if (bfd_link_pic (info))
|
||||||
|
{
|
||||||
|
s = htab->relpltlocal;
|
||||||
|
s->size += sizeof (Elf32_External_Rela);
|
||||||
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
htab->elf.srelplt->size += sizeof (Elf32_External_Rela);
|
htab->elf.srelplt->size += sizeof (Elf32_External_Rela);
|
||||||
@ -6425,16 +6480,25 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Allocate space for calls to local STT_GNU_IFUNC syms in .iplt. */
|
/* Allocate space for calls to local STT_GNU_IFUNC syms in .iplt. */
|
||||||
for (; local_plt < end_local_plt; ++local_plt)
|
lgot_masks = (char *) end_local_plt;
|
||||||
|
for (; local_plt < end_local_plt; ++local_plt, ++lgot_masks)
|
||||||
{
|
{
|
||||||
struct plt_entry *ent;
|
struct plt_entry *ent;
|
||||||
bfd_boolean doneone = FALSE;
|
bfd_boolean doneone = FALSE;
|
||||||
bfd_vma plt_offset = 0, glink_offset = 0;
|
bfd_vma plt_offset = 0, glink_offset = (bfd_vma) -1;
|
||||||
|
|
||||||
for (ent = *local_plt; ent != NULL; ent = ent->next)
|
for (ent = *local_plt; ent != NULL; ent = ent->next)
|
||||||
if (ent->plt.refcount > 0)
|
if (ent->plt.refcount > 0)
|
||||||
{
|
{
|
||||||
s = htab->elf.iplt;
|
if ((*lgot_masks & (TLS_TLS | PLT_IFUNC)) == PLT_IFUNC)
|
||||||
|
s = htab->elf.iplt;
|
||||||
|
else if ((*lgot_masks & (TLS_TLS | PLT_KEEP)) != PLT_KEEP)
|
||||||
|
{
|
||||||
|
ent->plt.offset = (bfd_vma) -1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
s = htab->pltlocal;
|
||||||
|
|
||||||
if (!doneone)
|
if (!doneone)
|
||||||
{
|
{
|
||||||
@ -6443,9 +6507,9 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
|
|||||||
}
|
}
|
||||||
ent->plt.offset = plt_offset;
|
ent->plt.offset = plt_offset;
|
||||||
|
|
||||||
s = htab->glink;
|
if (s != htab->pltlocal && (!doneone || bfd_link_pic (info)))
|
||||||
if (!doneone || bfd_link_pic (info))
|
|
||||||
{
|
{
|
||||||
|
s = htab->glink;
|
||||||
glink_offset = s->size;
|
glink_offset = s->size;
|
||||||
s->size += GLINK_ENTRY_SIZE (htab, NULL);
|
s->size += GLINK_ENTRY_SIZE (htab, NULL);
|
||||||
}
|
}
|
||||||
@ -6453,7 +6517,16 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
|
|||||||
|
|
||||||
if (!doneone)
|
if (!doneone)
|
||||||
{
|
{
|
||||||
htab->elf.irelplt->size += sizeof (Elf32_External_Rela);
|
if ((*lgot_masks & (TLS_TLS | PLT_IFUNC)) == PLT_IFUNC)
|
||||||
|
{
|
||||||
|
s = htab->elf.irelplt;
|
||||||
|
s->size += sizeof (Elf32_External_Rela);
|
||||||
|
}
|
||||||
|
else if (bfd_link_pic (info))
|
||||||
|
{
|
||||||
|
s = htab->relpltlocal;
|
||||||
|
s->size += sizeof (Elf32_External_Rela);
|
||||||
|
}
|
||||||
doneone = TRUE;
|
doneone = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6599,6 +6672,7 @@ ppc_elf_size_dynamic_sections (bfd *output_bfd,
|
|||||||
comment below. */
|
comment below. */
|
||||||
}
|
}
|
||||||
else if (s == htab->elf.iplt
|
else if (s == htab->elf.iplt
|
||||||
|
|| s == htab->pltlocal
|
||||||
|| s == htab->glink
|
|| s == htab->glink
|
||||||
|| s == htab->glink_eh_frame
|
|| s == htab->glink_eh_frame
|
||||||
|| s == htab->elf.sgotplt
|
|| s == htab->elf.sgotplt
|
||||||
@ -9173,9 +9247,18 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||||||
case R_PPC_PLT16_LO:
|
case R_PPC_PLT16_LO:
|
||||||
case R_PPC_PLT16_HI:
|
case R_PPC_PLT16_HI:
|
||||||
case R_PPC_PLT16_HA:
|
case R_PPC_PLT16_HA:
|
||||||
plt_list = ifunc;
|
plt_list = NULL;
|
||||||
if (h != NULL)
|
if (h != NULL)
|
||||||
plt_list = &h->plt.plist;
|
plt_list = &h->plt.plist;
|
||||||
|
else if (ifunc != NULL)
|
||||||
|
plt_list = ifunc;
|
||||||
|
else if (local_got_offsets != NULL)
|
||||||
|
{
|
||||||
|
struct plt_entry **local_plt;
|
||||||
|
local_plt = (struct plt_entry **) (local_got_offsets
|
||||||
|
+ symtab_hdr->sh_info);
|
||||||
|
plt_list = local_plt + r_symndx;
|
||||||
|
}
|
||||||
unresolved_reloc = TRUE;
|
unresolved_reloc = TRUE;
|
||||||
if (plt_list != NULL)
|
if (plt_list != NULL)
|
||||||
{
|
{
|
||||||
@ -9183,11 +9266,23 @@ ppc_elf_relocate_section (bfd *output_bfd,
|
|||||||
|
|
||||||
ent = find_plt_ent (plt_list, got2,
|
ent = find_plt_ent (plt_list, got2,
|
||||||
bfd_link_pic (info) ? addend : 0);
|
bfd_link_pic (info) ? addend : 0);
|
||||||
if (ent != NULL)
|
if (ent != NULL && ent->plt.offset != (bfd_vma) -1)
|
||||||
{
|
{
|
||||||
|
asection *plt;
|
||||||
|
|
||||||
unresolved_reloc = FALSE;
|
unresolved_reloc = FALSE;
|
||||||
relocation = (htab->elf.splt->output_section->vma
|
plt = htab->elf.splt;
|
||||||
+ htab->elf.splt->output_offset
|
if (!htab->elf.dynamic_sections_created
|
||||||
|
|| h == NULL
|
||||||
|
|| h->dynindx == -1)
|
||||||
|
{
|
||||||
|
if (ifunc != NULL)
|
||||||
|
plt = htab->elf.iplt;
|
||||||
|
else
|
||||||
|
plt = htab->pltlocal;
|
||||||
|
}
|
||||||
|
relocation = (plt->output_section->vma
|
||||||
|
+ plt->output_offset
|
||||||
+ ent->plt.offset);
|
+ ent->plt.offset);
|
||||||
if (bfd_link_pic (info))
|
if (bfd_link_pic (info))
|
||||||
{
|
{
|
||||||
@ -10085,6 +10180,8 @@ write_global_sym_plt (struct elf_link_hash_entry *h, void *inf)
|
|||||||
Elf_Internal_Rela rela;
|
Elf_Internal_Rela rela;
|
||||||
bfd_byte *loc;
|
bfd_byte *loc;
|
||||||
bfd_vma reloc_index;
|
bfd_vma reloc_index;
|
||||||
|
asection *plt = htab->elf.splt;
|
||||||
|
asection *relplt = htab->elf.srelplt;
|
||||||
|
|
||||||
if (htab->plt_type == PLT_NEW
|
if (htab->plt_type == PLT_NEW
|
||||||
|| !htab->elf.dynamic_sections_created
|
|| !htab->elf.dynamic_sections_created
|
||||||
@ -10120,10 +10217,10 @@ write_global_sym_plt (struct elf_link_hash_entry *h, void *inf)
|
|||||||
{
|
{
|
||||||
bfd_put_32 (info->output_bfd,
|
bfd_put_32 (info->output_bfd,
|
||||||
plt_entry[0] | PPC_HA (got_offset),
|
plt_entry[0] | PPC_HA (got_offset),
|
||||||
htab->elf.splt->contents + ent->plt.offset + 0);
|
plt->contents + ent->plt.offset + 0);
|
||||||
bfd_put_32 (info->output_bfd,
|
bfd_put_32 (info->output_bfd,
|
||||||
plt_entry[1] | PPC_LO (got_offset),
|
plt_entry[1] | PPC_LO (got_offset),
|
||||||
htab->elf.splt->contents + ent->plt.offset + 4);
|
plt->contents + ent->plt.offset + 4);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -10131,16 +10228,16 @@ write_global_sym_plt (struct elf_link_hash_entry *h, void *inf)
|
|||||||
|
|
||||||
bfd_put_32 (info->output_bfd,
|
bfd_put_32 (info->output_bfd,
|
||||||
plt_entry[0] | PPC_HA (got_loc),
|
plt_entry[0] | PPC_HA (got_loc),
|
||||||
htab->elf.splt->contents + ent->plt.offset + 0);
|
plt->contents + ent->plt.offset + 0);
|
||||||
bfd_put_32 (info->output_bfd,
|
bfd_put_32 (info->output_bfd,
|
||||||
plt_entry[1] | PPC_LO (got_loc),
|
plt_entry[1] | PPC_LO (got_loc),
|
||||||
htab->elf.splt->contents + ent->plt.offset + 4);
|
plt->contents + ent->plt.offset + 4);
|
||||||
}
|
}
|
||||||
|
|
||||||
bfd_put_32 (info->output_bfd, plt_entry[2],
|
bfd_put_32 (info->output_bfd, plt_entry[2],
|
||||||
htab->elf.splt->contents + ent->plt.offset + 8);
|
plt->contents + ent->plt.offset + 8);
|
||||||
bfd_put_32 (info->output_bfd, plt_entry[3],
|
bfd_put_32 (info->output_bfd, plt_entry[3],
|
||||||
htab->elf.splt->contents + ent->plt.offset + 12);
|
plt->contents + ent->plt.offset + 12);
|
||||||
|
|
||||||
/* This instruction is an immediate load. The value loaded is
|
/* This instruction is an immediate load. The value loaded is
|
||||||
the byte offset of the R_PPC_JMP_SLOT relocation from the
|
the byte offset of the R_PPC_JMP_SLOT relocation from the
|
||||||
@ -10150,7 +10247,7 @@ write_global_sym_plt (struct elf_link_hash_entry *h, void *inf)
|
|||||||
prescaled offset. */
|
prescaled offset. */
|
||||||
bfd_put_32 (info->output_bfd,
|
bfd_put_32 (info->output_bfd,
|
||||||
plt_entry[4] | reloc_index,
|
plt_entry[4] | reloc_index,
|
||||||
htab->elf.splt->contents + ent->plt.offset + 16);
|
plt->contents + ent->plt.offset + 16);
|
||||||
/* This instruction is a PC-relative branch whose target is
|
/* This instruction is a PC-relative branch whose target is
|
||||||
the start of the PLT section. The address of this branch
|
the start of the PLT section. The address of this branch
|
||||||
instruction is 20 bytes beyond the start of this PLT entry.
|
instruction is 20 bytes beyond the start of this PLT entry.
|
||||||
@ -10160,19 +10257,18 @@ write_global_sym_plt (struct elf_link_hash_entry *h, void *inf)
|
|||||||
bfd_put_32 (info->output_bfd,
|
bfd_put_32 (info->output_bfd,
|
||||||
(plt_entry[5]
|
(plt_entry[5]
|
||||||
| (-(ent->plt.offset + 20) & 0x03fffffc)),
|
| (-(ent->plt.offset + 20) & 0x03fffffc)),
|
||||||
htab->elf.splt->contents + ent->plt.offset + 20);
|
plt->contents + ent->plt.offset + 20);
|
||||||
bfd_put_32 (info->output_bfd, plt_entry[6],
|
bfd_put_32 (info->output_bfd, plt_entry[6],
|
||||||
htab->elf.splt->contents + ent->plt.offset + 24);
|
plt->contents + ent->plt.offset + 24);
|
||||||
bfd_put_32 (info->output_bfd, plt_entry[7],
|
bfd_put_32 (info->output_bfd, plt_entry[7],
|
||||||
htab->elf.splt->contents + ent->plt.offset + 28);
|
plt->contents + ent->plt.offset + 28);
|
||||||
|
|
||||||
/* Fill in the GOT entry corresponding to this PLT slot with
|
/* Fill in the GOT entry corresponding to this PLT slot with
|
||||||
the address immediately after the "bctr" instruction
|
the address immediately after the "bctr" instruction
|
||||||
in this PLT entry. */
|
in this PLT entry. */
|
||||||
bfd_put_32 (info->output_bfd,
|
bfd_put_32 (info->output_bfd, (plt->output_section->vma
|
||||||
(htab->elf.splt->output_section->vma
|
+ plt->output_offset
|
||||||
+ htab->elf.splt->output_offset
|
+ ent->plt.offset + 16),
|
||||||
+ ent->plt.offset + 16),
|
|
||||||
htab->elf.sgotplt->contents + got_offset);
|
htab->elf.sgotplt->contents + got_offset);
|
||||||
|
|
||||||
if (!bfd_link_pic (info))
|
if (!bfd_link_pic (info))
|
||||||
@ -10184,8 +10280,8 @@ write_global_sym_plt (struct elf_link_hash_entry *h, void *inf)
|
|||||||
* sizeof (Elf32_External_Rela));
|
* sizeof (Elf32_External_Rela));
|
||||||
|
|
||||||
/* Provide the @ha relocation for the first instruction. */
|
/* Provide the @ha relocation for the first instruction. */
|
||||||
rela.r_offset = (htab->elf.splt->output_section->vma
|
rela.r_offset = (plt->output_section->vma
|
||||||
+ htab->elf.splt->output_offset
|
+ plt->output_offset
|
||||||
+ ent->plt.offset + 2);
|
+ ent->plt.offset + 2);
|
||||||
rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx,
|
rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx,
|
||||||
R_PPC_ADDR16_HA);
|
R_PPC_ADDR16_HA);
|
||||||
@ -10194,8 +10290,8 @@ write_global_sym_plt (struct elf_link_hash_entry *h, void *inf)
|
|||||||
loc += sizeof (Elf32_External_Rela);
|
loc += sizeof (Elf32_External_Rela);
|
||||||
|
|
||||||
/* Provide the @l relocation for the second instruction. */
|
/* Provide the @l relocation for the second instruction. */
|
||||||
rela.r_offset = (htab->elf.splt->output_section->vma
|
rela.r_offset = (plt->output_section->vma
|
||||||
+ htab->elf.splt->output_offset
|
+ plt->output_offset
|
||||||
+ ent->plt.offset + 6);
|
+ ent->plt.offset + 6);
|
||||||
rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx,
|
rela.r_info = ELF32_R_INFO (htab->elf.hgot->indx,
|
||||||
R_PPC_ADDR16_LO);
|
R_PPC_ADDR16_LO);
|
||||||
@ -10222,66 +10318,83 @@ write_global_sym_plt (struct elf_link_hash_entry *h, void *inf)
|
|||||||
rela.r_offset = (htab->elf.sgotplt->output_section->vma
|
rela.r_offset = (htab->elf.sgotplt->output_section->vma
|
||||||
+ htab->elf.sgotplt->output_offset
|
+ htab->elf.sgotplt->output_offset
|
||||||
+ got_offset);
|
+ got_offset);
|
||||||
|
rela.r_addend = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
asection *splt = htab->elf.splt;
|
rela.r_addend = 0;
|
||||||
if (!htab->elf.dynamic_sections_created
|
if (!htab->elf.dynamic_sections_created
|
||||||
|| h->dynindx == -1)
|
|| h->dynindx == -1)
|
||||||
splt = htab->elf.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
|
|
||||||
|| h->dynindx == -1)
|
|
||||||
{
|
{
|
||||||
/* We don't need to fill in the .plt. The ppc dynamic
|
if (h->type == STT_GNU_IFUNC)
|
||||||
linker will fill it in. */
|
{
|
||||||
|
plt = htab->elf.iplt;
|
||||||
|
relplt = htab->elf.irelplt;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
plt = htab->pltlocal;
|
||||||
|
relplt = bfd_link_pic (info) ? htab->relpltlocal : NULL;
|
||||||
|
}
|
||||||
|
if (h->def_regular
|
||||||
|
&& (h->root.type == bfd_link_hash_defined
|
||||||
|
|| h->root.type == bfd_link_hash_defweak))
|
||||||
|
rela.r_addend = SYM_VAL (h);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (relplt == NULL)
|
||||||
|
{
|
||||||
|
loc = plt->contents + ent->plt.offset;
|
||||||
|
bfd_put_32 (info->output_bfd, rela.r_addend, loc);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bfd_vma val = (htab->glink_pltresolve + ent->plt.offset
|
rela.r_offset = (plt->output_section->vma
|
||||||
+ htab->glink->output_section->vma
|
+ plt->output_offset
|
||||||
+ htab->glink->output_offset);
|
+ ent->plt.offset);
|
||||||
bfd_put_32 (info->output_bfd, val,
|
|
||||||
splt->contents + ent->plt.offset);
|
if (htab->plt_type == PLT_OLD
|
||||||
|
|| !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. */
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bfd_vma val = (htab->glink_pltresolve + ent->plt.offset
|
||||||
|
+ htab->glink->output_section->vma
|
||||||
|
+ htab->glink->output_offset);
|
||||||
|
bfd_put_32 (info->output_bfd, val,
|
||||||
|
plt->contents + ent->plt.offset);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fill in the entry in the .rela.plt section. */
|
if (relplt != NULL)
|
||||||
rela.r_addend = 0;
|
|
||||||
if (!htab->elf.dynamic_sections_created
|
|
||||||
|| h->dynindx == -1)
|
|
||||||
{
|
{
|
||||||
BFD_ASSERT (h->type == STT_GNU_IFUNC
|
/* Fill in the entry in the .rela.plt section. */
|
||||||
&& h->def_regular
|
if (!htab->elf.dynamic_sections_created
|
||||||
&& (h->root.type == bfd_link_hash_defined
|
|| h->dynindx == -1)
|
||||||
|| h->root.type == bfd_link_hash_defweak));
|
{
|
||||||
rela.r_info = ELF32_R_INFO (0, R_PPC_IRELATIVE);
|
if (h->type == STT_GNU_IFUNC)
|
||||||
rela.r_addend = SYM_VAL (h);
|
rela.r_info = ELF32_R_INFO (0, R_PPC_IRELATIVE);
|
||||||
|
else
|
||||||
|
rela.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE);
|
||||||
|
loc = relplt->contents + (relplt->reloc_count++
|
||||||
|
* sizeof (Elf32_External_Rela));
|
||||||
|
htab->local_ifunc_resolver = 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_JMP_SLOT);
|
||||||
|
loc = relplt->contents + (reloc_index
|
||||||
|
* sizeof (Elf32_External_Rela));
|
||||||
|
if (h->type == STT_GNU_IFUNC && is_static_defined (h))
|
||||||
|
htab->maybe_local_ifunc_resolver = 1;
|
||||||
|
}
|
||||||
|
bfd_elf32_swap_reloca_out (info->output_bfd, &rela, loc);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
rela.r_info = ELF32_R_INFO (h->dynindx, R_PPC_JMP_SLOT);
|
|
||||||
|
|
||||||
if (!htab->elf.dynamic_sections_created
|
|
||||||
|| h->dynindx == -1)
|
|
||||||
{
|
|
||||||
loc = (htab->elf.irelplt->contents
|
|
||||||
+ (htab->elf.irelplt->reloc_count++
|
|
||||||
* sizeof (Elf32_External_Rela)));
|
|
||||||
htab->local_ifunc_resolver = 1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
loc = (htab->elf.srelplt->contents
|
|
||||||
+ reloc_index * sizeof (Elf32_External_Rela));
|
|
||||||
if (h->type == STT_GNU_IFUNC && is_static_defined (h))
|
|
||||||
htab->maybe_local_ifunc_resolver = 1;
|
|
||||||
}
|
|
||||||
bfd_elf32_swap_reloca_out (info->output_bfd, &rela, loc);
|
|
||||||
doneone = TRUE;
|
doneone = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -10294,7 +10407,12 @@ write_global_sym_plt (struct elf_link_hash_entry *h, void *inf)
|
|||||||
|
|
||||||
if (!htab->elf.dynamic_sections_created
|
if (!htab->elf.dynamic_sections_created
|
||||||
|| h->dynindx == -1)
|
|| h->dynindx == -1)
|
||||||
plt = htab->elf.iplt;
|
{
|
||||||
|
if (h->type == STT_GNU_IFUNC)
|
||||||
|
plt = htab->elf.iplt;
|
||||||
|
else
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
p = (unsigned char *) htab->glink->contents + ent->glink_offset;
|
p = (unsigned char *) htab->glink->contents + ent->glink_offset;
|
||||||
write_glink_stub (h, ent, plt, p, info);
|
write_glink_stub (h, ent, plt, p, info);
|
||||||
@ -10368,16 +10486,32 @@ ppc_finish_symbols (struct bfd_link_info *info)
|
|||||||
if (sym_sec != NULL && sym_sec->output_section != NULL)
|
if (sym_sec != NULL && sym_sec->output_section != NULL)
|
||||||
val += sym_sec->output_offset + sym_sec->output_section->vma;
|
val += sym_sec->output_offset + sym_sec->output_section->vma;
|
||||||
|
|
||||||
BFD_ASSERT (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC);
|
if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
|
||||||
|
{
|
||||||
htab->local_ifunc_resolver = 1;
|
htab->local_ifunc_resolver = 1;
|
||||||
plt = htab->elf.iplt;
|
plt = htab->elf.iplt;
|
||||||
relplt = htab->elf.irelplt;
|
relplt = htab->elf.irelplt;
|
||||||
|
rela.r_info = ELF32_R_INFO (0, R_PPC_IRELATIVE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
plt = htab->pltlocal;
|
||||||
|
if (bfd_link_pic (info))
|
||||||
|
{
|
||||||
|
relplt = htab->relpltlocal;
|
||||||
|
rela.r_info = ELF32_R_INFO (0, R_PPC_RELATIVE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
loc = plt->contents + ent->plt.offset;
|
||||||
|
bfd_put_32 (info->output_bfd, val, loc);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rela.r_offset = (ent->plt.offset
|
rela.r_offset = (ent->plt.offset
|
||||||
+ plt->output_offset
|
+ plt->output_offset
|
||||||
+ plt->output_section->vma);
|
+ plt->output_section->vma);
|
||||||
rela.r_info = ELF32_R_INFO (0, R_PPC_IRELATIVE);
|
|
||||||
rela.r_addend = val;
|
rela.r_addend = val;
|
||||||
loc = relplt->contents + (relplt->reloc_count++
|
loc = relplt->contents + (relplt->reloc_count++
|
||||||
* sizeof (Elf32_External_Rela));
|
* sizeof (Elf32_External_Rela));
|
||||||
|
274
bfd/elf64-ppc.c
274
bfd/elf64-ppc.c
@ -129,6 +129,7 @@ static bfd_vma opd_entry_value
|
|||||||
|
|
||||||
/* The size in bytes of an entry in the procedure linkage table. */
|
/* The size in bytes of an entry in the procedure linkage table. */
|
||||||
#define PLT_ENTRY_SIZE(htab) (htab->opd_abi ? 24 : 8)
|
#define PLT_ENTRY_SIZE(htab) (htab->opd_abi ? 24 : 8)
|
||||||
|
#define LOCAL_PLT_ENTRY_SIZE(htab) (htab->opd_abi ? 16 : 8)
|
||||||
|
|
||||||
/* The initial size of the plt reserved for the dynamic linker. */
|
/* The initial size of the plt reserved for the dynamic linker. */
|
||||||
#define PLT_INITIAL_ENTRY_SIZE(htab) (htab->opd_abi ? 24 : 16)
|
#define PLT_INITIAL_ENTRY_SIZE(htab) (htab->opd_abi ? 24 : 16)
|
||||||
@ -3977,6 +3978,9 @@ struct ppc_stub_hash_entry {
|
|||||||
struct ppc_link_hash_entry *h;
|
struct ppc_link_hash_entry *h;
|
||||||
struct plt_entry *plt_ent;
|
struct plt_entry *plt_ent;
|
||||||
|
|
||||||
|
/* Symbol type. */
|
||||||
|
unsigned char symtype;
|
||||||
|
|
||||||
/* Symbol st_other. */
|
/* Symbol st_other. */
|
||||||
unsigned char other;
|
unsigned char other;
|
||||||
};
|
};
|
||||||
@ -4068,6 +4072,7 @@ struct ppc_link_hash_entry
|
|||||||
/* The above field is also used to mark function symbols. In which
|
/* The above field is also used to mark function symbols. In which
|
||||||
case TLS_TLS will be 0. */
|
case TLS_TLS will be 0. */
|
||||||
#define PLT_IFUNC 2 /* STT_GNU_IFUNC. */
|
#define PLT_IFUNC 2 /* STT_GNU_IFUNC. */
|
||||||
|
#define PLT_KEEP 4 /* inline plt call requires plt entry. */
|
||||||
#define NON_GOT 256 /* local symbol plt, not stored. */
|
#define NON_GOT 256 /* local symbol plt, not stored. */
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -4124,6 +4129,8 @@ struct ppc_link_hash_table
|
|||||||
asection *glink;
|
asection *glink;
|
||||||
asection *global_entry;
|
asection *global_entry;
|
||||||
asection *sfpr;
|
asection *sfpr;
|
||||||
|
asection *pltlocal;
|
||||||
|
asection *relpltlocal;
|
||||||
asection *brlt;
|
asection *brlt;
|
||||||
asection *relbrlt;
|
asection *relbrlt;
|
||||||
asection *glink_eh_frame;
|
asection *glink_eh_frame;
|
||||||
@ -4505,18 +4512,31 @@ create_linkage_sections (bfd *dynobj, struct bfd_link_info *info)
|
|||||||
|| ! bfd_set_section_alignment (dynobj, htab->brlt, 3))
|
|| ! bfd_set_section_alignment (dynobj, htab->brlt, 3))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
/* Local plt entries, put in .branch_lt but a separate section for
|
||||||
|
convenience. */
|
||||||
|
htab->pltlocal = bfd_make_section_anyway_with_flags (dynobj, ".branch_lt",
|
||||||
|
flags);
|
||||||
|
if (htab->pltlocal == NULL
|
||||||
|
|| ! bfd_set_section_alignment (dynobj, htab->pltlocal, 3))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
if (!bfd_link_pic (info))
|
if (!bfd_link_pic (info))
|
||||||
return TRUE;
|
return TRUE;
|
||||||
|
|
||||||
flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
|
flags = (SEC_ALLOC | SEC_LOAD | SEC_READONLY
|
||||||
| SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
|
| SEC_HAS_CONTENTS | SEC_IN_MEMORY | SEC_LINKER_CREATED);
|
||||||
htab->relbrlt = bfd_make_section_anyway_with_flags (dynobj,
|
htab->relbrlt
|
||||||
".rela.branch_lt",
|
= bfd_make_section_anyway_with_flags (dynobj, ".rela.branch_lt", flags);
|
||||||
flags);
|
|
||||||
if (htab->relbrlt == NULL
|
if (htab->relbrlt == NULL
|
||||||
|| ! bfd_set_section_alignment (dynobj, htab->relbrlt, 3))
|
|| ! bfd_set_section_alignment (dynobj, htab->relbrlt, 3))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
|
htab->relpltlocal
|
||||||
|
= bfd_make_section_anyway_with_flags (dynobj, ".rela.branch_lt", flags);
|
||||||
|
if (htab->relpltlocal == NULL
|
||||||
|
|| ! bfd_set_section_alignment (dynobj, htab->relpltlocal, 3))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5634,20 +5654,13 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
|||||||
if (h->root.root.string[0] == '.'
|
if (h->root.root.string[0] == '.'
|
||||||
&& h->root.root.string[1] != '\0')
|
&& h->root.root.string[1] != '\0')
|
||||||
((struct ppc_link_hash_entry *) h)->is_func = 1;
|
((struct ppc_link_hash_entry *) h)->is_func = 1;
|
||||||
|
((struct ppc_link_hash_entry *) h)->tls_mask |= PLT_KEEP;
|
||||||
plt_list = &h->plt.plist;
|
plt_list = &h->plt.plist;
|
||||||
}
|
}
|
||||||
if (plt_list == NULL)
|
if (plt_list == NULL)
|
||||||
{
|
plt_list = update_local_sym_info (abfd, symtab_hdr, r_symndx,
|
||||||
/* It does not make sense to have a procedure linkage
|
rel->r_addend,
|
||||||
table entry for a non-ifunc local symbol. */
|
NON_GOT | PLT_KEEP);
|
||||||
info->callbacks->einfo
|
|
||||||
/* xgettext:c-format */
|
|
||||||
(_("%H: %s reloc against local symbol\n"),
|
|
||||||
abfd, sec, rel->r_offset,
|
|
||||||
ppc64_elf_howto_table[r_type]->name);
|
|
||||||
bfd_set_error (bfd_error_bad_value);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if (!update_plt_info (abfd, plt_list, rel->r_addend))
|
if (!update_plt_info (abfd, plt_list, rel->r_addend))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
break;
|
break;
|
||||||
@ -7201,7 +7214,10 @@ ppc64_elf_adjust_dynamic_symbol (struct bfd_link_info *info,
|
|||||||
if (ent->plt.refcount > 0)
|
if (ent->plt.refcount > 0)
|
||||||
break;
|
break;
|
||||||
if (ent == NULL
|
if (ent == NULL
|
||||||
|| (h->type != STT_GNU_IFUNC && local))
|
|| (h->type != STT_GNU_IFUNC
|
||||||
|
&& local
|
||||||
|
&& (((struct ppc_link_hash_entry *) h)->tls_mask
|
||||||
|
& (TLS_TLS | PLT_KEEP)) != PLT_KEEP))
|
||||||
{
|
{
|
||||||
h->plt.plist = NULL;
|
h->plt.plist = NULL;
|
||||||
h->needs_plt = 0;
|
h->needs_plt = 0;
|
||||||
@ -9822,9 +9838,19 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((htab->elf.dynamic_sections_created
|
/* We might need a PLT entry when the symbol
|
||||||
&& h->dynindx != -1)
|
a) is dynamic, or
|
||||||
|| h->type == STT_GNU_IFUNC)
|
b) is an ifunc, or
|
||||||
|
c) has plt16 relocs and has been processed by adjust_dynamic_symbol, or
|
||||||
|
d) has plt16 relocs and we are linking statically. */
|
||||||
|
if ((htab->elf.dynamic_sections_created && h->dynindx != -1)
|
||||||
|
|| h->type == STT_GNU_IFUNC
|
||||||
|
|| (h->needs_plt && h->dynamic_adjusted)
|
||||||
|
|| (h->needs_plt
|
||||||
|
&& h->def_regular
|
||||||
|
&& !htab->elf.dynamic_sections_created
|
||||||
|
&& (((struct ppc_link_hash_entry *) h)->tls_mask
|
||||||
|
& (TLS_TLS | PLT_KEEP)) == PLT_KEEP))
|
||||||
{
|
{
|
||||||
struct plt_entry *pent;
|
struct plt_entry *pent;
|
||||||
bfd_boolean doneone = FALSE;
|
bfd_boolean doneone = FALSE;
|
||||||
@ -9834,10 +9860,20 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||||||
if (!htab->elf.dynamic_sections_created
|
if (!htab->elf.dynamic_sections_created
|
||||||
|| h->dynindx == -1)
|
|| h->dynindx == -1)
|
||||||
{
|
{
|
||||||
s = htab->elf.iplt;
|
if (h->type == STT_GNU_IFUNC)
|
||||||
pent->plt.offset = s->size;
|
{
|
||||||
s->size += PLT_ENTRY_SIZE (htab);
|
s = htab->elf.iplt;
|
||||||
s = htab->elf.irelplt;
|
pent->plt.offset = s->size;
|
||||||
|
s->size += PLT_ENTRY_SIZE (htab);
|
||||||
|
s = htab->elf.irelplt;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s = htab->pltlocal;
|
||||||
|
pent->plt.offset = s->size;
|
||||||
|
s->size += LOCAL_PLT_ENTRY_SIZE (htab);
|
||||||
|
s = bfd_link_pic (info) ? htab->relpltlocal : NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -9869,7 +9905,8 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||||||
/* We also need to make an entry in the .rela.plt section. */
|
/* We also need to make an entry in the .rela.plt section. */
|
||||||
s = htab->elf.srelplt;
|
s = htab->elf.srelplt;
|
||||||
}
|
}
|
||||||
s->size += sizeof (Elf64_External_Rela);
|
if (s != NULL)
|
||||||
|
s->size += sizeof (Elf64_External_Rela);
|
||||||
doneone = TRUE;
|
doneone = TRUE;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -10124,19 +10161,32 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd,
|
|||||||
*pent = ent->next;
|
*pent = ent->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Allocate space for calls to local STT_GNU_IFUNC syms in .iplt. */
|
/* Allocate space for plt calls to local syms. */
|
||||||
for (; local_plt < end_local_plt; ++local_plt)
|
lgot_masks = (unsigned char *) end_local_plt;
|
||||||
|
for (; local_plt < end_local_plt; ++local_plt, ++lgot_masks)
|
||||||
{
|
{
|
||||||
struct plt_entry *ent;
|
struct plt_entry *ent;
|
||||||
|
|
||||||
for (ent = *local_plt; ent != NULL; ent = ent->next)
|
for (ent = *local_plt; ent != NULL; ent = ent->next)
|
||||||
if (ent->plt.refcount > 0)
|
if (ent->plt.refcount > 0)
|
||||||
{
|
{
|
||||||
s = htab->elf.iplt;
|
if ((*lgot_masks & (TLS_TLS | PLT_IFUNC)) == PLT_IFUNC)
|
||||||
ent->plt.offset = s->size;
|
{
|
||||||
s->size += PLT_ENTRY_SIZE (htab);
|
s = htab->elf.iplt;
|
||||||
|
ent->plt.offset = s->size;
|
||||||
htab->elf.irelplt->size += sizeof (Elf64_External_Rela);
|
s->size += PLT_ENTRY_SIZE (htab);
|
||||||
|
htab->elf.irelplt->size += sizeof (Elf64_External_Rela);
|
||||||
|
}
|
||||||
|
else if ((*lgot_masks & (TLS_TLS | PLT_KEEP)) != PLT_KEEP)
|
||||||
|
ent->plt.offset = (bfd_vma) -1;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
s = htab->pltlocal;
|
||||||
|
ent->plt.offset = s->size;
|
||||||
|
s->size += LOCAL_PLT_ENTRY_SIZE (htab);
|
||||||
|
if (bfd_link_pic (info))
|
||||||
|
htab->relpltlocal->size += sizeof (Elf64_External_Rela);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ent->plt.offset = (bfd_vma) -1;
|
ent->plt.offset = (bfd_vma) -1;
|
||||||
@ -10199,6 +10249,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd,
|
|||||||
else if (s == htab->elf.sgot
|
else if (s == htab->elf.sgot
|
||||||
|| s == htab->elf.splt
|
|| s == htab->elf.splt
|
||||||
|| s == htab->elf.iplt
|
|| s == htab->elf.iplt
|
||||||
|
|| s == htab->pltlocal
|
||||||
|| s == htab->glink
|
|| s == htab->glink
|
||||||
|| s == htab->global_entry
|
|| s == htab->global_entry
|
||||||
|| s == htab->elf.sdynbss
|
|| s == htab->elf.sdynbss
|
||||||
@ -11154,7 +11205,12 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
|||||||
if (!htab->elf.dynamic_sections_created
|
if (!htab->elf.dynamic_sections_created
|
||||||
|| stub_entry->h == NULL
|
|| stub_entry->h == NULL
|
||||||
|| stub_entry->h->elf.dynindx == -1)
|
|| stub_entry->h->elf.dynindx == -1)
|
||||||
plt = htab->elf.iplt;
|
{
|
||||||
|
if (stub_entry->symtype == STT_GNU_IFUNC)
|
||||||
|
plt = htab->elf.iplt;
|
||||||
|
else
|
||||||
|
plt = htab->pltlocal;
|
||||||
|
}
|
||||||
|
|
||||||
dest += plt->output_offset + plt->output_section->vma;
|
dest += plt->output_offset + plt->output_section->vma;
|
||||||
|
|
||||||
@ -11303,7 +11359,12 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
|||||||
if (!htab->elf.dynamic_sections_created
|
if (!htab->elf.dynamic_sections_created
|
||||||
|| stub_entry->h == NULL
|
|| stub_entry->h == NULL
|
||||||
|| stub_entry->h->elf.dynindx == -1)
|
|| stub_entry->h->elf.dynindx == -1)
|
||||||
plt = htab->elf.iplt;
|
{
|
||||||
|
if (stub_entry->symtype == STT_GNU_IFUNC)
|
||||||
|
plt = htab->elf.iplt;
|
||||||
|
else
|
||||||
|
plt = htab->pltlocal;
|
||||||
|
}
|
||||||
off += (plt->output_offset
|
off += (plt->output_offset
|
||||||
+ plt->output_section->vma
|
+ plt->output_section->vma
|
||||||
- elf_gp (info->output_bfd)
|
- elf_gp (info->output_bfd)
|
||||||
@ -12655,6 +12716,8 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
|
|||||||
}
|
}
|
||||||
stub_entry->h = hash;
|
stub_entry->h = hash;
|
||||||
stub_entry->plt_ent = plt_ent;
|
stub_entry->plt_ent = plt_ent;
|
||||||
|
stub_entry->symtype
|
||||||
|
= hash ? hash->elf.type : ELF_ST_TYPE (sym->st_info);
|
||||||
stub_entry->other = hash ? hash->elf.other : sym->st_other;
|
stub_entry->other = hash ? hash->elf.other : sym->st_other;
|
||||||
|
|
||||||
if (stub_entry->h != NULL)
|
if (stub_entry->h != NULL)
|
||||||
@ -13017,6 +13080,7 @@ build_global_entry_stubs_and_plt (struct elf_link_hash_entry *h, void *inf)
|
|||||||
/* This symbol has an entry in the procedure linkage
|
/* This symbol has an entry in the procedure linkage
|
||||||
table. Set it up. */
|
table. Set it up. */
|
||||||
Elf_Internal_Rela rela;
|
Elf_Internal_Rela rela;
|
||||||
|
asection *plt, *relplt;
|
||||||
bfd_byte *loc;
|
bfd_byte *loc;
|
||||||
|
|
||||||
if (!htab->elf.dynamic_sections_created
|
if (!htab->elf.dynamic_sections_created
|
||||||
@ -13026,21 +13090,55 @@ build_global_entry_stubs_and_plt (struct elf_link_hash_entry *h, void *inf)
|
|||||||
&& (h->root.type == bfd_link_hash_defined
|
&& (h->root.type == bfd_link_hash_defined
|
||||||
|| h->root.type == bfd_link_hash_defweak)))
|
|| h->root.type == bfd_link_hash_defweak)))
|
||||||
continue;
|
continue;
|
||||||
rela.r_offset = (htab->elf.iplt->output_section->vma
|
if (h->type == STT_GNU_IFUNC)
|
||||||
+ htab->elf.iplt->output_offset
|
{
|
||||||
+ ent->plt.offset);
|
plt = htab->elf.iplt;
|
||||||
if (htab->opd_abi)
|
relplt = htab->elf.irelplt;
|
||||||
rela.r_info = ELF64_R_INFO (0, R_PPC64_JMP_IREL);
|
htab->local_ifunc_resolver = 1;
|
||||||
|
if (htab->opd_abi)
|
||||||
|
rela.r_info = ELF64_R_INFO (0, R_PPC64_JMP_IREL);
|
||||||
|
else
|
||||||
|
rela.r_info = ELF64_R_INFO (0, R_PPC64_IRELATIVE);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
rela.r_info = ELF64_R_INFO (0, R_PPC64_IRELATIVE);
|
{
|
||||||
|
plt = htab->pltlocal;
|
||||||
|
if (bfd_link_pic (info))
|
||||||
|
{
|
||||||
|
relplt = htab->relpltlocal;
|
||||||
|
if (htab->opd_abi)
|
||||||
|
rela.r_info = ELF64_R_INFO (0, R_PPC64_JMP_SLOT);
|
||||||
|
else
|
||||||
|
rela.r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
relplt = NULL;
|
||||||
|
}
|
||||||
rela.r_addend = (h->root.u.def.value
|
rela.r_addend = (h->root.u.def.value
|
||||||
+ h->root.u.def.section->output_offset
|
+ h->root.u.def.section->output_offset
|
||||||
+ h->root.u.def.section->output_section->vma
|
+ h->root.u.def.section->output_section->vma
|
||||||
+ ent->addend);
|
+ ent->addend);
|
||||||
loc = (htab->elf.irelplt->contents
|
|
||||||
+ (htab->elf.irelplt->reloc_count++
|
if (relplt == NULL)
|
||||||
* sizeof (Elf64_External_Rela)));
|
{
|
||||||
htab->local_ifunc_resolver = 1;
|
loc = plt->contents + ent->plt.offset;
|
||||||
|
bfd_put_64 (info->output_bfd, rela.r_addend, loc);
|
||||||
|
if (htab->opd_abi)
|
||||||
|
{
|
||||||
|
bfd_vma toc = elf_gp (info->output_bfd);
|
||||||
|
toc += htab->sec_info[h->root.u.def.section->id].toc_off;
|
||||||
|
bfd_put_64 (info->output_bfd, toc, loc + 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rela.r_offset = (plt->output_section->vma
|
||||||
|
+ plt->output_offset
|
||||||
|
+ ent->plt.offset);
|
||||||
|
loc = relplt->contents + (relplt->reloc_count++
|
||||||
|
* sizeof (Elf64_External_Rela));
|
||||||
|
bfd_elf64_swap_reloca_out (info->output_bfd, &rela, loc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -13054,8 +13152,8 @@ build_global_entry_stubs_and_plt (struct elf_link_hash_entry *h, void *inf)
|
|||||||
/ PLT_ENTRY_SIZE (htab) * sizeof (Elf64_External_Rela)));
|
/ PLT_ENTRY_SIZE (htab) * sizeof (Elf64_External_Rela)));
|
||||||
if (h->type == STT_GNU_IFUNC && is_static_defined (h))
|
if (h->type == STT_GNU_IFUNC && is_static_defined (h))
|
||||||
htab->maybe_local_ifunc_resolver = 1;
|
htab->maybe_local_ifunc_resolver = 1;
|
||||||
|
bfd_elf64_swap_reloca_out (info->output_bfd, &rela, loc);
|
||||||
}
|
}
|
||||||
bfd_elf64_swap_reloca_out (info->output_bfd, &rela, loc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!h->pointer_equality_needed)
|
if (!h->pointer_equality_needed)
|
||||||
@ -13080,7 +13178,12 @@ build_global_entry_stubs_and_plt (struct elf_link_hash_entry *h, void *inf)
|
|||||||
plt = htab->elf.splt;
|
plt = htab->elf.splt;
|
||||||
if (!htab->elf.dynamic_sections_created
|
if (!htab->elf.dynamic_sections_created
|
||||||
|| h->dynindx == -1)
|
|| h->dynindx == -1)
|
||||||
plt = htab->elf.iplt;
|
{
|
||||||
|
if (h->type == STT_GNU_IFUNC)
|
||||||
|
plt = htab->elf.iplt;
|
||||||
|
else
|
||||||
|
plt = htab->pltlocal;
|
||||||
|
}
|
||||||
off = ent->plt.offset + plt->output_offset + plt->output_section->vma;
|
off = ent->plt.offset + plt->output_offset + plt->output_section->vma;
|
||||||
off -= h->root.u.def.value + s->output_offset + s->output_section->vma;
|
off -= h->root.u.def.value + s->output_offset + s->output_section->vma;
|
||||||
|
|
||||||
@ -13173,7 +13276,6 @@ write_plt_relocs_for_local_syms (struct bfd_link_info *info)
|
|||||||
asection *plt, *relplt;
|
asection *plt, *relplt;
|
||||||
bfd_byte *loc;
|
bfd_byte *loc;
|
||||||
bfd_vma val;
|
bfd_vma val;
|
||||||
Elf_Internal_Rela rela;
|
|
||||||
|
|
||||||
if (!get_sym_h (NULL, &sym, &sym_sec, NULL, &local_syms,
|
if (!get_sym_h (NULL, &sym, &sym_sec, NULL, &local_syms,
|
||||||
lplt - local_plt, ibfd))
|
lplt - local_plt, ibfd))
|
||||||
@ -13189,23 +13291,53 @@ write_plt_relocs_for_local_syms (struct bfd_link_info *info)
|
|||||||
if (sym_sec != NULL && sym_sec->output_section != NULL)
|
if (sym_sec != NULL && sym_sec->output_section != NULL)
|
||||||
val += sym_sec->output_offset + sym_sec->output_section->vma;
|
val += sym_sec->output_offset + sym_sec->output_section->vma;
|
||||||
|
|
||||||
BFD_ASSERT (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC);
|
if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
|
||||||
|
{
|
||||||
htab->local_ifunc_resolver = 1;
|
htab->local_ifunc_resolver = 1;
|
||||||
plt = htab->elf.iplt;
|
plt = htab->elf.iplt;
|
||||||
relplt = htab->elf.irelplt;
|
relplt = htab->elf.irelplt;
|
||||||
|
}
|
||||||
rela.r_offset = (ent->plt.offset
|
|
||||||
+ plt->output_offset
|
|
||||||
+ plt->output_section->vma);
|
|
||||||
if (htab->opd_abi)
|
|
||||||
rela.r_info = ELF64_R_INFO (0, R_PPC64_JMP_IREL);
|
|
||||||
else
|
else
|
||||||
rela.r_info = ELF64_R_INFO (0, R_PPC64_IRELATIVE);
|
{
|
||||||
rela.r_addend = val;
|
plt = htab->pltlocal;
|
||||||
loc = relplt->contents + (relplt->reloc_count++
|
relplt = bfd_link_pic (info) ? htab->relpltlocal : NULL;
|
||||||
* sizeof (Elf64_External_Rela));
|
}
|
||||||
bfd_elf64_swap_reloca_out (info->output_bfd, &rela, loc);
|
|
||||||
|
if (relplt == NULL)
|
||||||
|
{
|
||||||
|
loc = plt->contents + ent->plt.offset;
|
||||||
|
bfd_put_64 (info->output_bfd, val, loc);
|
||||||
|
if (htab->opd_abi)
|
||||||
|
{
|
||||||
|
bfd_vma toc = elf_gp (ibfd);
|
||||||
|
bfd_put_64 (info->output_bfd, toc, loc + 8);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Elf_Internal_Rela rela;
|
||||||
|
rela.r_offset = (ent->plt.offset
|
||||||
|
+ plt->output_offset
|
||||||
|
+ plt->output_section->vma);
|
||||||
|
if (ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
|
||||||
|
{
|
||||||
|
if (htab->opd_abi)
|
||||||
|
rela.r_info = ELF64_R_INFO (0, R_PPC64_JMP_IREL);
|
||||||
|
else
|
||||||
|
rela.r_info = ELF64_R_INFO (0, R_PPC64_IRELATIVE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (htab->opd_abi)
|
||||||
|
rela.r_info = ELF64_R_INFO (0, R_PPC64_JMP_SLOT);
|
||||||
|
else
|
||||||
|
rela.r_info = ELF64_R_INFO (0, R_PPC64_RELATIVE);
|
||||||
|
}
|
||||||
|
rela.r_addend = val;
|
||||||
|
loc = relplt->contents + (relplt->reloc_count++
|
||||||
|
* sizeof (Elf64_External_Rela));
|
||||||
|
bfd_elf64_swap_reloca_out (info->output_bfd, &rela, loc);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (local_syms != NULL
|
if (local_syms != NULL
|
||||||
@ -14792,10 +14924,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
{
|
{
|
||||||
struct plt_entry **local_plt = (struct plt_entry **)
|
struct plt_entry **local_plt = (struct plt_entry **)
|
||||||
(local_got_ents + symtab_hdr->sh_info);
|
(local_got_ents + symtab_hdr->sh_info);
|
||||||
unsigned char *local_got_tls_masks = (unsigned char *)
|
plt_list = local_plt + r_symndx;
|
||||||
(local_plt + symtab_hdr->sh_info);
|
|
||||||
if ((local_got_tls_masks[r_symndx] & PLT_IFUNC) != 0)
|
|
||||||
plt_list = local_plt + r_symndx;
|
|
||||||
}
|
}
|
||||||
if (plt_list)
|
if (plt_list)
|
||||||
{
|
{
|
||||||
@ -14812,7 +14941,17 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
if (!htab->elf.dynamic_sections_created
|
if (!htab->elf.dynamic_sections_created
|
||||||
|| h == NULL
|
|| h == NULL
|
||||||
|| h->elf.dynindx == -1)
|
|| h->elf.dynindx == -1)
|
||||||
plt = htab->elf.iplt;
|
{
|
||||||
|
if (h != NULL
|
||||||
|
? h->elf.type == STT_GNU_IFUNC
|
||||||
|
: ELF_ST_TYPE (sym->st_info) == STT_GNU_IFUNC)
|
||||||
|
plt = htab->elf.iplt;
|
||||||
|
else
|
||||||
|
plt = htab->pltlocal;
|
||||||
|
}
|
||||||
|
relocation = (plt->output_section->vma
|
||||||
|
+ plt->output_offset
|
||||||
|
+ ent->plt.offset);
|
||||||
if (r_type == R_PPC64_PLT16_HA
|
if (r_type == R_PPC64_PLT16_HA
|
||||||
|| r_type ==R_PPC64_PLT16_HI
|
|| r_type ==R_PPC64_PLT16_HI
|
||||||
|| r_type ==R_PPC64_PLT16_LO
|
|| r_type ==R_PPC64_PLT16_LO
|
||||||
@ -14822,9 +14961,6 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
+ htab->sec_info[input_section->id].toc_off);
|
+ htab->sec_info[input_section->id].toc_off);
|
||||||
relocation -= got;
|
relocation -= got;
|
||||||
}
|
}
|
||||||
relocation = (plt->output_section->vma
|
|
||||||
+ plt->output_offset
|
|
||||||
+ ent->plt.offset);
|
|
||||||
addend = 0;
|
addend = 0;
|
||||||
unresolved_reloc = FALSE;
|
unresolved_reloc = FALSE;
|
||||||
break;
|
break;
|
||||||
|
@ -1,3 +1,18 @@
|
|||||||
|
2018-04-09 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
|
* powerpc.cc (Target_powerpc::lplt_): New variable.
|
||||||
|
(Target_powerpc::lplt_section): Associated accessor.
|
||||||
|
(Target_powerpc::plt_off): Handle local non-ifunc symbols.
|
||||||
|
(Target_powerpc::make_lplt_section): New function.
|
||||||
|
(Target_powerpc::make_local_plt_entry): New function.
|
||||||
|
(Powerpc_relobj::do_relocate_sections): Write out lplt.
|
||||||
|
(Output_data_plt_powerpc::first_plt_entry_offset): Zero for lplt.
|
||||||
|
(Output_data_plt_powerpc::add_local_entry): New function.
|
||||||
|
(Output_data_plt_powerpc::do_write): Ignore lplt.
|
||||||
|
(Target_powerpc::make_iplt_section): Make lplt first.
|
||||||
|
(Target_powerpc::make_brlt_section): Make .branch_lt relro.
|
||||||
|
(Target_powerpc::Scan::local): Handle PLT16 relocs.
|
||||||
|
|
||||||
2018-04-09 Alan Modra <amodra@gmail.com>
|
2018-04-09 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
* powerpc.cc (Target_powerpc::plt_off): New functions.
|
* powerpc.cc (Target_powerpc::plt_off): New functions.
|
||||||
|
149
gold/powerpc.cc
149
gold/powerpc.cc
@ -607,7 +607,7 @@ class Target_powerpc : public Sized_target<size, big_endian>
|
|||||||
|
|
||||||
Target_powerpc()
|
Target_powerpc()
|
||||||
: Sized_target<size, big_endian>(&powerpc_info),
|
: Sized_target<size, big_endian>(&powerpc_info),
|
||||||
got_(NULL), plt_(NULL), iplt_(NULL), brlt_section_(NULL),
|
got_(NULL), plt_(NULL), iplt_(NULL), lplt_(NULL), brlt_section_(NULL),
|
||||||
glink_(NULL), rela_dyn_(NULL), copy_relocs_(),
|
glink_(NULL), rela_dyn_(NULL), copy_relocs_(),
|
||||||
tlsld_got_offset_(-1U),
|
tlsld_got_offset_(-1U),
|
||||||
stub_tables_(), branch_lookup_table_(), branch_info_(), tocsave_loc_(),
|
stub_tables_(), branch_lookup_table_(), branch_info_(), tocsave_loc_(),
|
||||||
@ -860,6 +860,13 @@ class Target_powerpc : public Sized_target<size, big_endian>
|
|||||||
return this->iplt_;
|
return this->iplt_;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the LPLT section.
|
||||||
|
const Output_data_plt_powerpc<size, big_endian>*
|
||||||
|
lplt_section() const
|
||||||
|
{
|
||||||
|
return this->lplt_;
|
||||||
|
}
|
||||||
|
|
||||||
// Return the plt offset and section for the given global sym.
|
// Return the plt offset and section for the given global sym.
|
||||||
Address
|
Address
|
||||||
plt_off(const Symbol* gsym,
|
plt_off(const Symbol* gsym,
|
||||||
@ -879,7 +886,11 @@ class Target_powerpc : public Sized_target<size, big_endian>
|
|||||||
unsigned int local_sym_index,
|
unsigned int local_sym_index,
|
||||||
const Output_data_plt_powerpc<size, big_endian>** sec) const
|
const Output_data_plt_powerpc<size, big_endian>** sec) const
|
||||||
{
|
{
|
||||||
*sec = this->iplt_section();
|
const Symbol_value<size>* lsym = relobj->local_symbol(local_sym_index);
|
||||||
|
if (lsym->is_ifunc_symbol())
|
||||||
|
*sec = this->iplt_section();
|
||||||
|
else
|
||||||
|
*sec = this->lplt_section();
|
||||||
return relobj->local_plt_offset(local_sym_index);
|
return relobj->local_plt_offset(local_sym_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1440,6 +1451,9 @@ class Target_powerpc : public Sized_target<size, big_endian>
|
|||||||
void
|
void
|
||||||
make_iplt_section(Symbol_table*, Layout*);
|
make_iplt_section(Symbol_table*, Layout*);
|
||||||
|
|
||||||
|
void
|
||||||
|
make_lplt_section(Layout*);
|
||||||
|
|
||||||
void
|
void
|
||||||
make_brlt_section(Layout*);
|
make_brlt_section(Layout*);
|
||||||
|
|
||||||
@ -1453,6 +1467,12 @@ class Target_powerpc : public Sized_target<size, big_endian>
|
|||||||
Sized_relobj_file<size, big_endian>*,
|
Sized_relobj_file<size, big_endian>*,
|
||||||
unsigned int);
|
unsigned int);
|
||||||
|
|
||||||
|
// Create a PLT entry for a local non-IFUNC symbol.
|
||||||
|
void
|
||||||
|
make_local_plt_entry(Layout*,
|
||||||
|
Sized_relobj_file<size, big_endian>*,
|
||||||
|
unsigned int);
|
||||||
|
|
||||||
|
|
||||||
// Create a GOT entry for local dynamic __tls_get_addr.
|
// Create a GOT entry for local dynamic __tls_get_addr.
|
||||||
unsigned int
|
unsigned int
|
||||||
@ -1585,6 +1605,8 @@ class Target_powerpc : public Sized_target<size, big_endian>
|
|||||||
// section is emitted and marked with __rela_iplt_start and
|
// section is emitted and marked with __rela_iplt_start and
|
||||||
// __rela_iplt_end symbols.
|
// __rela_iplt_end symbols.
|
||||||
Output_data_plt_powerpc<size, big_endian>* iplt_;
|
Output_data_plt_powerpc<size, big_endian>* iplt_;
|
||||||
|
// A PLT style section for local, non-ifunc symbols
|
||||||
|
Output_data_plt_powerpc<size, big_endian>* lplt_;
|
||||||
// Section holding long branch destinations.
|
// Section holding long branch destinations.
|
||||||
Output_data_brlt_powerpc<size, big_endian>* brlt_section_;
|
Output_data_brlt_powerpc<size, big_endian>* brlt_section_;
|
||||||
// The .glink section.
|
// The .glink section.
|
||||||
@ -2469,6 +2491,35 @@ Powerpc_relobj<size, big_endian>::do_relocate_sections(
|
|||||||
}
|
}
|
||||||
this->relocate_section_range(symtab, layout, pshdrs, of, pviews,
|
this->relocate_section_range(symtab, layout, pshdrs, of, pviews,
|
||||||
start, this->shnum() - 1);
|
start, this->shnum() - 1);
|
||||||
|
|
||||||
|
if (!parameters->options().output_is_position_independent())
|
||||||
|
{
|
||||||
|
Target_powerpc<size, big_endian>* target
|
||||||
|
= static_cast<Target_powerpc<size, big_endian>*>(
|
||||||
|
parameters->sized_target<size, big_endian>());
|
||||||
|
if (target->lplt_section() && target->lplt_section()->data_size() != 0)
|
||||||
|
{
|
||||||
|
const section_size_type offset = target->lplt_section()->offset();
|
||||||
|
const section_size_type oview_size
|
||||||
|
= convert_to_section_size_type(target->lplt_section()->data_size());
|
||||||
|
unsigned char* const oview = of->get_output_view(offset, oview_size);
|
||||||
|
|
||||||
|
bool modified = false;
|
||||||
|
unsigned int nsyms = this->local_symbol_count();
|
||||||
|
for (unsigned int i = 0; i < nsyms; i++)
|
||||||
|
if (this->local_has_plt_offset(i))
|
||||||
|
{
|
||||||
|
Address value = this->local_symbol_value(i, 0);
|
||||||
|
if (size == 64)
|
||||||
|
value += ppc64_local_entry_offset(i);
|
||||||
|
size_t off = this->local_plt_offset(i);
|
||||||
|
elfcpp::Swap<size, big_endian>::writeval(oview + off, value);
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
if (modified)
|
||||||
|
of->write_output_view(offset, oview_size, oview);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set up some symbols.
|
// Set up some symbols.
|
||||||
@ -3667,6 +3718,9 @@ class Output_data_plt_powerpc : public Output_section_data_build
|
|||||||
void
|
void
|
||||||
add_ifunc_entry(Symbol*);
|
add_ifunc_entry(Symbol*);
|
||||||
|
|
||||||
|
void
|
||||||
|
add_local_entry(Sized_relobj_file<size, big_endian>*, unsigned int);
|
||||||
|
|
||||||
void
|
void
|
||||||
add_local_ifunc_entry(Sized_relobj_file<size, big_endian>*, unsigned int);
|
add_local_ifunc_entry(Sized_relobj_file<size, big_endian>*, unsigned int);
|
||||||
|
|
||||||
@ -3704,8 +3758,8 @@ class Output_data_plt_powerpc : public Output_section_data_build
|
|||||||
unsigned int
|
unsigned int
|
||||||
first_plt_entry_offset() const
|
first_plt_entry_offset() const
|
||||||
{
|
{
|
||||||
// IPLT has no reserved entry.
|
// IPLT and LPLT have no reserved entry.
|
||||||
if (this->name_[3] == 'I')
|
if (this->name_[3] == 'I' || this->name_[3] == 'L')
|
||||||
return 0;
|
return 0;
|
||||||
return this->targ_->first_plt_entry_offset();
|
return this->targ_->first_plt_entry_offset();
|
||||||
}
|
}
|
||||||
@ -3768,6 +3822,31 @@ Output_data_plt_powerpc<size, big_endian>::add_ifunc_entry(Symbol* gsym)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add an entry for a local symbol to the PLT.
|
||||||
|
|
||||||
|
template<int size, bool big_endian>
|
||||||
|
void
|
||||||
|
Output_data_plt_powerpc<size, big_endian>::add_local_entry(
|
||||||
|
Sized_relobj_file<size, big_endian>* relobj,
|
||||||
|
unsigned int local_sym_index)
|
||||||
|
{
|
||||||
|
if (!relobj->local_has_plt_offset(local_sym_index))
|
||||||
|
{
|
||||||
|
section_size_type off = this->current_data_size();
|
||||||
|
relobj->set_local_plt_offset(local_sym_index, off);
|
||||||
|
if (this->rel_)
|
||||||
|
{
|
||||||
|
unsigned int dynrel = elfcpp::R_POWERPC_RELATIVE;
|
||||||
|
if (size == 64 && this->targ_->abiversion() < 2)
|
||||||
|
dynrel = elfcpp::R_POWERPC_JMP_SLOT;
|
||||||
|
this->rel_->add_symbolless_local_addend(relobj, local_sym_index,
|
||||||
|
dynrel, this, off, 0);
|
||||||
|
}
|
||||||
|
off += this->plt_entry_size();
|
||||||
|
this->set_current_data_size(off);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Add an entry for a local ifunc symbol to the IPLT.
|
// Add an entry for a local ifunc symbol to the IPLT.
|
||||||
|
|
||||||
template<int size, bool big_endian>
|
template<int size, bool big_endian>
|
||||||
@ -3888,7 +3967,7 @@ template<int size, bool big_endian>
|
|||||||
void
|
void
|
||||||
Output_data_plt_powerpc<size, big_endian>::do_write(Output_file* of)
|
Output_data_plt_powerpc<size, big_endian>::do_write(Output_file* of)
|
||||||
{
|
{
|
||||||
if (size == 32 && this->name_[3] != 'I')
|
if (size == 32 && (this->name_[3] != 'I' && this->name_[3] != 'L'))
|
||||||
{
|
{
|
||||||
const section_size_type offset = this->offset();
|
const section_size_type offset = this->offset();
|
||||||
const section_size_type oview_size
|
const section_size_type oview_size
|
||||||
@ -3966,6 +4045,7 @@ Target_powerpc<size, big_endian>::make_iplt_section(Symbol_table* symtab,
|
|||||||
if (this->iplt_ == NULL)
|
if (this->iplt_ == NULL)
|
||||||
{
|
{
|
||||||
this->make_plt_section(symtab, layout);
|
this->make_plt_section(symtab, layout);
|
||||||
|
this->make_lplt_section(layout);
|
||||||
|
|
||||||
Reloc_section* iplt_rel = new Reloc_section(false);
|
Reloc_section* iplt_rel = new Reloc_section(false);
|
||||||
if (this->rela_dyn_->output_section())
|
if (this->rela_dyn_->output_section())
|
||||||
@ -3978,6 +4058,40 @@ Target_powerpc<size, big_endian>::make_iplt_section(Symbol_table* symtab,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create the LPLT section.
|
||||||
|
|
||||||
|
template<int size, bool big_endian>
|
||||||
|
void
|
||||||
|
Target_powerpc<size, big_endian>::make_lplt_section(Layout* layout)
|
||||||
|
{
|
||||||
|
if (this->lplt_ == NULL)
|
||||||
|
{
|
||||||
|
Reloc_section* lplt_rel = NULL;
|
||||||
|
if (parameters->options().output_is_position_independent())
|
||||||
|
{
|
||||||
|
lplt_rel = new Reloc_section(false);
|
||||||
|
this->rela_dyn_section(layout);
|
||||||
|
if (this->rela_dyn_->output_section())
|
||||||
|
this->rela_dyn_->output_section()
|
||||||
|
->add_output_section_data(lplt_rel);
|
||||||
|
}
|
||||||
|
this->lplt_
|
||||||
|
= new Output_data_plt_powerpc<size, big_endian>(this, lplt_rel,
|
||||||
|
"** LPLT");
|
||||||
|
this->make_brlt_section(layout);
|
||||||
|
if (this->brlt_section_ && this->brlt_section_->output_section())
|
||||||
|
this->brlt_section_->output_section()
|
||||||
|
->add_output_section_data(this->lplt_);
|
||||||
|
else
|
||||||
|
layout->add_output_section_data(".branch_lt",
|
||||||
|
elfcpp::SHT_PROGBITS,
|
||||||
|
elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
|
||||||
|
this->lplt_,
|
||||||
|
ORDER_RELRO,
|
||||||
|
true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// A section for huge long branch addresses, similar to plt section.
|
// A section for huge long branch addresses, similar to plt section.
|
||||||
|
|
||||||
template<int size, bool big_endian>
|
template<int size, bool big_endian>
|
||||||
@ -6132,6 +6246,20 @@ Target_powerpc<size, big_endian>::make_plt_entry(Symbol_table* symtab,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make a PLT entry for a local symbol.
|
||||||
|
|
||||||
|
template<int size, bool big_endian>
|
||||||
|
void
|
||||||
|
Target_powerpc<size, big_endian>::make_local_plt_entry(
|
||||||
|
Layout* layout,
|
||||||
|
Sized_relobj_file<size, big_endian>* relobj,
|
||||||
|
unsigned int r_sym)
|
||||||
|
{
|
||||||
|
if (this->lplt_ == NULL)
|
||||||
|
this->make_lplt_section(layout);
|
||||||
|
this->lplt_->add_local_entry(relobj, r_sym);
|
||||||
|
}
|
||||||
|
|
||||||
// Make a PLT entry for a local STT_GNU_IFUNC symbol.
|
// Make a PLT entry for a local STT_GNU_IFUNC symbol.
|
||||||
|
|
||||||
template<int size, bool big_endian>
|
template<int size, bool big_endian>
|
||||||
@ -6669,6 +6797,17 @@ Target_powerpc<size, big_endian>::Scan::local(
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case elfcpp::R_POWERPC_PLT16_LO:
|
||||||
|
case elfcpp::R_POWERPC_PLT16_HI:
|
||||||
|
case elfcpp::R_POWERPC_PLT16_HA:
|
||||||
|
case elfcpp::R_PPC64_PLT16_LO_DS:
|
||||||
|
if (!is_ifunc)
|
||||||
|
{
|
||||||
|
unsigned int r_sym = elfcpp::elf_r_sym<size>(reloc.get_r_info());
|
||||||
|
target->make_local_plt_entry(layout, object, r_sym);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case elfcpp::R_POWERPC_REL24:
|
case elfcpp::R_POWERPC_REL24:
|
||||||
case elfcpp::R_PPC_PLTREL24:
|
case elfcpp::R_PPC_PLTREL24:
|
||||||
case elfcpp::R_PPC_LOCAL24PC:
|
case elfcpp::R_PPC_LOCAL24PC:
|
||||||
|
10
ld/ChangeLog
10
ld/ChangeLog
@ -1,3 +1,13 @@
|
|||||||
|
2018-04-09 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
|
* emulparams/elf32ppc.sh (OTHER_RELRO_SECTIONS_2): Add .branch_lt.
|
||||||
|
(OTHER_GOT_RELOC_SECTIONS): Add .rela.branch_lt.
|
||||||
|
* testsuite/ld-powerpc/elfv2so.d: Update for symbol/stub reordering.
|
||||||
|
* testsuite/ld-powerpc/relbrlt.d: Likewise.
|
||||||
|
* testsuite/ld-powerpc/relbrlt.s: Likewise.
|
||||||
|
* testsuite/ld-powerpc/tlsso.r: Likewise.
|
||||||
|
* testsuite/ld-powerpc/tlstocso.r: Likewise.
|
||||||
|
|
||||||
2018-04-09 Alan Modra <amodra@gmail.com>
|
2018-04-09 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
* ppc32elf.em (ppc_finish): Call ppc_finish_symbols.
|
* ppc32elf.em (ppc_finish): Call ppc_finish_symbols.
|
||||||
|
@ -15,6 +15,10 @@ GOTPLT=".plt ${RELOCATING-0} : SPECIAL { *(.plt) }"
|
|||||||
PLT=".plt ${RELOCATING-0} : SPECIAL { *(.plt) }
|
PLT=".plt ${RELOCATING-0} : SPECIAL { *(.plt) }
|
||||||
.iplt ${RELOCATING-0} : { *(.iplt) }"
|
.iplt ${RELOCATING-0} : { *(.iplt) }"
|
||||||
OTHER_TEXT_SECTIONS="*(.glink)"
|
OTHER_TEXT_SECTIONS="*(.glink)"
|
||||||
|
OTHER_GOT_RELOC_SECTIONS="
|
||||||
|
.rela.branch_lt ${RELOCATING-0} : { *(.rela.branch_lt) }"
|
||||||
|
OTHER_RELRO_SECTIONS_2="
|
||||||
|
.branch_lt ${RELOCATING-0} :${RELOCATING+ ALIGN(4)} { *(.branch_lt) }"
|
||||||
EXTRA_EM_FILE=ppc32elf
|
EXTRA_EM_FILE=ppc32elf
|
||||||
if grep -q 'ld_elf32_spu_emulation' ldemul-list.h; then
|
if grep -q 'ld_elf32_spu_emulation' ldemul-list.h; then
|
||||||
# crt1.o defines data_start and __data_start. Keep them first.
|
# crt1.o defines data_start and __data_start. Keep them first.
|
||||||
|
@ -14,16 +14,16 @@ Disassembly of section \.text:
|
|||||||
.*: (4e 80 04 20|20 04 80 4e) bctr
|
.*: (4e 80 04 20|20 04 80 4e) bctr
|
||||||
\.\.\.
|
\.\.\.
|
||||||
|
|
||||||
.* <.*\.plt_call\.f1>:
|
.* <.*\.plt_call\.f3>:
|
||||||
.*: (f8 41 00 18|18 00 41 f8) std r2,24\(r1\)
|
.*: (f8 41 00 18|18 00 41 f8) std r2,24\(r1\)
|
||||||
.*: (e9 82 80 40|40 80 82 e9) ld r12,-32704\(r2\)
|
.*: (e9 82 80 28|28 80 82 e9) ld r12,-32728\(r2\)
|
||||||
.*: (7d 89 03 a6|a6 03 89 7d) mtctr r12
|
.*: (7d 89 03 a6|a6 03 89 7d) mtctr r12
|
||||||
.*: (4e 80 04 20|20 04 80 4e) bctr
|
.*: (4e 80 04 20|20 04 80 4e) bctr
|
||||||
\.\.\.
|
\.\.\.
|
||||||
|
|
||||||
.* <.*\.plt_call\.f3>:
|
.* <.*\.plt_call\.f1>:
|
||||||
.*: (f8 41 00 18|18 00 41 f8) std r2,24\(r1\)
|
.*: (f8 41 00 18|18 00 41 f8) std r2,24\(r1\)
|
||||||
.*: (e9 82 80 28|28 80 82 e9) ld r12,-32728\(r2\)
|
.*: (e9 82 80 40|40 80 82 e9) ld r12,-32704\(r2\)
|
||||||
.*: (7d 89 03 a6|a6 03 89 7d) mtctr r12
|
.*: (7d 89 03 a6|a6 03 89 7d) mtctr r12
|
||||||
.*: (4e 80 04 20|20 04 80 4e) bctr
|
.*: (4e 80 04 20|20 04 80 4e) bctr
|
||||||
\.\.\.
|
\.\.\.
|
||||||
@ -41,12 +41,12 @@ Disassembly of section \.text:
|
|||||||
.*: (7c 08 02 a6|a6 02 08 7c) mflr r0
|
.*: (7c 08 02 a6|a6 02 08 7c) mflr r0
|
||||||
.*: (f8 21 ff e1|e1 ff 21 f8) stdu r1,-32\(r1\)
|
.*: (f8 21 ff e1|e1 ff 21 f8) stdu r1,-32\(r1\)
|
||||||
.*: (f8 01 00 30|30 00 01 f8) std r0,48\(r1\)
|
.*: (f8 01 00 30|30 00 01 f8) std r0,48\(r1\)
|
||||||
.*: (4b ff ff 8d|8d ff ff 4b) bl .*\.plt_call\.f1>
|
.*: (4b ff ff ad|ad ff ff 4b) bl .*\.plt_call\.f1>
|
||||||
.*: (e8 62 80 08|08 80 62 e8) ld r3,-32760\(r2\)
|
.*: (e8 62 80 08|08 80 62 e8) ld r3,-32760\(r2\)
|
||||||
.*: (4b ff ff c5|c5 ff ff 4b) bl .*\.plt_call\.f2>
|
.*: (4b ff ff c5|c5 ff ff 4b) bl .*\.plt_call\.f2>
|
||||||
.*: (e8 41 00 18|18 00 41 e8) ld r2,24\(r1\)
|
.*: (e8 41 00 18|18 00 41 e8) ld r2,24\(r1\)
|
||||||
.*: (e8 62 80 10|10 80 62 e8) ld r3,-32752\(r2\)
|
.*: (e8 62 80 10|10 80 62 e8) ld r3,-32752\(r2\)
|
||||||
.*: (4b ff ff 99|99 ff ff 4b) bl .*\.plt_call\.f3>
|
.*: (4b ff ff 79|79 ff ff 4b) bl .*\.plt_call\.f3>
|
||||||
.*: (e8 41 00 18|18 00 41 e8) ld r2,24\(r1\)
|
.*: (e8 41 00 18|18 00 41 e8) ld r2,24\(r1\)
|
||||||
.*: (4b ff ff 51|51 ff ff 4b) bl .*\.plt_call\.f4>
|
.*: (4b ff ff 51|51 ff ff 4b) bl .*\.plt_call\.f4>
|
||||||
.*: (e8 41 00 18|18 00 41 e8) ld r2,24\(r1\)
|
.*: (e8 41 00 18|18 00 41 e8) ld r2,24\(r1\)
|
||||||
|
@ -8,32 +8,32 @@
|
|||||||
Disassembly of section \.text:
|
Disassembly of section \.text:
|
||||||
|
|
||||||
0*100000c0 <_start>:
|
0*100000c0 <_start>:
|
||||||
[0-9a-f ]*: (49 bf 00 21|21 00 bf 49) bl .*
|
[0-9a-f ]*: (49 bf 00 2d|2d 00 bf 49) bl .*
|
||||||
[0-9a-f ]*: R_PPC64_REL24 \.text\+0x37e003c
|
[0-9a-f ]*: R_PPC64_REL24 \.text\+0x37e003c
|
||||||
[0-9a-f ]*: (60 00 00 00|00 00 00 60) nop
|
[0-9a-f ]*: (60 00 00 00|00 00 00 60) nop
|
||||||
[0-9a-f ]*: (49 bf 00 1d|1d 00 bf 49) bl .*
|
[0-9a-f ]*: (49 bf 00 19|19 00 bf 49) bl .*
|
||||||
[0-9a-f ]*: R_PPC64_REL24 \.text\+0x3bf002c
|
[0-9a-f ]*: R_PPC64_REL24 \.text\+0x3bf0020
|
||||||
[0-9a-f ]*: (60 00 00 00|00 00 00 60) nop
|
[0-9a-f ]*: (60 00 00 00|00 00 00 60) nop
|
||||||
[0-9a-f ]*: (49 bf 00 21|21 00 bf 49) bl .*
|
[0-9a-f ]*: (49 bf 00 21|21 00 bf 49) bl .*
|
||||||
[0-9a-f ]*: R_PPC64_REL24 \.text\+0x57e0030
|
[0-9a-f ]*: R_PPC64_REL24 \.text\+0x57e0024
|
||||||
[0-9a-f ]*: (60 00 00 00|00 00 00 60) nop
|
[0-9a-f ]*: (60 00 00 00|00 00 00 60) nop
|
||||||
[0-9a-f ]*: 00 00 00 00 \.long 0x0
|
[0-9a-f ]*: 00 00 00 00 \.long 0x0
|
||||||
[0-9a-f ]*: (4b ff ff e4|e4 ff ff 4b) b .* <_start>
|
[0-9a-f ]*: (4b ff ff e4|e4 ff ff 4b) b .* <_start>
|
||||||
\.\.\.
|
\.\.\.
|
||||||
|
|
||||||
[0-9a-f ]*<.*long_branch.*>:
|
|
||||||
[0-9a-f ]*: (49 bf 00 1c|1c 00 bf 49) b .* <far>
|
|
||||||
[0-9a-f ]*: R_PPC64_REL24 \*ABS\*\+0x137e00fc
|
|
||||||
|
|
||||||
[0-9a-f ]*<.*plt_branch.*>:
|
[0-9a-f ]*<.*plt_branch.*>:
|
||||||
[0-9a-f ]*: (e9 82 80 f8|f8 80 82 e9) ld r12,-32520\(r2\)
|
[0-9a-f ]*: (e9 82 80 e8|e8 80 82 e9) ld r12,-32536\(r2\)
|
||||||
[0-9a-f ]*: R_PPC64_TOC16_DS \*ABS\*\+0x157f00f8
|
[0-9a-f ]*: R_PPC64_TOC16_DS \*ABS\*\+0x157f00e8
|
||||||
[0-9a-f ]*: (7d 89 03 a6|a6 03 89 7d) mtctr r12
|
[0-9a-f ]*: (7d 89 03 a6|a6 03 89 7d) mtctr r12
|
||||||
[0-9a-f ]*: (4e 80 04 20|20 04 80 4e) bctr
|
[0-9a-f ]*: (4e 80 04 20|20 04 80 4e) bctr
|
||||||
|
|
||||||
|
[0-9a-f ]*<.*long_branch.*>:
|
||||||
|
[0-9a-f ]*: (49 bf 00 10|10 00 bf 49) b .* <far>
|
||||||
|
[0-9a-f ]*: R_PPC64_REL24 \*ABS\*\+0x137e00fc
|
||||||
|
|
||||||
[0-9a-f ]*<.*plt_branch.*>:
|
[0-9a-f ]*<.*plt_branch.*>:
|
||||||
[0-9a-f ]*: (e9 82 81 00|00 81 82 e9) ld r12,-32512\(r2\)
|
[0-9a-f ]*: (e9 82 80 f0|f0 80 82 e9) ld r12,-32528\(r2\)
|
||||||
[0-9a-f ]*: R_PPC64_TOC16_DS \*ABS\*\+0x157f0100
|
[0-9a-f ]*: R_PPC64_TOC16_DS \*ABS\*\+0x157f00f0
|
||||||
[0-9a-f ]*: (7d 89 03 a6|a6 03 89 7d) mtctr r12
|
[0-9a-f ]*: (7d 89 03 a6|a6 03 89 7d) mtctr r12
|
||||||
[0-9a-f ]*: (4e 80 04 20|20 04 80 4e) bctr
|
[0-9a-f ]*: (4e 80 04 20|20 04 80 4e) bctr
|
||||||
\.\.\.
|
\.\.\.
|
||||||
@ -42,19 +42,19 @@ Disassembly of section \.text:
|
|||||||
[0-9a-f ]*: (4e 80 00 20|20 00 80 4e) blr
|
[0-9a-f ]*: (4e 80 00 20|20 00 80 4e) blr
|
||||||
\.\.\.
|
\.\.\.
|
||||||
|
|
||||||
0*13bf00ec <far2far>:
|
0*13bf00e0 <far2far>:
|
||||||
[0-9a-f ]*: (4e 80 00 20|20 00 80 4e) blr
|
[0-9a-f ]*: (4e 80 00 20|20 00 80 4e) blr
|
||||||
\.\.\.
|
\.\.\.
|
||||||
|
|
||||||
0*157e00f0 <huge>:
|
0*157e00e4 <huge>:
|
||||||
[0-9a-f ]*: (4e 80 00 20|20 00 80 4e) blr
|
[0-9a-f ]*: (4e 80 00 20|20 00 80 4e) blr
|
||||||
|
|
||||||
Disassembly of section \.branch_lt:
|
Disassembly of section \.branch_lt:
|
||||||
|
|
||||||
0*157f00f8 .*:
|
0*157f00e8 .*:
|
||||||
[0-9a-f ]*: (00 00 00 00|ec 00 bf 13) .*
|
[0-9a-f ]*: (00 00 00 00|e0 00 bf 13) .*
|
||||||
[0-9a-f ]*: R_PPC64_RELATIVE \*ABS\*\+0x13bf00ec
|
[0-9a-f ]*: R_PPC64_RELATIVE \*ABS\*\+0x13bf00e0
|
||||||
[0-9a-f ]*: (13 bf 00 ec|00 00 00 00) .*
|
[0-9a-f ]*: (13 bf 00 e0|00 00 00 00) .*
|
||||||
[0-9a-f ]*: (00 00 00 00|f0 00 7e 15) .*
|
[0-9a-f ]*: (00 00 00 00|e4 00 7e 15) .*
|
||||||
[0-9a-f ]*: R_PPC64_RELATIVE \*ABS\*\+0x157e00f0
|
[0-9a-f ]*: R_PPC64_RELATIVE \*ABS\*\+0x157e00e4
|
||||||
[0-9a-f ]*: (15 7e 00 f0|00 00 00 00) .*
|
[0-9a-f ]*: (15 7e 00 e4|00 00 00 00) .*
|
||||||
|
@ -20,7 +20,7 @@ far:
|
|||||||
blr
|
blr
|
||||||
|
|
||||||
.section .text.pad2,"ax"
|
.section .text.pad2,"ax"
|
||||||
.space 0x40ffec
|
.space 0x40ffe0
|
||||||
|
|
||||||
.section .text.far2far,"ax"
|
.section .text.far2far,"ax"
|
||||||
far2far:
|
far2far:
|
||||||
|
@ -114,8 +114,8 @@ Symbol table '\.symtab' contains [0-9]+ entries:
|
|||||||
.* TLS +LOCAL +DEFAULT +7 le5
|
.* TLS +LOCAL +DEFAULT +7 le5
|
||||||
.* FILE +LOCAL +DEFAULT +ABS
|
.* FILE +LOCAL +DEFAULT +ABS
|
||||||
.* OBJECT +LOCAL +DEFAULT +9 _DYNAMIC
|
.* OBJECT +LOCAL +DEFAULT +9 _DYNAMIC
|
||||||
.* NOTYPE +LOCAL +DEFAULT +6 .*\.plt_call\.__tls_get_addr
|
|
||||||
.* NOTYPE +LOCAL +DEFAULT +6 __glink_PLTresolve
|
.* NOTYPE +LOCAL +DEFAULT +6 __glink_PLTresolve
|
||||||
|
.* NOTYPE +LOCAL +DEFAULT +6 .*\.plt_call\.__tls_get_addr
|
||||||
.* TLS +GLOBAL +DEFAULT +UND gd
|
.* TLS +GLOBAL +DEFAULT +UND gd
|
||||||
.* TLS +GLOBAL +DEFAULT +8 le0
|
.* TLS +GLOBAL +DEFAULT +8 le0
|
||||||
.* NOTYPE +GLOBAL +DEFAULT +UND __tls_get_addr
|
.* NOTYPE +GLOBAL +DEFAULT +UND __tls_get_addr
|
||||||
|
@ -110,8 +110,8 @@ Symbol table '\.symtab' contains [0-9]+ entries:
|
|||||||
.* NOTYPE +LOCAL +DEFAULT +11 \.Lie0
|
.* NOTYPE +LOCAL +DEFAULT +11 \.Lie0
|
||||||
.* FILE +LOCAL +DEFAULT +ABS
|
.* FILE +LOCAL +DEFAULT +ABS
|
||||||
.* OBJECT +LOCAL +DEFAULT +9 _DYNAMIC
|
.* OBJECT +LOCAL +DEFAULT +9 _DYNAMIC
|
||||||
.* NOTYPE +LOCAL +DEFAULT +6 .*\.plt_call\.__tls_get_addr
|
|
||||||
.* NOTYPE +LOCAL +DEFAULT +6 __glink_PLTresolve
|
.* NOTYPE +LOCAL +DEFAULT +6 __glink_PLTresolve
|
||||||
|
.* NOTYPE +LOCAL +DEFAULT +6 .*\.plt_call\.__tls_get_addr
|
||||||
.* TLS +GLOBAL +DEFAULT +UND gd
|
.* TLS +GLOBAL +DEFAULT +UND gd
|
||||||
.* TLS +GLOBAL +DEFAULT +8 le0
|
.* TLS +GLOBAL +DEFAULT +8 le0
|
||||||
.* NOTYPE +GLOBAL +DEFAULT +UND __tls_get_addr
|
.* NOTYPE +GLOBAL +DEFAULT +UND __tls_get_addr
|
||||||
|
Loading…
Reference in New Issue
Block a user