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>
|
2018-08-05 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
* elf64-ppc.c (ppc_build_one_stub): Lose "_r2off" in stub symbols.
|
* 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_ADDR16_HIGHA,
|
||||||
BFD_RELOC_PPC64_ADDR64_LOCAL,
|
BFD_RELOC_PPC64_ADDR64_LOCAL,
|
||||||
BFD_RELOC_PPC64_ENTRY,
|
BFD_RELOC_PPC64_ENTRY,
|
||||||
|
BFD_RELOC_PPC64_REL24_NOTOC,
|
||||||
|
|
||||||
/* PowerPC and PowerPC64 thread-local storage relocations. */
|
/* PowerPC and PowerPC64 thread-local storage relocations. */
|
||||||
BFD_RELOC_PPC_TLS,
|
BFD_RELOC_PPC_TLS,
|
||||||
|
708
bfd/elf64-ppc.c
708
bfd/elf64-ppc.c
@ -164,6 +164,8 @@ static bfd_vma opd_entry_value
|
|||||||
#define BCTR 0x4e800420 /* bctr */
|
#define BCTR 0x4e800420 /* bctr */
|
||||||
|
|
||||||
#define ADDI_R11_R11 0x396b0000 /* addi %r11,%r11,off@l */
|
#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 ADDIS_R2_R2 0x3c420000 /* addis %r2,%r2,off@ha */
|
||||||
#define ADDI_R2_R2 0x38420000 /* addi %r2,%r2,off@l */
|
#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 ADD_R2_R2_R12 0x7c426214 /* add %r2,%r2,%r12 */
|
||||||
|
|
||||||
#define LIS_R2 0x3c400000 /* lis %r2,xxx@ha */
|
#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_R2_R12 0x3c4c0000 /* addis %r2,%r12,xxx@ha */
|
||||||
#define ADDIS_R12_R2 0x3d820000 /* addis %r12,%r2,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 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 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. */
|
/* __glink_PLTresolve stub instructions. We enter with the index in R0. */
|
||||||
#define GLINK_PLTRESOLVE_SIZE(htab) \
|
#define GLINK_PLTRESOLVE_SIZE(htab) \
|
||||||
@ -446,6 +455,21 @@ static reloc_howto_type ppc64_elf_howto_raw[] =
|
|||||||
0x03fffffc, /* dst_mask */
|
0x03fffffc, /* dst_mask */
|
||||||
TRUE), /* pcrel_offset */
|
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. */
|
/* A relative 16 bit branch; the lower two bits must be zero. */
|
||||||
HOWTO (R_PPC64_REL14, /* type */
|
HOWTO (R_PPC64_REL14, /* type */
|
||||||
0, /* rightshift */
|
0, /* rightshift */
|
||||||
@ -2308,6 +2332,8 @@ ppc64_elf_reloc_type_lookup (bfd *abfd,
|
|||||||
break;
|
break;
|
||||||
case BFD_RELOC_PPC_B26: r = R_PPC64_REL24;
|
case BFD_RELOC_PPC_B26: r = R_PPC64_REL24;
|
||||||
break;
|
break;
|
||||||
|
case BFD_RELOC_PPC64_REL24_NOTOC: r = R_PPC64_REL24_NOTOC;
|
||||||
|
break;
|
||||||
case BFD_RELOC_PPC_B16: r = R_PPC64_REL14;
|
case BFD_RELOC_PPC_B16: r = R_PPC64_REL14;
|
||||||
break;
|
break;
|
||||||
case BFD_RELOC_PPC_B16_BRTAKEN: r = R_PPC64_REL14_BRTAKEN;
|
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
|
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
|
the plt entry referenced crosses a 64k boundary, then an extra
|
||||||
"addi %r11,%r11,xxx@toc@l" will be inserted before the "mtctr".
|
"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
|
. addis %r11,%r2,xxx@toc@ha
|
||||||
. ld %r12,xxx+0@toc@l(%r11)
|
. ld %r12,xxx+0@toc@l(%r11)
|
||||||
. mtctr %r12
|
. mtctr %r12
|
||||||
@ -3979,18 +4005,98 @@ must_be_dyn_reloc (struct bfd_link_info *info,
|
|||||||
. mtctr %r12
|
. mtctr %r12
|
||||||
. bctr
|
. bctr
|
||||||
|
|
||||||
In cases where the "addis" instruction would add zero, the "addis" is
|
All of the above stubs are shown as their ELFv1 variants. ELFv2
|
||||||
omitted and following instructions modified slightly in some cases.
|
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 {
|
enum ppc_stub_type {
|
||||||
ppc_stub_none,
|
ppc_stub_none,
|
||||||
ppc_stub_long_branch,
|
ppc_stub_long_branch,
|
||||||
ppc_stub_long_branch_r2off,
|
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,
|
||||||
ppc_stub_plt_branch_r2off,
|
ppc_stub_plt_branch_r2off,
|
||||||
|
ppc_stub_plt_branch_notoc,
|
||||||
|
ppc_stub_plt_branch_both,
|
||||||
ppc_stub_plt_call,
|
ppc_stub_plt_call,
|
||||||
ppc_stub_plt_call_r2save,
|
ppc_stub_plt_call_r2save,
|
||||||
|
ppc_stub_plt_call_notoc,
|
||||||
|
ppc_stub_plt_call_both,
|
||||||
ppc_stub_global_entry,
|
ppc_stub_global_entry,
|
||||||
ppc_stub_save_res
|
ppc_stub_save_res
|
||||||
};
|
};
|
||||||
@ -5478,6 +5584,7 @@ static bfd_boolean
|
|||||||
is_branch_reloc (enum elf_ppc64_reloc_type r_type)
|
is_branch_reloc (enum elf_ppc64_reloc_type r_type)
|
||||||
{
|
{
|
||||||
return (r_type == R_PPC64_REL24
|
return (r_type == R_PPC64_REL24
|
||||||
|
|| r_type == R_PPC64_REL24_NOTOC
|
||||||
|| r_type == R_PPC64_REL14
|
|| r_type == R_PPC64_REL14
|
||||||
|| r_type == R_PPC64_REL14_BRTAKEN
|
|| r_type == R_PPC64_REL14_BRTAKEN
|
||||||
|| r_type == R_PPC64_REL14_BRNTAKEN
|
|| r_type == R_PPC64_REL14_BRNTAKEN
|
||||||
@ -5848,6 +5955,7 @@ ppc64_elf_check_relocs (bfd *abfd, struct bfd_link_info *info,
|
|||||||
/* Fall through. */
|
/* Fall through. */
|
||||||
|
|
||||||
case R_PPC64_REL24:
|
case R_PPC64_REL24:
|
||||||
|
case R_PPC64_REL24_NOTOC:
|
||||||
rel24:
|
rel24:
|
||||||
plt_list = ifunc;
|
plt_list = ifunc;
|
||||||
if (h != NULL)
|
if (h != NULL)
|
||||||
@ -10757,6 +10865,106 @@ ppc_type_of_stub (asection *input_sec,
|
|||||||
return ppc_stub_none;
|
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
|
/* 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
|
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
|
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,
|
struct ppc_stub_hash_entry *stub_entry,
|
||||||
bfd_vma off)
|
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
|
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;
|
||||||
@ -11422,6 +11639,78 @@ ppc_build_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
|||||||
p += 4;
|
p += 4;
|
||||||
break;
|
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:
|
||||||
case ppc_stub_plt_call_r2save:
|
case ppc_stub_plt_call_r2save:
|
||||||
if (stub_entry->h != NULL
|
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;
|
size_t len1, len2;
|
||||||
char *name;
|
char *name;
|
||||||
const char *const stub_str[] = { "long_branch",
|
const char *const stub_str[] = { "long_branch",
|
||||||
|
"long_branch",
|
||||||
|
"long_branch",
|
||||||
"long_branch",
|
"long_branch",
|
||||||
"plt_branch",
|
"plt_branch",
|
||||||
"plt_branch",
|
"plt_branch",
|
||||||
|
"plt_branch",
|
||||||
|
"plt_branch",
|
||||||
|
"plt_call",
|
||||||
|
"plt_call",
|
||||||
"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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stub_entry->stub_type == ppc_stub_plt_call
|
if (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)
|
||||||
{
|
{
|
||||||
asection *plt;
|
asection *plt;
|
||||||
targ = stub_entry->plt_ent->plt.offset & ~(bfd_vma) 1;
|
targ = stub_entry->plt_ent->plt.offset & ~(bfd_vma) 1;
|
||||||
@ -11602,38 +11897,52 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
|||||||
}
|
}
|
||||||
targ += plt->output_offset + plt->output_section->vma;
|
targ += plt->output_offset + plt->output_section->vma;
|
||||||
|
|
||||||
off = (elf_gp (info->output_bfd)
|
if (stub_entry->stub_type >= ppc_stub_plt_call_notoc)
|
||||||
+ htab->sec_info[stub_entry->group->link_sec->id].toc_off);
|
{
|
||||||
off = targ - off;
|
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);
|
||||||
|
|
||||||
if (htab->params->plt_stub_align != 0)
|
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->group->stub_sec->size += pad;
|
||||||
stub_entry->stub_offset = stub_entry->group->stub_sec->size;
|
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);
|
size = plt_stub_size (htab, stub_entry, off);
|
||||||
|
|
||||||
if (stub_entry->h != NULL
|
if (stub_entry->stub_type < ppc_stub_plt_call_notoc)
|
||||||
&& (stub_entry->h == htab->tls_get_addr_fd
|
|
||||||
|| stub_entry->h == htab->tls_get_addr)
|
|
||||||
&& htab->params->tls_get_addr_opt
|
|
||||||
&& (ALWAYS_EMIT_R2SAVE
|
|
||||||
|| stub_entry->stub_type == ppc_stub_plt_call_r2save))
|
|
||||||
stub_entry->group->tls_get_addr_opt_bctrl
|
|
||||||
= stub_entry->stub_offset + size - 5 * 4;
|
|
||||||
|
|
||||||
if (info->emitrelocations)
|
|
||||||
{
|
{
|
||||||
stub_entry->group->stub_sec->reloc_count
|
if (stub_entry->h != NULL
|
||||||
+= ((PPC_HA (off) != 0)
|
&& (stub_entry->h == htab->tls_get_addr_fd
|
||||||
+ (htab->opd_abi
|
|| stub_entry->h == htab->tls_get_addr)
|
||||||
? 2 + (htab->params->plt_static_chain
|
&& htab->params->tls_get_addr_opt
|
||||||
&& PPC_HA (off + 16) == PPC_HA (off))
|
&& (ALWAYS_EMIT_R2SAVE
|
||||||
: 1));
|
|| stub_entry->stub_type == ppc_stub_plt_call_r2save))
|
||||||
stub_entry->group->stub_sec->flags |= SEC_RELOC;
|
stub_entry->group->tls_get_addr_opt_bctrl
|
||||||
|
= stub_entry->stub_offset + size - 5 * 4;
|
||||||
|
|
||||||
|
if (info->emitrelocations)
|
||||||
|
{
|
||||||
|
stub_entry->group->stub_sec->reloc_count
|
||||||
|
+= ((PPC_HA (off) != 0)
|
||||||
|
+ (htab->opd_abi
|
||||||
|
? 2 + (htab->params->plt_static_chain
|
||||||
|
&& PPC_HA (off + 16) == PPC_HA (off))
|
||||||
|
: 1));
|
||||||
|
stub_entry->group->stub_sec->flags |= SEC_RELOC;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -11671,82 +11980,102 @@ ppc_size_one_stub (struct bfd_hash_entry *gen_entry, void *in_arg)
|
|||||||
size += 4;
|
size += 4;
|
||||||
off += 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;
|
off = targ - off;
|
||||||
|
|
||||||
local_off = PPC64_LOCAL_ENTRY_OFFSET (stub_entry->other);
|
if (stub_entry->stub_type >= ppc_stub_long_branch_notoc)
|
||||||
|
|
||||||
/* 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
|
|
||||||
&& r2off == 0
|
|
||||||
&& htab->sec_info[stub_entry->target_section->id].toc_off == 0))
|
|
||||||
{
|
{
|
||||||
struct ppc_branch_hash_entry *br_entry;
|
if (off + (1 << 25) >= (bfd_vma) (1 << 26))
|
||||||
|
|
||||||
br_entry = ppc_branch_hash_lookup (&htab->branch_hash_table,
|
|
||||||
stub_entry->root.string + 9,
|
|
||||||
TRUE, FALSE);
|
|
||||||
if (br_entry == NULL)
|
|
||||||
{
|
{
|
||||||
_bfd_error_handler (_("can't build branch stub `%s'"),
|
stub_entry->stub_type += (ppc_stub_plt_branch_notoc
|
||||||
stub_entry->root.string);
|
- ppc_stub_long_branch_notoc);
|
||||||
htab->stub_error = TRUE;
|
size += 4;
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (br_entry->iter != htab->stub_iteration)
|
|
||||||
{
|
|
||||||
br_entry->iter = htab->stub_iteration;
|
|
||||||
br_entry->offset = htab->brlt->size;
|
|
||||||
htab->brlt->size += 8;
|
|
||||||
|
|
||||||
if (htab->relbrlt != NULL)
|
|
||||||
htab->relbrlt->size += sizeof (Elf64_External_Rela);
|
|
||||||
else if (info->emitrelocations)
|
|
||||||
{
|
|
||||||
htab->brlt->reloc_count += 1;
|
|
||||||
htab->brlt->flags |= SEC_RELOC;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
off = (elf_gp (info->output_bfd)
|
|
||||||
+ htab->sec_info[stub_entry->group->link_sec->id].toc_off);
|
|
||||||
off = targ - off;
|
|
||||||
|
|
||||||
if (info->emitrelocations)
|
|
||||||
{
|
|
||||||
stub_entry->group->stub_sec->reloc_count
|
|
||||||
+= 1 + (PPC_HA (off) != 0);
|
|
||||||
stub_entry->group->stub_sec->flags |= SEC_RELOC;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stub_entry->stub_type != ppc_stub_plt_branch_r2off)
|
|
||||||
{
|
|
||||||
size = 12;
|
|
||||||
if (PPC_HA (off) != 0)
|
|
||||||
size = 16;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
size = 16;
|
|
||||||
if (PPC_HA (off) != 0)
|
|
||||||
size += 4;
|
|
||||||
|
|
||||||
if (PPC_HA (r2off) != 0)
|
|
||||||
size += 4;
|
|
||||||
if (PPC_LO (r2off) != 0)
|
|
||||||
size += 4;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (info->emitrelocations)
|
else
|
||||||
{
|
{
|
||||||
stub_entry->group->stub_sec->reloc_count += 1;
|
local_off = PPC64_LOCAL_ENTRY_OFFSET (stub_entry->other);
|
||||||
stub_entry->group->stub_sec->flags |= SEC_RELOC;
|
|
||||||
|
/* If the branch offset is too big, use a ppc_stub_plt_branch.
|
||||||
|
Do the same for -R objects without function descriptors. */
|
||||||
|
if ((stub_entry->stub_type == ppc_stub_long_branch_r2off
|
||||||
|
&& r2off == 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;
|
||||||
|
|
||||||
|
br_entry = ppc_branch_hash_lookup (&htab->branch_hash_table,
|
||||||
|
stub_entry->root.string + 9,
|
||||||
|
TRUE, FALSE);
|
||||||
|
if (br_entry == NULL)
|
||||||
|
{
|
||||||
|
_bfd_error_handler (_("can't build branch stub `%s'"),
|
||||||
|
stub_entry->root.string);
|
||||||
|
htab->stub_error = TRUE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (br_entry->iter != htab->stub_iteration)
|
||||||
|
{
|
||||||
|
br_entry->iter = htab->stub_iteration;
|
||||||
|
br_entry->offset = htab->brlt->size;
|
||||||
|
htab->brlt->size += 8;
|
||||||
|
|
||||||
|
if (htab->relbrlt != NULL)
|
||||||
|
htab->relbrlt->size += sizeof (Elf64_External_Rela);
|
||||||
|
else if (info->emitrelocations)
|
||||||
|
{
|
||||||
|
htab->brlt->reloc_count += 1;
|
||||||
|
htab->brlt->flags |= SEC_RELOC;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
targ = (br_entry->offset
|
||||||
|
+ htab->brlt->output_offset
|
||||||
|
+ htab->brlt->output_section->vma);
|
||||||
|
off = (elf_gp (info->output_bfd)
|
||||||
|
+ htab->sec_info[stub_entry->group->link_sec->id].toc_off);
|
||||||
|
off = targ - off;
|
||||||
|
|
||||||
|
if (info->emitrelocations)
|
||||||
|
{
|
||||||
|
stub_entry->group->stub_sec->reloc_count
|
||||||
|
+= 1 + (PPC_HA (off) != 0);
|
||||||
|
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;
|
||||||
|
if (PPC_HA (off) != 0)
|
||||||
|
size = 16;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
size = 16;
|
||||||
|
if (PPC_HA (off) != 0)
|
||||||
|
size += 4;
|
||||||
|
|
||||||
|
if (PPC_HA (r2off) != 0)
|
||||||
|
size += 4;
|
||||||
|
if (PPC_LO (r2off) != 0)
|
||||||
|
size += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (info->emitrelocations)
|
||||||
|
{
|
||||||
|
stub_entry->group->stub_sec->reloc_count += 1;
|
||||||
|
stub_entry->group->stub_sec->flags |= SEC_RELOC;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -12154,6 +12483,7 @@ toc_adjusting_stub_needed (struct bfd_link_info *info, asection *isec)
|
|||||||
|
|
||||||
r_type = ELF64_R_TYPE (rel->r_info);
|
r_type = ELF64_R_TYPE (rel->r_info);
|
||||||
if (r_type != R_PPC64_REL24
|
if (r_type != R_PPC64_REL24
|
||||||
|
&& r_type != R_PPC64_REL24_NOTOC
|
||||||
&& r_type != R_PPC64_REL14
|
&& r_type != R_PPC64_REL14
|
||||||
&& r_type != R_PPC64_REL14_BRTAKEN
|
&& r_type != R_PPC64_REL14_BRTAKEN
|
||||||
&& r_type != R_PPC64_REL14_BRNTAKEN
|
&& 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. */
|
/* Only look for stubs on branch instructions. */
|
||||||
if (r_type != R_PPC64_REL24
|
if (r_type != R_PPC64_REL24
|
||||||
|
&& r_type != R_PPC64_REL24_NOTOC
|
||||||
&& r_type != R_PPC64_REL14
|
&& r_type != R_PPC64_REL14
|
||||||
&& r_type != R_PPC64_REL14_BRTAKEN
|
&& r_type != R_PPC64_REL14_BRTAKEN
|
||||||
&& r_type != R_PPC64_REL14_BRNTAKEN)
|
&& r_type != R_PPC64_REL14_BRNTAKEN)
|
||||||
@ -12857,7 +13188,19 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
|
|||||||
&plt_ent, destination,
|
&plt_ent, destination,
|
||||||
local_off);
|
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.
|
/* Check whether we need a TOC adjusting stub.
|
||||||
Since the linker pastes together pieces from
|
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. */
|
/* __tls_get_addr calls might be eliminated. */
|
||||||
if (stub_type != ppc_stub_plt_call
|
if (stub_type != ppc_stub_plt_call
|
||||||
|
&& stub_type != ppc_stub_plt_call_notoc
|
||||||
&& hash != NULL
|
&& hash != NULL
|
||||||
&& (hash == htab->tls_get_addr
|
&& (hash == htab->tls_get_addr
|
||||||
|| hash == htab->tls_get_addr_fd)
|
|| hash == htab->tls_get_addr_fd)
|
||||||
@ -12929,9 +13273,71 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
|
|||||||
stub_name, FALSE, FALSE);
|
stub_name, FALSE, FALSE);
|
||||||
if (stub_entry != NULL)
|
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);
|
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;
|
stub_entry->stub_type = stub_type;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -12952,17 +13358,17 @@ ppc64_elf_size_stubs (struct bfd_link_info *info)
|
|||||||
}
|
}
|
||||||
|
|
||||||
stub_entry->stub_type = stub_type;
|
stub_entry->stub_type = stub_type;
|
||||||
if (stub_type != ppc_stub_plt_call
|
if (stub_type >= ppc_stub_plt_call
|
||||||
&& stub_type != ppc_stub_plt_call_r2save)
|
&& stub_type <= ppc_stub_plt_call_both)
|
||||||
{
|
|
||||||
stub_entry->target_value = code_value;
|
|
||||||
stub_entry->target_section = code_sec;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
stub_entry->target_value = sym_value;
|
stub_entry->target_value = sym_value;
|
||||||
stub_entry->target_section = sym_sec;
|
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->h = hash;
|
||||||
stub_entry->plt_ent = plt_ent;
|
stub_entry->plt_ent = plt_ent;
|
||||||
stub_entry->symtype
|
stub_entry->symtype
|
||||||
@ -13841,19 +14247,31 @@ ppc64_elf_build_stubs (struct bfd_link_info *info,
|
|||||||
"linker stubs in %u groups\n",
|
"linker stubs in %u groups\n",
|
||||||
stub_sec_count),
|
stub_sec_count),
|
||||||
stub_sec_count);
|
stub_sec_count);
|
||||||
sprintf (*stats + len, _(" branch %lu\n"
|
sprintf (*stats + len, _(" branch %lu\n"
|
||||||
" toc adjust %lu\n"
|
" branch toc adj %lu\n"
|
||||||
" long branch %lu\n"
|
" branch notoc %lu\n"
|
||||||
" long toc adj %lu\n"
|
" branch both %lu\n"
|
||||||
" plt call %lu\n"
|
" long branch %lu\n"
|
||||||
" plt call toc %lu\n"
|
" long toc adj %lu\n"
|
||||||
" global entry %lu"),
|
" long notoc %lu\n"
|
||||||
|
" long both %lu\n"
|
||||||
|
" plt call %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 - 1],
|
||||||
htab->stub_count[ppc_stub_long_branch_r2off - 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 - 1],
|
||||||
htab->stub_count[ppc_stub_plt_branch_r2off - 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 - 1],
|
||||||
htab->stub_count[ppc_stub_plt_call_r2save - 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]);
|
htab->stub_count[ppc_stub_global_entry - 1]);
|
||||||
}
|
}
|
||||||
return TRUE;
|
return TRUE;
|
||||||
@ -14685,6 +15103,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
/* Fall through. */
|
/* Fall through. */
|
||||||
|
|
||||||
case R_PPC64_REL24:
|
case R_PPC64_REL24:
|
||||||
|
case R_PPC64_REL24_NOTOC:
|
||||||
case R_PPC64_PLTCALL:
|
case R_PPC64_PLTCALL:
|
||||||
/* Calls to functions with a different TOC, such as calls to
|
/* Calls to functions with a different TOC, such as calls to
|
||||||
shared objects, need to alter the TOC pointer. This is
|
shared objects, need to alter the TOC pointer. This is
|
||||||
@ -14701,15 +15120,18 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
htab);
|
htab);
|
||||||
if (r_type == R_PPC64_PLTCALL
|
if (r_type == R_PPC64_PLTCALL
|
||||||
&& stub_entry != NULL
|
&& stub_entry != NULL
|
||||||
&& (stub_entry->stub_type == ppc_stub_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_both)
|
||||||
stub_entry = NULL;
|
stub_entry = NULL;
|
||||||
|
|
||||||
if (stub_entry != NULL
|
if (stub_entry != NULL
|
||||||
&& (stub_entry->stub_type == ppc_stub_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_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_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;
|
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. */
|
/* The function doesn't use or change r2. */
|
||||||
can_plt_call = TRUE;
|
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
|
/* All of these stubs may modify r2, so there must be a
|
||||||
branch and link followed by a nop. The nop is
|
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 (!can_plt_call)
|
||||||
{
|
{
|
||||||
if (stub_entry->stub_type == ppc_stub_plt_call
|
if (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)
|
||||||
info->callbacks->einfo
|
info->callbacks->einfo
|
||||||
/* xgettext:c-format */
|
/* xgettext:c-format */
|
||||||
(_("%H: call to `%pT' lacks nop, can't restore toc; "
|
(_("%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
|
if (can_plt_call
|
||||||
&& (stub_entry->stub_type == ppc_stub_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_both)
|
||||||
unresolved_reloc = FALSE;
|
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. */
|
/* Don't use the stub if this branch is in range. */
|
||||||
stub_entry = NULL;
|
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)
|
if (stub_entry != NULL)
|
||||||
{
|
{
|
||||||
/* Munge up the value and addend so that we call the stub
|
/* 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;
|
addend = 0;
|
||||||
reloc_dest = DEST_STUB;
|
reloc_dest = DEST_STUB;
|
||||||
|
|
||||||
if ((stub_entry->stub_type == ppc_stub_plt_call
|
if (((stub_entry->stub_type == ppc_stub_plt_call
|
||||||
|| stub_entry->stub_type == ppc_stub_plt_call_r2save)
|
&& ALWAYS_EMIT_R2SAVE)
|
||||||
&& (ALWAYS_EMIT_R2SAVE
|
|| stub_entry->stub_type == ppc_stub_plt_call_r2save
|
||||||
|| stub_entry->stub_type == ppc_stub_plt_call_r2save)
|
|| stub_entry->stub_type == ppc_stub_plt_call_both)
|
||||||
&& rel + 1 < relend
|
&& rel + 1 < relend
|
||||||
&& rel[1].r_offset == rel->r_offset + 4
|
&& rel[1].r_offset == rel->r_offset + 4
|
||||||
&& ELF64_R_TYPE (rel[1].r_info) == R_PPC64_TOCSAVE)
|
&& ELF64_R_TYPE (rel[1].r_info) == R_PPC64_TOCSAVE)
|
||||||
relocation += 4;
|
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)
|
if (insn != 0)
|
||||||
@ -14923,7 +15377,8 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
else if (h != NULL
|
else if (h != NULL
|
||||||
&& h->elf.root.type == bfd_link_hash_undefweak
|
&& h->elf.root.type == bfd_link_hash_undefweak
|
||||||
&& h->elf.dynindx == -1
|
&& h->elf.dynindx == -1
|
||||||
&& r_type == R_PPC64_REL24
|
&& (r_type == R_PPC64_REL24
|
||||||
|
|| r_type == R_PPC64_REL24_NOTOC)
|
||||||
&& relocation == 0
|
&& relocation == 0
|
||||||
&& addend == 0)
|
&& addend == 0)
|
||||||
{
|
{
|
||||||
@ -15300,6 +15755,7 @@ ppc64_elf_relocate_section (bfd *output_bfd,
|
|||||||
case R_PPC64_REL14_BRNTAKEN:
|
case R_PPC64_REL14_BRNTAKEN:
|
||||||
case R_PPC64_REL14_BRTAKEN:
|
case R_PPC64_REL14_BRTAKEN:
|
||||||
case R_PPC64_REL24:
|
case R_PPC64_REL24:
|
||||||
|
case R_PPC64_REL24_NOTOC:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case R_PPC64_TPREL16:
|
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_ADDR16_HIGHA",
|
||||||
"BFD_RELOC_PPC64_ADDR64_LOCAL",
|
"BFD_RELOC_PPC64_ADDR64_LOCAL",
|
||||||
"BFD_RELOC_PPC64_ENTRY",
|
"BFD_RELOC_PPC64_ENTRY",
|
||||||
|
"BFD_RELOC_PPC64_REL24_NOTOC",
|
||||||
"BFD_RELOC_PPC_TLS",
|
"BFD_RELOC_PPC_TLS",
|
||||||
"BFD_RELOC_PPC_TLSGD",
|
"BFD_RELOC_PPC_TLSGD",
|
||||||
"BFD_RELOC_PPC_TLSLD",
|
"BFD_RELOC_PPC_TLSLD",
|
||||||
|
@ -3011,6 +3011,8 @@ ENUMX
|
|||||||
BFD_RELOC_PPC64_ADDR64_LOCAL
|
BFD_RELOC_PPC64_ADDR64_LOCAL
|
||||||
ENUMX
|
ENUMX
|
||||||
BFD_RELOC_PPC64_ENTRY
|
BFD_RELOC_PPC64_ENTRY
|
||||||
|
ENUMX
|
||||||
|
BFD_RELOC_PPC64_REL24_NOTOC
|
||||||
ENUMDOC
|
ENUMDOC
|
||||||
Power(rs6000) and PowerPC relocations.
|
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>
|
2018-08-03 Dimitar Dimitrov <dimitar@dinux.eu>
|
||||||
|
|
||||||
* config/tc-pru.c (pru_regname_to_dw2regnum): Return the starting HW
|
* 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@highera", BFD_RELOC_PPC64_TPREL16_HIGHERA),
|
||||||
MAP64 ("tprel@highest", BFD_RELOC_PPC64_TPREL16_HIGHEST),
|
MAP64 ("tprel@highest", BFD_RELOC_PPC64_TPREL16_HIGHEST),
|
||||||
MAP64 ("tprel@highesta", BFD_RELOC_PPC64_TPREL16_HIGHESTA),
|
MAP64 ("tprel@highesta", BFD_RELOC_PPC64_TPREL16_HIGHESTA),
|
||||||
|
MAP64 ("notoc", BFD_RELOC_PPC64_REL24_NOTOC),
|
||||||
{ (char *) 0, 0, 0, 0, BFD_RELOC_NONE }
|
{ (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_BA26:
|
||||||
case BFD_RELOC_PPC_B16:
|
case BFD_RELOC_PPC_B16:
|
||||||
case BFD_RELOC_PPC_BA16:
|
case BFD_RELOC_PPC_BA16:
|
||||||
|
case BFD_RELOC_PPC64_REL24_NOTOC:
|
||||||
/* All branch fixups targeting a localentry symbol must
|
/* All branch fixups targeting a localentry symbol must
|
||||||
force a relocation. */
|
force a relocation. */
|
||||||
if (fix->fx_addsy)
|
if (fix->fx_addsy)
|
||||||
@ -6454,6 +6456,7 @@ ppc_fix_adjustable (fixS *fix)
|
|||||||
case BFD_RELOC_PPC_B16_BRNTAKEN:
|
case BFD_RELOC_PPC_B16_BRNTAKEN:
|
||||||
case BFD_RELOC_PPC_BA16_BRTAKEN:
|
case BFD_RELOC_PPC_BA16_BRTAKEN:
|
||||||
case BFD_RELOC_PPC_BA16_BRNTAKEN:
|
case BFD_RELOC_PPC_BA16_BRNTAKEN:
|
||||||
|
case BFD_RELOC_PPC64_REL24_NOTOC:
|
||||||
if (fix->fx_addsy)
|
if (fix->fx_addsy)
|
||||||
{
|
{
|
||||||
asymbol *bfdsym = symbol_get_bfdsym (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>
|
2018-08-05 Alan Modra <amodra@gmail.com>
|
||||||
|
|
||||||
* testsuite/ld-powerpc/elfv2exe.d: Adjust for stub symbol change.
|
* 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 "dotsym2"
|
||||||
run_dump_test "dotsym3"
|
run_dump_test "dotsym3"
|
||||||
run_dump_test "dotsym4"
|
run_dump_test "dotsym4"
|
||||||
|
run_dump_test "ext"
|
||||||
|
run_dump_test "notoc"
|
||||||
}
|
}
|
||||||
|
|
||||||
run_dump_test "tlsld32"
|
run_dump_test "tlsld32"
|
||||||
|
Loading…
Reference in New Issue
Block a user