mirror of
https://github.com/espressif/binutils-gdb.git
synced 2025-06-25 04:49:54 +08:00
ELFv2 stub, plt and glink changes
An ELFv2 PLT entry is simply the address of the target function rather than three (or two) words to specify entry, toc and static chain. PLT call stubs are correspondingly simpler and need no thread safety barrier. The glink resolver stub and branch table also is simplified, a change that could be applied to ELFv1 too, but isn't as yet. * elf64-ppc.c (PLT_ENTRY_SIZE, PLT_INITIAL_ENTRY_SIZE): Add htab parameter and adjust for ELFv2. Update all uses. (PLT_CALL_STUB_SIZE): Delete. (ppc64_elf_get_synthetic_symtab): Support new glink layout. (allocate_dynrelocs): Likewise. (plt_stub_size, build_plt_stub): Adjust for ELFv2. (get_r2off): Return 0 for ELFv2 -R. (ppc_build_one_stub, ppc_size_one_stub): Adjust for ELFv2. (ppc64_elf_size_stubs): Likewise. (ppc64_elf_build_stubs): Add new ELFv2 glink.
This commit is contained in:
@ -1,3 +1,16 @@
|
|||||||
|
2013-10-30 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
|
* elf64-ppc.c (PLT_ENTRY_SIZE, PLT_INITIAL_ENTRY_SIZE): Add htab
|
||||||
|
parameter and adjust for ELFv2. Update all uses.
|
||||||
|
(PLT_CALL_STUB_SIZE): Delete.
|
||||||
|
(ppc64_elf_get_synthetic_symtab): Support new glink layout.
|
||||||
|
(allocate_dynrelocs): Likewise.
|
||||||
|
(plt_stub_size, build_plt_stub): Adjust for ELFv2.
|
||||||
|
(get_r2off): Return 0 for ELFv2 -R.
|
||||||
|
(ppc_build_one_stub, ppc_size_one_stub): Adjust for ELFv2.
|
||||||
|
(ppc64_elf_size_stubs): Likewise.
|
||||||
|
(ppc64_elf_build_stubs): Add new ELFv2 glink.
|
||||||
|
|
||||||
2013-10-30 Alan Modra <amodra@gmail.com>
|
2013-10-30 Alan Modra <amodra@gmail.com>
|
||||||
Ulrich Weigand <uweigand@de.ibm.com>
|
Ulrich Weigand <uweigand@de.ibm.com>
|
||||||
|
|
||||||
|
170
bfd/elf64-ppc.c
170
bfd/elf64-ppc.c
@ -125,10 +125,10 @@ static bfd_vma opd_entry_value
|
|||||||
#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1"
|
#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1"
|
||||||
|
|
||||||
/* 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 24
|
#define PLT_ENTRY_SIZE(htab) (htab->opd_abi ? 24 : 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 PLT_ENTRY_SIZE
|
#define PLT_INITIAL_ENTRY_SIZE(htab) (htab->opd_abi ? 24 : 16)
|
||||||
|
|
||||||
/* TOC base pointers offset from start of TOC. */
|
/* TOC base pointers offset from start of TOC. */
|
||||||
#define TOC_BASE_OFF 0x8000
|
#define TOC_BASE_OFF 0x8000
|
||||||
@ -140,7 +140,6 @@ static bfd_vma opd_entry_value
|
|||||||
/* .plt call stub instructions. The normal stub is like this, but
|
/* .plt call stub instructions. The normal stub is like this, but
|
||||||
sometimes the .plt entry crosses a 64k boundary and we need to
|
sometimes the .plt entry crosses a 64k boundary and we need to
|
||||||
insert an addi to adjust r11. */
|
insert an addi to adjust r11. */
|
||||||
#define PLT_CALL_STUB_SIZE (7*4)
|
|
||||||
#define STD_R2_40R1 0xf8410028 /* std %r2,40(%r1) */
|
#define STD_R2_40R1 0xf8410028 /* std %r2,40(%r1) */
|
||||||
#define ADDIS_R11_R2 0x3d620000 /* addis %r11,%r2,xxx@ha */
|
#define ADDIS_R11_R2 0x3d620000 /* addis %r11,%r2,xxx@ha */
|
||||||
#define LD_R12_0R11 0xe98b0000 /* ld %r12,xxx+0@l(%r11) */
|
#define LD_R12_0R11 0xe98b0000 /* ld %r12,xxx+0@l(%r11) */
|
||||||
@ -184,6 +183,11 @@ static bfd_vma opd_entry_value
|
|||||||
/* mtctr %12 */
|
/* mtctr %12 */
|
||||||
/* ld %11,16(%11) */
|
/* ld %11,16(%11) */
|
||||||
/* bctr */
|
/* bctr */
|
||||||
|
#define MFLR_R0 0x7c0802a6 /* mflr %r0 */
|
||||||
|
#define MTLR_R0 0x7c0803a6 /* mtlr %r0 */
|
||||||
|
#define SUB_R12_R12_R11 0x7d8b6050 /* subf %r12,%r11,%r12 */
|
||||||
|
#define ADDI_R0_R12 0x380c0000 /* addi %r0,%r12,0 */
|
||||||
|
#define SRDI_R0_R0_2 0x7800f082 /* rldicl %r0,%r0,62,2 */
|
||||||
|
|
||||||
/* Pad with this. */
|
/* Pad with this. */
|
||||||
#define NOP 0x60000000
|
#define NOP 0x60000000
|
||||||
@ -3345,9 +3349,9 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
|
|||||||
|
|
||||||
if (dyn.d_tag == DT_PPC64_GLINK)
|
if (dyn.d_tag == DT_PPC64_GLINK)
|
||||||
{
|
{
|
||||||
/* The first glink stub starts at offset 32; see comment in
|
/* The first glink stub starts at offset 32; see
|
||||||
ppc64_elf_finish_dynamic_sections. */
|
comment in ppc64_elf_finish_dynamic_sections. */
|
||||||
glink_vma = dyn.d_un.d_val + 32;
|
glink_vma = dyn.d_un.d_val + GLINK_CALL_STUB_SIZE - 8 * 4;
|
||||||
/* The .glink section usually does not survive the final
|
/* The .glink section usually does not survive the final
|
||||||
link; search for the section (usually .text) where the
|
link; search for the section (usually .text) where the
|
||||||
glink stubs now reside. */
|
glink stubs now reside. */
|
||||||
@ -3365,13 +3369,21 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
|
|||||||
/* Determine __glink trampoline by reading the relative branch
|
/* Determine __glink trampoline by reading the relative branch
|
||||||
from the first glink stub. */
|
from the first glink stub. */
|
||||||
bfd_byte buf[4];
|
bfd_byte buf[4];
|
||||||
if (bfd_get_section_contents (abfd, glink, buf,
|
unsigned int off = 0;
|
||||||
glink_vma + 4 - glink->vma, 4))
|
|
||||||
|
while (bfd_get_section_contents (abfd, glink, buf,
|
||||||
|
glink_vma + off - glink->vma, 4))
|
||||||
{
|
{
|
||||||
unsigned int insn = bfd_get_32 (abfd, buf);
|
unsigned int insn = bfd_get_32 (abfd, buf);
|
||||||
insn ^= B_DOT;
|
insn ^= B_DOT;
|
||||||
if ((insn & ~0x3fffffc) == 0)
|
if ((insn & ~0x3fffffc) == 0)
|
||||||
resolv_vma = glink_vma + 4 + (insn ^ 0x2000000) - 0x2000000;
|
{
|
||||||
|
resolv_vma = glink_vma + off + (insn ^ 0x2000000) - 0x2000000;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
off += 4;
|
||||||
|
if (off > 4)
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (resolv_vma)
|
if (resolv_vma)
|
||||||
@ -3524,10 +3536,15 @@ ppc64_elf_get_synthetic_symtab (bfd *abfd,
|
|||||||
memcpy (names, "@plt", sizeof ("@plt"));
|
memcpy (names, "@plt", sizeof ("@plt"));
|
||||||
names += sizeof ("@plt");
|
names += sizeof ("@plt");
|
||||||
s++;
|
s++;
|
||||||
|
if (abi < 2)
|
||||||
|
{
|
||||||
glink_vma += 8;
|
glink_vma += 8;
|
||||||
if (i >= 0x8000)
|
if (i >= 0x8000)
|
||||||
glink_vma += 4;
|
glink_vma += 4;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
glink_vma += 4;
|
||||||
|
}
|
||||||
count += plt_count;
|
count += plt_count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -9227,7 +9244,7 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||||||
{
|
{
|
||||||
s = htab->iplt;
|
s = htab->iplt;
|
||||||
pent->plt.offset = s->size;
|
pent->plt.offset = s->size;
|
||||||
s->size += PLT_ENTRY_SIZE;
|
s->size += PLT_ENTRY_SIZE (htab);
|
||||||
s = htab->reliplt;
|
s = htab->reliplt;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -9236,21 +9253,26 @@ allocate_dynrelocs (struct elf_link_hash_entry *h, void *inf)
|
|||||||
first entry. */
|
first entry. */
|
||||||
s = htab->plt;
|
s = htab->plt;
|
||||||
if (s->size == 0)
|
if (s->size == 0)
|
||||||
s->size += PLT_INITIAL_ENTRY_SIZE;
|
s->size += PLT_INITIAL_ENTRY_SIZE (htab);
|
||||||
|
|
||||||
pent->plt.offset = s->size;
|
pent->plt.offset = s->size;
|
||||||
|
|
||||||
/* Make room for this entry. */
|
/* Make room for this entry. */
|
||||||
s->size += PLT_ENTRY_SIZE;
|
s->size += PLT_ENTRY_SIZE (htab);
|
||||||
|
|
||||||
/* Make room for the .glink code. */
|
/* Make room for the .glink code. */
|
||||||
s = htab->glink;
|
s = htab->glink;
|
||||||
if (s->size == 0)
|
if (s->size == 0)
|
||||||
s->size += GLINK_CALL_STUB_SIZE;
|
s->size += GLINK_CALL_STUB_SIZE;
|
||||||
|
if (htab->opd_abi)
|
||||||
|
{
|
||||||
/* We need bigger stubs past index 32767. */
|
/* We need bigger stubs past index 32767. */
|
||||||
if (s->size >= GLINK_CALL_STUB_SIZE + 32768*2*4)
|
if (s->size >= GLINK_CALL_STUB_SIZE + 32768*2*4)
|
||||||
s->size += 4;
|
s->size += 4;
|
||||||
s->size += 2*4;
|
s->size += 2*4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
s->size += 4;
|
||||||
|
|
||||||
/* 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->relplt;
|
s = htab->relplt;
|
||||||
@ -9603,7 +9625,7 @@ ppc64_elf_size_dynamic_sections (bfd *output_bfd,
|
|||||||
{
|
{
|
||||||
s = htab->iplt;
|
s = htab->iplt;
|
||||||
ent->plt.offset = s->size;
|
ent->plt.offset = s->size;
|
||||||
s->size += PLT_ENTRY_SIZE;
|
s->size += PLT_ENTRY_SIZE (htab);
|
||||||
|
|
||||||
htab->reliplt->size += sizeof (Elf64_External_Rela);
|
htab->reliplt->size += sizeof (Elf64_External_Rela);
|
||||||
}
|
}
|
||||||
@ -9937,19 +9959,23 @@ plt_stub_size (struct ppc_link_hash_table *htab,
|
|||||||
struct ppc_stub_hash_entry *stub_entry,
|
struct ppc_stub_hash_entry *stub_entry,
|
||||||
bfd_vma off)
|
bfd_vma off)
|
||||||
{
|
{
|
||||||
unsigned size = PLT_CALL_STUB_SIZE;
|
unsigned size = 12;
|
||||||
|
|
||||||
if (!(ALWAYS_EMIT_R2SAVE
|
if (ALWAYS_EMIT_R2SAVE
|
||||||
|| stub_entry->stub_type == ppc_stub_plt_call_r2save))
|
|| stub_entry->stub_type == ppc_stub_plt_call_r2save)
|
||||||
size -= 4;
|
size += 4;
|
||||||
if (!htab->plt_static_chain)
|
if (PPC_HA (off) != 0)
|
||||||
size -= 4;
|
size += 4;
|
||||||
|
if (htab->opd_abi)
|
||||||
|
{
|
||||||
|
size += 4;
|
||||||
|
if (htab->plt_static_chain)
|
||||||
|
size += 4;
|
||||||
if (htab->plt_thread_safe)
|
if (htab->plt_thread_safe)
|
||||||
size += 8;
|
size += 8;
|
||||||
if (PPC_HA (off) == 0)
|
|
||||||
size -= 4;
|
|
||||||
if (PPC_HA (off + 8 + 8 * htab->plt_static_chain) != PPC_HA (off))
|
if (PPC_HA (off + 8 + 8 * htab->plt_static_chain) != PPC_HA (off))
|
||||||
size += 4;
|
size += 4;
|
||||||
|
}
|
||||||
if (stub_entry->h != NULL
|
if (stub_entry->h != NULL
|
||||||
&& (stub_entry->h == htab->tls_get_addr_fd
|
&& (stub_entry->h == htab->tls_get_addr_fd
|
||||||
|| stub_entry->h == htab->tls_get_addr)
|
|| stub_entry->h == htab->tls_get_addr)
|
||||||
@ -9983,12 +10009,14 @@ build_plt_stub (struct ppc_link_hash_table *htab,
|
|||||||
bfd_byte *p, bfd_vma offset, Elf_Internal_Rela *r)
|
bfd_byte *p, bfd_vma offset, Elf_Internal_Rela *r)
|
||||||
{
|
{
|
||||||
bfd *obfd = htab->stub_bfd;
|
bfd *obfd = htab->stub_bfd;
|
||||||
|
bfd_boolean plt_load_toc = htab->opd_abi;
|
||||||
bfd_boolean plt_static_chain = htab->plt_static_chain;
|
bfd_boolean plt_static_chain = htab->plt_static_chain;
|
||||||
bfd_boolean plt_thread_safe = htab->plt_thread_safe;
|
bfd_boolean plt_thread_safe = htab->plt_thread_safe;
|
||||||
bfd_boolean use_fake_dep = plt_thread_safe;
|
bfd_boolean use_fake_dep = plt_thread_safe;
|
||||||
bfd_vma cmp_branch_off = 0;
|
bfd_vma cmp_branch_off = 0;
|
||||||
|
|
||||||
if (!ALWAYS_USE_FAKE_DEP
|
if (!ALWAYS_USE_FAKE_DEP
|
||||||
|
&& plt_load_toc
|
||||||
&& plt_thread_safe
|
&& plt_thread_safe
|
||||||
&& !(stub_entry->h != NULL
|
&& !(stub_entry->h != NULL
|
||||||
&& (stub_entry->h == htab->tls_get_addr_fd
|
&& (stub_entry->h == htab->tls_get_addr_fd
|
||||||
@ -9996,7 +10024,8 @@ build_plt_stub (struct ppc_link_hash_table *htab,
|
|||||||
&& !htab->no_tls_get_addr_opt))
|
&& !htab->no_tls_get_addr_opt))
|
||||||
{
|
{
|
||||||
bfd_vma pltoff = stub_entry->plt_ent->plt.offset & ~1;
|
bfd_vma pltoff = stub_entry->plt_ent->plt.offset & ~1;
|
||||||
bfd_vma pltindex = (pltoff - PLT_INITIAL_ENTRY_SIZE) / PLT_ENTRY_SIZE;
|
bfd_vma pltindex = ((pltoff - PLT_INITIAL_ENTRY_SIZE (htab))
|
||||||
|
/ PLT_ENTRY_SIZE (htab));
|
||||||
bfd_vma glinkoff = GLINK_CALL_STUB_SIZE + pltindex * 8;
|
bfd_vma glinkoff = GLINK_CALL_STUB_SIZE + pltindex * 8;
|
||||||
bfd_vma to, from;
|
bfd_vma to, from;
|
||||||
|
|
||||||
@ -10030,6 +10059,8 @@ build_plt_stub (struct ppc_link_hash_table *htab,
|
|||||||
r[1].r_offset = r[0].r_offset + 4;
|
r[1].r_offset = r[0].r_offset + 4;
|
||||||
r[1].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO_DS);
|
r[1].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO_DS);
|
||||||
r[1].r_addend = r[0].r_addend;
|
r[1].r_addend = r[0].r_addend;
|
||||||
|
if (plt_load_toc)
|
||||||
|
{
|
||||||
if (PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
|
if (PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
|
||||||
{
|
{
|
||||||
r[2].r_offset = r[1].r_offset + 4;
|
r[2].r_offset = r[1].r_offset + 4;
|
||||||
@ -10049,17 +10080,21 @@ build_plt_stub (struct ppc_link_hash_table *htab,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (ALWAYS_EMIT_R2SAVE
|
if (ALWAYS_EMIT_R2SAVE
|
||||||
|| stub_entry->stub_type == ppc_stub_plt_call_r2save)
|
|| stub_entry->stub_type == ppc_stub_plt_call_r2save)
|
||||||
bfd_put_32 (obfd, STD_R2_40R1, p), p += 4;
|
bfd_put_32 (obfd, STD_R2_40R1, p), p += 4;
|
||||||
bfd_put_32 (obfd, ADDIS_R11_R2 | PPC_HA (offset), p), p += 4;
|
bfd_put_32 (obfd, ADDIS_R11_R2 | PPC_HA (offset), p), p += 4;
|
||||||
bfd_put_32 (obfd, LD_R12_0R11 | PPC_LO (offset), p), p += 4;
|
bfd_put_32 (obfd, LD_R12_0R11 | PPC_LO (offset), p), p += 4;
|
||||||
if (PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
|
if (plt_load_toc
|
||||||
|
&& PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
|
||||||
{
|
{
|
||||||
bfd_put_32 (obfd, ADDI_R11_R11 | PPC_LO (offset), p), p += 4;
|
bfd_put_32 (obfd, ADDI_R11_R11 | PPC_LO (offset), p), p += 4;
|
||||||
offset = 0;
|
offset = 0;
|
||||||
}
|
}
|
||||||
bfd_put_32 (obfd, MTCTR_R12, p), p += 4;
|
bfd_put_32 (obfd, MTCTR_R12, p), p += 4;
|
||||||
|
if (plt_load_toc)
|
||||||
|
{
|
||||||
if (use_fake_dep)
|
if (use_fake_dep)
|
||||||
{
|
{
|
||||||
bfd_put_32 (obfd, XOR_R2_R12_R12, p), p += 4;
|
bfd_put_32 (obfd, XOR_R2_R12_R12, p), p += 4;
|
||||||
@ -10069,6 +10104,7 @@ build_plt_stub (struct ppc_link_hash_table *htab,
|
|||||||
if (plt_static_chain)
|
if (plt_static_chain)
|
||||||
bfd_put_32 (obfd, LD_R11_0R11 | PPC_LO (offset + 16), p), p += 4;
|
bfd_put_32 (obfd, LD_R11_0R11 | PPC_LO (offset + 16), p), p += 4;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (r != NULL)
|
if (r != NULL)
|
||||||
@ -10077,6 +10113,8 @@ build_plt_stub (struct ppc_link_hash_table *htab,
|
|||||||
|| stub_entry->stub_type == ppc_stub_plt_call_r2save)
|
|| stub_entry->stub_type == ppc_stub_plt_call_r2save)
|
||||||
r[0].r_offset += 4;
|
r[0].r_offset += 4;
|
||||||
r[0].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
|
r[0].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
|
||||||
|
if (plt_load_toc)
|
||||||
|
{
|
||||||
if (PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
|
if (PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
|
||||||
{
|
{
|
||||||
r[1].r_offset = r[0].r_offset + 4;
|
r[1].r_offset = r[0].r_offset + 4;
|
||||||
@ -10096,16 +10134,20 @@ build_plt_stub (struct ppc_link_hash_table *htab,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (ALWAYS_EMIT_R2SAVE
|
if (ALWAYS_EMIT_R2SAVE
|
||||||
|| stub_entry->stub_type == ppc_stub_plt_call_r2save)
|
|| stub_entry->stub_type == ppc_stub_plt_call_r2save)
|
||||||
bfd_put_32 (obfd, STD_R2_40R1, p), p += 4;
|
bfd_put_32 (obfd, STD_R2_40R1, p), p += 4;
|
||||||
bfd_put_32 (obfd, LD_R12_0R2 | PPC_LO (offset), p), p += 4;
|
bfd_put_32 (obfd, LD_R12_0R2 | PPC_LO (offset), p), p += 4;
|
||||||
if (PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
|
if (plt_load_toc
|
||||||
|
&& PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
|
||||||
{
|
{
|
||||||
bfd_put_32 (obfd, ADDI_R2_R2 | PPC_LO (offset), p), p += 4;
|
bfd_put_32 (obfd, ADDI_R2_R2 | PPC_LO (offset), p), p += 4;
|
||||||
offset = 0;
|
offset = 0;
|
||||||
}
|
}
|
||||||
bfd_put_32 (obfd, MTCTR_R12, p), p += 4;
|
bfd_put_32 (obfd, MTCTR_R12, p), p += 4;
|
||||||
|
if (plt_load_toc)
|
||||||
|
{
|
||||||
if (use_fake_dep)
|
if (use_fake_dep)
|
||||||
{
|
{
|
||||||
bfd_put_32 (obfd, XOR_R11_R12_R12, p), p += 4;
|
bfd_put_32 (obfd, XOR_R11_R12_R12, p), p += 4;
|
||||||
@ -10115,7 +10157,8 @@ build_plt_stub (struct ppc_link_hash_table *htab,
|
|||||||
bfd_put_32 (obfd, LD_R11_0R2 | PPC_LO (offset + 16), p), p += 4;
|
bfd_put_32 (obfd, LD_R11_0R2 | PPC_LO (offset + 16), p), p += 4;
|
||||||
bfd_put_32 (obfd, LD_R2_0R2 | PPC_LO (offset + 8), p), p += 4;
|
bfd_put_32 (obfd, LD_R2_0R2 | PPC_LO (offset + 8), p), p += 4;
|
||||||
}
|
}
|
||||||
if (plt_thread_safe && !use_fake_dep)
|
}
|
||||||
|
if (plt_load_toc && plt_thread_safe && !use_fake_dep)
|
||||||
{
|
{
|
||||||
bfd_put_32 (obfd, CMPLDI_R2_0, p), p += 4;
|
bfd_put_32 (obfd, CMPLDI_R2_0, p), p += 4;
|
||||||
bfd_put_32 (obfd, BNECTR_P4, p), p += 4;
|
bfd_put_32 (obfd, BNECTR_P4, p), p += 4;
|
||||||
@ -10214,6 +10257,8 @@ get_r2off (struct bfd_link_info *info,
|
|||||||
/* Support linking -R objects. Get the toc pointer from the
|
/* Support linking -R objects. Get the toc pointer from the
|
||||||
opd entry. */
|
opd entry. */
|
||||||
char buf[8];
|
char buf[8];
|
||||||
|
if (!htab->opd_abi)
|
||||||
|
return r2off;
|
||||||
asection *opd = stub_entry->h->elf.root.u.def.section;
|
asection *opd = stub_entry->h->elf.root.u.def.section;
|
||||||
bfd_vma opd_off = stub_entry->h->elf.root.u.def.value;
|
bfd_vma opd_off = stub_entry->h->elf.root.u.def.value;
|
||||||
|
|
||||||
@ -10443,7 +10488,8 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
|||||||
r[0].r_offset = loc - stub_entry->stub_sec->contents;
|
r[0].r_offset = loc - stub_entry->stub_sec->contents;
|
||||||
if (bfd_big_endian (info->output_bfd))
|
if (bfd_big_endian (info->output_bfd))
|
||||||
r[0].r_offset += 2;
|
r[0].r_offset += 2;
|
||||||
if (stub_entry->stub_type == ppc_stub_plt_branch_r2off)
|
if (stub_entry->stub_type == ppc_stub_plt_branch_r2off
|
||||||
|
&& htab->opd_abi)
|
||||||
r[0].r_offset += 4;
|
r[0].r_offset += 4;
|
||||||
r[0].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
|
r[0].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
|
||||||
r[0].r_addend = dest;
|
r[0].r_addend = dest;
|
||||||
@ -10456,7 +10502,8 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stub_entry->stub_type != ppc_stub_plt_branch_r2off)
|
if (stub_entry->stub_type != ppc_stub_plt_branch_r2off
|
||||||
|
|| !htab->opd_abi)
|
||||||
{
|
{
|
||||||
if (PPC_HA (off) != 0)
|
if (PPC_HA (off) != 0)
|
||||||
{
|
{
|
||||||
@ -10707,10 +10754,11 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
|||||||
if (info->emitrelocations)
|
if (info->emitrelocations)
|
||||||
{
|
{
|
||||||
stub_entry->stub_sec->reloc_count
|
stub_entry->stub_sec->reloc_count
|
||||||
+= (2
|
+= ((PPC_HA (off) != 0)
|
||||||
+ (PPC_HA (off) != 0)
|
+ (htab->opd_abi
|
||||||
+ (htab->plt_static_chain
|
? 2 + (htab->plt_static_chain
|
||||||
&& PPC_HA (off + 16) == PPC_HA (off)));
|
&& PPC_HA (off + 16) == PPC_HA (off))
|
||||||
|
: 1));
|
||||||
stub_entry->stub_sec->flags |= SEC_RELOC;
|
stub_entry->stub_sec->flags |= SEC_RELOC;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -10737,7 +10785,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
|||||||
if (stub_entry->stub_type == ppc_stub_long_branch_r2off)
|
if (stub_entry->stub_type == ppc_stub_long_branch_r2off)
|
||||||
{
|
{
|
||||||
r2off = get_r2off (info, stub_entry);
|
r2off = get_r2off (info, stub_entry);
|
||||||
if (r2off == 0)
|
if (r2off == 0 && htab->opd_abi)
|
||||||
{
|
{
|
||||||
htab->stub_error = TRUE;
|
htab->stub_error = TRUE;
|
||||||
return FALSE;
|
return FALSE;
|
||||||
@ -10750,8 +10798,11 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
|||||||
|
|
||||||
local_off = PPC64_LOCAL_ENTRY_OFFSET (stub_entry->other);
|
local_off = PPC64_LOCAL_ENTRY_OFFSET (stub_entry->other);
|
||||||
|
|
||||||
/* If the branch offset if too big, use a ppc_stub_plt_branch. */
|
/* If the branch offset if too big, use a ppc_stub_plt_branch.
|
||||||
if (off + (1 << 25) >= (bfd_vma) (1 << 26) - local_off)
|
Do the same for -R objects without function descriptors. */
|
||||||
|
if (off + (1 << 25) >= (bfd_vma) (1 << 26) - local_off
|
||||||
|
|| (stub_entry->stub_type == ppc_stub_long_branch_r2off
|
||||||
|
&& r2off == 0))
|
||||||
{
|
{
|
||||||
struct ppc_branch_hash_entry *br_entry;
|
struct ppc_branch_hash_entry *br_entry;
|
||||||
|
|
||||||
@ -10794,7 +10845,8 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
|||||||
stub_entry->stub_sec->flags |= SEC_RELOC;
|
stub_entry->stub_sec->flags |= SEC_RELOC;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stub_entry->stub_type != ppc_stub_plt_branch_r2off)
|
if (stub_entry->stub_type != ppc_stub_plt_branch_r2off
|
||||||
|
|| !htab->opd_abi)
|
||||||
{
|
{
|
||||||
size = 12;
|
size = 12;
|
||||||
if (PPC_HA (off) != 0)
|
if (PPC_HA (off) != 0)
|
||||||
@ -11698,7 +11750,9 @@ ppc64_elf_size_stubs (struct bfd_link_info *info, bfd_signed_vma group_size,
|
|||||||
htab->plt_stub_align = plt_stub_align;
|
htab->plt_stub_align = plt_stub_align;
|
||||||
if (plt_thread_safe == -1 && !info->executable)
|
if (plt_thread_safe == -1 && !info->executable)
|
||||||
plt_thread_safe = 1;
|
plt_thread_safe = 1;
|
||||||
if (plt_thread_safe == -1)
|
if (!htab->opd_abi)
|
||||||
|
plt_thread_safe = 0;
|
||||||
|
else if (plt_thread_safe == -1)
|
||||||
{
|
{
|
||||||
static const char *const thread_starter[] =
|
static const char *const thread_starter[] =
|
||||||
{
|
{
|
||||||
@ -12281,6 +12335,8 @@ ppc64_elf_build_stubs (bfd_boolean emit_stub_syms,
|
|||||||
plt0 -= htab->glink->output_section->vma + htab->glink->output_offset;
|
plt0 -= htab->glink->output_section->vma + htab->glink->output_offset;
|
||||||
bfd_put_64 (htab->glink->owner, plt0, p);
|
bfd_put_64 (htab->glink->owner, plt0, p);
|
||||||
p += 8;
|
p += 8;
|
||||||
|
if (htab->opd_abi)
|
||||||
|
{
|
||||||
bfd_put_32 (htab->glink->owner, MFLR_R12, p);
|
bfd_put_32 (htab->glink->owner, MFLR_R12, p);
|
||||||
p += 4;
|
p += 4;
|
||||||
bfd_put_32 (htab->glink->owner, BCL_20_31, p);
|
bfd_put_32 (htab->glink->owner, BCL_20_31, p);
|
||||||
@ -12301,6 +12357,34 @@ ppc64_elf_build_stubs (bfd_boolean emit_stub_syms,
|
|||||||
p += 4;
|
p += 4;
|
||||||
bfd_put_32 (htab->glink->owner, LD_R11_0R11 | 16, p);
|
bfd_put_32 (htab->glink->owner, LD_R11_0R11 | 16, p);
|
||||||
p += 4;
|
p += 4;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bfd_put_32 (htab->glink->owner, MFLR_R0, p);
|
||||||
|
p += 4;
|
||||||
|
bfd_put_32 (htab->glink->owner, BCL_20_31, p);
|
||||||
|
p += 4;
|
||||||
|
bfd_put_32 (htab->glink->owner, MFLR_R11, p);
|
||||||
|
p += 4;
|
||||||
|
bfd_put_32 (htab->glink->owner, LD_R2_0R11 | (-16 & 0xfffc), p);
|
||||||
|
p += 4;
|
||||||
|
bfd_put_32 (htab->glink->owner, MTLR_R0, p);
|
||||||
|
p += 4;
|
||||||
|
bfd_put_32 (htab->glink->owner, SUB_R12_R12_R11, p);
|
||||||
|
p += 4;
|
||||||
|
bfd_put_32 (htab->glink->owner, ADD_R11_R2_R11, p);
|
||||||
|
p += 4;
|
||||||
|
bfd_put_32 (htab->glink->owner, ADDI_R0_R12 | (-48 & 0xffff), p);
|
||||||
|
p += 4;
|
||||||
|
bfd_put_32 (htab->glink->owner, LD_R12_0R11, p);
|
||||||
|
p += 4;
|
||||||
|
bfd_put_32 (htab->glink->owner, SRDI_R0_R0_2, p);
|
||||||
|
p += 4;
|
||||||
|
bfd_put_32 (htab->glink->owner, MTCTR_R12, p);
|
||||||
|
p += 4;
|
||||||
|
bfd_put_32 (htab->glink->owner, LD_R11_0R11 | 8, p);
|
||||||
|
p += 4;
|
||||||
|
}
|
||||||
bfd_put_32 (htab->glink->owner, BCTR, p);
|
bfd_put_32 (htab->glink->owner, BCTR, p);
|
||||||
p += 4;
|
p += 4;
|
||||||
while (p - htab->glink->contents < GLINK_CALL_STUB_SIZE)
|
while (p - htab->glink->contents < GLINK_CALL_STUB_SIZE)
|
||||||
@ -12312,6 +12396,8 @@ ppc64_elf_build_stubs (bfd_boolean emit_stub_syms,
|
|||||||
/* Build the .glink lazy link call stubs. */
|
/* Build the .glink lazy link call stubs. */
|
||||||
indx = 0;
|
indx = 0;
|
||||||
while (p < htab->glink->contents + htab->glink->size)
|
while (p < htab->glink->contents + htab->glink->size)
|
||||||
|
{
|
||||||
|
if (htab->opd_abi)
|
||||||
{
|
{
|
||||||
if (indx < 0x8000)
|
if (indx < 0x8000)
|
||||||
{
|
{
|
||||||
@ -12322,9 +12408,11 @@ ppc64_elf_build_stubs (bfd_boolean emit_stub_syms,
|
|||||||
{
|
{
|
||||||
bfd_put_32 (htab->glink->owner, LIS_R0_0 | PPC_HI (indx), p);
|
bfd_put_32 (htab->glink->owner, LIS_R0_0 | PPC_HI (indx), p);
|
||||||
p += 4;
|
p += 4;
|
||||||
bfd_put_32 (htab->glink->owner, ORI_R0_R0_0 | PPC_LO (indx), p);
|
bfd_put_32 (htab->glink->owner, ORI_R0_R0_0 | PPC_LO (indx),
|
||||||
|
p);
|
||||||
p += 4;
|
p += 4;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
bfd_put_32 (htab->glink->owner,
|
bfd_put_32 (htab->glink->owner,
|
||||||
B_DOT | ((htab->glink->contents - p + 8) & 0x3fffffc), p);
|
B_DOT | ((htab->glink->contents - p + 8) & 0x3fffffc), p);
|
||||||
indx++;
|
indx++;
|
||||||
@ -14451,8 +14539,8 @@ ppc64_elf_finish_dynamic_symbol (bfd *output_bfd,
|
|||||||
rela.r_info = ELF64_R_INFO (h->dynindx, R_PPC64_JMP_SLOT);
|
rela.r_info = ELF64_R_INFO (h->dynindx, R_PPC64_JMP_SLOT);
|
||||||
rela.r_addend = ent->addend;
|
rela.r_addend = ent->addend;
|
||||||
loc = (htab->relplt->contents
|
loc = (htab->relplt->contents
|
||||||
+ ((ent->plt.offset - PLT_INITIAL_ENTRY_SIZE)
|
+ ((ent->plt.offset - PLT_INITIAL_ENTRY_SIZE (htab))
|
||||||
/ (PLT_ENTRY_SIZE / sizeof (Elf64_External_Rela))));
|
/ PLT_ENTRY_SIZE (htab) * sizeof (Elf64_External_Rela)));
|
||||||
}
|
}
|
||||||
bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
|
bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
|
||||||
}
|
}
|
||||||
@ -14553,7 +14641,7 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd,
|
|||||||
of glink rather than the first entry point, which is
|
of glink rather than the first entry point, which is
|
||||||
what ld.so needs, and now have a bigger stub to
|
what ld.so needs, and now have a bigger stub to
|
||||||
support automatic multiple TOCs. */
|
support automatic multiple TOCs. */
|
||||||
dyn.d_un.d_ptr += GLINK_CALL_STUB_SIZE - 32;
|
dyn.d_un.d_ptr += GLINK_CALL_STUB_SIZE - 8 * 4;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case DT_PPC64_OPD:
|
case DT_PPC64_OPD:
|
||||||
@ -14626,7 +14714,7 @@ ppc64_elf_finish_dynamic_sections (bfd *output_bfd,
|
|||||||
{
|
{
|
||||||
/* Set .plt entry size. */
|
/* Set .plt entry size. */
|
||||||
elf_section_data (htab->plt->output_section)->this_hdr.sh_entsize
|
elf_section_data (htab->plt->output_section)->this_hdr.sh_entsize
|
||||||
= PLT_ENTRY_SIZE;
|
= PLT_ENTRY_SIZE (htab);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* brlt is SEC_LINKER_CREATED, so we need to write out relocs for
|
/* brlt is SEC_LINKER_CREATED, so we need to write out relocs for
|
||||||
|
Reference in New Issue
Block a user