diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -2216,14 +2216,16 @@ // same with its virtual address modulo the page size, so that the loader can // load executables without any address adjustment. 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) - return Off; - // If the section is not in a PT_LOAD, we just have to align it. - if (!OS->PtLoad) + if (!OS->PtLoad) { + // File offsets are not significant for .bss sections when not the first + // section in a PT_LOAD. By convention, we keep section offsets + // monotonically increasing rather than setting to zero. + if (OS->Type == SHT_NOBITS) + return Off; + return alignTo(Off, OS->Alignment); + } // The first section in a PT_LOAD has to have congruent offset and address // module the page size. @@ -2233,6 +2235,10 @@ return alignTo(Off, Alignment, OS->Addr); } + // This is a .bss section that isn't first in its PT_LOAD; see above. + if (OS->Type == SHT_NOBITS) + return Off; + // If two sections share the same PT_LOAD the file offset is calculated // using this formula: Off2 = Off1 + (VA2 - VA1). return First->Offset + OS->Addr - First->Addr; diff --git a/lld/test/ELF/linkerscript/Inputs/bss-first-align.s b/lld/test/ELF/linkerscript/Inputs/bss-first-align.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/linkerscript/Inputs/bss-first-align.s @@ -0,0 +1,7 @@ +.text +.globl _start +_start: + nop + +.bss +.short 0 diff --git a/lld/test/ELF/linkerscript/bss-first-align.test b/lld/test/ELF/linkerscript/bss-first-align.test new file mode 100644 --- /dev/null +++ b/lld/test/ELF/linkerscript/bss-first-align.test @@ -0,0 +1,19 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/bss-first-align.s -o %t.o +# RUN: ld.lld -o %t.exe --script %s %t.o +# RUN: llvm-readelf -program-headers %t.exe | FileCheck %s + +SECTIONS { + .text : { + *(.text) + } + .bss ALIGN(0x20): { + *(.bss) + } +} + +# CHECK: Program Headers: +# CHECK-NEXT: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align +# CHECK-NEXT: LOAD 0x001000 0x0000000000000000 0x0000000000000000 0x000001 0x000001 R E 0x1000 +# CHECK-NEXT: LOAD 0x001020 0x0000000000000020 0x0000000000000020 0x000000 0x000002 RW 0x1000 +# CHECK-NOT: LOAD