Index: ELF/Arch/X86.cpp =================================================================== --- ELF/Arch/X86.cpp +++ ELF/Arch/X86.cpp @@ -445,6 +445,7 @@ 0xc3, // 2e: ret }; memcpy(Buf, Insn, sizeof(Insn)); + memset(Buf + sizeof(Insn), 0xcc, TargetInfo::PltHeaderSize - sizeof(Insn)); uint32_t Ebx = InX::Got->getVA() + InX::Got->getSize(); uint32_t GotPlt = InX::GotPlt->getVA() - Ebx; @@ -464,6 +465,7 @@ 0xe9, 0, 0, 0, 0, // jmp plt+0 }; memcpy(Buf, Insn, sizeof(Insn)); + memset(Buf + sizeof(Insn), 0xcc, TargetInfo::PltEntrySize - sizeof(Insn)); uint32_t Ebx = InX::Got->getVA() + InX::Got->getSize(); unsigned Off = getPltEntryOffset(Index); @@ -484,7 +486,7 @@ } void RetpolineNoPic::writePltHeader(uint8_t *Buf) const { - const uint8_t PltData[] = { + const uint8_t Insn[] = { 0xff, 0x35, 0, 0, 0, 0, // 0: pushl GOTPLT+4 0x50, // 6: pushl %eax 0xa1, 0, 0, 0, 0, // 7: mov GOTPLT+8, %eax @@ -501,7 +503,8 @@ 0x59, // 2d: pop %ecx 0xc3, // 2e: ret }; - memcpy(Buf, PltData, sizeof(PltData)); + memcpy(Buf, Insn, sizeof(Insn)); + memset(Buf + sizeof(Insn), 0xcc, TargetInfo::PltHeaderSize - sizeof(Insn)); uint32_t GotPlt = InX::GotPlt->getVA(); write32le(Buf + 2, GotPlt + 4); @@ -520,6 +523,7 @@ 0xe9, 0, 0, 0, 0, // 15: jmp plt+0 }; memcpy(Buf, Insn, sizeof(Insn)); + memset(Buf + sizeof(Insn), 0xcc, TargetInfo::PltEntrySize - sizeof(Insn)); unsigned Off = getPltEntryOffset(Index); write32le(Buf + 2, GotPltEntryAddr); Index: ELF/Arch/X86_64.cpp =================================================================== --- ELF/Arch/X86_64.cpp +++ ELF/Arch/X86_64.cpp @@ -502,6 +502,7 @@ 0xc3, // 24: ret }; memcpy(Buf, Insn, sizeof(Insn)); + memset(Buf + sizeof(Insn), 0xcc, TargetInfo::PltHeaderSize - sizeof(Insn)); uint64_t GotPlt = InX::GotPlt->getVA(); uint64_t Plt = InX::Plt->getVA(); @@ -521,6 +522,7 @@ 0xe9, 0, 0, 0, 0, // 16: jmp plt+0 }; memcpy(Buf, Insn, sizeof(Insn)); + memset(Buf + sizeof(Insn), 0xcc, TargetInfo::PltEntrySize - sizeof(Insn)); uint64_t Off = TargetInfo::getPltEntryOffset(Index); @@ -548,6 +550,7 @@ 0xc3, // 14: ret }; memcpy(Buf, Insn, sizeof(Insn)); + memset(Buf + sizeof(Insn), 0xcc, TargetInfo::PltHeaderSize - sizeof(Insn)); } template @@ -559,6 +562,7 @@ 0xe9, 0, 0, 0, 0, // jmp plt+0 }; memcpy(Buf, Insn, sizeof(Insn)); + memset(Buf + sizeof(Insn), 0xcc, TargetInfo::PltEntrySize - sizeof(Insn)); write32le(Buf + 3, GotPltEntryAddr - PltEntryAddr - 7); write32le(Buf + 8, -TargetInfo::getPltEntryOffset(Index) - 12); Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -2184,9 +2184,18 @@ Sec->writeTo(Buf + Sec->Offset); } -static void fillTrap(uint8_t *I, uint8_t *End) { +static std::vector getSectionsInLoad(PhdrEntry *Load) { + std::vector V; + for (OutputSection *Sec : OutputSections) + if (Sec->PtLoad == Load) + V.push_back(Sec); + return V; +} + +void fillTrap(uint8_t *I, uint8_t *End) { for (; I + 4 <= End; I += 4) memcpy(I, &Target->TrapInstr, 4); + memcpy(I, &Target->TrapInstr, End - I); } // Fill the last page of executable segments with trap instructions @@ -2199,12 +2208,24 @@ if (Script->HasSectionsCommand) return; - // Fill the last page. + // Here we want to fill all paddings inside PT_LOAD with trap instructions. + // For that, we want to fill all gaps between sections and two gaps between + // the first and last sections and segment boundaries. There is never a gap + // between the beginning of the segment and first section, so we ignore it. uint8_t *Buf = Buffer->getBufferStart(); - for (PhdrEntry *P : Phdrs) - if (P->p_type == PT_LOAD && (P->p_flags & PF_X)) - fillTrap(Buf + alignDown(P->p_offset + P->p_filesz, Target->PageSize), - Buf + alignTo(P->p_offset + P->p_filesz, Target->PageSize)); + for (PhdrEntry *P : Phdrs) { + if (P->p_type != PT_LOAD || !(P->p_flags & PF_X)) + continue; + + // Fill gaps between output sections. + std::vector V = getSectionsInLoad(P); + for (size_t I = 0; I < V.size() - 1; ++I) + fillTrap(Buf + V[I]->Offset + V[I]->Size, Buf + V[I + 1]->Offset); + + // Fill gap between the last section and end of the segment. + fillTrap(Buf + V.back()->Offset + V.back()->Size, + Buf + alignTo(P->p_offset + P->p_filesz, Target->PageSize)); + } // Round up the file size of the last segment to the page boundary iff it is // an executable segment to ensure that other tools don't accidentally Index: test/ELF/fill-trap2.s =================================================================== --- test/ELF/fill-trap2.s +++ test/ELF/fill-trap2.s @@ -0,0 +1,27 @@ +# REQUIRES: x86 + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: ld.lld %t -o %t2 +# RUN: llvm-readobj -program-headers %t2 | FileCheck %s +# RUN: od -Ax -t x1 -N16 -j0x1000 %t2 | FileCheck %s -check-prefix=FILL + +# CHECK: ProgramHeader { +# CHECK: Type: PT_LOAD +# CHECK: Offset: 0x1000 +# CHECK-NEXT: VirtualAddress: +# CHECK-NEXT: PhysicalAddress: +# CHECK-NEXT: FileSize: 8192 +# CHECK-NEXT: MemSize: +# CHECK-NEXT: Flags [ +# CHECK-NEXT: PF_R +# CHECK-NEXT: PF_X +# CHECK-NEXT: ] + +# FILL: 001000 90 cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc + +nop + +.section .foo,"ax" +.align 16 +nop +.zero 0x1000