@@ -76,14 +76,8 @@ static unsigned char dosProgram[] = {
76
76
};
77
77
static_assert (sizeof (dosProgram) % 8 == 0,
78
78
"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");
87
81
88
82
static const int numberOfDataDirectory = 16 ;
89
83
@@ -214,6 +208,7 @@ class Writer {
214
208
void run ();
215
209
216
210
private:
211
+ void calculateStubDependentSizes ();
217
212
void createSections ();
218
213
void createMiscChunks ();
219
214
void createImportTables ();
@@ -315,6 +310,11 @@ class Writer {
315
310
uint64_t sizeOfImage;
316
311
uint64_t sizeOfHeaders;
317
312
313
+ uint32_t dosStubSize;
314
+ uint32_t coffHeaderOffset;
315
+ uint32_t peHeaderOffset;
316
+ uint32_t dataDirOffset64;
317
+
318
318
OutputSection *textSec;
319
319
OutputSection *hexpthkSec;
320
320
OutputSection *rdataSec;
@@ -728,10 +728,8 @@ void Writer::writePEChecksum() {
728
728
uint32_t *buf = (uint32_t *)buffer->getBufferStart ();
729
729
uint32_t size = (uint32_t )(buffer->getBufferSize ());
730
730
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));
735
733
736
734
uint64_t sum = 0 ;
737
735
uint32_t count = size;
@@ -762,6 +760,7 @@ void Writer::run() {
762
760
llvm::TimeTraceScope timeScope (" Write PE" );
763
761
ScopedTimer t1 (ctx.codeLayoutTimer );
764
762
763
+ calculateStubDependentSizes ();
765
764
if (ctx.config .machine == ARM64X)
766
765
ctx.dynamicRelocs = make<DynamicRelocsChunk>();
767
766
createImportTables ();
@@ -1035,6 +1034,17 @@ void Writer::sortSections() {
1035
1034
sortBySectionOrder (it.second ->chunks );
1036
1035
}
1037
1036
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
+
1038
1048
// Create output section objects and add them to OutputSections.
1039
1049
void Writer::createSections () {
1040
1050
llvm::TimeTraceScope timeScope (" Output sections" );
@@ -1668,21 +1678,37 @@ template <typename PEHeaderTy> void Writer::writeHeader() {
1668
1678
// When run under Windows, the loader looks at AddressOfNewExeHeader and uses
1669
1679
// the PE header instead.
1670
1680
Configuration *config = &ctx.config ;
1681
+
1671
1682
uint8_t *buf = buffer->getBufferStart ();
1672
1683
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;
1682
1684
1683
1685
// 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 );
1686
1712
1687
1713
// Write PE magic
1688
1714
memcpy (buf, PEMagic, sizeof (PEMagic));
0 commit comments