Skip to content

Commit 27923f7

Browse files
authored
[LLD][AArch64][ARM] Delay adding long thunk mapping symbols (#116975)
When we create a thunk we don't know whether it will be short or long. Move the emission of the long thunk mapping symbol to when we transition to a long thunk. This improves disassembly and binary analysis as tools like BOLT identify thunks by disassembly. This removes a FIXME added in #108989 aarch64-thunk-bti-multipass.s which had a corrupt disassembly due to missing mapping symbols.
1 parent 86fd4d4 commit 27923f7

File tree

2 files changed

+133
-34
lines changed

2 files changed

+133
-34
lines changed

lld/ELF/Thunks.cpp

Lines changed: 131 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,11 @@ class AArch64Thunk : public Thunk {
6969
private:
7070
bool mayUseShortThunk = true;
7171
virtual void writeLong(uint8_t *buf) = 0;
72+
// A thunk may be written out as a short or long, and we may not know which
73+
// type at thunk creation time. In some thunk implementations the long thunk
74+
// has additional mapping symbols. Thus function can be overridden to add
75+
// these additional mapping symbols.
76+
virtual void addLongMapSyms() {}
7277
};
7378

7479
// AArch64 long range Thunks.
@@ -82,6 +87,8 @@ class AArch64ABSLongThunk final : public AArch64Thunk {
8287

8388
private:
8489
void writeLong(uint8_t *buf) override;
90+
void addLongMapSyms() override;
91+
ThunkSection *tsec = nullptr;
8592
};
8693

8794
class AArch64ADRPThunk final : public AArch64Thunk {
@@ -148,6 +155,8 @@ class ARMThunk : public Thunk {
148155
// can create layout oscillations in certain corner cases which would prevent
149156
// the layout from converging.
150157
bool mayUseShortThunk = true;
158+
// See comment in AArch64Thunk.
159+
virtual void addLongMapSyms() {}
151160
};
152161

153162
// Base class for Thumb-2 thunks.
@@ -176,6 +185,8 @@ class ThumbThunk : public Thunk {
176185
private:
177186
// See comment in ARMThunk above.
178187
bool mayUseShortThunk = true;
188+
// See comment in AArch64Thunk.
189+
virtual void addLongMapSyms() {}
179190
};
180191

181192
// Specific ARM Thunk implementations. The naming convention is:
@@ -229,6 +240,10 @@ class ThumbV6MABSLongThunk final : public ThumbThunk {
229240
uint32_t sizeLong() override { return 12; }
230241
void writeLong(uint8_t *buf) override;
231242
void addSymbols(ThunkSection &isec) override;
243+
244+
private:
245+
void addLongMapSyms() override;
246+
ThunkSection *tsec = nullptr;
232247
};
233248

234249
class ThumbV6MABSXOLongThunk final : public ThumbThunk {
@@ -249,6 +264,10 @@ class ThumbV6MPILongThunk final : public ThumbThunk {
249264
uint32_t sizeLong() override { return 16; }
250265
void writeLong(uint8_t *buf) override;
251266
void addSymbols(ThunkSection &isec) override;
267+
268+
private:
269+
void addLongMapSyms() override;
270+
ThunkSection *tsec = nullptr;
252271
};
253272

254273
// Architectures v4, v5 and v6 do not support the movt/movw instructions. v5 and
@@ -267,6 +286,10 @@ class ARMV5LongLdrPcThunk final : public ARMThunk {
267286
uint32_t sizeLong() override { return 8; }
268287
void writeLong(uint8_t *buf) override;
269288
void addSymbols(ThunkSection &isec) override;
289+
290+
private:
291+
void addLongMapSyms() override;
292+
ThunkSection *tsec = nullptr;
270293
};
271294

272295
// Implementations of Thunks for v4. BLX is not supported, and loads
@@ -279,6 +302,10 @@ class ARMV4PILongBXThunk final : public ARMThunk {
279302
uint32_t sizeLong() override { return 16; }
280303
void writeLong(uint8_t *buf) override;
281304
void addSymbols(ThunkSection &isec) override;
305+
306+
private:
307+
void addLongMapSyms() override;
308+
ThunkSection *tsec = nullptr;
282309
};
283310

284311
class ARMV4PILongThunk final : public ARMThunk {
@@ -289,6 +316,10 @@ class ARMV4PILongThunk final : public ARMThunk {
289316
uint32_t sizeLong() override { return 12; }
290317
void writeLong(uint8_t *buf) override;
291318
void addSymbols(ThunkSection &isec) override;
319+
320+
private:
321+
void addLongMapSyms() override;
322+
ThunkSection *tsec = nullptr;
292323
};
293324

294325
class ThumbV4PILongBXThunk final : public ThumbThunk {
@@ -299,6 +330,10 @@ class ThumbV4PILongBXThunk final : public ThumbThunk {
299330
uint32_t sizeLong() override { return 16; }
300331
void writeLong(uint8_t *buf) override;
301332
void addSymbols(ThunkSection &isec) override;
333+
334+
private:
335+
void addLongMapSyms() override;
336+
ThunkSection *tsec = nullptr;
302337
};
303338

304339
class ThumbV4PILongThunk final : public ThumbThunk {
@@ -309,6 +344,10 @@ class ThumbV4PILongThunk final : public ThumbThunk {
309344
uint32_t sizeLong() override { return 20; }
310345
void writeLong(uint8_t *buf) override;
311346
void addSymbols(ThunkSection &isec) override;
347+
348+
private:
349+
void addLongMapSyms() override;
350+
ThunkSection *tsec = nullptr;
312351
};
313352

314353
class ARMV4ABSLongBXThunk final : public ARMThunk {
@@ -319,6 +358,10 @@ class ARMV4ABSLongBXThunk final : public ARMThunk {
319358
uint32_t sizeLong() override { return 12; }
320359
void writeLong(uint8_t *buf) override;
321360
void addSymbols(ThunkSection &isec) override;
361+
362+
private:
363+
void addLongMapSyms() override;
364+
ThunkSection *tsec = nullptr;
322365
};
323366

324367
class ThumbV4ABSLongBXThunk final : public ThumbThunk {
@@ -329,6 +372,10 @@ class ThumbV4ABSLongBXThunk final : public ThumbThunk {
329372
uint32_t sizeLong() override { return 12; }
330373
void writeLong(uint8_t *buf) override;
331374
void addSymbols(ThunkSection &isec) override;
375+
376+
private:
377+
void addLongMapSyms() override;
378+
ThunkSection *tsec = nullptr;
332379
};
333380

334381
class ThumbV4ABSLongThunk final : public ThumbThunk {
@@ -339,6 +386,10 @@ class ThumbV4ABSLongThunk final : public ThumbThunk {
339386
uint32_t sizeLong() override { return 16; }
340387
void writeLong(uint8_t *buf) override;
341388
void addSymbols(ThunkSection &isec) override;
389+
390+
private:
391+
void addLongMapSyms() override;
392+
ThunkSection *tsec = nullptr;
342393
};
343394

344395
// The AVR devices need thunks for R_AVR_LO8_LDI_GS/R_AVR_HI8_LDI_GS
@@ -560,6 +611,8 @@ bool AArch64Thunk::getMayUseShortThunk() {
560611
uint64_t s = getAArch64ThunkDestVA(ctx, destination, addend);
561612
uint64_t p = getThunkTargetSym()->getVA(ctx);
562613
mayUseShortThunk = llvm::isInt<28>(s - p);
614+
if (!mayUseShortThunk)
615+
addLongMapSyms();
563616
return mayUseShortThunk;
564617
}
565618

@@ -602,8 +655,12 @@ void AArch64ABSLongThunk::addSymbols(ThunkSection &isec) {
602655
addSymbol(ctx.saver.save("__AArch64AbsLongThunk_" + destination.getName()),
603656
STT_FUNC, 0, isec);
604657
addSymbol("$x", STT_NOTYPE, 0, isec);
605-
if (!getMayUseShortThunk())
606-
addSymbol("$d", STT_NOTYPE, 8, isec);
658+
tsec = &isec;
659+
(void)getMayUseShortThunk();
660+
}
661+
662+
void AArch64ABSLongThunk::addLongMapSyms() {
663+
addSymbol("$d", STT_NOTYPE, 8, *tsec);
607664
}
608665

609666
// This Thunk has a maximum range of 4Gb, this is sufficient for all programs
@@ -691,11 +748,14 @@ bool ARMThunk::getMayUseShortThunk() {
691748
uint64_t s = getARMThunkDestVA(ctx, destination);
692749
if (s & 1) {
693750
mayUseShortThunk = false;
751+
addLongMapSyms();
694752
return false;
695753
}
696754
uint64_t p = getThunkTargetSym()->getVA(ctx);
697755
int64_t offset = s - p - 8;
698756
mayUseShortThunk = llvm::isInt<26>(offset);
757+
if (!mayUseShortThunk)
758+
addLongMapSyms();
699759
return mayUseShortThunk;
700760
}
701761

@@ -729,16 +789,19 @@ bool ARMThunk::isCompatibleWith(const InputSection &isec,
729789
// (see comment for mayUseShortThunk)
730790
// && the arch supports Thumb branch range extension.
731791
bool ThumbThunk::getMayUseShortThunk() {
732-
if (!mayUseShortThunk || !ctx.arg.armJ1J2BranchEncoding)
792+
if (!mayUseShortThunk)
733793
return false;
734794
uint64_t s = getARMThunkDestVA(ctx, destination);
735-
if ((s & 1) == 0) {
795+
if ((s & 1) == 0 || !ctx.arg.armJ1J2BranchEncoding) {
736796
mayUseShortThunk = false;
797+
addLongMapSyms();
737798
return false;
738799
}
739800
uint64_t p = getThunkTargetSym()->getVA(ctx) & ~1;
740801
int64_t offset = s - p - 4;
741802
mayUseShortThunk = llvm::isInt<25>(offset);
803+
if (!mayUseShortThunk)
804+
addLongMapSyms();
742805
return mayUseShortThunk;
743806
}
744807

@@ -856,8 +919,12 @@ void ThumbV6MABSLongThunk::addSymbols(ThunkSection &isec) {
856919
addSymbol(ctx.saver.save("__Thumbv6MABSLongThunk_" + destination.getName()),
857920
STT_FUNC, 1, isec);
858921
addSymbol("$t", STT_NOTYPE, 0, isec);
859-
if (!getMayUseShortThunk())
860-
addSymbol("$d", STT_NOTYPE, 8, isec);
922+
tsec = &isec;
923+
(void)getMayUseShortThunk();
924+
}
925+
926+
void ThumbV6MABSLongThunk::addLongMapSyms() {
927+
addSymbol("$d", STT_NOTYPE, 8, *tsec);
861928
}
862929

863930
void ThumbV6MABSXOLongThunk::writeLong(uint8_t *buf) {
@@ -912,8 +979,12 @@ void ThumbV6MPILongThunk::addSymbols(ThunkSection &isec) {
912979
addSymbol(ctx.saver.save("__Thumbv6MPILongThunk_" + destination.getName()),
913980
STT_FUNC, 1, isec);
914981
addSymbol("$t", STT_NOTYPE, 0, isec);
915-
if (!getMayUseShortThunk())
916-
addSymbol("$d", STT_NOTYPE, 12, isec);
982+
tsec = &isec;
983+
(void)getMayUseShortThunk();
984+
}
985+
986+
void ThumbV6MPILongThunk::addLongMapSyms() {
987+
addSymbol("$d", STT_NOTYPE, 12, *tsec);
917988
}
918989

919990
void ARMV5LongLdrPcThunk::writeLong(uint8_t *buf) {
@@ -927,8 +998,12 @@ void ARMV5LongLdrPcThunk::addSymbols(ThunkSection &isec) {
927998
addSymbol(ctx.saver.save("__ARMv5LongLdrPcThunk_" + destination.getName()),
928999
STT_FUNC, 0, isec);
9291000
addSymbol("$a", STT_NOTYPE, 0, isec);
930-
if (!getMayUseShortThunk())
931-
addSymbol("$d", STT_NOTYPE, 4, isec);
1001+
tsec = &isec;
1002+
(void)getMayUseShortThunk();
1003+
}
1004+
1005+
void ARMV5LongLdrPcThunk::addLongMapSyms() {
1006+
addSymbol("$d", STT_NOTYPE, 4, *tsec);
9321007
}
9331008

9341009
void ARMV4ABSLongBXThunk::writeLong(uint8_t *buf) {
@@ -943,8 +1018,12 @@ void ARMV4ABSLongBXThunk::addSymbols(ThunkSection &isec) {
9431018
addSymbol(ctx.saver.save("__ARMv4ABSLongBXThunk_" + destination.getName()),
9441019
STT_FUNC, 0, isec);
9451020
addSymbol("$a", STT_NOTYPE, 0, isec);
946-
if (!getMayUseShortThunk())
947-
addSymbol("$d", STT_NOTYPE, 8, isec);
1021+
tsec = &isec;
1022+
(void)getMayUseShortThunk();
1023+
}
1024+
1025+
void ARMV4ABSLongBXThunk::addLongMapSyms() {
1026+
addSymbol("$d", STT_NOTYPE, 8, *tsec);
9481027
}
9491028

9501029
void ThumbV4ABSLongBXThunk::writeLong(uint8_t *buf) {
@@ -961,9 +1040,13 @@ void ThumbV4ABSLongBXThunk::addSymbols(ThunkSection &isec) {
9611040
addSymbol(ctx.saver.save("__Thumbv4ABSLongBXThunk_" + destination.getName()),
9621041
STT_FUNC, 1, isec);
9631042
addSymbol("$t", STT_NOTYPE, 0, isec);
964-
addSymbol("$a", STT_NOTYPE, 4, isec);
965-
if (!getMayUseShortThunk())
966-
addSymbol("$d", STT_NOTYPE, 8, isec);
1043+
tsec = &isec;
1044+
(void)getMayUseShortThunk();
1045+
}
1046+
1047+
void ThumbV4ABSLongBXThunk::addLongMapSyms() {
1048+
addSymbol("$a", STT_NOTYPE, 4, *tsec);
1049+
addSymbol("$d", STT_NOTYPE, 8, *tsec);
9671050
}
9681051

9691052
void ThumbV4ABSLongThunk::writeLong(uint8_t *buf) {
@@ -981,9 +1064,13 @@ void ThumbV4ABSLongThunk::addSymbols(ThunkSection &isec) {
9811064
addSymbol(ctx.saver.save("__Thumbv4ABSLongThunk_" + destination.getName()),
9821065
STT_FUNC, 1, isec);
9831066
addSymbol("$t", STT_NOTYPE, 0, isec);
984-
addSymbol("$a", STT_NOTYPE, 4, isec);
985-
if (!getMayUseShortThunk())
986-
addSymbol("$d", STT_NOTYPE, 12, isec);
1067+
tsec = &isec;
1068+
(void)getMayUseShortThunk();
1069+
}
1070+
1071+
void ThumbV4ABSLongThunk::addLongMapSyms() {
1072+
addSymbol("$a", STT_NOTYPE, 4, *tsec);
1073+
addSymbol("$d", STT_NOTYPE, 12, *tsec);
9871074
}
9881075

9891076
void ARMV4PILongBXThunk::writeLong(uint8_t *buf) {
@@ -1000,8 +1087,12 @@ void ARMV4PILongBXThunk::addSymbols(ThunkSection &isec) {
10001087
addSymbol(ctx.saver.save("__ARMv4PILongBXThunk_" + destination.getName()),
10011088
STT_FUNC, 0, isec);
10021089
addSymbol("$a", STT_NOTYPE, 0, isec);
1003-
if (!getMayUseShortThunk())
1004-
addSymbol("$d", STT_NOTYPE, 12, isec);
1090+
tsec = &isec;
1091+
(void)getMayUseShortThunk();
1092+
}
1093+
1094+
void ARMV4PILongBXThunk::addLongMapSyms() {
1095+
addSymbol("$d", STT_NOTYPE, 12, *tsec);
10051096
}
10061097

10071098
void ARMV4PILongThunk::writeLong(uint8_t *buf) {
@@ -1017,8 +1108,12 @@ void ARMV4PILongThunk::addSymbols(ThunkSection &isec) {
10171108
addSymbol(ctx.saver.save("__ARMv4PILongThunk_" + destination.getName()),
10181109
STT_FUNC, 0, isec);
10191110
addSymbol("$a", STT_NOTYPE, 0, isec);
1020-
if (!getMayUseShortThunk())
1021-
addSymbol("$d", STT_NOTYPE, 8, isec);
1111+
tsec = &isec;
1112+
(void)getMayUseShortThunk();
1113+
}
1114+
1115+
void ARMV4PILongThunk::addLongMapSyms() {
1116+
addSymbol("$d", STT_NOTYPE, 8, *tsec);
10221117
}
10231118

10241119
void ThumbV4PILongBXThunk::writeLong(uint8_t *buf) {
@@ -1037,9 +1132,13 @@ void ThumbV4PILongBXThunk::addSymbols(ThunkSection &isec) {
10371132
addSymbol(ctx.saver.save("__Thumbv4PILongBXThunk_" + destination.getName()),
10381133
STT_FUNC, 1, isec);
10391134
addSymbol("$t", STT_NOTYPE, 0, isec);
1040-
addSymbol("$a", STT_NOTYPE, 4, isec);
1041-
if (!getMayUseShortThunk())
1042-
addSymbol("$d", STT_NOTYPE, 12, isec);
1135+
tsec = &isec;
1136+
(void)getMayUseShortThunk();
1137+
}
1138+
1139+
void ThumbV4PILongBXThunk::addLongMapSyms() {
1140+
addSymbol("$a", STT_NOTYPE, 4, *tsec);
1141+
addSymbol("$d", STT_NOTYPE, 12, *tsec);
10431142
}
10441143

10451144
void ThumbV4PILongThunk::writeLong(uint8_t *buf) {
@@ -1059,9 +1158,13 @@ void ThumbV4PILongThunk::addSymbols(ThunkSection &isec) {
10591158
addSymbol(ctx.saver.save("__Thumbv4PILongThunk_" + destination.getName()),
10601159
STT_FUNC, 1, isec);
10611160
addSymbol("$t", STT_NOTYPE, 0, isec);
1062-
addSymbol("$a", STT_NOTYPE, 4, isec);
1063-
if (!getMayUseShortThunk())
1064-
addSymbol("$d", STT_NOTYPE, 16, isec);
1161+
tsec = &isec;
1162+
(void)getMayUseShortThunk();
1163+
}
1164+
1165+
void ThumbV4PILongThunk::addLongMapSyms() {
1166+
addSymbol("$a", STT_NOTYPE, 4, *tsec);
1167+
addSymbol("$d", STT_NOTYPE, 16, *tsec);
10651168
}
10661169

10671170
// Use the long jump which covers a range up to 8MiB.

lld/test/ELF/aarch64-thunk-bti-multipass.s

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,11 @@ _start:
4040
// CHECK-LABEL: <_start>:
4141
// CHECK-NEXT: 10001000: bl 0x10002004 <__AArch64AbsLongThunk_fn1>
4242

43-
/// FIXME, the 2nd ldr and udf are a result of mapping symbols being generated
44-
/// on Thunk insertion. When that is fixed in lld they will be data statements
45-
/// like in __AArch64AbsLongThunk_far below.
4643
// CHECK-LABEL: <__AArch64AbsLongThunk_fn1>:
4744
// CHECK-NEXT: 10002004: ldr x16, 0x1000200c <__AArch64AbsLongThunk_fn1+0x8>
4845
// CHECK-NEXT: br x16
49-
// CHECK-NEXT: ldr w0, 0x1000260c <__AArch64AbsLongThunk_fn1+0x608>
50-
// CHECK-NEXT: udf #0x0
51-
46+
// CHECK-NEXT: 00 30 00 18 .word 0x18003000
47+
// CHECK-NEXT: 00 00 00 00 .word 0x00000000
5248

5349
.section .text.1, "ax", %progbits
5450
.balign 0x1000

0 commit comments

Comments
 (0)