bool ARMExidxSyntheticSection::addSection(InputSection *isec) {
if (isec->type == SHT_ARM_EXIDX) {
if (InputSection *dep = isec->getLinkOrderDep())
- if (isValidExidxSectionDep(dep))
+ if (isValidExidxSectionDep(dep)) {
exidxSections.push_back(isec);
+ // Every exidxSection is 8 bytes, we need an estimate of
+ // size before assignAddresses can be called. Final size
+ // will only be known after finalize is called.
+ size += 8;
+ }
return true;
}
// 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.
+ // relative positions of InputSections and OutputSections 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 aOut->addr < bOut->addr;
return a->outSecOff < b->outSecOff;
};
llvm::stable_sort(executableSections, compareByFilePosition);
std::vector<InputSection *> exidxSections;
private:
- size_t size;
+ size_t size = 0;
// Instead of storing pointers to the .ARM.exidx InputSections from
// InputObjects, we store pointers to the executable sections that need
}
}
+static void finalizeSynthetic(SyntheticSection *sec) {
+ if (sec && sec->isNeeded() && sec->getParent())
+ sec->finalizeContents();
+}
+
// We need to generate and finalize the content that depends on the address of
// InputSections. As the generation of the content may also alter InputSection
// addresses we must converge to a fixed point. We do that here. See the comment
AArch64Err843419Patcher a64p;
ARMErr657417Patcher a32p;
script->assignAddresses();
+ // .ARM.exidx does not require precise addresses, but it does require the
+ // relative addresses of OutputSections because linker scripts can assign
+ // Virtual Addresses to OutputSections that are not monotonically increasing.
+ for (Partition &part : partitions)
+ finalizeSynthetic(part.armExidx);
// Converts call x@GDPLT to call __tls_get_addr
if (config->emachine == EM_HEXAGON)
}
}
-static void finalizeSynthetic(SyntheticSection *sec) {
- if (sec && sec->isNeeded() && sec->getParent())
- sec->finalizeContents();
-}
-
// In order to allow users to manipulate linker-synthesized sections,
// we had to add synthetic sections to the input section list early,
// even before we make decisions whether they are needed. This allows
// Dynamic section must be the last one in this list and dynamic
// symbol table section (dynSymTab) must be the first one.
for (Partition &part : partitions) {
- finalizeSynthetic(part.armExidx);
finalizeSynthetic(part.dynSymTab);
finalizeSynthetic(part.gnuHashTab);
finalizeSynthetic(part.hashTab);
--- /dev/null
+// REQUIRES: arm
+// RUN: llvm-mc --arm-add-build-attributes --triple=armv7a-linux-gnueabihf -filetype=obj %s -o %t.o
+// RUN: echo "SECTIONS { \
+// RUN: . = 0x80000000; \
+// RUN: .ARM.exidx : { *(.ARM.exidx) } \
+// RUN: .text : { *(.text) } \
+// RUN: .text.1 0x80000200 : AT(0x1000) { *(.text.1) } \
+// RUN: .text.2 0x80000100 : AT(0x2000) { *(.text.2) } \
+// RUN: } " > %t.script
+// RUN: ld.lld --script %t.script %t.o -o %t
+// RUN: llvm-readobj -x .ARM.exidx %t | FileCheck %s
+
+/// When a linker script does not have monotonically increasing addresses
+/// the .ARM.exidx table should still be in monotonically increasing order.
+
+// CHECK: Hex dump of section '.ARM.exidx':
+// 0x80000000 + 0x28 = 0x80000028, 0x80000008 + 0xf8 = 0x80000100
+// CHECK-NEXT: 0x80000000 24000000 08849780 f8000000 20849980
+// 0x80000010 + 0x1f0 = 0x8000200, 0x80000018 + 0x1ec = 0x8000204
+// CHECK-NEXT: 0x80000010 f0010000 10849880 ec010000 01000000
+
+ .text
+ .global _start
+ .type _start, %function
+_start:
+ .fnstart
+ bx lr
+ .save {r7, lr}
+ .setfp r7, sp, #0
+ .fnend
+
+ .section .text.1, "ax", %progbits
+ .global fn1
+ .type fn1, %function
+fn1:
+ .fnstart
+ bx lr
+ .save {r8, lr}
+ .setfp r8, sp, #0
+ .fnend
+
+ .section .text.2, "ax", %progbits
+ .global fn2
+ .type fn2, %function
+fn2:
+ .fnstart
+ bx lr
+ .save {r9, lr}
+ .setfp r9, sp, #0
+ .fnend
+
+/// Dummy definition for a reference from the personality routine created by
+/// the assembler, use .data to avoid generating a cantunwind table.
+ .section .rodata
+ .global __aeabi_unwind_cpp_pr0
+__aeabi_unwind_cpp_pr0:
+ .word 0