From 3834385f27aeb4cafe1f5f957bff36bdbececf81 Mon Sep 17 00:00:00 2001 From: Peter Smith Date: Wed, 22 Apr 2020 20:28:52 +0100 Subject: [PATCH] [ELF] Move SHF_LINK_ORDER till OutputSection addresses are known 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 --- lld/ELF/Writer.cpp | 18 ++++++++---------- lld/test/ELF/linkorder-script.s | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 10 deletions(-) create mode 100644 lld/test/ELF/linkorder-script.s diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 3c197391a91a9..b5a8c33ddd8d4 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -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; } @@ -1666,11 +1666,13 @@ template void Writer::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) @@ -2104,12 +2106,6 @@ template void Writer::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 @@ -2132,6 +2128,8 @@ template void Writer::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); diff --git a/lld/test/ELF/linkorder-script.s b/lld/test/ELF/linkorder-script.s new file mode 100644 index 0000000000000..6bf2887abb2a5 --- /dev/null +++ b/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