diff options
Diffstat (limited to 'lld/ELF/Arch/Hexagon.cpp')
-rw-r--r-- | lld/ELF/Arch/Hexagon.cpp | 66 |
1 files changed, 44 insertions, 22 deletions
diff --git a/lld/ELF/Arch/Hexagon.cpp b/lld/ELF/Arch/Hexagon.cpp index 106bc9bab5bd..7740ce9a71e0 100644 --- a/lld/ELF/Arch/Hexagon.cpp +++ b/lld/ELF/Arch/Hexagon.cpp @@ -19,9 +19,8 @@ using namespace llvm; using namespace llvm::object; using namespace llvm::support::endian; using namespace llvm::ELF; - -namespace lld { -namespace elf { +using namespace lld; +using namespace lld::elf; namespace { class Hexagon final : public TargetInfo { @@ -31,7 +30,8 @@ public: RelExpr getRelExpr(RelType type, const Symbol &s, const uint8_t *loc) const override; RelType getDynRel(RelType type) const override; - void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override; + void relocate(uint8_t *loc, const Relocation &rel, + uint64_t val) const override; void writePltHeader(uint8_t *buf) const override; void writePlt(uint8_t *buf, const Symbol &sym, uint64_t pltEntryAddr) const override; @@ -55,6 +55,8 @@ Hexagon::Hexagon() { defaultMaxPageSize = 0x10000; noneRel = R_HEX_NONE; tlsGotRel = R_HEX_TPREL_32; + tlsModuleIndexRel = R_HEX_DTPMOD_32; + tlsOffsetRel = R_HEX_DTPREL_32; } uint32_t Hexagon::calcEFlags() const { @@ -102,6 +104,7 @@ RelExpr Hexagon::getRelExpr(RelType type, const Symbol &s, case R_HEX_32_6_X: case R_HEX_HI16: case R_HEX_LO16: + case R_HEX_DTPREL_32: return R_ABS; case R_HEX_B9_PCREL: case R_HEX_B13_PCREL: @@ -115,12 +118,19 @@ RelExpr Hexagon::getRelExpr(RelType type, const Symbol &s, case R_HEX_PLT_B22_PCREL: case R_HEX_B22_PCREL_X: case R_HEX_B32_PCREL_X: + case R_HEX_GD_PLT_B22_PCREL: + case R_HEX_GD_PLT_B22_PCREL_X: + case R_HEX_GD_PLT_B32_PCREL_X: return R_PLT_PC; case R_HEX_IE_32_6_X: case R_HEX_IE_16_X: case R_HEX_IE_HI16: case R_HEX_IE_LO16: return R_GOT; + case R_HEX_GD_GOT_11_X: + case R_HEX_GD_GOT_16_X: + case R_HEX_GD_GOT_32_6_X: + return R_TLSGD_GOTPLT; case R_HEX_GOTREL_11_X: case R_HEX_GOTREL_16_X: case R_HEX_GOTREL_32_6_X: @@ -152,6 +162,13 @@ RelExpr Hexagon::getRelExpr(RelType type, const Symbol &s, } } +static bool isDuplex(uint32_t insn) { + // Duplex forms have a fixed mask and parse bits 15:14 are always + // zero. Non-duplex insns will always have at least one bit set in the + // parse field. + return (0xC000 & insn) == 0; +} + static uint32_t findMaskR6(uint32_t insn) { // There are (arguably too) many relocation masks for the DSP's // R_HEX_6_X type. The table below is used to select the correct mask @@ -176,10 +193,7 @@ static uint32_t findMaskR6(uint32_t insn) { {0xd7000000, 0x006020e0}, {0xd8000000, 0x006020e0}, {0xdb000000, 0x006020e0}, {0xdf000000, 0x006020e0}}; - // Duplex forms have a fixed mask and parse bits 15:14 are always - // zero. Non-duplex insns will always have at least one bit set in the - // parse field. - if ((0xC000 & insn) == 0x0) + if (isDuplex(insn)) return 0x03f00000; for (InstructionMask i : r6) @@ -215,6 +229,9 @@ static uint32_t findMaskR16(uint32_t insn) { if ((0xff000000 & insn) == 0xb0000000) return 0x0fe03fe0; + if (isDuplex(insn)) + return 0x03f00000; + error("unrecognized instruction for R_HEX_16_X relocation: 0x" + utohexstr(insn)); return 0; @@ -222,8 +239,9 @@ static uint32_t findMaskR16(uint32_t insn) { static void or32le(uint8_t *p, int32_t v) { write32le(p, read32le(p) | v); } -void Hexagon::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { - switch (type) { +void Hexagon::relocate(uint8_t *loc, const Relocation &rel, + uint64_t val) const { + switch (rel.type) { case R_HEX_NONE: break; case R_HEX_6_PCREL_X: @@ -240,6 +258,7 @@ void Hexagon::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { or32le(loc, applyMask(0x00203fe0, val & 0x3f)); break; case R_HEX_11_X: + case R_HEX_GD_GOT_11_X: case R_HEX_IE_GOT_11_X: case R_HEX_GOT_11_X: case R_HEX_GOTREL_11_X: @@ -252,6 +271,7 @@ void Hexagon::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { case R_HEX_16_X: // These relocs only have 6 effective bits. case R_HEX_IE_16_X: case R_HEX_IE_GOT_16_X: + case R_HEX_GD_GOT_16_X: case R_HEX_GOT_16_X: case R_HEX_GOTREL_16_X: case R_HEX_TPREL_16_X: @@ -262,9 +282,11 @@ void Hexagon::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { break; case R_HEX_32: case R_HEX_32_PCREL: + case R_HEX_DTPREL_32: or32le(loc, val); break; case R_HEX_32_6_X: + case R_HEX_GD_GOT_32_6_X: case R_HEX_GOT_32_6_X: case R_HEX_GOTREL_32_6_X: case R_HEX_IE_GOT_32_6_X: @@ -273,32 +295,35 @@ void Hexagon::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { or32le(loc, applyMask(0x0fff3fff, val >> 6)); break; case R_HEX_B9_PCREL: - checkInt(loc, val, 11, type); + checkInt(loc, val, 11, rel); or32le(loc, applyMask(0x003000fe, val >> 2)); break; case R_HEX_B9_PCREL_X: or32le(loc, applyMask(0x003000fe, val & 0x3f)); break; case R_HEX_B13_PCREL: - checkInt(loc, val, 15, type); + checkInt(loc, val, 15, rel); or32le(loc, applyMask(0x00202ffe, val >> 2)); break; case R_HEX_B15_PCREL: - checkInt(loc, val, 17, type); + checkInt(loc, val, 17, rel); or32le(loc, applyMask(0x00df20fe, val >> 2)); break; case R_HEX_B15_PCREL_X: or32le(loc, applyMask(0x00df20fe, val & 0x3f)); break; case R_HEX_B22_PCREL: + case R_HEX_GD_PLT_B22_PCREL: case R_HEX_PLT_B22_PCREL: - checkInt(loc, val, 22, type); + checkInt(loc, val, 22, rel); or32le(loc, applyMask(0x1ff3ffe, val >> 2)); break; case R_HEX_B22_PCREL_X: + case R_HEX_GD_PLT_B22_PCREL_X: or32le(loc, applyMask(0x1ff3ffe, val & 0x3f)); break; case R_HEX_B32_PCREL_X: + case R_HEX_GD_PLT_B32_PCREL_X: or32le(loc, applyMask(0x0fff3fff, val >> 6)); break; case R_HEX_GOTREL_HI16: @@ -335,8 +360,8 @@ void Hexagon::writePltHeader(uint8_t *buf) const { // Offset from PLT0 to the GOT. uint64_t off = in.gotPlt->getVA() - in.plt->getVA(); - relocateOne(buf, R_HEX_B32_PCREL_X, off); - relocateOne(buf + 4, R_HEX_6_PCREL_X, off); + relocateNoSym(buf, R_HEX_B32_PCREL_X, off); + relocateNoSym(buf + 4, R_HEX_6_PCREL_X, off); } void Hexagon::writePlt(uint8_t *buf, const Symbol &sym, @@ -350,8 +375,8 @@ void Hexagon::writePlt(uint8_t *buf, const Symbol &sym, memcpy(buf, inst, sizeof(inst)); uint64_t gotPltEntryAddr = sym.getGotPltVA(); - relocateOne(buf, R_HEX_B32_PCREL_X, gotPltEntryAddr - pltEntryAddr); - relocateOne(buf + 4, R_HEX_6_PCREL_X, gotPltEntryAddr - pltEntryAddr); + relocateNoSym(buf, R_HEX_B32_PCREL_X, gotPltEntryAddr - pltEntryAddr); + relocateNoSym(buf + 4, R_HEX_6_PCREL_X, gotPltEntryAddr - pltEntryAddr); } RelType Hexagon::getDynRel(RelType type) const { @@ -360,10 +385,7 @@ RelType Hexagon::getDynRel(RelType type) const { return R_HEX_NONE; } -TargetInfo *getHexagonTargetInfo() { +TargetInfo *elf::getHexagonTargetInfo() { static Hexagon target; return ⌖ } - -} // namespace elf -} // namespace lld |