Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions lld/ELF/Arch/RISCV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#include "InputFiles.h"
#include "OutputSections.h"
#include "RelocScan.h"
#include "Symbols.h"
#include "SyntheticSections.h"
#include "Target.h"
Expand Down Expand Up @@ -38,6 +39,10 @@ class RISCV final : public TargetInfo {
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;
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -1476,3 +1482,71 @@ void elf::mergeRISCVAttributesSections(Ctx &ctx) {
}

void elf::setRISCVTargetInfo(Ctx &ctx) { ctx.target.reset(new RISCV(ctx)); }

class RISCVRelocScan : public RelocScan {
public:
StringRef rvVendor;

RISCVRelocScan(Ctx &ctx, InputSectionBase *sec = nullptr)
: RelocScan(ctx, sec) {}
template <class ELFT, class RelTy>
void scan(typename Relocs<RelTy>::const_iterator &it, RelType type,
int64_t addend);
};

template <class ELFT, class RelTy>
void RISCVRelocScan::scan(typename Relocs<RelTy>::const_iterator &it,
RelType type, int64_t addend) {
const RelTy &rel = *it;
uint32_t symIndex = rel.getSymbol(false);
Symbol &sym = sec->getFile<ELFT>()->getSymbol(symIndex);

if (type == R_RISCV_VENDOR) {
if (!rvVendor.empty())
Err(ctx) << getErrorLoc(ctx, sec->content().data() + it->r_offset)
<< "malformed consecutive R_RISCV_VENDOR relocations";
rvVendor = sym.getName();
return;
} else if (!rvVendor.empty()) {
Err(ctx) << getErrorLoc(ctx, sec->content().data() + it->r_offset)
<< "unknown vendor-specific relocation (" << type.v
<< ") in vendor namespace \"" << rvVendor << "\" against symbol "
<< &sym;
rvVendor = "";
return;
}

RelocScan::scan<ELFT, RelTy>(it, type, addend);
}

template <class ELFT, class RelTy>
void RISCV::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels) {
RISCVRelocScan rs(ctx, &sec);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

RISCVRelocScan is unnecessary. Just define rvVendor in this function and make the whole logic in this function.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

// Many relocations end up in sec.relocations.
sec.relocations.reserve(rels.size());

for (auto it = rels.begin(); it != rels.end(); ++it) {
auto type = it->getType(false);
rs.scan<ELFT, RelTy>(it, type, rs.getAddend<ELFT>(*it, type));
}

// Sort relocations by offset for more efficient searching for
// R_RISCV_PCREL_HI20, ALIGN relocations, R_PPC64_ADDR64 and the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"R_PPC64_ADDR64 and the branch-to-branch optimization" are not relevant and should be removed.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

// branch-to-branch optimization.
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);
}
18 changes: 18 additions & 0 deletions lld/test/riscv-vendor-relocations.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# RUN: llvm-mc -triple riscv32 %s -filetype=obj -o %t.o
# RUN: not ld.lld -pie %t.o -o /dev/null 2>&1 | FileCheck %s

.option exact

.global TARGET
TARGET:
nop

.global INVALID_VENDOR
.reloc 1f, R_RISCV_VENDOR, INVALID_VENDOR+0
.reloc 1f, R_RISCV_VENDOR, INVALID_VENDOR+0
.reloc 1f, R_RISCV_CUSTOM255, TARGET
1:
nop

# CHECK: error: {{.*}} malformed consecutive R_RISCV_VENDOR relocations
# CHECK: error: {{.*}} unknown vendor-specific relocation (255) in vendor namespace "INVALID_VENDOR" against symbol TARGET