Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -1019,6 +1019,9 @@ // If there isn't enough space for these sections, we'll remove them from the // PT_LOAD segment, and we'll also remove the PT_PHDR segment. void LinkerScript::allocateHeaders(std::vector &phdrs) { + if (!script->hasSectionsCommand) + return; + uint64_t min = std::numeric_limits::max(); for (OutputSection *sec : outputSections) if (sec->flags & SHF_ALLOC) @@ -1063,28 +1066,22 @@ } } -static uint64_t getInitialDot() { - // By default linker scripts use an initial value of 0 for '.', - // but prefer -image-base if set. - if (script->hasSectionsCommand) - return config->imageBase ? *config->imageBase : 0; - - uint64_t startAddr = UINT64_MAX; - // The sections with -T
have been sorted in order of ascending - // address. We must lower startAddr if the lowest -T
as - // calls to setDot() must be monotonically increasing. - for (auto &kv : config->sectionStartMap) - startAddr = std::min(startAddr, kv.second); - return std::min(startAddr, target->getImageBase() + elf::getHeaderSize()); -} - // Here we assign addresses as instructed by linker script SECTIONS // sub-commands. Doing that allows us to use final VA values, so here // we also handle rest commands like symbol assignments and ASSERTs. // Returns a symbol that has changed its section or value, or nullptr if no // symbol has changed. const Defined *LinkerScript::assignAddresses() { - dot = getInitialDot(); + if (script->hasSectionsCommand) { + // Delay the allocation of headers to allocateHeaders(). + dot = config->imageBase ? *config->imageBase : 0; + } else { + // Assign addresses to headers right now. + dot = target->getImageBase(); + Out::elfHeader->addr = dot; + Out::programHeaders->addr = dot + Out::elfHeader->size; + dot += getHeaderSize(); + } auto deleter = std::make_unique(); ctx = deleter.get(); Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -2036,8 +2036,7 @@ // nmagic or omagic output does not have PT_PHDR, PT_INTERP, or the readonly // PT_LOAD. - bool paged = !config->nmagic && !config->omagic; - if (paged) { + if (!config->nmagic && !config->omagic) { // The first phdr entry is PT_PHDR which describes the program header // itself. if (isMain) Index: test/ELF/basic-aarch64.s =================================================================== --- test/ELF/basic-aarch64.s +++ test/ELF/basic-aarch64.s @@ -159,8 +159,8 @@ # CHECK-NEXT: ProgramHeader { # CHECK-NEXT: Type: PT_PHDR (0x6) # CHECK-NEXT: Offset: 0x40 -# CHECK-NEXT: VirtualAddress: 0x210040 -# CHECK-NEXT: PhysicalAddress: 0x210040 +# CHECK-NEXT: VirtualAddress: 0x200040 +# CHECK-NEXT: PhysicalAddress: 0x200040 # CHECK-NEXT: FileSize: 224 # CHECK-NEXT: MemSize: 224 # CHECK-NEXT: Flags [ (0x4) @@ -171,8 +171,8 @@ # CHECK-NEXT: ProgramHeader { # CHECK-NEXT: Type: PT_LOAD (0x1) # CHECK-NEXT: Offset: 0x0 -# CHECK-NEXT: VirtualAddress: 0x210000 -# CHECK-NEXT: PhysicalAddress: 0x210000 +# CHECK-NEXT: VirtualAddress: 0x200000 +# CHECK-NEXT: PhysicalAddress: 0x200000 # CHECK-NEXT: FileSize: 288 # CHECK-NEXT: MemSize: 288 # CHECK-NEXT: Flags [ Index: test/ELF/basic-i386.s =================================================================== --- test/ELF/basic-i386.s +++ test/ELF/basic-i386.s @@ -129,8 +129,8 @@ # CHECK-NEXT: ProgramHeader { # CHECK-NEXT: Type: PT_PHDR (0x6) # CHECK-NEXT: Offset: 0x34 -# CHECK-NEXT: VirtualAddress: 0x401034 -# CHECK-NEXT: PhysicalAddress: 0x401034 +# CHECK-NEXT: VirtualAddress: 0x400034 +# CHECK-NEXT: PhysicalAddress: 0x400034 # CHECK-NEXT: FileSize: 128 # CHECK-NEXT: MemSize: 128 # CHECK-NEXT: Flags [ (0x4) @@ -141,8 +141,8 @@ # CHECK-NEXT: ProgramHeader { # CHECK-NEXT: Type: PT_LOAD (0x1) # CHECK-NEXT: Offset: 0x0 -# CHECK-NEXT: VirtualAddress: 0x401000 -# CHECK-NEXT: PhysicalAddress: 0x401000 +# CHECK-NEXT: VirtualAddress: 0x400000 +# CHECK-NEXT: PhysicalAddress: 0x400000 # CHECK-NEXT: FileSize: 180 # CHECK-NEXT: MemSize: 180 # CHECK-NEXT: Flags [ Index: test/ELF/basic-ppc.s =================================================================== --- test/ELF/basic-ppc.s +++ test/ELF/basic-ppc.s @@ -143,8 +143,8 @@ // CHECK-NEXT: ProgramHeader { // CHECK-NEXT: Type: PT_PHDR (0x6) // CHECK-NEXT: Offset: 0x34 -// CHECK-NEXT: VirtualAddress: 0x10010034 -// CHECK-NEXT: PhysicalAddress: 0x10010034 +// CHECK-NEXT: VirtualAddress: 0x10000034 +// CHECK-NEXT: PhysicalAddress: 0x10000034 // CHECK-NEXT: FileSize: 128 // CHECK-NEXT: MemSize: 128 // CHECK-NEXT: Flags [ (0x4) @@ -155,8 +155,8 @@ // CHECK-NEXT: ProgramHeader { // CHECK-NEXT: Type: PT_LOAD (0x1) // CHECK-NEXT: Offset: 0x0 -// CHECK-NEXT: VirtualAddress: 0x10010000 -// CHECK-NEXT: PhysicalAddress: 0x10010000 +// CHECK-NEXT: VirtualAddress: 0x10000000 +// CHECK-NEXT: PhysicalAddress: 0x10000000 // CHECK-NEXT: FileSize: 180 // CHECK-NEXT: MemSize: 180 // CHECK-NEXT: Flags [ (0x4) Index: test/ELF/basic-sparcv9.s =================================================================== --- test/ELF/basic-sparcv9.s +++ test/ELF/basic-sparcv9.s @@ -150,8 +150,8 @@ # CHECK-NEXT: ProgramHeader { # CHECK-NEXT: Type: PT_PHDR (0x6) # CHECK-NEXT: Offset: 0x40 -# CHECK-NEXT: VirtualAddress: 0x200040 -# CHECK-NEXT: PhysicalAddress: 0x200040 +# CHECK-NEXT: VirtualAddress: 0x100040 +# CHECK-NEXT: PhysicalAddress: 0x100040 # CHECK-NEXT: FileSize: 224 # CHECK-NEXT: MemSize: 224 # CHECK-NEXT: Flags [ (0x4) @@ -162,8 +162,8 @@ # CHECK-NEXT: ProgramHeader { # CHECK-NEXT: Type: PT_LOAD (0x1) # CHECK-NEXT: Offset: 0x0 -# CHECK-NEXT: VirtualAddress: 0x200000 -# CHECK-NEXT: PhysicalAddress: 0x200000 +# CHECK-NEXT: VirtualAddress: 0x100000 +# CHECK-NEXT: PhysicalAddress: 0x100000 # CHECK-NEXT: FileSize: 288 # CHECK-NEXT: MemSize: 288 # CHECK-NEXT: Flags [ Index: test/ELF/ttext-tdata-tbss.s =================================================================== --- test/ELF/ttext-tdata-tbss.s +++ test/ELF/ttext-tdata-tbss.s @@ -13,7 +13,9 @@ # CHECK-NEXT: PHDR # CHECK-NEXT: LOAD 0x000000 0x0000000000200000 -## With .text at 0 there is no space to allocate the headers. +## If -Ttext is smaller than the image base (which defaults to 0x200000 for -no-pie), +## the headers will still be allocated, but mapped at a higher address, +## which may look strange. # RUN: ld.lld -Ttext 0x0 -Tdata 0x4000 -Tbss 0x8000 %t.o -o %t2 # RUN: llvm-readelf -S -l %t2 | FileCheck %s --check-prefix=USER1 # USER1: .text PROGBITS 0000000000000000 001000 000001 @@ -22,10 +24,12 @@ # USER1-NEXT: .rodata PROGBITS 0000000000009000 003000 000008 # USER1-NEXT: .aw PROGBITS 000000000000a000 004000 000008 # USER1: Type +# USER1-NEXT: PHDR 0x000040 0x0000000000200040 +# USER1-NEXT: LOAD 0x000000 0x0000000000200000 # USER1-NEXT: LOAD 0x001000 0x0000000000000000 -## With .text at 0x1000 there is space to allocate the headers. -# RUN: ld.lld -Ttext 0x1000 -Tdata 0x4000 -Tbss 0x8000 %t.o -o %t3 +## Specify --image-base to make program headers look normal. +# RUN: ld.lld --image-base=0 -Ttext 0x1000 -Tdata 0x4000 -Tbss 0x8000 %t.o -o %t3 # RUN: llvm-readelf -S -l %t3 | FileCheck %s --check-prefix=USER2 # USER2: .text PROGBITS 0000000000001000 001000 000001 # USER2-NEXT: .data PROGBITS 0000000000004000 002000 000008 @@ -33,8 +37,9 @@ # USER2-NEXT: .rodata PROGBITS 0000000000009000 003000 000008 # USER2-NEXT: .aw PROGBITS 000000000000a000 004000 000008 # USER2: Type -# USER2-NEXT: PHDR +# USER2-NEXT: PHDR 0x000040 0x0000000000000040 # USER2-NEXT: LOAD 0x000000 0x0000000000000000 +# USER2-NEXT: LOAD 0x001000 0x0000000000001000 ## With .text well above 200000 we don't need to change the image base # RUN: ld.lld -Ttext 0x201000 %t.o -o %t4 @@ -45,8 +50,9 @@ # USER3-NEX: .data PROGBITS 0000000000203008 003008 000008 # USER3-NEX: .bss NOBITS 0000000000203010 003010 000008 # USER3: Type -# USER3-NEXT: PHDR +# USER3-NEXT: PHDR 0x000040 0x0000000000200040 # USER3-NEXT: LOAD 0x000000 0x0000000000200000 +# USER3-NEXT: LOAD 0x001000 0x0000000000201000 .text .globl _start