Skip to content

Commit afe208c

Browse files
resistorLukacma
authored andcommitted
[lld] Add infrastructure for handling RISCV vendor-specific relocations. (llvm#159987)
1 parent 94fb62a commit afe208c

File tree

2 files changed

+75
-0
lines changed

2 files changed

+75
-0
lines changed

lld/ELF/Arch/RISCV.cpp

Lines changed: 57 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,54 @@ void elf::mergeRISCVAttributesSections(Ctx &ctx) {
14761482
}
14771483

14781484
void elf::setRISCVTargetInfo(Ctx &ctx) { ctx.target.reset(new RISCV(ctx)); }
1485+
1486+
template <class ELFT, class RelTy>
1487+
void RISCV::scanSectionImpl(InputSectionBase &sec, Relocs<RelTy> rels) {
1488+
RelocScan rs(ctx, &sec);
1489+
// Many relocations end up in sec.relocations.
1490+
sec.relocations.reserve(rels.size());
1491+
1492+
StringRef rvVendor;
1493+
for (auto it = rels.begin(); it != rels.end(); ++it) {
1494+
RelType type = it->getType(false);
1495+
uint32_t symIndex = it->getSymbol(false);
1496+
Symbol &sym = sec.getFile<ELFT>()->getSymbol(symIndex);
1497+
const uint8_t *loc = sec.content().data() + it->r_offset;
1498+
1499+
if (type == R_RISCV_VENDOR) {
1500+
if (!rvVendor.empty())
1501+
Err(ctx) << getErrorLoc(ctx, loc)
1502+
<< "malformed consecutive R_RISCV_VENDOR relocations";
1503+
rvVendor = sym.getName();
1504+
continue;
1505+
} else if (!rvVendor.empty()) {
1506+
Err(ctx) << getErrorLoc(ctx, loc)
1507+
<< "unknown vendor-specific relocation (" << type.v
1508+
<< ") in namespace '" << rvVendor << "' against symbol '" << &sym
1509+
<< "'";
1510+
rvVendor = "";
1511+
continue;
1512+
}
1513+
1514+
rs.scan<ELFT, RelTy>(it, type, rs.getAddend<ELFT>(*it, type));
1515+
}
1516+
1517+
// Sort relocations by offset for more efficient searching for
1518+
// R_RISCV_PCREL_HI20.
1519+
llvm::stable_sort(sec.relocs(),
1520+
[](const Relocation &lhs, const Relocation &rhs) {
1521+
return lhs.offset < rhs.offset;
1522+
});
1523+
}
1524+
1525+
template <class ELFT> void RISCV::scanSection1(InputSectionBase &sec) {
1526+
const RelsOrRelas<ELFT> rels = sec.template relsOrRelas<ELFT>();
1527+
if (rels.areRelocsCrel())
1528+
scanSectionImpl<ELFT>(sec, rels.crels);
1529+
else
1530+
scanSectionImpl<ELFT>(sec, rels.relas);
1531+
}
1532+
1533+
void RISCV::scanSection(InputSectionBase &sec) {
1534+
invokeELFT(scanSection1, sec);
1535+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
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_VENDOR, INVALID_VENDOR+0
13+
.reloc 1f, R_RISCV_CUSTOM255, TARGET
14+
1:
15+
nop
16+
17+
# CHECK: error: {{.*}}:(.text+0x4): malformed consecutive R_RISCV_VENDOR relocations
18+
# CHECK: error: {{.*}}:(.text+0x4): unknown vendor-specific relocation (255) in namespace 'INVALID_VENDOR' against symbol 'TARGET'

0 commit comments

Comments
 (0)