Skip to content

Commit

Permalink
[ELF] Prevent crash in writing an .ARM.exidx sentinel entry.
Browse files Browse the repository at this point in the history
We might crash in 'ARMExidxSentinelSection::writeTo()' because it expected
the sentinel entry to be put in the same 'InputSectionDescription' as
the last real entry. This assumption fails if the last output section command
for .ARM.exidx is anything but an input section description, because in this
case 'OutputSection::addSection()' creates a new 'InputSectionDescription'.

Differential Revision: https://reviews.llvm.org/D41105

llvm-svn: 320668
  • Loading branch information
igorkudrin committed Dec 14, 2017
1 parent b308cac commit f01caab
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 9 deletions.
24 changes: 15 additions & 9 deletions lld/ELF/SyntheticSections.cpp
Expand Up @@ -2569,16 +2569,22 @@ ARMExidxSentinelSection::ARMExidxSentinelSection()
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. By construction the Sentinel is in the last
// InputSectionDescription as the InputSection that precedes it.
// sentinel.
OutputSection *C = getParent();
auto ISD =
std::find_if(C->SectionCommands.rbegin(), C->SectionCommands.rend(),
[](const BaseCommand *Base) {
return isa<InputSectionDescription>(Base);
});
auto L = cast<InputSectionDescription>(*ISD);
InputSection *Highest = L->Sections[L->Sections.size() - 2];
InputSection *Highest = nullptr;
int 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 P = getVA();
Expand Down
24 changes: 24 additions & 0 deletions lld/test/ELF/linkerscript/arm-exidx-sentinel-and-assignment.s
@@ -0,0 +1,24 @@
# REQUIRES: arm
# RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o
# RUN: echo "SECTIONS { \
# RUN: .ARM.exidx 0x1000 : { *(.ARM.exidx*) foo = .; } \
# RUN: .text 0x2000 : { *(.text*) } \
# RUN: }" > %t.script
## We used to crash if the last output section command for .ARM.exidx
## was anything but an input section description.
# RUN: ld.lld -T %t.script %t.o -shared -o %t.so
# RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t.so | FileCheck %s

.syntax unified
.text
.global _start
_start:
.fnstart
.cantunwind
bx lr
.fnend

// CHECK: Contents of section .ARM.exidx:
// 1000 + 1000 = 0x2000 = _start
// 1008 + 0ffc = 0x2004 = _start + sizeof(_start)
// CHECK-NEXT: 1000 00100000 01000000 fc0f0000 01000000

0 comments on commit f01caab

Please sign in to comment.