R_PPC64_REL24_NOTOC support
R_PPC64_REL24_NOTOC is used on calls like "bl foo@notoc" to tell the linker that linkage stubs for PLT calls or long branches can't use r2 for pic addressing. Instead, new stubs that generate pc-relative addresses are used. One complication is that pc-relative offsets to the PLT may need to be 64-bit in large programs, in contrast to the toc-relative addressing used by older PLT linkage stubs where a 32-bit offset is sufficient until the PLT itself exceeds 2G in size. .eh_frame info to cover the _notoc stubs is yet to be implemented. bfd/ * elf64-ppc.c (ADDI_R12_R11, ADDI_R12_R12, LIS_R12), (ADDIS_R12_R11, ORIS_R12_R12_0, ORI_R12_R12_0), (SLDI_R12_R12_32, LDX_R12_R11_R12, ADD_R12_R11_R12): Define. (ppc64_elf_howto_raw): Add R_PPC64_REL24_NOTOC entry. (ppc64_elf_reloc_type_lookup): Support R_PPC64_REL24_NOTOC. (ppc_stub_type): Add ppc_stub_long_branch_notoc, ppc_stub_long_branch_both, ppc_stub_plt_branch_notoc, ppc_stub_plt_branch_both, ppc_stub_plt_call_notoc, and ppc_stub_plt_call_both. (is_branch_reloc): Add R_PPC64_REL24_NOTOC. (build_offset, size_offset): New functions. (plt_stub_size): Support plt_call_notoc and plt_call_both. (ppc_build_one_stub, ppc_size_one_stub): Support new stubs. (toc_adjusting_stub_needed): Handle R_PPC64_REL24_NOTOC. (ppc64_elf_size_stubs): Likewise, and new stubs. (ppc64_elf_build_stubs, ppc64_elf_relocate_section): Likewise. * reloc.c: Add BFD_RELOC_PPC64_REL24_NOTOC. * bfd-in2.h: Regenerate. * libbfd.h: Regenerate. gas/ * config/tc-ppc.c (ppc_elf_suffix): Support @notoc. (ppc_force_relocation, ppc_fix_adjustable): Handle REL24_NOTOC. ld/ * testsuite/ld-powerpc/ext.d, * testsuite/ld-powerpc/ext.s, * testsuite/ld-powerpc/ext.lnk, * testsuite/ld-powerpc/notoc.d, * testsuite/ld-powerpc/notoc.s: New tests. * testsuite/ld-powerpc/powerpc.exp: Run them.
This commit is contained in:
parent
3f6ff4799b
commit
05d0e962f0
@ -1,3 +1,25 @@
|
||||
2018-08-05 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* elf64-ppc.c (ADDI_R12_R11, ADDI_R12_R12, LIS_R12),
|
||||
(ADDIS_R12_R11, ORIS_R12_R12_0, ORI_R12_R12_0),
|
||||
(SLDI_R12_R12_32, LDX_R12_R11_R12, ADD_R12_R11_R12): Define.
|
||||
(ppc64_elf_howto_raw): Add R_PPC64_REL24_NOTOC entry.
|
||||
(ppc64_elf_reloc_type_lookup): Support R_PPC64_REL24_NOTOC.
|
||||
(ppc_stub_type): Add ppc_stub_long_branch_notoc,
|
||||
ppc_stub_long_branch_both, ppc_stub_plt_branch_notoc,
|
||||
ppc_stub_plt_branch_both, ppc_stub_plt_call_notoc, and
|
||||
ppc_stub_plt_call_both.
|
||||
(is_branch_reloc): Add R_PPC64_REL24_NOTOC.
|
||||
(build_offset, size_offset): New functions.
|
||||
(plt_stub_size): Support plt_call_notoc and plt_call_both.
|
||||
(ppc_build_one_stub, ppc_size_one_stub): Support new stubs.
|
||||
(toc_adjusting_stub_needed): Handle R_PPC64_REL24_NOTOC.
|
||||
(ppc64_elf_size_stubs): Likewise, and new stubs.
|
||||
(ppc64_elf_build_stubs, ppc64_elf_relocate_section): Likewise.
|
||||
* reloc.c: Add BFD_RELOC_PPC64_REL24_NOTOC.
|
||||
* bfd-in2.h: Regenerate.
|
||||
* libbfd.h: Regenerate.
|
||||
|
||||
2018-08-05 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* elf64-ppc.c (ppc_build_one_stub): Lose "_r2off" in stub symbols.
|
||||
|
@ -3457,6 +3457,7 @@ instruction. */
|
||||
BFD_RELOC_PPC64_ADDR16_HIGHA,
|
||||
BFD_RELOC_PPC64_ADDR64_LOCAL,
|
||||
BFD_RELOC_PPC64_ENTRY,
|
||||
BFD_RELOC_PPC64_REL24_NOTOC,
|
||||
|
||||
/* PowerPC and PowerPC64 thread-local storage relocations. */
|
||||
BFD_RELOC_PPC_TLS,
|
||||
|
530
bfd/elf64-ppc.c
530
bfd/elf64-ppc.c
@ -164,6 +164,8 @@ static bfd_vma opd_entry_value
|
||||
#define BCTR 0x4e800420 /* bctr */
|
||||
|
||||
#define ADDI_R11_R11 0x396b0000 /* addi %r11,%r11,off@l */
|
||||
#define ADDI_R12_R11 0x398b0000 /* addi %r12,%r11,off@l */
|
||||
#define ADDI_R12_R12 0x398c0000 /* addi %r12,%r12,off@l */
|
||||
#define ADDIS_R2_R2 0x3c420000 /* addis %r2,%r2,off@ha */
|
||||
#define ADDI_R2_R2 0x38420000 /* addi %r2,%r2,off@l */
|
||||
|
||||
@ -184,10 +186,17 @@ static bfd_vma opd_entry_value
|
||||
#define ADD_R2_R2_R12 0x7c426214 /* add %r2,%r2,%r12 */
|
||||
|
||||
#define LIS_R2 0x3c400000 /* lis %r2,xxx@ha */
|
||||
#define LIS_R12 0x3d800000 /* lis %r12,xxx@ha */
|
||||
#define ADDIS_R2_R12 0x3c4c0000 /* addis %r2,%r12,xxx@ha */
|
||||
#define ADDIS_R12_R2 0x3d820000 /* addis %r12,%r2,xxx@ha */
|
||||
#define ADDIS_R12_R11 0x3d8b0000 /* addis %r12,%r11,xxx@ha */
|
||||
#define ADDIS_R12_R12 0x3d8c0000 /* addis %r12,%r12,xxx@ha */
|
||||
#define ORIS_R12_R12_0 0x658c0000 /* oris %r12,%r12,xxx@hi */
|
||||
#define ORI_R12_R12_0 0x618c0000 /* ori %r12,%r12,xxx@l */
|
||||
#define LD_R12_0R12 0xe98c0000 /* ld %r12,xxx@l(%r12) */
|
||||
#define SLDI_R12_R12_32 0x799c07c6 /* sldi %r12,%r12,32 */
|
||||
#define LDX_R12_R11_R12 0x7d8b602a /* ldx %r12,%r11,%r12 */
|
||||
#define ADD_R12_R11_R12 0x7d8b6214 /* add %r12,%r11,%r12 */
|
||||
|
||||
/* __glink_PLTresolve stub instructions. We enter with the index in R0. */
|
||||
#define GLINK_PLTRESOLVE_SIZE(htab) \
|
||||
@ -446,6 +455,21 @@ static reloc_howto_type ppc64_elf_howto_raw[] =
|
||||
0x03fffffc, /* dst_mask */
|
||||
TRUE), /* pcrel_offset */
|
||||
|
||||
/* A variant of R_PPC64_REL24, used when r2 is not the toc pointer. */
|
||||
HOWTO (R_PPC64_REL24_NOTOC, /* type */
|
||||
0, /* rightshift */
|
||||
2, /* size (0 = byte, 1 = short, 2 = long) */
|
||||
26, /* bitsize */
|
||||
TRUE, /* pc_relative */
|
||||
0, /* bitpos */
|
||||
complain_overflow_signed, /* complain_on_overflow */
|
||||
ppc64_elf_branch_reloc, /* special_function */
|
||||
"R_PPC64_REL24_NOTOC", /* name */
|
||||
FALSE, /* partial_inplace */
|
||||
0, /* src_mask */
|
||||
0x03fffffc, /* dst_mask */
|
||||
TRUE), /* pcrel_offset */
|
||||
|
||||
/* A relative 16 bit branch; the lower two bits must be zero. */
|
||||
HOWTO (R_PPC64_REL14, /* type */
|
||||
0, /* rightshift */
|
||||
@ -2308,6 +2332,8 @@ ppc64_elf_reloc_type_lookup (bfd *abfd,
|
||||
break;
|
||||
case BFD_RELOC_PPC_B26: r = R_PPC64_REL24;
|
||||
break;
|
||||
case BFD_RELOC_PPC64_REL24_NOTOC: r = R_PPC64_REL24_NOTOC;
|
||||
break;
|
||||
case BFD_RELOC_PPC_B16: r = R_PPC64_REL14;
|
||||
break;
|
||||
case BFD_RELOC_PPC_B16_BRTAKEN: r = R_PPC64_REL14_BRTAKEN;
|
||||
@ -3954,7 +3980,7 @@ must_be_dyn_reloc (struct bfd_link_info *info,
|
||||
Used to call a function in a shared library. If it so happens that
|
||||
the plt entry referenced crosses a 64k boundary, then an extra
|
||||
"addi %r11,%r11,xxx@toc@l" will be inserted before the "mtctr".
|
||||
. std %r2,40(%r1)
|
||||
ppc_stub_plt_call_r2save starts with "std %r2,40(%r1)".
|
||||
. addis %r11,%r2,xxx@toc@ha
|
||||
. ld %r12,xxx+0@toc@l(%r11)
|
||||
. mtctr %r12
|
||||
@ -3979,18 +4005,98 @@ must_be_dyn_reloc (struct bfd_link_info *info,
|
||||
. mtctr %r12
|
||||
. bctr
|
||||
|
||||
In cases where the "addis" instruction would add zero, the "addis" is
|
||||
omitted and following instructions modified slightly in some cases.
|
||||
*/
|
||||
All of the above stubs are shown as their ELFv1 variants. ELFv2
|
||||
variants exist too, simpler for plt calls since a new toc pointer
|
||||
and static chain are not loaded by the stub. In addition, ELFv2
|
||||
has some more complex stubs to handle calls marked with NOTOC
|
||||
relocs from functions where r2 is not a valid toc pointer. These
|
||||
come in two flavours, the ones shown below, and _both variants that
|
||||
start with "std %r2,24(%r1)" to save r2 in the unlikely event that
|
||||
one call is from a function where r2 is used as the toc pointer but
|
||||
needs a toc adjusting stub for small-model multi-toc, and another
|
||||
call is from a function where r2 is not valid.
|
||||
ppc_stub_long_branch_notoc:
|
||||
. mflr %r12
|
||||
. bcl 20,31,1f
|
||||
. 1:
|
||||
. mflr %r11
|
||||
. mtlr %r12
|
||||
. lis %r12,xxx-1b@highest
|
||||
. ori %r12,xxx-1b@higher
|
||||
. sldi %r12,%r12,32
|
||||
. oris %r12,%r12,xxx-1b@hi
|
||||
. ori %r12,%r12,xxx-1b@l
|
||||
. add %r12,%r11,%r12
|
||||
. b dest
|
||||
|
||||
ppc_stub_plt_branch_notoc:
|
||||
. mflr %r12
|
||||
. bcl 20,31,1f
|
||||
. 1:
|
||||
. mflr %r11
|
||||
. mtlr %r12
|
||||
. lis %r12,xxx-1b@highest
|
||||
. ori %r12,xxx-1b@higher
|
||||
. sldi %r12,%r12,32
|
||||
. oris %r12,%r12,xxx-1b@hi
|
||||
. ori %r12,%r12,xxx-1b@l
|
||||
. add %r12,%r11,%r12
|
||||
. mtctr %r12
|
||||
. bctr
|
||||
|
||||
ppc_stub_plt_call_notoc:
|
||||
. mflr %r12
|
||||
. bcl 20,31,1f
|
||||
. 1:
|
||||
. mflr %r11
|
||||
. mtlr %r12
|
||||
. lis %r12,xxx-1b@highest
|
||||
. ori %r12,xxx-1b@higher
|
||||
. sldi %r12,%r12,32
|
||||
. oris %r12,%r12,xxx-1b@hi
|
||||
. ori %r12,%r12,xxx-1b@l
|
||||
. ldx %r12,%r11,%r12
|
||||
. mtctr %r12
|
||||
. bctr
|
||||
|
||||
In cases where the high instructions would add zero, they are
|
||||
omitted and following instructions modified in some cases.
|
||||
|
||||
For a given stub group (a set of sections all using the same toc
|
||||
pointer value) there will be just one stub type used for any
|
||||
particular function symbol. For example, if printf is called from
|
||||
code with the tocsave optimization (ie. r2 saved in function
|
||||
prologue) and therefore calls use a ppc_stub_plt_call linkage stub,
|
||||
and from other code without the tocsave optimization requiring a
|
||||
ppc_stub_plt_call_r2save linkage stub, a single stub of the latter
|
||||
type will be created. Calls with the tocsave optimization will
|
||||
enter this stub after the instruction saving r2. A similar
|
||||
situation exists when calls are marked with R_PPC64_REL24_NOTOC
|
||||
relocations. These require a ppc_stub_plt_call_notoc linkage stub
|
||||
to call an external function like printf. If other calls to printf
|
||||
require a ppc_stub_plt_call linkage stub then a single
|
||||
ppc_stub_plt_call_notoc linkage stub will be used for both types of
|
||||
call. If other calls to printf require a ppc_stub_plt_call_r2save
|
||||
linkage stub then a single ppc_stub_plt_call_both linkage stub will
|
||||
be created and calls not requiring r2 to be saved will enter the
|
||||
stub after the r2 save instruction. There is an analogous
|
||||
hierarchy of long branch and plt branch stubs for local call
|
||||
linkage. */
|
||||
|
||||
enum ppc_stub_type {
|
||||
ppc_stub_none,
|
||||
ppc_stub_long_branch,
|
||||
ppc_stub_long_branch_r2off,
|
||||
ppc_stub_long_branch_notoc,
|
||||
ppc_stub_long_branch_both, /* r2off and notoc variants both needed. */
|
||||
ppc_stub_plt_branch,
|
||||
ppc_stub_plt_branch_r2off,
|
||||
ppc_stub_plt_branch_notoc,
|
||||
ppc_stub_plt_branch_both,
|
||||
ppc_stub_plt_call,
|
||||
ppc_stub_plt_call_r2save,
|
||||
ppc_stub_plt_call_notoc,
|
||||
ppc_stub_plt_call_both,
|
||||
ppc_stub_global_entry,
|
||||
ppc_stub_save_res
|
||||
};
|
||||
@ -5478,6 +5584,7 @@ static bfd_boolean
|
||||
is_branch_reloc (enum elf_ppc64_reloc_type r_type)
|
||||
{
|
||||
return (r_type == R_PPC64_REL24
|
||||
|| r_type == R_PPC64_REL24_NOTOC
|
||||
|| r_type == R_PPC64_REL14
|
||||
|| r_type == R_PPC64_REL14_BRTAKEN
|
||||
|| r_type == R_PPC64_REL14_BRNTAKEN
|
||||
@ -5848,6 +5955,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
||||
/* Fall through. */
|
||||
|
||||
case R_PPC64_REL24:
|
||||
case R_PPC64_REL24_NOTOC:
|
||||
rel24:
|
||||
plt_list = ifunc;
|
||||
if (h != NULL)
|
||||
@ -10757,6 +10865,106 @@ ppc_type_of_stub (asection *input_sec,
|
||||
return ppc_stub_none;
|
||||
}
|
||||
|
||||
/* Builds a 64-bit offset in r12 then adds it to r11 (LOAD false) or
|
||||
loads r12 from r11+r12 (LOAD true).
|
||||
. lis %r12,xxx-1b@highest
|
||||
. ori %r12,xxx-1b@higher
|
||||
. sldi %r12,%r12,32
|
||||
. oris %r12,%r12,xxx-1b@hi
|
||||
. ori %r12,%r12,xxx-1b@l
|
||||
. add %r12,%r11,%r12 */
|
||||
|
||||
static bfd_byte *
|
||||
build_offset (bfd *abfd, bfd_byte *p, bfd_vma off, bfd_boolean load)
|
||||
{
|
||||
if (off + 0x8000 < 0x10000)
|
||||
{
|
||||
if (load)
|
||||
bfd_put_32 (abfd, LD_R12_0R11 + PPC_LO (off), p);
|
||||
else
|
||||
bfd_put_32 (abfd, ADDI_R12_R11 + PPC_LO (off), p);
|
||||
p += 4;
|
||||
}
|
||||
else if (off + 0x80008000ULL < 0x100000000ULL)
|
||||
{
|
||||
bfd_put_32 (abfd, ADDIS_R12_R11 + PPC_HA (off), p);
|
||||
p += 4;
|
||||
if (load)
|
||||
bfd_put_32 (abfd, LD_R12_0R12 + PPC_LO (off), p);
|
||||
else
|
||||
bfd_put_32 (abfd, ADDI_R12_R12 + PPC_LO (off), p);
|
||||
p += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (off + 0x800000000000ULL < 0x1000000000000ULL)
|
||||
{
|
||||
bfd_put_32 (abfd, LI_R12_0 + ((off >> 32) & 0xffff), p);
|
||||
p += 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
bfd_put_32 (abfd, LIS_R12 + ((off >> 48) & 0xffff), p);
|
||||
p += 4;
|
||||
if (((off >> 32) & 0xffff) != 0)
|
||||
{
|
||||
bfd_put_32 (abfd, ORI_R12_R12_0 + ((off >> 32) & 0xffff), p);
|
||||
p += 4;
|
||||
}
|
||||
}
|
||||
if (((off >> 32) & 0xffffffffULL) != 0)
|
||||
{
|
||||
bfd_put_32 (abfd, SLDI_R12_R12_32, p);
|
||||
p += 4;
|
||||
}
|
||||
if (PPC_HI (off) != 0)
|
||||
{
|
||||
bfd_put_32 (abfd, ORIS_R12_R12_0 + PPC_HI (off), p);
|
||||
p += 4;
|
||||
}
|
||||
if (PPC_LO (off) != 0)
|
||||
{
|
||||
bfd_put_32 (abfd, ORI_R12_R12_0 + PPC_LO (off), p);
|
||||
p += 4;
|
||||
}
|
||||
if (load)
|
||||
bfd_put_32 (abfd, LDX_R12_R11_R12, p);
|
||||
else
|
||||
bfd_put_32 (abfd, ADD_R12_R11_R12, p);
|
||||
p += 4;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
size_offset (bfd_vma off)
|
||||
{
|
||||
unsigned int size;
|
||||
if (off + 0x8000 < 0x10000)
|
||||
size = 4;
|
||||
else if (off + 0x80008000ULL < 0x100000000ULL)
|
||||
size = 8;
|
||||
else
|
||||
{
|
||||
if (off + 0x800000000000ULL < 0x1000000000000ULL)
|
||||
size = 4;
|
||||
else
|
||||
{
|
||||
size = 4;
|
||||
if (((off >> 32) & 0xffff) != 0)
|
||||
size += 4;
|
||||
}
|
||||
if (((off >> 32) & 0xffffffffULL) != 0)
|
||||
size += 4;
|
||||
if (PPC_HI (off) != 0)
|
||||
size += 4;
|
||||
if (PPC_LO (off) != 0)
|
||||
size += 4;
|
||||
size += 4;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
/* With power7 weakly ordered memory model, it is possible for ld.so
|
||||
to update a plt entry in one thread and have another thread see a
|
||||
stale zero toc entry. To avoid this we need some sort of acquire
|
||||
@ -10784,8 +10992,17 @@ plt_stub_size (struct ppc_link_hash_table *htab,
|
||||
struct ppc_stub_hash_entry *stub_entry,
|
||||
bfd_vma off)
|
||||
{
|
||||
unsigned size = 12;
|
||||
unsigned size;
|
||||
|
||||
if (stub_entry->stub_type >= ppc_stub_plt_call_notoc)
|
||||
{
|
||||
size = 24 + size_offset (off);
|
||||
if (stub_entry->stub_type > ppc_stub_plt_call_notoc)
|
||||
size += 4;
|
||||
return size;
|
||||
}
|
||||
|
||||
size = 12;
|
||||
if (ALWAYS_EMIT_R2SAVE
|
||||
|| stub_entry->stub_type == ppc_stub_plt_call_r2save)
|
||||
size += 4;
|
||||
@ -11422,6 +11639,78 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
||||
p += 4;
|
||||
break;
|
||||
|
||||
case ppc_stub_long_branch_notoc:
|
||||
case ppc_stub_long_branch_both:
|
||||
case ppc_stub_plt_branch_notoc:
|
||||
case ppc_stub_plt_branch_both:
|
||||
case ppc_stub_plt_call_notoc:
|
||||
case ppc_stub_plt_call_both:
|
||||
p = loc;
|
||||
off = (8 + stub_entry->stub_offset
|
||||
+ stub_entry->group->stub_sec->output_offset
|
||||
+ stub_entry->group->stub_sec->output_section->vma);
|
||||
if (stub_entry->stub_type == ppc_stub_long_branch_both
|
||||
|| stub_entry->stub_type == ppc_stub_plt_branch_both
|
||||
|| stub_entry->stub_type == ppc_stub_plt_call_both)
|
||||
{
|
||||
off += 4;
|
||||
bfd_put_32 (htab->params->stub_bfd, STD_R2_0R1 + STK_TOC (htab), p);
|
||||
p += 4;
|
||||
}
|
||||
if (stub_entry->stub_type >= ppc_stub_plt_call_notoc)
|
||||
{
|
||||
targ = stub_entry->plt_ent->plt.offset & ~1;
|
||||
if (targ >= (bfd_vma) -2)
|
||||
abort ();
|
||||
|
||||
plt = htab->elf.splt;
|
||||
if (!htab->elf.dynamic_sections_created
|
||||
|| stub_entry->h == NULL
|
||||
|| stub_entry->h->elf.dynindx == -1)
|
||||
{
|
||||
if (stub_entry->symtype == STT_GNU_IFUNC)
|
||||
plt = htab->elf.iplt;
|
||||
else
|
||||
plt = htab->pltlocal;
|
||||
}
|
||||
targ += plt->output_offset + plt->output_section->vma;
|
||||
}
|
||||
else
|
||||
targ = (stub_entry->target_value
|
||||
+ stub_entry->target_section->output_offset
|
||||
+ stub_entry->target_section->output_section->vma);
|
||||
off = targ - off;
|
||||
bfd_put_32 (htab->params->stub_bfd, MFLR_R12, p);
|
||||
p += 4;
|
||||
bfd_put_32 (htab->params->stub_bfd, BCL_20_31, p);
|
||||
p += 4;
|
||||
bfd_put_32 (htab->params->stub_bfd, MFLR_R11, p);
|
||||
p += 4;
|
||||
bfd_put_32 (htab->params->stub_bfd, MTLR_R12, p);
|
||||
p += 4;
|
||||
p = build_offset (htab->params->stub_bfd, p, off,
|
||||
stub_entry->stub_type >= ppc_stub_plt_call_notoc);
|
||||
if (stub_entry->stub_type == ppc_stub_long_branch_notoc)
|
||||
{
|
||||
off += 8;
|
||||
bfd_put_32 (htab->params->stub_bfd,
|
||||
B_DOT | ((off - (p - loc)) & 0x3fffffc), p);
|
||||
}
|
||||
else if (stub_entry->stub_type == ppc_stub_long_branch_both)
|
||||
{
|
||||
off += 12;
|
||||
bfd_put_32 (htab->params->stub_bfd,
|
||||
B_DOT | ((off - (p - loc)) & 0x3fffffc), p);
|
||||
}
|
||||
else
|
||||
{
|
||||
bfd_put_32 (htab->params->stub_bfd, MTCTR_R12, p);
|
||||
p += 4;
|
||||
bfd_put_32 (htab->params->stub_bfd, BCTR, p);
|
||||
}
|
||||
p += 4;
|
||||
break;
|
||||
|
||||
case ppc_stub_plt_call:
|
||||
case ppc_stub_plt_call_r2save:
|
||||
if (stub_entry->h != NULL
|
||||
@ -11513,9 +11802,15 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
||||
size_t len1, len2;
|
||||
char *name;
|
||||
const char *const stub_str[] = { "long_branch",
|
||||
"long_branch",
|
||||
"long_branch",
|
||||
"long_branch",
|
||||
"plt_branch",
|
||||
"plt_branch",
|
||||
"plt_branch",
|
||||
"plt_branch",
|
||||
"plt_call",
|
||||
"plt_call",
|
||||
"plt_call",
|
||||
"plt_call" };
|
||||
|
||||
@ -11583,8 +11878,8 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if (stub_entry->stub_type == ppc_stub_plt_call
|
||||
|| stub_entry->stub_type == ppc_stub_plt_call_r2save)
|
||||
if (stub_entry->stub_type >= ppc_stub_plt_call
|
||||
&& stub_entry->stub_type <= ppc_stub_plt_call_both)
|
||||
{
|
||||
asection *plt;
|
||||
targ = stub_entry->plt_ent->plt.offset & ~(bfd_vma) 1;
|
||||
@ -11602,20 +11897,33 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
||||
}
|
||||
targ += plt->output_offset + plt->output_section->vma;
|
||||
|
||||
if (stub_entry->stub_type >= ppc_stub_plt_call_notoc)
|
||||
{
|
||||
off = (8 + stub_entry->stub_offset
|
||||
+ stub_entry->group->stub_sec->output_offset
|
||||
+ stub_entry->group->stub_sec->output_section->vma);
|
||||
if (stub_entry->stub_type > ppc_stub_plt_call_notoc)
|
||||
off += 4;
|
||||
}
|
||||
else
|
||||
off = (elf_gp (info->output_bfd)
|
||||
+ htab->sec_info[stub_entry->group->link_sec->id].toc_off);
|
||||
off = targ - off;
|
||||
|
||||
if (htab->params->plt_stub_align != 0)
|
||||
{
|
||||
unsigned pad = plt_stub_pad (htab, stub_entry, off);
|
||||
unsigned pad = plt_stub_pad (htab, stub_entry, targ - off);
|
||||
|
||||
stub_entry->group->stub_sec->size += pad;
|
||||
stub_entry->stub_offset = stub_entry->group->stub_sec->size;
|
||||
if (stub_entry->stub_type >= ppc_stub_plt_call_notoc)
|
||||
off += pad;
|
||||
}
|
||||
|
||||
off = targ - off;
|
||||
size = plt_stub_size (htab, stub_entry, off);
|
||||
|
||||
if (stub_entry->stub_type < ppc_stub_plt_call_notoc)
|
||||
{
|
||||
if (stub_entry->h != NULL
|
||||
&& (stub_entry->h == htab->tls_get_addr_fd
|
||||
|| stub_entry->h == htab->tls_get_addr)
|
||||
@ -11636,6 +11944,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
||||
stub_entry->group->stub_sec->flags |= SEC_RELOC;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ppc_stub_long_branch or ppc_stub_plt_branch, or their r2off
|
||||
@ -11671,16 +11980,34 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
||||
size += 4;
|
||||
off += size - 4;
|
||||
}
|
||||
else if (stub_entry->stub_type >= ppc_stub_long_branch_notoc)
|
||||
{
|
||||
size = 20 + size_offset (targ - (off + 8));
|
||||
if (stub_entry->stub_type > ppc_stub_long_branch_notoc)
|
||||
size += 4;
|
||||
off += size - 4;
|
||||
}
|
||||
off = targ - off;
|
||||
|
||||
if (stub_entry->stub_type >= ppc_stub_long_branch_notoc)
|
||||
{
|
||||
if (off + (1 << 25) >= (bfd_vma) (1 << 26))
|
||||
{
|
||||
stub_entry->stub_type += (ppc_stub_plt_branch_notoc
|
||||
- ppc_stub_long_branch_notoc);
|
||||
size += 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
local_off = PPC64_LOCAL_ENTRY_OFFSET (stub_entry->other);
|
||||
|
||||
/* If the branch offset is too big, use a ppc_stub_plt_branch.
|
||||
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
|
||||
if ((stub_entry->stub_type == ppc_stub_long_branch_r2off
|
||||
&& r2off == 0
|
||||
&& htab->sec_info[stub_entry->target_section->id].toc_off == 0))
|
||||
&& htab->sec_info[stub_entry->target_section->id].toc_off == 0)
|
||||
|| off + (1 << 25) >= (bfd_vma) (1 << 26) - local_off)
|
||||
{
|
||||
struct ppc_branch_hash_entry *br_entry;
|
||||
|
||||
@ -11710,7 +12037,6 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
||||
}
|
||||
}
|
||||
|
||||
stub_entry->stub_type += ppc_stub_plt_branch - ppc_stub_long_branch;
|
||||
targ = (br_entry->offset
|
||||
+ htab->brlt->output_offset
|
||||
+ htab->brlt->output_section->vma);
|
||||
@ -11725,6 +12051,8 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
||||
stub_entry->group->stub_sec->flags |= SEC_RELOC;
|
||||
}
|
||||
|
||||
stub_entry->stub_type
|
||||
+= ppc_stub_plt_branch - ppc_stub_long_branch;
|
||||
if (stub_entry->stub_type != ppc_stub_plt_branch_r2off)
|
||||
{
|
||||
size = 12;
|
||||
@ -11749,6 +12077,7 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
||||
stub_entry->group->stub_sec->flags |= SEC_RELOC;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stub_entry->group->stub_sec->size += size;
|
||||
return TRUE;
|
||||
@ -12154,6 +12483,7 @@ toc_adjusting_stub_needed (struct bfd_link_info *info, asection *isec)
|
||||
|
||||
r_type = ELF64_R_TYPE (rel->r_info);
|
||||
if (r_type != R_PPC64_REL24
|
||||
&& r_type != R_PPC64_REL24_NOTOC
|
||||
&& r_type != R_PPC64_REL14
|
||||
&& r_type != R_PPC64_REL14_BRTAKEN
|
||||
&& r_type != R_PPC64_REL14_BRNTAKEN
|
||||
@ -12750,6 +13080,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
|
||||
|
||||
/* Only look for stubs on branch instructions. */
|
||||
if (r_type != R_PPC64_REL24
|
||||
&& r_type != R_PPC64_REL24_NOTOC
|
||||
&& r_type != R_PPC64_REL14
|
||||
&& r_type != R_PPC64_REL14_BRTAKEN
|
||||
&& r_type != R_PPC64_REL14_BRNTAKEN)
|
||||
@ -12857,7 +13188,19 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
|
||||
&plt_ent, destination,
|
||||
local_off);
|
||||
|
||||
if (stub_type != ppc_stub_plt_call)
|
||||
if (r_type == R_PPC64_REL24_NOTOC)
|
||||
{
|
||||
if (stub_type == ppc_stub_plt_call)
|
||||
stub_type = ppc_stub_plt_call_notoc;
|
||||
else if (stub_type == ppc_stub_long_branch
|
||||
|| (code_sec != NULL
|
||||
&& code_sec->output_section != NULL
|
||||
&& (((hash ? hash->elf.other : sym->st_other)
|
||||
& STO_PPC64_LOCAL_MASK)
|
||||
!= 1 << STO_PPC64_LOCAL_BIT)))
|
||||
stub_type = ppc_stub_long_branch_notoc;
|
||||
}
|
||||
else if (stub_type != ppc_stub_plt_call)
|
||||
{
|
||||
/* Check whether we need a TOC adjusting stub.
|
||||
Since the linker pastes together pieces from
|
||||
@ -12882,6 +13225,7 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
|
||||
|
||||
/* __tls_get_addr calls might be eliminated. */
|
||||
if (stub_type != ppc_stub_plt_call
|
||||
&& stub_type != ppc_stub_plt_call_notoc
|
||||
&& hash != NULL
|
||||
&& (hash == htab->tls_get_addr
|
||||
|| hash == htab->tls_get_addr_fd)
|
||||
@ -12929,9 +13273,71 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
|
||||
stub_name, FALSE, FALSE);
|
||||
if (stub_entry != NULL)
|
||||
{
|
||||
/* The proper stub has already been created. */
|
||||
enum ppc_stub_type old_type;
|
||||
/* A stub has already been created, but it may
|
||||
not be the required type. We shouldn't be
|
||||
transitioning from plt_call to long_branch
|
||||
stubs or vice versa, but we might be
|
||||
upgrading from plt_call to plt_call_r2save or
|
||||
from long_branch to long_branch_r2off. */
|
||||
free (stub_name);
|
||||
if (stub_type == ppc_stub_plt_call_r2save)
|
||||
old_type = stub_entry->stub_type;
|
||||
switch (old_type)
|
||||
{
|
||||
default:
|
||||
abort ();
|
||||
|
||||
case ppc_stub_save_res:
|
||||
continue;
|
||||
|
||||
case ppc_stub_plt_call:
|
||||
case ppc_stub_plt_call_r2save:
|
||||
case ppc_stub_plt_call_notoc:
|
||||
case ppc_stub_plt_call_both:
|
||||
if (stub_type == ppc_stub_plt_call)
|
||||
continue;
|
||||
else if (stub_type == ppc_stub_plt_call_r2save)
|
||||
{
|
||||
if (old_type == ppc_stub_plt_call_notoc)
|
||||
stub_type = ppc_stub_plt_call_both;
|
||||
}
|
||||
else if (stub_type == ppc_stub_plt_call_notoc)
|
||||
{
|
||||
if (old_type == ppc_stub_plt_call_r2save)
|
||||
stub_type = ppc_stub_plt_call_both;
|
||||
}
|
||||
else
|
||||
abort ();
|
||||
break;
|
||||
|
||||
case ppc_stub_plt_branch:
|
||||
case ppc_stub_plt_branch_r2off:
|
||||
case ppc_stub_plt_branch_notoc:
|
||||
case ppc_stub_plt_branch_both:
|
||||
old_type += (ppc_stub_long_branch
|
||||
- ppc_stub_plt_branch);
|
||||
/* Fall through. */
|
||||
case ppc_stub_long_branch:
|
||||
case ppc_stub_long_branch_r2off:
|
||||
case ppc_stub_long_branch_notoc:
|
||||
case ppc_stub_long_branch_both:
|
||||
if (stub_type == ppc_stub_long_branch)
|
||||
continue;
|
||||
else if (stub_type == ppc_stub_long_branch_r2off)
|
||||
{
|
||||
if (old_type == ppc_stub_long_branch_notoc)
|
||||
stub_type = ppc_stub_long_branch_both;
|
||||
}
|
||||
else if (stub_type == ppc_stub_long_branch_notoc)
|
||||
{
|
||||
if (old_type == ppc_stub_long_branch_r2off)
|
||||
stub_type = ppc_stub_long_branch_both;
|
||||
}
|
||||
else
|
||||
abort ();
|
||||
break;
|
||||
}
|
||||
if (old_type < stub_type)
|
||||
stub_entry->stub_type = stub_type;
|
||||
continue;
|
||||
}
|
||||
@ -12952,17 +13358,17 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
|
||||
}
|
||||
|
||||
stub_entry->stub_type = stub_type;
|
||||
if (stub_type != ppc_stub_plt_call
|
||||
&& stub_type != ppc_stub_plt_call_r2save)
|
||||
{
|
||||
stub_entry->target_value = code_value;
|
||||
stub_entry->target_section = code_sec;
|
||||
}
|
||||
else
|
||||
if (stub_type >= ppc_stub_plt_call
|
||||
&& stub_type <= ppc_stub_plt_call_both)
|
||||
{
|
||||
stub_entry->target_value = sym_value;
|
||||
stub_entry->target_section = sym_sec;
|
||||
}
|
||||
else
|
||||
{
|
||||
stub_entry->target_value = code_value;
|
||||
stub_entry->target_section = code_sec;
|
||||
}
|
||||
stub_entry->h = hash;
|
||||
stub_entry->plt_ent = plt_ent;
|
||||
stub_entry->symtype
|
||||
@ -13842,18 +14248,30 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
|
||||
stub_sec_count),
|
||||
stub_sec_count);
|
||||
sprintf (*stats + len, _(" branch %lu\n"
|
||||
" toc adjust %lu\n"
|
||||
" branch toc adj %lu\n"
|
||||
" branch notoc %lu\n"
|
||||
" branch both %lu\n"
|
||||
" long branch %lu\n"
|
||||
" long toc adj %lu\n"
|
||||
" long notoc %lu\n"
|
||||
" long both %lu\n"
|
||||
" plt call %lu\n"
|
||||
" plt call toc %lu\n"
|
||||
" plt call save %lu\n"
|
||||
" plt call notoc %lu\n"
|
||||
" plt call both %lu\n"
|
||||
" global entry %lu"),
|
||||
htab->stub_count[ppc_stub_long_branch - 1],
|
||||
htab->stub_count[ppc_stub_long_branch_r2off - 1],
|
||||
htab->stub_count[ppc_stub_long_branch_notoc - 1],
|
||||
htab->stub_count[ppc_stub_long_branch_both - 1],
|
||||
htab->stub_count[ppc_stub_plt_branch - 1],
|
||||
htab->stub_count[ppc_stub_plt_branch_r2off - 1],
|
||||
htab->stub_count[ppc_stub_plt_branch_notoc - 1],
|
||||
htab->stub_count[ppc_stub_plt_branch_both - 1],
|
||||
htab->stub_count[ppc_stub_plt_call - 1],
|
||||
htab->stub_count[ppc_stub_plt_call_r2save - 1],
|
||||
htab->stub_count[ppc_stub_plt_call_notoc - 1],
|
||||
htab->stub_count[ppc_stub_plt_call_both - 1],
|
||||
htab->stub_count[ppc_stub_global_entry - 1]);
|
||||
}
|
||||
return TRUE;
|
||||
@ -14685,6 +15103,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
/* Fall through. */
|
||||
|
||||
case R_PPC64_REL24:
|
||||
case R_PPC64_REL24_NOTOC:
|
||||
case R_PPC64_PLTCALL:
|
||||
/* Calls to functions with a different TOC, such as calls to
|
||||
shared objects, need to alter the TOC pointer. This is
|
||||
@ -14701,15 +15120,18 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
htab);
|
||||
if (r_type == R_PPC64_PLTCALL
|
||||
&& stub_entry != NULL
|
||||
&& (stub_entry->stub_type == ppc_stub_plt_call
|
||||
|| stub_entry->stub_type == ppc_stub_plt_call_r2save))
|
||||
&& stub_entry->stub_type >= ppc_stub_plt_call
|
||||
&& stub_entry->stub_type <= ppc_stub_plt_call_both)
|
||||
stub_entry = NULL;
|
||||
|
||||
if (stub_entry != NULL
|
||||
&& (stub_entry->stub_type == ppc_stub_plt_call
|
||||
|| stub_entry->stub_type == ppc_stub_plt_call_r2save
|
||||
|| stub_entry->stub_type == ppc_stub_plt_call_both
|
||||
|| stub_entry->stub_type == ppc_stub_plt_branch_r2off
|
||||
|| stub_entry->stub_type == ppc_stub_long_branch_r2off))
|
||||
|| stub_entry->stub_type == ppc_stub_plt_branch_both
|
||||
|| stub_entry->stub_type == ppc_stub_long_branch_r2off
|
||||
|| stub_entry->stub_type == ppc_stub_long_branch_both))
|
||||
{
|
||||
bfd_boolean can_plt_call = FALSE;
|
||||
|
||||
@ -14721,6 +15143,11 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
/* The function doesn't use or change r2. */
|
||||
can_plt_call = TRUE;
|
||||
}
|
||||
else if (r_type == R_PPC64_REL24_NOTOC)
|
||||
{
|
||||
/* NOTOC calls don't need to restore r2. */
|
||||
can_plt_call = TRUE;
|
||||
}
|
||||
|
||||
/* All of these stubs may modify r2, so there must be a
|
||||
branch and link followed by a nop. The nop is
|
||||
@ -14802,8 +15229,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
|
||||
if (!can_plt_call)
|
||||
{
|
||||
if (stub_entry->stub_type == ppc_stub_plt_call
|
||||
|| stub_entry->stub_type == ppc_stub_plt_call_r2save)
|
||||
if (stub_entry->stub_type >= ppc_stub_plt_call
|
||||
&& stub_entry->stub_type <= ppc_stub_plt_call_both)
|
||||
info->callbacks->einfo
|
||||
/* xgettext:c-format */
|
||||
(_("%H: call to `%pT' lacks nop, can't restore toc; "
|
||||
@ -14821,8 +15248,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
}
|
||||
|
||||
if (can_plt_call
|
||||
&& (stub_entry->stub_type == ppc_stub_plt_call
|
||||
|| stub_entry->stub_type == ppc_stub_plt_call_r2save))
|
||||
&& stub_entry->stub_type >= ppc_stub_plt_call
|
||||
&& stub_entry->stub_type <= ppc_stub_plt_call_both)
|
||||
unresolved_reloc = FALSE;
|
||||
}
|
||||
|
||||
@ -14864,6 +15291,28 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
/* Don't use the stub if this branch is in range. */
|
||||
stub_entry = NULL;
|
||||
|
||||
if (stub_entry != NULL
|
||||
&& (stub_entry->stub_type == ppc_stub_long_branch_notoc
|
||||
|| stub_entry->stub_type == ppc_stub_long_branch_both
|
||||
|| stub_entry->stub_type == ppc_stub_plt_branch_notoc
|
||||
|| stub_entry->stub_type == ppc_stub_plt_branch_both)
|
||||
&& (r_type != R_PPC64_REL24_NOTOC
|
||||
|| ((fdh ? fdh->elf.other : sym->st_other)
|
||||
& STO_PPC64_LOCAL_MASK) == 1 << STO_PPC64_LOCAL_BIT)
|
||||
&& (relocation + addend - from + max_br_offset
|
||||
< 2 * max_br_offset))
|
||||
stub_entry = NULL;
|
||||
|
||||
if (stub_entry != NULL
|
||||
&& (stub_entry->stub_type == ppc_stub_long_branch_r2off
|
||||
|| stub_entry->stub_type == ppc_stub_long_branch_both
|
||||
|| stub_entry->stub_type == ppc_stub_plt_branch_r2off
|
||||
|| stub_entry->stub_type == ppc_stub_plt_branch_both)
|
||||
&& r_type == R_PPC64_REL24_NOTOC
|
||||
&& (relocation + addend - from + max_br_offset
|
||||
< 2 * max_br_offset))
|
||||
stub_entry = NULL;
|
||||
|
||||
if (stub_entry != NULL)
|
||||
{
|
||||
/* Munge up the value and addend so that we call the stub
|
||||
@ -14883,14 +15332,19 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
addend = 0;
|
||||
reloc_dest = DEST_STUB;
|
||||
|
||||
if ((stub_entry->stub_type == ppc_stub_plt_call
|
||||
|| stub_entry->stub_type == ppc_stub_plt_call_r2save)
|
||||
&& (ALWAYS_EMIT_R2SAVE
|
||||
|| stub_entry->stub_type == ppc_stub_plt_call_r2save)
|
||||
if (((stub_entry->stub_type == ppc_stub_plt_call
|
||||
&& ALWAYS_EMIT_R2SAVE)
|
||||
|| stub_entry->stub_type == ppc_stub_plt_call_r2save
|
||||
|| stub_entry->stub_type == ppc_stub_plt_call_both)
|
||||
&& rel + 1 < relend
|
||||
&& rel[1].r_offset == rel->r_offset + 4
|
||||
&& ELF64_R_TYPE (rel[1].r_info) == R_PPC64_TOCSAVE)
|
||||
relocation += 4;
|
||||
else if ((stub_entry->stub_type == ppc_stub_long_branch_both
|
||||
|| stub_entry->stub_type == ppc_stub_plt_branch_both
|
||||
|| stub_entry->stub_type == ppc_stub_plt_call_both)
|
||||
&& r_type == R_PPC64_REL24_NOTOC)
|
||||
relocation += 4;
|
||||
}
|
||||
|
||||
if (insn != 0)
|
||||
@ -14923,7 +15377,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
else if (h != NULL
|
||||
&& h->elf.root.type == bfd_link_hash_undefweak
|
||||
&& h->elf.dynindx == -1
|
||||
&& r_type == R_PPC64_REL24
|
||||
&& (r_type == R_PPC64_REL24
|
||||
|| r_type == R_PPC64_REL24_NOTOC)
|
||||
&& relocation == 0
|
||||
&& addend == 0)
|
||||
{
|
||||
@ -15300,6 +15755,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
||||
case R_PPC64_REL14_BRNTAKEN:
|
||||
case R_PPC64_REL14_BRTAKEN:
|
||||
case R_PPC64_REL24:
|
||||
case R_PPC64_REL24_NOTOC:
|
||||
break;
|
||||
|
||||
case R_PPC64_TPREL16:
|
||||
|
@ -1469,6 +1469,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
|
||||
"BFD_RELOC_PPC64_ADDR16_HIGHA",
|
||||
"BFD_RELOC_PPC64_ADDR64_LOCAL",
|
||||
"BFD_RELOC_PPC64_ENTRY",
|
||||
"BFD_RELOC_PPC64_REL24_NOTOC",
|
||||
"BFD_RELOC_PPC_TLS",
|
||||
"BFD_RELOC_PPC_TLSGD",
|
||||
"BFD_RELOC_PPC_TLSLD",
|
||||
|
@ -3011,6 +3011,8 @@ ENUMX
|
||||
BFD_RELOC_PPC64_ADDR64_LOCAL
|
||||
ENUMX
|
||||
BFD_RELOC_PPC64_ENTRY
|
||||
ENUMX
|
||||
BFD_RELOC_PPC64_REL24_NOTOC
|
||||
ENUMDOC
|
||||
Power(rs6000) and PowerPC relocations.
|
||||
|
||||
|
@ -1,3 +1,8 @@
|
||||
2018-08-05 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* config/tc-ppc.c (ppc_elf_suffix): Support @notoc.
|
||||
(ppc_force_relocation, ppc_fix_adjustable): Handle REL24_NOTOC.
|
||||
|
||||
2018-08-03 Dimitar Dimitrov <dimitar@dinux.eu>
|
||||
|
||||
* config/tc-pru.c (pru_regname_to_dw2regnum): Return the starting HW
|
||||
|
@ -2085,6 +2085,7 @@ ppc_elf_suffix (char **str_p, expressionS *exp_p)
|
||||
MAP64 ("tprel@highera", BFD_RELOC_PPC64_TPREL16_HIGHERA),
|
||||
MAP64 ("tprel@highest", BFD_RELOC_PPC64_TPREL16_HIGHEST),
|
||||
MAP64 ("tprel@highesta", BFD_RELOC_PPC64_TPREL16_HIGHESTA),
|
||||
MAP64 ("notoc", BFD_RELOC_PPC64_REL24_NOTOC),
|
||||
{ (char *) 0, 0, 0, 0, BFD_RELOC_NONE }
|
||||
};
|
||||
|
||||
@ -6416,6 +6417,7 @@ ppc_force_relocation (fixS *fix)
|
||||
case BFD_RELOC_PPC_BA26:
|
||||
case BFD_RELOC_PPC_B16:
|
||||
case BFD_RELOC_PPC_BA16:
|
||||
case BFD_RELOC_PPC64_REL24_NOTOC:
|
||||
/* All branch fixups targeting a localentry symbol must
|
||||
force a relocation. */
|
||||
if (fix->fx_addsy)
|
||||
@ -6454,6 +6456,7 @@ ppc_fix_adjustable (fixS *fix)
|
||||
case BFD_RELOC_PPC_B16_BRNTAKEN:
|
||||
case BFD_RELOC_PPC_BA16_BRTAKEN:
|
||||
case BFD_RELOC_PPC_BA16_BRNTAKEN:
|
||||
case BFD_RELOC_PPC64_REL24_NOTOC:
|
||||
if (fix->fx_addsy)
|
||||
{
|
||||
asymbol *bfdsym = symbol_get_bfdsym (fix->fx_addsy);
|
||||
|
@ -1,3 +1,12 @@
|
||||
2018-08-05 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* testsuite/ld-powerpc/ext.d,
|
||||
* testsuite/ld-powerpc/ext.s,
|
||||
* testsuite/ld-powerpc/ext.lnk,
|
||||
* testsuite/ld-powerpc/notoc.d,
|
||||
* testsuite/ld-powerpc/notoc.s: New tests.
|
||||
* testsuite/ld-powerpc/powerpc.exp: Run them.
|
||||
|
||||
2018-08-05 Alan Modra <amodra@gmail.com>
|
||||
|
||||
* testsuite/ld-powerpc/elfv2exe.d: Adjust for stub symbol change.
|
||||
|
17
ld/testsuite/ld-powerpc/ext.d
Normal file
17
ld/testsuite/ld-powerpc/ext.d
Normal file
@ -0,0 +1,17 @@
|
||||
#source: ext.s
|
||||
#as: -a64
|
||||
#objdump: -dr
|
||||
#target: powerpc64*-*-*
|
||||
# Just assembles an object for notoc.d
|
||||
|
||||
.*
|
||||
|
||||
Disassembly of section \.text:
|
||||
|
||||
0+ <ext>:
|
||||
0: (00 00 4c 3c|3c 4c 00 00) addis r2,r12,0
|
||||
(0|2): R_PPC64_REL16_HA \.TOC\.(|\+0x2)
|
||||
4: (00 00 42 38|38 42 00 00) addi r2,r2,0
|
||||
(4|6): R_PPC64_REL16_LO \.TOC\.\+0x(4|6)
|
||||
8: (00 00 00 60|60 00 00 00) nop
|
||||
c: (20 00 80 4e|4e 80 00 20) blr
|
6
ld/testsuite/ld-powerpc/ext.lnk
Normal file
6
ld/testsuite/ld-powerpc/ext.lnk
Normal file
@ -0,0 +1,6 @@
|
||||
SECTIONS
|
||||
{
|
||||
. = 0x8000000000000000;
|
||||
.text.ext : { tmpdir/ext.o(.text) }
|
||||
}
|
||||
INSERT BEFORE .stab;
|
9
ld/testsuite/ld-powerpc/ext.s
Normal file
9
ld/testsuite/ld-powerpc/ext.s
Normal file
@ -0,0 +1,9 @@
|
||||
.text
|
||||
.globl ext
|
||||
ext:
|
||||
0:
|
||||
addis 2,12,.TOC.-0b@ha
|
||||
addi 2,2,.TOC.-0b@l
|
||||
.localentry ext,.-0b
|
||||
nop
|
||||
blr
|
102
ld/testsuite/ld-powerpc/notoc.d
Normal file
102
ld/testsuite/ld-powerpc/notoc.d
Normal file
@ -0,0 +1,102 @@
|
||||
#source: notoc.s
|
||||
#as: -a64
|
||||
#ld: --no-plt-localentry -T ext.lnk
|
||||
#objdump: -dr
|
||||
#target: powerpc64*-*-*
|
||||
|
||||
.*
|
||||
|
||||
Disassembly of section \.text:
|
||||
|
||||
.* <.*\.long_branch\.f1>:
|
||||
.*: (18 00 41 f8|f8 41 00 18) std r2,24\(r1\)
|
||||
.*: (7c 00 00 48|48 00 00 7c) b .* <f1>
|
||||
|
||||
.* <.*\.long_branch\.g1>:
|
||||
.*: (18 00 41 f8|f8 41 00 18) std r2,24\(r1\)
|
||||
.*: (8c 00 00 48|48 00 00 8c) b .* <g1>
|
||||
|
||||
.* <.*\.plt_branch\.ext>:
|
||||
.*: (a6 02 88 7d|7d 88 02 a6) mflr r12
|
||||
.*: (05 00 9f 42|42 9f 00 05) bcl .*
|
||||
.*: (a6 02 68 7d|7d 68 02 a6) mflr r11
|
||||
.*: (a6 03 88 7d|7d 88 03 a6) mtlr r12
|
||||
.*: (ff 7f 80 3d|3d 80 7f ff) lis r12,32767
|
||||
.*: (ff ff 8c 61|61 8c ff ff) ori r12,r12,65535
|
||||
.*: (c6 07 9c 79|79 9c 07 c6) rldicr r28,r12,32,31
|
||||
.*: (ff ef 8c 65|65 8c ef ff) oris r12,r12,61439
|
||||
.*: (28 ff 8c 61|61 8c ff 28) ori r12,r12,65320
|
||||
.*: (14 62 8b 7d|7d 8b 62 14) add r12,r11,r12
|
||||
.*: (a6 03 89 7d|7d 89 03 a6) mtctr r12
|
||||
.*: (20 04 80 4e|4e 80 04 20) bctr
|
||||
|
||||
.* <.*\.long_branch\.f2>:
|
||||
.*: (a6 02 88 7d|7d 88 02 a6) mflr r12
|
||||
.*: (05 00 9f 42|42 9f 00 05) bcl .*
|
||||
.*: (a6 02 68 7d|7d 68 02 a6) mflr r11
|
||||
.*: (a6 03 88 7d|7d 88 03 a6) mtlr r12
|
||||
.*: (64 00 8b 39|39 8b 00 64) addi r12,r11,100
|
||||
.*: (58 00 00 48|48 00 00 58) b .* <f2>
|
||||
|
||||
.* <.*\.long_branch\.g2>:
|
||||
.*: (a6 02 88 7d|7d 88 02 a6) mflr r12
|
||||
.*: (05 00 9f 42|42 9f 00 05) bcl .*
|
||||
.*: (a6 02 68 7d|7d 68 02 a6) mflr r11
|
||||
.*: (a6 03 88 7d|7d 88 03 a6) mtlr r12
|
||||
.*: (80 00 8b 39|39 8b 00 80) addi r12,r11,128
|
||||
.*: (74 00 00 48|48 00 00 74) b .* <g2>
|
||||
\.\.\.
|
||||
|
||||
.* <f1>:
|
||||
.*: (01 00 00 48|48 00 00 01) bl .* <f1>
|
||||
.*: (bd ff ff 4b|4b ff ff bd) bl .* <.*\.long_branch\.f2>
|
||||
.*: (11 00 00 48|48 00 00 11) bl .* <g1>
|
||||
.*: (cd ff ff 4b|4b ff ff cd) bl .* <.*\.long_branch\.g2>
|
||||
.*: (81 ff ff 4b|4b ff ff 81) bl .* <.*\.plt_branch\.ext>
|
||||
.*: (20 00 80 4e|4e 80 00 20) blr
|
||||
|
||||
.* <g1>:
|
||||
.*: (a9 ff ff 4b|4b ff ff a9) bl .* <.*\.long_branch\.f2>
|
||||
.*: (e5 ff ff 4b|4b ff ff e5) bl .* <f1>
|
||||
.*: (b9 ff ff 4b|4b ff ff b9) bl .* <.*\.long_branch\.g2>
|
||||
.*: (f5 ff ff 4b|4b ff ff f5) bl .* <g1>
|
||||
.*: (20 00 80 4e|4e 80 00 20) blr
|
||||
|
||||
.* <f2>:
|
||||
.*: (02 10 40 3c|3c 40 10 02) lis r2,4098
|
||||
.*: (00 90 42 38|38 42 90 00) addi r2,r2,-28672
|
||||
.*: (4d ff ff 4b|4b ff ff 4d) bl .* <.*\.long_branch\.f1>
|
||||
.*: (18 00 41 e8|e8 41 00 18) ld r2,24\(r1\)
|
||||
.*: (f9 ff ff 4b|4b ff ff f9) bl .* <f2\+0x8>
|
||||
.*: (00 00 00 60|60 00 00 00) nop
|
||||
.*: (45 ff ff 4b|4b ff ff 45) bl .* <.*\.long_branch\.g1>
|
||||
.*: (18 00 41 e8|e8 41 00 18) ld r2,24\(r1\)
|
||||
.*: (1d 00 00 48|48 00 00 1d) bl .* <g2\+0x8>
|
||||
.*: (00 00 00 60|60 00 00 00) nop
|
||||
.*: (3d ff ff 4b|4b ff ff 3d) bl .* <.*\.plt_branch\.ext>
|
||||
.*: (00 00 00 60|60 00 00 00) nop
|
||||
.*: (20 00 80 4e|4e 80 00 20) blr
|
||||
|
||||
.* <g2>:
|
||||
.*: (02 10 40 3c|3c 40 10 02) lis r2,4098
|
||||
.*: (00 90 42 38|38 42 90 00) addi r2,r2,-28672
|
||||
.*: (cd ff ff 4b|4b ff ff cd) bl .* <f2\+0x8>
|
||||
.*: (00 00 00 60|60 00 00 00) nop
|
||||
.*: (11 ff ff 4b|4b ff ff 11) bl .* <.*\.long_branch\.f1>
|
||||
.*: (18 00 41 e8|e8 41 00 18) ld r2,24\(r1\)
|
||||
.*: (f1 ff ff 4b|4b ff ff f1) bl .* <g2\+0x8>
|
||||
.*: (00 00 00 60|60 00 00 00) nop
|
||||
.*: (09 ff ff 4b|4b ff ff 09) bl .* <.*\.long_branch\.g1>
|
||||
.*: (18 00 41 e8|e8 41 00 18) ld r2,24\(r1\)
|
||||
.*: (20 00 80 4e|4e 80 00 20) blr
|
||||
|
||||
.* <_start>:
|
||||
.*: (00 00 00 48|48 00 00 00) b .* <_start>
|
||||
|
||||
Disassembly of section \.text\.ext:
|
||||
|
||||
8000000000000000 <ext>:
|
||||
8000000000000000: (02 10 40 3c|3c 40 10 02) lis r2,4098
|
||||
8000000000000004: (00 90 42 38|38 42 90 00) addi r2,r2,-28672
|
||||
8000000000000008: (00 00 00 60|60 00 00 00) nop
|
||||
800000000000000c: (20 00 80 4e|4e 80 00 20) blr
|
56
ld/testsuite/ld-powerpc/notoc.s
Normal file
56
ld/testsuite/ld-powerpc/notoc.s
Normal file
@ -0,0 +1,56 @@
|
||||
.text
|
||||
.globl f1, f2, g1, g2, _start
|
||||
.weak ext
|
||||
.abiversion 2
|
||||
|
||||
f1:
|
||||
.localentry f1,1
|
||||
bl f1@notoc
|
||||
bl f2@notoc
|
||||
bl g1@notoc
|
||||
bl g2@notoc
|
||||
bl ext@notoc
|
||||
blr
|
||||
|
||||
g1:
|
||||
.localentry g1,1
|
||||
bl f2@notoc
|
||||
bl f1@notoc
|
||||
bl g2@notoc
|
||||
bl g1@notoc
|
||||
blr
|
||||
|
||||
f2:
|
||||
0:
|
||||
addis 2,12,.TOC.-0b@ha
|
||||
addi 2,2,.TOC.-0b@l
|
||||
.localentry f2,.-0b
|
||||
bl f1
|
||||
nop
|
||||
bl f2
|
||||
nop
|
||||
bl g1
|
||||
nop
|
||||
bl g2
|
||||
nop
|
||||
bl ext
|
||||
nop
|
||||
blr
|
||||
|
||||
g2:
|
||||
0:
|
||||
addis 2,12,.TOC.-0b@ha
|
||||
addi 2,2,.TOC.-0b@l
|
||||
.localentry g2,.-0b
|
||||
bl f2
|
||||
nop
|
||||
bl f1
|
||||
nop
|
||||
bl g2
|
||||
nop
|
||||
bl g1
|
||||
nop
|
||||
blr
|
||||
|
||||
_start:
|
||||
b _start
|
@ -331,6 +331,8 @@ if [ supports_ppc64 ] then {
|
||||
run_dump_test "dotsym2"
|
||||
run_dump_test "dotsym3"
|
||||
run_dump_test "dotsym4"
|
||||
run_dump_test "ext"
|
||||
run_dump_test "notoc"
|
||||
}
|
||||
|
||||
run_dump_test "tlsld32"
|
||||
|
Loading…
Reference in New Issue
Block a user