[PPC64] Fix toc restore nops offset for V2 ABI

The PPC64 V2 ABI restores the toc base by loading from an offset of 24 from r1.
This patch fixes the offset and updates the testcases from V1 to V2. It also
issues an error when a nop is missing after a call to an external function.

Differential Revision: https://reviews.llvm.org/D45892

llvm-svn: 330600
This commit is contained in:
Zaara Syeda 2018-04-23 15:01:24 +00:00
parent 08824567af
commit 25b488b0ea
7 changed files with 122 additions and 66 deletions

View File

@ -740,8 +740,12 @@ void InputSectionBase::relocateAlloc(uint8_t *Buf, uint8_t *BufEnd) {
break; break;
case R_PPC_PLT_OPD: case R_PPC_PLT_OPD:
// Patch a nop (0x60000000) to a ld. // Patch a nop (0x60000000) to a ld.
if (BufLoc + 8 <= BufEnd && read32be(BufLoc + 4) == 0x60000000) if (BufLoc + 8 <= BufEnd && read32(BufLoc + 4) == 0x60000000) {
write32be(BufLoc + 4, 0xe8410028); // ld %r2, 40(%r1) write32(BufLoc + 4, 0xe8410018); // ld %r2, 24(%r1)
} else {
error(getErrorLocation(BufLoc) + "error: call lacks nop, can't restore toc.");
return;
}
LLVM_FALLTHROUGH; LLVM_FALLTHROUGH;
default: default:
Target->relocateOne(BufLoc, Type, TargetVA); Target->relocateOne(BufLoc, Type, TargetVA);

View File

@ -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

View File

@ -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

View File

@ -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
# A tail call to an external function without a nop should issue an error.
// CHECK: error: call lacks nop, can't restore toc
.text
.abiversion 2
.global _start
_start:
b foo

View File

@ -1,34 +1,35 @@
# REQUIRES: ppc # REQUIRES: ppc
# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o # RUN: llvm-mc -filetype=obj -triple=powerpc64le-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 %p/Inputs/shared-ppc64le.s -o %t2.o
# RUN: ld.lld -shared %t2.o -o %t2.so # 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 -o %t
# RUN: llvm-objdump -d %t | FileCheck %s # RUN: llvm-objdump -d %t | FileCheck %s
# CHECK: _start: # CHECK: _start:
# CHECK-NEXT: 10010004: {{.*}} bl .+12 # CHECK-NEXT: 10010004: 1d 00 00 48 bl .+28
# CHECK-NEXT: 10010008: {{.*}} bl .+40 # 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) # 0x10010004 + 28 = 0x10010020 (PLT entry 0)
# 0x10010008 + 40 = 0x10010030 (PLT entry 1) # 0x1001000c + 52 = 0x10010040 (PLT entry 1)
# CHECK: Disassembly of section .plt: # CHECK: Disassembly of section .plt:
# CHECK: 10010010: {{.*}} std 2, 40(1) # CHECK-NEXT: .plt:
# CHECK-NEXT: 10010014: {{.*}} addis 11, 2, 4098 # CHECK-NEXT: 10010020: 18 00 41 f8 std 2, 24(1)
# CHECK-NEXT: 10010018: {{.*}} ld 12, -32744(11) # CHECK-NEXT: 10010024: 02 10 82 3d addis 12, 2, 4098
# CHECK-NEXT: 1001001c: {{.*}} ld 11, 0(12) # CHECK-NEXT: 10010028: 10 80 8c e9 ld 12, -32752(12)
# CHECK-NEXT: 10010020: {{.*}} mtctr 11 # CHECK-NEXT: 1001002c: a6 03 89 7d mtctr 12
# CHECK-NEXT: 10010024: {{.*}} ld 2, 8(12) # CHECK-NEXT: 10010030: 20 04 80 4e bctr
# CHECK-NEXT: 10010028: {{.*}} ld 11, 16(12) # CHECK-NEXT: 10010034: 08 00 e0 7f trap
# CHECK-NEXT: 1001002c: {{.*}} bctr # CHECK-NEXT: 10010038: 08 00 e0 7f trap
# CHECK-NEXT: 10010030: {{.*}} std 2, 40(1) # CHECK-NEXT: 1001003c: 08 00 e0 7f trap
# CHECK-NEXT: 10010034: {{.*}} addis 11, 2, 4098 # CHECK-NEXT: 10010040: 18 00 41 f8 std 2, 24(1)
# CHECK-NEXT: 10010038: {{.*}} ld 12, -32736(11) # CHECK-NEXT: 10010044: 02 10 82 3d addis 12, 2, 4098
# CHECK-NEXT: 1001003c: {{.*}} ld 11, 0(12) # CHECK-NEXT: 10010048: 18 80 8c e9 ld 12, -32744(12)
# CHECK-NEXT: 10010040: {{.*}} mtctr 11 # CHECK-NEXT: 1001004c: a6 03 89 7d mtctr 12
# CHECK-NEXT: 10010044: {{.*}} ld 2, 8(12) .text
# CHECK-NEXT: 10010048: {{.*}} ld 11, 16(12) .abiversion 2
# CHECK-NEXT: 1001004c: {{.*}} bctr
.type ifunc STT_GNU_IFUNC .type ifunc STT_GNU_IFUNC
.globl ifunc .globl ifunc
@ -37,5 +38,7 @@ ifunc:
.global _start .global _start
_start: _start:
bl bar bl foo
nop
bl ifunc bl ifunc
nop

View File

@ -1,62 +1,69 @@
// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o // RUN: llvm-mc -filetype=obj -triple=powerpc64le-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 %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 -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 // RUN: llvm-objdump -d %t | FileCheck %s
// REQUIRES: ppc // 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: // CHECK: Disassembly of section .text:
.global _start .global _start
_start: _start:
bl bar bl foo
nop nop
bl bar_local
// CHECK: _start: // CHECK: _start:
// CHECK: 10010000: 48 00 00 21 bl .+32 // CHECK: 10010008: 49 00 00 48 bl .+72
// CHECK-NOT: 10010004: 60 00 00 00 nop // CHECK-NOT: 1001000c: 00 00 00 60 nop
// CHECK: 10010004: e8 41 00 28 ld 2, 40(1) // 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 noret # Calling a function in another object file which will have same
noret: # TOC base does not need a nop. If nop present, do not rewrite to
bl bar # a toc restore
li 5, 7 .global diff_object
_diff_object:
bl foo_not_shared
bl foo_not_shared
nop
// CHECK: noret: // CHECK: _diff_object:
// CHECK: 10010008: 48 00 00 19 bl .+24 // CHECK-NEXT: 10010014: 1d 00 00 48 bl .+28
// CHECK: 1001000c: 38 a0 00 07 li 5, 7 // CHECK-NEXT: 10010018: 19 00 00 48 bl .+24
// CHECK-NEXT: 1001001c: 00 00 00 60 nop
.global noretend # Branching to a local function does not need a nop
noretend: .global noretbranch
bl bar noretbranch:
b bar_local
// CHECK: noretend: // CHECK: noretbranch:
// CHECK: 10010010: 48 00 00 11 bl .+16 // CHECK: 10010020: e0 ff ff 4b b .+67108832
// CHECK-NOT: 10010024: 00 00 00 60 nop
.global noretb // CHECK-NOT: 10010024: 18 00 41 e8 ld 2, 24(1)
noretb:
b bar
// CHECK: noretb:
// CHECK: 10010014: 48 00 00 0c b .+12
// This should come last to check the end-of-buffer condition. // This should come last to check the end-of-buffer condition.
.global last .global last
last: last:
bl bar bl foo
nop nop
// CHECK: last: // CHECK: last:
// CHECK: 10010018: 48 00 00 09 bl .+8 // CHECK: 10010024: 2d 00 00 48 bl .+44
// CHECK: 1001001c: e8 41 00 28 ld 2, 40(1) // CHECK-NEXT: 10010028: 18 00 41 e8 ld 2, 24(1)
// CHECK: Disassembly of section .plt: // CHECK: Disassembly of section .plt:
// CHECK: .plt: // CHECK: .plt:
// CHECK: 10010020: f8 41 00 28 std 2, 40(1) // CHECK-NEXT: 10010050: 18 00 41 f8 std 2, 24(1)
// CHECK: 10010024: 3d 62 10 02 addis 11, 2, 4098 // CHECK-NEXT: 10010054: 02 10 82 3d addis 12, 2, 4098
// CHECK: 10010028: e9 8b 80 18 ld 12, -32744(11) // CHECK-NEXT: 10010058: 10 80 8c e9 ld 12, -32752(12)
// CHECK: 1001002c: e9 6c 00 00 ld 11, 0(12) // CHECK-NEXT: 1001005c: a6 03 89 7d mtctr 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

View File

@ -10,7 +10,7 @@
.text .text
.Lfoo: .Lfoo:
bl weakfunc bl weakfunc
nop
// CHECK-NOT: R_PPC64_REL24 // CHECK-NOT: R_PPC64_REL24
.weak weakfunc .weak weakfunc