[lld] 978eb3b - [lld] [ELF] AArch64: Handle DT_AARCH64_VARIANT_PCS

Adhemerval Zanella via llvm-commits llvm-commits at lists.llvm.org
Thu Dec 17 06:34:34 PST 2020


Author: Adhemerval Zanella
Date: 2020-12-17T11:09:55-03:00
New Revision: 978eb3b87bca0837d52d096c343fc70b06d9a04d

URL: https://github.com/llvm/llvm-project/commit/978eb3b87bca0837d52d096c343fc70b06d9a04d
DIFF: https://github.com/llvm/llvm-project/commit/978eb3b87bca0837d52d096c343fc70b06d9a04d.diff

LOG: [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

Added: 
    lld/test/ELF/aarch64-variant_pcs.s

Modified: 
    lld/ELF/SyntheticSections.cpp

Removed: 
    


################################################################################
diff  --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp
index eccd3ef1795e..9b5fb3f26c59 100644
--- a/lld/ELF/SyntheticSections.cpp
+++ b/lld/ELF/SyntheticSections.cpp
@@ -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)

diff  --git a/lld/test/ELF/aarch64-variant_pcs.s b/lld/test/ELF/aarch64-variant_pcs.s
new file mode 100644
index 000000000000..b7f1efc16d6c
--- /dev/null
+++ b/lld/test/ELF/aarch64-variant_pcs.s
@@ -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


        


More information about the llvm-commits mailing list