Skip to content

Commit bc8160c

Browse files
committed
Add execute-only compatible thunks
1 parent d558675 commit bc8160c

File tree

4 files changed

+94
-2
lines changed

4 files changed

+94
-2
lines changed

lld/ELF/Thunks.cpp

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,19 @@ class AArch64ABSLongThunk final : public AArch64Thunk {
9191
ThunkSection *tsec = nullptr;
9292
};
9393

94+
// AArch64 long range Thunks compatible with execute-only code.
95+
class AArch64ABSXOLongThunk final : public AArch64Thunk {
96+
public:
97+
AArch64ABSXOLongThunk(Ctx &ctx, Symbol &dest, int64_t addend,
98+
bool mayNeedLandingPad)
99+
: AArch64Thunk(ctx, dest, addend, mayNeedLandingPad) {}
100+
uint32_t size() override { return getMayUseShortThunk() ? 4 : 20; }
101+
void addSymbols(ThunkSection &sec) override;
102+
103+
private:
104+
void writeLong(uint8_t *buf) override;
105+
};
106+
94107
class AArch64ADRPThunk final : public AArch64Thunk {
95108
public:
96109
AArch64ADRPThunk(Ctx &ctx, Symbol &dest, int64_t addend,
@@ -663,6 +676,33 @@ void AArch64ABSLongThunk::addLongMapSyms() {
663676
addSymbol("$d", STT_NOTYPE, 8, *tsec);
664677
}
665678

679+
void AArch64ABSXOLongThunk::writeLong(uint8_t *buf) {
680+
const uint8_t data[] = {
681+
0x10, 0x00, 0x80, 0xd2, // movz x16, :abs_g0_nc:S, lsl #0
682+
0x10, 0x00, 0xa0, 0xf2, // movk x16, :abs_g1_nc:S, lsl #16
683+
0x10, 0x00, 0xc0, 0xf2, // movk x16, :abs_g2_nc:S, lsl #32
684+
0x10, 0x00, 0xe0, 0xf2, // movk x16, :abs_g3:S, lsl #48
685+
0x00, 0x02, 0x1f, 0xd6, // br x16
686+
};
687+
// If mayNeedLandingPad is true then destination is an
688+
// AArch64BTILandingPadThunk that defines landingPad.
689+
assert(!mayNeedLandingPad || landingPad != nullptr);
690+
uint64_t s = mayNeedLandingPad
691+
? landingPad->getVA(ctx, 0)
692+
: getAArch64ThunkDestVA(ctx, destination, addend);
693+
memcpy(buf, data, sizeof(data));
694+
ctx.target->relocateNoSym(buf + 0, R_AARCH64_MOVW_UABS_G0_NC, s);
695+
ctx.target->relocateNoSym(buf + 4, R_AARCH64_MOVW_UABS_G1_NC, s);
696+
ctx.target->relocateNoSym(buf + 8, R_AARCH64_MOVW_UABS_G2_NC, s);
697+
ctx.target->relocateNoSym(buf + 12, R_AARCH64_MOVW_UABS_G3, s);
698+
}
699+
700+
void AArch64ABSXOLongThunk::addSymbols(ThunkSection &sec) {
701+
addSymbol(ctx.saver.save("__AArch64AbsXOLongThunk_" + destination.getName()),
702+
STT_FUNC, 0, sec);
703+
addSymbol("$x", STT_NOTYPE, 0, sec);
704+
}
705+
666706
// This Thunk has a maximum range of 4Gb, this is sufficient for all programs
667707
// using the small code model, including pc-relative ones. At time of writing
668708
// clang and gcc do not support the large code model for position independent
@@ -1482,15 +1522,20 @@ Thunk::Thunk(Ctx &ctx, Symbol &d, int64_t a)
14821522

14831523
Thunk::~Thunk() = default;
14841524

1485-
static std::unique_ptr<Thunk> addThunkAArch64(Ctx &ctx, RelType type, Symbol &s,
1525+
static std::unique_ptr<Thunk> addThunkAArch64(Ctx &ctx, const InputSection &sec,
1526+
RelType type, Symbol &s,
14861527
int64_t a) {
14871528
assert(is_contained({R_AARCH64_CALL26, R_AARCH64_JUMP26, R_AARCH64_PLT32},
14881529
type));
14891530
bool mayNeedLandingPad =
14901531
(ctx.arg.andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_BTI) &&
14911532
!isAArch64BTILandingPad(ctx, s, a);
1533+
bool isPureCode = sec.getParent()->flags & SHF_AARCH64_PURECODE;
14921534
if (ctx.arg.picThunk)
14931535
return std::make_unique<AArch64ADRPThunk>(ctx, s, a, mayNeedLandingPad);
1536+
if (isPureCode)
1537+
return std::make_unique<AArch64ABSXOLongThunk>(ctx, s, a,
1538+
mayNeedLandingPad);
14941539
return std::make_unique<AArch64ABSLongThunk>(ctx, s, a, mayNeedLandingPad);
14951540
}
14961541

@@ -1702,7 +1747,7 @@ std::unique_ptr<Thunk> elf::addThunk(Ctx &ctx, const InputSection &isec,
17021747

17031748
switch (ctx.arg.emachine) {
17041749
case EM_AARCH64:
1705-
return addThunkAArch64(ctx, rel.type, s, a);
1750+
return addThunkAArch64(ctx, isec, rel.type, s, a);
17061751
case EM_ARM:
17071752
return addThunkArm(ctx, isec, rel.type, s, a);
17081753
case EM_AVR:
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.section .text,"axy",@progbits,unique,0
2+
.global big
3+
big = 0x1111222233334444
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// REQUIRES: aarch64
2+
// RUN: llvm-mc -filetype=obj -triple=aarch64 %S/Inputs/big-execute-only.s -o %tbig.o
3+
// RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o
4+
// RUN: ld.lld %t.o %tbig.o -o %t
5+
// RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
6+
7+
.section .text,"axy",@progbits,unique,0
8+
.globl _start
9+
_start:
10+
bl big
11+
12+
// CHECK: Disassembly of section .text:
13+
// CHECK-EMPTY:
14+
// CHECK-NEXT: <_start>:
15+
// CHECK-NEXT: 210120: bl 0x210124
16+
// CHECK: <__AArch64AbsXOLongThunk_big>:
17+
// CHECK-NEXT: 210124: mov x16, #0x4444
18+
// CHECK-NEXT: 210128: movk x16, #0x3333, lsl #16
19+
// CHECK-NEXT: 21012c: movk x16, #0x2222, lsl #32
20+
// CHECK-NEXT: 210130: movk x16, #0x1111, lsl #48
21+
// CHECK-NEXT: 210134: br x16
22+
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// REQUIRES: aarch64
2+
// RUN: llvm-mc -filetype=obj -triple=aarch64 %S/Inputs/big-execute-only.s -o %tbig.o
3+
// RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o
4+
// RUN: ld.lld %t.o %tbig.o -o %t
5+
// RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
6+
7+
.section .text,"axy",@progbits,unique,0
8+
.globl _start
9+
_start:
10+
b big
11+
12+
// CHECK: Disassembly of section .text:
13+
// CHECK-EMPTY:
14+
// CHECK-NEXT: <_start>:
15+
// CHECK-NEXT: 210120: b 0x210124
16+
// CHECK: <__AArch64AbsXOLongThunk_big>:
17+
// CHECK-NEXT: 210124: mov x16, #0x4444
18+
// CHECK-NEXT: 210128: movk x16, #0x3333, lsl #16
19+
// CHECK-NEXT: 21012c: movk x16, #0x2222, lsl #32
20+
// CHECK-NEXT: 210130: movk x16, #0x1111, lsl #48
21+
// CHECK-NEXT: 210134: br x16
22+

0 commit comments

Comments
 (0)