@@ -333,7 +333,8 @@ void CheriCapRelocsSection::addCapReloc(CheriCapRelocLocation loc,
333333 auto sourceMsg = [&]() -> std::string {
334334 return sourceSymbol ? verboseToString (ctx, sourceSymbol) : loc.toString (ctx);
335335 };
336- if (target.sym ()->isUndefined () && !target.sym ()->isUndefWeak ()) {
336+ if (isa<Symbol *>(target.symOrSec ) && target.sym ()->isUndefined () &&
337+ !target.sym ()->isUndefWeak ()) {
337338 auto diag = (ctx.arg .unresolvedSymbols == UnresolvedPolicy::ReportError)
338339 ? Err (ctx)
339340 : (errorHandler ().fatalWarnings ) ? Msg (ctx)
@@ -362,6 +363,7 @@ void CheriCapRelocsSection::addCapReloc(CheriCapRelocLocation loc,
362363 return ; // Maybe happens with vtables?
363364 }
364365 if (targetNeedsDynReloc) {
366+ assert (isa<Symbol *>(target.symOrSec ));
365367 bool relativeToLoadAddress = false ;
366368 // The addend is not used as the offset into the capability here, as we
367369 // have the offset field in the __cap_relocs for that. The Addend
@@ -398,6 +400,9 @@ void CheriCapRelocsSection::addCapReloc(CheriCapRelocLocation loc,
398400template <typename ELFT>
399401static uint64_t getTargetSize (Ctx &ctx, const CheriCapRelocLocation &location,
400402 const SymbolAndOffset &target) {
403+ if (InputSectionBase *isec = dyn_cast<InputSectionBase *>(target.symOrSec ))
404+ return isec->getSize ();
405+
401406 uint64_t targetSize = target.sym ()->getSize (ctx);
402407 if (targetSize > INT_MAX) {
403408 error (" Insanely large symbol size for " + target.verboseToString (ctx) +
@@ -523,9 +528,24 @@ void CheriCapRelocsSection::writeToImpl(uint8_t *buf) {
523528 location.section ->getOutputSection ()->addr + outSecOffset;
524529
525530 // The target VA is the base address of the capability, so symbol + 0
526- uint64_t targetVA = realTarget.sym ()->getVA (ctx, 0 );
527- bool preemptibleDynReloc =
528- reloc.needsDynReloc && realTarget.sym ()->isPreemptible ;
531+ uint64_t targetVA;
532+ bool isPreemptible, isFunc, isTls;
533+ OutputSection *os;
534+ if (Symbol *s = dyn_cast<Symbol *>(realTarget.symOrSec )) {
535+ targetVA = realTarget.sym ()->getVA (ctx, 0 );
536+ isPreemptible = reloc.needsDynReloc && realTarget.sym ()->isPreemptible ;
537+ isFunc = s->isFunc ();
538+ isTls = s->isTls ();
539+ os = s->getOutputSection ();
540+ } else {
541+ InputSectionBase *isec = cast<InputSectionBase *>(realTarget.symOrSec );
542+ targetVA = isec->getVA (0 );
543+ isPreemptible = false ;
544+ isFunc = (isec->flags & SHF_EXECINSTR) != 0 ;
545+ isTls = isec->type == STT_TLS;
546+ os = isec->getOutputSection ();
547+ }
548+ bool preemptibleDynReloc = reloc.needsDynReloc && isPreemptible;
529549 uint64_t targetSize = 0 ;
530550 if (preemptibleDynReloc) {
531551 // If we have a relocation against a preemptible symbol (even in the
@@ -543,10 +563,10 @@ void CheriCapRelocsSection::writeToImpl(uint8_t *buf) {
543563 uint64_t targetOffset = reloc.capabilityOffset + realTarget.offset ;
544564 uint64_t permissions = 0 ;
545565 // Fow now Function implies ReadOnly so don't add the flag
546- if (realTarget. sym ()-> isFunc () ) {
566+ if (isFunc) {
547567 permissions |= CaptablePermissions<ELFT>::function;
548- } else if (auto os = realTarget. sym ()-> getOutputSection () ) {
549- assert (!realTarget. sym ()-> isTls () );
568+ } else if (os ) {
569+ assert (!isTls);
550570 // if ((OS->getPhdrFlags() & PF_W) == 0) {
551571 if (((os->flags & SHF_WRITE) == 0 ) || isRelroSection (ctx, os)) {
552572 permissions |= CaptablePermissions<ELFT>::readOnly;
@@ -1080,15 +1100,16 @@ static bool isSymIncludedInDynsym(Ctx &ctx, const Symbol &sym) {
10801100 (ctx.arg .exportDynamic && (sym.isUsedInRegularObj || !sym.ltoCanOmit ));
10811101}
10821102
1083-
10841103template <typename ELFT>
1085- void addCapabilityRelocation (Ctx &ctx, Symbol *sym, RelType type,
1086- InputSectionBase *sec, uint64_t offset,
1087- RelExpr expr, int64_t addend, bool isCallExpr,
1088- llvm::function_ref<std::string()> referencedBy,
1089- RelocationBaseSection *dynRelSec) {
1104+ void addCapabilityRelocation (
1105+ Ctx &ctx, llvm::PointerUnion<Symbol *, InputSectionBase *> symOrSec,
1106+ RelType type, InputSectionBase *sec, uint64_t offset, RelExpr expr,
1107+ int64_t addend, bool isCallExpr,
1108+ llvm::function_ref<std::string()> referencedBy,
1109+ RelocationBaseSection *dynRelSec) {
1110+ Symbol *sym = dyn_cast<Symbol *>(symOrSec);
10901111 assert (expr == R_CHERI_CAPABILITY);
1091- if (sec->name == " .gcc_except_table" && sym->isPreemptible ) {
1112+ if (sec->name == " .gcc_except_table" && sym && sym ->isPreemptible ) {
10921113 // We previously had an ugly workaround here to create a hidden alias for
10931114 // relocations in the exception table, but this has since been fixed in
10941115 // the compiler. Add an explicit error here in case someone tries to
@@ -1102,14 +1123,15 @@ void addCapabilityRelocation(Ctx &ctx, Symbol *sym, RelType type,
11021123 // Emit either the legacy __cap_relocs section or a R_CHERI_CAPABILITY reloc
11031124 // For local symbols we can also emit the untagged capability bits and
11041125 // instruct csu/rtld to run CBuildCap
1105- CapRelocsMode capRelocMode = sym->isPreemptible
1126+ CapRelocsMode capRelocMode = sym && sym ->isPreemptible
11061127 ? ctx.arg .preemptibleCapRelocsMode
11071128 : ctx.arg .localCapRelocsMode ;
11081129 bool needTrampoline = false ;
11091130 // In the PLT ABI (and fndesc?) we have to use an elf relocation for function
11101131 // pointers to ensure that the runtime linker adds the required trampolines
11111132 // that sets $cgp:
1112- if (!isCallExpr && ctx.arg .emachine == llvm::ELF::EM_MIPS && sym->isFunc ()) {
1133+ if (!isCallExpr && ctx.arg .emachine == llvm::ELF::EM_MIPS && sym &&
1134+ sym->isFunc ()) {
11131135 if (!lld::elf::hasDynamicLinker (ctx)) {
11141136 // In static binaries we do not need PLT stubs for function pointers since
11151137 // all functions share the same $cgp
@@ -1118,26 +1140,26 @@ void addCapabilityRelocation(Ctx &ctx, Symbol *sym, RelType type,
11181140 if (ctx.arg .verboseCapRelocs )
11191141 Msg (ctx) << " Do not need function pointer trampoline for "
11201142 << toStr (ctx, *sym) << " in static binary" ;
1121- needTrampoline = false ;
11221143 } else if (ctx.in .mipsAbiFlags ) {
11231144 auto abi = static_cast <MipsAbiFlagsSection<ELFT> &>(*ctx.in .mipsAbiFlags )
11241145 .getCheriAbiVariant ();
11251146 if (abi && (*abi == llvm::ELF::DF_MIPS_CHERI_ABI_PLT ||
11261147 *abi == llvm::ELF::DF_MIPS_CHERI_ABI_FNDESC))
11271148 needTrampoline = true ;
11281149 }
1129- }
11301150
1131- if (needTrampoline) {
1132- capRelocMode = CapRelocsMode::ElfReloc;
1133- assert (capRelocMode == ctx.arg .preemptibleCapRelocsMode );
1134- if (ctx.arg .verboseCapRelocs )
1135- message (" Using trampoline for function pointer against " +
1136- verboseToString (ctx, sym));
1151+ if (needTrampoline) {
1152+ capRelocMode = CapRelocsMode::ElfReloc;
1153+ assert (capRelocMode == ctx.arg .preemptibleCapRelocsMode );
1154+ if (ctx.arg .verboseCapRelocs )
1155+ message (" Using trampoline for function pointer against " +
1156+ verboseToString (ctx, sym));
1157+ }
11371158 }
11381159
11391160 // local cap relocs don't need a Elf relocation with a full symbol lookup:
11401161 if (capRelocMode == CapRelocsMode::ElfReloc) {
1162+ assert (sym && " ELF relocs should not be used against sections" );
11411163 assert ((sym->isPreemptible || needTrampoline) &&
11421164 " ELF relocs should not be used for non-preemptible symbols" );
11431165 assert ((!sym->isLocal () || needTrampoline) &&
@@ -1195,10 +1217,10 @@ void addCapabilityRelocation(Ctx &ctx, Symbol *sym, RelType type,
11951217
11961218 } else if (capRelocMode == CapRelocsMode::Legacy) {
11971219 if (ctx.arg .relativeCapRelocsOnly ) {
1198- assert (!sym->isPreemptible );
1220+ assert (!sym || !sym ->isPreemptible );
11991221 }
1200- ctx.in .capRelocs ->addCapReloc <ELFT>({sec, offset}, {sym , 0u },
1201- sym->isPreemptible , addend);
1222+ ctx.in .capRelocs ->addCapReloc <ELFT>({sec, offset}, {symOrSec , 0u },
1223+ sym && sym ->isPreemptible , addend);
12021224 } else {
12031225 assert (ctx.arg .localCapRelocsMode == CapRelocsMode::CBuildCap);
12041226 error (" CBuildCap method not implemented yet!" );
@@ -1209,14 +1231,18 @@ void addCapabilityRelocation(Ctx &ctx, Symbol *sym, RelType type,
12091231} // namespace lld
12101232
12111233template void lld::elf::addCapabilityRelocation<ELF32LE>(
1212- Ctx &ctx, Symbol *, RelType, InputSectionBase *, uint64_t , RelExpr, int64_t ,
1213- bool , llvm::function_ref<std::string()>, RelocationBaseSection *);
1234+ Ctx &ctx, llvm::PointerUnion<Symbol *, InputSectionBase *>, RelType,
1235+ InputSectionBase *, uint64_t , RelExpr, int64_t , bool ,
1236+ llvm::function_ref<std::string()>, RelocationBaseSection *);
12141237template void lld::elf::addCapabilityRelocation<ELF32BE>(
1215- Ctx &ctx, Symbol *, RelType, InputSectionBase *, uint64_t , RelExpr, int64_t ,
1216- bool , llvm::function_ref<std::string()>, RelocationBaseSection *);
1238+ Ctx &ctx, llvm::PointerUnion<Symbol *, InputSectionBase *>, RelType,
1239+ InputSectionBase *, uint64_t , RelExpr, int64_t , bool ,
1240+ llvm::function_ref<std::string()>, RelocationBaseSection *);
12171241template void lld::elf::addCapabilityRelocation<ELF64LE>(
1218- Ctx &ctx, Symbol *, RelType, InputSectionBase *, uint64_t , RelExpr, int64_t ,
1219- bool , llvm::function_ref<std::string()>, RelocationBaseSection *);
1242+ Ctx &ctx, llvm::PointerUnion<Symbol *, InputSectionBase *>, RelType,
1243+ InputSectionBase *, uint64_t , RelExpr, int64_t , bool ,
1244+ llvm::function_ref<std::string()>, RelocationBaseSection *);
12201245template void lld::elf::addCapabilityRelocation<ELF64BE>(
1221- Ctx &ctx, Symbol *, RelType, InputSectionBase *, uint64_t , RelExpr, int64_t ,
1222- bool , llvm::function_ref<std::string()>, RelocationBaseSection *);
1246+ Ctx &ctx, llvm::PointerUnion<Symbol *, InputSectionBase *>, RelType,
1247+ InputSectionBase *, uint64_t , RelExpr, int64_t , bool ,
1248+ llvm::function_ref<std::string()>, RelocationBaseSection *);
0 commit comments