authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-08-21 09:56:55+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-08-30 10:42:21+02:00
log3c10221030c47a68c17b4e037abd8afcdfd08486
tree7da93d06b93b39b1ed0088ed989807e760d7f4bf
parent06371950cf0a75f7b2e602381f5250fa2419d25a

coff: move header writing logic into flush


1 files changed, 253 insertions(+), 248 deletions(-)

src/link/Coff.zig+253-248
...@@ -144,39 +144,10 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option...@@ -144,39 +144,10 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option
144 });144 });
145 self.base.file = file;145 self.base.file = file;
146146
147 // TODO Write object specific relocations, COFF symbol table, then enable object file output.147 const coff_file_header_offset: u32 = if (options.output_mode == .Exe) msdos_stub.len + 4 else 0;
148 switch (options.output_mode) {148 const default_offset_table_size = file_alignment;
149 .Exe => {},
150 .Obj => return error.TODOImplementWritingObjFiles,
151 .Lib => return error.TODOImplementWritingLibFiles,
152 }
153
154 var coff_file_header_offset: u32 = 0;
155 if (options.output_mode == .Exe) {
156 // Write the MS-DOS stub and the PE signature
157 try self.base.file.?.pwriteAll(msdos_stub ++ "PE\x00\x00", 0);
158 coff_file_header_offset = msdos_stub.len + 4;
159 }
160
161 // COFF file header
162 const data_directory_count = 0;149 const data_directory_count = 0;
163 var hdr_data: [112 + data_directory_count * 8 + section_table_size]u8 = undefined;150 const default_size_of_code = 0;
164 var index: usize = 0;
165
166 const machine = self.base.options.target.cpu.arch.toCoffMachine();
167 if (machine == .Unknown) {
168 return error.UnsupportedCOFFArchitecture;
169 }
170 mem.writeIntLittle(u16, hdr_data[0..2], @enumToInt(machine));
171 index += 2;
172
173 // Number of sections (we only use .got, .text)
174 mem.writeIntLittle(u16, hdr_data[index..][0..2], 2);
175 index += 2;
176 // TimeDateStamp (u32), PointerToSymbolTable (u32), NumberOfSymbols (u32)
177 mem.set(u8, hdr_data[index..][0..12], 0);
178 index += 12;
179
180 const optional_header_size = switch (options.output_mode) {151 const optional_header_size = switch (options.output_mode) {
181 .Exe => data_directory_count * 8 + switch (self.ptr_width) {152 .Exe => data_directory_count * 8 + switch (self.ptr_width) {
182 .p32 => @as(u16, 96),153 .p32 => @as(u16, 96),
...@@ -184,218 +155,15 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option...@@ -184,218 +155,15 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option
184 },155 },
185 else => 0,156 else => 0,
186 };157 };
187
188 const section_table_offset = coff_file_header_offset + 20 + optional_header_size;158 const section_table_offset = coff_file_header_offset + 20 + optional_header_size;
189 const default_offset_table_size = file_alignment;159 self.section_data_offset = mem.alignForwardGeneric(u32, section_table_offset + section_table_size, file_alignment);
190 const default_size_of_code = 0;160 const section_data_relative_virtual_address = mem.alignForwardGeneric(u32, section_table_offset + section_table_size, section_alignment);
191
192 self.section_data_offset = mem.alignForwardGeneric(u32, self.section_table_offset + section_table_size, file_alignment);
193 const section_data_relative_virtual_address = mem.alignForwardGeneric(u32, self.section_table_offset + section_table_size, section_alignment);
194 self.offset_table_virtual_address = default_image_base + section_data_relative_virtual_address;161 self.offset_table_virtual_address = default_image_base + section_data_relative_virtual_address;
195 self.offset_table_size = default_offset_table_size;162 self.offset_table_size = default_offset_table_size;
196 self.section_table_offset = section_table_offset;163 self.section_table_offset = section_table_offset;
197 self.text_section_virtual_address = default_image_base + section_data_relative_virtual_address + section_alignment;164 self.text_section_virtual_address = default_image_base + section_data_relative_virtual_address + section_alignment;
198 self.text_section_size = default_size_of_code;165 self.text_section_size = default_size_of_code;
199166
200 // Size of file when loaded in memory
201 const size_of_image = mem.alignForwardGeneric(u32, self.text_section_virtual_address - default_image_base + default_size_of_code, section_alignment);
202
203 mem.writeIntLittle(u16, hdr_data[index..][0..2], optional_header_size);
204 index += 2;
205
206 // Characteristics
207 var characteristics: std.coff.CoffHeaderFlags = .{
208 .DEBUG_STRIPPED = 1, // TODO remove debug info stripped flag when necessary
209 .RELOCS_STRIPPED = 1,
210 };
211 if (options.output_mode == .Exe) {
212 characteristics.EXECUTABLE_IMAGE = 1;
213 }
214 switch (self.ptr_width) {
215 .p32 => characteristics.@"32BIT_MACHINE" = 1,
216 .p64 => characteristics.LARGE_ADDRESS_AWARE = 1,
217 }
218 mem.writeIntLittle(u16, hdr_data[index..][0..2], @bitCast(u16, characteristics));
219 index += 2;
220
221 assert(index == 20);
222 try self.base.file.?.pwriteAll(hdr_data[0..index], coff_file_header_offset);
223
224 if (options.output_mode == .Exe) {
225 self.optional_header_offset = coff_file_header_offset + 20;
226 // Optional header
227 index = 0;
228 mem.writeIntLittle(u16, hdr_data[0..2], switch (self.ptr_width) {
229 .p32 => @as(u16, 0x10b),
230 .p64 => 0x20b,
231 });
232 index += 2;
233
234 // Linker version (u8 + u8)
235 mem.set(u8, hdr_data[index..][0..2], 0);
236 index += 2;
237
238 // SizeOfCode (UNUSED, u32), SizeOfInitializedData (u32), SizeOfUninitializedData (u32), AddressOfEntryPoint (u32), BaseOfCode (UNUSED, u32)
239 mem.set(u8, hdr_data[index..][0..20], 0);
240 index += 20;
241
242 if (self.ptr_width == .p32) {
243 // Base of data relative to the image base (UNUSED)
244 mem.set(u8, hdr_data[index..][0..4], 0);
245 index += 4;
246
247 // Image base address
248 mem.writeIntLittle(u32, hdr_data[index..][0..4], default_image_base);
249 index += 4;
250 } else {
251 // Image base address
252 mem.writeIntLittle(u64, hdr_data[index..][0..8], default_image_base);
253 index += 8;
254 }
255
256 // Section alignment
257 mem.writeIntLittle(u32, hdr_data[index..][0..4], section_alignment);
258 index += 4;
259 // File alignment
260 mem.writeIntLittle(u32, hdr_data[index..][0..4], file_alignment);
261 index += 4;
262 // Required OS version, 6.0 is vista
263 mem.writeIntLittle(u16, hdr_data[index..][0..2], 6);
264 index += 2;
265 mem.writeIntLittle(u16, hdr_data[index..][0..2], 0);
266 index += 2;
267 // Image version
268 mem.set(u8, hdr_data[index..][0..4], 0);
269 index += 4;
270 // Required subsystem version, same as OS version
271 mem.writeIntLittle(u16, hdr_data[index..][0..2], 6);
272 index += 2;
273 mem.writeIntLittle(u16, hdr_data[index..][0..2], 0);
274 index += 2;
275 // Reserved zeroes (u32)
276 mem.set(u8, hdr_data[index..][0..4], 0);
277 index += 4;
278 mem.writeIntLittle(u32, hdr_data[index..][0..4], size_of_image);
279 index += 4;
280 mem.writeIntLittle(u32, hdr_data[index..][0..4], self.section_data_offset);
281 index += 4;
282 // CheckSum (u32)
283 mem.set(u8, hdr_data[index..][0..4], 0);
284 index += 4;
285 // Subsystem, TODO: Let users specify the subsystem, always CUI for now
286 mem.writeIntLittle(u16, hdr_data[index..][0..2], 3);
287 index += 2;
288 // DLL characteristics
289 mem.writeIntLittle(u16, hdr_data[index..][0..2], 0x0);
290 index += 2;
291
292 switch (self.ptr_width) {
293 .p32 => {
294 // Size of stack reserve + commit
295 mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x1_000_000);
296 index += 4;
297 mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x1_000);
298 index += 4;
299 // Size of heap reserve + commit
300 mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x100_000);
301 index += 4;
302 mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x1_000);
303 index += 4;
304 },
305 .p64 => {
306 // Size of stack reserve + commit
307 mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x1_000_000);
308 index += 8;
309 mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x1_000);
310 index += 8;
311 // Size of heap reserve + commit
312 mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x100_000);
313 index += 8;
314 mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x1_000);
315 index += 8;
316 },
317 }
318
319 // Reserved zeroes
320 mem.set(u8, hdr_data[index..][0..4], 0);
321 index += 4;
322
323 // Number of data directories
324 mem.writeIntLittle(u32, hdr_data[index..][0..4], data_directory_count);
325 index += 4;
326 // Initialize data directories to zero
327 mem.set(u8, hdr_data[index..][0 .. data_directory_count * 8], 0);
328 index += data_directory_count * 8;
329
330 assert(index == optional_header_size);
331 }
332
333 // Write section table.
334 // First, the .got section
335 hdr_data[index..][0..8].* = ".got\x00\x00\x00\x00".*;
336 index += 8;
337 if (options.output_mode == .Exe) {
338 // Virtual size (u32)
339 mem.writeIntLittle(u32, hdr_data[index..][0..4], default_offset_table_size);
340 index += 4;
341 // Virtual address (u32)
342 mem.writeIntLittle(u32, hdr_data[index..][0..4], self.offset_table_virtual_address - default_image_base);
343 index += 4;
344 } else {
345 mem.set(u8, hdr_data[index..][0..8], 0);
346 index += 8;
347 }
348 // Size of raw data (u32)
349 mem.writeIntLittle(u32, hdr_data[index..][0..4], default_offset_table_size);
350 index += 4;
351 // File pointer to the start of the section
352 mem.writeIntLittle(u32, hdr_data[index..][0..4], self.section_data_offset);
353 index += 4;
354 // Pointer to relocations (u32), PointerToLinenumbers (u32), NumberOfRelocations (u16), NumberOfLinenumbers (u16)
355 mem.set(u8, hdr_data[index..][0..12], 0);
356 index += 12;
357 // Section flags
358 mem.writeIntLittle(u32, hdr_data[index..][0..4], @bitCast(u32, std.coff.SectionHeaderFlags{
359 .CNT_INITIALIZED_DATA = 1,
360 .MEM_READ = 1,
361 }));
362 index += 4;
363 // Then, the .text section
364 hdr_data[index..][0..8].* = ".text\x00\x00\x00".*;
365 index += 8;
366 if (options.output_mode == .Exe) {
367 // Virtual size (u32)
368 mem.writeIntLittle(u32, hdr_data[index..][0..4], default_size_of_code);
369 index += 4;
370 // Virtual address (u32)
371 mem.writeIntLittle(u32, hdr_data[index..][0..4], self.text_section_virtual_address - default_image_base);
372 index += 4;
373 } else {
374 mem.set(u8, hdr_data[index..][0..8], 0);
375 index += 8;
376 }
377 // Size of raw data (u32)
378 mem.writeIntLittle(u32, hdr_data[index..][0..4], default_size_of_code);
379 index += 4;
380 // File pointer to the start of the section
381 mem.writeIntLittle(u32, hdr_data[index..][0..4], self.section_data_offset + default_offset_table_size);
382 index += 4;
383 // Pointer to relocations (u32), PointerToLinenumbers (u32), NumberOfRelocations (u16), NumberOfLinenumbers (u16)
384 mem.set(u8, hdr_data[index..][0..12], 0);
385 index += 12;
386 // Section flags
387 mem.writeIntLittle(u32, hdr_data[index..][0..4], @bitCast(u32, std.coff.SectionHeaderFlags{
388 .CNT_CODE = 1,
389 .MEM_EXECUTE = 1,
390 .MEM_READ = 1,
391 .MEM_WRITE = 1,
392 }));
393 index += 4;
394
395 assert(index == optional_header_size + section_table_size);
396 try self.base.file.?.pwriteAll(hdr_data[0..index], self.optional_header_offset);
397 try self.base.file.?.setEndPos(self.section_data_offset + default_offset_table_size + default_size_of_code);
398
399 return self;167 return self;
400}168}
401169
...@@ -728,6 +496,12 @@ pub fn updateDecl(self: *Coff, module: *Module, decl_index: Module.Decl.Index) !...@@ -728,6 +496,12 @@ pub fn updateDecl(self: *Coff, module: *Module, decl_index: Module.Decl.Index) !
728 if (decl.val.tag() == .extern_fn) {496 if (decl.val.tag() == .extern_fn) {
729 return; // TODO Should we do more when front-end analyzed extern decl?497 return; // TODO Should we do more when front-end analyzed extern decl?
730 }498 }
499 if (decl.val.castTag(.variable)) |payload| {
500 const variable = payload.data;
501 if (variable.is_extern) {
502 return; // TODO Should we do more when front-end analyzed extern decl?
503 }
504 }
731505
732 // TODO COFF/PE debug information506 // TODO COFF/PE debug information
733 // TODO Implement exports507 // TODO Implement exports
...@@ -735,9 +509,10 @@ pub fn updateDecl(self: *Coff, module: *Module, decl_index: Module.Decl.Index) !...@@ -735,9 +509,10 @@ pub fn updateDecl(self: *Coff, module: *Module, decl_index: Module.Decl.Index) !
735 var code_buffer = std.ArrayList(u8).init(self.base.allocator);509 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
736 defer code_buffer.deinit();510 defer code_buffer.deinit();
737511
512 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
738 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{513 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
739 .ty = decl.ty,514 .ty = decl.ty,
740 .val = decl.val,515 .val = decl_val,
741 }, &code_buffer, .none, .{516 }, &code_buffer, .none, .{
742 .parent_atom_index = 0,517 .parent_atom_index = 0,
743 });518 });
...@@ -862,15 +637,14 @@ pub fn updateDeclExports(...@@ -862,15 +637,14 @@ pub fn updateDeclExports(
862 continue;637 continue;
863 }638 }
864 }639 }
865 if (mem.eql(u8, exp.options.name, "_start")) {640 if (mem.eql(u8, exp.options.name, "wWinMainCRTStartup")) {
866 self.entry_addr = decl.link.coff.getVAddr(self.*) - default_image_base;641 self.entry_addr = decl.link.coff.getVAddr(self.*) - default_image_base;
867 } else {642 } else {
868 try module.failed_exports.ensureUnusedCapacity(module.gpa, 1);643 try module.failed_exports.ensureUnusedCapacity(module.gpa, 1);
869 module.failed_exports.putAssumeCapacityNoClobber(644 module.failed_exports.putAssumeCapacityNoClobber(
870 exp,645 exp,
871 try Module.ErrorMsg.create(self.base.allocator, decl.srcLoc(), "Unimplemented: Exports other than '_start'", .{}),646 try Module.ErrorMsg.create(self.base.allocator, decl.srcLoc(), "Unimplemented: Exports other than 'wWinMainCRTStartup'", .{}),
872 );647 );
873 continue;
874 }648 }
875 }649 }
876}650}
...@@ -884,14 +658,13 @@ pub fn flush(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) !vo...@@ -884,14 +658,13 @@ pub fn flush(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Node) !vo
884 }658 }
885 return;659 return;
886 }660 }
887 if (build_options.have_llvm and self.base.options.use_lld) {661 const use_lld = build_options.have_llvm and self.base.options.use_lld;
662 if (use_lld) {
888 return self.linkWithLLD(comp, prog_node);663 return self.linkWithLLD(comp, prog_node);
889 } else {664 }
890 switch (self.base.options.effectiveOutputMode()) {665 switch (self.base.options.output_mode) {
891 .Exe, .Obj => {},666 .Exe, .Obj => return self.flushModule(comp, prog_node),
892 .Lib => return error.TODOImplementWritingLibFiles,667 .Lib => return error.TODOImplementWritingLibFiles,
893 }
894 return self.flushModule(comp, prog_node);
895 }668 }
896}669}
897670
...@@ -909,6 +682,238 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod...@@ -909,6 +682,238 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
909 sub_prog_node.activate();682 sub_prog_node.activate();
910 defer sub_prog_node.end();683 defer sub_prog_node.end();
911684
685 const output_mode = self.base.options.output_mode;
686 log.debug("in flushModule with {}", .{output_mode});
687
688 var coff_file_header_offset: u32 = 0;
689 if (output_mode == .Exe) {
690 // Write the MS-DOS stub and the PE signature
691 try self.base.file.?.pwriteAll(msdos_stub ++ "PE\x00\x00", 0);
692 coff_file_header_offset = msdos_stub.len + 4;
693 }
694
695 // COFF file header
696 const data_directory_count = 0;
697 var hdr_data: [112 + data_directory_count * 8 + section_table_size]u8 = undefined;
698 var index: usize = 0;
699
700 const machine = self.base.options.target.cpu.arch.toCoffMachine();
701 if (machine == .Unknown) {
702 return error.UnsupportedCOFFArchitecture;
703 }
704 mem.writeIntLittle(u16, hdr_data[0..2], @enumToInt(machine));
705 index += 2;
706
707 // Number of sections (we only use .got, .text)
708 mem.writeIntLittle(u16, hdr_data[index..][0..2], 2);
709 index += 2;
710 // TimeDateStamp (u32), PointerToSymbolTable (u32), NumberOfSymbols (u32)
711 mem.set(u8, hdr_data[index..][0..12], 0);
712 index += 12;
713
714 const optional_header_size = switch (output_mode) {
715 .Exe => data_directory_count * 8 + switch (self.ptr_width) {
716 .p32 => @as(u16, 96),
717 .p64 => 112,
718 },
719 else => 0,
720 };
721
722 const default_offset_table_size = file_alignment;
723 const default_size_of_code = 0;
724
725 // Size of file when loaded in memory
726 const size_of_image = mem.alignForwardGeneric(u32, self.text_section_virtual_address - default_image_base + default_size_of_code, section_alignment);
727
728 mem.writeIntLittle(u16, hdr_data[index..][0..2], optional_header_size);
729 index += 2;
730
731 // Characteristics
732 var characteristics: u16 = std.coff.IMAGE_FILE_DEBUG_STRIPPED | std.coff.IMAGE_FILE_RELOCS_STRIPPED; // TODO Remove debug info stripped flag when necessary
733 if (output_mode == .Exe) {
734 characteristics |= std.coff.IMAGE_FILE_EXECUTABLE_IMAGE;
735 }
736 switch (self.ptr_width) {
737 .p32 => characteristics |= std.coff.IMAGE_FILE_32BIT_MACHINE,
738 .p64 => characteristics |= std.coff.IMAGE_FILE_LARGE_ADDRESS_AWARE,
739 }
740 mem.writeIntLittle(u16, hdr_data[index..][0..2], characteristics);
741 index += 2;
742
743 assert(index == 20);
744 try self.base.file.?.pwriteAll(hdr_data[0..index], coff_file_header_offset);
745
746 if (output_mode == .Exe) {
747 self.optional_header_offset = coff_file_header_offset + 20;
748 // Optional header
749 index = 0;
750 mem.writeIntLittle(u16, hdr_data[0..2], switch (self.ptr_width) {
751 .p32 => @as(u16, 0x10b),
752 .p64 => 0x20b,
753 });
754 index += 2;
755
756 // Linker version (u8 + u8)
757 mem.set(u8, hdr_data[index..][0..2], 0);
758 index += 2;
759
760 // SizeOfCode (UNUSED, u32), SizeOfInitializedData (u32), SizeOfUninitializedData (u32), AddressOfEntryPoint (u32), BaseOfCode (UNUSED, u32)
761 mem.set(u8, hdr_data[index..][0..20], 0);
762 index += 20;
763
764 if (self.ptr_width == .p32) {
765 // Base of data relative to the image base (UNUSED)
766 mem.set(u8, hdr_data[index..][0..4], 0);
767 index += 4;
768
769 // Image base address
770 mem.writeIntLittle(u32, hdr_data[index..][0..4], default_image_base);
771 index += 4;
772 } else {
773 // Image base address
774 mem.writeIntLittle(u64, hdr_data[index..][0..8], default_image_base);
775 index += 8;
776 }
777
778 // Section alignment
779 mem.writeIntLittle(u32, hdr_data[index..][0..4], section_alignment);
780 index += 4;
781 // File alignment
782 mem.writeIntLittle(u32, hdr_data[index..][0..4], file_alignment);
783 index += 4;
784 // Required OS version, 6.0 is vista
785 mem.writeIntLittle(u16, hdr_data[index..][0..2], 6);
786 index += 2;
787 mem.writeIntLittle(u16, hdr_data[index..][0..2], 0);
788 index += 2;
789 // Image version
790 mem.set(u8, hdr_data[index..][0..4], 0);
791 index += 4;
792 // Required subsystem version, same as OS version
793 mem.writeIntLittle(u16, hdr_data[index..][0..2], 6);
794 index += 2;
795 mem.writeIntLittle(u16, hdr_data[index..][0..2], 0);
796 index += 2;
797 // Reserved zeroes (u32)
798 mem.set(u8, hdr_data[index..][0..4], 0);
799 index += 4;
800 mem.writeIntLittle(u32, hdr_data[index..][0..4], size_of_image);
801 index += 4;
802 mem.writeIntLittle(u32, hdr_data[index..][0..4], self.section_data_offset);
803 index += 4;
804 // CheckSum (u32)
805 mem.set(u8, hdr_data[index..][0..4], 0);
806 index += 4;
807 // Subsystem, TODO: Let users specify the subsystem, always CUI for now
808 mem.writeIntLittle(u16, hdr_data[index..][0..2], 3);
809 index += 2;
810 // DLL characteristics
811 mem.writeIntLittle(u16, hdr_data[index..][0..2], 0x0);
812 index += 2;
813
814 switch (self.ptr_width) {
815 .p32 => {
816 // Size of stack reserve + commit
817 mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x1_000_000);
818 index += 4;
819 mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x1_000);
820 index += 4;
821 // Size of heap reserve + commit
822 mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x100_000);
823 index += 4;
824 mem.writeIntLittle(u32, hdr_data[index..][0..4], 0x1_000);
825 index += 4;
826 },
827 .p64 => {
828 // Size of stack reserve + commit
829 mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x1_000_000);
830 index += 8;
831 mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x1_000);
832 index += 8;
833 // Size of heap reserve + commit
834 mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x100_000);
835 index += 8;
836 mem.writeIntLittle(u64, hdr_data[index..][0..8], 0x1_000);
837 index += 8;
838 },
839 }
840
841 // Reserved zeroes
842 mem.set(u8, hdr_data[index..][0..4], 0);
843 index += 4;
844
845 // Number of data directories
846 mem.writeIntLittle(u32, hdr_data[index..][0..4], data_directory_count);
847 index += 4;
848 // Initialize data directories to zero
849 mem.set(u8, hdr_data[index..][0 .. data_directory_count * 8], 0);
850 index += data_directory_count * 8;
851
852 assert(index == optional_header_size);
853 }
854
855 // Write section table.
856 // First, the .got section
857 hdr_data[index..][0..8].* = ".got\x00\x00\x00\x00".*;
858 index += 8;
859 if (output_mode == .Exe) {
860 // Virtual size (u32)
861 mem.writeIntLittle(u32, hdr_data[index..][0..4], default_offset_table_size);
862 index += 4;
863 // Virtual address (u32)
864 mem.writeIntLittle(u32, hdr_data[index..][0..4], self.offset_table_virtual_address - default_image_base);
865 index += 4;
866 } else {
867 mem.set(u8, hdr_data[index..][0..8], 0);
868 index += 8;
869 }
870 // Size of raw data (u32)
871 mem.writeIntLittle(u32, hdr_data[index..][0..4], default_offset_table_size);
872 index += 4;
873 // File pointer to the start of the section
874 mem.writeIntLittle(u32, hdr_data[index..][0..4], self.section_data_offset);
875 index += 4;
876 // Pointer to relocations (u32), PointerToLinenumbers (u32), NumberOfRelocations (u16), NumberOfLinenumbers (u16)
877 mem.set(u8, hdr_data[index..][0..12], 0);
878 index += 12;
879 // Section flags
880 mem.writeIntLittle(u32, hdr_data[index..][0..4], std.coff.IMAGE_SCN_CNT_INITIALIZED_DATA | std.coff.IMAGE_SCN_MEM_READ);
881 index += 4;
882 // Then, the .text section
883 hdr_data[index..][0..8].* = ".text\x00\x00\x00".*;
884 index += 8;
885 if (output_mode == .Exe) {
886 // Virtual size (u32)
887 mem.writeIntLittle(u32, hdr_data[index..][0..4], default_size_of_code);
888 index += 4;
889 // Virtual address (u32)
890 mem.writeIntLittle(u32, hdr_data[index..][0..4], self.text_section_virtual_address - default_image_base);
891 index += 4;
892 } else {
893 mem.set(u8, hdr_data[index..][0..8], 0);
894 index += 8;
895 }
896 // Size of raw data (u32)
897 mem.writeIntLittle(u32, hdr_data[index..][0..4], default_size_of_code);
898 index += 4;
899 // File pointer to the start of the section
900 mem.writeIntLittle(u32, hdr_data[index..][0..4], self.section_data_offset + default_offset_table_size);
901 index += 4;
902 // Pointer to relocations (u32), PointerToLinenumbers (u32), NumberOfRelocations (u16), NumberOfLinenumbers (u16)
903 mem.set(u8, hdr_data[index..][0..12], 0);
904 index += 12;
905 // Section flags
906 mem.writeIntLittle(
907 u32,
908 hdr_data[index..][0..4],
909 std.coff.IMAGE_SCN_CNT_CODE | std.coff.IMAGE_SCN_MEM_EXECUTE | std.coff.IMAGE_SCN_MEM_READ | std.coff.IMAGE_SCN_MEM_WRITE,
910 );
911 index += 4;
912
913 assert(index == optional_header_size + section_table_size);
914 try self.base.file.?.pwriteAll(hdr_data[0..index], self.optional_header_offset);
915 try self.base.file.?.setEndPos(self.section_data_offset + default_offset_table_size + default_size_of_code);
916
912 if (self.text_section_size_dirty) {917 if (self.text_section_size_dirty) {
913 // Write the new raw size in the .text header918 // Write the new raw size in the .text header
914 var buf: [4]u8 = undefined;919 var buf: [4]u8 = undefined;