mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-23 22:00:10 +00:00
[PowerPC][LLD] Make sure that the correct Thunks are used.
This fixes an issue where mixed TOC / NOTOC calls can call the incorrect thunks if a previous thunk already exists. The issue appears when a TOC funciton calls a NOTOC callee and then a different NOTOC function calls the same NOTOC callee. In this case the linker would sometimes incorrectly call the same thunk for both cases. Reviewed By: MaskRay Differential Revision: https://reviews.llvm.org/D101837
This commit is contained in:
parent
6660319cef
commit
f0adf3a24c
@ -312,6 +312,8 @@ public:
|
||||
uint32_t size() override { return getMayUseShortThunk() ? 8 : 32; }
|
||||
void writeTo(uint8_t *buf) override;
|
||||
void addSymbols(ThunkSection &isec) override;
|
||||
bool isCompatibleWith(const InputSection &isec,
|
||||
const Relocation &rel) const override;
|
||||
|
||||
private:
|
||||
// Transitioning from long to short can create layout oscillations in
|
||||
@ -333,6 +335,8 @@ public:
|
||||
uint32_t size() override { return 32; }
|
||||
void writeTo(uint8_t *buf) override;
|
||||
void addSymbols(ThunkSection &isec) override;
|
||||
bool isCompatibleWith(const InputSection &isec,
|
||||
const Relocation &rel) const override;
|
||||
};
|
||||
|
||||
// PPC64 PC-relative PLT Stub
|
||||
@ -965,6 +969,11 @@ void PPC64R2SaveStub::addSymbols(ThunkSection &isec) {
|
||||
s->needsTocRestore = true;
|
||||
}
|
||||
|
||||
bool PPC64R2SaveStub::isCompatibleWith(const InputSection &isec,
|
||||
const Relocation &rel) const {
|
||||
return rel.type == R_PPC64_REL24 || rel.type == R_PPC64_REL14;
|
||||
}
|
||||
|
||||
void PPC64R12SetupStub::writeTo(uint8_t *buf) {
|
||||
int64_t offset = destination.getVA() - getThunkTargetSym()->getVA();
|
||||
if (!isInt<34>(offset))
|
||||
@ -995,6 +1004,11 @@ void PPC64R12SetupStub::addSymbols(ThunkSection &isec) {
|
||||
isec);
|
||||
}
|
||||
|
||||
bool PPC64R12SetupStub::isCompatibleWith(const InputSection &isec,
|
||||
const Relocation &rel) const {
|
||||
return rel.type == R_PPC64_REL24_NOTOC;
|
||||
}
|
||||
|
||||
void PPC64PCRelPLTStub::writeTo(uint8_t *buf) {
|
||||
int nextInstOffset = 0;
|
||||
int64_t offset = destination.getGotPltVA() - getThunkTargetSym()->getVA();
|
||||
|
140
lld/test/ELF/ppc64-pcrel-cross-link.s
Normal file
140
lld/test/ELF/ppc64-pcrel-cross-link.s
Normal file
@ -0,0 +1,140 @@
|
||||
# REQUIRES: ppc
|
||||
# RUN: split-file %s %t
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -triple=powerpc64le %t/callees.s -o %t-callees.o
|
||||
# RUN: llvm-mc -filetype=obj -triple=powerpc64le %t/callertoc.s -o %t-callertoc.o
|
||||
# RUN: llvm-mc -filetype=obj -triple=powerpc64le %t/callernotoc.s -o %t-callernotoc.o
|
||||
# RUN: ld.lld -T %t/lds %t-callees.o %t-callernotoc.o %t-callertoc.o -o %t-r12setup
|
||||
# RUN: ld.lld -T %t/ldsswap %t-callees.o %t-callernotoc.o %t-callertoc.o -o %t-r2save
|
||||
|
||||
# RUN: llvm-objdump -d --no-show-raw-insn --mcpu=pwr10 %t-r12setup | \
|
||||
# RUN: FileCheck %s --check-prefix=NOSWAP
|
||||
# RUN: llvm-objdump -d --no-show-raw-insn --mcpu=pwr10 %t-r2save | \
|
||||
# RUN: FileCheck %s --check-prefix=SWAP
|
||||
|
||||
## This test checks that it is possible to mix TOC and NOTOC functions and have
|
||||
## the correct thunks for all of the calls.
|
||||
|
||||
# NOSWAP-LABEL: 01001000 <func>:
|
||||
# NOSWAP-NEXT: blr
|
||||
# NOSWAP-LABEL: 01002000 <callee_toc>:
|
||||
# NOSWAP: bl 0x1001000
|
||||
# NOSWAP: blr
|
||||
# NOSWAP-LABEL: 01002018 <callee_notoc>:
|
||||
# NOSWAP: bl 0x1001000
|
||||
# NOSWAP: blr
|
||||
# NOSWAP-LABEL: 10030000 <caller_notoc>:
|
||||
# NOSWAP-NEXT: bl 0x10030010
|
||||
# NOSWAP-NEXT: bl 0x10030030
|
||||
# NOSWAP-NEXT: blr
|
||||
# NOSWAP-LABEL: 10030010 <__gep_setup_callee_toc>:
|
||||
# NOSWAP: bctr
|
||||
# NOSWAP-LABEL: 10030030 <__long_branch_pcrel_callee_notoc>:
|
||||
# NOSWAP: bctr
|
||||
# NOSWAP-LABEL: 10040000 <caller_toc>:
|
||||
# NOSWAP: bl 0x10040020
|
||||
# NOSWAP-NEXT: nop
|
||||
# NOSWAP-NEXT: bl 0x10040040
|
||||
# NOSWAP-NEXT: ld 2, 24(1)
|
||||
# NOSWAP-NEXT: blr
|
||||
# NOSWAP-LABEL: 10040020 <__long_branch_callee_toc>:
|
||||
# NOSWAP: bctr
|
||||
# NOSWAP-LABEL: 10040040 <__toc_save_callee_notoc>:
|
||||
# NOSWAP-NEXT: std 2, 24(1)
|
||||
# NOSWAP: bctr
|
||||
|
||||
# SWAP-LABEL: 01001000 <func>:
|
||||
# SWAP-NEXT: blr
|
||||
# SWAP-LABEL: 01002000 <callee_toc>:
|
||||
# SWAP: bl 0x1001000
|
||||
# SWAP: blr
|
||||
# SWAP-LABEL: 01002018 <callee_notoc>:
|
||||
# SWAP: bl 0x1001000
|
||||
# SWAP: blr
|
||||
# SWAP-LABEL: 10030000 <caller_toc>:
|
||||
# SWAP: bl 0x10030020
|
||||
# SWAP-NEXT: nop
|
||||
# SWAP-NEXT: bl 0x10030040
|
||||
# SWAP-NEXT: ld 2, 24(1)
|
||||
# SWAP-NEXT: blr
|
||||
# SWAP-LABEL: 10030020 <__long_branch_callee_toc>:
|
||||
# SWAP: bctr
|
||||
# SWAP-LABEL: 10030040 <__toc_save_callee_notoc>:
|
||||
# SWAP-NEXT: std 2, 24(1)
|
||||
# SWAP: bctr
|
||||
# SWAP-LABEL: 10040000 <caller_notoc>:
|
||||
# SWAP-NEXT: bl 0x10040010
|
||||
# SWAP-NEXT: bl 0x10040030
|
||||
# SWAP-NEXT: blr
|
||||
# SWAP-LABEL: 10040010 <__gep_setup_callee_toc>:
|
||||
# SWAP: bctr
|
||||
# SWAP-LABEL: 10040030 <__long_branch_pcrel_callee_notoc>:
|
||||
# SWAP: bctr
|
||||
|
||||
#--- lds
|
||||
SECTIONS {
|
||||
.text_func 0x1001000 : { *(.text_func) }
|
||||
.text_callee 0x1002000 : { *(.text_callee) }
|
||||
.text_caller_notoc 0x10030000 : { *(.text_caller_notoc) }
|
||||
.text_caller_toc 0x10040000 : { *(.text_caller_toc) }
|
||||
}
|
||||
|
||||
#--- ldsswap
|
||||
SECTIONS {
|
||||
.text_func 0x1001000 : { *(.text_func) }
|
||||
.text_callee 0x1002000 : { *(.text_callee) }
|
||||
.text_caller_toc 0x10030000 : { *(.text_caller_toc) }
|
||||
.text_caller_notoc 0x10040000 : { *(.text_caller_notoc) }
|
||||
}
|
||||
|
||||
#--- callees.s
|
||||
.section .text_func, "ax", %progbits
|
||||
func:
|
||||
blr
|
||||
|
||||
.globl callee_toc
|
||||
.section .text_callee, "ax", %progbits
|
||||
callee_toc:
|
||||
.Lfunc_gep1:
|
||||
addis 2, 12, .TOC.-.Lfunc_gep1@ha
|
||||
addi 2, 2, .TOC.-.Lfunc_gep1@l
|
||||
.Lfunc_lep1:
|
||||
.localentry callee_toc, .Lfunc_lep1-.Lfunc_gep1
|
||||
bl func
|
||||
addis 4, 2, global@toc@ha
|
||||
lwz 4, global@toc@l(4)
|
||||
blr
|
||||
|
||||
.globl callee_notoc
|
||||
callee_notoc:
|
||||
.localentry callee_notoc, 1
|
||||
bl func
|
||||
plwz 4, global@pcrel(0), 1
|
||||
blr
|
||||
|
||||
## .globl global
|
||||
global:
|
||||
.long 0
|
||||
.size global, 4
|
||||
|
||||
#--- callernotoc.s
|
||||
.section .text_caller_notoc, "ax", %progbits
|
||||
caller_notoc:
|
||||
.localentry caller, 1
|
||||
bl callee_toc@notoc
|
||||
bl callee_notoc@notoc
|
||||
blr
|
||||
|
||||
#--- callertoc.s
|
||||
.section .text_caller_toc, "ax", %progbits
|
||||
caller_toc:
|
||||
.Lfunc_gep2:
|
||||
addis 2, 12, .TOC.-.Lfunc_gep2@ha
|
||||
addi 2, 2, .TOC.-.Lfunc_gep2@l
|
||||
.Lfunc_lep2:
|
||||
.localentry caller_toc, .Lfunc_lep2-.Lfunc_gep2
|
||||
bl callee_toc
|
||||
nop
|
||||
bl callee_notoc
|
||||
nop
|
||||
blr
|
Loading…
Reference in New Issue
Block a user