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.cpp66
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