| ... | @@ -38,6 +38,7 @@ error_flags: link.File.ErrorFlags = .{}, | ... | @@ -38,6 +38,7 @@ error_flags: link.File.ErrorFlags = .{}, |
| 38 | ptr_width: PtrWidth, | 38 | ptr_width: PtrWidth, |
| 39 | | 39 | |
| 40 | sections: std.MultiArrayList(Section) = .{}, | 40 | sections: std.MultiArrayList(Section) = .{}, |
| | 41 | data_directories: std.ArrayListUnmanaged(coff.ImageDataDirectory) = .{}, |
| 41 | | 42 | |
| 42 | text_section_index: ?u16 = null, | 43 | text_section_index: ?u16 = null, |
| 43 | got_section_index: ?u16 = null, | 44 | got_section_index: ?u16 = null, |
| ... | @@ -49,8 +50,6 @@ locals_free_list: std.ArrayListUnmanaged(u32) = .{}, | ... | @@ -49,8 +50,6 @@ locals_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| 49 | | 50 | |
| 50 | strtab: StringTable(.strtab) = .{}, | 51 | strtab: StringTable(.strtab) = .{}, |
| 51 | | 52 | |
| 52 | symtab_offset: ?u32 = null, | | |
| 53 | | | |
| 54 | got_entries: std.AutoArrayHashMapUnmanaged(SymbolWithLoc, u32) = .{}, | 53 | got_entries: std.AutoArrayHashMapUnmanaged(SymbolWithLoc, u32) = .{}, |
| 55 | got_entries_free_list: std.ArrayListUnmanaged(u32) = .{}, | 54 | got_entries_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| 56 | | 55 | |
| ... | @@ -73,6 +72,7 @@ const default_section_alignment: u16 = 0x1000; | ... | @@ -73,6 +72,7 @@ const default_section_alignment: u16 = 0x1000; |
| 73 | const default_file_alignment: u16 = 0x200; | 72 | const default_file_alignment: u16 = 0x200; |
| 74 | const default_image_base_dll: u64 = 0x10000000; | 73 | const default_image_base_dll: u64 = 0x10000000; |
| 75 | const default_image_base_exe: u64 = 0x10000; | 74 | const default_image_base_exe: u64 = 0x10000; |
| | 75 | const default_header_size: u64 = default_section_alignment; |
| 76 | | 76 | |
| 77 | const Section = struct { | 77 | const Section = struct { |
| 78 | header: coff.SectionHeader, | 78 | header: coff.SectionHeader, |
| ... | @@ -192,6 +192,7 @@ pub fn deinit(self: *Coff) void { | ... | @@ -192,6 +192,7 @@ pub fn deinit(self: *Coff) void { |
| 192 | free_list.deinit(gpa); | 192 | free_list.deinit(gpa); |
| 193 | } | 193 | } |
| 194 | self.sections.deinit(gpa); | 194 | self.sections.deinit(gpa); |
| | 195 | self.data_directories.deinit(gpa); |
| 195 | | 196 | |
| 196 | for (self.managed_atoms.items) |atom| { | 197 | for (self.managed_atoms.items) |atom| { |
| 197 | gpa.destroy(atom); | 198 | gpa.destroy(atom); |
| ... | @@ -209,11 +210,8 @@ pub fn deinit(self: *Coff) void { | ... | @@ -209,11 +210,8 @@ pub fn deinit(self: *Coff) void { |
| 209 | } | 210 | } |
| 210 | | 211 | |
| 211 | fn populateMissingMetadata(self: *Coff) !void { | 212 | fn populateMissingMetadata(self: *Coff) !void { |
| 212 | log.debug("{x}", .{msdos_stub.len}); | | |
| 213 | | | |
| 214 | if (self.text_section_index == null) {} | 213 | if (self.text_section_index == null) {} |
| 215 | if (self.got_section_index == null) {} | 214 | if (self.got_section_index == null) {} |
| 216 | if (self.symtab_offset == null) {} | | |
| 217 | } | 215 | } |
| 218 | | 216 | |
| 219 | pub fn allocateDeclIndexes(self: *Coff, decl_index: Module.Decl.Index) !void { | 217 | pub fn allocateDeclIndexes(self: *Coff, decl_index: Module.Decl.Index) !void { |
| ... | @@ -662,6 +660,8 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod | ... | @@ -662,6 +660,8 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod |
| 662 | sub_prog_node.activate(); | 660 | sub_prog_node.activate(); |
| 663 | defer sub_prog_node.end(); | 661 | defer sub_prog_node.end(); |
| 664 | | 662 | |
| | 663 | try self.writeDataDirectoriesHeaders(); |
| | 664 | try self.writeSectionHeaders(); |
| 665 | try self.writeHeader(); | 665 | try self.writeHeader(); |
| 666 | | 666 | |
| 667 | if (self.entry_addr == null and self.base.options.output_mode == .Exe) { | 667 | if (self.entry_addr == null and self.base.options.output_mode == .Exe) { |
| ... | @@ -692,24 +692,28 @@ pub fn updateDeclLineNumber(self: *Coff, module: *Module, decl: *Module.Decl) !v | ... | @@ -692,24 +692,28 @@ pub fn updateDeclLineNumber(self: *Coff, module: *Module, decl: *Module.Decl) !v |
| 692 | log.debug("TODO implement updateDeclLineNumber", .{}); | 692 | log.debug("TODO implement updateDeclLineNumber", .{}); |
| 693 | } | 693 | } |
| 694 | | 694 | |
| | 695 | fn writeSectionHeaders(self: *Coff) !void { |
| | 696 | const offset = self.getSectionHeadersOffset(); |
| | 697 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.sections.items(.header)), offset); |
| | 698 | } |
| | 699 | |
| | 700 | fn writeDataDirectoriesHeaders(self: *Coff) !void { |
| | 701 | const offset = self.getDataDirectoryHeadersOffset(); |
| | 702 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.data_directories.items), offset); |
| | 703 | } |
| | 704 | |
| 695 | fn writeHeader(self: *Coff) !void { | 705 | fn writeHeader(self: *Coff) !void { |
| 696 | const gpa = self.base.allocator; | 706 | const gpa = self.base.allocator; |
| 697 | var buffer = std.ArrayList(u8).init(gpa); | 707 | var buffer = std.ArrayList(u8).init(gpa); |
| 698 | defer buffer.deinit(); | 708 | defer buffer.deinit(); |
| 699 | const writer = buffer.writer(); | 709 | const writer = buffer.writer(); |
| 700 | | 710 | |
| 701 | try buffer.ensureUnusedCapacity(msdos_stub.len + 8); | 711 | try buffer.ensureTotalCapacity(self.getSizeOfHeaders()); |
| 702 | writer.writeAll(msdos_stub) catch unreachable; | 712 | writer.writeAll(msdos_stub) catch unreachable; |
| 703 | writer.writeByteNTimes(0, 4) catch unreachable; // align to 8 bytes | 713 | writer.writeByteNTimes(0, 4) catch unreachable; // align to 8 bytes |
| 704 | writer.writeAll("PE\x00\x00") catch unreachable; | 714 | writer.writeAll("PE\x00\x00") catch unreachable; |
| 705 | buffer.items[0x3c] = @intCast(u8, msdos_stub.len + 4); | 715 | buffer.items[0x3c] = @intCast(u8, msdos_stub.len + 4); |
| 706 | | 716 | |
| 707 | var num_data_directories: u32 = 0; | | |
| 708 | var size_of_optional_header = switch (self.ptr_width) { | | |
| 709 | .p32 => @intCast(u32, @sizeOf(coff.OptionalHeaderPE32)), | | |
| 710 | .p64 => @intCast(u32, @sizeOf(coff.OptionalHeaderPE64)), | | |
| 711 | } + num_data_directories * @sizeOf(coff.ImageDataDirectory); | | |
| 712 | | | |
| 713 | var flags = coff.CoffHeaderFlags{ | 717 | var flags = coff.CoffHeaderFlags{ |
| 714 | .EXECUTABLE_IMAGE = 1, | 718 | .EXECUTABLE_IMAGE = 1, |
| 715 | .DEBUG_STRIPPED = 1, // TODO | 719 | .DEBUG_STRIPPED = 1, // TODO |
| ... | @@ -722,17 +726,20 @@ fn writeHeader(self: *Coff) !void { | ... | @@ -722,17 +726,20 @@ fn writeHeader(self: *Coff) !void { |
| 722 | flags.DLL = 1; | 726 | flags.DLL = 1; |
| 723 | } | 727 | } |
| 724 | | 728 | |
| | 729 | const size_of_optional_header = @intCast( |
| | 730 | u16, |
| | 731 | self.getOptionalHeaderSize() + self.getDataDirectoryHeadersSize() + self.getSectionHeadersSize(), |
| | 732 | ); |
| 725 | var coff_header = coff.CoffHeader{ | 733 | var coff_header = coff.CoffHeader{ |
| 726 | .machine = coff.MachineType.fromTargetCpuArch(self.base.options.target.cpu.arch), | 734 | .machine = coff.MachineType.fromTargetCpuArch(self.base.options.target.cpu.arch), |
| 727 | .number_of_sections = @intCast(u16, self.sections.slice().len), // TODO what if we prune a section | 735 | .number_of_sections = @intCast(u16, self.sections.slice().len), // TODO what if we prune a section |
| 728 | .time_date_stamp = 0, // TODO | 736 | .time_date_stamp = 0, // TODO |
| 729 | .pointer_to_symbol_table = self.symtab_offset orelse 0, | 737 | .pointer_to_symbol_table = 0, |
| 730 | .number_of_symbols = if (self.symtab_offset) |_| self.getTotalNumberOfSymbols() else 0, | 738 | .number_of_symbols = 0, |
| 731 | .size_of_optional_header = @intCast(u16, size_of_optional_header), | 739 | .size_of_optional_header = size_of_optional_header, |
| 732 | .flags = flags, | 740 | .flags = flags, |
| 733 | }; | 741 | }; |
| 734 | | 742 | |
| 735 | try buffer.ensureUnusedCapacity(@sizeOf(coff.CoffHeader)); | | |
| 736 | writer.writeAll(mem.asBytes(&coff_header)) catch unreachable; | 743 | writer.writeAll(mem.asBytes(&coff_header)) catch unreachable; |
| 737 | | 744 | |
| 738 | const dll_flags: coff.DllFlags = .{ | 745 | const dll_flags: coff.DllFlags = .{ |
| ... | @@ -742,10 +749,7 @@ fn writeHeader(self: *Coff) !void { | ... | @@ -742,10 +749,7 @@ fn writeHeader(self: *Coff) !void { |
| 742 | .NX_COMPAT = 1, // We are compatible with Data Execution Prevention | 749 | .NX_COMPAT = 1, // We are compatible with Data Execution Prevention |
| 743 | }; | 750 | }; |
| 744 | const subsystem: coff.Subsystem = .WINDOWS_CUI; | 751 | const subsystem: coff.Subsystem = .WINDOWS_CUI; |
| 745 | const size_of_headers: u32 = @intCast( | 752 | const size_of_headers: u32 = @intCast(u32, self.getSizeOfHeaders()); |
| 746 | u32, | | |
| 747 | msdos_stub.len + 8 + size_of_optional_header + self.sections.slice().len * @sizeOf(coff.SectionHeader), | | |
| 748 | ); | | |
| 749 | const size_of_image_aligned: u32 = mem.alignForwardGeneric(u32, size_of_headers, default_section_alignment); | 753 | const size_of_image_aligned: u32 = mem.alignForwardGeneric(u32, size_of_headers, default_section_alignment); |
| 750 | const size_of_headers_aligned: u32 = mem.alignForwardGeneric(u32, size_of_headers, default_file_alignment); | 754 | const size_of_headers_aligned: u32 = mem.alignForwardGeneric(u32, size_of_headers, default_file_alignment); |
| 751 | const image_base = self.base.options.image_base_override orelse switch (self.base.options.output_mode) { | 755 | const image_base = self.base.options.image_base_override orelse switch (self.base.options.output_mode) { |
| ... | @@ -756,7 +760,6 @@ fn writeHeader(self: *Coff) !void { | ... | @@ -756,7 +760,6 @@ fn writeHeader(self: *Coff) !void { |
| 756 | | 760 | |
| 757 | switch (self.ptr_width) { | 761 | switch (self.ptr_width) { |
| 758 | .p32 => { | 762 | .p32 => { |
| 759 | try buffer.ensureUnusedCapacity(@sizeOf(coff.OptionalHeaderPE32)); | | |
| 760 | var opt_header = coff.OptionalHeaderPE32{ | 763 | var opt_header = coff.OptionalHeaderPE32{ |
| 761 | .magic = coff.IMAGE_NT_OPTIONAL_HDR32_MAGIC, | 764 | .magic = coff.IMAGE_NT_OPTIONAL_HDR32_MAGIC, |
| 762 | .major_linker_version = 0, | 765 | .major_linker_version = 0, |
| ... | @@ -787,12 +790,11 @@ fn writeHeader(self: *Coff) !void { | ... | @@ -787,12 +790,11 @@ fn writeHeader(self: *Coff) !void { |
| 787 | .size_of_heap_reserve = 0, | 790 | .size_of_heap_reserve = 0, |
| 788 | .size_of_heap_commit = 0, | 791 | .size_of_heap_commit = 0, |
| 789 | .loader_flags = 0, | 792 | .loader_flags = 0, |
| 790 | .number_of_rva_and_sizes = num_data_directories, | 793 | .number_of_rva_and_sizes = @intCast(u32, self.data_directories.items.len), |
| 791 | }; | 794 | }; |
| 792 | writer.writeAll(mem.asBytes(&opt_header)) catch unreachable; | 795 | writer.writeAll(mem.asBytes(&opt_header)) catch unreachable; |
| 793 | }, | 796 | }, |
| 794 | .p64 => { | 797 | .p64 => { |
| 795 | try buffer.ensureUnusedCapacity(@sizeOf(coff.OptionalHeaderPE64)); | | |
| 796 | var opt_header = coff.OptionalHeaderPE64{ | 798 | var opt_header = coff.OptionalHeaderPE64{ |
| 797 | .magic = coff.IMAGE_NT_OPTIONAL_HDR64_MAGIC, | 799 | .magic = coff.IMAGE_NT_OPTIONAL_HDR64_MAGIC, |
| 798 | .major_linker_version = 0, | 800 | .major_linker_version = 0, |
| ... | @@ -822,33 +824,16 @@ fn writeHeader(self: *Coff) !void { | ... | @@ -822,33 +824,16 @@ fn writeHeader(self: *Coff) !void { |
| 822 | .size_of_heap_reserve = 0, | 824 | .size_of_heap_reserve = 0, |
| 823 | .size_of_heap_commit = 0, | 825 | .size_of_heap_commit = 0, |
| 824 | .loader_flags = 0, | 826 | .loader_flags = 0, |
| 825 | .number_of_rva_and_sizes = num_data_directories, | 827 | .number_of_rva_and_sizes = @intCast(u32, self.data_directories.items.len), |
| 826 | }; | 828 | }; |
| 827 | writer.writeAll(mem.asBytes(&opt_header)) catch unreachable; | 829 | writer.writeAll(mem.asBytes(&opt_header)) catch unreachable; |
| 828 | }, | 830 | }, |
| 829 | } | 831 | } |
| 830 | | 832 | |
| 831 | try buffer.ensureUnusedCapacity(num_data_directories * @sizeOf(coff.ImageDataDirectory)); | | |
| 832 | { | | |
| 833 | var i: usize = 0; | | |
| 834 | while (i < num_data_directories) : (i += 1) { | | |
| 835 | writer.writeAll(mem.asBytes(&coff.ImageDataDirectory{ | | |
| 836 | .virtual_address = 0, | | |
| 837 | .size = 0, | | |
| 838 | })) catch unreachable; | | |
| 839 | } | | |
| 840 | } | | |
| 841 | | | |
| 842 | try self.base.file.?.pwriteAll(&[_]u8{0}, size_of_headers_aligned); | 833 | try self.base.file.?.pwriteAll(&[_]u8{0}, size_of_headers_aligned); |
| 843 | try self.base.file.?.pwriteAll(buffer.items, 0); | 834 | try self.base.file.?.pwriteAll(buffer.items, 0); |
| 844 | } | 835 | } |
| 845 | | 836 | |
| 846 | fn getTotalNumberOfSymbols(self: Coff) u32 { | | |
| 847 | _ = self; | | |
| 848 | // TODO | | |
| 849 | return 0; | | |
| 850 | } | | |
| 851 | | | |
| 852 | pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { | 837 | pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { |
| 853 | // TODO https://github.com/ziglang/zig/issues/1284 | 838 | // TODO https://github.com/ziglang/zig/issues/1284 |
| 854 | return math.add(@TypeOf(actual_size), actual_size, actual_size / ideal_factor) catch | 839 | return math.add(@TypeOf(actual_size), actual_size, actual_size / ideal_factor) catch |
| ... | @@ -856,14 +841,12 @@ pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { | ... | @@ -856,14 +841,12 @@ pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { |
| 856 | } | 841 | } |
| 857 | | 842 | |
| 858 | // fn detectAllocCollision(self: *Coff, start: u64, size: u64) ?u64 { | 843 | // fn detectAllocCollision(self: *Coff, start: u64, size: u64) ?u64 { |
| 859 | // const small_ptr = self.ptr_width == .p32; | | |
| 860 | // const ehdr_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Ehdr) else @sizeOf(elf.Elf64_Ehdr); | | |
| 861 | // if (start < default_header_size) | 844 | // if (start < default_header_size) |
| 862 | // return ehdr_size; | 845 | // return default_header_size; |
| 863 | | 846 | |
| 864 | // const end = start + padToIdeal(size); | 847 | // const end = start + padToIdeal(size); |
| 865 | | 848 | |
| 866 | // if (self.shdr_table_offset) |off| { | 849 | // if (self.symtab_offset) |off| { |
| 867 | // const shdr_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Shdr) else @sizeOf(elf.Elf64_Shdr); | 850 | // const shdr_size: u64 = if (small_ptr) @sizeOf(elf.Elf32_Shdr) else @sizeOf(elf.Elf64_Shdr); |
| 868 | // const tight_size = self.sections.items.len * shdr_size; | 851 | // const tight_size = self.sections.items.len * shdr_size; |
| 869 | // const increased_size = padToIdeal(tight_size); | 852 | // const increased_size = padToIdeal(tight_size); |
| ... | @@ -900,26 +883,26 @@ pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { | ... | @@ -900,26 +883,26 @@ pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { |
| 900 | // return null; | 883 | // return null; |
| 901 | // } | 884 | // } |
| 902 | | 885 | |
| 903 | // pub fn allocatedSize(self: *Coff, start: u64) u64 { | 886 | // // pub fn allocatedSize(self: *Coff, start: u64) u64 { |
| 904 | // if (start == 0) | 887 | // // if (start == 0) |
| 905 | // return 0; | 888 | // // return 0; |
| 906 | // var min_pos: u64 = std.math.maxInt(u64); | 889 | // // var min_pos: u64 = std.math.maxInt(u64); |
| 907 | // if (self.shdr_table_offset) |off| { | 890 | // // if (self.shdr_table_offset) |off| { |
| 908 | // if (off > start and off < min_pos) min_pos = off; | 891 | // // if (off > start and off < min_pos) min_pos = off; |
| 909 | // } | 892 | // // } |
| 910 | // if (self.phdr_table_offset) |off| { | 893 | // // if (self.phdr_table_offset) |off| { |
| 911 | // if (off > start and off < min_pos) min_pos = off; | 894 | // // if (off > start and off < min_pos) min_pos = off; |
| 912 | // } | 895 | // // } |
| 913 | // for (self.sections.items) |section| { | 896 | // // for (self.sections.items) |section| { |
| 914 | // if (section.sh_offset <= start) continue; | 897 | // // if (section.sh_offset <= start) continue; |
| 915 | // if (section.sh_offset < min_pos) min_pos = section.sh_offset; | 898 | // // if (section.sh_offset < min_pos) min_pos = section.sh_offset; |
| 916 | // } | 899 | // // } |
| 917 | // for (self.program_headers.items) |program_header| { | 900 | // // for (self.program_headers.items) |program_header| { |
| 918 | // if (program_header.p_offset <= start) continue; | 901 | // // if (program_header.p_offset <= start) continue; |
| 919 | // if (program_header.p_offset < min_pos) min_pos = program_header.p_offset; | 902 | // // if (program_header.p_offset < min_pos) min_pos = program_header.p_offset; |
| 920 | // } | 903 | // // } |
| 921 | // return min_pos - start; | 904 | // // return min_pos - start; |
| 922 | // } | 905 | // // } |
| 923 | | 906 | |
| 924 | // pub fn findFreeSpace(self: *Coff, object_size: u64, min_alignment: u32) u64 { | 907 | // pub fn findFreeSpace(self: *Coff, object_size: u64, min_alignment: u32) u64 { |
| 925 | // var start: u64 = 0; | 908 | // var start: u64 = 0; |
| ... | @@ -929,12 +912,34 @@ pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { | ... | @@ -929,12 +912,34 @@ pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { |
| 929 | // return start; | 912 | // return start; |
| 930 | // } | 913 | // } |
| 931 | | 914 | |
| 932 | fn getMaxOptionalHeaderSize(self: Coff) usize { | 915 | inline fn getSizeOfHeaders(self: Coff) usize { |
| 933 | const hdr_size: usize = switch (self.ptr_width) { | 916 | const msdos_hdr_size = msdos_stub.len + 8; |
| | 917 | return msdos_hdr_size + @sizeOf(coff.CoffHeader) + self.getOptionalHeaderSize() + |
| | 918 | self.getDataDirectoryHeadersSize() + self.getSectionHeadersSize(); |
| | 919 | } |
| | 920 | |
| | 921 | inline fn getOptionalHeaderSize(self: Coff) usize { |
| | 922 | return switch (self.ptr_width) { |
| 934 | .p32 => @sizeOf(coff.OptionalHeaderPE32), | 923 | .p32 => @sizeOf(coff.OptionalHeaderPE32), |
| 935 | .p64 => @sizeOf(coff.OptionalHeaderPE64), | 924 | .p64 => @sizeOf(coff.OptionalHeaderPE64), |
| 936 | }; | 925 | }; |
| 937 | return hdr_size + @sizeOf(coff.ImageDataDirectory) * 16; | 926 | } |
| | 927 | |
| | 928 | inline fn getDataDirectoryHeadersSize(self: Coff) usize { |
| | 929 | return self.data_directories.items.len * @sizeOf(coff.ImageDataDirectory); |
| | 930 | } |
| | 931 | |
| | 932 | inline fn getSectionHeadersSize(self: Coff) usize { |
| | 933 | return self.sections.slice().len * @sizeOf(coff.SectionHeader); |
| | 934 | } |
| | 935 | |
| | 936 | inline fn getDataDirectoryHeadersOffset(self: Coff) usize { |
| | 937 | const msdos_hdr_size = msdos_stub.len + 8; |
| | 938 | return msdos_hdr_size + @sizeOf(coff.CoffHeader) + self.getOptionalHeaderSize(); |
| | 939 | } |
| | 940 | |
| | 941 | inline fn getSectionHeadersOffset(self: Coff) usize { |
| | 942 | return self.getDataDirectoryHeadersOffset() + self.getDataDirectoryHeadersSize(); |
| 938 | } | 943 | } |
| 939 | | 944 | |
| 940 | /// Returns pointer-to-symbol described by `sym_with_loc` descriptor. | 945 | /// Returns pointer-to-symbol described by `sym_with_loc` descriptor. |