Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
13 changes: 13 additions & 0 deletions lld/ELF/Arch/RISCV.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ class RISCV final : public TargetInfo {
RelType getDynRel(RelType type) const override;
RelExpr getRelExpr(RelType type, const Symbol &s,
const uint8_t *loc) const override;
RelExpr getVendorRelExpr(RelType type, const Symbol &s, const uint8_t *loc,
StringRef vendor) const override;
void relocate(uint8_t *loc, const Relocation &rel,
uint64_t val) const override;
void relocateAlloc(InputSectionBase &sec, uint8_t *buf) const override;
Expand Down Expand Up @@ -338,6 +340,8 @@ RelExpr RISCV::getRelExpr(const RelType type, const Symbol &s,
case R_RISCV_SET_ULEB128:
case R_RISCV_SUB_ULEB128:
return RE_RISCV_LEB128;
case R_RISCV_VENDOR:
return R_NONE;
default:
Err(ctx) << getErrorLoc(ctx, loc) << "unknown relocation (" << type.v
<< ") against symbol " << &s;
Expand Down Expand Up @@ -555,6 +559,15 @@ void RISCV::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
}
}

RelExpr RISCV::getVendorRelExpr(const RelType type, const Symbol &s,
const uint8_t *loc, StringRef vendor) const {
// TODO: Dispatch to vendor-specific relocation handling.
Err(ctx) << getErrorLoc(ctx, loc) << "unknown vendor-specific relocation ("
<< type.v << ") in vendor namespace \"" << vendor
<< "\" against symbol " << &s;
return R_NONE;
}

static bool relaxable(ArrayRef<Relocation> relocs, size_t i) {
return i + 1 != relocs.size() && relocs[i + 1].type == R_RISCV_RELAX;
}
Expand Down
20 changes: 18 additions & 2 deletions lld/ELF/Relocations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -457,6 +457,7 @@ class RelocationScanner {
Ctx &ctx;
InputSectionBase *sec;
OffsetGetter getter;
StringRef rvVendor;

// End of relocations, used by Mips/PPC64.
const void *end = nullptr;
Expand Down Expand Up @@ -1510,13 +1511,25 @@ void RelocationScanner::scanOne(typename Relocs<RelTy>::const_iterator &i) {
++i;
}
}

// Stash the RISCV vendor namespace for the subsequent relocation.
if (LLVM_UNLIKELY(ctx.arg.emachine == EM_RISCV && type == R_RISCV_VENDOR)) {
Copy link
Member

Choose a reason for hiding this comment

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

I am not sure the PR is useful. It adds some stuff that is not testable.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Every new line, except the error path for non-RV targets, is executed when running the included test, and the correctness of the parsing is verified by checking the vendor name in the error message.

rvVendor = sym.getName();
return;
}

// Get an offset in an output section this relocation is applied to.
uint64_t offset = getter.get(ctx, rel.r_offset);
if (offset == uint64_t(-1))
return;

RelExpr expr =
ctx.target->getRelExpr(type, sym, sec->content().data() + offset);
RelExpr expr;
if (LLVM_LIKELY(rvVendor.empty())) {
expr = ctx.target->getRelExpr(type, sym, sec->content().data() + offset);
} else {
expr = ctx.target->getVendorRelExpr(
type, sym, sec->content().data() + offset, rvVendor);
}
int64_t addend = RelTy::HasAddend
? getAddend<ELFT>(rel)
: ctx.target->getImplicitAddend(
Expand All @@ -1526,6 +1539,9 @@ void RelocationScanner::scanOne(typename Relocs<RelTy>::const_iterator &i) {
else if (ctx.arg.emachine == EM_PPC64 && ctx.arg.isPic && type == R_PPC64_TOC)
addend += getPPC64TocBase(ctx);

// A RISCV vendor namespace only applies to a single relocation.
rvVendor = "";

// Ignore R_*_NONE and other marker relocations.
if (expr == R_NONE)
return;
Expand Down
5 changes: 5 additions & 0 deletions lld/ELF/Target.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,11 @@ class TargetInfo {
virtual uint32_t calcEFlags() const { return 0; }
virtual RelExpr getRelExpr(RelType type, const Symbol &s,
const uint8_t *loc) const = 0;
virtual RelExpr getVendorRelExpr(RelType type, const Symbol &s,
const uint8_t *loc, StringRef vendor) const {
Err(ctx) << "target doesn't support vendor-specific relocations";
return R_NONE;
};
virtual RelType getDynRel(RelType type) const { return 0; }
virtual void writeGotPltHeader(uint8_t *buf) const {}
virtual void writeGotHeader(uint8_t *buf) const {}
Expand Down
16 changes: 16 additions & 0 deletions lld/test/ELF/riscv-vendor-relocations.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# 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_CUSTOM255, TARGET
1:
nop

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