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 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,13 @@ return alignTo(Off, Alignment, OS->Addr); } + // File offsets are also not significant for .bss sections when not the first + // section in a PT_LOAD and we can guarantee they won't be zero-filled in the + // file, which for now is simplified to being the last section in a PT_LOAD. + // Follow the same convention as above in this case. + if (OS->Type == SHT_NOBITS && OS == OS->PtLoad->LastSec) + 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/basic-ppc64.s b/lld/test/ELF/basic-ppc64.s --- a/lld/test/ELF/basic-ppc64.s +++ b/lld/test/ELF/basic-ppc64.s @@ -28,7 +28,7 @@ // CHECK-NEXT: Version: 1 // CHECK-NEXT: Entry: 0x10000 // CHECK-NEXT: ProgramHeaderOffset: 0x40 -// CHECK-NEXT: SectionHeaderOffset: 0x200F8 +// CHECK-NEXT: SectionHeaderOffset: 0x30098 // CHECK-NEXT: Flags [ (0x2) // CHECK-NEXT: 0x2 // CHECK-NEXT: ] @@ -163,7 +163,7 @@ // CHECK-NEXT: SHF_WRITE (0x1) // CHECK-NEXT: ] // CHECK-NEXT: Address: 0x30000 -// CHECK-NEXT: Offset: 0x20060 +// CHECK-NEXT: Offset: 0x30000 // CHECK-NEXT: Size: 0 // CHECK-NEXT: Link: 0 // CHECK-NEXT: Info: 0 @@ -179,7 +179,7 @@ // CHECK-NEXT: SHF_STRINGS (0x20) // CHECK-NEXT: ] // CHECK-NEXT: Address: 0x0 -// CHECK-NEXT: Offset: 0x20060 +// CHECK-NEXT: Offset: 0x30000 // CHECK-NEXT: Size: 8 // CHECK-NEXT: Link: 0 // CHECK-NEXT: Info: 0 @@ -196,7 +196,7 @@ // CHECK-NEXT: Flags [ (0x0) // CHECK-NEXT: ] // CHECK-NEXT: Address: 0x0 -// CHECK-NEXT: Offset: 0x20068 +// CHECK-NEXT: Offset: 0x30008 // CHECK-NEXT: Size: 48 // CHECK-NEXT: Link: 10 // CHECK-NEXT: Info: 2 @@ -215,7 +215,7 @@ // CHECK-NEXT: Flags [ (0x0) // CHECK-NEXT: ] // CHECK-NEXT: Address: 0x0 -// CHECK-NEXT: Offset: 0x20098 +// CHECK-NEXT: Offset: 0x30038 // CHECK-NEXT: Size: 84 // CHECK-NEXT: Link: 0 // CHECK-NEXT: Info: 0 @@ -237,7 +237,7 @@ // CHECK-NEXT: Flags [ (0x0) // CHECK-NEXT: ] // CHECK-NEXT: Address: 0x0 -// CHECK-NEXT: Offset: 0x200EC +// CHECK-NEXT: Offset: 0x3008C // CHECK-NEXT: Size: 10 // CHECK-NEXT: Link: 0 // CHECK-NEXT: Info: 0 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/Inputs/bss-middle-align.s b/lld/test/ELF/linkerscript/Inputs/bss-middle-align.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/linkerscript/Inputs/bss-middle-align.s @@ -0,0 +1,13 @@ +.text +.globl _start +_start: + nop + +.section .data.1,"a",@progbits +.short 0 + +.bss +.short 0 + +.section .data.2,"a",@progbits +.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 diff --git a/lld/test/ELF/linkerscript/bss-middle-align.test b/lld/test/ELF/linkerscript/bss-middle-align.test new file mode 100644 --- /dev/null +++ b/lld/test/ELF/linkerscript/bss-middle-align.test @@ -0,0 +1,33 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/bss-middle-align.s -o %t.o +# RUN: ld.lld -o %t.exe --script %s %t.o +# RUN: llvm-readelf -section-headers -program-headers %t.exe | FileCheck %s + +SECTIONS { + .text : { + *(.text) + } + .data.1 : { + *(.data.1) + } + .bss ALIGN(0x20): { + *(.bss) + } + .data.2 : { + *(.data.2) + } +} + +# CHECK: Section Headers: +# CHECK-NEXT: [Nr] Name Type Address Off Size ES Flg Lk Inf Al +# CHECK-NEXT: [ 0] NULL 0000000000000000 000000 000000 00 0 0 0 +# CHECK-NEXT: [ 1] .text PROGBITS 0000000000000000 001000 000001 00 AX 0 0 4 +# CHECK-NEXT: [ 2] .data.1 PROGBITS 0000000000000001 001001 000002 00 WA 0 0 1 +# CHECK-NEXT: [ 3] .bss NOBITS 0000000000000020 001020 000002 00 WA 0 0 1 +# CHECK-NEXT: [ 4] .data.2 PROGBITS 0000000000000022 001022 000002 00 WA 0 0 1 + +# 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 0x001001 0x0000000000000001 0x0000000000000001 0x000023 0x000023 RW 0x1000 +# CHECK-NOT: LOAD diff --git a/lld/test/ELF/relocation-copy-align-common.s b/lld/test/ELF/relocation-copy-align-common.s --- a/lld/test/ELF/relocation-copy-align-common.s +++ b/lld/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