-
Notifications
You must be signed in to change notification settings - Fork 14.9k
[lld] Add infrastructure for handling RISCV vendor-specific relocations. #159987
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 @@ 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; | ||
|
@@ -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,80 @@ 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) << "found 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; | ||
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); | ||
|
||
// Many relocations end up in sec.relocations. | ||
sec.relocations.reserve(rels.size()); | ||
|
||
// On SystemZ, all sections need to be sorted by r_offset, to allow TLS | ||
// relaxation to be handled correctly - see SystemZ::getTlsGdRelaxSkip. | ||
SmallVector<RelTy, 0> storage; | ||
if (ctx.arg.emachine == EM_S390) | ||
rels = sortRels(rels, storage); | ||
|
||
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 | ||
|
||
// branch-to-branch optimization. | ||
if (is_contained({EM_RISCV, EM_LOONGARCH}, ctx.arg.emachine) || | ||
(ctx.arg.emachine == EM_PPC64 && sec.name == ".toc") || | ||
ctx.arg.branchToBranch) | ||
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 if (rels.areRelocsRel()) | ||
scanSectionImpl<ELFT>(sec, rels.rels); | ||
else | ||
scanSectionImpl<ELFT>(sec, rels.relas); | ||
} | ||
|
||
void RISCV::scanSection(InputSectionBase &sec) { | ||
invokeELFT(scanSection1, sec); | ||
} |
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 | ||
resistor marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
Uh oh!
There was an error while loading. Please reload this page.