Index: COFF/Writer.cpp =================================================================== --- COFF/Writer.cpp +++ COFF/Writer.cpp @@ -42,8 +42,37 @@ using namespace lld; using namespace lld::coff; +/* To re-generate DOSProgram: +$ cat > /tmp/DOSProgram.asm +org 0 + ; Copy cs to ds. + push cs + pop ds + ; Point ds:dx at the $-terminated string. + mov dx, str + ; Int 21/AH=09h: Write string to standard output. + mov ah, 0x9 + int 0x21 + ; Int 21/AH=4Ch: Exit with return code (in AL). + mov ax, 0x4C01 + int 0x21 +str: + db 'This program cannot be run in DOS mode.$' +$ nasm -fbin /tmp/DOSProgram.asm -o /tmp/DOSProgram.bin +$ xxd -i /tmp/DOSProgram.bin +*/ +static unsigned char DOSProgram[] = { + 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c, + 0xcd, 0x21, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, + 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65, + 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20, + 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x24 +}; + static const int SectorSize = 512; -static const int DOSStubSize = 64; +static const int DOSStubSize = sizeof(dos_header) + sizeof(DOSProgram); +static const int PEOffset = alignTo(DOSStubSize, 8); + static const int NumberfOfDataDirectory = 16; namespace { @@ -631,7 +660,7 @@ // Visits all sections to assign incremental, non-overlapping RVAs and // file offsets. void Writer::assignAddresses() { - SizeOfHeaders = DOSStubSize + sizeof(PEMagic) + sizeof(coff_file_header) + + SizeOfHeaders = PEOffset + sizeof(PEMagic) + sizeof(coff_file_header) + sizeof(data_directory) * NumberfOfDataDirectory + sizeof(coff_section) * OutputSections.size(); SizeOfHeaders += @@ -657,16 +686,24 @@ } template void Writer::writeHeader() { - // Write DOS stub + // Write DOS header. uint8_t *Buf = Buffer->getBufferStart(); auto *DOS = reinterpret_cast(Buf); - Buf += DOSStubSize; + Buf += sizeof(dos_header); DOS->Magic[0] = 'M'; DOS->Magic[1] = 'Z'; + DOS->UsedBytesInTheLastPage = DOSStubSize % 512; + DOS->FileSizeInPages = divideCeil(DOSStubSize, 512); + DOS->HeaderSizeInParagraphs = sizeof(dos_header) / 16; + DOS->AddressOfRelocationTable = sizeof(dos_header); - DOS->AddressOfNewExeHeader = DOSStubSize; + DOS->AddressOfNewExeHeader = PEOffset; + + // Write DOS program. + memcpy(Buf, DOSProgram, sizeof(DOSProgram)); // Write PE magic + Buf = Buffer->getBufferStart() + PEOffset; memcpy(Buf, PEMagic, sizeof(PEMagic)); Buf += sizeof(PEMagic); Index: test/COFF/hello32.test =================================================================== --- test/COFF/hello32.test +++ test/COFF/hello32.test @@ -40,7 +40,7 @@ HEADER-NEXT: MajorSubsystemVersion: 6 HEADER-NEXT: MinorSubsystemVersion: 0 HEADER-NEXT: SizeOfImage: 20480 -HEADER-NEXT: SizeOfHeaders: 512 +HEADER-NEXT: SizeOfHeaders: 1024 HEADER-NEXT: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI (0x3) HEADER-NEXT: Characteristics [ (0x9540) HEADER-NEXT: IMAGE_DLL_CHARACTERISTICS_APPCONTAINER (0x1000) @@ -91,10 +91,10 @@ HEADER-NEXT: } HEADER-NEXT: DOSHeader { HEADER-NEXT: Magic: MZ -HEADER-NEXT: UsedBytesInTheLastPage: 0 -HEADER-NEXT: FileSizeInPages: 0 +HEADER-NEXT: UsedBytesInTheLastPage: 118 +HEADER-NEXT: FileSizeInPages: 1 HEADER-NEXT: NumberOfRelocationItems: 0 -HEADER-NEXT: HeaderSizeInParagraphs: 0 +HEADER-NEXT: HeaderSizeInParagraphs: 4 HEADER-NEXT: MinimumExtraParagraphs: 0 HEADER-NEXT: MaximumExtraParagraphs: 0 HEADER-NEXT: InitialRelativeSS: 0 @@ -106,7 +106,7 @@ HEADER-NEXT: OverlayNumber: 0 HEADER-NEXT: OEMid: 0 HEADER-NEXT: OEMinfo: 0 -HEADER-NEXT: AddressOfNewExeHeader: 64 +HEADER-NEXT: AddressOfNewExeHeader: 120 HEADER-NEXT: } IMPORTS: Format: COFF-i386