forked from OSchip/llvm-project
[lld] [ELF] AArch64: Handle DT_AARCH64_VARIANT_PCS
As indicated by AArch64 ELF specification, symbols with st_other marked with STO_AARCH64_VARIANT_PCS indicates it may follow a variant procedure call standard with different register usage convention (for instance SVE calls). Static linkers must preserve the marking and propagate it to the dynamic symbol table if any reference or definition of the symbol is marked with STO_AARCH64_VARIANT_PCS, and add a DT_AARCH64_VARIANT_PCS dynamic tag if there are R_<CLS>_JUMP_SLOT relocations that reference that symbols. It implements https://bugs.llvm.org/show_bug.cgi?id=48368. Reviewed By: MaskRay Differential Revision: https://reviews.llvm.org/D93045
This commit is contained in:
parent
e04dc5f557
commit
978eb3b87b
|
@ -1436,6 +1436,13 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
|
|||
case EM_SPARCV9:
|
||||
addInSec(DT_PLTGOT, in.plt);
|
||||
break;
|
||||
case EM_AARCH64:
|
||||
if (llvm::find_if(in.relaPlt->relocs, [](const DynamicReloc &r) {
|
||||
return r.type == target->pltRel &&
|
||||
r.sym->stOther & STO_AARCH64_VARIANT_PCS;
|
||||
}) != in.relaPlt->relocs.end())
|
||||
addInt(DT_AARCH64_VARIANT_PCS, 0);
|
||||
LLVM_FALLTHROUGH;
|
||||
default:
|
||||
addInSec(DT_PLTGOT, in.gotPlt);
|
||||
break;
|
||||
|
@ -2181,6 +2188,10 @@ template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *buf) {
|
|||
// See getPPC64GlobalEntryToLocalEntryOffset() for more details.
|
||||
if (config->emachine == EM_PPC64)
|
||||
eSym->st_other |= sym->stOther & 0xe0;
|
||||
// The most significant bit of st_other is used by AArch64 ABI for the
|
||||
// variant PCS.
|
||||
else if (config->emachine == EM_AARCH64)
|
||||
eSym->st_other |= sym->stOther & STO_AARCH64_VARIANT_PCS;
|
||||
|
||||
eSym->st_name = ent.strTabOffset;
|
||||
if (isDefinedHere)
|
||||
|
|
|
@ -0,0 +1,130 @@
|
|||
# REQUIRES: aarch64
|
||||
# RUN: split-file %s %t
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %t/test1 -o %t.o
|
||||
# RUN: ld.lld %t.o --shared -o %t.so
|
||||
# RUN: llvm-readelf --dynamic-table %t.so | FileCheck --check-prefix T1-PCSDYN %s
|
||||
# RUN: llvm-readelf --symbols %t.so | FileCheck --check-prefix T1-PCSSYM %s
|
||||
|
||||
# T1-PCSDYN-NOT: 0x0000000070000005 (AARCH64_VARIANT_PCS) 0
|
||||
# T1-PCSSYM: Symbol table '.dynsym'
|
||||
# T1-PCSSYM: 0 NOTYPE GLOBAL DEFAULT [VARIANT_PCS] [[#]] pcs_func_global_def
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %t/test2 -o %t.o
|
||||
# RUN: ld.lld %t.o --shared -o %t.so
|
||||
# RUN: llvm-readelf --dynamic-table %t.so | FileCheck --check-prefix T2-PCSDYN %s
|
||||
# RUN: llvm-readelf --symbols %t.so | FileCheck --check-prefix T2-PCSSYM %s
|
||||
|
||||
# T2-PCSDYN: 0x0000000070000005 (AARCH64_VARIANT_PCS) 0
|
||||
# T2-PCSSYM: Symbol table '.dynsym'
|
||||
# T2-PCSSYM: 0 NOTYPE GLOBAL DEFAULT [VARIANT_PCS] [[#]] pcs_func_global_def
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %t/test3 -o %t.o
|
||||
# RUN: ld.lld %t.o --shared -o %t.so
|
||||
# RUN: llvm-readelf --dynamic-table %t.so | FileCheck --check-prefix T3-PCSDYN %s
|
||||
# RUN: llvm-readelf --symbols %t.so | FileCheck --check-prefix T3-PCSSYM %s
|
||||
|
||||
# T3-PCSDYN: 0x0000000070000005 (AARCH64_VARIANT_PCS) 0
|
||||
# T3-PCSSYM: Symbol table '.dynsym'
|
||||
# T3-PCSSYM: 0 IFUNC GLOBAL DEFAULT [VARIANT_PCS] UND pcs_ifunc_global_def
|
||||
# T3-PCSSYM: 0 NOTYPE GLOBAL DEFAULT [[#]] pcs_func_global_def
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %t/test4 -o %t.o
|
||||
# RUN: ld.lld %t.o --shared -o %t.so
|
||||
# RUN: llvm-readelf --dynamic-table %t.so | FileCheck --check-prefix T4-PCSDYN %s
|
||||
# RUN: llvm-readelf --symbols %t.so | FileCheck --check-prefix T4-PCSSYM %s
|
||||
|
||||
# T4-PCSDYN-NOT: 0x0000000070000005 (AARCH64_VARIANT_PCS) 0
|
||||
# T4-PCSSYM: Symbol table '.dynsym'
|
||||
# T4-PCSSYM: 0 IFUNC GLOBAL DEFAULT [VARIANT_PCS] [[#]] pcs_ifunc_global_def
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %t/test5 -o %t.o
|
||||
# RUN: ld.lld %t.o --shared -o %t.so
|
||||
# RUN: llvm-readelf --symbols %t.so | FileCheck --check-prefix T5-PCSSYM %s
|
||||
|
||||
# T5-PCSSYM: Symbol table '.dynsym'
|
||||
# T5-PCSSYM: 0 NOTYPE GLOBAL DEFAULT [VARIANT_PCS] UND pcs_func_global_undef
|
||||
# T5-PCSSYM-NEXT: 0 NOTYPE GLOBAL DEFAULT [VARIANT_PCS] [[#]] pcs_func_global_def
|
||||
# T5-PCSSYM-NEXT: 0 IFUNC GLOBAL DEFAULT [VARIANT_PCS] [[#]] pcs_ifunc_global_def
|
||||
# T5-PCSSYM: Symbol table '.symtab' contains 10 entries:
|
||||
# T5-PCSSYM: 0 NOTYPE LOCAL DEFAULT [VARIANT_PCS] [[#]] pcs_func_local
|
||||
# T5-PCSSYM-NEXT: 0 IFUNC LOCAL DEFAULT [VARIANT_PCS] [[#]] pcs_ifunc_local
|
||||
# T5-PCSSYM-NEXT: 0 NOTYPE LOCAL HIDDEN [VARIANT_PCS] [[#]] pcs_func_global_hidden
|
||||
# T5-PCSSYM-NEXT: 0 IFUNC LOCAL HIDDEN [VARIANT_PCS] [[#]] pcs_ifunc_global_hidden
|
||||
# T5-PCSSYM: 0 NOTYPE GLOBAL DEFAULT [VARIANT_PCS] [[#]] pcs_func_global_def
|
||||
# T5-PCSSYM-NEXT: 0 NOTYPE GLOBAL DEFAULT [VARIANT_PCS] UND pcs_func_global_undef
|
||||
# T5-PCSSYM-NEXT: 0 IFUNC GLOBAL DEFAULT [VARIANT_PCS] [[#]] pcs_ifunc_global_def
|
||||
|
||||
|
||||
#--- test1
|
||||
## An object with a variant_pcs symbol but without a R_AARCH64_JMP_SLOT
|
||||
## should not generate a DT_AARCH64_VARIANT_PCS.
|
||||
.text
|
||||
.global pcs_func_global_def
|
||||
.variant_pcs pcs_func_global_def
|
||||
|
||||
pcs_func_global_def:
|
||||
ret
|
||||
|
||||
#--- test2
|
||||
## An object with a variant_pcs symbol and with a R_AARCH64_JMP_SLOT
|
||||
## should generate a DT_AARCH64_VARIANT_PCS.
|
||||
.text
|
||||
.global pcs_func_global_def
|
||||
.variant_pcs pcs_func_global_def
|
||||
|
||||
pcs_func_global_def:
|
||||
bl pcs_func_global_def
|
||||
|
||||
#--- test3
|
||||
## Same as before, but targeting a GNU IFUNC.
|
||||
.text
|
||||
.global pcs_ifunc_global_def
|
||||
.global pcs_func_global_def
|
||||
.variant_pcs pcs_ifunc_global_def
|
||||
.type pcs_ifunc_global_def, %gnu_indirect_function
|
||||
|
||||
pcs_func_global_def:
|
||||
bl pcs_ifunc_global_def
|
||||
|
||||
#--- test4
|
||||
## An object with a variant_pcs symbol and with a R_AARCH64_IRELATIVE
|
||||
## should not generate a DT_AARCH64_VARIANT_PCS.
|
||||
.text
|
||||
.global pcs_ifunc_global_def
|
||||
.global pcs_func_global_def
|
||||
.variant_pcs pcs_ifunc_global_def
|
||||
.type pcs_ifunc_global_def, %gnu_indirect_function
|
||||
|
||||
pcs_ifunc_global_def:
|
||||
bl pcs_func_global_def
|
||||
|
||||
#--- test5
|
||||
## Check if STO_AARCH64_VARIANT_PCS is kept on symbol st_other for both undef,
|
||||
## local, and hidden visibility.
|
||||
.text
|
||||
.global pcs_func_global_def, pcs_func_global_undef, pcs_func_global_hidden
|
||||
.global pcs_ifunc_global_def, pcs_ifunc_global_hidden
|
||||
.local pcs_func_local
|
||||
|
||||
.hidden pcs_func_global_hidden, pcs_ifunc_global_hidden
|
||||
|
||||
.type pcs_ifunc_global_def, %gnu_indirect_function
|
||||
.type pcs_ifunc_global_hidden, %gnu_indirect_function
|
||||
.type pcs_ifunc_local, %gnu_indirect_function
|
||||
|
||||
.variant_pcs pcs_func_global_def
|
||||
.variant_pcs pcs_func_global_undef
|
||||
.variant_pcs pcs_func_global_hidden
|
||||
.variant_pcs pcs_func_local
|
||||
.variant_pcs pcs_ifunc_global_def
|
||||
.variant_pcs pcs_ifunc_global_hidden
|
||||
.variant_pcs pcs_ifunc_local
|
||||
|
||||
pcs_func_global_def:
|
||||
pcs_func_global_hidden:
|
||||
pcs_func_local:
|
||||
pcs_ifunc_global_def:
|
||||
pcs_ifunc_global_hidden:
|
||||
pcs_ifunc_local:
|
||||
ret
|
Loading…
Reference in New Issue