Index: lld/ELF/InputSection.cpp =================================================================== --- lld/ELF/InputSection.cpp +++ lld/ELF/InputSection.cpp @@ -740,8 +740,12 @@ break; case R_PPC_PLT_OPD: // Patch a nop (0x60000000) to a ld. - if (BufLoc + 8 <= BufEnd && read32be(BufLoc + 4) == 0x60000000) - write32be(BufLoc + 4, 0xe8410028); // ld %r2, 40(%r1) + if (BufLoc + 8 <= BufEnd && read32(BufLoc + 4) == 0x60000000) { + write32(BufLoc + 4, 0xe8410018); // ld %r2, 24(%r1) + } else { + error(getErrorLocation(BufLoc) + "error: call lacks nop, can't restore toc."); + return; + } LLVM_FALLTHROUGH; default: Target->relocateOne(BufLoc, Type, TargetVA); Index: lld/test/ELF/Inputs/ppc64-func.s =================================================================== --- /dev/null +++ lld/test/ELF/Inputs/ppc64-func.s @@ -0,0 +1,14 @@ + .text + .abiversion 2 + .globl foo_not_shared + .p2align 4 + .type foo_not_shared,@function + +foo_not_shared: +.Lfunc_begin0: + li 3, 55 + blr + .long 0 + .quad 0 +.Lfunc_end0: + .size foo_not_shared, .Lfunc_end0-.Lfunc_begin0 Index: lld/test/ELF/ppc64-error-toc-restore.s =================================================================== --- /dev/null +++ lld/test/ELF/ppc64-error-toc-restore.s @@ -0,0 +1,14 @@ +// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o +// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/shared-ppc64le.s -o %t2.o +// RUN: ld.lld -shared %t2.o -o %t2.so +// RUN: not ld.lld %t.o %t2.so -o %t 2>&1 | FileCheck %s +// REQUIRES: ppc + +# Calling external function bar needs a nop +// CHECK: error: call lacks nop, can't restore toc + .text + .abiversion 2 + +.global _start +_start: + bl foo Index: lld/test/ELF/ppc64-ifunc.s =================================================================== --- lld/test/ELF/ppc64-ifunc.s +++ lld/test/ELF/ppc64-ifunc.s @@ -1,34 +1,35 @@ # REQUIRES: ppc -# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o -# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/shared-ppc64.s -o %t2.o +# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o +# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/shared-ppc64le.s -o %t2.o # RUN: ld.lld -shared %t2.o -o %t2.so # RUN: ld.lld %t.o %t2.so -o %t # RUN: llvm-objdump -d %t | FileCheck %s # CHECK: _start: -# CHECK-NEXT: 10010004: {{.*}} bl .+12 -# CHECK-NEXT: 10010008: {{.*}} bl .+40 +# CHECK-NEXT: 10010004: 1d 00 00 48 bl .+28 +# CHECK-NEXT: 10010008: 18 00 41 e8 ld 2, 24(1) +# CHECK-NEXT: 1001000c: 35 00 00 48 bl .+52 +# CHECK-NEXT: 10010010: 18 00 41 e8 ld 2, 24(1) -# 0x10010004 + 12 = 0x10010010 (PLT entry 0) -# 0x10010008 + 40 = 0x10010030 (PLT entry 1) +# 0x10010004 + 28 = 0x10010020 (PLT entry 0) +# 0x1001000c + 52 = 0x10010040 (PLT entry 1) # CHECK: Disassembly of section .plt: -# CHECK: 10010010: {{.*}} std 2, 40(1) -# CHECK-NEXT: 10010014: {{.*}} addis 11, 2, 4098 -# CHECK-NEXT: 10010018: {{.*}} ld 12, -32744(11) -# CHECK-NEXT: 1001001c: {{.*}} ld 11, 0(12) -# CHECK-NEXT: 10010020: {{.*}} mtctr 11 -# CHECK-NEXT: 10010024: {{.*}} ld 2, 8(12) -# CHECK-NEXT: 10010028: {{.*}} ld 11, 16(12) -# CHECK-NEXT: 1001002c: {{.*}} bctr -# CHECK-NEXT: 10010030: {{.*}} std 2, 40(1) -# CHECK-NEXT: 10010034: {{.*}} addis 11, 2, 4098 -# CHECK-NEXT: 10010038: {{.*}} ld 12, -32736(11) -# CHECK-NEXT: 1001003c: {{.*}} ld 11, 0(12) -# CHECK-NEXT: 10010040: {{.*}} mtctr 11 -# CHECK-NEXT: 10010044: {{.*}} ld 2, 8(12) -# CHECK-NEXT: 10010048: {{.*}} ld 11, 16(12) -# CHECK-NEXT: 1001004c: {{.*}} bctr +# CHECK-NEXT: .plt: +# CHECK-NEXT: 10010020: 18 00 41 f8 std 2, 24(1) +# CHECK-NEXT: 10010024: 02 10 82 3d addis 12, 2, 4098 +# CHECK-NEXT: 10010028: 10 80 8c e9 ld 12, -32752(12) +# CHECK-NEXT: 1001002c: a6 03 89 7d mtctr 12 +# CHECK-NEXT: 10010030: 20 04 80 4e bctr +# CHECK-NEXT: 10010034: 08 00 e0 7f trap +# CHECK-NEXT: 10010038: 08 00 e0 7f trap +# CHECK-NEXT: 1001003c: 08 00 e0 7f trap +# CHECK-NEXT: 10010040: 18 00 41 f8 std 2, 24(1) +# CHECK-NEXT: 10010044: 02 10 82 3d addis 12, 2, 4098 +# CHECK-NEXT: 10010048: 18 80 8c e9 ld 12, -32744(12) +# CHECK-NEXT: 1001004c: a6 03 89 7d mtctr 12 + .text + .abiversion 2 .type ifunc STT_GNU_IFUNC .globl ifunc @@ -37,5 +38,7 @@ .global _start _start: - bl bar + bl foo + nop bl ifunc + nop Index: lld/test/ELF/ppc64-toc-restore.s =================================================================== --- lld/test/ELF/ppc64-toc-restore.s +++ lld/test/ELF/ppc64-toc-restore.s @@ -1,62 +1,69 @@ -// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o -// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/shared-ppc64.s -o %t2.o +// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o +// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/shared-ppc64le.s -o %t2.o +// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/ppc64-func.s -o %t3.o // RUN: ld.lld -shared %t2.o -o %t2.so -// RUN: ld.lld %t.o %t2.so -o %t +// RUN: ld.lld %t.o %t2.so %t3.o -o %t // RUN: llvm-objdump -d %t | FileCheck %s // REQUIRES: ppc + .text + .abiversion 2 +.global bar_local +bar_local: + li 3, 2 + blr +# Calling external function foo in a shared object needs a nop. +# Calling local function bar_local doe snot need a nop. // CHECK: Disassembly of section .text: - .global _start _start: - bl bar + bl foo nop + bl bar_local // CHECK: _start: -// CHECK: 10010000: 48 00 00 21 bl .+32 -// CHECK-NOT: 10010004: 60 00 00 00 nop -// CHECK: 10010004: e8 41 00 28 ld 2, 40(1) - -.global noret -noret: - bl bar - li 5, 7 - -// CHECK: noret: -// CHECK: 10010008: 48 00 00 19 bl .+24 -// CHECK: 1001000c: 38 a0 00 07 li 5, 7 +// CHECK: 10010008: 49 00 00 48 bl .+72 +// CHECK-NOT: 1001000c: 00 00 00 60 nop +// CHECK: 1001000c: 18 00 41 e8 ld 2, 24(1) +// CHECK: 10010010: f1 ff ff 4b bl .+67108848 +// CHECK-NOT: 10010014: 00 00 00 60 nop +// CHECK-NOT: 10010014: 18 00 41 e8 ld 2, 24(1) -.global noretend -noretend: - bl bar - -// CHECK: noretend: -// CHECK: 10010010: 48 00 00 11 bl .+16 +# Calling a function in another object file which will have same +# TOC base does not need a nop. If nop present, do not rewrite to +# a toc restore +.global diff_object +_diff_object: + bl foo_not_shared + bl foo_not_shared + nop -.global noretb -noretb: - b bar +// CHECK: _diff_object: +// CHECK-NEXT: 10010014: 1d 00 00 48 bl .+28 +// CHECK-NEXT: 10010018: 19 00 00 48 bl .+24 +// CHECK-NEXT: 1001001c: 00 00 00 60 nop -// CHECK: noretb: -// CHECK: 10010014: 48 00 00 0c b .+12 +# Branching to a local function does not need a nop +.global noretbranch +noretbranch: + b bar_local +// CHECK: noretbranch: +// CHECK: 10010020: e0 ff ff 4b b .+67108832 +// CHECK-NOT: 10010024: 00 00 00 60 nop +// CHECK-NOT: 10010024: 18 00 41 e8 ld 2, 24(1) // This should come last to check the end-of-buffer condition. .global last last: - bl bar + bl foo nop - // CHECK: last: -// CHECK: 10010018: 48 00 00 09 bl .+8 -// CHECK: 1001001c: e8 41 00 28 ld 2, 40(1) +// CHECK: 10010024: 2d 00 00 48 bl .+44 +// CHECK-NEXT: 10010028: 18 00 41 e8 ld 2, 24(1) // CHECK: Disassembly of section .plt: // CHECK: .plt: -// CHECK: 10010020: f8 41 00 28 std 2, 40(1) -// CHECK: 10010024: 3d 62 10 02 addis 11, 2, 4098 -// CHECK: 10010028: e9 8b 80 18 ld 12, -32744(11) -// CHECK: 1001002c: e9 6c 00 00 ld 11, 0(12) -// CHECK: 10010030: 7d 69 03 a6 mtctr 11 -// CHECK: 10010034: e8 4c 00 08 ld 2, 8(12) -// CHECK: 10010038: e9 6c 00 10 ld 11, 16(12) -// CHECK: 1001003c: 4e 80 04 20 bctr +// CHECK-NEXT: 10010050: 18 00 41 f8 std 2, 24(1) +// CHECK-NEXT: 10010054: 02 10 82 3d addis 12, 2, 4098 +// CHECK-NEXT: 10010058: 10 80 8c e9 ld 12, -32752(12) +// CHECK-NEXT: 1001005c: a6 03 89 7d mtctr 12 Index: lld/test/ELF/ppc64-weak-undef-call-shared.s =================================================================== --- lld/test/ELF/ppc64-weak-undef-call-shared.s +++ lld/test/ELF/ppc64-weak-undef-call-shared.s @@ -10,7 +10,7 @@ .text .Lfoo: bl weakfunc + nop // CHECK-NOT: R_PPC64_REL24 .weak weakfunc -