diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index 28a956391107..98b335e4b14a 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -62,6 +62,7 @@ private: void addPredefinedSections(); std::vector createPhdrs(); + void removeEmptyPTLoad(); void addPtArmExid(std::vector &Phdrs); void assignAddresses(); void assignFileOffsets(); @@ -134,6 +135,16 @@ template static bool needsInterpSection() { template void elf::writeResult() { Writer().run(); } +template void Writer::removeEmptyPTLoad() { + auto I = std::remove_if(Phdrs.begin(), Phdrs.end(), [&](const Phdr &P) { + if (P.H.p_type != PT_LOAD) + return false; + uintX_t Size = P.Last->Addr + P.Last->Size - P.First->Addr; + return Size == 0; + }); + Phdrs.erase(I, Phdrs.end()); +} + // The main function of the writer. template void Writer::run() { // Create linker-synthesized sections such as .got or .plt. @@ -198,6 +209,11 @@ template void Writer::run() { assignAddresses(); } + // Remove empty PT_LOAD to avoid causing the dynamic linker to try to mmap a + // 0 sized region. This has to be done late since only after assignAddresses + // we know the size of the sections. + removeEmptyPTLoad(); + if (!Config->OFormatBinary) assignFileOffsets(); else diff --git a/lld/test/ELF/empty-pt-load.s b/lld/test/ELF/empty-pt-load.s new file mode 100644 index 000000000000..4074b63cb80f --- /dev/null +++ b/lld/test/ELF/empty-pt-load.s @@ -0,0 +1,11 @@ +// REQUIRES: x86 +// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o +// RUN: ld.lld %t.o -o %t.so -shared +// RUN: llvm-readobj -l --elf-output-style=GNU %t.so | FileCheck %s + +// Test that we don't create an empty executable PT_LOAD. + +// CHECK: PHDR {{.*}} R 0x8 +// CHECK-NEXT: LOAD {{.*}} R 0x1000 +// CHECK-NEXT: LOAD {{.*}} RW 0x1000 +// CHECK-NEXT: DYNAMIC {{.*}} RW 0x8 diff --git a/lld/test/ELF/program-header-layout.s b/lld/test/ELF/program-header-layout.s index 31c1fc2de128..57759c946dac 100644 --- a/lld/test/ELF/program-header-layout.s +++ b/lld/test/ELF/program-header-layout.s @@ -61,19 +61,6 @@ _start: # CHECK-NEXT: Offset: # CHECK-NEXT: VirtualAddress: # CHECK-NEXT: PhysicalAddress: -# CHECK-NEXT: FileSize: 0 -# CHECK-NEXT: MemSize: 0 -# CHECK-NEXT: Flags [ -# CHECK-NEXT: PF_R -# CHECK-NEXT: PF_X -# CHECK-NEXT: ] -# CHECK-NEXT: Alignment: -# CHECK-NEXT: } -# CHECK-NEXT: ProgramHeader { -# CHECK-NEXT: Type: PT_LOAD -# CHECK-NEXT: Offset: -# CHECK-NEXT: VirtualAddress: -# CHECK-NEXT: PhysicalAddress: # CHECK-NEXT: FileSize: 16 # CHECK-NEXT: MemSize: 16 # CHECK-NEXT: Flags [