diff options
Diffstat (limited to 'lld/ELF/Arch/Hexagon.cpp')
| -rw-r--r-- | lld/ELF/Arch/Hexagon.cpp | 47 |
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) { |
