diff options
Diffstat (limited to 'lld/ELF/Arch/RISCV.cpp')
| -rw-r--r-- | lld/ELF/Arch/RISCV.cpp | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp index dc2ab97..5ed89e4 100644 --- a/lld/ELF/Arch/RISCV.cpp +++ b/lld/ELF/Arch/RISCV.cpp @@ -8,6 +8,7 @@ #include "InputFiles.h" #include "OutputSections.h" +#include "RelocScan.h" #include "Symbols.h" #include "SyntheticSections.h" #include "Target.h" @@ -38,6 +39,10 @@ public: void writePltHeader(uint8_t *buf) const override; void writePlt(uint8_t *buf, const Symbol &sym, uint64_t pltEntryAddr) const override; + template <class ELFT, class RelTy> + void scanSectionImpl(InputSectionBase &, Relocs<RelTy>); + template <class ELFT> void scanSection1(InputSectionBase &); + void scanSection(InputSectionBase &) override; RelType getDynRel(RelType type) const override; RelExpr getRelExpr(RelType type, const Symbol &s, const uint8_t *loc) const override; @@ -278,6 +283,7 @@ RelExpr RISCV::getRelExpr(const RelType type, const Symbol &s, const uint8_t *loc) const { switch (type) { case R_RISCV_NONE: + case R_RISCV_VENDOR: return R_NONE; case R_RISCV_32: case R_RISCV_64: @@ -1476,3 +1482,54 @@ void elf::mergeRISCVAttributesSections(Ctx &ctx) { } void elf::setRISCVTargetInfo(Ctx &ctx) { ctx.target.reset(new RISCV(ctx)); } + +template <class ELFT, class RelTy> +void RISCV::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels) { + RelocScan rs(ctx, &sec); + // Many relocations end up in sec.relocations. + sec.relocations.reserve(rels.size()); + + StringRef rvVendor; + for (auto it = rels.begin(); it != rels.end(); ++it) { + RelType type = it->getType(false); + uint32_t symIndex = it->getSymbol(false); + Symbol &sym = sec.getFile<ELFT>()->getSymbol(symIndex); + const uint8_t *loc = sec.content().data() + it->r_offset; + + if (type == R_RISCV_VENDOR) { + if (!rvVendor.empty()) + Err(ctx) << getErrorLoc(ctx, loc) + << "malformed consecutive R_RISCV_VENDOR relocations"; + rvVendor = sym.getName(); + continue; + } else if (!rvVendor.empty()) { + Err(ctx) << getErrorLoc(ctx, loc) + << "unknown vendor-specific relocation (" << type.v + << ") in namespace '" << rvVendor << "' against symbol '" << &sym + << "'"; + rvVendor = ""; + continue; + } + + rs.scan<ELFT, RelTy>(it, type, rs.getAddend<ELFT>(*it, type)); + } + + // Sort relocations by offset for more efficient searching for + // R_RISCV_PCREL_HI20. + llvm::stable_sort(sec.relocs(), + [](const Relocation &lhs, const Relocation &rhs) { + return lhs.offset < rhs.offset; + }); +} + +template <class ELFT> void RISCV::scanSection1(InputSectionBase &sec) { + const RelsOrRelas<ELFT> rels = sec.template relsOrRelas<ELFT>(); + if (rels.areRelocsCrel()) + scanSectionImpl<ELFT>(sec, rels.crels); + else + scanSectionImpl<ELFT>(sec, rels.relas); +} + +void RISCV::scanSection(InputSectionBase &sec) { + invokeELFT(scanSection1, sec); +} |
