diff --git a/lld/ELF/LinkerScript.cpp b/lld/ELF/LinkerScript.cpp --- a/lld/ELF/LinkerScript.cpp +++ b/lld/ELF/LinkerScript.cpp @@ -1149,9 +1149,16 @@ // and we'll also remove the PT_PHDR segment. void LinkerScript::allocateHeaders(std::vector &phdrs) { uint64_t min = std::numeric_limits::max(); - for (OutputSection *sec : outputSections) - if (sec->flags & SHF_ALLOC) - min = std::min(min, sec->addr); + auto hdrs = {Out::elfHeader, Out::programHeaders}; + for (OutputSection *hdr : hdrs) + if (hdr->ptLoad) + for (OutputSection *sec : hdr->ptLoad->sections) + if (llvm::find(hdrs, sec) == hdrs.end()) + min = std::min(min, sec->addr); + if (min == std::numeric_limits::max()) + for (OutputSection *sec : outputSections) + if (sec->flags & SHF_ALLOC) + min = std::min(min, sec->addr); auto it = llvm::find_if( phdrs, [](const PhdrEntry *e) { return e->p_type == PT_LOAD; }); diff --git a/lld/test/ELF/linkerscript/offset-headers.s b/lld/test/ELF/linkerscript/offset-headers.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/linkerscript/offset-headers.s @@ -0,0 +1,31 @@ +# REQUIRES: x86 +# RUN: split-file %s %t +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %t/test.s -o %t.o +# RUN: ld.lld -o %t1 --script %t/test.lds %t.o +# RUN: llvm-readelf -l %t1 | FileCheck %s + +# CHECK: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align +# CHECK-NEXT: LOAD 0x000000 0x0000000000001000 0x0000000000001000 0x0010b0 0x0010b0 R E 0x1000 +# CHECK-NEXT: LOAD 0x002000 0x0000000000000000 0x0000000000000000 0x001000 0x001000 RW 0x1000 + +#--- test.s +.global _start +_start: + .rept 0x1000 + nop + .endr + +.data + .rept 0x1000 + .byte 0 + .endr + +#--- test.lds +PHDRS { + ph1 PT_LOAD FILEHDR PHDRS; + ph2 PT_LOAD; +} +SECTIONS { + .data 0 : {*(.data*)} :ph2 + .text 0x1000 + SIZEOF_HEADERS : {*(.text*)} :ph1 +}