@@ -322,7 +322,8 @@ void CheriCapRelocsSection::addCapReloc(CheriCapRelocLocation loc,
322322 auto sourceMsg = [&]() -> std::string {
323323 return sourceSymbol ? verboseToString (sourceSymbol) : loc.toString ();
324324 };
325- if (target.sym ()->isUndefined () && !target.sym ()->isUndefWeak ()) {
325+ if (isa<Symbol *>(target.symOrSec ) && target.sym ()->isUndefined () &&
326+ !target.sym ()->isUndefWeak ()) {
326327 std::string msg =
327328 " cap_reloc against undefined symbol: " + toString (*target.sym ()) +
328329 " \n >>> referenced by " + sourceMsg ();
@@ -348,6 +349,7 @@ void CheriCapRelocsSection::addCapReloc(CheriCapRelocLocation loc,
348349 return ; // Maybe happens with vtables?
349350 }
350351 if (targetNeedsDynReloc) {
352+ assert (isa<Symbol *>(target.symOrSec ));
351353 bool relativeToLoadAddress = false ;
352354 // The addend is not used as the offset into the capability here, as we
353355 // have the offset field in the __cap_relocs for that. The Addend
@@ -384,6 +386,9 @@ void CheriCapRelocsSection::addCapReloc(CheriCapRelocLocation loc,
384386template <typename ELFT>
385387static uint64_t getTargetSize (const CheriCapRelocLocation &location,
386388 const SymbolAndOffset &target) {
389+ if (InputSectionBase *isec = dyn_cast<InputSectionBase *>(target.symOrSec ))
390+ return isec->getSize ();
391+
387392 uint64_t targetSize = target.sym ()->getSize ();
388393 if (targetSize > INT_MAX) {
389394 error (" Insanely large symbol size for " + target.verboseToString () +
@@ -510,9 +515,24 @@ void CheriCapRelocsSection::writeToImpl(uint8_t *buf) {
510515 location.section ->getOutputSection ()->addr + outSecOffset;
511516
512517 // The target VA is the base address of the capability, so symbol + 0
513- uint64_t targetVA = realTarget.sym ()->getVA (0 );
514- bool preemptibleDynReloc =
515- reloc.needsDynReloc && realTarget.sym ()->isPreemptible ;
518+ uint64_t targetVA;
519+ bool isPreemptible, isFunc, isTls;
520+ OutputSection *os;
521+ if (Symbol *s = dyn_cast<Symbol *>(realTarget.symOrSec )) {
522+ targetVA = realTarget.sym ()->getVA (0 );
523+ isPreemptible = reloc.needsDynReloc && realTarget.sym ()->isPreemptible ;
524+ isFunc = s->isFunc ();
525+ isTls = s->isTls ();
526+ os = s->getOutputSection ();
527+ } else {
528+ InputSectionBase *isec = cast<InputSectionBase *>(realTarget.symOrSec );
529+ targetVA = isec->getVA (0 );
530+ isPreemptible = false ;
531+ isFunc = (isec->flags & SHF_EXECINSTR) != 0 ;
532+ isTls = isec->type == STT_TLS;
533+ os = isec->getOutputSection ();
534+ }
535+ bool preemptibleDynReloc = reloc.needsDynReloc && isPreemptible;
516536 uint64_t targetSize = 0 ;
517537 if (preemptibleDynReloc) {
518538 // If we have a relocation against a preemptible symbol (even in the
@@ -529,10 +549,10 @@ void CheriCapRelocsSection::writeToImpl(uint8_t *buf) {
529549 uint64_t targetOffset = reloc.capabilityOffset + realTarget.offset ;
530550 uint64_t permissions = 0 ;
531551 // Fow now Function implies ReadOnly so don't add the flag
532- if (realTarget. sym ()-> isFunc () ) {
552+ if (isFunc) {
533553 permissions |= CaptablePermissions<ELFT>::function;
534- } else if (auto os = realTarget. sym ()-> getOutputSection () ) {
535- assert (!realTarget. sym ()-> isTls () );
554+ } else if (os ) {
555+ assert (!isTls);
536556 // if ((OS->getPhdrFlags() & PF_W) == 0) {
537557 if (((os->flags & SHF_WRITE) == 0 ) || isRelroSection (os)) {
538558 permissions |= CaptablePermissions<ELFT>::readOnly;
@@ -1047,13 +1067,14 @@ void MipsCheriCapTableMappingSection::writeTo(uint8_t *buf) {
10471067}
10481068
10491069template <typename ELFT>
1050- void addCapabilityRelocation (Symbol *sym, RelType type, InputSectionBase *sec,
1051- uint64_t offset, RelExpr expr, int64_t addend,
1052- bool isCallExpr,
1053- llvm::function_ref<std::string()> referencedBy,
1054- RelocationBaseSection *dynRelSec) {
1070+ void addCapabilityRelocation (
1071+ llvm::PointerUnion<Symbol *, InputSectionBase *> symOrSec, RelType type,
1072+ InputSectionBase *sec, uint64_t offset, RelExpr expr, int64_t addend,
1073+ bool isCallExpr, llvm::function_ref<std::string()> referencedBy,
1074+ RelocationBaseSection *dynRelSec) {
1075+ Symbol *sym = dyn_cast<Symbol *>(symOrSec);
10551076 assert (expr == R_CHERI_CAPABILITY);
1056- if (sec->name == " .gcc_except_table" && sym->isPreemptible ) {
1077+ if (sec->name == " .gcc_except_table" && sym && sym ->isPreemptible ) {
10571078 // We previously had an ugly workaround here to create a hidden alias for
10581079 // relocations in the exception table, but this has since been fixed in
10591080 // the compiler. Add an explicit error here in case someone tries to
@@ -1067,14 +1088,15 @@ void addCapabilityRelocation(Symbol *sym, RelType type, InputSectionBase *sec,
10671088 // Emit either the legacy __cap_relocs section or a R_CHERI_CAPABILITY reloc
10681089 // For local symbols we can also emit the untagged capability bits and
10691090 // instruct csu/rtld to run CBuildCap
1070- CapRelocsMode capRelocMode = sym->isPreemptible
1091+ CapRelocsMode capRelocMode = sym && sym ->isPreemptible
10711092 ? config->preemptibleCapRelocsMode
10721093 : config->localCapRelocsMode ;
10731094 bool needTrampoline = false ;
10741095 // In the PLT ABI (and fndesc?) we have to use an elf relocation for function
10751096 // pointers to ensure that the runtime linker adds the required trampolines
10761097 // that sets $cgp:
1077- if (!isCallExpr && config->emachine == llvm::ELF::EM_MIPS && sym->isFunc ()) {
1098+ if (!isCallExpr && config->emachine == llvm::ELF::EM_MIPS && sym &&
1099+ sym->isFunc ()) {
10781100 if (!lld::elf::hasDynamicLinker ()) {
10791101 // In static binaries we do not need PLT stubs for function pointers since
10801102 // all functions share the same $cgp
@@ -1083,26 +1105,26 @@ void addCapabilityRelocation(Symbol *sym, RelType type, InputSectionBase *sec,
10831105 if (config->verboseCapRelocs )
10841106 message (" Do not need function pointer trampoline for " +
10851107 toString (*sym) + " in static binary" );
1086- needTrampoline = false ;
10871108 } else if (in.mipsAbiFlags ) {
10881109 auto abi = static_cast <MipsAbiFlagsSection<ELFT> &>(*in.mipsAbiFlags )
10891110 .getCheriAbiVariant ();
10901111 if (abi && (*abi == llvm::ELF::DF_MIPS_CHERI_ABI_PLT ||
10911112 *abi == llvm::ELF::DF_MIPS_CHERI_ABI_FNDESC))
10921113 needTrampoline = true ;
10931114 }
1094- }
10951115
1096- if (needTrampoline) {
1097- capRelocMode = CapRelocsMode::ElfReloc;
1098- assert (capRelocMode == config->preemptibleCapRelocsMode );
1099- if (config->verboseCapRelocs )
1100- message (" Using trampoline for function pointer against " +
1101- verboseToString (sym));
1116+ if (needTrampoline) {
1117+ capRelocMode = CapRelocsMode::ElfReloc;
1118+ assert (capRelocMode == config->preemptibleCapRelocsMode );
1119+ if (config->verboseCapRelocs )
1120+ message (" Using trampoline for function pointer against " +
1121+ verboseToString (sym));
1122+ }
11021123 }
11031124
11041125 // local cap relocs don't need a Elf relocation with a full symbol lookup:
11051126 if (capRelocMode == CapRelocsMode::ElfReloc) {
1127+ assert (sym && " ELF relocs should not be used against sections" );
11061128 assert ((sym->isPreemptible || needTrampoline) &&
11071129 " ELF relocs should not be used for non-preemptible symbols" );
11081130 assert ((!sym->isLocal () || needTrampoline) &&
@@ -1157,10 +1179,10 @@ void addCapabilityRelocation(Symbol *sym, RelType type, InputSectionBase *sec,
11571179
11581180 } else if (capRelocMode == CapRelocsMode::Legacy) {
11591181 if (config->relativeCapRelocsOnly ) {
1160- assert (!sym->isPreemptible );
1182+ assert (!sym || !sym ->isPreemptible );
11611183 }
1162- in.capRelocs ->addCapReloc <ELFT>({sec, offset}, {sym , 0u },
1163- sym->isPreemptible , addend);
1184+ in.capRelocs ->addCapReloc <ELFT>({sec, offset}, {symOrSec , 0u },
1185+ sym && sym ->isPreemptible , addend);
11641186 } else {
11651187 assert (config->localCapRelocsMode == CapRelocsMode::CBuildCap);
11661188 error (" CBuildCap method not implemented yet!" );
@@ -1171,14 +1193,18 @@ void addCapabilityRelocation(Symbol *sym, RelType type, InputSectionBase *sec,
11711193} // namespace lld
11721194
11731195template void lld::elf::addCapabilityRelocation<ELF32LE>(
1174- Symbol *, RelType, InputSectionBase *, uint64_t , RelExpr, int64_t , bool ,
1196+ llvm::PointerUnion<Symbol *, InputSectionBase *>, RelType,
1197+ InputSectionBase *, uint64_t , RelExpr, int64_t , bool ,
11751198 llvm::function_ref<std::string()>, RelocationBaseSection *);
11761199template void lld::elf::addCapabilityRelocation<ELF32BE>(
1177- Symbol *, RelType, InputSectionBase *, uint64_t , RelExpr, int64_t , bool ,
1200+ llvm::PointerUnion<Symbol *, InputSectionBase *>, RelType,
1201+ InputSectionBase *, uint64_t , RelExpr, int64_t , bool ,
11781202 llvm::function_ref<std::string()>, RelocationBaseSection *);
11791203template void lld::elf::addCapabilityRelocation<ELF64LE>(
1180- Symbol *, RelType, InputSectionBase *, uint64_t , RelExpr, int64_t , bool ,
1204+ llvm::PointerUnion<Symbol *, InputSectionBase *>, RelType,
1205+ InputSectionBase *, uint64_t , RelExpr, int64_t , bool ,
11811206 llvm::function_ref<std::string()>, RelocationBaseSection *);
11821207template void lld::elf::addCapabilityRelocation<ELF64BE>(
1183- Symbol *, RelType, InputSectionBase *, uint64_t , RelExpr, int64_t , bool ,
1208+ llvm::PointerUnion<Symbol *, InputSectionBase *>, RelType,
1209+ InputSectionBase *, uint64_t , RelExpr, int64_t , bool ,
11841210 llvm::function_ref<std::string()>, RelocationBaseSection *);
0 commit comments