@@ -76,14 +76,8 @@ static unsigned char dosProgram[] = {
7676};
7777static_assert (sizeof (dosProgram) % 8 == 0 ,
7878 " DOSProgram size must be multiple of 8" );
79-
80- static const int dosStubSize = sizeof (dos_header) + sizeof (dosProgram);
81- static_assert (dosStubSize % 8 == 0 , " DOSStub size must be multiple of 8" );
82- static const uint32_t coffHeaderOffset = dosStubSize + sizeof (PEMagic);
83- static const uint32_t peHeaderOffset =
84- coffHeaderOffset + sizeof (coff_file_header);
85- static const uint32_t dataDirOffset64 =
86- peHeaderOffset + sizeof (pe32plus_header);
79+ static_assert ((sizeof (dos_header) + sizeof (dosProgram)) % 8 == 0 ,
80+ " DOSStub size must be multiple of 8" );
8781
8882static const int numberOfDataDirectory = 16 ;
8983
@@ -214,6 +208,7 @@ class Writer {
214208 void run ();
215209
216210private:
211+ void calculateStubDependentSizes ();
217212 void createSections ();
218213 void createMiscChunks ();
219214 void createImportTables ();
@@ -315,6 +310,11 @@ class Writer {
315310 uint64_t sizeOfImage;
316311 uint64_t sizeOfHeaders;
317312
313+ uint32_t dosStubSize;
314+ uint32_t coffHeaderOffset;
315+ uint32_t peHeaderOffset;
316+ uint32_t dataDirOffset64;
317+
318318 OutputSection *textSec;
319319 OutputSection *hexpthkSec;
320320 OutputSection *rdataSec;
@@ -728,10 +728,8 @@ void Writer::writePEChecksum() {
728728 uint32_t *buf = (uint32_t *)buffer->getBufferStart ();
729729 uint32_t size = (uint32_t )(buffer->getBufferSize ());
730730
731- coff_file_header *coffHeader =
732- (coff_file_header *)((uint8_t *)buf + dosStubSize + sizeof (PEMagic));
733- pe32_header *peHeader =
734- (pe32_header *)((uint8_t *)coffHeader + sizeof (coff_file_header));
731+ pe32_header *peHeader = (pe32_header *)((uint8_t *)buf + coffHeaderOffset +
732+ sizeof (coff_file_header));
735733
736734 uint64_t sum = 0 ;
737735 uint32_t count = size;
@@ -762,6 +760,7 @@ void Writer::run() {
762760 llvm::TimeTraceScope timeScope (" Write PE" );
763761 ScopedTimer t1 (ctx.codeLayoutTimer );
764762
763+ calculateStubDependentSizes ();
765764 if (ctx.config .machine == ARM64X)
766765 ctx.dynamicRelocs = make<DynamicRelocsChunk>();
767766 createImportTables ();
@@ -1035,6 +1034,17 @@ void Writer::sortSections() {
10351034 sortBySectionOrder (it.second ->chunks );
10361035}
10371036
1037+ void Writer::calculateStubDependentSizes () {
1038+ if (ctx.config .dosStub )
1039+ dosStubSize = alignTo (ctx.config .dosStub ->getBufferSize (), 8 );
1040+ else
1041+ dosStubSize = sizeof (dos_header) + sizeof (dosProgram);
1042+
1043+ coffHeaderOffset = dosStubSize + sizeof (PEMagic);
1044+ peHeaderOffset = coffHeaderOffset + sizeof (coff_file_header);
1045+ dataDirOffset64 = peHeaderOffset + sizeof (pe32plus_header);
1046+ }
1047+
10381048// Create output section objects and add them to OutputSections.
10391049void Writer::createSections () {
10401050 llvm::TimeTraceScope timeScope (" Output sections" );
@@ -1668,21 +1678,37 @@ template <typename PEHeaderTy> void Writer::writeHeader() {
16681678 // When run under Windows, the loader looks at AddressOfNewExeHeader and uses
16691679 // the PE header instead.
16701680 Configuration *config = &ctx.config ;
1681+
16711682 uint8_t *buf = buffer->getBufferStart ();
16721683 auto *dos = reinterpret_cast <dos_header *>(buf);
1673- buf += sizeof (dos_header);
1674- dos->Magic [0 ] = ' M' ;
1675- dos->Magic [1 ] = ' Z' ;
1676- dos->UsedBytesInTheLastPage = dosStubSize % 512 ;
1677- dos->FileSizeInPages = divideCeil (dosStubSize, 512 );
1678- dos->HeaderSizeInParagraphs = sizeof (dos_header) / 16 ;
1679-
1680- dos->AddressOfRelocationTable = sizeof (dos_header);
1681- dos->AddressOfNewExeHeader = dosStubSize;
16821684
16831685 // Write DOS program.
1684- memcpy (buf, dosProgram, sizeof (dosProgram));
1685- buf += sizeof (dosProgram);
1686+ if (config->dosStub ) {
1687+ memcpy (buf, config->dosStub ->getBufferStart (),
1688+ config->dosStub ->getBufferSize ());
1689+ // MS link.exe accepts an invalid `e_lfanew` (AddressOfNewExeHeader) and
1690+ // updates it automatically. Replicate the same behaviour.
1691+ dos->AddressOfNewExeHeader = alignTo (config->dosStub ->getBufferSize (), 8 );
1692+ // Unlike MS link.exe, LLD accepts non-8-byte-aligned stubs.
1693+ // In that case, we add zero paddings ourselves.
1694+ buf += alignTo (config->dosStub ->getBufferSize (), 8 );
1695+ } else {
1696+ buf += sizeof (dos_header);
1697+ dos->Magic [0 ] = ' M' ;
1698+ dos->Magic [1 ] = ' Z' ;
1699+ dos->UsedBytesInTheLastPage = dosStubSize % 512 ;
1700+ dos->FileSizeInPages = divideCeil (dosStubSize, 512 );
1701+ dos->HeaderSizeInParagraphs = sizeof (dos_header) / 16 ;
1702+
1703+ dos->AddressOfRelocationTable = sizeof (dos_header);
1704+ dos->AddressOfNewExeHeader = dosStubSize;
1705+
1706+ memcpy (buf, dosProgram, sizeof (dosProgram));
1707+ buf += sizeof (dosProgram);
1708+ }
1709+
1710+ // Make sure DOS stub is aligned to 8 bytes at this point
1711+ assert ((buf - buffer->getBufferStart ()) % 8 == 0 );
16861712
16871713 // Write PE magic
16881714 memcpy (buf, PEMagic, sizeof (PEMagic));
0 commit comments