Index: ELF/LinkerScript.h =================================================================== --- ELF/LinkerScript.h +++ ELF/LinkerScript.h @@ -115,7 +115,7 @@ Expr SubalignExpr; std::vector Commands; std::vector Phdrs; - uint32_t Filler = 0; + llvm::Optional Filler; ConstraintKind Constraint = ConstraintKind::NoConstraint; std::string Location; std::string MemoryRegionName; @@ -265,7 +265,7 @@ std::vector createPhdrs(); bool ignoreInterpSection(); - uint32_t getFiller(StringRef Name); + llvm::Optional getFiller(StringRef Name); bool hasLMA(StringRef Name); bool shouldKeep(InputSectionBase *S); void assignOffsets(OutputSectionCommand *Cmd); Index: ELF/LinkerScript.cpp =================================================================== --- ELF/LinkerScript.cpp +++ ELF/LinkerScript.cpp @@ -865,12 +865,12 @@ return true; } -uint32_t LinkerScript::getFiller(StringRef Name) { +Optional LinkerScript::getFiller(StringRef Name) { for (BaseCommand *Base : Opt.Commands) if (auto *Cmd = dyn_cast(Base)) if (Cmd->Name == Name) return Cmd->Filler; - return 0; + return None; } static void writeInt(uint8_t *Buf, uint64_t Data, uint64_t Size) { Index: ELF/OutputSections.h =================================================================== --- ELF/OutputSections.h +++ ELF/OutputSections.h @@ -81,6 +81,7 @@ void sort(std::function Order); void sortInitFini(); void sortCtorsDtors(); + uint32_t getFill(); template void writeTo(uint8_t *Buf); template void finalize(); void assignOffsets(); Index: ELF/OutputSections.cpp =================================================================== --- ELF/OutputSections.cpp +++ ELF/OutputSections.cpp @@ -225,6 +225,9 @@ // Fill [Buf, Buf + Size) with Filler. Filler is written in big // endian order. This is used for linker script "=fillexp" command. static void fill(uint8_t *Buf, size_t Size, uint32_t Filler) { + if (Filler == 0) + return; + uint8_t V[4]; write32be(V, Filler); size_t I = 0; @@ -233,17 +236,44 @@ memcpy(Buf + I, V, Size - I); } +uint32_t OutputSection::getFill() { + // Determine what to fill gaps between InputSections with, as specified by the + // linker script. If nothing is specified and this is an executable section, + // fall back to trap instructions to prevent bad diassembly and detect invalid + // jumps to padding. + if (Optional Filler = Script->getFiller(Name)) + return *Filler; + if (Flags & SHF_EXECINSTR) + return Target->TrapInstr; + return 0; +} + template void OutputSection::writeTo(uint8_t *Buf) { Loc = Buf; - if (uint32_t Filler = Script->getFiller(this->Name)) - fill(Buf, this->Size, Filler); - parallelForEach(Sections.begin(), Sections.end(), - [=](InputSection *IS) { IS->writeTo(Buf); }); + uint32_t Filler = getFill(); + + // Write leading padding. + size_t FillSize = Sections.empty() ? Size : Sections.front()->OutSecOff; + fill(Buf, FillSize, Filler); + + parallelFor(0, Sections.size(), [=](size_t I) { + InputSection *Sec = Sections[I]; + Sec->writeTo(Buf); + + // Fill gaps between sections with the specified fill value. + uint8_t *Start = Buf + Sec->OutSecOff + Sec->getSize(); + uint8_t *End; + if (I + 1 == Sections.size()) + End = Buf + Size; + else + End = Buf + Sections[I + 1]->OutSecOff; + fill(Start, End - Start, Filler); + }); // Linker scripts may have BYTE()-family commands with which you // can write arbitrary bytes to the output. Process them if any. - Script->writeDataBytes(this->Name, Buf); + Script->writeDataBytes(Name, Buf); } static uint64_t getOutFlags(InputSectionBase *S) { Index: ELF/SyntheticSections.cpp =================================================================== --- ELF/SyntheticSections.cpp +++ ELF/SyntheticSections.cpp @@ -2180,7 +2180,11 @@ void MipsRldMapSection::writeTo(uint8_t *Buf) { // Apply filler from linker script. - uint64_t Filler = Script->getFiller(this->Name); + Optional Fill = Script->getFiller(this->Name); + if (!Fill || *Fill == 0) + return; + + uint64_t Filler = *Fill; Filler = (Filler << 32) | Filler; memcpy(Buf, &Filler, getSize()); } Index: ELF/Target.h =================================================================== --- ELF/Target.h +++ ELF/Target.h @@ -91,6 +91,10 @@ bool NeedsThunks = false; + // A 4-byte field corresponding to one or more trap instructions, used to pad + // executable OutputSections. + uint32_t TrapInstr = 0; + virtual RelExpr adjustRelaxExpr(uint32_t Type, const uint8_t *Data, RelExpr Expr) const; virtual void relaxGot(uint8_t *Loc, uint64_t Val) const; Index: ELF/Target.cpp =================================================================== --- ELF/Target.cpp +++ ELF/Target.cpp @@ -355,6 +355,8 @@ PltEntrySize = 16; PltHeaderSize = 16; TlsGdRelaxSkip = 2; + // 0xCC is the "int3" (call debug exception handler) instruction. + TrapInstr = 0xcccccccc; } RelExpr X86TargetInfo::getRelExpr(uint32_t Type, const SymbolBody &S) const { @@ -647,6 +649,8 @@ // Align to the large page size (known as a superpage or huge page). // FreeBSD automatically promotes large, superpage-aligned allocations. DefaultImageBase = 0x200000; + // 0xCC is the "int3" (call debug exception handler) instruction. + TrapInstr = 0xcccccccc; } template Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -1802,7 +1802,7 @@ // The .eh_frame_hdr depends on .eh_frame section contents, therefore // it should be written after .eh_frame is written. - if (EhFrameHdr) + if (EhFrameHdr && !EhFrameHdr->Sections.empty()) EhFrameHdr->writeTo(Buf + EhFrameHdr->Offset); } Index: test/ELF/default-fill.s =================================================================== --- test/ELF/default-fill.s +++ test/ELF/default-fill.s @@ -0,0 +1,38 @@ +# REQUIRES: x86 +# Verify that the fill between sections has a default of interrupt instructions +# (0xcc on x86/x86_64) for executable sections and zero for other sections. + +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o +# RUN: ld.lld %t1.o -o %t1.elf +# RUN: llvm-objdump -s %t1.elf > %t1.sections +# RUN: FileCheck %s --input-file %t1.sections --check-prefix=TEXT +# RUN: FileCheck %s --input-file %t1.sections --check-prefix=DATA + +# RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t2.o +# RUN: ld.lld %t2.o -o %t2.elf +# RUN: llvm-objdump -s %t2.elf > %t2.sections +# RUN: FileCheck %s --input-file %t2.sections --check-prefix=TEXT +# RUN: FileCheck %s --input-file %t2.sections --check-prefix=DATA + +# TEXT: Contents of section .text: +# TEXT-NEXT: 11cccccc cccccccc cccccccc cccccccc +# TEXT-NEXT: 22 +# DATA: Contents of section .data: +# DATA-NEXT: 33000000 00000000 00000000 00000000 +# DATA-NEXT: 44 + +.section .text.1,"ax",@progbits +.align 16 +.byte 0x11 + +.section .text.2,"ax",@progbits +.align 16 +.byte 0x22 + +.section .data.1,"a",@progbits +.align 16 +.byte 0x33 + +.section .data.2,"a",@progbits +.align 16 +.byte 0x44 Index: test/ELF/linkerscript/excludefile.s =================================================================== --- test/ELF/linkerscript/excludefile.s +++ test/ELF/linkerscript/excludefile.s @@ -13,11 +13,13 @@ # CHECK: _start: # CHECK-NEXT: : 48 c7 c0 3c 00 00 00 movq $60, %rax # CHECK-NEXT: : 48 c7 c7 2a 00 00 00 movq $42, %rdi -# CHECK-NEXT: : 00 00 addb %al, (%rax) +# CHECK-NEXT: : cc int3 +# CHECK-NEXT: : cc int3 # CHECK: _potato: # CHECK-NEXT: : 90 nop # CHECK-NEXT: : 90 nop -# CHECK-NEXT: : 00 00 addb %al, (%rax) +# CHECK-NEXT: : cc int3 +# CHECK-NEXT: : cc int3 # CHECK: tomato: # CHECK-NEXT: : b8 01 00 00 00 movl $1, %eax @@ -31,7 +33,8 @@ # EXCLUDE: _start: # EXCLUDE-NEXT: : 48 c7 c0 3c 00 00 00 movq $60, %rax # EXCLUDE-NEXT: : 48 c7 c7 2a 00 00 00 movq $42, %rdi -# EXCLUDE-NEXT: : 00 00 addb %al, (%rax) +# EXCLUDE-NEXT: : cc int3 +# EXCLUDE-NEXT: : cc int3 # EXCLUDE: _potato: # EXCLUDE-NEXT: : 90 nop # EXCLUDE-NEXT: : 90 nop Index: test/ELF/linkerscript/fill-exec-sections.s =================================================================== --- test/ELF/linkerscript/fill-exec-sections.s +++ test/ELF/linkerscript/fill-exec-sections.s @@ -0,0 +1,40 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t + +## Check that padding of executable sections are filled with trap bytes if not +## otherwise specified in the script. +# RUN: echo "SECTIONS { .exec : { *(.exec*) } }" > %t.script +# RUN: ld.lld -o %t.out --script %t.script %t +# RUN: llvm-objdump -s %t.out | FileCheck %s --check-prefix=EXEC +# EXEC: 0000 66cccccc cccccccc cccccccc cccccccc +# EXEC-NEXT: 0010 66 + +## Check that a fill expression or command overrides the default filler... +# RUN: echo "SECTIONS { .exec : { *(.exec*) }=0x11223344 }" > %t2.script +# RUN: ld.lld -o %t2.out --script %t2.script %t +# RUN: llvm-objdump -s %t2.out | FileCheck %s --check-prefix=OVERRIDE +# RUN: echo "SECTIONS { .exec : { FILL(0x11223344); *(.exec*) } }" > %t3.script +# RUN: ld.lld -o %t3.out --script %t3.script %t +# RUN: llvm-objdump -s %t3.out | FileCheck %s --check-prefix=OVERRIDE +# OVERRIDE: Contents of section .exec: +# OVERRIDE-NEXT: 0000 66112233 44112233 44112233 44112233 +# OVERRIDE-NEXT: 0010 66 + +## ...even for a value of zero. +# RUN: echo "SECTIONS { .exec : { *(.exec*) }=0x00000000 }" > %t4.script +# RUN: ld.lld -o %t4.out --script %t4.script %t +# RUN: llvm-objdump -s %t4.out | FileCheck %s --check-prefix=ZERO +# RUN: echo "SECTIONS { .exec : { FILL(0x00000000); *(.exec*) } }" > %t5.script +# RUN: ld.lld -o %t5.out --script %t5.script %t +# RUN: llvm-objdump -s %t5.out | FileCheck %s --check-prefix=ZERO +# ZERO: Contents of section .exec: +# ZERO-NEXT: 0000 66000000 00000000 00000000 00000000 +# ZERO-NEXT: 0010 66 + +.section .exec.1,"ax" +.align 16 +.byte 0x66 + +.section .exec.2,"ax" +.align 16 +.byte 0x66 Index: test/ELF/linkerscript/fill.s =================================================================== --- test/ELF/linkerscript/fill.s +++ test/ELF/linkerscript/fill.s @@ -3,6 +3,7 @@ # RUN: echo "SECTIONS { \ # RUN: .out : { \ # RUN: FILL(0x11111111); \ +# RUN: . += 2; \ # RUN: *(.aaa) \ # RUN: . += 4; \ # RUN: *(.bbb) \ @@ -15,7 +16,7 @@ # RUN: llvm-objdump -s %t | FileCheck %s # CHECK: Contents of section .out: -# CHECK-NEXT: aa222222 22bb2222 22222222 2222 +# CHECK-NEXT: 2222aa22 222222bb 22222222 22222222 .text .globl _start Index: test/ELF/linkerscript/sections-padding.s =================================================================== --- test/ELF/linkerscript/sections-padding.s +++ test/ELF/linkerscript/sections-padding.s @@ -5,13 +5,13 @@ # RUN: echo "SECTIONS { .mysec : { *(.mysec*) } =0x1122 }" > %t.script # RUN: ld.lld -o %t.out --script %t.script %t # RUN: llvm-objdump -s %t.out | FileCheck -check-prefix=YES %s -# YES: 66001122 00001122 00001122 00001122 +# YES: 66000011 22000011 22000011 22000011 ## Confirming that address was correct: # RUN: echo "SECTIONS { .mysec : { *(.mysec*) } =0x99887766 }" > %t.script # RUN: ld.lld -o %t.out --script %t.script %t # RUN: llvm-objdump -s %t.out | FileCheck -check-prefix=YES2 %s -# YES2: 66887766 99887766 99887766 99887766 +# YES2: 66998877 66998877 66998877 66998877 ## Default padding value is 0x00: # RUN: echo "SECTIONS { .mysec : { *(.mysec*) } }" > %t.script @@ -23,7 +23,7 @@ # RUN: echo "SECTIONS { .mysec : { *(.mysec*) } =777 }" > %t.script # RUN: ld.lld -o %t.out --script %t.script %t # RUN: llvm-objdump -s %t.out | FileCheck -check-prefix=DEC %s -# DEC: 66000309 00000309 00000309 00000309 +# DEC: 66000003 09000003 09000003 09000003 ## Invalid hex value: # RUN: echo "SECTIONS { .mysec : { *(.mysec*) } =0x99XX }" > %t.script