Index: lld/ELF/Writer.cpp =================================================================== --- lld/ELF/Writer.cpp +++ lld/ELF/Writer.cpp @@ -2182,12 +2182,15 @@ Sec->writeTo(Buf + Sec->Offset); } -static void fillTrap(uint8_t *I, uint8_t *End) { - for (; I + 4 <= End; I += 4) - memcpy(I, &Target->TrapInstr, 4); +static void fillTrap(uint8_t *Buf) { + assert(sizeof(Target->TrapInstr) == 4); + + auto *P = reinterpret_cast(Buf); + for (size_t I = 0; I < Target->PageSize / 4; ++I) + *P++ = Target->TrapInstr; } -// Fill the last page of executable segments with trap instructions +// Fill the last pages of executable sections with trap instructions // instead of leaving them as zero. Even though it is not required by any // standard, it is in general a good thing to do for security reasons. // @@ -2197,12 +2200,16 @@ if (Script->HasSectionsCommand) return; - // Fill the last page. + // Fill the last page of each executable section. 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 (OutputSection *Sec : OutputSections) { + PhdrEntry *P = Sec->PtLoad; + if (!P || P->p_type != PT_LOAD || !(P->p_flags & PF_X)) + continue; + if ((Sec->Offset + Sec->Size) % Target->PageSize == 0) + continue; + fillTrap(Buf + alignDown(Sec->Offset + Sec->Size, 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: lld/test/ELF/fill-trap.s =================================================================== --- lld/test/ELF/fill-trap.s +++ lld/test/ELF/fill-trap.s @@ -3,23 +3,25 @@ # 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 -x -N16 -j0x1ff0 %t2 | FileCheck %s -check-prefix=FILL +# RUN: od -Ax -t x1 -N16 -j0x1000 %t2 | FileCheck %s -check-prefix=FILL -# CHECK: ProgramHeader { -# CHECK: Type: PT_LOAD -# CHECK: Offset: 0x1000 +# CHECK: ProgramHeader { +# CHECK: Type: PT_LOAD +# CHECK: Offset: 0x1000 # CHECK-NEXT: VirtualAddress: # CHECK-NEXT: PhysicalAddress: -# CHECK-NEXT: FileSize: 4096 +# CHECK-NEXT: FileSize: 8192 # CHECK-NEXT: MemSize: # CHECK-NEXT: Flags [ # CHECK-NEXT: PF_R # CHECK-NEXT: PF_X # CHECK-NEXT: ] -## Check that executable page is filled with traps at its end. -# FILL: 001ff0 cccc cccc cccc cccc cccc cccc cccc cccc +# FILL: 001000 90 cc cc cc cc cc cc cc cc cc cc cc cc cc cc cc -.globl _start -_start: - nop +nop + +.section .foo,"ax" +.align 16 +nop +.zero 0x1000