diff options
| author | Petr Hosek <phosek@chromium.org> | 2017-08-02 16:35:00 +0000 |
|---|---|---|
| committer | Petr Hosek <phosek@chromium.org> | 2017-08-02 16:35:00 +0000 |
| commit | edd6c3587c736f2c76df77ace5a98d0c21e7e534 (patch) | |
| tree | 9209b16b07e646077f142cfada6b0fda0c26cd81 | |
| parent | a70e2649ab868d532c012581435230b3ed85fb41 (diff) | |
| download | bcm5719-llvm-edd6c3587c736f2c76df77ace5a98d0c21e7e534.tar.gz bcm5719-llvm-edd6c3587c736f2c76df77ace5a98d0c21e7e534.zip | |
[ELF] When the code segment is the last, align it to the page boundary
When the data segment is the last segment, it is correct to leave
it unaligned. However, when the code segment is the last segment,
it should be aligned to the page boundary to avoid loading the
non-segment parts of the ELF file at the end of the file.
Differential Revision: https://reviews.llvm.org/D33630
llvm-svn: 309829
| -rw-r--r-- | lld/ELF/Writer.cpp | 61 | ||||
| -rw-r--r-- | lld/test/ELF/avoid-empty-program-headers.s | 4 | ||||
| -rw-r--r-- | lld/test/ELF/basic-aarch64.s | 12 | ||||
| -rw-r--r-- | lld/test/ELF/basic-sparcv9.s | 12 | ||||
| -rw-r--r-- | lld/test/ELF/basic.s | 12 | ||||
| -rw-r--r-- | lld/test/ELF/basic32.s | 12 | ||||
| -rw-r--r-- | lld/test/ELF/build-id.s | 6 | ||||
| -rw-r--r-- | lld/test/ELF/image-base.s | 2 | ||||
| -rw-r--r-- | lld/test/ELF/relocatable.s | 2 |
9 files changed, 91 insertions, 32 deletions
diff --git a/lld/ELF/Writer.cpp b/lld/ELF/Writer.cpp index a9e385649d8..0ea28d87c02 100644 --- a/lld/ELF/Writer.cpp +++ b/lld/ELF/Writer.cpp @@ -65,6 +65,7 @@ private: void fixSectionAlignments(); void fixPredefinedSymbols(); void openFile(); + void writeTrapInstr(); void writeHeader(); void writeSections(); void writeSectionsBinary(); @@ -232,6 +233,7 @@ template <class ELFT> void Writer<ELFT>::run() { return; if (!Config->OFormatBinary) { + writeTrapInstr(); writeHeader(); writeSections(); } else { @@ -1596,8 +1598,21 @@ template <class ELFT> void Writer<ELFT>::assignFileOffsets() { Off = setOffset(Out::ElfHeader, Off); Off = setOffset(Out::ProgramHeaders, Off); - for (OutputSection *Sec : OutputSections) + PhdrEntry *LastRX = nullptr; + for (PhdrEntry *P : Phdrs) + if (P->p_type == PT_LOAD && (P->p_flags & PF_X)) + LastRX = P; + + for (OutputSection *Sec : OutputSections) { Off = setOffset(Sec, Off); + if (Script->Opt.HasSections) + continue; + // 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 == Sec) + Off = alignTo(Off, Target->PageSize); + } SectionHeaderOff = alignTo(Off, Config->Wordsize); FileSize = SectionHeaderOff + (OutputSections.size() + 1) * sizeof(Elf_Shdr); @@ -1815,6 +1830,50 @@ template <class ELFT> void Writer<ELFT>::writeSectionsBinary() { Sec->writeTo<ELFT>(Buf + Sec->Offset); } +static void fillTrapInstr(uint8_t *I, uint8_t *End) { + for (; I + 4 < End; I += 4) + memcpy(I, &Target->TrapInstr, 4); +} + + +// Fill the first and the last page of executable segments 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. +template <class ELFT> void Writer<ELFT>::writeTrapInstr() { + if (Script->Opt.HasSections) + return; + + uint8_t *Buf = Buffer->getBufferStart(); + + for (PhdrEntry *P : Phdrs) { + if (P->p_type != PT_LOAD || !(P->p_flags & PF_X)) + continue; + + // We only fill the first and the last page of the segment because the + // middle part will be overwritten by output sections. + fillTrapInstr(Buf + alignDown(P->p_offset, Target->PageSize), + Buf + alignTo(P->p_offset, Target->PageSize)); + fillTrapInstr(Buf + alignDown(P->p_offset + P->p_filesz, Target->PageSize), + Buf + alignTo(P->p_offset + P->p_filesz, Target->PageSize)); + } + + 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; + } + + // Round up the file size of the last segment to the page boundary iff it is + // an executable segment to ensure that other other tools don't accidentally + // trim the instruction padding (e.g. when stripping the file). + if (LastRX) + LastRX->p_filesz = alignTo(LastRX->p_filesz, Target->PageSize); +} + // Write section contents to a mmap'ed file. template <class ELFT> void Writer<ELFT>::writeSections() { uint8_t *Buf = Buffer->getBufferStart(); diff --git a/lld/test/ELF/avoid-empty-program-headers.s b/lld/test/ELF/avoid-empty-program-headers.s index 271d1a30385..e990a0ebfa7 100644 --- a/lld/test/ELF/avoid-empty-program-headers.s +++ b/lld/test/ELF/avoid-empty-program-headers.s @@ -42,7 +42,7 @@ _start: // 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 @@ _start: // 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 diff --git a/lld/test/ELF/basic-aarch64.s b/lld/test/ELF/basic-aarch64.s index 144fe6aee41..408d106f54e 100644 --- a/lld/test/ELF/basic-aarch64.s +++ b/lld/test/ELF/basic-aarch64.s @@ -26,7 +26,7 @@ _start: # 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 @@ _start: # 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 @@ _start: # 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 @@ _start: # 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 @@ _start: # 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 @@ _start: # 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) diff --git a/lld/test/ELF/basic-sparcv9.s b/lld/test/ELF/basic-sparcv9.s index 983224c5291..48ba8f4bf19 100644 --- a/lld/test/ELF/basic-sparcv9.s +++ b/lld/test/ELF/basic-sparcv9.s @@ -26,7 +26,7 @@ _start: # 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 @@ _start: # 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 @@ _start: # 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 @@ _start: # 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 @@ _start: # 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 @@ _start: # 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) diff --git a/lld/test/ELF/basic.s b/lld/test/ELF/basic.s index c62a516c1bf..164e17c805e 100644 --- a/lld/test/ELF/basic.s +++ b/lld/test/ELF/basic.s @@ -28,7 +28,7 @@ _start: # 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 @@ _start: # 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 @@ _start: # 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 @@ _start: # 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 @@ _start: # 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 @@ _start: # 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) diff --git a/lld/test/ELF/basic32.s b/lld/test/ELF/basic32.s index cbf67eec8b7..ef87258d19c 100644 --- a/lld/test/ELF/basic32.s +++ b/lld/test/ELF/basic32.s @@ -25,7 +25,7 @@ _start: # 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 @@ _start: # 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 @@ _start: # 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 @@ _start: # 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 @@ _start: # 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 @@ _start: # 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) diff --git a/lld/test/ELF/build-id.s b/lld/test/ELF/build-id.s index 2d193478df7..f1740ee8b02 100644 --- a/lld/test/ELF/build-id.s +++ b/lld/test/ELF/build-id.s @@ -48,15 +48,15 @@ _start: # 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. diff --git a/lld/test/ELF/image-base.s b/lld/test/ELF/image-base.s index 2f1f6bc75f0..05b2608723f 100644 --- a/lld/test/ELF/image-base.s +++ b/lld/test/ELF/image-base.s @@ -44,7 +44,7 @@ _start: # 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) diff --git a/lld/test/ELF/relocatable.s b/lld/test/ELF/relocatable.s index 00572d07cbb..7cb2a084c93 100644 --- a/lld/test/ELF/relocatable.s +++ b/lld/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 |

