Index: lld/trunk/ELF/Writer.cpp =================================================================== --- lld/trunk/ELF/Writer.cpp +++ lld/trunk/ELF/Writer.cpp @@ -1662,6 +1662,24 @@ } } +// Adjusts the file alignment for a given output section and returns +// its new file offset. The file offset must be the same with its +// virtual address (modulo the page size) so that the loader can load +// executables without any address adjustment. +template +static uintX_t getFileAlignment(uintX_t Off, OutputSectionBase *Sec) { + uintX_t Align = Sec->getAlign(); + if (Sec->PageAlign) + Align = std::max(Align, Target->PageSize); + Off = alignTo(Off, Align); + + // Relocatable output does not have program headers + // and does not need any other offset adjusting. + if (Config->Relocatable || !(Sec->getFlags() & SHF_ALLOC)) + return Off; + return alignTo(Off, Target->PageSize, Sec->getVA()); +} + // Assign file offsets to output sections. template void Writer::assignFileOffsets() { uintX_t Off = @@ -1672,10 +1690,8 @@ Sec->setFileOffset(Off); continue; } - uintX_t Align = Sec->getAlign(); - if (Sec->PageAlign) - Align = std::max(Align, Target->PageSize); - Off = alignTo(Off, Align); + + Off = getFileAlignment(Off, Sec); Sec->setFileOffset(Off); Off += Sec->getSize(); } Index: lld/trunk/test/ELF/phdr-align.s =================================================================== --- lld/trunk/test/ELF/phdr-align.s +++ lld/trunk/test/ELF/phdr-align.s @@ -0,0 +1,82 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o + +# RUN: echo "SECTIONS { \ +# RUN: .bss : { *(.bss) } \ +# RUN: .data : { *(.data) } \ +# RUN: .text : { *(.text) } }" > %t.script +# RUN: ld.lld %t.o --script %t.script -o %t +# RUN: llvm-readobj -sections -symbols %t | FileCheck %s + +# CHECK: Sections [ +# CHECK-NEXT: Section { +# CHECK-NEXT: Index: 0 +# CHECK-NEXT: Name: (0) +# CHECK-NEXT: Type: SHT_NULL +# CHECK-NEXT: Flags [ +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x0 +# CHECK-NEXT: Offset: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Link: 0 +# CHECK-NEXT: Info: 0 +# CHECK-NEXT: AddressAlignment: 0 +# CHECK-NEXT: EntrySize: 0 +# CHECK-NEXT: } +# CHECK-NEXT: Section { +# CHECK-NEXT: Index: 1 +# CHECK-NEXT: Name: .bss +# CHECK-NEXT: Type: SHT_NOBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: SHF_WRITE +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x158 +# CHECK-NEXT: Offset: 0x158 +# CHECK-NEXT: Size: 6 +# CHECK-NEXT: Link: 0 +# CHECK-NEXT: Info: 0 +# CHECK-NEXT: AddressAlignment: 1 +# CHECK-NEXT: EntrySize: 0 +# CHECK-NEXT: } +# CHECK-NEXT: Section { +# CHECK-NEXT: Index: 2 +# CHECK-NEXT: Name: .data +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: SHF_WRITE +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x15E +# CHECK-NEXT: Offset: 0x15E +# CHECK-NEXT: Size: 2 +# CHECK-NEXT: Link: 0 +# CHECK-NEXT: Info: 0 +# CHECK-NEXT: AddressAlignment: 1 +# CHECK-NEXT: EntrySize: 0 +# CHECK-NEXT: } +# CHECK-NEXT: Section { +# CHECK-NEXT: Index: 3 +# CHECK-NEXT: Name: .text +# CHECK-NEXT: Type: SHT_PROGBITS +# CHECK-NEXT: Flags [ +# CHECK-NEXT: SHF_ALLOC +# CHECK-NEXT: SHF_EXECINSTR +# CHECK-NEXT: ] +# CHECK-NEXT: Address: 0x160 +# CHECK-NEXT: Offset: 0x160 +# CHECK-NEXT: Size: 1 +# CHECK-NEXT: Link: 0 +# CHECK-NEXT: Info: 0 +# CHECK-NEXT: AddressAlignment: 4 +# CHECK-NEXT: EntrySize: 0 +# CHECK-NEXT: } + +.global _start +.text +_start: + nop +.data + .word 1 +.bss + .space 6