Skip to content

Commit fc46315

Browse files
committed
[lld] Add infrastructure for handling RISCV vendor-specific relocations.
1 parent 90cbc37 commit fc46315

File tree

2 files changed

+99
-0
lines changed

2 files changed

+99
-0
lines changed

lld/ELF/Arch/RISCV.cpp

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
#include "InputFiles.h"
1010
#include "OutputSections.h"
11+
#include "RelocScan.h"
1112
#include "Symbols.h"
1213
#include "SyntheticSections.h"
1314
#include "Target.h"
@@ -38,6 +39,10 @@ class RISCV final : public TargetInfo {
3839
void writePltHeader(uint8_t *buf) const override;
3940
void writePlt(uint8_t *buf, const Symbol &sym,
4041
uint64_t pltEntryAddr) const override;
42+
template <class ELFT, class RelTy>
43+
void scanSectionImpl(InputSectionBase &, Relocs<RelTy>);
44+
template <class ELFT> void scanSection1(InputSectionBase &);
45+
void scanSection(InputSectionBase &) override;
4146
RelType getDynRel(RelType type) const override;
4247
RelExpr getRelExpr(RelType type, const Symbol &s,
4348
const uint8_t *loc) const override;
@@ -278,6 +283,7 @@ RelExpr RISCV::getRelExpr(const RelType type, const Symbol &s,
278283
const uint8_t *loc) const {
279284
switch (type) {
280285
case R_RISCV_NONE:
286+
case R_RISCV_VENDOR:
281287
return R_NONE;
282288
case R_RISCV_32:
283289
case R_RISCV_64:
@@ -1476,3 +1482,80 @@ void elf::mergeRISCVAttributesSections(Ctx &ctx) {
14761482
}
14771483

14781484
void elf::setRISCVTargetInfo(Ctx &ctx) { ctx.target.reset(new RISCV(ctx)); }
1485+
1486+
class RISCVRelocScan : public RelocScan {
1487+
public:
1488+
StringRef rvVendor;
1489+
1490+
RISCVRelocScan(Ctx &ctx, InputSectionBase *sec = nullptr)
1491+
: RelocScan(ctx, sec) {}
1492+
template <class ELFT, class RelTy>
1493+
void scan(typename Relocs<RelTy>::const_iterator &it, RelType type,
1494+
int64_t addend);
1495+
};
1496+
1497+
template <class ELFT, class RelTy>
1498+
void RISCVRelocScan::scan(typename Relocs<RelTy>::const_iterator &it,
1499+
RelType type, int64_t addend) {
1500+
const RelTy &rel = *it;
1501+
uint32_t symIndex = rel.getSymbol(false);
1502+
Symbol &sym = sec->getFile<ELFT>()->getSymbol(symIndex);
1503+
1504+
if (type == R_RISCV_VENDOR) {
1505+
if (!rvVendor.empty())
1506+
Err(ctx) << "found consecutive R_RISCV_VENDOR relocations";
1507+
rvVendor = sym.getName();
1508+
return;
1509+
} else if (!rvVendor.empty()) {
1510+
Err(ctx) << getErrorLoc(ctx, sec->content().data() + it->r_offset)
1511+
<< "unknown vendor-specific relocation (" << type.v
1512+
<< ") in vendor namespace \"" << rvVendor << "\" against symbol "
1513+
<< &sym;
1514+
return;
1515+
}
1516+
1517+
RelocScan::scan<ELFT, RelTy>(it, type, addend);
1518+
}
1519+
1520+
template <class ELFT, class RelTy>
1521+
void RISCV::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels) {
1522+
RISCVRelocScan rs(ctx, &sec);
1523+
// Many relocations end up in sec.relocations.
1524+
sec.relocations.reserve(rels.size());
1525+
1526+
// On SystemZ, all sections need to be sorted by r_offset, to allow TLS
1527+
// relaxation to be handled correctly - see SystemZ::getTlsGdRelaxSkip.
1528+
SmallVector<RelTy, 0> storage;
1529+
if (ctx.arg.emachine == EM_S390)
1530+
rels = sortRels(rels, storage);
1531+
1532+
for (auto it = rels.begin(); it != rels.end(); ++it) {
1533+
auto type = it->getType(false);
1534+
rs.scan<ELFT, RelTy>(it, type, rs.getAddend<ELFT>(*it, type));
1535+
}
1536+
1537+
// Sort relocations by offset for more efficient searching for
1538+
// R_RISCV_PCREL_HI20, ALIGN relocations, R_PPC64_ADDR64 and the
1539+
// branch-to-branch optimization.
1540+
if (is_contained({EM_RISCV, EM_LOONGARCH}, ctx.arg.emachine) ||
1541+
(ctx.arg.emachine == EM_PPC64 && sec.name == ".toc") ||
1542+
ctx.arg.branchToBranch)
1543+
llvm::stable_sort(sec.relocs(),
1544+
[](const Relocation &lhs, const Relocation &rhs) {
1545+
return lhs.offset < rhs.offset;
1546+
});
1547+
}
1548+
1549+
template <class ELFT> void RISCV::scanSection1(InputSectionBase &sec) {
1550+
const RelsOrRelas<ELFT> rels = sec.template relsOrRelas<ELFT>();
1551+
if (rels.areRelocsCrel())
1552+
scanSectionImpl<ELFT>(sec, rels.crels);
1553+
else if (rels.areRelocsRel())
1554+
scanSectionImpl<ELFT>(sec, rels.rels);
1555+
else
1556+
scanSectionImpl<ELFT>(sec, rels.relas);
1557+
}
1558+
1559+
void RISCV::scanSection(InputSectionBase &sec) {
1560+
invokeELFT(scanSection1, sec);
1561+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# RUN: llvm-mc -triple riscv32 %s -filetype=obj -o %t.o
2+
# RUN: not ld.lld -pie %t.o -o /dev/null 2>&1 | FileCheck %s
3+
4+
.option exact
5+
6+
.global TARGET
7+
TARGET:
8+
nop
9+
10+
.global INVALID_VENDOR
11+
.reloc 1f, R_RISCV_VENDOR, INVALID_VENDOR+0
12+
.reloc 1f, R_RISCV_CUSTOM255, TARGET
13+
1:
14+
nop
15+
16+
# CHECK: error: {{.*}} unknown vendor-specific relocation (255) in vendor namespace "INVALID_VENDOR" against symbol TARGET

0 commit comments

Comments
 (0)