From 05d0e962f08af24f18cc79b890a68176b42bcb78 Mon Sep 17 00:00:00 2001 From: Alan Modra Date: Fri, 3 Aug 2018 16:41:22 +0930 Subject: 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. --- ld/ChangeLog | 9 ++++ ld/testsuite/ld-powerpc/ext.d | 17 ++++++ ld/testsuite/ld-powerpc/ext.lnk | 6 +++ ld/testsuite/ld-powerpc/ext.s | 9 ++++ ld/testsuite/ld-powerpc/notoc.d | 102 ++++++++++++++++++++++++++++++++++++ ld/testsuite/ld-powerpc/notoc.s | 56 ++++++++++++++++++++ ld/testsuite/ld-powerpc/powerpc.exp | 2 + 7 files changed, 201 insertions(+) create mode 100644 ld/testsuite/ld-powerpc/ext.d create mode 100644 ld/testsuite/ld-powerpc/ext.lnk create mode 100644 ld/testsuite/ld-powerpc/ext.s create mode 100644 ld/testsuite/ld-powerpc/notoc.d create mode 100644 ld/testsuite/ld-powerpc/notoc.s (limited to 'ld') diff --git a/ld/ChangeLog b/ld/ChangeLog index b32879d..62ba530 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,5 +1,14 @@ 2018-08-05 Alan Modra + * 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 + * testsuite/ld-powerpc/elfv2exe.d: Adjust for stub symbol change. * testsuite/ld-powerpc/tocopt6.d: Likewise. diff --git a/ld/testsuite/ld-powerpc/ext.d b/ld/testsuite/ld-powerpc/ext.d new file mode 100644 index 0000000..61527f9 --- /dev/null +++ b/ld/testsuite/ld-powerpc/ext.d @@ -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+ : + 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 diff --git a/ld/testsuite/ld-powerpc/ext.lnk b/ld/testsuite/ld-powerpc/ext.lnk new file mode 100644 index 0000000..62c4a23 --- /dev/null +++ b/ld/testsuite/ld-powerpc/ext.lnk @@ -0,0 +1,6 @@ +SECTIONS +{ + . = 0x8000000000000000; + .text.ext : { tmpdir/ext.o(.text) } +} +INSERT BEFORE .stab; diff --git a/ld/testsuite/ld-powerpc/ext.s b/ld/testsuite/ld-powerpc/ext.s new file mode 100644 index 0000000..dd51d8f --- /dev/null +++ b/ld/testsuite/ld-powerpc/ext.s @@ -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 diff --git a/ld/testsuite/ld-powerpc/notoc.d b/ld/testsuite/ld-powerpc/notoc.d new file mode 100644 index 0000000..97e7274 --- /dev/null +++ b/ld/testsuite/ld-powerpc/notoc.d @@ -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 .* + +.* <.*\.long_branch\.g1>: +.*: (18 00 41 f8|f8 41 00 18) std r2,24\(r1\) +.*: (8c 00 00 48|48 00 00 8c) b .* + +.* <.*\.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 .* + +.* <.*\.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 .* + \.\.\. + +.* : +.*: (01 00 00 48|48 00 00 01) bl .* +.*: (bd ff ff 4b|4b ff ff bd) bl .* <.*\.long_branch\.f2> +.*: (11 00 00 48|48 00 00 11) bl .* +.*: (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 + +.* : +.*: (a9 ff ff 4b|4b ff ff a9) bl .* <.*\.long_branch\.f2> +.*: (e5 ff ff 4b|4b ff ff e5) bl .* +.*: (b9 ff ff 4b|4b ff ff b9) bl .* <.*\.long_branch\.g2> +.*: (f5 ff ff 4b|4b ff ff f5) bl .* +.*: (20 00 80 4e|4e 80 00 20) blr + +.* : +.*: (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 .* +.*: (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 .* +.*: (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 + +.* : +.*: (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 .* +.*: (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 .* +.*: (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 : +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 diff --git a/ld/testsuite/ld-powerpc/notoc.s b/ld/testsuite/ld-powerpc/notoc.s new file mode 100644 index 0000000..8c620df --- /dev/null +++ b/ld/testsuite/ld-powerpc/notoc.s @@ -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 diff --git a/ld/testsuite/ld-powerpc/powerpc.exp b/ld/testsuite/ld-powerpc/powerpc.exp index ac563eb..c4ab3de 100644 --- a/ld/testsuite/ld-powerpc/powerpc.exp +++ b/ld/testsuite/ld-powerpc/powerpc.exp @@ -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" -- cgit v1.1