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
7 changes: 5 additions & 2 deletions lld/ELF/Relocations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1644,8 +1644,11 @@ void elf::postScanRelocations(Ctx &ctx) {
}

assert(ctx.symAux.size() == 1);
for (Symbol *sym : ctx.symtab->getSymbols())
fn(*sym);
// When RISCV vendor-specific relocations are used in the GOT, a new marker
// symbol may be introduced during this iteration, so we have to use an
// invalidation-safe loop.
for (size_t i = 0; i < ctx.symtab->getSymbols().size(); ++i)
fn(*ctx.symtab->getSymbols()[i]);

// Local symbols may need the aforementioned non-preemptible ifunc and GOT
// handling. They don't need regular PLT.
Expand Down
54 changes: 54 additions & 0 deletions lld/ELF/SyntheticSections.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
//===----------------------------------------------------------------------===//

#include "SyntheticSections.h"
#include "Arch/RISCVInternalRelocations.h"
#include "Config.h"
#include "DWARF.h"
#include "EhFrame.h"
Expand Down Expand Up @@ -1703,6 +1704,18 @@ void DynamicReloc::finalize(Ctx &ctx, SymbolTableBaseSection *symt) {
isFinal = true; // Catch errors
}

size_t RelocationBaseSection::getSize() const {
size_t size = relocs.size() * entsize;
if (ctx.arg.emachine == EM_RISCV) {
for (const auto &reloc : relocs) {
if (reloc.type.v & INTERNAL_RISCV_VENDOR_MASK) {
size += entsize;
}
}
}
return size;
}

void RelocationBaseSection::computeRels() {
SymbolTableBaseSection *symTab = getPartition(ctx).dynSymTab.get();
parallelForEach(relocs, [&ctx = ctx, symTab](DynamicReloc &rel) {
Expand All @@ -1725,6 +1738,47 @@ void RelocationBaseSection::computeRels() {
return std::tie(a.r_sym, a.r_offset) < std::tie(b.r_sym, b.r_offset);
});
}
// Insert R_RISCV_VENDOR relocations very late, so that it doesn't interfere
// with relocation sorting above.
if (ctx.arg.emachine == EM_RISCV) {
SmallVector<DynamicReloc, 0> processedRelocs;
processedRelocs.reserve(relocs.size());
for (auto reloc : relocs) {
auto vendorString = getRISCVVendorString(reloc.type);
if (vendorString) {
// Symbol *vendorSym = ctx.symtab->find(*vendorString);
auto *vendorSym = ctx.symtab->find(*vendorString);
if (!vendorSym || !vendorSym->isDefined()) {
vendorSym = ctx.symtab->addSymbol(Defined{ctx, nullptr, *vendorString,
STB_GLOBAL, STV_HIDDEN,
STT_NOTYPE, 0, 0, nullptr});
symTab->addSymbol(vendorSym);
}
vendorSym->isUsedInRegularObj = true;
vendorSym->isExported = true;
processedRelocs.push_back({llvm::ELF::R_RISCV_VENDOR, reloc.inputSec,
reloc.offsetInSec, true, *vendorSym, 0,
R_ABS});
processedRelocs.back().finalize(ctx, symTab);
}

reloc.type.v &= ~INTERNAL_RISCV_VENDOR_MASK;
processedRelocs.push_back(reloc);
}

relocs = std::move(processedRelocs);
}
}

void RelocationBaseSection::maybeAddRISCVendorRelocation(
const DynamicReloc &reloc, SmallVector<DynamicReloc, 0> &outRelocs) {
auto riscvVendorString = getRISCVVendorString(reloc.type);
if (ctx.arg.emachine == llvm::ELF::EM_RISCV && riscvVendorString) {
Comment on lines +1775 to +1776
Copy link
Member

Choose a reason for hiding this comment

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

It might be clearer to push the riscvVendorString declaration inside the if - so that there's no overhead for other architectures.

Symbol &vendorSym = *ctx.symtab->addSymbol(Defined{
ctx, ctx.internalFile, *riscvVendorString, llvm::ELF::STB_GLOBAL,
llvm::ELF::STV_HIDDEN, llvm::ELF::STT_NOTYPE, 0, 0, nullptr});
vendorSym.isUsedInRegularObj = true;
}
}

template <class ELFT>
Expand Down
7 changes: 6 additions & 1 deletion lld/ELF/SyntheticSections.h
Original file line number Diff line number Diff line change
Expand Up @@ -478,6 +478,7 @@ class RelocationBaseSection : public SyntheticSection {
/// This overload can be used if the addends are written directly instead of
/// using relocations on the input section (e.g. MipsGotSection::writeTo()).
template <bool shard = false> void addReloc(const DynamicReloc &reloc) {
maybeAddRISCVendorRelocation(reloc, relocs);
relocs.push_back(reloc);
}
/// Add a dynamic relocation against \p sym with an optional addend.
Expand Down Expand Up @@ -518,7 +519,7 @@ class RelocationBaseSection : public SyntheticSection {
return !relocs.empty() ||
llvm::any_of(relocsVec, [](auto &v) { return !v.empty(); });
}
size_t getSize() const override { return relocs.size() * this->entsize; }
size_t getSize() const override;
size_t getRelativeRelocCount() const { return numRelativeRelocs; }
void mergeRels();
void partitionRels();
Expand All @@ -529,6 +530,8 @@ class RelocationBaseSection : public SyntheticSection {

protected:
void computeRels();
void maybeAddRISCVendorRelocation(const DynamicReloc &reloc,
SmallVector<DynamicReloc, 0> &outRelocs);
// Used when parallel relocation scanning adds relocations. The elements
// will be moved into relocs by mergeRel().
SmallVector<SmallVector<DynamicReloc, 0>, 0> relocsVec;
Expand All @@ -538,6 +541,8 @@ class RelocationBaseSection : public SyntheticSection {

template <>
inline void RelocationBaseSection::addReloc<true>(const DynamicReloc &reloc) {
maybeAddRISCVendorRelocation(reloc,
relocsVec[llvm::parallel::getThreadIndex()]);
relocsVec[llvm::parallel::getThreadIndex()].push_back(reloc);
}

Expand Down
Loading