Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -289,7 +289,9 @@ // SHF_LINK_ORDER flag. The dependency is indicated by the sh_link field. We // need to translate the InputSection sh_link to the OutputSection sh_link, // all InputSections in the OutputSection have the same dependency. - if (auto *D = First->getLinkOrderDep()) + if (auto *EX = dyn_cast(First)) + Link = EX->getLinkOrderDep()->getParent()->SectionIndex; + else if (auto *D = First->getLinkOrderDep()) Link = D->getParent()->SectionIndex; } Index: ELF/SyntheticSections.h =================================================================== --- ELF/SyntheticSections.h +++ ELF/SyntheticSections.h @@ -938,19 +938,76 @@ void writeTo(uint8_t *Buf) override {} }; -class ARMExidxSentinelSection : public SyntheticSection { +// Representation of the combined .ARM.Exidx input sections. We process these +// as a SyntheticSection like .eh_frame as we need to merge duplicate entries +// and add terminating sentinel entries. +// +// The .ARM.exidx input sections after SHF_LINK_ORDER processing is done form +// a table that the unwinder can derive (Addresses are encoded as offsets from +// table): +// | Address of function | Unwind instructions for function | +// where the unwind instructions are either a small number of unwind or the +// special EXIDX_CANTUNWIND entry representing no unwinding information. +// When an exception is thrown from an address A, the unwinder searches the +// table for the closest table entry with Address of function <= A. This means +// that for two consecutive table entries: +// | A1 | U1 | +// | A2 | U2 | +// The range of addresses described by U1 is [A1, A2) +// +// There are two cases where we need a linker generated table entry to fixup +// the address ranges in the table +// Case 1: +// - A sentinel entry added with an address higher than all +// executable sections. This was needed to work around libunwind bug pr31091. +// - After address assignment we need to find the highest addressed executable +// section and use the limit of that section so that the unwinder never +// matches it. +// Case 2: +// - InputSections without a .ARM.exidx section (usually from Assembly) +// need a table entry so that they terminate the range of the previously +// function. This is pr40277. +// +// Instead of storing pointers to the .ARM.exidx InputSections from +// InputObjects, we store pointers to the executable sections that need +// .ARM.exidx sections. We can then use the dependentSections of these to +// either find the .ARM.exidx section or know that we need to generate one. +class ARMExidxSyntheticSection : public SyntheticSection { public: - ARMExidxSentinelSection(); - size_t getSize() const override { return 8; } + ARMExidxSyntheticSection(); + size_t getSize() const override { return Size; } void writeTo(uint8_t *Buf) override; - bool empty() const override; + bool empty() const override { return Empty; } + // Sort and remove duplicate entries. + void finalizeContents() override; + InputSection *getLinkOrderDep() const; static bool classof(const SectionBase *D); - // The last section referenced by a regular .ARM.exidx section. - // It is found and filled in Writer::resolveShfLinkOrder(). - // The sentinel points at the end of that section. - InputSection *Highest = nullptr; + // Links to the ARMExidxSections so we can transfer the relocations once the + // layout is known. + std::vector ExidxSections; + +private: + // Derive Size from contents of ExecutableSections, including any linker + // generated sentinels. Also set the OutSecOff of the ExidxSections. + void setSizeAndOffsets(); + size_t Size; + + // Empty if ExecutableSections contains no dependent .ARM.exidx sections. + bool Empty = true; + + // Instead of storing pointers to the .ARM.exidx InputSections from + // InputObjects, we store pointers to the executable sections that need + // .ARM.exidx sections. We can then use the dependentSections of these to + // either find the .ARM.exidx section or know that we need to generate one. + std::vector ExecutableSections; + + // The executable InputSection with the highest address to use for the + // sentinel. We store separately from ExecutableSections as merging of + // duplicate entries may mean this InputSection is removed from + // ExecutableSections. + InputSection *Sentinel = nullptr; }; // A container for one or more linker generated thunks. Instances of these @@ -1005,6 +1062,7 @@ // Linker generated sections which can be used as inputs. struct InStruct { InputSection *ARMAttributes; + ARMExidxSyntheticSection *ARMExidx; BssSection *Bss; BssSection *BssRelRo; BuildIdSection *BuildId; Index: ELF/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -3039,33 +3039,194 @@ : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, Config->Wordsize, ".rld_map") {} -ARMExidxSentinelSection::ARMExidxSentinelSection() +ARMExidxSyntheticSection::ARMExidxSyntheticSection() : SyntheticSection(SHF_ALLOC | SHF_LINK_ORDER, SHT_ARM_EXIDX, - Config->Wordsize, ".ARM.exidx") {} - -// Write a terminating sentinel entry to the end of the .ARM.exidx table. -// 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) { - assert(Highest); - uint64_t S = Highest->getVA(Highest->getSize()); - uint64_t P = getVA(); - Target->relocateOne(Buf, R_ARM_PREL31, S - P); - write32le(Buf + 4, 1); -} - -// The sentinel has to be removed if there are no other .ARM.exidx entries. -bool ARMExidxSentinelSection::empty() const { - for (InputSection *IS : getInputSections(getParent())) - if (!isa(IS)) + Config->Wordsize, ".ARM.exidx") { + for (InputSectionBase *&IS : InputSections) { + if (isa(IS) && IS->Type == SHT_ARM_EXIDX) { + ExidxSections.push_back(cast(IS)); + IS = nullptr; + } else if (IS->Live && isa(IS) && + IS->kind() != SectionBase::Synthetic && + (IS->Flags & SHF_ALLOC) && (IS->Flags & SHF_EXECINSTR) && + IS->getSize() > 0) { + ExecutableSections.push_back(cast(IS)); + } + } + setSizeAndOffsets(); + + // FIXME: we do not output a relocation section when --emit-relocs is used + // as we do not have relocation sections for linker generated table entries + // and we would have to erase at a late stage relocations from merged entries. + // Given that exception tables are already position independent and a binary + // analyzer could derive the relocations we choose to erase the relocations. + if (Config->EmitRelocs) + for (InputSectionBase *&IS : InputSections) + if (IS && isa(IS) && IS->Type == SHT_REL) { + InputSection *RS = cast(IS); + if (InputSectionBase *EX = RS->getRelocatedSection()) + if (isa(EX) && EX->Type == SHT_ARM_EXIDX) + IS = nullptr; + } + + std::vector &V = InputSections; + V.erase(std::remove(V.begin(), V.end(), nullptr), V.end()); +} + +static InputSection *findExidxSection(InputSection *IS) { + for (InputSection *D : IS->DependentSections) + if (D->Type == SHT_ARM_EXIDX) + return D; + return nullptr; +} + +void ARMExidxSyntheticSection::setSizeAndOffsets() { + size_t Offset = 0; + Size = 0; + for (InputSection *IS : ExecutableSections) { + if (InputSection *D = findExidxSection(IS)) { + D->OutSecOff = Offset; + D->Parent = getParent(); + Offset += D->getSize(); + Empty = false; + } else { + Offset += 8; + } + } + // Size includes Sentinel. + Size = Offset + 8; +} + +// References to .ARM.Extab Sections have bit 31 clear and are not the +// special EXIDX_CANTUNWIND bit-pattern. +static bool isExtabRef(uint32_t Unwind) { + return (Unwind & 0x80000000) == 0 && Unwind != 0x1; +} + +// Return true if the .ARM.exidx section Cur can be merged into the .ARM.exidx +// section Prev, where Cur follows Prev in the table. This can be done if the +// unwinding instructions in Cur are identical to Prev. Linker generated +// EXIDX_CANTUNWIND entries are represented by nullptr as they do not have an +// InputSection. +static bool isDuplicateArmExidxSec(InputSection *Prev, InputSection *Cur) { + + struct ExidxEntry { + ulittle32_t Fn; + ulittle32_t Unwind; + }; + // Get the last table Entry from the previous .ARM.exidx section. If Prev is + // nullptr then it will be a synthesized EXIDX_CANTUNWIND entry. + ExidxEntry PrevEntry = {ulittle32_t(0), ulittle32_t(1)}; + if (Prev) + PrevEntry = Prev->getDataAs().back(); + if (isExtabRef(PrevEntry.Unwind)) + return false; + + // We consider the unwind instructions of an .ARM.exidx table entry + // a duplicate if the previous unwind instructions if: + // - Both are the special EXIDX_CANTUNWIND. + // - Both are the same inline unwind instructions. + // We do not attempt to follow and check links into .ARM.extab tables as + // consecutive identical entries are rare and the effort to check that they + // are identical is high. + + // If Cur is nullptr then this is synthesized EXIDX_CANTUNWIND entry. + if (Cur == nullptr) + return PrevEntry.Unwind == 1; + + for (const ExidxEntry Entry : Cur->getDataAs()) + if (isExtabRef(Entry.Unwind) || Entry.Unwind != PrevEntry.Unwind) return false; + + // All table entries in this .ARM.exidx Section can be merged into the + // previous Section. return true; } -bool ARMExidxSentinelSection::classof(const SectionBase *D) { +// The .ARM.exidx table must be sorted in ascending order of the address of the +// functions the table describes. Optionally duplicate adjacent table entries +// can be removed. At the end of the function the ExecutableSections must be +// sorted in ascending order of address, Sentinel is set to the InputSection +// with the highest address and any InputSections that have mergeable +// .ARM.exidx table entries are removed from it. +void ARMExidxSyntheticSection::finalizeContents() { + // Sort the executable sections that may or may not have associated + // .ARM.exidx sections by order of ascending address. This requires the + // relative positions of InputSections to be known. + auto CompareByFilePosition = [](const InputSection *A, + const InputSection *B) { + OutputSection *AOut = A->getParent(); + OutputSection *BOut = B->getParent(); + + if (AOut != BOut) + return AOut->SectionIndex < BOut->SectionIndex; + return A->OutSecOff < B->OutSecOff; + }; + std::stable_sort(ExecutableSections.begin(), ExecutableSections.end(), + CompareByFilePosition); + Sentinel = ExecutableSections.back(); + // Optionally merge adjacent duplicate entries. + if (Config->MergeArmExidx) { + std::vector SelectedSections; + SelectedSections.reserve(ExecutableSections.size()); + SelectedSections.push_back(ExecutableSections[0]); + size_t Prev = 0; + for (size_t I = 1; I < ExecutableSections.size(); ++I) { + InputSection *EX1 = findExidxSection(ExecutableSections[Prev]); + InputSection *EX2 = findExidxSection(ExecutableSections[I]); + if (!isDuplicateArmExidxSec(EX1, EX2)) { + SelectedSections.push_back(ExecutableSections[I]); + Prev = I; + } + } + ExecutableSections = std::move(SelectedSections); + } + setSizeAndOffsets(); +} + +InputSection *ARMExidxSyntheticSection::getLinkOrderDep() const { + return ExecutableSections.front(); +} + +// To write the .ARM.exidx table from the ExecutableSections we have three cases +// 1.) The InputSection has a .ARM.exidx InputSection in its dependent sections. +// We write the .ARM.exidx section contents and apply its relocations. +// 2.) The InputSection does not have a dependent .ARM.exidx InputSection. We +// must write the contents of an EXIDX_CANTUNWIND directly. We use the +// start of the InputSection as the purpose of the linker generated +// section is to terminate the address range of the previous entry. +// 3.) A trailing EXIDX_CANTUNWIND sentinel section is required at the end of +// the table to terminate the address range of the final entry. +void ARMExidxSyntheticSection::writeTo(uint8_t *Buf) { + + const uint8_t CantUnwindData[8] = {0, 0, 0, 0, // PREL31 to target + 1, 0, 0, 0}; // EXIDX_CANTUNWIND + + uint64_t Offset = 0; + for (InputSection *IS : ExecutableSections) { + assert(IS->getParent() != nullptr); + if (InputSection *D = findExidxSection(IS)) { + memcpy(Buf + Offset, D->data().data(), D->data().size()); + D->relocateAlloc(Buf, Buf + D->getSize()); + Offset += D->getSize(); + } else { + // A Linker generated CANTUNWIND section. + memcpy(Buf + Offset, CantUnwindData, sizeof(CantUnwindData)); + uint64_t S = IS->getVA(); + uint64_t P = getVA() + Offset; + Target->relocateOne(Buf + Offset, R_ARM_PREL31, S - P); + Offset += 8; + } + } + // Write Sentinel. + memcpy(Buf + Offset, CantUnwindData, sizeof(CantUnwindData)); + uint64_t S = Sentinel->getVA(Sentinel->getSize()); + uint64_t P = getVA() + Offset; + Target->relocateOne(Buf + Offset, R_ARM_PREL31, S - P); + assert(Size == Offset + 8); +} + +bool ARMExidxSyntheticSection::classof(const SectionBase *D) { return D->kind() == InputSectionBase::Synthetic && D->Type == SHT_ARM_EXIDX; } Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -444,10 +444,12 @@ if (In.StrTab) Add(In.StrTab); - if (Config->EMachine == EM_ARM && !Config->Relocatable) - // Add a sentinel to terminate .ARM.exidx. It helps an unwinder - // to find the exact address range of the last entry. - Add(make()); + if (Config->EMachine == EM_ARM && !Config->Relocatable) { + // The ARMExidxsyntheticsection replaces all the individual .ARM.exidx + // InputSections. + In.ARMExidx = make(); + Add(In.ARMExidx); + } } // The main function of the writer. @@ -930,6 +932,9 @@ Fn(*IS); for (EhInputSection *ES : In.EhFrame->Sections) Fn(*ES); + if (In.ARMExidx && In.ARMExidx->Live) + for (InputSection *Ex : In.ARMExidx->ExidxSections) + Fn(*Ex); } // This function generates assignments for predefined symbols (e.g. _end or @@ -1392,11 +1397,6 @@ } static bool compareByFilePosition(InputSection *A, InputSection *B) { - // Synthetic, i. e. a sentinel section, should go last. - if (A->kind() == InputSectionBase::Synthetic || - B->kind() == InputSectionBase::Synthetic) - return A->kind() != InputSectionBase::Synthetic; - InputSection *LA = A->getLinkOrderDep(); InputSection *LB = B->getLinkOrderDep(); OutputSection *AOut = LA->getParent(); @@ -1407,53 +1407,6 @@ return LA->OutSecOff < LB->OutSecOff; } -// This function is used by the --merge-exidx-entries to detect duplicate -// .ARM.exidx sections. It is Arm only. -// -// The .ARM.exidx section is of the form: -// | PREL31 offset to function | Unwind instructions for function | -// where the unwind instructions are either a small number of unwind -// instructions inlined into the table entry, the special CANT_UNWIND value of -// 0x1 or a PREL31 offset into a .ARM.extab Section that contains unwind -// instructions. -// -// We return true if all the unwind instructions in the .ARM.exidx entries of -// Cur can be merged into the last entry of Prev. -static bool isDuplicateArmExidxSec(InputSection *Prev, InputSection *Cur) { - - // References to .ARM.Extab Sections have bit 31 clear and are not the - // special EXIDX_CANTUNWIND bit-pattern. - auto IsExtabRef = [](uint32_t Unwind) { - return (Unwind & 0x80000000) == 0 && Unwind != 0x1; - }; - - struct ExidxEntry { - ulittle32_t Fn; - ulittle32_t Unwind; - }; - - // Get the last table Entry from the previous .ARM.exidx section. - const ExidxEntry &PrevEntry = Prev->getDataAs().back(); - if (IsExtabRef(PrevEntry.Unwind)) - return false; - - // We consider the unwind instructions of an .ARM.exidx table entry - // a duplicate if the previous unwind instructions if: - // - Both are the special EXIDX_CANTUNWIND. - // - Both are the same inline unwind instructions. - // We do not attempt to follow and check links into .ARM.extab tables as - // consecutive identical entries are rare and the effort to check that they - // are identical is high. - - for (const ExidxEntry Entry : Cur->getDataAs()) - if (IsExtabRef(Entry.Unwind) || Entry.Unwind != PrevEntry.Unwind) - return false; - - // All table entries in this .ARM.exidx Section can be merged into the - // previous Section. - return true; -} - template void Writer::resolveShfLinkOrder() { for (OutputSection *Sec : OutputSections) { if (!(Sec->Flags & SHF_LINK_ORDER)) @@ -1471,46 +1424,17 @@ } } } - std::stable_sort(Sections.begin(), Sections.end(), compareByFilePosition); + // The ARM.exidx section use SHF_LINK_ORDER, but we have consolidated + // this processing inside the ARMExidxsyntheticsection::finalizeContents(). if (!Config->Relocatable && Config->EMachine == EM_ARM && - Sec->Type == SHT_ARM_EXIDX) { - - if (auto *Sentinel = dyn_cast(Sections.back())) { - assert(Sections.size() >= 2 && - "We should create a sentinel section only if there are " - "alive regular exidx sections."); - - // The last executable section is required to fill the sentinel. - // Remember it here so that we don't have to find it again. - Sentinel->Highest = Sections[Sections.size() - 2]->getLinkOrderDep(); - } + Sec->Type == SHT_ARM_EXIDX) + continue; - // The EHABI for the Arm Architecture permits consecutive identical - // table entries to be merged. We use a simple implementation that - // removes a .ARM.exidx Input Section if it can be merged into the - // previous one. This does not require any rewriting of InputSection - // contents but misses opportunities for fine grained deduplication - // where only a subset of the InputSection contents can be merged. - if (Config->MergeArmExidx) { - size_t Prev = 0; - // The last one is a sentinel entry which should not be removed. - for (size_t I = 1; I < Sections.size() - 1; ++I) { - if (isDuplicateArmExidxSec(Sections[Prev], Sections[I])) - Sections[I] = nullptr; - else - Prev = I; - } - } - } + std::stable_sort(Sections.begin(), Sections.end(), compareByFilePosition); for (int I = 0, N = Sections.size(); I < N; ++I) *ScriptSections[I] = Sections[I]; - - // Remove the Sections we marked as duplicate earlier. - for (BaseCommand *Base : Sec->SectionCommands) - if (auto *ISD = dyn_cast(Base)) - llvm::erase_if(ISD->Sections, [](InputSection *IS) { return !IS; }); } } @@ -1780,6 +1704,7 @@ // Dynamic section must be the last one in this list and dynamic // symbol table section (DynSymTab) must be the first one. finalizeSynthetic(In.DynSymTab); + finalizeSynthetic(In.ARMExidx); finalizeSynthetic(In.Bss); finalizeSynthetic(In.BssRelRo); finalizeSynthetic(In.GnuHashTab); @@ -1806,8 +1731,8 @@ if (!Script->HasSectionsCommand && !Config->Relocatable) fixSectionAlignments(); - // After link order processing .ARM.exidx sections can be deduplicated, which - // needs to be resolved before any other address dependent operation. + // SHFLinkOrder processing must be processed after relative section placements are + // known but before addresses are allocated. resolveShfLinkOrder(); // Jump instructions in many ISAs have small displacements, and therefore they Index: test/ELF/arm-data-prel.s =================================================================== --- test/ELF/arm-data-prel.s +++ test/ELF/arm-data-prel.s @@ -1,9 +1,8 @@ // REQUIRES: arm -// RUN: llvm-mc %s -triple=armv7-unknown-linux-gnueabi -filetype=obj -o %t.o +// RUN: llvm-mc %s -triple=armv7-unknown-linux-gnueabi -filetype=obj --arm-add-build-attributes -o %t.o // RUN: echo "SECTIONS { \ // RUN: .text : { *(.text) } \ // RUN: .prel.test : { *(.ARM.exidx) } \ -// RUN: .prel.test.TEST1 : { *(.ARM.exidx.TEST1) } \ // RUN: .TEST1 : { *(.TEST1) } } " > %t.script // RUN: ld.lld --script %t.script %t.o -o %t // RUN: llvm-readobj -s -sd %t | FileCheck --check-prefix=CHECK %s @@ -47,17 +46,14 @@ // The expected value of the exception table is // Word0 0 in bit 31, -4 encoded in 31-bit signed offset // Word1 Inline table entry EHT Inline Personality Routine #0 -// CHECK: Name: .prel.test -// CHECK: SectionData ( -// CHECK: 0000: FCFFFF7F B0B0B080 -// CHECK: ) - -// The expected value of the exception table is -// Word0 0 in bit 31, +8 encoded in 31-bit signed offset -// Word1 Inline table entry EHT Inline Personality Routine #0 +// Word3 0 in bit 31, +10 encoded in 31-bit signed offset +// Word4 Inline table entry EHT Inline Personality Routine #0 // set vsp = r11 // pop r11, r14 -// CHECK: Name: .prel.test.TEST1 +// Word5 Sentinel +18 EXIDX_CANTUNWIND + +// CHECK: Name: .prel.test // CHECK: SectionData ( -// CHECK: 0000: 08000000 80849B80 +// CHECK: 0000: FCFFFF7F B0B0B080 10000000 80849B80 +// CHECK: 0010: 18000000 01000000 // CHECK: ) Index: test/ELF/arm-exidx-add-missing.s =================================================================== --- /dev/null +++ test/ELF/arm-exidx-add-missing.s @@ -0,0 +1,66 @@ +// REQUIRES: arm +// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi --arm-add-build-attributes %s -o %t +// RUN: ld-lld %t --no-merge-exidx-entries -o %t2 +// RUN: llvm-objdump -s %t2 | FileCheck %s +// RUN: ld-lld %t -o %t3 +// RUN: llvm-objdump -s %t3 | FileCheck %s -check-prefix=CHECK-MERGE + +// The ARM.exidx section is a table of 8-byte entries of the form: +// | PREL31 Relocation to start of function | Unwinding information | +// The range of addresses covered by the table entry is terminated by the +// next table entry. This means that an executable section without a .ARM.exidx +// section does not terminate the range of addresses. To fix this the linker +// synthesises an EXIDX_CANTUNWIND entry for each section wihout a .ARM.exidx +// section. + + .syntax unified + + // Expect inline unwind instructions + .section .text.01, "ax", %progbits + .global f1 +f1: + .fnstart + bx lr + .save {r7, lr} + .setfp r7, sp, #0 + .fnend + + // Expect no unwind information from assembler. The linker must + // synthesise an EXIDX_CANTUNWIND entry to prevent an exception + // thrown through f2 from matching against the unwind instructions + // for f1. + .section .text.02, "ax", %progbits + .global f2 +f2: + bx lr + + + // Expect 1 EXIDX_CANTUNWIND entry that can be merged into the linker + // generated EXIDX_CANTUNWIND as if the assembler had generated it. + .section .text.03, "ax",%progbits + .global f3 +f3: + .fnstart + bx lr + .cantunwind + .fnend + + // Dummy implementation of personality routines to satisfy reference + // from exception tables, linker will generate EXIDX_CANTUNWIND. + .section .text.__aeabi_unwind_cpp_pr0, "ax", %progbits + .global __aeabi_unwind_cpp_pr0 +__aeabi_unwind_cpp_pr0: + bx lr + +// f1, f2 +// CHECK: 100d4 2c0f0000 08849780 280f0000 01000000 +// f3, __aeabi_unwind_cpp_pr0 +// CHECK-NEXT: 100e4 240f0000 01000000 200f0000 01000000 +// sentinel +// CHECK-NEXT: 100f4 1c0f0000 01000000 + +// f1, (f2, f3, __aeabi_unwind_cpp_pr0) +// CHECK-MERGE: 100d4 2c0f0000 08849780 280f0000 01000000 +// sentinel +// CHECK-MERGE-NEXT: 100e4 2c0f0000 01000000 + Index: test/ELF/arm-exidx-canunwind.s =================================================================== --- test/ELF/arm-exidx-canunwind.s +++ test/ELF/arm-exidx-canunwind.s @@ -1,6 +1,6 @@ // REQUIRES: arm -// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t -// RUN: ld.lld %t -o %t2 2>&1 +// RUN: llvm-mc -filetype=obj --arm-add-build-attributes -triple=armv7a-none-linux-gnueabi %s -o %t +// RUN: ld.lld %t -o %t2 // RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s // RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-EXIDX %s // RUN: llvm-readobj --program-headers --sections %t2 | FileCheck -check-prefix=CHECK-PT %s @@ -66,15 +66,14 @@ // CHECK: __aeabi_unwind_cpp_pr0: // CHECK-NEXT: 11018: 1e ff 2f e1 bx lr -// CHECK-EXIDX: Contents of section .ARM.exidx: -// 100d4 + f38 = 1100c = func1 (inline unwinding data) -// 100dc + f34 = 11010 = func2 (100e0 + c = 100ec = .ARM.extab entry) -// CHECK-EXIDX-NEXT: 100d4 380f0000 08849780 340f0000 0c000000 -// 100e4 + f30 = 11014 = terminate = func2 + sizeof(func2) -// CHECK-EXIDX-NEXT: 100e4 300f0000 01000000 -// CHECK-EXIDX-NEXT: Contents of section .ARM.extab: -// 100ec + f28 = 11014 = __gxx_personality_v0 -// CHECK-EXIDX-NEXT: 100ec 280f0000 b0b0b000 00000000 +// 100d4 + f2c = 11000 = main (linker generated cantunwind) +// 100dc + f30 = 1100c = func1 (inline unwinding data) +// CHECK-EXIDX: 100d4 2c0f0000 01000000 300f0000 08849780 +// 100e4 + f2c = 11010 = func2 (100e8 + 14 = 100fc = .ARM.extab entry) +// 100ec + f28 = 11014 = __gcc_personality_v0 (linker generated cantunwind) +// CHECK-EXIDX-NEXT: 100e4 2c0f0000 14000000 280f0000 01000000 +// 100f4 + f28 = 1101c = sentinel +// CHECK-EXIDX-NEXT: 100f4 280f0000 01000000 // CHECK-PT: Name: .ARM.exidx // CHECK-PT-NEXT: Type: SHT_ARM_EXIDX (0x70000001) @@ -84,14 +83,14 @@ // CHECK-PT-NEXT: ] // CHECK-PT-NEXT: Address: 0x100D4 // CHECK-PT-NEXT: Offset: 0xD4 -// CHECK-PT-NEXT: Size: 24 +// CHECK-PT-NEXT: Size: 40 // CHECK-PT: Type: PT_ARM_EXIDX (0x70000001) // CHECK-PT-NEXT: Offset: 0xD4 // CHECK-PT-NEXT: VirtualAddress: 0x100D4 // CHECK-PT-NEXT: PhysicalAddress: 0x100D4 -// CHECK-PT-NEXT: FileSize: 24 -// CHECK-PT-NEXT: MemSize: 24 +// CHECK-PT-NEXT: FileSize: 40 +// CHECK-PT-NEXT: MemSize: 40 // CHECK-PT-NEXT: Flags [ (0x4) // CHECK-PT-NEXT: PF_R (0x4) // CHECK-PT-NEXT: ] Index: test/ELF/arm-exidx-dedup.s =================================================================== --- test/ELF/arm-exidx-dedup.s +++ test/ELF/arm-exidx-dedup.s @@ -1,27 +1,29 @@ // REQUIRES: arm -// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t +// RUN: llvm-mc -filetype=obj --arm-add-build-attributes -triple=armv7a-none-linux-gnueabi %s -o %t // RUN: ld.lld %t --no-merge-exidx-entries -o %t2 // RUN: llvm-objdump -s %t2 | FileCheck --check-prefix CHECK-DUPS %s // RUN: ld.lld %t -o %t3 // RUN: llvm-objdump -s %t3 | FileCheck %s + // Test that lld can at least remove duplicate .ARM.exidx sections. A more // fine grained implementation will be able to remove duplicate entries within // a .ARM.exidx section. // With duplicate entries // CHECK-DUPS: Contents of section .ARM.exidx: -// CHECK-DUPS-NEXT: 100d4 2c0f0000 01000000 280f0000 01000000 -// CHECK-DUPS-NEXT: 100e4 240f0000 01000000 200f0000 01000000 -// CHECK-DUPS-NEXT: 100f4 1c0f0000 08849780 180f0000 08849780 -// CHECK-DUPS-NEXT: 10104 140f0000 08849780 100f0000 14000000 -// CHECK-DUPS-NEXT: 10114 0c0f0000 18000000 080f0000 01000000 +// CHECK-DUPS-NEXT: 100d4 2c0f0000 01000000 280f0000 01000000 +// CHECK-DUPS-NEXT: 100e4 240f0000 01000000 200f0000 01000000 +// CHECK-DUPS-NEXT: 100f4 1c0f0000 08849780 180f0000 08849780 +// CHECK-DUPS-NEXT: 10104 140f0000 08849780 100f0000 24000000 +// CHECK-DUPS-NEXT: 10114 0c0f0000 28000000 080f0000 01000000 +// CHECK-DUPS-NEXT: 10124 040f0000 01000000 000f0000 01000000 // CHECK-DUPS-NEXT: Contents of section .ARM.extab: // After duplicate entry removal // CHECK: Contents of section .ARM.exidx: -// CHECK-NEXT: 100d4 2c0f0000 01000000 340f0000 08849780 -// CHECK-NEXT: 100e4 380f0000 14000000 340f0000 18000000 -// CHECK-NEXT: 100f4 300f0000 01000000 +// CHECK-NEXT: 100d4 2c0f0000 01000000 340f0000 08849780 +// CHECK-NEXT: 100e4 380f0000 1c000000 340f0000 20000000 +// CHECK-NEXT: 100f4 300f0000 01000000 300f0000 01000000 // CHECK-NEXT: Contents of section .ARM.extab: .syntax unified @@ -113,8 +115,9 @@ .long 0 .fnend - // Dummy implementation of personality routines to satisfy reference from - // exception tables +// Dummy implementation of personality routines to satisfy reference from +// exception tables +// Expect Linker generated EXIDX_CANTUNWIND tables .section .text.__gcc_personality_v0, "ax", %progbits .global __gxx_personality_v0 __gxx_personality_v0: Index: test/ELF/arm-exidx-discard.s =================================================================== --- test/ELF/arm-exidx-discard.s +++ test/ELF/arm-exidx-discard.s @@ -6,8 +6,11 @@ .globl __entrypoint __entrypoint: +.fnstart bx lr - + .save {r7, lr} + .setfp r7, sp, #0 + .fnend // Check that .ARM.exidx/.gnu.linkonce.armexidx // are correctly removed if they were added. // CHECK-NOT: .ARM.exidx Index: test/ELF/arm-exidx-emit-relocs.s =================================================================== --- /dev/null +++ test/ELF/arm-exidx-emit-relocs.s @@ -0,0 +1,71 @@ +// REQUIRES: arm +// RUN: llvm-mc -filetype=obj --arm-add-build-attributes -triple=armv7a-none-linux-gnueabi %s -o %t +// RUN: ld.lld --emit-relocs %t -o %t2 +// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s +// RUN: llvm-readelf --relocs %t2 | FileCheck -check-prefix=CHECK-RELOCS %s + +// LLD does not support --emit-relocs for .ARM.exidx sections as the relocations +// from synthetic table entries won't be represented. Given the known use cases +// of --emit-relocs, relocating kernels, and binary analysis, the former doesn't +// use exceptions and the latter can derive the relocations from the table if +// they need them. + .syntax unified + // Will produce an ARM.exidx entry with inline unwinding instructions + .section .text.func1, "ax",%progbits + .global func1 +func1: + .fnstart + bx lr + .save {r7, lr} + .setfp r7, sp, #0 + .fnend + + .syntax unified + .section .text.func2, "ax",%progbits +// A function with the same inline unwinding instructions, expect merge. + .global func2 +func2: + .fnstart + bx lr + .save {r7, lr} + .setfp r7, sp, #0 + .fnend + + .section .text.25, "ax", %progbits + .global func25 +func25: + .fnstart + bx lr + .cantunwind + .fnend + + .section .text.26, "ax", %progbits + .global func26 +func26: + .fnstart + bx lr + .cantunwind + .fnend + + .syntax unified + .section .text.func3, "ax",%progbits +// A function with the same inline unwinding instructions, expect merge. + .global func3 +func3: + .fnstart + bx lr + .save {r7, lr} + .setfp r7, sp, #0 + .fnend + + .section .text.__aeabi_unwind_cpp_pr0, "ax", %progbits + .global __aeabi_unwind_cpp_pr0 +__aeabi_unwind_cpp_pr0: + bx lr + +// CHECK: Contents of section .ARM.exidx: +// CHECK-NEXT: 100d4 2c0f0000 08849780 2c0f0000 01000000 +// CHECK-NEXT: 100e4 2c0f0000 08849780 280f0000 01000000 +// CHECK-NEXT: 100f4 240f0000 01000000 + +// CHECK-RELOCS-NOT: Relocation section '.rel.ARM.exidx' Index: test/ELF/arm-exidx-gc.s =================================================================== --- test/ELF/arm-exidx-gc.s +++ test/ELF/arm-exidx-gc.s @@ -1,5 +1,5 @@ // REQUIRES: arm -// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t +// RUN: llvm-mc -filetype=obj --arm-add-build-attributes -triple=armv7a-none-linux-gnueabi %s -o %t // RUN: ld.lld %t --no-merge-exidx-entries -o %t2 --gc-sections 2>&1 // RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s // RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-EXIDX %s @@ -111,14 +111,15 @@ // CHECK-NOT: __gxx_personality_v1 // CHECK-EXIDX: Contents of section .ARM.exidx: -// 100d4 + f38 = 1100c = func1 -// 100dc + f34 = 11010 = func2 (100e0 + 1c = 100fc = .ARM.extab) -// CHECK-EXIDX-NEXT: 100d4 380f0000 08849780 340f0000 1c000000 -// 100e4 + f30 = 11014 = __gxx_personality_v0 -// 100ec + f2c = 11018 = __aeabi_unwind_cpp_pr0 -// CHECK-EXIDX-NEXT: 100e4 300f0000 01000000 2c0f0000 01000000 -// 100f4 + f28 = 1101c = __aeabi_unwind_cpp_pr0 + sizeof(__aeabi_unwind_cpp_pr0) -// CHECK-EXIDX-NEXT: 100f4 280f0000 01000000 +// 100d4 + f2c = 11000 +// 100dc + f30 = 1100c = func1 +// CHECK-EXIDX-NEXT: 100d4 2c0f0000 01000000 300f0000 08849780 +// 100e4 + f2c = 11010 = func2 (100e8 + 1c = 10104 = .ARM.extab) +// 100ec + f28 = 11014 = __gxx_personality_v0 +// CHECK-EXIDX-NEXT: 100e4 2c0f0000 1c000000 280f0000 01000000 +// 100f4 + f24 = 11018 = __aeabi_unwind_cpp_pr0 +// 100fc + f20 = 1101c = __aeabi_unwind_cpp_pr0 + sizeof(__aeabi_unwind_cpp_pr0) +// CHECK-EXIDX-NEXT: 100f4 240f0000 01000000 200f0000 01000000 // CHECK-EXIDX-NEXT: Contents of section .ARM.extab: -// 100fc + f18 = 11014 = __gxx_personality_v0 -// CHECK-EXIDX-NEXT: 100fc 180f0000 b0b0b000 +// 10104 + f10 = 11014 = __gxx_personality_v0 +// CHECK-EXIDX-NEXT: 10104 100f0000 b0b0b000 Index: test/ELF/arm-exidx-no-add-missing.s =================================================================== --- /dev/null +++ test/ELF/arm-exidx-no-add-missing.s @@ -0,0 +1,16 @@ +// REQUIRES: arm +// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi --arm-add-build-attributes %s -o %t +// RUN: ld-lld %t -o %t2 +// RUN: llvm-objdump -s %t2 | FileCheck %s + +// We do not want to generate missing EXIDX_CANTUNWIND entries if there are no +// input .ARM.exidx sections. + +// CHECK-NOT: .ARM.exidx + .syntax unified + .text + .globl _start + .type _start, %function +_start: + bx lr + Index: test/ELF/arm-exidx-shared.s =================================================================== --- test/ELF/arm-exidx-shared.s +++ test/ELF/arm-exidx-shared.s @@ -1,8 +1,8 @@ // REQUIRES: arm -// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t +// RUN: llvm-mc -filetype=obj -arm-add-build-attributes -triple=armv7a-none-linux-gnueabi %s -o %t // RUN: ld.lld --hash-style=sysv %t --shared -o %t2 2>&1 // RUN: llvm-readobj --relocations %t2 | FileCheck %s -// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-EXTAB %s +// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck --check-prefix=CHECK-EXTAB-NEXT %s // Check that the relative R_ARM_PREL31 relocation can access a PLT entry // for when the personality routine is referenced from a shared library. @@ -41,5 +41,5 @@ // CHECK-NEXT: 0x300C R_ARM_JUMP_SLOT __gxx_personality_v0 // CHECK-EXTAB: Contents of section .ARM.extab: -// 0x0210 + 0x0e20 = 0x1030 = __gxx_personality_v0(PLT) -// CHECK-EXTAB-NEXT: 0230 000e0000 b0b0b000 00000000 +// 0x0238 + 0xdf8 = 0x1030 = __gxx_personality_v0(PLT) +// CHECK-EXTAB-NEXT: 0238 f80d0000 b0b0b000 00000000 Index: test/ELF/arm-exidx-synthetic-link.s =================================================================== --- /dev/null +++ test/ELF/arm-exidx-synthetic-link.s @@ -0,0 +1,37 @@ +// REQUIRES: arm +// RUN: llvm-mc -filetype=obj -arm-add-build-attributes -triple=armv7a-none-linux-gnueabi %s -o %t.o +// RUN: ld.lld %t.o -o %t.so -shared +// RUN: llvm-readobj -s %t.so | FileCheck %s + +// Test that when all the .ARM.exidx sections are merged into a single +// synthetic EXIDX_CANTUNWIND entry we can still set the SHF_LINK_ORDER +// link. + .syntax unified + .section .text.1, "ax", %progbits + .globl f1 + .type f1, %function +f1: + bx lr + + .section .text.2, "ax", %progbits + .globl f2 + .type f2, %function +f2: + .fnstart + bx lr + .cantunwind + .fnend + +// CHECK: Name: .ARM.exidx +// CHECK-NEXT: Type: SHT_ARM_EXIDX +// CHECK-NEXT: Flags [ +// CHECK-NEXT: SHF_ALLOC +// CHECK-NEXT: SHF_LINK_ORDER +// CHECK-NEXT: ] +// CHECK-NEXT: Address: +// CHECK-NEXT: Offset: +// CHECK-NEXT: Size: +// CHECK-NEXT: Link: [[INDEX:.*]] + +// CHECK: Index: [[INDEX]] +// CHECK-NEXT: Name: .text