Skip to content

Commit 03f2efd

Browse files
jrtc27resistor
authored andcommitted
[NFCI][ELF] Move undef weak capability code to align more with integer case
Burying it in addCapabilityRelocation isn't quite right, since we don't actually want a dynamic relocation, which the name would suggest (like addRelativeReloc). This will also help for Morello LLD, which has its own addMorelloCapabilityRelocation that would otherwise need to duplicate (a subset of) the code in question.
1 parent 9d1606d commit 03f2efd

File tree

3 files changed

+66
-35
lines changed

3 files changed

+66
-35
lines changed

lld/ELF/Arch/Cheri.cpp

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -766,15 +766,18 @@ uint64_t MipsCheriCapTableSection::assignIndices(uint64_t startIndex,
766766
RelocationBaseSection *dynRelSec = it.second.usedInCallExpr
767767
? ctx.in.relaPlt.get()
768768
: ctx.mainPart->relaDyn.get();
769-
addCapabilityRelocation<ELFT>(
770-
ctx, targetSym, elfCapabilityReloc, this, off, R_CHERI_CAPABILITY, 0,
771-
it.second.usedInCallExpr,
772-
[&]() {
773-
return ("\n>>> referenced by " + refName + "\n>>> first used in " +
774-
it.second.firstUse->verboseToString(ctx))
775-
.str();
776-
},
777-
dynRelSec);
769+
if (!targetSym->isPreemptible && targetSym->isUndefWeak())
770+
addNullDerivedCapability(ctx, *targetSym, *this, off, 0);
771+
else
772+
addCapabilityRelocation<ELFT>(
773+
ctx, targetSym, elfCapabilityReloc, this, off, R_CHERI_CAPABILITY, 0,
774+
it.second.usedInCallExpr,
775+
[&]() {
776+
return ("\n>>> referenced by " + refName + "\n>>> first used in " +
777+
it.second.firstUse->verboseToString(ctx))
778+
.str();
779+
},
780+
dynRelSec);
778781
}
779782
assert(assignedSmallIndexes + assignedLargeIndexes == entries.size());
780783
return assignedSmallIndexes + assignedLargeIndexes;
@@ -1030,26 +1033,10 @@ void addCapabilityRelocation(
10301033
}
10311034
}
10321035

1033-
// Non-preemptible undef weak symbols are link-time constants
1034-
if (sym && !sym->isPreemptible && sym->isUndefWeak()) {
1035-
if (ctx.arg.isLE) {
1036-
sec->addReloc({R_ABS, ctx.target->symbolicRel, offset, addend, sym});
1037-
sec->addReloc({R_ADDEND, ctx.target->symbolicRel,
1038-
offset + ctx.arg.wordsize, 0, sym});
1039-
} else {
1040-
sec->addReloc({R_ADDEND, ctx.target->symbolicRel, offset, 0, sym});
1041-
sec->addReloc({R_ABS, ctx.target->symbolicRel, offset + ctx.arg.wordsize,
1042-
addend, sym});
1043-
}
1044-
// Handle deprecated CHERI-256
1045-
if (ctx.target->getCapabilitySize() == ctx.arg.wordsize * 4) {
1046-
sec->addReloc({R_ADDEND, ctx.target->symbolicRel,
1047-
offset + 2 * ctx.arg.wordsize, 0, sym});
1048-
sec->addReloc({R_ADDEND, ctx.target->symbolicRel,
1049-
offset + 3 * ctx.arg.wordsize, 0, sym});
1050-
}
1051-
return;
1052-
}
1036+
// Non-preemptible undef weak symbols are link-time constants and should use
1037+
// addNullDerivedCapability
1038+
if (sym)
1039+
assert(sym->isPreemptible || !sym->isUndefWeak());
10531040

10541041
// local cap relocs don't need a Elf relocation with a full symbol lookup:
10551042
if (capRelocMode == CapRelocsMode::ElfReloc) {
@@ -1121,6 +1108,28 @@ void addCapabilityRelocation(
11211108
}
11221109
}
11231110

1111+
void addNullDerivedCapability(Ctx &ctx, Symbol &sym, InputSectionBase &sec,
1112+
uint64_t offset, int64_t addend) {
1113+
// Only non-preemptible undef weak symbols are link-time constants
1114+
assert(!sym.isPreemptible && sym.isUndefWeak());
1115+
if (ctx.arg.isLE) {
1116+
sec.addReloc({R_ABS, ctx.target->symbolicRel, offset, addend, &sym});
1117+
sec.addReloc({R_ADDEND, ctx.target->symbolicRel, offset + ctx.arg.wordsize,
1118+
0, &sym});
1119+
} else {
1120+
sec.addReloc({R_ADDEND, ctx.target->symbolicRel, offset, 0, &sym});
1121+
sec.addReloc({R_ABS, ctx.target->symbolicRel, offset + ctx.arg.wordsize,
1122+
addend, &sym});
1123+
}
1124+
// Handle deprecated CHERI-256
1125+
if (ctx.target->getCapabilitySize() == ctx.arg.wordsize * 4) {
1126+
sec.addReloc({R_ADDEND, ctx.target->symbolicRel,
1127+
offset + 2 * ctx.arg.wordsize, 0, &sym});
1128+
sec.addReloc({R_ADDEND, ctx.target->symbolicRel,
1129+
offset + 3 * ctx.arg.wordsize, 0, &sym});
1130+
}
1131+
}
1132+
11241133
} // namespace elf
11251134
} // namespace lld
11261135

lld/ELF/Arch/Cheri.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,9 @@ void addCapabilityRelocation(
364364
int64_t addend, bool isCallExpr,
365365
llvm::function_ref<std::string()> referencedBy,
366366
RelocationBaseSection *dynRelSec = nullptr);
367+
368+
void addNullDerivedCapability(Ctx &ctx, Symbol &sym, InputSectionBase &sec,
369+
uint64_t offset, int64_t addend);
367370
} // namespace elf
368371
} // namespace lld
369372

lld/ELF/Relocations.cpp

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -962,8 +962,11 @@ void elf::addGotEntry(Ctx &ctx, Symbol &sym) {
962962
}
963963

964964
// Otherwise, the value is either a link-time constant or the load base
965-
// plus a constant. For CHERI it always requires run-time initialisation.
966-
if (ctx.arg.isCheriAbi) {
965+
// plus a constant. For CHERI it always requires run-time initialisation,
966+
// with the exception of undef weak symbols.
967+
if (ctx.arg.isCheriAbi && sym.isUndefWeak())
968+
addNullDerivedCapability(ctx, sym, *ctx.in.got, off, 0);
969+
else if (ctx.arg.isCheriAbi) {
967970
invokeELFT(addCapabilityRelocation, ctx, &sym, *ctx.target->cheriCapRel,
968971
ctx.in.got.get(), off, R_CHERI_CAPABILITY, 0, false,
969972
[] { return ""; });
@@ -1057,9 +1060,10 @@ bool RelocationScanner::isStaticLinkTimeConstant(RelExpr e, RelType type,
10571060
// Cheri capability relocations are never static link time constants since
10581061
// even if we know the exact value of the capability we can't write it since
10591062
// there is no way to store the tag bit
1060-
// TODO: for undef weak -> 0 (or other untagged values) it actually is okay
1063+
// The exception is for non-preemptible undef weak symbols, which are
1064+
// NULL-derived constants.
10611065
if (e == R_CHERI_CAPABILITY)
1062-
return false;
1066+
return !sym.isPreemptible && sym.isUndefWeak();
10631067

10641068
// These never do, except if the entire file is position dependent or if
10651069
// only the low bits are used.
@@ -1211,8 +1215,23 @@ void RelocationScanner::processAux(RelExpr expr, RelType type, uint64_t offset,
12111215
// If the relocation is known to be a link-time constant, we know no dynamic
12121216
// relocation will be created, pass the control to relocateAlloc() or
12131217
// relocateNonAlloc() to resolve it.
1214-
if (isStaticLinkTimeConstant(expr, type, sym, offset)) {
1215-
sec->addReloc({expr, type, offset, addend, &sym});
1218+
//
1219+
// The behavior of an undefined weak reference is implementation defined. For
1220+
// non-link-time constants, we resolve relocations statically (let
1221+
// relocate{,Non}Alloc() resolve them) for -no-pie and try producing dynamic
1222+
// relocations for -pie and -shared.
1223+
//
1224+
// The general expectation of -no-pie static linking is that there is no
1225+
// dynamic relocation (except IRELATIVE). Emitting dynamic relocations for
1226+
// -shared matches the spirit of its -z undefs default. -pie has freedom on
1227+
// choices, and we choose dynamic relocations to be consistent with the
1228+
// handling of GOT-generating relocations.
1229+
if (isStaticLinkTimeConstant(expr, type, sym, offset) ||
1230+
(!ctx.arg.isPic && sym.isUndefWeak())) {
1231+
if (expr == R_CHERI_CAPABILITY)
1232+
addNullDerivedCapability(ctx, sym, *sec, offset, addend);
1233+
else
1234+
sec->addReloc({expr, type, offset, addend, &sym});
12161235
return;
12171236
}
12181237

0 commit comments

Comments
 (0)