void fixSectionAlignments();
void fixPredefinedSymbols();
void openFile();
+ void writeTrapInstr();
void writeHeader();
void writeSections();
void writeSectionsBinary();
return;
if (!Config->OFormatBinary) {
+ writeTrapInstr();
writeHeader();
writeSections();
} else {
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);
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();
// 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)
// 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
# 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
# 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
# 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
# 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
# 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
# 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)
# 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
# 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
# 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
# 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
# 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
# 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)
# 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
# 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
# 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
# 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
# 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
# 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)
# 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
# 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
# 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
# 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
# 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
# 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)
# 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.
# 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)
# 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