Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -300,6 +300,9 @@ extern LinkerScript *Script; } // end namespace elf + +void fill(uint8_t *Buf, size_t Size, uint32_t Filler); + } // end namespace lld #endif // LLD_ELF_LINKER_SCRIPT_H Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -165,7 +165,7 @@ // Fill [Buf, Buf + Size) with Filler. // This is used for linker script "=fillexp" command. -static void fill(uint8_t *Buf, size_t Size, uint32_t Filler) { +void lld::fill(uint8_t *Buf, size_t Size, uint32_t Filler) { size_t I = 0; for (; I + 4 < Size; I += 4) memcpy(Buf + I, &Filler, 4); Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -66,6 +66,7 @@ void fixSectionAlignments(); void fixPredefinedSymbols(); void openFile(); + void writeTrapInstr(); void writeHeader(); void writeSections(); void writeSectionsBinary(); @@ -245,6 +246,7 @@ return; if (!Config->OFormatBinary) { + writeTrapInstr(); writeHeader(); writeSections(); } else { @@ -1629,15 +1631,35 @@ FileSize = alignTo(Off, Config->Wordsize); } +static std::vector getExecLoads(ArrayRef V) { + std::vector Ret; + for (PhdrEntry *Load : V) + if (Load->p_type == PT_LOAD && Load->p_flags & PF_X) + Ret.push_back(Load); + return Ret; +} + // Assign file offsets to output sections. template void Writer::assignFileOffsets() { uint64_t Off = 0; Off = setOffset(Out::ElfHeader, Off); Off = setOffset(Out::ProgramHeaders, Off); - for (OutputSectionCommand *Cmd : OutputSectionCommands) + std::vector ExecLoads = getExecLoads(Phdrs); + OutputSection *LastExec = + ExecLoads.empty() ? nullptr : ExecLoads.back()->Last; + for (OutputSectionCommand *Cmd : OutputSectionCommands) { Off = setOffset(Cmd->Sec, Off); + // If no linker script is involved and allocatable section is the last in + // executable segment, that means we want to ensure segment contains only + // valid instructions and hence we align next section's offset to avoid + // loading of non-allocatable content. We will fill gap with trap op codes. + if (!Script->Opt.HasSections) + if (Cmd->Sec == LastExec) + Off = alignTo(Off, Target->PageSize); + } + SectionHeaderOff = alignTo(Off, Config->Wordsize); FileSize = SectionHeaderOff + (OutputSectionCommands.size() + 1) * sizeof(Elf_Shdr); @@ -1857,6 +1879,35 @@ } } +static void fillPage(uint8_t *Buf, uint64_t Offset, uint32_t Filler) { + uint64_t Begin = alignDown(Offset, Target->PageSize); + uint64_t End = alignTo(Offset, Target->PageSize); + fill(Buf + Begin, End - Begin, Filler); +} + +template void Writer::writeTrapInstr() { + // FIXME: do the same for case when sections present. + if (Script->Opt.HasSections) + return; + + uint8_t *Buf = Buffer->getBufferStart(); + for (PhdrEntry *Load : getExecLoads(Phdrs)) { + // We only fill the first and the last page of the segment because the + // middle part will be overwritten by output sections. + fillPage(Buf, Load->p_offset, Target->TrapInstr); + fillPage(Buf, Load->p_offset + Load->p_filesz, Target->TrapInstr); + } + + // Round up the file size of the last segment to the page boundary if it is + // an executable segment to ensure that other other tools don't accidentally + // trim the instruction padding (e.g. when stripping the file). + auto It = llvm::find_if(llvm::reverse(Phdrs), [](PhdrEntry *Phdr) { + return Phdr->p_type == PT_LOAD; + }); + if (It != Phdrs.rend() && (*It)->p_flags & PF_X) + (*It)->p_filesz = alignTo((*It)->p_filesz, Target->PageSize); +} + // 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-sparcv9.s =================================================================== --- test/ELF/basic-sparcv9.s +++ test/ELF/basic-sparcv9.s @@ -26,7 +26,7 @@ # CHECK-NEXT: Version: 1 # CHECK-NEXT: Entry: [[ENTRY:0x[0-9A-F]+]] # CHECK-NEXT: ProgramHeaderOffset: 0x40 -# CHECK-NEXT: SectionHeaderOffset: 0x100080 +# CHECK-NEXT: SectionHeaderOffset: 0x102070 # 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: 0x10000C +# CHECK-NEXT: Offset: 0x102000 # 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: 0x100018 +# CHECK-NEXT: Offset: 0x102008 # CHECK-NEXT: Size: 48 # CHECK-NEXT: Link: 5 # CHECK-NEXT: Info: 1 @@ -104,7 +104,7 @@ # CHECK-NEXT: Flags [ (0x0) # CHECK-NEXT: ] # CHECK-NEXT: Address: 0x0 -# CHECK-NEXT: Offset: 0x100048 +# CHECK-NEXT: Offset: 0x102038 # 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: 0x100072 +# CHECK-NEXT: Offset: 0x102062 # CHECK-NEXT: Size: 8 # CHECK-NEXT: Link: 0 # CHECK-NEXT: Info: 0 @@ -176,7 +176,7 @@ # CHECK-NEXT: Offset: 0x100000 # CHECK-NEXT: VirtualAddress: 0x200000 # CHECK-NEXT: PhysicalAddress: 0x200000 -# CHECK-NEXT: FileSize: 12 +# CHECK-NEXT: FileSize: 8192 # 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,7 +48,7 @@ # 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: b0148597 ba5eb7e9 # MD5: Contents of section .note.gnu.build-id: # MD5-NEXT: 04000000 10000000 03000000 474e5500 ............GNU. @@ -56,7 +56,7 @@ # SHA1: Contents of section .note.gnu.build-id: # SHA1-NEXT: 04000000 14000000 03000000 474e5500 ............GNU. -# SHA1-NEXT: 55b1eedb 03b588e1 09987d1d e9a79be7 +# SHA1-NEXT: 2f716666 fe3668fe 370a02a1 579c3eb2 # 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 @@ -44,7 +44,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) Index: test/ELF/relocatable.s =================================================================== --- test/ELF/relocatable.s +++ test/ELF/relocatable.s @@ -81,7 +81,7 @@ # CHECKEXE-NEXT: Version: 1 # CHECKEXE-NEXT: Entry: 0x201000 # CHECKEXE-NEXT: ProgramHeaderOffset: 0x40 -# CHECKEXE-NEXT: SectionHeaderOffset: 0x11F8 +# CHECKEXE-NEXT: SectionHeaderOffset: 0x21A0 # CHECKEXE-NEXT: Flags [ # CHECKEXE-NEXT: ] # CHECKEXE-NEXT: HeaderSize: 64