aboutsummaryrefslogtreecommitdiff
path: root/lld/ELF/Arch/RISCV.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lld/ELF/Arch/RISCV.cpp')
-rw-r--r--lld/ELF/Arch/RISCV.cpp57
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);
+}