[lld] r283734 - [ELF][ARM] Garbage collection support for .ARM.exidx sections
Peter Smith via llvm-commits
llvm-commits at lists.llvm.org
Mon Oct 10 03:10:27 PDT 2016
Author: psmith
Date: Mon Oct 10 05:10:27 2016
New Revision: 283734
URL: http://llvm.org/viewvc/llvm-project?rev=283734&view=rev
Log:
[ELF][ARM] Garbage collection support for .ARM.exidx sections
.ARM.exidx sections have a reverse dependency on the section they have
a SHF_LINK_ORDER dependency on. In other words a .ARM.exidx section is
live only if the executable section it describes is live. We implement
this with a reverse dependency field in InputSection.
Adding the dependency to InputSection is the simplest implementation
but it could be moved out to a separate map if it were found to decrease
performance for non ARM targets.
Differential revision: https://reviews.llvm.org/D25234
Added:
lld/trunk/test/ELF/arm-exidx-gc.s
Modified:
lld/trunk/ELF/InputFiles.cpp
lld/trunk/ELF/InputFiles.h
lld/trunk/ELF/InputSection.h
lld/trunk/ELF/MarkLive.cpp
Modified: lld/trunk/ELF/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.cpp?rev=283734&r1=283733&r2=283734&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.cpp (original)
+++ lld/trunk/ELF/InputFiles.cpp Mon Oct 10 05:10:27 2016
@@ -145,6 +145,8 @@ void elf::ObjectFile<ELFT>::parse(DenseS
// Read section and symbol tables.
initializeSections(ComdatGroups);
initializeSymbols();
+ if (Config->GcSections && Config->EMachine == EM_ARM )
+ initializeReverseDependencies();
}
// Sections with SHT_GROUP and comdat bits define comdat section groups.
@@ -270,6 +272,24 @@ void elf::ObjectFile<ELFT>::initializeSe
}
}
+// .ARM.exidx sections have a reverse dependency on the InputSection they
+// have a SHF_LINK_ORDER dependency, this is identified by the sh_link.
+template <class ELFT>
+void elf::ObjectFile<ELFT>::initializeReverseDependencies() {
+ unsigned I = -1;
+ for (const Elf_Shdr &Sec : this->ELFObj.sections()) {
+ ++I;
+ if ((Sections[I] == &InputSection<ELFT>::Discarded) ||
+ !(Sec.sh_flags & SHF_LINK_ORDER))
+ continue;
+ if (Sec.sh_link >= Sections.size())
+ fatal(getFilename(this) + ": invalid sh_link index: " +
+ Twine(Sec.sh_link));
+ auto *IS = cast<InputSection<ELFT>>(Sections[Sec.sh_link]);
+ IS->DependentSection = Sections[I];
+ }
+}
+
template <class ELFT>
InputSectionBase<ELFT> *
elf::ObjectFile<ELFT>::getRelocTarget(const Elf_Shdr &Sec) {
Modified: lld/trunk/ELF/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.h?rev=283734&r1=283733&r2=283734&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.h (original)
+++ lld/trunk/ELF/InputFiles.h Mon Oct 10 05:10:27 2016
@@ -179,6 +179,7 @@ public:
private:
void initializeSections(llvm::DenseSet<StringRef> &ComdatGroups);
void initializeSymbols();
+ void initializeReverseDependencies();
InputSectionBase<ELFT> *getRelocTarget(const Elf_Shdr &Sec);
InputSectionBase<ELFT> *createInputSection(const Elf_Shdr &Sec);
Modified: lld/trunk/ELF/InputSection.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputSection.h?rev=283734&r1=283733&r2=283734&view=diff
==============================================================================
--- lld/trunk/ELF/InputSection.h (original)
+++ lld/trunk/ELF/InputSection.h Mon Oct 10 05:10:27 2016
@@ -235,6 +235,9 @@ public:
// to. The writer sets a value.
uint64_t OutSecOff = 0;
+ // InputSection that is dependent on us (reverse dependency for GC)
+ InputSectionBase<ELFT> *DependentSection = nullptr;
+
static bool classof(const InputSectionBase<ELFT> *S);
InputSectionBase<ELFT> *getRelocatedSection();
Modified: lld/trunk/ELF/MarkLive.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/MarkLive.cpp?rev=283734&r1=283733&r2=283734&view=diff
==============================================================================
--- lld/trunk/ELF/MarkLive.cpp (original)
+++ lld/trunk/ELF/MarkLive.cpp Mon Oct 10 05:10:27 2016
@@ -91,6 +91,8 @@ static void forEachSuccessor(InputSectio
Fn(resolveReloc(Sec, Rel));
}
}
+ if (Sec.DependentSection)
+ Fn({Sec.DependentSection, 0});
}
// The .eh_frame section is an unfortunate special case.
Added: lld/trunk/test/ELF/arm-exidx-gc.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-exidx-gc.s?rev=283734&view=auto
==============================================================================
--- lld/trunk/test/ELF/arm-exidx-gc.s (added)
+++ lld/trunk/test/ELF/arm-exidx-gc.s Mon Oct 10 05:10:27 2016
@@ -0,0 +1,123 @@
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
+// RUN: ld.lld %t -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
+// REQUIRES: arm
+
+// Test the behavior of .ARM.exidx sections under garbage collection
+// A .ARM.exidx section is live if it has a relocation to a live executable
+// section.
+// A .ARM.exidx section may have a relocation to a .ARM.extab section, if the
+// .ARM.exidx is live then the .ARM.extab section is live
+
+ .syntax unified
+ .section .text.func1, "ax",%progbits
+ .global func1
+func1:
+ .fnstart
+ bx lr
+ .save {r7, lr}
+ .setfp r7, sp, #0
+ .fnend
+
+ .section .text.unusedfunc1, "ax",%progbits
+ .global unusedfunc1
+unusedfunc1:
+ .fnstart
+ bx lr
+ .cantunwind
+ .fnend
+
+ // Unwinding instructions for .text2 too large for an inline entry ARM.exidx
+ // entry. A separate .ARM.extab section is created to hold the unwind entries
+ // The .ARM.exidx table entry has a reference to the .ARM.extab section.
+ .section .text.func2, "ax",%progbits
+ .global func2
+func2:
+ .fnstart
+ bx lr
+ .personality __gxx_personality_v0
+ .handlerdata
+ .section .text.func2
+ .fnend
+
+ // An unused function with a reference to a .ARM.extab section. Both should
+ // be removed by gc.
+ .section .text.unusedfunc2, "ax",%progbits
+ .global unusedfunc2
+unusedfunc2:
+ .fnstart
+ bx lr
+ .personality __gxx_personality_v1
+ .handlerdata
+ .section .text.unusedfunc2
+ .fnend
+
+ // 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:
+ .fnstart
+ bx lr
+ .cantunwind
+ .fnend
+
+ .section .text.__gcc_personality_v1, "ax", %progbits
+ .global __gxx_personality_v1
+__gxx_personality_v1:
+ .fnstart
+ bx lr
+ .cantunwind
+ .fnend
+
+ .section .text.__aeabi_unwind_cpp_pr0, "ax", %progbits
+ .global __aeabi_unwind_cpp_pr0
+__aeabi_unwind_cpp_pr0:
+ .fnstart
+ bx lr
+ .cantunwind
+ .fnend
+
+// Entry point for GC
+ .text
+ .global _start
+_start:
+ bl func1
+ bl func2
+ bx lr
+
+// GC should have only removed unusedfunc1 and unusedfunc2 the personality
+// routines are kept alive by references from live .ARM.exidx and .ARM.extab
+// sections
+// CHECK: Disassembly of section .text:
+// CHECK-NEXT: _start:
+// CHECK-NEXT: 11000: 01 00 00 eb bl #4 <func1>
+// CHECK-NEXT: 11004: 01 00 00 eb bl #4 <func2>
+// CHECK-NEXT: 11008: 1e ff 2f e1 bx lr
+// CHECK: func1:
+// CHECK-NEXT: 1100c: 1e ff 2f e1 bx lr
+// CHECK: func2:
+// CHECK-NEXT: 11010: 1e ff 2f e1 bx lr
+// CHECK: __gxx_personality_v0:
+// CHECK-NEXT: 11014: 1e ff 2f e1 bx lr
+// CHECK: __aeabi_unwind_cpp_pr0:
+// CHECK-NEXT: 11018: 1e ff 2f e1 bx lr
+
+// GC should have removed table entries for unusedfunc1, unusedfunc2
+// and __gxx_personality_v1
+// CHECK-NOT: unusedfunc1
+// CHECK-NOT: unusedfunc2
+// CHECK-NOT: __gxx_personality_v1
+
+// CHECK-EXIDX-NOT: Contents of section .ARM.extab.text.unusedfunc2:
+// CHECK-EXIDX: Contents of section .ARM.exidx:
+// 100d4 + f38 = 1100c = func1
+// 100dc + f34 = 11010 = func2 (100e0 + 14 = 100f4 = .ARM.extab.text.func2)
+// CHECK-EXIDX-NEXT: 100d4 380f0000 08849780 340f0000 14000000
+// 100e4 + f30 = 11014 = __gxx_personality_v0
+// 100ec + f2c = 11018 = __aeabi_unwind_cpp_pr0
+// CHECK-EXIDX-NEXT: 100e4 300f0000 01000000 2c0f0000 01000000
+// CHECK-EXIDX-NEXT: Contents of section .ARM.extab.text.func2:
+// 100f4 + f20 = 11014 = __gxx_personality_v0
+// CHECK-EXIDX-NEXT: 100f4 200f0000 b0b0b000
More information about the llvm-commits
mailing list