[lld] c335acc - [ELF] --pack-dyn-relocs=android+relr: place IRELATIVE in .rela.plt (#86751)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Mar 27 09:47:20 PDT 2024
Author: Fangrui Song
Date: 2024-03-27T09:47:16-07:00
New Revision: c335accb07c0cfa4bd7f47edc94c9005692edfcc
URL: https://github.com/llvm/llvm-project/commit/c335accb07c0cfa4bd7f47edc94c9005692edfcc
DIFF: https://github.com/llvm/llvm-project/commit/c335accb07c0cfa4bd7f47edc94c9005692edfcc.diff
LOG: [ELF] --pack-dyn-relocs=android+relr: place IRELATIVE in .rela.plt (#86751)
Current Bionic processes relocations in this order:
* DT_ANDROID_REL[A]
* DT_RELR
* DT_REL[A]
* DT_JMPREL
If an IRELATIVE relocation is in DT_ANDROID_REL[A], it would read
unrelocated (incorrect) global variables associated with RELR when
--pack-dyn-relocs=android+relr is enabled. Work around this by placing
IRELATIVE in .rel[a].plt (DT_JMPREL).
Link: https://r.android.com/3014185
Added:
lld/test/ELF/pack-dyn-relocs-ifunc.s
Modified:
lld/ELF/Relocations.cpp
Removed:
################################################################################
diff --git a/lld/ELF/Relocations.cpp b/lld/ELF/Relocations.cpp
index 33c50133bec495..92f2e200db1107 100644
--- a/lld/ELF/Relocations.cpp
+++ b/lld/ELF/Relocations.cpp
@@ -1659,10 +1659,17 @@ static bool handleNonPreemptibleIfunc(Symbol &sym, uint16_t flags) {
// original section/value pairs. For non-GOT non-PLT relocation case below, we
// may alter section/value, so create a copy of the symbol to make
// section/value fixed.
+ //
+ // Prior to Android V, there was a bug that caused RELR relocations to be
+ // applied after packed relocations. This meant that resolvers referenced by
+ // IRELATIVE relocations in the packed relocation section would read
+ // unrelocated globals with RELR relocations when
+ // --pack-relative-relocs=android+relr is enabled. Work around this by placing
+ // IRELATIVE in .rela.plt.
auto *directSym = makeDefined(cast<Defined>(sym));
directSym->allocateAux();
- addPltEntry(*in.iplt, *in.igotPlt, *mainPart->relaDyn, target->iRelativeRel,
- *directSym);
+ auto &dyn = config->androidPackDynRelocs ? *in.relaPlt : *mainPart->relaDyn;
+ addPltEntry(*in.iplt, *in.igotPlt, dyn, target->iRelativeRel, *directSym);
sym.allocateAux();
symAux.back().pltIdx = symAux[directSym->auxIdx].pltIdx;
diff --git a/lld/test/ELF/pack-dyn-relocs-ifunc.s b/lld/test/ELF/pack-dyn-relocs-ifunc.s
new file mode 100644
index 00000000000000..6168d06f99d9e9
--- /dev/null
+++ b/lld/test/ELF/pack-dyn-relocs-ifunc.s
@@ -0,0 +1,49 @@
+# REQUIRES: aarch64
+## Prior to Android V, there was a bug that caused RELR relocations to be
+## applied after packed relocations. This meant that resolvers referenced by
+## IRELATIVE relocations in the packed relocation section would read unrelocated
+## globals when --pack-relative-relocs=android+relr is enabled. Work around this
+## by placing IRELATIVE in .rela.plt.
+
+# RUN: rm -rf %t && split-file %s %t && cd %t
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-android a.s -o a.o
+# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-android b.s -o b.o
+# RUN: ld.lld -shared b.o -o b.so
+# RUN: ld.lld -pie --pack-dyn-relocs=android+relr -z separate-loadable-segments a.o b.so -o a
+# RUN: llvm-readobj -r a | FileCheck %s
+# RUN: llvm-objdump -d a | FileCheck %s --check-prefix=ASM
+
+# CHECK: .relr.dyn {
+# CHECK-NEXT: 0x30000 R_AARCH64_RELATIVE -
+# CHECK-NEXT: }
+# CHECK: .rela.plt {
+# CHECK-NEXT: 0x30020 R_AARCH64_JUMP_SLOT bar 0x0
+# CHECK-NEXT: 0x30028 R_AARCH64_IRELATIVE - 0x10000
+# CHECK-NEXT: }
+
+# ASM: <.iplt>:
+# ASM-NEXT: adrp x16, 0x30000
+# ASM-NEXT: ldr x17, [x16, #0x28]
+# ASM-NEXT: add x16, x16, #0x28
+# ASM-NEXT: br x17
+
+#--- a.s
+.text
+.type foo, %gnu_indirect_function
+.globl foo
+foo:
+ ret
+
+.globl _start
+_start:
+ bl foo
+ bl bar
+
+.data
+.balign 8
+.quad .data
+
+#--- b.s
+.globl bar
+bar:
+ ret
More information about the llvm-commits
mailing list