Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -1638,6 +1638,29 @@ } } +// System V ABI 4.1 specifies that program header's +// p_vaddr should equal p_offset, modulo p_align. +// (http://www.x86-64.org/documentation/abi.pdf, p.76), +// this method used to adjust sections file offsets. +template +static uintX_t alignOffset(uintX_t Off, uintX_t Align, + OutputSectionBase *Sec) { + 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; + + uintX_t PageSize = Target->PageSize; + uintX_t VA = Sec->getVA(); + if ((VA % PageSize) != (Off % PageSize)) { + uintX_t Val = ((Off & ~(PageSize - 1)) | (VA % PageSize)); + Off = Val < Off ? (Val + PageSize) : Val; + } + return Off; +} + // Assign file offsets to output sections. template void Writer::assignFileOffsets() { uintX_t Off = @@ -1651,7 +1674,7 @@ uintX_t Align = Sec->getAlign(); if (Sec->PageAlign) Align = std::max(Align, Target->PageSize); - Off = alignTo(Off, Align); + Off = alignOffset(Off, Align, Sec); Sec->setFileOffset(Off); Off += Sec->getSize(); } Index: test/ELF/phdr-align.s =================================================================== --- test/ELF/phdr-align.s +++ 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