summaryrefslogtreecommitdiffstats
path: root/lld/ELF/Thunks.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/Thunks.cpp')
-rw-r--r--lld/ELF/Thunks.cpp51
1 files changed, 26 insertions, 25 deletions
diff --git a/lld/ELF/Thunks.cpp b/lld/ELF/Thunks.cpp
index d1351778604..8d2cdba616a 100644
--- a/lld/ELF/Thunks.cpp
+++ b/lld/ELF/Thunks.cpp
@@ -49,7 +49,7 @@ namespace {
// AArch64 long range Thunks
class AArch64ABSLongThunk final : public Thunk {
public:
- AArch64ABSLongThunk(Symbol &dest) : Thunk(dest) {}
+ AArch64ABSLongThunk(Symbol &dest, int64_t addend) : Thunk(dest, addend) {}
uint32_t size() override { return 16; }
void writeTo(uint8_t *buf) override;
void addSymbols(ThunkSection &isec) override;
@@ -57,7 +57,7 @@ public:
class AArch64ADRPThunk final : public Thunk {
public:
- AArch64ADRPThunk(Symbol &dest) : Thunk(dest) {}
+ AArch64ADRPThunk(Symbol &dest, int64_t addend) : Thunk(dest, addend) {}
uint32_t size() override { return 12; }
void writeTo(uint8_t *buf) override;
void addSymbols(ThunkSection &isec) override;
@@ -73,7 +73,7 @@ public:
// if the target is in range, otherwise it creates a long thunk.
class ARMThunk : public Thunk {
public:
- ARMThunk(Symbol &dest) : Thunk(dest) {}
+ ARMThunk(Symbol &dest) : Thunk(dest, 0) {}
bool getMayUseShortThunk();
uint32_t size() override { return getMayUseShortThunk() ? 4 : sizeLong(); }
@@ -103,7 +103,7 @@ private:
// which has a range of 16MB.
class ThumbThunk : public Thunk {
public:
- ThumbThunk(Symbol &dest) : Thunk(dest) { alignment = 2; }
+ ThumbThunk(Symbol &dest) : Thunk(dest, 0) { alignment = 2; }
bool getMayUseShortThunk();
uint32_t size() override { return getMayUseShortThunk() ? 4 : sizeLong(); }
@@ -209,7 +209,7 @@ public:
// MIPS LA25 thunk
class MipsThunk final : public Thunk {
public:
- MipsThunk(Symbol &dest) : Thunk(dest) {}
+ MipsThunk(Symbol &dest) : Thunk(dest, 0) {}
uint32_t size() override { return 16; }
void writeTo(uint8_t *buf) override;
@@ -220,7 +220,7 @@ public:
// microMIPS R2-R5 LA25 thunk
class MicroMipsThunk final : public Thunk {
public:
- MicroMipsThunk(Symbol &dest) : Thunk(dest) {}
+ MicroMipsThunk(Symbol &dest) : Thunk(dest, 0) {}
uint32_t size() override { return 14; }
void writeTo(uint8_t *buf) override;
@@ -231,7 +231,7 @@ public:
// microMIPS R6 LA25 thunk
class MicroMipsR6Thunk final : public Thunk {
public:
- MicroMipsR6Thunk(Symbol &dest) : Thunk(dest) {}
+ MicroMipsR6Thunk(Symbol &dest) : Thunk(dest, 0) {}
uint32_t size() override { return 12; }
void writeTo(uint8_t *buf) override;
@@ -241,8 +241,11 @@ public:
class PPC32PltCallStub final : public Thunk {
public:
- PPC32PltCallStub(const InputSection &isec, const Relocation &rel, Symbol &dest)
- : Thunk(dest), addend(rel.type == R_PPC_PLTREL24 ? rel.addend : 0),
+ // For R_PPC_PLTREL24, Thunk::addend records the addend which will be used to
+ // decide the offsets in the call stub.
+ PPC32PltCallStub(const InputSection &isec, const Relocation &rel,
+ Symbol &dest)
+ : Thunk(dest, rel.type == R_PPC_PLTREL24 ? rel.addend : 0),
file(isec.file) {}
uint32_t size() override { return 16; }
void writeTo(uint8_t *buf) override;
@@ -250,10 +253,6 @@ public:
bool isCompatibleWith(const InputSection &isec, const Relocation &rel) const override;
private:
- // For R_PPC_PLTREL24, this records the addend, which will be used to decide
- // the offsets in the call stub.
- uint32_t addend;
-
// Records the call site of the call stub.
const InputFile *file;
};
@@ -268,7 +267,7 @@ private:
// 3) Transferring control to the target function through an indirect branch.
class PPC64PltCallStub final : public Thunk {
public:
- PPC64PltCallStub(Symbol &dest) : Thunk(dest) {}
+ PPC64PltCallStub(Symbol &dest) : Thunk(dest, 0) {}
uint32_t size() override { return 20; }
void writeTo(uint8_t *buf) override;
void addSymbols(ThunkSection &isec) override;
@@ -289,7 +288,7 @@ public:
void addSymbols(ThunkSection &isec) override;
protected:
- PPC64LongBranchThunk(Symbol &dest) : Thunk(dest) {}
+ PPC64LongBranchThunk(Symbol &dest) : Thunk(dest, 0) {}
};
class PPC64PILongBranchThunk final : public PPC64LongBranchThunk {
@@ -332,8 +331,8 @@ void Thunk::setOffset(uint64_t newOffset) {
// AArch64 long range Thunks
-static uint64_t getAArch64ThunkDestVA(const Symbol &s) {
- uint64_t v = s.isInPlt() ? s.getPltVA() : s.getVA();
+static uint64_t getAArch64ThunkDestVA(const Symbol &s, int64_t a) {
+ uint64_t v = s.isInPlt() ? s.getPltVA() : s.getVA(a);
return v;
}
@@ -344,7 +343,7 @@ void AArch64ABSLongThunk::writeTo(uint8_t *buf) {
0x00, 0x00, 0x00, 0x00, // L0: .xword S
0x00, 0x00, 0x00, 0x00,
};
- uint64_t s = getAArch64ThunkDestVA(destination);
+ uint64_t s = getAArch64ThunkDestVA(destination, addend);
memcpy(buf, data, sizeof(data));
target->relocateOne(buf + 8, R_AARCH64_ABS64, s);
}
@@ -367,7 +366,7 @@ void AArch64ADRPThunk::writeTo(uint8_t *buf) {
0x10, 0x02, 0x00, 0x91, // add x16, x16, R_AARCH64_ADD_ABS_LO12_NC(Dest)
0x00, 0x02, 0x1f, 0xd6, // br x16
};
- uint64_t s = getAArch64ThunkDestVA(destination);
+ uint64_t s = getAArch64ThunkDestVA(destination, addend);
uint64_t p = getThunkTargetSym()->getVA();
memcpy(buf, data, sizeof(data));
target->relocateOne(buf, R_AARCH64_ADR_PREL_PG_HI21,
@@ -795,16 +794,16 @@ void PPC64LongBranchThunk::addSymbols(ThunkSection &isec) {
isec);
}
-Thunk::Thunk(Symbol &d) : destination(d), offset(0) {}
+Thunk::Thunk(Symbol &d, int64_t a) : destination(d), addend(a), offset(0) {}
Thunk::~Thunk() = default;
-static Thunk *addThunkAArch64(RelType type, Symbol &s) {
+static Thunk *addThunkAArch64(RelType type, Symbol &s, int64_t a) {
if (type != R_AARCH64_CALL26 && type != R_AARCH64_JUMP26)
fatal("unrecognized relocation type");
if (config->picThunk)
- return make<AArch64ADRPThunk>(s);
- return make<AArch64ABSLongThunk>(s);
+ return make<AArch64ADRPThunk>(s, a);
+ return make<AArch64ABSLongThunk>(s, a);
}
// Creates a thunk for Thumb-ARM interworking.
@@ -895,7 +894,8 @@ static Thunk *addThunkMips(RelType type, Symbol &s) {
return make<MipsThunk>(s);
}
-static Thunk *addThunkPPC32(const InputSection &isec, const Relocation &rel, Symbol &s) {
+static Thunk *addThunkPPC32(const InputSection &isec, const Relocation &rel,
+ Symbol &s) {
assert((rel.type == R_PPC_REL24 || rel.type == R_PPC_PLTREL24) &&
"unexpected relocation type for thunk");
return make<PPC32PltCallStub>(isec, rel, s);
@@ -914,9 +914,10 @@ static Thunk *addThunkPPC64(RelType type, Symbol &s) {
Thunk *addThunk(const InputSection &isec, Relocation &rel) {
Symbol &s = *rel.sym;
+ int64_t a = rel.addend;
if (config->emachine == EM_AARCH64)
- return addThunkAArch64(rel.type, s);
+ return addThunkAArch64(rel.type, s, a);
if (config->emachine == EM_ARM)
return addThunkArm(rel.type, s);
OpenPOWER on IntegriCloud