[lld] r321154 - [ELF] Fix an assignment command at the end of an .ARM.exidx section.
Igor Kudrin via llvm-commits
llvm-commits at lists.llvm.org
Wed Dec 20 00:56:10 PST 2017
Author: ikudrin
Date: Wed Dec 20 00:56:10 2017
New Revision: 321154
URL: http://llvm.org/viewvc/llvm-project?rev=321154&view=rev
Log:
[ELF] Fix an assignment command at the end of an .ARM.exidx section.
The value of the symbol in the assignment should include the sentinel entry.
Differential Revision: https://reviews.llvm.org/D41234
Added:
lld/trunk/test/ELF/arm-exidx-dedup-and-sentinel.s
Modified:
lld/trunk/ELF/SyntheticSections.cpp
lld/trunk/ELF/SyntheticSections.h
lld/trunk/ELF/Writer.cpp
lld/trunk/test/ELF/linkerscript/arm-exidx-sentinel-and-assignment.s
Modified: lld/trunk/ELF/SyntheticSections.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.cpp?rev=321154&r1=321153&r2=321154&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.cpp (original)
+++ lld/trunk/ELF/SyntheticSections.cpp Wed Dec 20 00:56:10 2017
@@ -2561,31 +2561,25 @@ ARMExidxSentinelSection::ARMExidxSentine
// 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) {
- // The Sections are sorted in order of ascending PREL31 address with the
- // sentinel last. We need to find the InputSection that precedes the
- // sentinel.
- OutputSection *C = getParent();
- InputSection *Highest = nullptr;
- unsigned Skip = 1;
- for (const BaseCommand *Base : llvm::reverse(C->SectionCommands)) {
- if (!isa<InputSectionDescription>(Base))
- continue;
- auto L = cast<InputSectionDescription>(Base);
- if (Skip >= L->Sections.size()) {
- Skip -= L->Sections.size();
- continue;
- }
- Highest = L->Sections[L->Sections.size() - Skip - 1];
- break;
- }
assert(Highest);
- InputSection *LS = Highest->getLinkOrderDep();
- uint64_t S = LS->getParent()->Addr + LS->getOffset(LS->getSize());
+ uint64_t S =
+ Highest->getParent()->Addr + Highest->getOffset(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 {
+ OutputSection *OS = getParent();
+ for (auto *B : OS->SectionCommands)
+ if (auto *ISD = dyn_cast<InputSectionDescription>(B))
+ for (auto *S : ISD->Sections)
+ if (!isa<ARMExidxSentinelSection>(S))
+ return false;
+ return true;
+}
+
ThunkSection::ThunkSection(OutputSection *OS, uint64_t Off)
: SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS,
Config->Wordsize, ".text.thunk") {
Modified: lld/trunk/ELF/SyntheticSections.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/SyntheticSections.h?rev=321154&r1=321153&r2=321154&view=diff
==============================================================================
--- lld/trunk/ELF/SyntheticSections.h (original)
+++ lld/trunk/ELF/SyntheticSections.h Wed Dec 20 00:56:10 2017
@@ -785,6 +785,9 @@ public:
ARMExidxSentinelSection();
size_t getSize() const override { return 8; }
void writeTo(uint8_t *Buf) override;
+ bool empty() const override;
+
+ InputSection *Highest = 0;
};
// A container for one or more linker generated thunks. Instances of these
Modified: lld/trunk/ELF/Writer.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Writer.cpp?rev=321154&r1=321153&r2=321154&view=diff
==============================================================================
--- lld/trunk/ELF/Writer.cpp (original)
+++ lld/trunk/ELF/Writer.cpp Wed Dec 20 00:56:10 2017
@@ -54,7 +54,6 @@ private:
void resolveShfLinkOrder();
void sortInputSections();
void finalizeSections();
- void addPredefinedSections();
void setReservedSymbolSections();
std::vector<PhdrEntry *> createPhdrs();
@@ -390,6 +389,11 @@ template <class ELFT> static void create
Add(InX::ShStrTab);
if (InX::StrTab)
Add(InX::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<ARMExidxSentinelSection>());
}
// The main function of the writer.
@@ -1145,10 +1149,10 @@ template <class ELFT> void Writer<ELFT>:
}
static bool compareByFilePosition(InputSection *A, InputSection *B) {
- // Synthetic doesn't have link order dependecy, stable_sort will keep it last
+ // Synthetic, i. e. a sentinel section, should go last.
if (A->kind() == InputSectionBase::Synthetic ||
B->kind() == InputSectionBase::Synthetic)
- return false;
+ return A->kind() != InputSectionBase::Synthetic;
InputSection *LA = A->getLinkOrderDep();
InputSection *LB = B->getLinkOrderDep();
OutputSection *AOut = LA->getParent();
@@ -1231,23 +1235,37 @@ template <class ELFT> void Writer<ELFT>:
}
std::stable_sort(Sections.begin(), Sections.end(), compareByFilePosition);
- if (Config->MergeArmExidx && !Config->Relocatable &&
- Config->EMachine == EM_ARM && Sec->Type == SHT_ARM_EXIDX) {
- // 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.
- int Cur = 1;
- int Prev = 0;
- int N = Sections.size();
- while (Cur < N) {
- if (isDuplicateArmExidxSec(Sections[Prev], Sections[Cur]))
- Sections[Cur] = nullptr;
- else
- Prev = Cur;
- ++Cur;
+ if (!Config->Relocatable && Config->EMachine == EM_ARM &&
+ Sec->Type == SHT_ARM_EXIDX) {
+
+ if (!Sections.empty() && isa<ARMExidxSentinelSection>(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.
+ auto *Sentinel = cast<ARMExidxSentinelSection>(Sections.back());
+ Sentinel->Highest = Sections[Sections.size() - 2]->getLinkOrderDep();
+ }
+
+ if (Config->MergeArmExidx) {
+ // 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.
+ int Cur = 1;
+ int Prev = 0;
+ // The last one is a sentinel entry which should not be removed.
+ int N = Sections.size() - 1;
+ while (Cur < N) {
+ if (isDuplicateArmExidxSec(Sections[Prev], Sections[Cur]))
+ Sections[Cur] = nullptr;
+ else
+ Prev = Cur;
+ ++Cur;
+ }
}
}
@@ -1413,7 +1431,6 @@ template <class ELFT> void Writer<ELFT>:
if (errorCount())
return;
- addPredefinedSections();
removeUnusedSyntheticSections();
sortSections();
@@ -1510,17 +1527,6 @@ template <class ELFT> void Writer<ELFT>:
[](SyntheticSection *SS) { SS->postThunkContents(); });
}
-template <class ELFT> void Writer<ELFT>::addPredefinedSections() {
- // ARM ABI requires .ARM.exidx to be terminated by some piece of data.
- // We have the terminater synthetic section class. Add that at the end.
- OutputSection *Cmd = findSection(".ARM.exidx");
- if (!Cmd || !Cmd->Live || Config->Relocatable)
- return;
-
- auto *Sentinel = make<ARMExidxSentinelSection>();
- Cmd->addSection(Sentinel);
-}
-
// The linker is expected to define SECNAME_start and SECNAME_end
// symbols for a few sections. This function defines them.
template <class ELFT> void Writer<ELFT>::addStartEndSymbols() {
Added: lld/trunk/test/ELF/arm-exidx-dedup-and-sentinel.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/arm-exidx-dedup-and-sentinel.s?rev=321154&view=auto
==============================================================================
--- lld/trunk/test/ELF/arm-exidx-dedup-and-sentinel.s (added)
+++ lld/trunk/test/ELF/arm-exidx-dedup-and-sentinel.s Wed Dec 20 00:56:10 2017
@@ -0,0 +1,29 @@
+// REQUIRES: arm
+// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o
+// RUN: ld.lld %t.o -shared -o %t.so --section-start .text=0x2000 --section-start .ARM.exidx=0x1000
+// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t.so | FileCheck %s
+
+ .syntax unified
+
+ .section .text.foo, "ax", %progbits
+ .globl foo
+foo:
+ .fnstart
+ bx lr
+ .cantunwind
+ .fnend
+
+ .section .text.bar, "ax", %progbits
+ .globl bar
+bar:
+ .fnstart
+ bx lr
+ .cantunwind
+ .fnend
+
+// CHECK: Contents of section .ARM.exidx:
+// 1000 + 1000 = 0x2000 = foo
+// The entry for bar is the same as previous and is eliminated.
+// The sentinel entry should be preserved.
+// 1008 + 1000 = 0x2008 = bar + sizeof(bar)
+// CHECK-NEXT: 1000 00100000 01000000 00100000 01000000
Modified: lld/trunk/test/ELF/linkerscript/arm-exidx-sentinel-and-assignment.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/linkerscript/arm-exidx-sentinel-and-assignment.s?rev=321154&r1=321153&r2=321154&view=diff
==============================================================================
--- lld/trunk/test/ELF/linkerscript/arm-exidx-sentinel-and-assignment.s (original)
+++ lld/trunk/test/ELF/linkerscript/arm-exidx-sentinel-and-assignment.s Wed Dec 20 00:56:10 2017
@@ -8,6 +8,7 @@
## was anything but an input section description.
# RUN: ld.lld --no-merge-exidx-entries -T %t.script %t.o -shared -o %t.so
# RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t.so | FileCheck %s
+# RUN: llvm-readobj -s -t %t.so | FileCheck %s --check-prefix=SYMBOL
.syntax unified
.text
@@ -22,3 +23,19 @@ _start:
# 1000 + 1000 = 0x2000 = _start
# 1008 + 0ffc = 0x2004 = _start + sizeof(_start)
# CHECK-NEXT: 1000 00100000 01000000 fc0f0000 01000000
+
+# SYMBOL: Section {
+# SYMBOL: Name: .ARM.exidx
+# SYMBOL-NEXT: Type: SHT_ARM_EXIDX
+# SYMBOL-NEXT: Flags [
+# SYMBOL-NEXT: SHF_ALLOC
+# SYMBOL-NEXT: SHF_LINK_ORDER
+# SYMBOL-NEXT: ]
+# SYMBOL-NEXT: Address: 0x1000
+# SYMBOL-NEXT: Offset:
+# SYMBOL-NEXT: Size: 16
+
+# Symbol 'foo' is expected to point at the end of the section.
+# SYMBOL: Symbol {
+# SYMBOL: Name: foo
+# SYMBOL-NEXT: Value: 0x1010
More information about the llvm-commits
mailing list