Commit 3c10221030

Jakub Konka <kubkon@jakubkonka.com>
2022-08-21 09:56:55
coff: move header writing logic into flush
1 parent 0637195
Changed files (1)
src
src/link/Coff.zig
@@ -144,39 +144,10 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option
     });
     self.base.file = file;
 
-    // TODO Write object specific relocations, COFF symbol table, then enable object file output.
-    switch (options.output_mode) {
-        .Exe => {},
-        .Obj => return error.TODOImplementWritingObjFiles,
-        .Lib => return error.TODOImplementWritingLibFiles,
-    }
-
-    var coff_file_header_offset: u32 = 0;
-    if (options.output_mode == .Exe) {
-        // Write the MS-DOS stub and the PE signature
-        try self.base.file.?.pwriteAll(msdos_stub ++ "PE\x00\x00", 0);
-        coff_file_header_offset = msdos_stub.len + 4;
-    }
-
-    // COFF file header
+    const coff_file_header_offset: u32 = if (options.output_mode == .Exe) msdos_stub.len + 4 else 0;
+    const default_offset_table_size = file_alignment;
     const data_directory_count = 0;
-    var hdr_data: [112 + data_directory_count * 8 + section_table_size]u8 = undefined;
-    var index: usize = 0;
-
-    const machine = self.base.options.target.cpu.arch.toCoffMachine();
-    if (machine == .Unknown) {
-        return error.UnsupportedCOFFArchitecture;
-    }
-    mem.writeIntLittle(u16, hdr_data[0..2], @enumToInt(machine));
-    index += 2;
-
-    // Number of sections (we only use .got, .text)
-    mem.writeIntLittle(u16, hdr_data[index..][0..2], 2);
-    index += 2;
-    // TimeDateStamp (u32), PointerToSymbolTable (u32), NumberOfSymbols (u32)
-    mem.set(u8, hdr_data[index..][0..12], 0);
-    index += 12;
-
+    const default_size_of_code = 0;
     const optional_header_size = switch (options.output_mode) {
         .Exe => data_directory_count * 8 + switch (self.ptr_width) {
             .p32 => @as(u16, 96),
@@ -184,218 +155,15 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option
         },
         else => 0,
     };
-
     const section_table_offset = coff_file_header_offset + 20 + optional_header_size;
-    const default_offset_table_size = file_alignment;
-    const default_size_of_code = 0;
-
-    self.section_data_offset = mem.alignForwardGeneric(u32, self.section_table_offset + section_table_size, file_alignment);
-    const section_data_relative_virtual_address = mem.alignForwardGeneric(u32, self.section_table_offset + section_table_size, section_alignment);
+    self.section_data_offset = mem.alignForwardGeneric(u32, section_table_offset + section_table_size, file_alignment);
+    const section_data_relative_virtual_address = mem.alignForwardGeneric(u32, section_table_offset + section_table_size, section_alignment);
     self.offset_table_virtual_address = default_image_base + section_data_relative_virtual_address;
     self.offset_table_size = default_offset_table_size;
     self.section_table_offset = section_table_offset;
     self.text_section_virtual_address = default_image_base + section_data_relative_virtual_address + section_alignment;
     self.text_section_size = default_size_of_code;
 
-    // Size of file when loaded in memory
-    const size_of_image = mem.alignForwardGeneric(u32, self.text_section_virtual_address - default_image_base + default_size_of_code, section_alignment);
-
-    mem.writeIntLittle(u16, hdr_data[index..][0..2], optional_header_size);
-    index += 2;
-
-    // Characteristics
-    var characteristics: std.coff.CoffHeaderFlags = .{
-        .DEBUG_STRIPPED = 1, // TODO remove debug info stripped flag when necessary
-        .RELOCS_STRIPPED = 1,
-    };
-    if (options.output_mode == .Exe) {
-        characteristics.EXECUTABLE_IMAGE = 1;
-    }
-    switch (self.ptr_width) {
-        .p32 => characteristics.@"32BIT_MACHINE" = 1,
-        .p64 => characteristics.LARGE_ADDRESS_AWARE = 1,
-    }
-    mem.writeIntLittle(u16, hdr_data[index..][0..2], @bitCast(u16, characteristics));
-    index += 2;
-
-    assert(index == 20);
-    try self.base.file.?.pwriteAll(hdr_data[0..index], coff_file_header_offset);
-
-    if (options.output_mode == .Exe) {
-        self.optional_header_offset = coff_file_header_offset + 20;
-        // Optional header
-        index = 0;
-        mem.writeIntLittle(u16, hdr_data[0..2], switch (self.ptr_width) {
-            .p32 => @as(u16, 0x10b),
-            .p64 => 0x20b,
-        });
-        index += 2;
-
-        // Linker version (u8 + u8)
-        mem.set(u8, hdr_data[index..][0..2], 0);
-        index += 2;
-
-        // SizeOfCode (UNUSED, u32), SizeOfInitializedData (u32), SizeOfUninitializedData (u32), AddressOfEntryPoint (u32), BaseOfCode (UNUSED, u32)
-        mem.set(u8, hdr_data[index..][0..20], 0);
-        index += 20;
-
-        if (self.ptr_width == .p32) {
-            // Base of data relative to the image base (UNUSED)
-            mem.set(u8, hdr_data[index..][0..4], 0);
-            index += 4;
-
-            // Image base address
-            mem.writeIntLittle(u32, hdr_data[index..][0..4], default_image_base);
-            index += 4;
-        } else {
-            // Image base address
-            mem.writeIntLittle(u64, hdr_data[index..][0..8], default_image_base);
-            index += 8;
-        }
-
-        // Section alignment
-        mem.writeIntLittle(u32, hdr_data[index..][0..4], section_alignment);
-        index += 4;
-        // File alignment
-        mem.writeIntLittle(u32, hdr_data[index..][0..4], file_alignment);
-        index += 4;
-        // Required OS version, 6.0 is vista
-        mem.writeIntLittle(u16, hdr_data[index..][0..2], 6);
-        index += 2;
-        mem.writeIntLittle(u16, hdr_data[index..][0..2], 0);
-        index += 2;
-        // Image version
-        mem.set(u8, hdr_data[index..][0..4], 0);
-        index += 4;
-        // Required subsystem version, same as OS version
-        mem.writeIntLittle(u16, hdr_data[index..][0..2], 6);
-        index += 2;
-        mem.writeIntLittle(u16, hdr_data[index..][0..2], 0);
-        index += 2;
-        // Reserved zeroes (u32)
-        mem.set(u8, hdr_data[index..][0..4], 0);
-        index += 4;
-        mem.writeIntLittle(u32, hdr_data[index..][0..4], size_of_image);
-        index += 4;
-        mem.writeIntLittle(u32, hdr_data[index..][0..4], self.section_data_offset);
-        index += 4;
-        // CheckSum (u32)
-        mem.set(u8, hdr_data[index..][0..4], 0);
-        index += 4;
-        // Subsystem, TODO: Let users specify the subsystem, always CUI for now
-        mem.writeIntLittle(u16, hdr_data[index..][0..2], 3);
-        index += 2;
-        // DLL characteristics
-        mem.writeIntLittle(u16, hdr_data[index..][0..2], 0x0);
-        index += 2;
-
-        switch (self.ptr_width) {
-            .p32 => {
-                // Size of stack reserve + commit
-                mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x1_000_000);
-                index += 4;
-                mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x1_000);
-                index += 4;
-                // Size of heap reserve + commit
-                mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x100_000);
-                index += 4;
-                mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x1_000);
-                index += 4;
-            },
-            .p64 => {
-                // Size of stack reserve + commit
-                mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x1_000_000);
-                index += 8;
-                mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x1_000);
-                index += 8;
-                // Size of heap reserve + commit
-                mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x100_000);
-                index += 8;
-                mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x1_000);
-                index += 8;
-            },
-        }
-
-        // Reserved zeroes
-        mem.set(u8, hdr_data[index..][0..4], 0);
-        index += 4;
-
-        // Number of data directories
-        mem.writeIntLittle(u32, hdr_data[index..][0..4], data_directory_count);
-        index += 4;
-        // Initialize data directories to zero
-        mem.set(u8, hdr_data[index..][0 .. data_directory_count * 8], 0);
-        index += data_directory_count * 8;
-
-        assert(index == optional_header_size);
-    }
-
-    // Write section table.
-    // First, the .got section
-    hdr_data[index..][0..8].* = ".got\x00\x00\x00\x00".*;
-    index += 8;
-    if (options.output_mode == .Exe) {
-        // Virtual size (u32)
-        mem.writeIntLittle(u32, hdr_data[index..][0..4], default_offset_table_size);
-        index += 4;
-        // Virtual address (u32)
-        mem.writeIntLittle(u32, hdr_data[index..][0..4], self.offset_table_virtual_address - default_image_base);
-        index += 4;
-    } else {
-        mem.set(u8, hdr_data[index..][0..8], 0);
-        index += 8;
-    }
-    // Size of raw data (u32)
-    mem.writeIntLittle(u32, hdr_data[index..][0..4], default_offset_table_size);
-    index += 4;
-    // File pointer to the start of the section
-    mem.writeIntLittle(u32, hdr_data[index..][0..4], self.section_data_offset);
-    index += 4;
-    // Pointer to relocations (u32), PointerToLinenumbers (u32), NumberOfRelocations (u16), NumberOfLinenumbers (u16)
-    mem.set(u8, hdr_data[index..][0..12], 0);
-    index += 12;
-    // Section flags
-    mem.writeIntLittle(u32, hdr_data[index..][0..4], @bitCast(u32, std.coff.SectionHeaderFlags{
-        .CNT_INITIALIZED_DATA = 1,
-        .MEM_READ = 1,
-    }));
-    index += 4;
-    // Then, the .text section
-    hdr_data[index..][0..8].* = ".text\x00\x00\x00".*;
-    index += 8;
-    if (options.output_mode == .Exe) {
-        // Virtual size (u32)
-        mem.writeIntLittle(u32, hdr_data[index..][0..4], default_size_of_code);
-        index += 4;
-        // Virtual address (u32)
-        mem.writeIntLittle(u32, hdr_data[index..][0..4], self.text_section_virtual_address - default_image_base);
-        index += 4;
-    } else {
-        mem.set(u8, hdr_data[index..][0..8], 0);
-        index += 8;
-    }
-    // Size of raw data (u32)
-    mem.writeIntLittle(u32, hdr_data[index..][0..4], default_size_of_code);
-    index += 4;
-    // File pointer to the start of the section
-    mem.writeIntLittle(u32, hdr_data[index..][0..4], self.section_data_offset + default_offset_table_size);
-    index += 4;
-    // Pointer to relocations (u32), PointerToLinenumbers (u32), NumberOfRelocations (u16), NumberOfLinenumbers (u16)
-    mem.set(u8, hdr_data[index..][0..12], 0);
-    index += 12;
-    // Section flags
-    mem.writeIntLittle(u32, hdr_data[index..][0..4], @bitCast(u32, std.coff.SectionHeaderFlags{
-        .CNT_CODE = 1,
-        .MEM_EXECUTE = 1,
-        .MEM_READ = 1,
-        .MEM_WRITE = 1,
-    }));
-    index += 4;
-
-    assert(index == optional_header_size + section_table_size);
-    try self.base.file.?.pwriteAll(hdr_data[0..index], self.optional_header_offset);
-    try self.base.file.?.setEndPos(self.section_data_offset + default_offset_table_size + default_size_of_code);
-
     return self;
 }
 
@@ -728,6 +496,12 @@ pub fn updateDecl(self: *Coff, module: *Module, decl_index: Module.Decl.Index) !
     if (decl.val.tag() == .extern_fn) {
         return; // TODO Should we do more when front-end analyzed extern decl?
     }
+    if (decl.val.castTag(.variable)) |payload| {
+        const variable = payload.data;
+        if (variable.is_extern) {
+            return; // TODO Should we do more when front-end analyzed extern decl?
+        }
+    }
 
     // TODO COFF/PE debug information
     // TODO Implement exports
@@ -735,9 +509,10 @@ pub fn updateDecl(self: *Coff, module: *Module, decl_index: Module.Decl.Index) !
     var code_buffer = std.ArrayList(u8).init(self.base.allocator);
     defer code_buffer.deinit();
 
+    const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
     const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
         .ty = decl.ty,
-        .val = decl.val,
+        .val = decl_val,
     }, &code_buffer, .none, .{
         .parent_atom_index = 0,
     });
@@ -862,15 +637,14 @@ pub fn updateDeclExports(
                 continue;
             }
         }
-        if (mem.eql(u8, exp.options.name, "_start")) {
+        if (mem.eql(u8, exp.options.name, "wWinMainCRTStartup")) {
             self.entry_addr = decl.link.coff.getVAddr(self.*) - default_image_base;
         } else {
             try module.failed_exports.ensureUnusedCapacity(module.gpa, 1);
             module.failed_exports.putAssumeCapacityNoClobber(
                 exp,
-                try Module.ErrorMsg.create(self.base.allocator, decl.srcLoc(), "Unimplemented: Exports other than '_start'", .{}),
+                try Module.ErrorMsg.create(self.base.allocator, decl.srcLoc(), "Unimplemented: Exports other than 'wWinMainCRTStartup'", .{}),
             );
-            continue;
         }
     }
 }
@@ -884,14 +658,13 @@ pub fn flush(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) !vo
         }
         return;
     }
-    if (build_options.have_llvm and self.base.options.use_lld) {
+    const use_lld = build_options.have_llvm and self.base.options.use_lld;
+    if (use_lld) {
         return self.linkWithLLD(comp, prog_node);
-    } else {
-        switch (self.base.options.effectiveOutputMode()) {
-            .Exe, .Obj => {},
-            .Lib => return error.TODOImplementWritingLibFiles,
-        }
-        return self.flushModule(comp, prog_node);
+    }
+    switch (self.base.options.output_mode) {
+        .Exe, .Obj => return self.flushModule(comp, prog_node),
+        .Lib => return error.TODOImplementWritingLibFiles,
     }
 }
 
@@ -909,6 +682,238 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
     sub_prog_node.activate();
     defer sub_prog_node.end();
 
+    const output_mode = self.base.options.output_mode;
+    log.debug("in flushModule with {}", .{output_mode});
+
+    var coff_file_header_offset: u32 = 0;
+    if (output_mode == .Exe) {
+        // Write the MS-DOS stub and the PE signature
+        try self.base.file.?.pwriteAll(msdos_stub ++ "PE\x00\x00", 0);
+        coff_file_header_offset = msdos_stub.len + 4;
+    }
+
+    // COFF file header
+    const data_directory_count = 0;
+    var hdr_data: [112 + data_directory_count * 8 + section_table_size]u8 = undefined;
+    var index: usize = 0;
+
+    const machine = self.base.options.target.cpu.arch.toCoffMachine();
+    if (machine == .Unknown) {
+        return error.UnsupportedCOFFArchitecture;
+    }
+    mem.writeIntLittle(u16, hdr_data[0..2], @enumToInt(machine));
+    index += 2;
+
+    // Number of sections (we only use .got, .text)
+    mem.writeIntLittle(u16, hdr_data[index..][0..2], 2);
+    index += 2;
+    // TimeDateStamp (u32), PointerToSymbolTable (u32), NumberOfSymbols (u32)
+    mem.set(u8, hdr_data[index..][0..12], 0);
+    index += 12;
+
+    const optional_header_size = switch (output_mode) {
+        .Exe => data_directory_count * 8 + switch (self.ptr_width) {
+            .p32 => @as(u16, 96),
+            .p64 => 112,
+        },
+        else => 0,
+    };
+
+    const default_offset_table_size = file_alignment;
+    const default_size_of_code = 0;
+
+    // Size of file when loaded in memory
+    const size_of_image = mem.alignForwardGeneric(u32, self.text_section_virtual_address - default_image_base + default_size_of_code, section_alignment);
+
+    mem.writeIntLittle(u16, hdr_data[index..][0..2], optional_header_size);
+    index += 2;
+
+    // Characteristics
+    var characteristics: u16 = std.coff.IMAGE_FILE_DEBUG_STRIPPED | std.coff.IMAGE_FILE_RELOCS_STRIPPED; // TODO Remove debug info stripped flag when necessary
+    if (output_mode == .Exe) {
+        characteristics |= std.coff.IMAGE_FILE_EXECUTABLE_IMAGE;
+    }
+    switch (self.ptr_width) {
+        .p32 => characteristics |= std.coff.IMAGE_FILE_32BIT_MACHINE,
+        .p64 => characteristics |= std.coff.IMAGE_FILE_LARGE_ADDRESS_AWARE,
+    }
+    mem.writeIntLittle(u16, hdr_data[index..][0..2], characteristics);
+    index += 2;
+
+    assert(index == 20);
+    try self.base.file.?.pwriteAll(hdr_data[0..index], coff_file_header_offset);
+
+    if (output_mode == .Exe) {
+        self.optional_header_offset = coff_file_header_offset + 20;
+        // Optional header
+        index = 0;
+        mem.writeIntLittle(u16, hdr_data[0..2], switch (self.ptr_width) {
+            .p32 => @as(u16, 0x10b),
+            .p64 => 0x20b,
+        });
+        index += 2;
+
+        // Linker version (u8 + u8)
+        mem.set(u8, hdr_data[index..][0..2], 0);
+        index += 2;
+
+        // SizeOfCode (UNUSED, u32), SizeOfInitializedData (u32), SizeOfUninitializedData (u32), AddressOfEntryPoint (u32), BaseOfCode (UNUSED, u32)
+        mem.set(u8, hdr_data[index..][0..20], 0);
+        index += 20;
+
+        if (self.ptr_width == .p32) {
+            // Base of data relative to the image base (UNUSED)
+            mem.set(u8, hdr_data[index..][0..4], 0);
+            index += 4;
+
+            // Image base address
+            mem.writeIntLittle(u32, hdr_data[index..][0..4], default_image_base);
+            index += 4;
+        } else {
+            // Image base address
+            mem.writeIntLittle(u64, hdr_data[index..][0..8], default_image_base);
+            index += 8;
+        }
+
+        // Section alignment
+        mem.writeIntLittle(u32, hdr_data[index..][0..4], section_alignment);
+        index += 4;
+        // File alignment
+        mem.writeIntLittle(u32, hdr_data[index..][0..4], file_alignment);
+        index += 4;
+        // Required OS version, 6.0 is vista
+        mem.writeIntLittle(u16, hdr_data[index..][0..2], 6);
+        index += 2;
+        mem.writeIntLittle(u16, hdr_data[index..][0..2], 0);
+        index += 2;
+        // Image version
+        mem.set(u8, hdr_data[index..][0..4], 0);
+        index += 4;
+        // Required subsystem version, same as OS version
+        mem.writeIntLittle(u16, hdr_data[index..][0..2], 6);
+        index += 2;
+        mem.writeIntLittle(u16, hdr_data[index..][0..2], 0);
+        index += 2;
+        // Reserved zeroes (u32)
+        mem.set(u8, hdr_data[index..][0..4], 0);
+        index += 4;
+        mem.writeIntLittle(u32, hdr_data[index..][0..4], size_of_image);
+        index += 4;
+        mem.writeIntLittle(u32, hdr_data[index..][0..4], self.section_data_offset);
+        index += 4;
+        // CheckSum (u32)
+        mem.set(u8, hdr_data[index..][0..4], 0);
+        index += 4;
+        // Subsystem, TODO: Let users specify the subsystem, always CUI for now
+        mem.writeIntLittle(u16, hdr_data[index..][0..2], 3);
+        index += 2;
+        // DLL characteristics
+        mem.writeIntLittle(u16, hdr_data[index..][0..2], 0x0);
+        index += 2;
+
+        switch (self.ptr_width) {
+            .p32 => {
+                // Size of stack reserve + commit
+                mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x1_000_000);
+                index += 4;
+                mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x1_000);
+                index += 4;
+                // Size of heap reserve + commit
+                mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x100_000);
+                index += 4;
+                mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x1_000);
+                index += 4;
+            },
+            .p64 => {
+                // Size of stack reserve + commit
+                mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x1_000_000);
+                index += 8;
+                mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x1_000);
+                index += 8;
+                // Size of heap reserve + commit
+                mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x100_000);
+                index += 8;
+                mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x1_000);
+                index += 8;
+            },
+        }
+
+        // Reserved zeroes
+        mem.set(u8, hdr_data[index..][0..4], 0);
+        index += 4;
+
+        // Number of data directories
+        mem.writeIntLittle(u32, hdr_data[index..][0..4], data_directory_count);
+        index += 4;
+        // Initialize data directories to zero
+        mem.set(u8, hdr_data[index..][0 .. data_directory_count * 8], 0);
+        index += data_directory_count * 8;
+
+        assert(index == optional_header_size);
+    }
+
+    // Write section table.
+    // First, the .got section
+    hdr_data[index..][0..8].* = ".got\x00\x00\x00\x00".*;
+    index += 8;
+    if (output_mode == .Exe) {
+        // Virtual size (u32)
+        mem.writeIntLittle(u32, hdr_data[index..][0..4], default_offset_table_size);
+        index += 4;
+        // Virtual address (u32)
+        mem.writeIntLittle(u32, hdr_data[index..][0..4], self.offset_table_virtual_address - default_image_base);
+        index += 4;
+    } else {
+        mem.set(u8, hdr_data[index..][0..8], 0);
+        index += 8;
+    }
+    // Size of raw data (u32)
+    mem.writeIntLittle(u32, hdr_data[index..][0..4], default_offset_table_size);
+    index += 4;
+    // File pointer to the start of the section
+    mem.writeIntLittle(u32, hdr_data[index..][0..4], self.section_data_offset);
+    index += 4;
+    // Pointer to relocations (u32), PointerToLinenumbers (u32), NumberOfRelocations (u16), NumberOfLinenumbers (u16)
+    mem.set(u8, hdr_data[index..][0..12], 0);
+    index += 12;
+    // Section flags
+    mem.writeIntLittle(u32, hdr_data[index..][0..4], std.coff.IMAGE_SCN_CNT_INITIALIZED_DATA | std.coff.IMAGE_SCN_MEM_READ);
+    index += 4;
+    // Then, the .text section
+    hdr_data[index..][0..8].* = ".text\x00\x00\x00".*;
+    index += 8;
+    if (output_mode == .Exe) {
+        // Virtual size (u32)
+        mem.writeIntLittle(u32, hdr_data[index..][0..4], default_size_of_code);
+        index += 4;
+        // Virtual address (u32)
+        mem.writeIntLittle(u32, hdr_data[index..][0..4], self.text_section_virtual_address - default_image_base);
+        index += 4;
+    } else {
+        mem.set(u8, hdr_data[index..][0..8], 0);
+        index += 8;
+    }
+    // Size of raw data (u32)
+    mem.writeIntLittle(u32, hdr_data[index..][0..4], default_size_of_code);
+    index += 4;
+    // File pointer to the start of the section
+    mem.writeIntLittle(u32, hdr_data[index..][0..4], self.section_data_offset + default_offset_table_size);
+    index += 4;
+    // Pointer to relocations (u32), PointerToLinenumbers (u32), NumberOfRelocations (u16), NumberOfLinenumbers (u16)
+    mem.set(u8, hdr_data[index..][0..12], 0);
+    index += 12;
+    // Section flags
+    mem.writeIntLittle(
+        u32,
+        hdr_data[index..][0..4],
+        std.coff.IMAGE_SCN_CNT_CODE | std.coff.IMAGE_SCN_MEM_EXECUTE | std.coff.IMAGE_SCN_MEM_READ | std.coff.IMAGE_SCN_MEM_WRITE,
+    );
+    index += 4;
+
+    assert(index == optional_header_size + section_table_size);
+    try self.base.file.?.pwriteAll(hdr_data[0..index], self.optional_header_offset);
+    try self.base.file.?.setEndPos(self.section_data_offset + default_offset_table_size + default_size_of_code);
+
     if (self.text_section_size_dirty) {
         // Write the new raw size in the .text header
         var buf: [4]u8 = undefined;