Skip to content

Commit

Permalink
[ELF] Move SHF_LINK_ORDER till OutputSection addresses are known
Browse files Browse the repository at this point in the history
Sections with the SHF_LINK_ORDER flag must be ordered in the same relative
order as the Sections they have a link to. When using a linker script an
arbitrary expression may be used for the virtual address of the
OutputSection. In some cases the virtual address does not monotonically
increase as the OutputSection index increases, so if we base the ordering
of the SHF_LINK_ORDER sections on the index then we can get the order
wrong. We fix this by moving SHF_LINK_ORDER resolution till after we have
created OutputSection virtual addresses.

Differential Revision: https://reviews.llvm.org/D79286
  • Loading branch information
smithp35 committed May 4, 2020
1 parent ff4a3ee commit 3834385
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 10 deletions.
18 changes: 8 additions & 10 deletions lld/ELF/Writer.cpp
Expand Up @@ -1596,7 +1596,7 @@ static bool compareByFilePosition(InputSection *a, InputSection *b) {
OutputSection *bOut = lb->getParent();

if (aOut != bOut)
return aOut->sectionIndex < bOut->sectionIndex;
return aOut->addr < bOut->addr;
return la->outSecOff < lb->outSecOff;
}

Expand Down Expand Up @@ -1666,11 +1666,13 @@ template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
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.
// .ARM.exidx and SHF_LINK_ORDER do not require precise addresses, but they
// do 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);
resolveShfLinkOrder();

// Converts call x@GDPLT to call __tls_get_addr
if (config->emachine == EM_HEXAGON)
Expand Down Expand Up @@ -2104,12 +2106,6 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
if (!script->hasSectionsCommand && !config->relocatable)
fixSectionAlignments();

// SHFLinkOrder processing must be processed after relative section placements are
// known but before addresses are allocated.
resolveShfLinkOrder();
if (errorCount())
return;

// This is used to:
// 1) Create "thunks":
// Jump instructions in many ISAs have small displacements, and therefore
Expand All @@ -2132,6 +2128,8 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
// sometimes using forward symbol declarations. We want to set the correct
// values. They also might change after adding the thunks.
finalizeAddressDependentContent();
if (errorCount())
return;

// finalizeAddressDependentContent may have added local symbols to the static symbol table.
finalizeSynthetic(in.symTab);
Expand Down
32 changes: 32 additions & 0 deletions lld/test/ELF/linkorder-script.s
@@ -0,0 +1,32 @@
// REQUIRES: x86
// RUN: llvm-mc --triple=x86_64 -filetype=obj %s -o %t.o
// RUN: echo "SECTIONS { \
// RUN: . = 0x80000000; \
// RUN: .linkorder : { *(.linkorder.*) } \
// 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 .linkorder %t | FileCheck %s

/// When a linker script does not have monotonically increasing addresses
/// the SHF_LINK_ORDER sections should still be in monotonically increasing
/// order.

// CHECK: Hex dump of section '.linkorder':
// CHECK-NEXT: 0x80000000 0201

.section .text.1, "ax", %progbits
.global _start
_start:
nop

.section .text.2, "ax", %progbits
.byte 0

.section .linkorder.1, "ao", %progbits, .text.1
.byte 1

.section .linkorder.2, "ao", %progbits, .text.2
.byte 2

0 comments on commit 3834385

Please sign in to comment.