Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -2271,7 +2271,10 @@ static uint64_t computeFileOffset(OutputSection *os, uint64_t off) { // File offsets are not significant for .bss sections. By convention, we keep // section offsets monotonically increasing rather than setting to zero. - if (os->type == SHT_NOBITS) + // However, if os is the first section of a PT_LOAD segment, p_offset of the + // segment will be set to the offset of os, we must align sh_offset to ensure + // p_vaddr=p_offset (mod p_align). + if (os->type == SHT_NOBITS && !(os->ptLoad && os->ptLoad->firstSec == os)) return off; // If the section is not in a PT_LOAD, we just have to align it. Index: test/ELF/linkerscript/nobits-offset.s =================================================================== --- test/ELF/linkerscript/nobits-offset.s +++ test/ELF/linkerscript/nobits-offset.s @@ -2,17 +2,24 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o # RUN: echo "SECTIONS { \ # RUN: .sec1 (NOLOAD) : { . += 1; } \ -# RUN: .text : { *(.text) } \ +# RUN: .bss : { *(.bss) } \ # RUN: };" > %t.script # RUN: ld.lld %t.o -T %t.script -o %t -# RUN: llvm-readelf --sections %t | FileCheck %s +# RUN: llvm-readelf -S -l %t | FileCheck %s -# We used to misalign section offsets if the first section in a -# PT_LOAD was SHT_NOBITS. +## If a SHT_NOBITS section is the only section of a PT_LOAD segment, +## p_offset will be set to the sh_offset field of the section. Check we align +## sh_offset to sh_addr modulo max-page-size, so that p_vaddr=p_offset (mod +## p_align). -# CHECK: [ 2] .text PROGBITS 0000000000000010 001010 000010 00 AX 0 0 16 +# CHECK: Name Type Address Off Size ES Flg Lk Inf Al +# CHECK: .bss NOBITS 0000000000000400 001400 000001 00 WA 0 0 1024 -.global _start -_start: - nop -.p2align 4 +# CHECK: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align +# CHECK: LOAD 0x001400 0x0000000000000400 0x0000000000000400 0x000000 0x000001 RW 0x1000 + +# CHECK: 00 .bss + +.bss +.p2align 10 +.byte 0 Index: test/ELF/nobits-offset.s =================================================================== --- /dev/null +++ test/ELF/nobits-offset.s @@ -0,0 +1,21 @@ +# REQUIRES: aarch64 +# RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o +# RUN: ld.lld %t.o -o %t +# RUN: llvm-readelf -S -l %t | FileCheck %s + +## If a SHT_NOBITS section is the only section of a PT_LOAD segment, +## p_offset will be set to the sh_offset field of the section. Check we align +## sh_offset to sh_addr modulo max-page-size, so that p_vaddr=p_offset (mod +## p_align). + +# CHECK: Name Type Address Off Size ES Flg Lk Inf Al +# CHECK: .bss NOBITS 0000000000221000 001000 000001 00 WA 0 0 4096 + +# CHECK: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align +# CHECK: LOAD 0x001000 0x0000000000221000 0x0000000000221000 0x000000 0x000001 RW 0x10000 + +# CHECK: 02 .bss + +.bss +.p2align 12 +.byte 0 Index: test/ELF/relocatable.s =================================================================== --- test/ELF/relocatable.s +++ test/ELF/relocatable.s @@ -94,7 +94,7 @@ # CHECKEXE-NEXT: Version: 1 # CHECKEXE-NEXT: Entry: 0x201000 # CHECKEXE-NEXT: ProgramHeaderOffset: 0x40 -# CHECKEXE-NEXT: SectionHeaderOffset: 0x11F8 +# CHECKEXE-NEXT: SectionHeaderOffset: 0x21A0 # CHECKEXE-NEXT: Flags [ # CHECKEXE-NEXT: ] # CHECKEXE-NEXT: HeaderSize: 64 Index: test/ELF/relocation-copy-align-common.s =================================================================== --- test/ELF/relocation-copy-align-common.s +++ test/ELF/relocation-copy-align-common.s @@ -15,7 +15,7 @@ # CHECK-NEXT: SHF_WRITE # CHECK-NEXT: ] # CHECK-NEXT: Address: 0x203000 -# CHECK-NEXT: Offset: 0x20B0 +# CHECK-NEXT: Offset: 0x3000 # CHECK-NEXT: Size: 16 # CHECK-NEXT: Link: 0 # CHECK-NEXT: Info: 0