Skip to content

Commit

Permalink
[ELF] --pack-dyn-relocs=android+relr: place IRELATIVE in .rela.plt (#…
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
MaskRay committed Mar 27, 2024
1 parent 1c96580 commit c335acc
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 2 deletions.
11 changes: 9 additions & 2 deletions lld/ELF/Relocations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down
49 changes: 49 additions & 0 deletions lld/test/ELF/pack-dyn-relocs-ifunc.s
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit c335acc

Please sign in to comment.