| ... | ... | @@ -144,39 +144,10 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option |
| 144 | 144 | }); |
| 145 | 145 | self.base.file = file; |
| 146 | 146 | |
| 147 | | // TODO Write object specific relocations, COFF symbol table, then enable object file output. |
| 148 | | switch (options.output_mode) { |
| 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 |
| 147 | const coff_file_header_offset: u32 = if (options.output_mode == .Exe) msdos_stub.len + 4 else 0; |
| 148 | const default_offset_table_size = file_alignment; |
| 162 | 149 | const data_directory_count = 0; |
| 163 | | var hdr_data: [112 + data_directory_count * 8 + section_table_size]u8 = undefined; |
| 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 | | |
| 150 | const default_size_of_code = 0; |
| 180 | 151 | const optional_header_size = switch (options.output_mode) { |
| 181 | 152 | .Exe => data_directory_count * 8 + switch (self.ptr_width) { |
| 182 | 153 | .p32 => @as(u16, 96), |
| ... | ... | @@ -184,218 +155,15 @@ pub fn openPath(allocator: Allocator, sub_path: []const u8, options: link.Option |
| 184 | 155 | }, |
| 185 | 156 | else => 0, |
| 186 | 157 | }; |
| 187 | | |
| 188 | 158 | const section_table_offset = coff_file_header_offset + 20 + optional_header_size; |
| 189 | | const default_offset_table_size = file_alignment; |
| 190 | | const default_size_of_code = 0; |
| 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); |
| 159 | self.section_data_offset = mem.alignForwardGeneric(u32, section_table_offset + section_table_size, file_alignment); |
| 160 | const section_data_relative_virtual_address = mem.alignForwardGeneric(u32, section_table_offset + section_table_size, section_alignment); |
| 194 | 161 | self.offset_table_virtual_address = default_image_base + section_data_relative_virtual_address; |
| 195 | 162 | self.offset_table_size = default_offset_table_size; |
| 196 | 163 | self.section_table_offset = section_table_offset; |
| 197 | 164 | self.text_section_virtual_address = default_image_base + section_data_relative_virtual_address + section_alignment; |
| 198 | 165 | self.text_section_size = default_size_of_code; |
| 199 | 166 | |
| 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 | 167 | return self; |
| 400 | 168 | } |
| 401 | 169 | |
| ... | ... | @@ -728,6 +496,12 @@ pub fn updateDecl(self: *Coff, module: *Module, decl_index: Module.Decl.Index) ! |
| 728 | 496 | if (decl.val.tag() == .extern_fn) { |
| 729 | 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 | } |
| 731 | 505 | |
| 732 | 506 | // TODO COFF/PE debug information |
| 733 | 507 | // TODO Implement exports |
| ... | ... | @@ -735,9 +509,10 @@ pub fn updateDecl(self: *Coff, module: *Module, decl_index: Module.Decl.Index) ! |
| 735 | 509 | var code_buffer = std.ArrayList(u8).init(self.base.allocator); |
| 736 | 510 | defer code_buffer.deinit(); |
| 737 | 511 | |
| 512 | const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val; |
| 738 | 513 | const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{ |
| 739 | 514 | .ty = decl.ty, |
| 740 | | .val = decl.val, |
| 515 | .val = decl_val, |
| 741 | 516 | }, &code_buffer, .none, .{ |
| 742 | 517 | .parent_atom_index = 0, |
| 743 | 518 | }); |
| ... | ... | @@ -862,15 +637,14 @@ pub fn updateDeclExports( |
| 862 | 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 | 641 | self.entry_addr = decl.link.coff.getVAddr(self.*) - default_image_base; |
| 867 | 642 | } else { |
| 868 | 643 | try module.failed_exports.ensureUnusedCapacity(module.gpa, 1); |
| 869 | 644 | module.failed_exports.putAssumeCapacityNoClobber( |
| 870 | 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 | 658 | } |
| 885 | 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 | 663 | return self.linkWithLLD(comp, prog_node); |
| 889 | | } else { |
| 890 | | switch (self.base.options.effectiveOutputMode()) { |
| 891 | | .Exe, .Obj => {}, |
| 892 | | .Lib => return error.TODOImplementWritingLibFiles, |
| 893 | | } |
| 894 | | return self.flushModule(comp, prog_node); |
| 664 | } |
| 665 | switch (self.base.options.output_mode) { |
| 666 | .Exe, .Obj => return self.flushModule(comp, prog_node), |
| 667 | .Lib => return error.TODOImplementWritingLibFiles, |
| 895 | 668 | } |
| 896 | 669 | } |
| 897 | 670 | |
| ... | ... | @@ -909,6 +682,238 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod |
| 909 | 682 | sub_prog_node.activate(); |
| 910 | 683 | defer sub_prog_node.end(); |
| 911 | 684 | |
| 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 | 917 | if (self.text_section_size_dirty) { |
| 913 | 918 | // Write the new raw size in the .text header |
| 914 | 919 | var buf: [4]u8 = undefined; |