Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -20,6 +20,7 @@ #include "OutputSections.h" #include "ScriptParser.h" #include "SymbolTable.h" +#include "Target.h" #include "llvm/ADT/StringSwitch.h" #include "llvm/Support/ELF.h" #include "llvm/Support/FileSystem.h" @@ -221,8 +222,9 @@ } // Assign addresses as instructed by linker script SECTIONS sub-commands. - Dot = Out::ElfHeader->getSize() + Out::ProgramHeaders->getSize(); - uintX_t ThreadBssOffset = 0; + Dot = Out::ElfHeader->getSize() + Out::ProgramHeaders->getSize(); + uintX_t MinVA = std::numeric_limits::max(); + uintX_t ThreadBssOffset = 0; for (SectionsCommand &Cmd : Opt.Commands) { if (Cmd.Kind == ExprKind) { @@ -248,11 +250,17 @@ if (Sec->getFlags() & SHF_ALLOC) { Dot = alignTo(Dot, Sec->getAlignment()); Sec->setVA(Dot); + MinVA = std::min(MinVA, Dot); Dot += Sec->getSize(); continue; } } } + + MinVA = alignDown(MinVA - Out::ElfHeader->getSize() - + Out::ProgramHeaders->getSize(), Target->PageSize); + Out::ElfHeader->setVA(MinVA); + Out::ProgramHeaders->setVA(Out::ElfHeader->getSize() + MinVA); } template Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -1186,6 +1186,14 @@ uintX_t Off = Out::ElfHeader->getSize() + Out::ProgramHeaders->getSize(); + if (ScriptConfig->DoLayout && OutputSections.size()) { + // File offsets should always be equal section virtual addresses + // modulo page size. In case linker script is used we enforce this constraint + // for ELF headers here + OutputSectionBase *Sec = OutputSections.front(); + Off = Sec->getVA() - alignDown(Sec->getVA() - Off, Target->PageSize); + } + for (OutputSectionBase *Sec : OutputSections) { if (Sec->getType() == SHT_NOBITS) { Sec->setFileOffset(Off); @@ -1227,7 +1235,7 @@ Out::TlsPhdr = &H; H.p_memsz = alignTo(H.p_memsz, H.p_align); } - } + } } static uint32_t getMipsEFlags(bool Is64Bits) { Index: test/ELF/linkerscript-phdr-check.s =================================================================== --- test/ELF/linkerscript-phdr-check.s +++ test/ELF/linkerscript-phdr-check.s @@ -0,0 +1,16 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +# RUN: echo "SECTIONS { . = 0x10000000; .text : {*(.text.*)} }" > %t.script +# RUN: ld.lld -o %t1 --script %t.script %t +# RUN: llvm-readobj -program-headers %t1 | FileCheck %s +# CHECK: ProgramHeaders [ +# CHECK-NEXT: ProgramHeader { +# CHECK-NEXT: Type: PT_PHDR (0x6) +# CHECK-NEXT: Offset: 0x40 +# CHECK-NEXT: VirtualAddress: 0xFFFF040 + +.global _start +_start: + nop +