Skip to content

Commit b4c74c0

Browse files
committed
ELF: Do not rewrite IFUNC relocations to point to PLT if no GOT/PLT needed.
This enables the use of IFUNC to implement custom relocation types, such as the PAuth relocation types that will be introduced in a subsequent pull request. TODO: - Add tests. - Fix broken tests. Pull Request: llvm#133531
1 parent d8f654b commit b4c74c0

File tree

3 files changed

+12
-4
lines changed

3 files changed

+12
-4
lines changed

lld/ELF/Relocations.cpp

+5-3
Original file line numberDiff line numberDiff line change
@@ -869,7 +869,8 @@ static void addRelativeReloc(Ctx &ctx, InputSectionBase &isec,
869869
// relrDyn sections don't support odd offsets. Also, relrDyn sections
870870
// don't store the addend values, so we must write it to the relocated
871871
// address.
872-
if (part.relrDyn && isec.addralign >= 2 && offsetInSec % 2 == 0) {
872+
if (part.relrDyn && isec.addralign >= 2 && offsetInSec % 2 == 0 &&
873+
!sym.isGnuIFunc()) {
873874
isec.addReloc({expr, type, offsetInSec, addend, &sym});
874875
if (shard)
875876
part.relrDyn->relocsVec[parallel::getThreadIndex()].push_back(
@@ -1107,8 +1108,6 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset,
11071108
}
11081109
} else if (needsPlt(expr)) {
11091110
sym.setFlags(NEEDS_PLT);
1110-
} else if (LLVM_UNLIKELY(isIfunc)) {
1111-
sym.setFlags(HAS_DIRECT_RELOC);
11121111
}
11131112

11141113
// If the relocation is known to be a link-time constant, we know no dynamic
@@ -1194,6 +1193,9 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset,
11941193
}
11951194
}
11961195

1196+
if (LLVM_UNLIKELY(isIfunc && !needsGot(expr) && !needsPlt(expr)))
1197+
sym.setFlags(HAS_DIRECT_RELOC);
1198+
11971199
// When producing an executable, we can perform copy relocations (for
11981200
// STT_OBJECT) and canonical PLT (for STT_FUNC) if sym is defined by a DSO.
11991201
// Copy relocations/canonical PLT entries are unsupported for

lld/ELF/Symbols.h

+2
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ void printTraceSymbol(const Symbol &sym, StringRef name);
4242
enum {
4343
NEEDS_GOT = 1 << 0,
4444
NEEDS_PLT = 1 << 1,
45+
// True if this is an ifunc with a direct relocation that cannot be
46+
// represented as a RELATIVE relocation.
4547
HAS_DIRECT_RELOC = 1 << 2,
4648
// True if this symbol needs a canonical PLT entry, or (during
4749
// postScanRelocations) a copy relocation.

lld/ELF/SyntheticSections.cpp

+5-1
Original file line numberDiff line numberDiff line change
@@ -1707,9 +1707,13 @@ void RelocationBaseSection::mergeRels() {
17071707
}
17081708

17091709
void RelocationBaseSection::partitionRels() {
1710+
const RelType relativeRel = ctx.target->relativeRel;
1711+
const RelType iRelativeRel = ctx.target->iRelativeRel;
1712+
for (auto &r : relocs)
1713+
if (r.type == relativeRel && r.sym->isGnuIFunc())
1714+
r.type = iRelativeRel;
17101715
if (!combreloc)
17111716
return;
1712-
const RelType relativeRel = ctx.target->relativeRel;
17131717
numRelativeRelocs =
17141718
std::stable_partition(relocs.begin(), relocs.end(),
17151719
[=](auto &r) { return r.type == relativeRel; }) -

0 commit comments

Comments
 (0)