forked from OSchip/llvm-project
[LLD][ELF][ARM] Fix ARM Exidx order for non monotonic section order
The contents of the .ARM.exidx section must be ordered by SHF_LINK_ORDER rules. We don't need to know the precise address for this order, but we do need to know the relative order of sections. We have been using the sectionIndex for this purpose, this works when the OutputSection order has a monotonically increasing virtual address, but it is possible to write a linker script with non-monotonically increasing virtual address. For these cases we need to evaluate the base address of the OutputSection so that we can order the .ARM.exidx sections properly. This change moves the finalisation of .ARM.exidx till after the first call to AssignAddresses. This permits us to sort on virtual address which is linker script safe. It also permits a fix for part of pr44824 where we generate .ARM.exidx section for the vector table when that table is so far away it is out of range of the .ARM.exidx section. This fix will come in a follow up patch. Differential Revision: https://reviews.llvm.org/D78422
This commit is contained in:
parent
b0a1c0b72c
commit
f969c2aa65
|
@ -3363,14 +3363,14 @@ void ARMExidxSyntheticSection::finalizeContents() {
|
||||||
|
|
||||||
// Sort the executable sections that may or may not have associated
|
// Sort the executable sections that may or may not have associated
|
||||||
// .ARM.exidx sections by order of ascending address. This requires the
|
// .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,
|
auto compareByFilePosition = [](const InputSection *a,
|
||||||
const InputSection *b) {
|
const InputSection *b) {
|
||||||
OutputSection *aOut = a->getParent();
|
OutputSection *aOut = a->getParent();
|
||||||
OutputSection *bOut = b->getParent();
|
OutputSection *bOut = b->getParent();
|
||||||
|
|
||||||
if (aOut != bOut)
|
if (aOut != bOut)
|
||||||
return aOut->sectionIndex < bOut->sectionIndex;
|
return aOut->addr < bOut->addr;
|
||||||
return a->outSecOff < b->outSecOff;
|
return a->outSecOff < b->outSecOff;
|
||||||
};
|
};
|
||||||
llvm::stable_sort(executableSections, compareByFilePosition);
|
llvm::stable_sort(executableSections, compareByFilePosition);
|
||||||
|
|
|
@ -1604,6 +1604,11 @@ template <class ELFT> void Writer<ELFT>::resolveShfLinkOrder() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
// 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
|
// 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
|
// addresses we must converge to a fixed point. We do that here. See the comment
|
||||||
|
@ -1613,6 +1618,11 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
|
||||||
AArch64Err843419Patcher a64p;
|
AArch64Err843419Patcher a64p;
|
||||||
ARMErr657417Patcher a32p;
|
ARMErr657417Patcher a32p;
|
||||||
script->assignAddresses();
|
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
|
// Converts call x@GDPLT to call __tls_get_addr
|
||||||
if (config->emachine == EM_HEXAGON)
|
if (config->emachine == EM_HEXAGON)
|
||||||
|
@ -1762,11 +1772,6 @@ template <class ELFT> void Writer<ELFT>::optimizeBasicBlockJumps() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void finalizeSynthetic(SyntheticSection *sec) {
|
|
||||||
if (sec && sec->isNeeded() && sec->getParent())
|
|
||||||
sec->finalizeContents();
|
|
||||||
}
|
|
||||||
|
|
||||||
// In order to allow users to manipulate linker-synthesized sections,
|
// In order to allow users to manipulate linker-synthesized sections,
|
||||||
// we had to add synthetic sections to the input section list early,
|
// we had to add synthetic sections to the input section list early,
|
||||||
// even before we make decisions whether they are needed. This allows
|
// even before we make decisions whether they are needed. This allows
|
||||||
|
@ -2035,7 +2040,6 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
|
||||||
// Dynamic section must be the last one in this list and dynamic
|
// Dynamic section must be the last one in this list and dynamic
|
||||||
// symbol table section (dynSymTab) must be the first one.
|
// symbol table section (dynSymTab) must be the first one.
|
||||||
for (Partition &part : partitions) {
|
for (Partition &part : partitions) {
|
||||||
finalizeSynthetic(part.armExidx);
|
|
||||||
finalizeSynthetic(part.dynSymTab);
|
finalizeSynthetic(part.dynSymTab);
|
||||||
finalizeSynthetic(part.gnuHashTab);
|
finalizeSynthetic(part.gnuHashTab);
|
||||||
finalizeSynthetic(part.hashTab);
|
finalizeSynthetic(part.hashTab);
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
// 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
|
Loading…
Reference in New Issue