Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -257,6 +257,8 @@ std::vector *OutputSections; void fabricateDefaultCommands(bool AllocateHeader); + std::vector *> + inputSectionRanges(StringRef S); void addOrphanSections(OutputSectionFactory &Factory); void removeEmptyCommands(); void adjustSectionsBeforeSorting(); Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -463,6 +463,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) { std::map> Orphanage; Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -113,6 +113,12 @@ template void OutputSection::finalize() { if ((this->Flags & SHF_LINK_ORDER) && !this->Sections.empty()) { + std::vector *> InputRanges = + Script->inputSectionRanges(Name); + // Make the sections with link order dependencies orphans to prevent + // the script address assignment taking precedent. + for (std::vector *Range : InputRanges) + Range->clear(); std::sort(Sections.begin(), Sections.end(), compareByFilePosition); assignOffsets(); Index: test/ELF/arm-exidx-script.s =================================================================== --- /dev/null +++ test/ELF/arm-exidx-script.s @@ -0,0 +1,30 @@ +// REQUIRES: arm +// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t +// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/arm-exidx-cantunwind.s -o %tcantunwind +// RUN: echo "SECTIONS { \ +// RUN: .ARM.exidx 0x11000 : { *(.ARM.exidx*) } \ +// RUN: .func : { *(.func*) } \ +// RUN: .text : { *(.text*) } } " > %t.script +// RUN: ld.lld --script %t.script %t %tcantunwind -o %t2 2>&1 +// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s +// Check that a linker script that describes .ARM.exidx sections orders the +// .ARM.exidx sections in ascending order of their link order dependencies. + .syntax unified + .text + .global _start +_start: + .fnstart + bx lr + .cantunwind +.fnend +// Check ascending order of first word of each 2 word entry +// [PREL31 to target, unwind info] +// 11000 + 38 = 11038, 11008 + 34 = 1103c ... 11030 + 20 = 11050 +// CHECK: 11000 38000000 01000000 34000000 01000000 +// CHECK-NEXT: 11010 30000000 01000000 2c000000 01000000 +// CHECK-NEXT: 11020 28000000 01000000 24000000 01000000 +// CHECK-NEXT: 11030 20000000 01000000 +// CHECK-NEXT: Contents of section .func: +// CHECK-NEXT: 11038 1eff2fe1 1eff2fe1 1eff2fe1 +// CHECK-NEXT: Contents of section .text: +// CHECK-NEXT: 11044 1eff2fe1 1eff2fe1 1eff2fe1