Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -255,6 +255,8 @@ std::vector *OutputSections; void fabricateDefaultCommands(); + std::vector *> + inputSectionRanges(StringRef S); void addOrphanSections(OutputSectionFactory &Factory); void removeEmptyCommands(); void adjustSectionsBeforeSorting(); Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -469,6 +469,28 @@ Opt.Commands = std::move(Commands); } +// For an OutputSection S, return the InputSectionDescriptions that are +// associated with S. The intention is that callers can iterate over +// InputSectionDescription::Sections and insert sections such as Thunks. +std::vector *> +LinkerScript::inputSectionRanges(StringRef S) { + std::vector *> Ranges; + auto OutCmdPos = std::find_if( + Opt.Commands.begin(), Opt.Commands.end(), [=](BaseCommand *Cmd) { + if (auto *OSCmd = dyn_cast(Cmd)) + return (OSCmd->Name == S); + return false; + }); + if (OutCmdPos == Opt.Commands.end()) + return Ranges; + auto *OutCmd = cast(*OutCmdPos); + for (auto *BaseCmd : OutCmd->Commands) { + if (auto *ISD = dyn_cast(BaseCmd)) + Ranges.push_back(&ISD->Sections); + } + return Ranges; +} + // Add sections that didn't match any sections command. void LinkerScript::addOrphanSections(OutputSectionFactory &Factory) { for (InputSectionBase *S : InputSections) { Index: ELF/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -2192,13 +2192,19 @@ // This section will have been sorted last in the .ARM.exidx table. // This table entry will have the form: // | PREL31 upper bound of code that has exception tables | EXIDX_CANTUNWIND | +// The sentinel must have the PREL31 value of an address higher than any +// address described by any other table entry. void ARMExidxSentinelSection::writeTo(uint8_t *Buf) { - // Get the InputSection before us, we are by definition last - auto RI = cast(this->OutSec)->Sections.rbegin(); - InputSection *LE = *(++RI); - InputSection *LC = cast(LE->getLinkOrderDep()); - uint64_t S = LC->OutSec->Addr + LC->getOffset(LC->getSize()); - uint64_t P = this->getVA(); + uint64_t S = 0; + uint64_t P = getVA(); + std::vector *> Ranges = + Script->inputSectionRanges(OutSec->Name); + for (std::vector *Range : Ranges) + for (InputSection* IS : *Range) + if (IS->kind() != InputSectionBase::Synthetic) { + InputSection *LS = cast(IS->getLinkOrderDep()); + S = std::max(S, LS->OutSec->Addr + LS->getOffset(LS->getSize())); + } Target->relocateOne(Buf, R_ARM_PREL31, S - P); write32le(Buf + 4, 0x1); }