summaryrefslogtreecommitdiff
path: root/lld/ELF/Arch/Hexagon.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/Arch/Hexagon.cpp')
-rw-r--r--lld/ELF/Arch/Hexagon.cpp47
1 files changed, 47 insertions, 0 deletions
diff --git a/lld/ELF/Arch/Hexagon.cpp b/lld/ELF/Arch/Hexagon.cpp
index 479131a24dcf..9b33e78731c9 100644
--- a/lld/ELF/Arch/Hexagon.cpp
+++ b/lld/ELF/Arch/Hexagon.cpp
@@ -11,6 +11,7 @@
#include "Symbols.h"
#include "SyntheticSections.h"
#include "Target.h"
+#include "Thunks.h"
#include "lld/Common/ErrorHandler.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/BinaryFormat/ELF.h"
@@ -36,6 +37,10 @@ public:
const uint8_t *loc) const override;
RelType getDynRel(RelType type) const override;
int64_t getImplicitAddend(const uint8_t *buf, RelType type) const override;
+ bool needsThunk(RelExpr expr, RelType type, const InputFile *file,
+ uint64_t branchAddr, const Symbol &s,
+ int64_t a) const override;
+ bool inBranchRange(RelType type, uint64_t src, uint64_t dst) const override;
void relocate(uint8_t *loc, const Relocation &rel,
uint64_t val) const override;
void writePltHeader(uint8_t *buf) const override;
@@ -63,6 +68,8 @@ Hexagon::Hexagon(Ctx &ctx) : TargetInfo(ctx) {
tlsGotRel = R_HEX_TPREL_32;
tlsModuleIndexRel = R_HEX_DTPMOD_32;
tlsOffsetRel = R_HEX_DTPREL_32;
+
+ needsThunks = true;
}
uint32_t Hexagon::calcEFlags() const {
@@ -258,6 +265,46 @@ static uint32_t findMaskR16(Ctx &ctx, uint32_t insn) {
static void or32le(uint8_t *p, int32_t v) { write32le(p, read32le(p) | v); }
+bool Hexagon::inBranchRange(RelType type, uint64_t src, uint64_t dst) const {
+ int64_t offset = dst - src;
+ switch (type) {
+ case llvm::ELF::R_HEX_B22_PCREL:
+ case llvm::ELF::R_HEX_PLT_B22_PCREL:
+ case llvm::ELF::R_HEX_GD_PLT_B22_PCREL:
+ case llvm::ELF::R_HEX_LD_PLT_B22_PCREL:
+ return llvm::isInt<22>(offset >> 2);
+ case llvm::ELF::R_HEX_B15_PCREL:
+ return llvm::isInt<15>(offset >> 2);
+ break;
+ case llvm::ELF::R_HEX_B13_PCREL:
+ return llvm::isInt<13>(offset >> 2);
+ break;
+ case llvm::ELF::R_HEX_B9_PCREL:
+ return llvm::isInt<9>(offset >> 2);
+ default:
+ return true;
+ }
+ llvm_unreachable("unsupported relocation");
+}
+
+bool Hexagon::needsThunk(RelExpr expr, RelType type, const InputFile *file,
+ uint64_t branchAddr, const Symbol &s,
+ int64_t a) const {
+ // Only check branch range for supported branch relocation types
+ switch (type) {
+ case R_HEX_B22_PCREL:
+ case R_HEX_PLT_B22_PCREL:
+ case R_HEX_GD_PLT_B22_PCREL:
+ case R_HEX_LD_PLT_B22_PCREL:
+ case R_HEX_B15_PCREL:
+ case R_HEX_B13_PCREL:
+ case R_HEX_B9_PCREL:
+ return !ctx.target->inBranchRange(type, branchAddr, s.getVA(ctx, a));
+ default:
+ return false;
+ }
+}
+
void Hexagon::relocate(uint8_t *loc, const Relocation &rel,
uint64_t val) const {
switch (rel.type) {