|
|
7ab123 |
commit b9e5796b0d6ebc355e4a6d06791b7366939d10f2
|
|
|
7ab123 |
Author: Alan Modra <amodra@gmail.com>
|
|
|
7ab123 |
Date: Tue Oct 29 15:58:05 2013 +1030
|
|
|
7ab123 |
|
|
|
7ab123 |
ELFv2 stub, plt and glink changes
|
|
|
7ab123 |
|
|
|
7ab123 |
An ELFv2 PLT entry is simply the address of the target function rather
|
|
|
7ab123 |
than three (or two) words to specify entry, toc and static chain. PLT
|
|
|
7ab123 |
call stubs are correspondingly simpler and need no thread safety
|
|
|
7ab123 |
barrier. The glink resolver stub and branch table also is simplified,
|
|
|
7ab123 |
a change that could be applied to ELFv1 too, but isn't as yet.
|
|
|
7ab123 |
|
|
|
7ab123 |
* elf64-ppc.c (PLT_ENTRY_SIZE, PLT_INITIAL_ENTRY_SIZE): Add htab
|
|
|
7ab123 |
parameter and adjust for ELFv2. Update all uses.
|
|
|
7ab123 |
(PLT_CALL_STUB_SIZE): Delete.
|
|
|
7ab123 |
(ppc64_elf_get_synthetic_symtab): Support new glink layout.
|
|
|
7ab123 |
(allocate_dynrelocs): Likewise.
|
|
|
7ab123 |
(plt_stub_size, build_plt_stub): Adjust for ELFv2.
|
|
|
7ab123 |
(get_r2off): Return 0 for ELFv2 -R.
|
|
|
7ab123 |
(ppc_build_one_stub, ppc_size_one_stub): Adjust for ELFv2.
|
|
|
7ab123 |
(ppc64_elf_size_stubs): Likewise.
|
|
|
7ab123 |
(ppc64_elf_build_stubs): Add new ELFv2 glink.
|
|
|
7ab123 |
|
|
|
7ab123 |
Index: gdb-7.6.1/bfd/elf64-ppc.c
|
|
|
7ab123 |
===================================================================
|
|
|
7ab123 |
--- gdb-7.6.1.orig/bfd/elf64-ppc.c
|
|
|
7ab123 |
+++ gdb-7.6.1/bfd/elf64-ppc.c
|
|
|
7ab123 |
@@ -125,10 +125,10 @@ static bfd_vma opd_entry_value
|
|
|
7ab123 |
#define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1"
|
|
|
7ab123 |
|
|
|
7ab123 |
/* The size in bytes of an entry in the procedure linkage table. */
|
|
|
7ab123 |
-#define PLT_ENTRY_SIZE 24
|
|
|
7ab123 |
+#define PLT_ENTRY_SIZE(htab) (htab->opd_abi ? 24 : 8)
|
|
|
7ab123 |
|
|
|
7ab123 |
/* The initial size of the plt reserved for the dynamic linker. */
|
|
|
7ab123 |
-#define PLT_INITIAL_ENTRY_SIZE PLT_ENTRY_SIZE
|
|
|
7ab123 |
+#define PLT_INITIAL_ENTRY_SIZE(htab) (htab->opd_abi ? 24 : 16)
|
|
|
7ab123 |
|
|
|
7ab123 |
/* TOC base pointers offset from start of TOC. */
|
|
|
7ab123 |
#define TOC_BASE_OFF 0x8000
|
|
|
7ab123 |
@@ -140,7 +140,6 @@ static bfd_vma opd_entry_value
|
|
|
7ab123 |
/* .plt call stub instructions. The normal stub is like this, but
|
|
|
7ab123 |
sometimes the .plt entry crosses a 64k boundary and we need to
|
|
|
7ab123 |
insert an addi to adjust r11. */
|
|
|
7ab123 |
-#define PLT_CALL_STUB_SIZE (7*4)
|
|
|
7ab123 |
#define STD_R2_40R1 0xf8410028 /* std %r2,40(%r1) */
|
|
|
7ab123 |
#define ADDIS_R11_R2 0x3d620000 /* addis %r11,%r2,xxx@ha */
|
|
|
7ab123 |
#define LD_R12_0R11 0xe98b0000 /* ld %r12,xxx+0@l(%r11) */
|
|
|
7ab123 |
@@ -184,6 +183,11 @@ static bfd_vma opd_entry_value
|
|
|
7ab123 |
/* mtctr %12 */
|
|
|
7ab123 |
/* ld %11,16(%11) */
|
|
|
7ab123 |
/* bctr */
|
|
|
7ab123 |
+#define MFLR_R0 0x7c0802a6 /* mflr %r0 */
|
|
|
7ab123 |
+#define MTLR_R0 0x7c0803a6 /* mtlr %r0 */
|
|
|
7ab123 |
+#define SUB_R12_R12_R11 0x7d8b6050 /* subf %r12,%r11,%r12 */
|
|
|
7ab123 |
+#define ADDI_R0_R12 0x380c0000 /* addi %r0,%r12,0 */
|
|
|
7ab123 |
+#define SRDI_R0_R0_2 0x7800f082 /* rldicl %r0,%r0,62,2 */
|
|
|
7ab123 |
|
|
|
7ab123 |
/* Pad with this. */
|
|
|
7ab123 |
#define NOP 0x60000000
|
|
|
7ab123 |
@@ -3238,9 +3242,9 @@ ppc64_elf_get_synthetic_symtab (bfd *abf
|
|
|
7ab123 |
|
|
|
7ab123 |
if (dyn.d_tag == DT_PPC64_GLINK)
|
|
|
7ab123 |
{
|
|
|
7ab123 |
- /* The first glink stub starts at offset 32; see comment in
|
|
|
7ab123 |
- ppc64_elf_finish_dynamic_sections. */
|
|
|
7ab123 |
- glink_vma = dyn.d_un.d_val + 32;
|
|
|
7ab123 |
+ /* The first glink stub starts at offset 32; see
|
|
|
7ab123 |
+ comment in ppc64_elf_finish_dynamic_sections. */
|
|
|
7ab123 |
+ glink_vma = dyn.d_un.d_val + GLINK_CALL_STUB_SIZE - 8 * 4;
|
|
|
7ab123 |
/* The .glink section usually does not survive the final
|
|
|
7ab123 |
link; search for the section (usually .text) where the
|
|
|
7ab123 |
glink stubs now reside. */
|
|
|
7ab123 |
@@ -3258,13 +3262,21 @@ ppc64_elf_get_synthetic_symtab (bfd *abf
|
|
|
7ab123 |
/* Determine __glink trampoline by reading the relative branch
|
|
|
7ab123 |
from the first glink stub. */
|
|
|
7ab123 |
bfd_byte buf[4];
|
|
|
7ab123 |
- if (bfd_get_section_contents (abfd, glink, buf,
|
|
|
7ab123 |
- glink_vma + 4 - glink->vma, 4))
|
|
|
7ab123 |
+ unsigned int off = 0;
|
|
|
7ab123 |
+
|
|
|
7ab123 |
+ while (bfd_get_section_contents (abfd, glink, buf,
|
|
|
7ab123 |
+ glink_vma + off - glink->vma, 4))
|
|
|
7ab123 |
{
|
|
|
7ab123 |
unsigned int insn = bfd_get_32 (abfd, buf);
|
|
|
7ab123 |
insn ^= B_DOT;
|
|
|
7ab123 |
if ((insn & ~0x3fffffc) == 0)
|
|
|
7ab123 |
- resolv_vma = glink_vma + 4 + (insn ^ 0x2000000) - 0x2000000;
|
|
|
7ab123 |
+ {
|
|
|
7ab123 |
+ resolv_vma = glink_vma + off + (insn ^ 0x2000000) - 0x2000000;
|
|
|
7ab123 |
+ break;
|
|
|
7ab123 |
+ }
|
|
|
7ab123 |
+ off += 4;
|
|
|
7ab123 |
+ if (off > 4)
|
|
|
7ab123 |
+ break;
|
|
|
7ab123 |
}
|
|
|
7ab123 |
|
|
|
7ab123 |
if (resolv_vma)
|
|
|
7ab123 |
@@ -3417,8 +3429,13 @@ ppc64_elf_get_synthetic_symtab (bfd *abf
|
|
|
7ab123 |
memcpy (names, "@plt", sizeof ("@plt"));
|
|
|
7ab123 |
names += sizeof ("@plt");
|
|
|
7ab123 |
s++;
|
|
|
7ab123 |
- glink_vma += 8;
|
|
|
7ab123 |
- if (i >= 0x8000)
|
|
|
7ab123 |
+ if (abi < 2)
|
|
|
7ab123 |
+ {
|
|
|
7ab123 |
+ glink_vma += 8;
|
|
|
7ab123 |
+ if (i >= 0x8000)
|
|
|
7ab123 |
+ glink_vma += 4;
|
|
|
7ab123 |
+ }
|
|
|
7ab123 |
+ else
|
|
|
7ab123 |
glink_vma += 4;
|
|
|
7ab123 |
}
|
|
|
7ab123 |
count += plt_count;
|
|
|
7ab123 |
@@ -9021,7 +9038,7 @@ allocate_dynrelocs (struct elf_link_hash
|
|
|
7ab123 |
{
|
|
|
7ab123 |
s = htab->iplt;
|
|
|
7ab123 |
pent->plt.offset = s->size;
|
|
|
7ab123 |
- s->size += PLT_ENTRY_SIZE;
|
|
|
7ab123 |
+ s->size += PLT_ENTRY_SIZE (htab);
|
|
|
7ab123 |
s = htab->reliplt;
|
|
|
7ab123 |
}
|
|
|
7ab123 |
else
|
|
|
7ab123 |
@@ -9030,21 +9047,26 @@ allocate_dynrelocs (struct elf_link_hash
|
|
|
7ab123 |
first entry. */
|
|
|
7ab123 |
s = htab->plt;
|
|
|
7ab123 |
if (s->size == 0)
|
|
|
7ab123 |
- s->size += PLT_INITIAL_ENTRY_SIZE;
|
|
|
7ab123 |
+ s->size += PLT_INITIAL_ENTRY_SIZE (htab);
|
|
|
7ab123 |
|
|
|
7ab123 |
pent->plt.offset = s->size;
|
|
|
7ab123 |
|
|
|
7ab123 |
/* Make room for this entry. */
|
|
|
7ab123 |
- s->size += PLT_ENTRY_SIZE;
|
|
|
7ab123 |
+ s->size += PLT_ENTRY_SIZE (htab);
|
|
|
7ab123 |
|
|
|
7ab123 |
/* Make room for the .glink code. */
|
|
|
7ab123 |
s = htab->glink;
|
|
|
7ab123 |
if (s->size == 0)
|
|
|
7ab123 |
s->size += GLINK_CALL_STUB_SIZE;
|
|
|
7ab123 |
- /* We need bigger stubs past index 32767. */
|
|
|
7ab123 |
- if (s->size >= GLINK_CALL_STUB_SIZE + 32768*2*4)
|
|
|
7ab123 |
+ if (htab->opd_abi)
|
|
|
7ab123 |
+ {
|
|
|
7ab123 |
+ /* We need bigger stubs past index 32767. */
|
|
|
7ab123 |
+ if (s->size >= GLINK_CALL_STUB_SIZE + 32768*2*4)
|
|
|
7ab123 |
+ s->size += 4;
|
|
|
7ab123 |
+ s->size += 2*4;
|
|
|
7ab123 |
+ }
|
|
|
7ab123 |
+ else
|
|
|
7ab123 |
s->size += 4;
|
|
|
7ab123 |
- s->size += 2*4;
|
|
|
7ab123 |
|
|
|
7ab123 |
/* We also need to make an entry in the .rela.plt section. */
|
|
|
7ab123 |
s = htab->relplt;
|
|
|
7ab123 |
@@ -9393,7 +9415,7 @@ ppc64_elf_size_dynamic_sections (bfd *ou
|
|
|
7ab123 |
{
|
|
|
7ab123 |
s = htab->iplt;
|
|
|
7ab123 |
ent->plt.offset = s->size;
|
|
|
7ab123 |
- s->size += PLT_ENTRY_SIZE;
|
|
|
7ab123 |
+ s->size += PLT_ENTRY_SIZE (htab);
|
|
|
7ab123 |
|
|
|
7ab123 |
htab->reliplt->size += sizeof (Elf64_External_Rela);
|
|
|
7ab123 |
}
|
|
|
7ab123 |
@@ -9727,19 +9749,23 @@ plt_stub_size (struct ppc_link_hash_tabl
|
|
|
7ab123 |
struct ppc_stub_hash_entry *stub_entry,
|
|
|
7ab123 |
bfd_vma off)
|
|
|
7ab123 |
{
|
|
|
7ab123 |
- unsigned size = PLT_CALL_STUB_SIZE;
|
|
|
7ab123 |
+ unsigned size = 12;
|
|
|
7ab123 |
|
|
|
7ab123 |
- if (!(ALWAYS_EMIT_R2SAVE
|
|
|
7ab123 |
- || stub_entry->stub_type == ppc_stub_plt_call_r2save))
|
|
|
7ab123 |
- size -= 4;
|
|
|
7ab123 |
- if (!htab->plt_static_chain)
|
|
|
7ab123 |
- size -= 4;
|
|
|
7ab123 |
- if (htab->plt_thread_safe)
|
|
|
7ab123 |
- size += 8;
|
|
|
7ab123 |
- if (PPC_HA (off) == 0)
|
|
|
7ab123 |
- size -= 4;
|
|
|
7ab123 |
- if (PPC_HA (off + 8 + 8 * htab->plt_static_chain) != PPC_HA (off))
|
|
|
7ab123 |
+ if (ALWAYS_EMIT_R2SAVE
|
|
|
7ab123 |
+ || stub_entry->stub_type == ppc_stub_plt_call_r2save)
|
|
|
7ab123 |
size += 4;
|
|
|
7ab123 |
+ if (PPC_HA (off) != 0)
|
|
|
7ab123 |
+ size += 4;
|
|
|
7ab123 |
+ if (htab->opd_abi)
|
|
|
7ab123 |
+ {
|
|
|
7ab123 |
+ size += 4;
|
|
|
7ab123 |
+ if (htab->plt_static_chain)
|
|
|
7ab123 |
+ size += 4;
|
|
|
7ab123 |
+ if (htab->plt_thread_safe)
|
|
|
7ab123 |
+ size += 8;
|
|
|
7ab123 |
+ if (PPC_HA (off + 8 + 8 * htab->plt_static_chain) != PPC_HA (off))
|
|
|
7ab123 |
+ size += 4;
|
|
|
7ab123 |
+ }
|
|
|
7ab123 |
if (stub_entry->h != NULL
|
|
|
7ab123 |
&& (stub_entry->h == htab->tls_get_addr_fd
|
|
|
7ab123 |
|| stub_entry->h == htab->tls_get_addr)
|
|
|
7ab123 |
@@ -9773,12 +9799,14 @@ build_plt_stub (struct ppc_link_hash_tab
|
|
|
7ab123 |
bfd_byte *p, bfd_vma offset, Elf_Internal_Rela *r)
|
|
|
7ab123 |
{
|
|
|
7ab123 |
bfd *obfd = htab->stub_bfd;
|
|
|
7ab123 |
+ bfd_boolean plt_load_toc = htab->opd_abi;
|
|
|
7ab123 |
bfd_boolean plt_static_chain = htab->plt_static_chain;
|
|
|
7ab123 |
bfd_boolean plt_thread_safe = htab->plt_thread_safe;
|
|
|
7ab123 |
bfd_boolean use_fake_dep = plt_thread_safe;
|
|
|
7ab123 |
bfd_vma cmp_branch_off = 0;
|
|
|
7ab123 |
|
|
|
7ab123 |
if (!ALWAYS_USE_FAKE_DEP
|
|
|
7ab123 |
+ && plt_load_toc
|
|
|
7ab123 |
&& plt_thread_safe
|
|
|
7ab123 |
&& !(stub_entry->h != NULL
|
|
|
7ab123 |
&& (stub_entry->h == htab->tls_get_addr_fd
|
|
|
7ab123 |
@@ -9786,7 +9814,8 @@ build_plt_stub (struct ppc_link_hash_tab
|
|
|
7ab123 |
&& !htab->no_tls_get_addr_opt))
|
|
|
7ab123 |
{
|
|
|
7ab123 |
bfd_vma pltoff = stub_entry->plt_ent->plt.offset & ~1;
|
|
|
7ab123 |
- bfd_vma pltindex = (pltoff - PLT_INITIAL_ENTRY_SIZE) / PLT_ENTRY_SIZE;
|
|
|
7ab123 |
+ bfd_vma pltindex = ((pltoff - PLT_INITIAL_ENTRY_SIZE (htab))
|
|
|
7ab123 |
+ / PLT_ENTRY_SIZE (htab));
|
|
|
7ab123 |
bfd_vma glinkoff = GLINK_CALL_STUB_SIZE + pltindex * 8;
|
|
|
7ab123 |
bfd_vma to, from;
|
|
|
7ab123 |
|
|
|
7ab123 |
@@ -9820,22 +9849,25 @@ build_plt_stub (struct ppc_link_hash_tab
|
|
|
7ab123 |
r[1].r_offset = r[0].r_offset + 4;
|
|
|
7ab123 |
r[1].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO_DS);
|
|
|
7ab123 |
r[1].r_addend = r[0].r_addend;
|
|
|
7ab123 |
- if (PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
|
|
|
7ab123 |
- {
|
|
|
7ab123 |
- r[2].r_offset = r[1].r_offset + 4;
|
|
|
7ab123 |
- r[2].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO);
|
|
|
7ab123 |
- r[2].r_addend = r[0].r_addend;
|
|
|
7ab123 |
- }
|
|
|
7ab123 |
- else
|
|
|
7ab123 |
+ if (plt_load_toc)
|
|
|
7ab123 |
{
|
|
|
7ab123 |
- r[2].r_offset = r[1].r_offset + 8 + 8 * use_fake_dep;
|
|
|
7ab123 |
- r[2].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO_DS);
|
|
|
7ab123 |
- r[2].r_addend = r[0].r_addend + 8;
|
|
|
7ab123 |
- if (plt_static_chain)
|
|
|
7ab123 |
- {
|
|
|
7ab123 |
- r[3].r_offset = r[2].r_offset + 4;
|
|
|
7ab123 |
- r[3].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO_DS);
|
|
|
7ab123 |
- r[3].r_addend = r[0].r_addend + 16;
|
|
|
7ab123 |
+ if (PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
|
|
|
7ab123 |
+ {
|
|
|
7ab123 |
+ r[2].r_offset = r[1].r_offset + 4;
|
|
|
7ab123 |
+ r[2].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO);
|
|
|
7ab123 |
+ r[2].r_addend = r[0].r_addend;
|
|
|
7ab123 |
+ }
|
|
|
7ab123 |
+ else
|
|
|
7ab123 |
+ {
|
|
|
7ab123 |
+ r[2].r_offset = r[1].r_offset + 8 + 8 * use_fake_dep;
|
|
|
7ab123 |
+ r[2].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO_DS);
|
|
|
7ab123 |
+ r[2].r_addend = r[0].r_addend + 8;
|
|
|
7ab123 |
+ if (plt_static_chain)
|
|
|
7ab123 |
+ {
|
|
|
7ab123 |
+ r[3].r_offset = r[2].r_offset + 4;
|
|
|
7ab123 |
+ r[3].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_LO_DS);
|
|
|
7ab123 |
+ r[3].r_addend = r[0].r_addend + 16;
|
|
|
7ab123 |
+ }
|
|
|
7ab123 |
}
|
|
|
7ab123 |
}
|
|
|
7ab123 |
}
|
|
|
7ab123 |
@@ -9844,20 +9876,24 @@ build_plt_stub (struct ppc_link_hash_tab
|
|
|
7ab123 |
bfd_put_32 (obfd, STD_R2_40R1, p), p += 4;
|
|
|
7ab123 |
bfd_put_32 (obfd, ADDIS_R11_R2 | PPC_HA (offset), p), p += 4;
|
|
|
7ab123 |
bfd_put_32 (obfd, LD_R12_0R11 | PPC_LO (offset), p), p += 4;
|
|
|
7ab123 |
- if (PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
|
|
|
7ab123 |
+ if (plt_load_toc
|
|
|
7ab123 |
+ && PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
|
|
|
7ab123 |
{
|
|
|
7ab123 |
bfd_put_32 (obfd, ADDI_R11_R11 | PPC_LO (offset), p), p += 4;
|
|
|
7ab123 |
offset = 0;
|
|
|
7ab123 |
}
|
|
|
7ab123 |
bfd_put_32 (obfd, MTCTR_R12, p), p += 4;
|
|
|
7ab123 |
- if (use_fake_dep)
|
|
|
7ab123 |
+ if (plt_load_toc)
|
|
|
7ab123 |
{
|
|
|
7ab123 |
- bfd_put_32 (obfd, XOR_R2_R12_R12, p), p += 4;
|
|
|
7ab123 |
- bfd_put_32 (obfd, ADD_R11_R11_R2, p), p += 4;
|
|
|
7ab123 |
+ if (use_fake_dep)
|
|
|
7ab123 |
+ {
|
|
|
7ab123 |
+ bfd_put_32 (obfd, XOR_R2_R12_R12, p), p += 4;
|
|
|
7ab123 |
+ bfd_put_32 (obfd, ADD_R11_R11_R2, p), p += 4;
|
|
|
7ab123 |
+ }
|
|
|
7ab123 |
+ bfd_put_32 (obfd, LD_R2_0R11 | PPC_LO (offset + 8), p), p += 4;
|
|
|
7ab123 |
+ if (plt_static_chain)
|
|
|
7ab123 |
+ bfd_put_32 (obfd, LD_R11_0R11 | PPC_LO (offset + 16), p), p += 4;
|
|
|
7ab123 |
}
|
|
|
7ab123 |
- bfd_put_32 (obfd, LD_R2_0R11 | PPC_LO (offset + 8), p), p += 4;
|
|
|
7ab123 |
- if (plt_static_chain)
|
|
|
7ab123 |
- bfd_put_32 (obfd, LD_R11_0R11 | PPC_LO (offset + 16), p), p += 4;
|
|
|
7ab123 |
}
|
|
|
7ab123 |
else
|
|
|
7ab123 |
{
|
|
|
7ab123 |
@@ -9867,22 +9903,25 @@ build_plt_stub (struct ppc_link_hash_tab
|
|
|
7ab123 |
|| stub_entry->stub_type == ppc_stub_plt_call_r2save)
|
|
|
7ab123 |
r[0].r_offset += 4;
|
|
|
7ab123 |
r[0].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
|
|
|
7ab123 |
- if (PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
|
|
|
7ab123 |
+ if (plt_load_toc)
|
|
|
7ab123 |
{
|
|
|
7ab123 |
- r[1].r_offset = r[0].r_offset + 4;
|
|
|
7ab123 |
- r[1].r_info = ELF64_R_INFO (0, R_PPC64_TOC16);
|
|
|
7ab123 |
- r[1].r_addend = r[0].r_addend;
|
|
|
7ab123 |
- }
|
|
|
7ab123 |
- else
|
|
|
7ab123 |
- {
|
|
|
7ab123 |
- r[1].r_offset = r[0].r_offset + 8 + 8 * use_fake_dep;
|
|
|
7ab123 |
- r[1].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
|
|
|
7ab123 |
- r[1].r_addend = r[0].r_addend + 8 + 8 * plt_static_chain;
|
|
|
7ab123 |
- if (plt_static_chain)
|
|
|
7ab123 |
+ if (PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
|
|
|
7ab123 |
{
|
|
|
7ab123 |
- r[2].r_offset = r[1].r_offset + 4;
|
|
|
7ab123 |
- r[2].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
|
|
|
7ab123 |
- r[2].r_addend = r[0].r_addend + 8;
|
|
|
7ab123 |
+ r[1].r_offset = r[0].r_offset + 4;
|
|
|
7ab123 |
+ r[1].r_info = ELF64_R_INFO (0, R_PPC64_TOC16);
|
|
|
7ab123 |
+ r[1].r_addend = r[0].r_addend;
|
|
|
7ab123 |
+ }
|
|
|
7ab123 |
+ else
|
|
|
7ab123 |
+ {
|
|
|
7ab123 |
+ r[1].r_offset = r[0].r_offset + 8 + 8 * use_fake_dep;
|
|
|
7ab123 |
+ r[1].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
|
|
|
7ab123 |
+ r[1].r_addend = r[0].r_addend + 8 + 8 * plt_static_chain;
|
|
|
7ab123 |
+ if (plt_static_chain)
|
|
|
7ab123 |
+ {
|
|
|
7ab123 |
+ r[2].r_offset = r[1].r_offset + 4;
|
|
|
7ab123 |
+ r[2].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
|
|
|
7ab123 |
+ r[2].r_addend = r[0].r_addend + 8;
|
|
|
7ab123 |
+ }
|
|
|
7ab123 |
}
|
|
|
7ab123 |
}
|
|
|
7ab123 |
}
|
|
|
7ab123 |
@@ -9890,22 +9929,26 @@ build_plt_stub (struct ppc_link_hash_tab
|
|
|
7ab123 |
|| stub_entry->stub_type == ppc_stub_plt_call_r2save)
|
|
|
7ab123 |
bfd_put_32 (obfd, STD_R2_40R1, p), p += 4;
|
|
|
7ab123 |
bfd_put_32 (obfd, LD_R12_0R2 | PPC_LO (offset), p), p += 4;
|
|
|
7ab123 |
- if (PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
|
|
|
7ab123 |
+ if (plt_load_toc
|
|
|
7ab123 |
+ && PPC_HA (offset + 8 + 8 * plt_static_chain) != PPC_HA (offset))
|
|
|
7ab123 |
{
|
|
|
7ab123 |
bfd_put_32 (obfd, ADDI_R2_R2 | PPC_LO (offset), p), p += 4;
|
|
|
7ab123 |
offset = 0;
|
|
|
7ab123 |
}
|
|
|
7ab123 |
bfd_put_32 (obfd, MTCTR_R12, p), p += 4;
|
|
|
7ab123 |
- if (use_fake_dep)
|
|
|
7ab123 |
+ if (plt_load_toc)
|
|
|
7ab123 |
{
|
|
|
7ab123 |
- bfd_put_32 (obfd, XOR_R11_R12_R12, p), p += 4;
|
|
|
7ab123 |
- bfd_put_32 (obfd, ADD_R2_R2_R11, p), p += 4;
|
|
|
7ab123 |
+ if (use_fake_dep)
|
|
|
7ab123 |
+ {
|
|
|
7ab123 |
+ bfd_put_32 (obfd, XOR_R11_R12_R12, p), p += 4;
|
|
|
7ab123 |
+ bfd_put_32 (obfd, ADD_R2_R2_R11, p), p += 4;
|
|
|
7ab123 |
+ }
|
|
|
7ab123 |
+ if (plt_static_chain)
|
|
|
7ab123 |
+ bfd_put_32 (obfd, LD_R11_0R2 | PPC_LO (offset + 16), p), p += 4;
|
|
|
7ab123 |
+ bfd_put_32 (obfd, LD_R2_0R2 | PPC_LO (offset + 8), p), p += 4;
|
|
|
7ab123 |
}
|
|
|
7ab123 |
- if (plt_static_chain)
|
|
|
7ab123 |
- bfd_put_32 (obfd, LD_R11_0R2 | PPC_LO (offset + 16), p), p += 4;
|
|
|
7ab123 |
- bfd_put_32 (obfd, LD_R2_0R2 | PPC_LO (offset + 8), p), p += 4;
|
|
|
7ab123 |
}
|
|
|
7ab123 |
- if (plt_thread_safe && !use_fake_dep)
|
|
|
7ab123 |
+ if (plt_load_toc && plt_thread_safe && !use_fake_dep)
|
|
|
7ab123 |
{
|
|
|
7ab123 |
bfd_put_32 (obfd, CMPLDI_R2_0, p), p += 4;
|
|
|
7ab123 |
bfd_put_32 (obfd, BNECTR_P4, p), p += 4;
|
|
|
7ab123 |
@@ -10004,6 +10047,8 @@ get_r2off (struct bfd_link_info *info,
|
|
|
7ab123 |
/* Support linking -R objects. Get the toc pointer from the
|
|
|
7ab123 |
opd entry. */
|
|
|
7ab123 |
char buf[8];
|
|
|
7ab123 |
+ if (!htab->opd_abi)
|
|
|
7ab123 |
+ return r2off;
|
|
|
7ab123 |
asection *opd = stub_entry->h->elf.root.u.def.section;
|
|
|
7ab123 |
bfd_vma opd_off = stub_entry->h->elf.root.u.def.value;
|
|
|
7ab123 |
|
|
|
7ab123 |
@@ -10233,7 +10278,8 @@ ppc_build_one_stub (struct bfd_hash_entr
|
|
|
7ab123 |
r[0].r_offset = loc - stub_entry->stub_sec->contents;
|
|
|
7ab123 |
if (bfd_big_endian (info->output_bfd))
|
|
|
7ab123 |
r[0].r_offset += 2;
|
|
|
7ab123 |
- if (stub_entry->stub_type == ppc_stub_plt_branch_r2off)
|
|
|
7ab123 |
+ if (stub_entry->stub_type == ppc_stub_plt_branch_r2off
|
|
|
7ab123 |
+ && htab->opd_abi)
|
|
|
7ab123 |
r[0].r_offset += 4;
|
|
|
7ab123 |
r[0].r_info = ELF64_R_INFO (0, R_PPC64_TOC16_DS);
|
|
|
7ab123 |
r[0].r_addend = dest;
|
|
|
7ab123 |
@@ -10246,7 +10292,8 @@ ppc_build_one_stub (struct bfd_hash_entr
|
|
|
7ab123 |
}
|
|
|
7ab123 |
}
|
|
|
7ab123 |
|
|
|
7ab123 |
- if (stub_entry->stub_type != ppc_stub_plt_branch_r2off)
|
|
|
7ab123 |
+ if (stub_entry->stub_type != ppc_stub_plt_branch_r2off
|
|
|
7ab123 |
+ || !htab->opd_abi)
|
|
|
7ab123 |
{
|
|
|
7ab123 |
if (PPC_HA (off) != 0)
|
|
|
7ab123 |
{
|
|
|
7ab123 |
@@ -10497,10 +10544,11 @@ ppc_size_one_stub (struct bfd_hash_entry
|
|
|
7ab123 |
if (info->emitrelocations)
|
|
|
7ab123 |
{
|
|
|
7ab123 |
stub_entry->stub_sec->reloc_count
|
|
|
7ab123 |
- += (2
|
|
|
7ab123 |
- + (PPC_HA (off) != 0)
|
|
|
7ab123 |
- + (htab->plt_static_chain
|
|
|
7ab123 |
- && PPC_HA (off + 16) == PPC_HA (off)));
|
|
|
7ab123 |
+ += ((PPC_HA (off) != 0)
|
|
|
7ab123 |
+ + (htab->opd_abi
|
|
|
7ab123 |
+ ? 2 + (htab->plt_static_chain
|
|
|
7ab123 |
+ && PPC_HA (off + 16) == PPC_HA (off))
|
|
|
7ab123 |
+ : 1));
|
|
|
7ab123 |
stub_entry->stub_sec->flags |= SEC_RELOC;
|
|
|
7ab123 |
}
|
|
|
7ab123 |
}
|
|
|
7ab123 |
@@ -10527,7 +10575,7 @@ ppc_size_one_stub (struct bfd_hash_entry
|
|
|
7ab123 |
if (stub_entry->stub_type == ppc_stub_long_branch_r2off)
|
|
|
7ab123 |
{
|
|
|
7ab123 |
r2off = get_r2off (info, stub_entry);
|
|
|
7ab123 |
- if (r2off == 0)
|
|
|
7ab123 |
+ if (r2off == 0 && htab->opd_abi)
|
|
|
7ab123 |
{
|
|
|
7ab123 |
htab->stub_error = TRUE;
|
|
|
7ab123 |
return FALSE;
|
|
|
7ab123 |
@@ -10540,8 +10588,11 @@ ppc_size_one_stub (struct bfd_hash_entry
|
|
|
7ab123 |
|
|
|
7ab123 |
local_off = PPC64_LOCAL_ENTRY_OFFSET (stub_entry->other);
|
|
|
7ab123 |
|
|
|
7ab123 |
- /* If the branch offset if too big, use a ppc_stub_plt_branch. */
|
|
|
7ab123 |
- if (off + (1 << 25) >= (bfd_vma) (1 << 26) - local_off)
|
|
|
7ab123 |
+ /* If the branch offset if too big, use a ppc_stub_plt_branch.
|
|
|
7ab123 |
+ Do the same for -R objects without function descriptors. */
|
|
|
7ab123 |
+ if (off + (1 << 25) >= (bfd_vma) (1 << 26) - local_off
|
|
|
7ab123 |
+ || (stub_entry->stub_type == ppc_stub_long_branch_r2off
|
|
|
7ab123 |
+ && r2off == 0))
|
|
|
7ab123 |
{
|
|
|
7ab123 |
struct ppc_branch_hash_entry *br_entry;
|
|
|
7ab123 |
|
|
|
7ab123 |
@@ -10584,7 +10635,8 @@ ppc_size_one_stub (struct bfd_hash_entry
|
|
|
7ab123 |
stub_entry->stub_sec->flags |= SEC_RELOC;
|
|
|
7ab123 |
}
|
|
|
7ab123 |
|
|
|
7ab123 |
- if (stub_entry->stub_type != ppc_stub_plt_branch_r2off)
|
|
|
7ab123 |
+ if (stub_entry->stub_type != ppc_stub_plt_branch_r2off
|
|
|
7ab123 |
+ || !htab->opd_abi)
|
|
|
7ab123 |
{
|
|
|
7ab123 |
size = 12;
|
|
|
7ab123 |
if (PPC_HA (off) != 0)
|
|
|
7ab123 |
@@ -11487,7 +11539,9 @@ ppc64_elf_size_stubs (struct bfd_link_in
|
|
|
7ab123 |
htab->plt_stub_align = plt_stub_align;
|
|
|
7ab123 |
if (plt_thread_safe == -1 && !info->executable)
|
|
|
7ab123 |
plt_thread_safe = 1;
|
|
|
7ab123 |
- if (plt_thread_safe == -1)
|
|
|
7ab123 |
+ if (!htab->opd_abi)
|
|
|
7ab123 |
+ plt_thread_safe = 0;
|
|
|
7ab123 |
+ else if (plt_thread_safe == -1)
|
|
|
7ab123 |
{
|
|
|
7ab123 |
static const char *const thread_starter[] =
|
|
|
7ab123 |
{
|
|
|
7ab123 |
@@ -12059,26 +12113,56 @@ ppc64_elf_build_stubs (bfd_boolean emit_
|
|
|
7ab123 |
plt0 -= htab->glink->output_section->vma + htab->glink->output_offset;
|
|
|
7ab123 |
bfd_put_64 (htab->glink->owner, plt0, p);
|
|
|
7ab123 |
p += 8;
|
|
|
7ab123 |
- bfd_put_32 (htab->glink->owner, MFLR_R12, p);
|
|
|
7ab123 |
- p += 4;
|
|
|
7ab123 |
- bfd_put_32 (htab->glink->owner, BCL_20_31, p);
|
|
|
7ab123 |
- p += 4;
|
|
|
7ab123 |
- bfd_put_32 (htab->glink->owner, MFLR_R11, p);
|
|
|
7ab123 |
- p += 4;
|
|
|
7ab123 |
- bfd_put_32 (htab->glink->owner, LD_R2_0R11 | (-16 & 0xfffc), p);
|
|
|
7ab123 |
- p += 4;
|
|
|
7ab123 |
- bfd_put_32 (htab->glink->owner, MTLR_R12, p);
|
|
|
7ab123 |
- p += 4;
|
|
|
7ab123 |
- bfd_put_32 (htab->glink->owner, ADD_R11_R2_R11, p);
|
|
|
7ab123 |
- p += 4;
|
|
|
7ab123 |
- bfd_put_32 (htab->glink->owner, LD_R12_0R11, p);
|
|
|
7ab123 |
- p += 4;
|
|
|
7ab123 |
- bfd_put_32 (htab->glink->owner, LD_R2_0R11 | 8, p);
|
|
|
7ab123 |
- p += 4;
|
|
|
7ab123 |
- bfd_put_32 (htab->glink->owner, MTCTR_R12, p);
|
|
|
7ab123 |
- p += 4;
|
|
|
7ab123 |
- bfd_put_32 (htab->glink->owner, LD_R11_0R11 | 16, p);
|
|
|
7ab123 |
- p += 4;
|
|
|
7ab123 |
+ if (htab->opd_abi)
|
|
|
7ab123 |
+ {
|
|
|
7ab123 |
+ bfd_put_32 (htab->glink->owner, MFLR_R12, p);
|
|
|
7ab123 |
+ p += 4;
|
|
|
7ab123 |
+ bfd_put_32 (htab->glink->owner, BCL_20_31, p);
|
|
|
7ab123 |
+ p += 4;
|
|
|
7ab123 |
+ bfd_put_32 (htab->glink->owner, MFLR_R11, p);
|
|
|
7ab123 |
+ p += 4;
|
|
|
7ab123 |
+ bfd_put_32 (htab->glink->owner, LD_R2_0R11 | (-16 & 0xfffc), p);
|
|
|
7ab123 |
+ p += 4;
|
|
|
7ab123 |
+ bfd_put_32 (htab->glink->owner, MTLR_R12, p);
|
|
|
7ab123 |
+ p += 4;
|
|
|
7ab123 |
+ bfd_put_32 (htab->glink->owner, ADD_R11_R2_R11, p);
|
|
|
7ab123 |
+ p += 4;
|
|
|
7ab123 |
+ bfd_put_32 (htab->glink->owner, LD_R12_0R11, p);
|
|
|
7ab123 |
+ p += 4;
|
|
|
7ab123 |
+ bfd_put_32 (htab->glink->owner, LD_R2_0R11 | 8, p);
|
|
|
7ab123 |
+ p += 4;
|
|
|
7ab123 |
+ bfd_put_32 (htab->glink->owner, MTCTR_R12, p);
|
|
|
7ab123 |
+ p += 4;
|
|
|
7ab123 |
+ bfd_put_32 (htab->glink->owner, LD_R11_0R11 | 16, p);
|
|
|
7ab123 |
+ p += 4;
|
|
|
7ab123 |
+ }
|
|
|
7ab123 |
+ else
|
|
|
7ab123 |
+ {
|
|
|
7ab123 |
+ bfd_put_32 (htab->glink->owner, MFLR_R0, p);
|
|
|
7ab123 |
+ p += 4;
|
|
|
7ab123 |
+ bfd_put_32 (htab->glink->owner, BCL_20_31, p);
|
|
|
7ab123 |
+ p += 4;
|
|
|
7ab123 |
+ bfd_put_32 (htab->glink->owner, MFLR_R11, p);
|
|
|
7ab123 |
+ p += 4;
|
|
|
7ab123 |
+ bfd_put_32 (htab->glink->owner, LD_R2_0R11 | (-16 & 0xfffc), p);
|
|
|
7ab123 |
+ p += 4;
|
|
|
7ab123 |
+ bfd_put_32 (htab->glink->owner, MTLR_R0, p);
|
|
|
7ab123 |
+ p += 4;
|
|
|
7ab123 |
+ bfd_put_32 (htab->glink->owner, SUB_R12_R12_R11, p);
|
|
|
7ab123 |
+ p += 4;
|
|
|
7ab123 |
+ bfd_put_32 (htab->glink->owner, ADD_R11_R2_R11, p);
|
|
|
7ab123 |
+ p += 4;
|
|
|
7ab123 |
+ bfd_put_32 (htab->glink->owner, ADDI_R0_R12 | (-48 & 0xffff), p);
|
|
|
7ab123 |
+ p += 4;
|
|
|
7ab123 |
+ bfd_put_32 (htab->glink->owner, LD_R12_0R11, p);
|
|
|
7ab123 |
+ p += 4;
|
|
|
7ab123 |
+ bfd_put_32 (htab->glink->owner, SRDI_R0_R0_2, p);
|
|
|
7ab123 |
+ p += 4;
|
|
|
7ab123 |
+ bfd_put_32 (htab->glink->owner, MTCTR_R12, p);
|
|
|
7ab123 |
+ p += 4;
|
|
|
7ab123 |
+ bfd_put_32 (htab->glink->owner, LD_R11_0R11 | 8, p);
|
|
|
7ab123 |
+ p += 4;
|
|
|
7ab123 |
+ }
|
|
|
7ab123 |
bfd_put_32 (htab->glink->owner, BCTR, p);
|
|
|
7ab123 |
p += 4;
|
|
|
7ab123 |
while (p - htab->glink->contents < GLINK_CALL_STUB_SIZE)
|
|
|
7ab123 |
@@ -12091,17 +12175,21 @@ ppc64_elf_build_stubs (bfd_boolean emit_
|
|
|
7ab123 |
indx = 0;
|
|
|
7ab123 |
while (p < htab->glink->contents + htab->glink->size)
|
|
|
7ab123 |
{
|
|
|
7ab123 |
- if (indx < 0x8000)
|
|
|
7ab123 |
- {
|
|
|
7ab123 |
- bfd_put_32 (htab->glink->owner, LI_R0_0 | indx, p);
|
|
|
7ab123 |
- p += 4;
|
|
|
7ab123 |
- }
|
|
|
7ab123 |
- else
|
|
|
7ab123 |
+ if (htab->opd_abi)
|
|
|
7ab123 |
{
|
|
|
7ab123 |
- bfd_put_32 (htab->glink->owner, LIS_R0_0 | PPC_HI (indx), p);
|
|
|
7ab123 |
- p += 4;
|
|
|
7ab123 |
- bfd_put_32 (htab->glink->owner, ORI_R0_R0_0 | PPC_LO (indx), p);
|
|
|
7ab123 |
- p += 4;
|
|
|
7ab123 |
+ if (indx < 0x8000)
|
|
|
7ab123 |
+ {
|
|
|
7ab123 |
+ bfd_put_32 (htab->glink->owner, LI_R0_0 | indx, p);
|
|
|
7ab123 |
+ p += 4;
|
|
|
7ab123 |
+ }
|
|
|
7ab123 |
+ else
|
|
|
7ab123 |
+ {
|
|
|
7ab123 |
+ bfd_put_32 (htab->glink->owner, LIS_R0_0 | PPC_HI (indx), p);
|
|
|
7ab123 |
+ p += 4;
|
|
|
7ab123 |
+ bfd_put_32 (htab->glink->owner, ORI_R0_R0_0 | PPC_LO (indx),
|
|
|
7ab123 |
+ p);
|
|
|
7ab123 |
+ p += 4;
|
|
|
7ab123 |
+ }
|
|
|
7ab123 |
}
|
|
|
7ab123 |
bfd_put_32 (htab->glink->owner,
|
|
|
7ab123 |
B_DOT | ((htab->glink->contents - p + 8) & 0x3fffffc), p);
|
|
|
7ab123 |
@@ -14192,8 +14280,8 @@ ppc64_elf_finish_dynamic_symbol (bfd *ou
|
|
|
7ab123 |
rela.r_info = ELF64_R_INFO (h->dynindx, R_PPC64_JMP_SLOT);
|
|
|
7ab123 |
rela.r_addend = ent->addend;
|
|
|
7ab123 |
loc = (htab->relplt->contents
|
|
|
7ab123 |
- + ((ent->plt.offset - PLT_INITIAL_ENTRY_SIZE)
|
|
|
7ab123 |
- / (PLT_ENTRY_SIZE / sizeof (Elf64_External_Rela))));
|
|
|
7ab123 |
+ + ((ent->plt.offset - PLT_INITIAL_ENTRY_SIZE (htab))
|
|
|
7ab123 |
+ / PLT_ENTRY_SIZE (htab) * sizeof (Elf64_External_Rela)));
|
|
|
7ab123 |
}
|
|
|
7ab123 |
bfd_elf64_swap_reloca_out (output_bfd, &rela, loc);
|
|
|
7ab123 |
}
|
|
|
7ab123 |
@@ -14288,7 +14376,7 @@ ppc64_elf_finish_dynamic_sections (bfd *
|
|
|
7ab123 |
of glink rather than the first entry point, which is
|
|
|
7ab123 |
what ld.so needs, and now have a bigger stub to
|
|
|
7ab123 |
support automatic multiple TOCs. */
|
|
|
7ab123 |
- dyn.d_un.d_ptr += GLINK_CALL_STUB_SIZE - 32;
|
|
|
7ab123 |
+ dyn.d_un.d_ptr += GLINK_CALL_STUB_SIZE - 8 * 4;
|
|
|
7ab123 |
break;
|
|
|
7ab123 |
|
|
|
7ab123 |
case DT_PPC64_OPD:
|
|
|
7ab123 |
@@ -14361,7 +14449,7 @@ ppc64_elf_finish_dynamic_sections (bfd *
|
|
|
7ab123 |
{
|
|
|
7ab123 |
/* Set .plt entry size. */
|
|
|
7ab123 |
elf_section_data (htab->plt->output_section)->this_hdr.sh_entsize
|
|
|
7ab123 |
- = PLT_ENTRY_SIZE;
|
|
|
7ab123 |
+ = PLT_ENTRY_SIZE (htab);
|
|
|
7ab123 |
}
|
|
|
7ab123 |
|
|
|
7ab123 |
/* brlt is SEC_LINKER_CREATED, so we need to write out relocs for
|