From 54dab70bb75eabe1319fe1b1c94c0930230eb06d Mon Sep 17 00:00:00 2001 From: Peter Smith Date: Thu, 21 Mar 2019 17:17:54 +0000 Subject: [PATCH] [ELF][ARM] Revert Redesign of .ARM.exidx handling to use a SyntheticSection There is a reproducible buildbot failure (segfault) on the 2 stage clang-cmake-armv8-lld bot. Reverting while I investigate. Differential Revision: https://reviews.llvm.org/D59216 llvm-svn: 356684 --- lld/ELF/OutputSections.cpp | 4 +- lld/ELF/SyntheticSections.cpp | 188 +++--------------------- lld/ELF/SyntheticSections.h | 74 +--------- lld/ELF/Writer.cpp | 113 +++++++++++--- lld/test/ELF/arm-data-prel.s | 22 +-- lld/test/ELF/arm-exidx-add-missing.s | 66 --------- lld/test/ELF/arm-exidx-canunwind.s | 27 ++-- lld/test/ELF/arm-exidx-dedup.s | 25 ++-- lld/test/ELF/arm-exidx-gc.s | 23 ++- lld/test/ELF/arm-exidx-no-add-missing.s | 16 -- lld/test/ELF/arm-exidx-shared.s | 8 +- 11 files changed, 175 insertions(+), 391 deletions(-) delete mode 100644 lld/test/ELF/arm-exidx-add-missing.s delete mode 100644 lld/test/ELF/arm-exidx-no-add-missing.s diff --git a/lld/ELF/OutputSections.cpp b/lld/ELF/OutputSections.cpp index 4cb5a3cdc591..a7f35ebfc57c 100644 --- a/lld/ELF/OutputSections.cpp +++ b/lld/ELF/OutputSections.cpp @@ -289,9 +289,7 @@ void OutputSection::finalize() { // 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 *EX = dyn_cast(First)) - Link = EX->getLinkOrderDep()->getParent()->SectionIndex; - else if (auto *D = First->getLinkOrderDep()) + if (auto *D = First->getLinkOrderDep()) Link = D->getParent()->SectionIndex; } diff --git a/lld/ELF/SyntheticSections.cpp b/lld/ELF/SyntheticSections.cpp index e5473e58a75e..182542450610 100644 --- a/lld/ELF/SyntheticSections.cpp +++ b/lld/ELF/SyntheticSections.cpp @@ -3052,183 +3052,33 @@ MipsRldMapSection::MipsRldMapSection() : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, Config->Wordsize, ".rld_map") {} -ARMExidxSyntheticSection::ARMExidxSyntheticSection() +ARMExidxSentinelSection::ARMExidxSentinelSection() : SyntheticSection(SHF_ALLOC | SHF_LINK_ORDER, SHT_ARM_EXIDX, - 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(); + Config->Wordsize, ".ARM.exidx") {} - std::vector &V = InputSections; - V.erase(std::remove(V.begin(), V.end(), nullptr), V.end()); +// 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); } -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) +// 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)) return false; - - // All table entries in this .ARM.exidx Section can be merged into the - // previous Section. return true; } -// 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 { - for (InputSection *IS : ExecutableSections) - if (findExidxSection(IS)) - return IS; - return nullptr; -} - -// 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) { +bool ARMExidxSentinelSection::classof(const SectionBase *D) { return D->kind() == InputSectionBase::Synthetic && D->Type == SHT_ARM_EXIDX; } diff --git a/lld/ELF/SyntheticSections.h b/lld/ELF/SyntheticSections.h index c8656bd35a8e..11dae7933d04 100644 --- a/lld/ELF/SyntheticSections.h +++ b/lld/ELF/SyntheticSections.h @@ -936,76 +936,19 @@ public: void writeTo(uint8_t *Buf) override {} }; -// 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 { +class ARMExidxSentinelSection : public SyntheticSection { public: - ARMExidxSyntheticSection(); - size_t getSize() const override { return Size; } + ARMExidxSentinelSection(); + size_t getSize() const override { return 8; } void writeTo(uint8_t *Buf) override; - bool empty() const override { return Empty; } - // Sort and remove duplicate entries. - void finalizeContents() override; - InputSection *getLinkOrderDep() const; + bool empty() const override; static bool classof(const SectionBase *D); - // 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; + // 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; }; // A container for one or more linker generated thunks. Instances of these @@ -1060,7 +1003,6 @@ Defined *addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value, // Linker generated sections which can be used as inputs. struct InStruct { InputSection *ARMAttributes; - ARMExidxSyntheticSection *ARMExidx; BssSection *Bss; BssSection *BssRelRo; BuildIdSection *BuildId; diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 014ed7c98c3c..2fdecaa7e7f8 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -435,12 +435,10 @@ template static void createSyntheticSections() { if (In.StrTab) Add(In.StrTab); - if (Config->EMachine == EM_ARM && !Config->Relocatable) { - // The ARMExidxsyntheticsection replaces all the individual .ARM.exidx - // InputSections. - In.ARMExidx = make(); - Add(In.ARMExidx); - } + 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()); } // The main function of the writer. @@ -923,9 +921,6 @@ void Writer::forEachRelSec( Fn(*IS); for (EhInputSection *ES : In.EhFrame->Sections) Fn(*ES); - if (In.ARMExidx) - for (InputSection *Ex : In.ARMExidx->ExidxSections) - Fn(*Ex); } // This function generates assignments for predefined symbols (e.g. _end or @@ -1388,6 +1383,11 @@ template void Writer::sortSections() { } 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(); @@ -1398,6 +1398,53 @@ static bool compareByFilePosition(InputSection *A, InputSection *B) { 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)) @@ -1415,17 +1462,46 @@ template void Writer::resolveShfLinkOrder() { } } } - - // 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) - continue; - std::stable_sort(Sections.begin(), Sections.end(), compareByFilePosition); + 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(); + } + + // 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; + } + } + } + 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; }); } } @@ -1695,7 +1771,6 @@ template void Writer::finalizeSections() { // 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); @@ -1722,8 +1797,8 @@ template void Writer::finalizeSections() { if (!Script->HasSectionsCommand && !Config->Relocatable) fixSectionAlignments(); - // SHFLinkOrder processing must be processed after relative section placements are - // known but before addresses are allocated. + // After link order processing .ARM.exidx sections can be deduplicated, which + // needs to be resolved before any other address dependent operation. resolveShfLinkOrder(); // Jump instructions in many ISAs have small displacements, and therefore they diff --git a/lld/test/ELF/arm-data-prel.s b/lld/test/ELF/arm-data-prel.s index e5bb6fa5759b..78b42818609b 100644 --- a/lld/test/ELF/arm-data-prel.s +++ b/lld/test/ELF/arm-data-prel.s @@ -1,8 +1,9 @@ // REQUIRES: arm -// RUN: llvm-mc %s -triple=armv7-unknown-linux-gnueabi -filetype=obj --arm-add-build-attributes -o %t.o +// RUN: llvm-mc %s -triple=armv7-unknown-linux-gnueabi -filetype=obj -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 @@ -46,14 +47,17 @@ __aeabi_unwind_cpp_pr0: // 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 -// 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 -// Word5 Sentinel +18 EXIDX_CANTUNWIND - // CHECK: Name: .prel.test // CHECK: SectionData ( -// CHECK: 0000: FCFFFF7F B0B0B080 10000000 80849B80 -// CHECK: 0010: 18000000 01000000 +// 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 +// set vsp = r11 +// pop r11, r14 +// CHECK: Name: .prel.test.TEST1 +// CHECK: SectionData ( +// CHECK: 0000: 08000000 80849B80 // CHECK: ) diff --git a/lld/test/ELF/arm-exidx-add-missing.s b/lld/test/ELF/arm-exidx-add-missing.s deleted file mode 100644 index 7e452c6b439e..000000000000 --- a/lld/test/ELF/arm-exidx-add-missing.s +++ /dev/null @@ -1,66 +0,0 @@ -// 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 - diff --git a/lld/test/ELF/arm-exidx-canunwind.s b/lld/test/ELF/arm-exidx-canunwind.s index cb1588606463..df89d0082fcf 100644 --- a/lld/test/ELF/arm-exidx-canunwind.s +++ b/lld/test/ELF/arm-exidx-canunwind.s @@ -1,6 +1,6 @@ // REQUIRES: arm -// 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-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t +// RUN: ld.lld %t -o %t2 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 // RUN: llvm-readobj --program-headers --sections %t2 | FileCheck -check-prefix=CHECK-PT %s @@ -66,14 +66,15 @@ _start: // CHECK: __aeabi_unwind_cpp_pr0: // CHECK-NEXT: 11018: 1e ff 2f e1 bx lr -// 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-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 // CHECK-PT: Name: .ARM.exidx // CHECK-PT-NEXT: Type: SHT_ARM_EXIDX (0x70000001) @@ -83,14 +84,14 @@ _start: // CHECK-PT-NEXT: ] // CHECK-PT-NEXT: Address: 0x100D4 // CHECK-PT-NEXT: Offset: 0xD4 -// CHECK-PT-NEXT: Size: 40 +// CHECK-PT-NEXT: Size: 24 // 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: 40 -// CHECK-PT-NEXT: MemSize: 40 +// CHECK-PT-NEXT: FileSize: 24 +// CHECK-PT-NEXT: MemSize: 24 // CHECK-PT-NEXT: Flags [ (0x4) // CHECK-PT-NEXT: PF_R (0x4) // CHECK-PT-NEXT: ] diff --git a/lld/test/ELF/arm-exidx-dedup.s b/lld/test/ELF/arm-exidx-dedup.s index d91641886173..49d4c2cd1ec3 100644 --- a/lld/test/ELF/arm-exidx-dedup.s +++ b/lld/test/ELF/arm-exidx-dedup.s @@ -1,29 +1,27 @@ // REQUIRES: arm -// RUN: llvm-mc -filetype=obj --arm-add-build-attributes -triple=armv7a-none-linux-gnueabi %s -o %t +// RUN: llvm-mc -filetype=obj -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 24000000 -// CHECK-DUPS-NEXT: 10114 0c0f0000 28000000 080f0000 01000000 -// CHECK-DUPS-NEXT: 10124 040f0000 01000000 000f0000 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 14000000 +// CHECK-DUPS-NEXT: 10114 0c0f0000 18000000 080f0000 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 1c000000 340f0000 20000000 -// CHECK-NEXT: 100f4 300f0000 01000000 300f0000 01000000 +// CHECK-NEXT: 100d4 2c0f0000 01000000 340f0000 08849780 +// CHECK-NEXT: 100e4 380f0000 14000000 340f0000 18000000 +// CHECK-NEXT: 100f4 300f0000 01000000 // CHECK-NEXT: Contents of section .ARM.extab: .syntax unified @@ -115,9 +113,8 @@ f8: .long 0 .fnend -// Dummy implementation of personality routines to satisfy reference from -// exception tables -// Expect Linker generated EXIDX_CANTUNWIND tables + // Dummy implementation of personality routines to satisfy reference from + // exception tables .section .text.__gcc_personality_v0, "ax", %progbits .global __gxx_personality_v0 __gxx_personality_v0: diff --git a/lld/test/ELF/arm-exidx-gc.s b/lld/test/ELF/arm-exidx-gc.s index b5431cbc0ece..50c8616ae773 100644 --- a/lld/test/ELF/arm-exidx-gc.s +++ b/lld/test/ELF/arm-exidx-gc.s @@ -1,5 +1,5 @@ // REQUIRES: arm -// RUN: llvm-mc -filetype=obj --arm-add-build-attributes -triple=armv7a-none-linux-gnueabi %s -o %t +// RUN: llvm-mc -filetype=obj -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,15 +111,14 @@ _start: // CHECK-NOT: __gxx_personality_v1 // CHECK-EXIDX: Contents of section .ARM.exidx: -// 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 +// 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 // CHECK-EXIDX-NEXT: Contents of section .ARM.extab: -// 10104 + f10 = 11014 = __gxx_personality_v0 -// CHECK-EXIDX-NEXT: 10104 100f0000 b0b0b000 +// 100fc + f18 = 11014 = __gxx_personality_v0 +// CHECK-EXIDX-NEXT: 100fc 180f0000 b0b0b000 diff --git a/lld/test/ELF/arm-exidx-no-add-missing.s b/lld/test/ELF/arm-exidx-no-add-missing.s deleted file mode 100644 index 743daecd75b6..000000000000 --- a/lld/test/ELF/arm-exidx-no-add-missing.s +++ /dev/null @@ -1,16 +0,0 @@ -// 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 - diff --git a/lld/test/ELF/arm-exidx-shared.s b/lld/test/ELF/arm-exidx-shared.s index 7987035046d1..9b7a246a13bb 100644 --- a/lld/test/ELF/arm-exidx-shared.s +++ b/lld/test/ELF/arm-exidx-shared.s @@ -1,8 +1,8 @@ // REQUIRES: arm -// RUN: llvm-mc -filetype=obj -arm-add-build-attributes -triple=armv7a-none-linux-gnueabi %s -o %t +// RUN: llvm-mc -filetype=obj -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-NEXT %s +// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-EXTAB %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 @@ __aeabi_unwind_cpp_pr0: // CHECK-NEXT: 0x300C R_ARM_JUMP_SLOT __gxx_personality_v0 // CHECK-EXTAB: Contents of section .ARM.extab: -// 0x0238 + 0xdf8 = 0x1030 = __gxx_personality_v0(PLT) -// CHECK-EXTAB-NEXT: 0238 f80d0000 b0b0b000 00000000 +// 0x0210 + 0x0e20 = 0x1030 = __gxx_personality_v0(PLT) +// CHECK-EXTAB-NEXT: 0230 000e0000 b0b0b000 00000000