diff options
Diffstat (limited to 'lld/ELF/Arch/SPARCV9.cpp')
-rw-r--r-- | lld/ELF/Arch/SPARCV9.cpp | 83 |
1 files changed, 66 insertions, 17 deletions
diff --git a/lld/ELF/Arch/SPARCV9.cpp b/lld/ELF/Arch/SPARCV9.cpp index 08ef52099de9..f137c21fc898 100644 --- a/lld/ELF/Arch/SPARCV9.cpp +++ b/lld/ELF/Arch/SPARCV9.cpp @@ -16,9 +16,8 @@ using namespace llvm; using namespace llvm::support::endian; using namespace llvm::ELF; - -namespace lld { -namespace elf { +using namespace lld; +using namespace lld::elf; namespace { class SPARCV9 final : public TargetInfo { @@ -28,7 +27,8 @@ public: const uint8_t *loc) const override; void writePlt(uint8_t *buf, const Symbol &sym, uint64_t pltEntryAddr) 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; }; } // namespace @@ -54,6 +54,14 @@ RelExpr SPARCV9::getRelExpr(RelType type, const Symbol &s, case R_SPARC_UA32: case R_SPARC_64: case R_SPARC_UA64: + case R_SPARC_H44: + case R_SPARC_M44: + case R_SPARC_L44: + case R_SPARC_HH22: + case R_SPARC_HM10: + case R_SPARC_LM22: + case R_SPARC_HI22: + case R_SPARC_LO10: return R_ABS; case R_SPARC_PC10: case R_SPARC_PC22: @@ -68,6 +76,9 @@ RelExpr SPARCV9::getRelExpr(RelType type, const Symbol &s, return R_PLT_PC; case R_SPARC_NONE: return R_NONE; + case R_SPARC_TLS_LE_HIX22: + case R_SPARC_TLS_LE_LOX10: + return R_TLS; default: error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) + ") against symbol " + toString(s)); @@ -75,38 +86,45 @@ RelExpr SPARCV9::getRelExpr(RelType type, const Symbol &s, } } -void SPARCV9::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { - switch (type) { +void SPARCV9::relocate(uint8_t *loc, const Relocation &rel, + uint64_t val) const { + switch (rel.type) { case R_SPARC_32: case R_SPARC_UA32: // V-word32 - checkUInt(loc, val, 32, type); + checkUInt(loc, val, 32, rel); write32be(loc, val); break; case R_SPARC_DISP32: // V-disp32 - checkInt(loc, val, 32, type); + checkInt(loc, val, 32, rel); write32be(loc, val); break; case R_SPARC_WDISP30: case R_SPARC_WPLT30: // V-disp30 - checkInt(loc, val, 32, type); + checkInt(loc, val, 32, rel); write32be(loc, (read32be(loc) & ~0x3fffffff) | ((val >> 2) & 0x3fffffff)); break; case R_SPARC_22: // V-imm22 - checkUInt(loc, val, 22, type); + checkUInt(loc, val, 22, rel); write32be(loc, (read32be(loc) & ~0x003fffff) | (val & 0x003fffff)); break; case R_SPARC_GOT22: case R_SPARC_PC22: + case R_SPARC_LM22: // T-imm22 write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 10) & 0x003fffff)); break; + case R_SPARC_HI22: + // V-imm22 + checkUInt(loc, val >> 10, 22, rel); + write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 10) & 0x003fffff)); + break; case R_SPARC_WDISP19: // V-disp19 - checkInt(loc, val, 21, type); + checkInt(loc, val, 21, rel); write32be(loc, (read32be(loc) & ~0x0007ffff) | ((val >> 2) & 0x0007ffff)); break; case R_SPARC_GOT10: @@ -114,11 +132,45 @@ void SPARCV9::relocateOne(uint8_t *loc, RelType type, uint64_t val) const { // T-simm10 write32be(loc, (read32be(loc) & ~0x000003ff) | (val & 0x000003ff)); break; + case R_SPARC_LO10: + // T-simm13 + write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x000003ff)); + break; case R_SPARC_64: case R_SPARC_UA64: // V-xword64 write64be(loc, val); break; + case R_SPARC_HH22: + // V-imm22 + checkUInt(loc, val >> 42, 22, rel); + write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 42) & 0x003fffff)); + break; + case R_SPARC_HM10: + // T-simm13 + write32be(loc, (read32be(loc) & ~0x00001fff) | ((val >> 32) & 0x000003ff)); + break; + case R_SPARC_H44: + // V-imm22 + checkUInt(loc, val >> 22, 22, rel); + write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 22) & 0x003fffff)); + break; + case R_SPARC_M44: + // T-imm10 + write32be(loc, (read32be(loc) & ~0x000003ff) | ((val >> 12) & 0x000003ff)); + break; + case R_SPARC_L44: + // T-imm13 + write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x00000fff)); + break; + case R_SPARC_TLS_LE_HIX22: + // T-imm22 + write32be(loc, (read32be(loc) & ~0x003fffff) | ((~val >> 10) & 0x003fffff)); + break; + case R_SPARC_TLS_LE_LOX10: + // T-simm13 + write32be(loc, (read32be(loc) & ~0x00001fff) | (val & 0x000003ff) | 0x1C00); + break; default: llvm_unreachable("unknown relocation"); } @@ -139,14 +191,11 @@ void SPARCV9::writePlt(uint8_t *buf, const Symbol & /*sym*/, memcpy(buf, pltData, sizeof(pltData)); uint64_t off = pltEntryAddr - in.plt->getVA(); - relocateOne(buf, R_SPARC_22, off); - relocateOne(buf + 4, R_SPARC_WDISP19, -(off + 4 - pltEntrySize)); + relocateNoSym(buf, R_SPARC_22, off); + relocateNoSym(buf + 4, R_SPARC_WDISP19, -(off + 4 - pltEntrySize)); } -TargetInfo *getSPARCV9TargetInfo() { +TargetInfo *elf::getSPARCV9TargetInfo() { static SPARCV9 target; return ⌖ } - -} // namespace elf -} // namespace lld |