Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -67,6 +67,7 @@ void fixPredefinedSymbols(); void openFile(); void writeHeader(); + void writeTrapInstr(); void writeSections(); void writeSectionsBinary(); void writeBuildId(); @@ -246,6 +247,8 @@ return; if (!Config->OFormatBinary) { + if (!Script->Opt.HasSections) + writeTrapInstr(); writeHeader(); writeSections(); } else { @@ -1618,8 +1621,25 @@ Off = setOffset(Out::ElfHeader, Off); Off = setOffset(Out::ProgramHeaders, Off); - for (OutputSectionCommand *Cmd : OutputSectionCommands) + PhdrEntry *LastRX = nullptr; + for (PhdrEntry &P : Phdrs) { + if (P.p_type != PT_LOAD) + continue; + if (P.p_flags & PF_X) + LastRX = &P; + else + LastRX = nullptr; + } + + for (OutputSectionCommand *Cmd : OutputSectionCommands) { Off = setOffset(Cmd->Sec, Off); + if (!Script->Opt.HasSections) + // If this is a last section of the last executable segment and that + // segment is the last loadable segment, align the offset of the + // following section to avoid loading non-segments parts of the file. + if (LastRX && LastRX->Last == Cmd->Sec) + Off = alignTo(Off, Target->PageSize); + } SectionHeaderOff = alignTo(Off, Config->Wordsize); FileSize = @@ -1629,6 +1649,7 @@ // Finalize the program headers. We call this function after we assign // file offsets and VAs to all sections. template void Writer::setPhdrs() { + PhdrEntry *LastRX = nullptr; for (PhdrEntry &P : Phdrs) { OutputSection *First = P.First; OutputSection *Last = P.Last; @@ -1642,9 +1663,13 @@ if (!P.HasLMA) P.p_paddr = First->getLMA(); } - if (P.p_type == PT_LOAD) + if (P.p_type == PT_LOAD) { + if (P.p_flags & PF_X) + LastRX = &P; + else + LastRX = nullptr; P.p_align = Config->MaxPageSize; - else if (P.p_type == PT_GNU_RELRO) { + } else if (P.p_type == PT_GNU_RELRO) { P.p_align = 1; // The glibc dynamic loader rounds the size down, so we need to round up // to protect the last page. This is a no-op on FreeBSD which always @@ -1660,6 +1685,14 @@ P.p_memsz = alignTo(P.p_memsz, P.p_align); } } + + if (!Script->Opt.HasSections) + // Round up the size of the last segment to the page boundary iff it is the + // executable segment to avoid loading the non-segment parts at the end + // of the ELF file as executable. + if (LastRX) + LastRX->p_filesz = alignTo(LastRX->p_filesz, Target->PageSize) - + (LastRX->p_offset & (Target->PageSize - 1)); } // The entry point address is chosen in the following ways. @@ -1840,6 +1873,22 @@ } } +template void Writer::writeTrapInstr() { + uint8_t *Buf = Buffer->getBufferStart(); + + for (PhdrEntry &P : Phdrs) { + if (!(P.p_flags & PF_X)) + continue; + + // FIXME: We should fill only the first and the last page of the segment + // because the middle part will be overwritten by output sections. + uint8_t *I = Buf + P.p_offset; + uint8_t *End = I + P.p_filesz; + for (; I + 4 < End; I += 4) + memcpy(I, &Target->TrapInstr, 4); + } +} + // Write section contents to a mmap'ed file. template void Writer::writeSections() { uint8_t *Buf = Buffer->getBufferStart(); Index: test/ELF/avoid-empty-program-headers.s =================================================================== --- test/ELF/avoid-empty-program-headers.s +++ test/ELF/avoid-empty-program-headers.s @@ -42,7 +42,7 @@ // CHECK-NEXT: Offset: 0x1000 // CHECK-NEXT: VirtualAddress: 0x201000 // CHECK-NEXT: PhysicalAddress: 0x201000 -// CHECK-NEXT: FileSize: 1 +// CHECK-NEXT: FileSize: 4096 // CHECK-NEXT: MemSize: 1 // CHECK-NEXT: Flags [ (0x5) // CHECK-NEXT: PF_R (0x4) @@ -52,7 +52,7 @@ // CHECK-NEXT: } // CHECK-NEXT: ProgramHeader { // CHECK-NEXT: Type: PT_TLS (0x7) -// CHECK-NEXT: Offset: 0x1001 +// CHECK-NEXT: Offset: 0x2000 // CHECK-NEXT: VirtualAddress: 0x201001 // CHECK-NEXT: PhysicalAddress: 0x201001 // CHECK-NEXT: FileSize: 0 Index: test/ELF/basic-aarch64.s =================================================================== --- test/ELF/basic-aarch64.s +++ test/ELF/basic-aarch64.s @@ -26,7 +26,7 @@ # CHECK-NEXT: Version: 1 # CHECK-NEXT: Entry: [[ENTRY:0x[0-9A-F]+]] # CHECK-NEXT: ProgramHeaderOffset: 0x40 -# CHECK-NEXT: SectionHeaderOffset: 0x10098 +# CHECK-NEXT: SectionHeaderOffset: 0x11088 # CHECK-NEXT: Flags [ (0x0) # CHECK-NEXT: ] # CHECK-NEXT: HeaderSize: 64 @@ -76,7 +76,7 @@ # CHECK-NEXT: SHF_STRINGS (0x20) # CHECK-NEXT: ] # CHECK-NEXT: Address: 0x0 -# CHECK-NEXT: Offset: 0x1000C +# CHECK-NEXT: Offset: 0x11000 # CHECK-NEXT: Size: 8 # CHECK-NEXT: Link: 0 # CHECK-NEXT: Info: 0 @@ -90,7 +90,7 @@ # CHECK-NEXT: Flags [ (0x0) # CHECK-NEXT: ] # CHECK-NEXT: Address: 0x0 -# CHECK-NEXT: Offset: 0x10018 +# CHECK-NEXT: Offset: 0x11008 # CHECK-NEXT: Size: 72 # CHECK-NEXT: Link: 5 # CHECK-NEXT: Info: 2 @@ -104,7 +104,7 @@ # CHECK-NEXT: Flags [ (0x0) # CHECK-NEXT: ] # CHECK-NEXT: Address: 0x0 -# CHECK-NEXT: Offset: 0x10060 +# CHECK-NEXT: Offset: 0x11050 # CHECK-NEXT: Size: 42 # CHECK-NEXT: Link: 0 # CHECK-NEXT: Info: 0 @@ -118,7 +118,7 @@ # CHECK-NEXT: Flags [ (0x0) # CHECK-NEXT: ] # CHECK-NEXT: Address: 0x0 -# CHECK-NEXT: Offset: 0x1008A +# CHECK-NEXT: Offset: 0x1107A # CHECK-NEXT: Size: 13 # CHECK-NEXT: Link: 0 # CHECK-NEXT: Info: 0 @@ -185,7 +185,7 @@ # CHECK-NEXT: Offset: 0x1000 # CHECK-NEXT: VirtualAddress: 0x20000 # CHECK-NEXT: PhysicalAddress: 0x20000 -# CHECK-NEXT: FileSize: 12 +# CHECK-NEXT: FileSize: 4096 # CHECK-NEXT: MemSize: 12 # CHECK-NEXT: Flags [ (0x5) # CHECK-NEXT: PF_R (0x4) Index: test/ELF/basic.s =================================================================== --- test/ELF/basic.s +++ test/ELF/basic.s @@ -28,7 +28,7 @@ # CHECK-NEXT: Version: 1 # CHECK-NEXT: Entry: [[ENTRY:0x[0-9A-F]+]] # CHECK-NEXT: ProgramHeaderOffset: 0x40 -# CHECK-NEXT: SectionHeaderOffset: 0x1080 +# CHECK-NEXT: SectionHeaderOffset: 0x2070 # CHECK-NEXT: Flags [ (0x0) # CHECK-NEXT: ] # CHECK-NEXT: HeaderSize: 64 @@ -78,7 +78,7 @@ # CHECK-NEXT: SHF_STRINGS (0x20) # CHECK-NEXT: ] # CHECK-NEXT: Address: 0x0 -# CHECK-NEXT: Offset: 0x1010 +# CHECK-NEXT: Offset: 0x2000 # CHECK-NEXT: Size: 8 # CHECK-NEXT: Link: 0 # CHECK-NEXT: Info: 0 @@ -92,7 +92,7 @@ # CHECK-NEXT: Flags [ (0x0) # CHECK-NEXT: ] # CHECK-NEXT: Address: 0x0 -# CHECK-NEXT: Offset: 0x1018 +# CHECK-NEXT: Offset: 0x2008 # CHECK-NEXT: Size: 48 # CHECK-NEXT: Link: 5 # CHECK-NEXT: Info: 1 @@ -106,7 +106,7 @@ # CHECK-NEXT: Flags [ (0x0) # CHECK-NEXT: ] # CHECK-NEXT: Address: 0x0 -# CHECK-NEXT: Offset: 0x1048 +# CHECK-NEXT: Offset: 0x2038 # CHECK-NEXT: Size: 42 # CHECK-NEXT: Link: 0 # CHECK-NEXT: Info: 0 @@ -120,7 +120,7 @@ # CHECK-NEXT: Flags [ (0x0) # CHECK-NEXT: ] # CHECK-NEXT: Address: 0x0 -# CHECK-NEXT: Offset: 0x1072 +# CHECK-NEXT: Offset: 0x2062 # CHECK-NEXT: Size: 8 # CHECK-NEXT: Link: 0 # CHECK-NEXT: Info: 0 @@ -178,7 +178,7 @@ # CHECK-NEXT: Offset: 0x1000 # CHECK-NEXT: VirtualAddress: 0x201000 # CHECK-NEXT: PhysicalAddress: 0x201000 -# CHECK-NEXT: FileSize: 16 +# CHECK-NEXT: FileSize: 4096 # CHECK-NEXT: MemSize: 16 # CHECK-NEXT: Flags [ (0x5) # CHECK-NEXT: PF_R (0x4) Index: test/ELF/basic32.s =================================================================== --- test/ELF/basic32.s +++ test/ELF/basic32.s @@ -25,7 +25,7 @@ # CHECK-NEXT: Version: 1 # CHECK-NEXT: Entry: 0x11000 # CHECK-NEXT: ProgramHeaderOffset: 0x34 -# CHECK-NEXT: SectionHeaderOffset: 0x1068 +# CHECK-NEXT: SectionHeaderOffset: 0x205C # CHECK-NEXT: Flags [ (0x0) # CHECK-NEXT: ] # CHECK-NEXT: HeaderSize: 52 @@ -75,7 +75,7 @@ # CHECK-NEXT: SHF_STRINGS (0x20) # CHECK-NEXT: ] # CHECK-NEXT: Address: 0x0 -# CHECK-NEXT: Offset: 0x100C +# CHECK-NEXT: Offset: 0x2000 # CHECK-NEXT: Size: 8 # CHECK-NEXT: Link: 0 # CHECK-NEXT: Info: 0 @@ -89,7 +89,7 @@ # CHECK-NEXT: Flags [ # CHECK-NEXT: ] # CHECK-NEXT: Address: 0x0 -# CHECK-NEXT: Offset: 0x1014 +# CHECK-NEXT: Offset: 0x2008 # CHECK-NEXT: Size: 32 # CHECK-NEXT: Link: 5 # CHECK-NEXT: Info: 1 @@ -103,7 +103,7 @@ # CHECK-NEXT: Flags [ (0x0) # CHECK-NEXT: ] # CHECK-NEXT: Address: 0x0 -# CHECK-NEXT: Offset: 0x1034 +# CHECK-NEXT: Offset: 0x2028 # CHECK-NEXT: Size: 42 # CHECK-NEXT: Link: 0 # CHECK-NEXT: Info: 0 @@ -117,7 +117,7 @@ # CHECK-NEXT: Flags [ (0x0) # CHECK-NEXT: ] # CHECK-NEXT: Address: 0x0 -# CHECK-NEXT: Offset: 0x105E +# CHECK-NEXT: Offset: 0x2052 # CHECK-NEXT: Size: 8 # CHECK-NEXT: Link: 0 # CHECK-NEXT: Info: 0 @@ -155,7 +155,7 @@ # CHECK-NEXT: Offset: 0x1000 # CHECK-NEXT: VirtualAddress: 0x11000 # CHECK-NEXT: PhysicalAddress: 0x11000 -# CHECK-NEXT: FileSize: 12 +# CHECK-NEXT: FileSize: 4096 # CHECK-NEXT: MemSize: 12 # CHECK-NEXT: Flags [ (0x5) # CHECK-NEXT: PF_R (0x4) Index: test/ELF/build-id.s =================================================================== --- test/ELF/build-id.s +++ test/ELF/build-id.s @@ -48,15 +48,15 @@ # DEFAULT: Contents of section .note.test: # DEFAULT: Contents of section .note.gnu.build-id: # DEFAULT-NEXT: 04000000 08000000 03000000 474e5500 ............GNU. -# DEFAULT-NEXT: fd36edb1 f6ff02af +# DEFAULT-NEXT: d618a375 bc6301ec # MD5: Contents of section .note.gnu.build-id: # MD5-NEXT: 04000000 10000000 03000000 474e5500 ............GNU. -# MD5-NEXT: fc +# MD5-NEXT: 051084fe ce1f30ed e035b79e 11262808 # SHA1: Contents of section .note.gnu.build-id: # SHA1-NEXT: 04000000 14000000 03000000 474e5500 ............GNU. -# SHA1-NEXT: 55b1eedb 03b588e1 09987d1d e9a79be7 +# SHA1-NEXT: c70b9aec 903fd291 8b677cd8 1e04f8b6 # UUID: Contents of section .note.gnu.build-id: # UUID-NEXT: 04000000 10000000 03000000 474e5500 ............GNU. Index: test/ELF/image-base.s =================================================================== --- test/ELF/image-base.s +++ test/ELF/image-base.s @@ -41,7 +41,7 @@ # CHECK-NEXT: Offset: 0x1000 # CHECK-NEXT: VirtualAddress: 0x1001000 # CHECK-NEXT: PhysicalAddress: 0x1001000 -# CHECK-NEXT: FileSize: 1 +# CHECK-NEXT: FileSize: 4096 # CHECK-NEXT: MemSize: 1 # CHECK-NEXT: Flags [ (0x5) # CHECK-NEXT: PF_R (0x4)