Skip to content

Commit 7d66e84

Browse files
committedJul 5, 2017
[ELF] Introduce Thunk reuse compatibility
On ARM the interworking thunks are only produced for branch instructions that can't be changed into a blx instruction so only Thumb callers would call Thumb thunks and only ARM callers would call ARM thunks. With range extension thunks branch and link instructions may need a Thunk. These instructions can be rewritten as a blx and can use either ARM or Thumb thunks. We introduce an isCompatibleWith() function so that a caller can check if an existing Thunk is compatible before reusing it. Differential Revision: https://reviews.llvm.org/D34035 llvm-svn: 307132
1 parent 5aedebf commit 7d66e84

File tree

3 files changed

+31
-1
lines changed

3 files changed

+31
-1
lines changed
 

‎lld/ELF/Relocations.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1050,7 +1050,7 @@ ThunkSection *ThunkCreator::addThunkSection(OutputSection *OS,
10501050
std::pair<Thunk *, bool> ThunkCreator::getThunk(SymbolBody &Body,
10511051
uint32_t Type) {
10521052
auto res = ThunkedSymbols.insert({&Body, nullptr});
1053-
if (res.second)
1053+
if (res.second || !res.first->second->isCompatibleWith(Type))
10541054
res.first->second = addThunk(Type, Body);
10551055
return std::make_pair(res.first->second, res.second);
10561056
}

‎lld/ELF/Thunks.cpp

+26
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ class ARMV7ABSLongThunk final : public Thunk {
5757
uint32_t size() const override { return 12; }
5858
void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
5959
void addSymbols(ThunkSection &IS) override;
60+
bool isCompatibleWith(uint32_t RelocType) const override;
6061
};
6162

6263
class ARMV7PILongThunk final : public Thunk {
@@ -66,6 +67,7 @@ class ARMV7PILongThunk final : public Thunk {
6667
uint32_t size() const override { return 16; }
6768
void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
6869
void addSymbols(ThunkSection &IS) override;
70+
bool isCompatibleWith(uint32_t RelocType) const override;
6971
};
7072

7173
class ThumbV7ABSLongThunk final : public Thunk {
@@ -77,6 +79,7 @@ class ThumbV7ABSLongThunk final : public Thunk {
7779
uint32_t size() const override { return 10; }
7880
void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
7981
void addSymbols(ThunkSection &IS) override;
82+
bool isCompatibleWith(uint32_t RelocType) const override;
8083
};
8184

8285
class ThumbV7PILongThunk final : public Thunk {
@@ -88,6 +91,7 @@ class ThumbV7PILongThunk final : public Thunk {
8891
uint32_t size() const override { return 12; }
8992
void writeTo(uint8_t *Buf, ThunkSection &IS) const override;
9093
void addSymbols(ThunkSection &IS) override;
94+
bool isCompatibleWith(uint32_t RelocType) const override;
9195
};
9296

9397
// MIPS LA25 thunk
@@ -128,6 +132,11 @@ void ARMV7ABSLongThunk::addSymbols(ThunkSection &IS) {
128132
addSyntheticLocal("$a", STT_NOTYPE, Offset, 0, &IS);
129133
}
130134

135+
bool ARMV7ABSLongThunk::isCompatibleWith(uint32_t RelocType) const {
136+
// Thumb branch relocations can't use BLX
137+
return RelocType != R_ARM_THM_JUMP19 && RelocType != R_ARM_THM_JUMP24;
138+
}
139+
131140
void ThumbV7ABSLongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
132141
const uint8_t Data[] = {
133142
0x40, 0xf2, 0x00, 0x0c, // movw ip, :lower16:S
@@ -147,6 +156,12 @@ void ThumbV7ABSLongThunk::addSymbols(ThunkSection &IS) {
147156
addSyntheticLocal("$t", STT_NOTYPE, Offset, 0, &IS);
148157
}
149158

159+
bool ThumbV7ABSLongThunk::isCompatibleWith(uint32_t RelocType) const {
160+
// ARM branch relocations can't use BLX
161+
return RelocType != R_ARM_JUMP24 && RelocType != R_ARM_PC24 &&
162+
RelocType != R_ARM_PLT32;
163+
}
164+
150165
void ARMV7PILongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
151166
const uint8_t Data[] = {
152167
0xf0, 0xcf, 0x0f, 0xe3, // P: movw ip,:lower16:S - (P + (L1-P) +8)
@@ -168,6 +183,11 @@ void ARMV7PILongThunk::addSymbols(ThunkSection &IS) {
168183
addSyntheticLocal("$a", STT_NOTYPE, Offset, 0, &IS);
169184
}
170185

186+
bool ARMV7PILongThunk::isCompatibleWith(uint32_t RelocType) const {
187+
// Thumb branch relocations can't use BLX
188+
return RelocType != R_ARM_THM_JUMP19 && RelocType != R_ARM_THM_JUMP24;
189+
}
190+
171191
void ThumbV7PILongThunk::writeTo(uint8_t *Buf, ThunkSection &IS) const {
172192
const uint8_t Data[] = {
173193
0x4f, 0xf6, 0xf4, 0x7c, // P: movw ip,:lower16:S - (P + (L1-P) + 4)
@@ -189,6 +209,12 @@ void ThumbV7PILongThunk::addSymbols(ThunkSection &IS) {
189209
addSyntheticLocal("$t", STT_NOTYPE, Offset, 0, &IS);
190210
}
191211

212+
bool ThumbV7PILongThunk::isCompatibleWith(uint32_t RelocType) const {
213+
// ARM branch relocations can't use BLX
214+
return RelocType != R_ARM_JUMP24 && RelocType != R_ARM_PC24 &&
215+
RelocType != R_ARM_PLT32;
216+
}
217+
192218
// Write MIPS LA25 thunk code to call PIC function from the non-PIC one.
193219
void MipsThunk::writeTo(uint8_t *Buf, ThunkSection &) const {
194220
uint64_t S = Destination.getVA();

‎lld/ELF/Thunks.h

+4
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ class Thunk {
4141
// a branch and fall through to the first Symbol in the Target.
4242
virtual InputSection *getTargetInputSection() const { return nullptr; }
4343

44+
// To reuse a Thunk the caller as identified by the RelocType must be
45+
// compatible with it.
46+
virtual bool isCompatibleWith(uint32_t RelocType) const { return true; }
47+
4448
// The alignment requirement for this Thunk, defaults to the size of the
4549
// typical code section alignment.
4650
const SymbolBody &Destination;

0 commit comments

Comments
 (0)
Please sign in to comment.