| ... | @@ -5,6 +5,7 @@ const build_options = @import("build_options"); | ... | @@ -5,6 +5,7 @@ const build_options = @import("build_options"); |
| 5 | const builtin = @import("builtin"); | 5 | const builtin = @import("builtin"); |
| 6 | const assert = std.debug.assert; | 6 | const assert = std.debug.assert; |
| 7 | const coff = std.coff; | 7 | const coff = std.coff; |
| | 8 | const fmt = std.fmt; |
| 8 | const log = std.log.scoped(.link); | 9 | const log = std.log.scoped(.link); |
| 9 | const math = std.math; | 10 | const math = std.math; |
| 10 | const mem = std.mem; | 11 | const mem = std.mem; |
| ... | @@ -36,6 +37,7 @@ base: link.File, | ... | @@ -36,6 +37,7 @@ base: link.File, |
| 36 | error_flags: link.File.ErrorFlags = .{}, | 37 | error_flags: link.File.ErrorFlags = .{}, |
| 37 | | 38 | |
| 38 | ptr_width: PtrWidth, | 39 | ptr_width: PtrWidth, |
| | 40 | page_size: u32, |
| 39 | | 41 | |
| 40 | sections: std.MultiArrayList(Section) = .{}, | 42 | sections: std.MultiArrayList(Section) = .{}, |
| 41 | data_directories: [16]coff.ImageDataDirectory, | 43 | data_directories: [16]coff.ImageDataDirectory, |
| ... | @@ -69,7 +71,6 @@ managed_atoms: std.ArrayListUnmanaged(*Atom) = .{}, | ... | @@ -69,7 +71,6 @@ managed_atoms: std.ArrayListUnmanaged(*Atom) = .{}, |
| 69 | /// Table of atoms indexed by the symbol index. | 71 | /// Table of atoms indexed by the symbol index. |
| 70 | atom_by_index_table: std.AutoHashMapUnmanaged(u32, *Atom) = .{}, | 72 | atom_by_index_table: std.AutoHashMapUnmanaged(u32, *Atom) = .{}, |
| 71 | | 73 | |
| 72 | const default_section_alignment: u16 = 0x1000; | | |
| 73 | const default_file_alignment: u16 = 0x200; | 74 | const default_file_alignment: u16 = 0x200; |
| 74 | const default_image_base_dll: u64 = 0x10000000; | 75 | const default_image_base_dll: u64 = 0x10000000; |
| 75 | const default_image_base_exe: u64 = 0x10000; | 76 | const default_image_base_exe: u64 = 0x10000; |
| ... | @@ -150,6 +151,9 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Coff { | ... | @@ -150,6 +151,9 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Coff { |
| 150 | 33...64 => .p64, | 151 | 33...64 => .p64, |
| 151 | else => return error.UnsupportedCOFFArchitecture, | 152 | else => return error.UnsupportedCOFFArchitecture, |
| 152 | }; | 153 | }; |
| | 154 | const page_size: u32 = switch (options.target.cpu.arch) { |
| | 155 | else => 0x1000, |
| | 156 | }; |
| 153 | const self = try gpa.create(Coff); | 157 | const self = try gpa.create(Coff); |
| 154 | errdefer gpa.destroy(self); | 158 | errdefer gpa.destroy(self); |
| 155 | self.* = .{ | 159 | self.* = .{ |
| ... | @@ -160,6 +164,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Coff { | ... | @@ -160,6 +164,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Coff { |
| 160 | .file = null, | 164 | .file = null, |
| 161 | }, | 165 | }, |
| 162 | .ptr_width = ptr_width, | 166 | .ptr_width = ptr_width, |
| | 167 | .page_size = page_size, |
| 163 | .data_directories = comptime mem.zeroes([16]coff.ImageDataDirectory), | 168 | .data_directories = comptime mem.zeroes([16]coff.ImageDataDirectory), |
| 164 | }; | 169 | }; |
| 165 | | 170 | |
| ... | @@ -199,9 +204,15 @@ pub fn deinit(self: *Coff) void { | ... | @@ -199,9 +204,15 @@ pub fn deinit(self: *Coff) void { |
| 199 | } | 204 | } |
| 200 | | 205 | |
| 201 | fn populateMissingMetadata(self: *Coff) !void { | 206 | fn populateMissingMetadata(self: *Coff) !void { |
| | 207 | assert(self.llvm_object == null); |
| 202 | const gpa = self.base.allocator; | 208 | const gpa = self.base.allocator; |
| 203 | | 209 | |
| 204 | if (self.text_section_index == null) {} | 210 | if (self.text_section_index == null) { |
| | 211 | self.text_section_index = @intCast(u16, self.sections.slice().len); |
| | 212 | const file_size = self.base.options.program_code_size_hint; |
| | 213 | const off = self.findFreeSpace(file_size, self.page_size); // TODO we are over-aligning in file; we should track both in file and in memory pointers |
| | 214 | log.debug("found .text free space 0x{x} to 0x{x}", .{ off, off + file_size }); |
| | 215 | } |
| 205 | | 216 | |
| 206 | if (self.got_section_index == null) {} | 217 | if (self.got_section_index == null) {} |
| 207 | | 218 | |
| ... | @@ -756,7 +767,7 @@ fn writeHeader(self: *Coff) !void { | ... | @@ -756,7 +767,7 @@ fn writeHeader(self: *Coff) !void { |
| 756 | }; | 767 | }; |
| 757 | const subsystem: coff.Subsystem = .WINDOWS_CUI; | 768 | const subsystem: coff.Subsystem = .WINDOWS_CUI; |
| 758 | const size_of_headers: u32 = @intCast(u32, self.getSizeOfHeaders()); | 769 | const size_of_headers: u32 = @intCast(u32, self.getSizeOfHeaders()); |
| 759 | const size_of_image_aligned: u32 = mem.alignForwardGeneric(u32, size_of_headers, default_section_alignment); | 770 | const size_of_image_aligned: u32 = mem.alignForwardGeneric(u32, size_of_headers, self.page_size); |
| 760 | const size_of_headers_aligned: u32 = mem.alignForwardGeneric(u32, size_of_headers, default_file_alignment); | 771 | const size_of_headers_aligned: u32 = mem.alignForwardGeneric(u32, size_of_headers, default_file_alignment); |
| 761 | const image_base = self.base.options.image_base_override orelse switch (self.base.options.output_mode) { | 772 | const image_base = self.base.options.image_base_override orelse switch (self.base.options.output_mode) { |
| 762 | .Exe => default_image_base_exe, | 773 | .Exe => default_image_base_exe, |
| ... | @@ -777,7 +788,7 @@ fn writeHeader(self: *Coff) !void { | ... | @@ -777,7 +788,7 @@ fn writeHeader(self: *Coff) !void { |
| 777 | .base_of_code = 0, | 788 | .base_of_code = 0, |
| 778 | .base_of_data = 0, | 789 | .base_of_data = 0, |
| 779 | .image_base = @intCast(u32, image_base), | 790 | .image_base = @intCast(u32, image_base), |
| 780 | .section_alignment = default_section_alignment, | 791 | .section_alignment = self.page_size, |
| 781 | .file_alignment = default_file_alignment, | 792 | .file_alignment = default_file_alignment, |
| 782 | .major_operating_system_version = 6, | 793 | .major_operating_system_version = 6, |
| 783 | .minor_operating_system_version = 0, | 794 | .minor_operating_system_version = 0, |
| ... | @@ -811,7 +822,7 @@ fn writeHeader(self: *Coff) !void { | ... | @@ -811,7 +822,7 @@ fn writeHeader(self: *Coff) !void { |
| 811 | .address_of_entry_point = self.entry_addr orelse 0, | 822 | .address_of_entry_point = self.entry_addr orelse 0, |
| 812 | .base_of_code = 0, | 823 | .base_of_code = 0, |
| 813 | .image_base = image_base, | 824 | .image_base = image_base, |
| 814 | .section_alignment = default_section_alignment, | 825 | .section_alignment = self.page_size, |
| 815 | .file_alignment = default_file_alignment, | 826 | .file_alignment = default_file_alignment, |
| 816 | .major_operating_system_version = 6, | 827 | .major_operating_system_version = 6, |
| 817 | .minor_operating_system_version = 0, | 828 | .minor_operating_system_version = 0, |
| ... | @@ -956,3 +967,23 @@ pub fn getGotAtomForSymbol(self: *Coff, sym_loc: SymbolWithLoc) ?*Atom { | ... | @@ -956,3 +967,23 @@ pub fn getGotAtomForSymbol(self: *Coff, sym_loc: SymbolWithLoc) ?*Atom { |
| 956 | const got_index = self.got_entries.get(sym_loc) orelse return null; | 967 | const got_index = self.got_entries.get(sym_loc) orelse return null; |
| 957 | return self.atom_by_index_table.get(got_index); | 968 | return self.atom_by_index_table.get(got_index); |
| 958 | } | 969 | } |
| | 970 | |
| | 971 | fn setSectionName(self: *Coff, header: *coff.SectionHeader, name: []const u8) !void { |
| | 972 | if (name.len <= 8) { |
| | 973 | mem.copy(u8, &header.name, name); |
| | 974 | return; |
| | 975 | } |
| | 976 | const offset = try self.strtab.insert(self.base.allocator, name); |
| | 977 | const name_offset = try fmt.bufPrint(&header.name, "/{d}", .{offset}); |
| | 978 | mem.set(u8, header.name[name_offset.len..], 0); |
| | 979 | } |
| | 980 | |
| | 981 | fn setSymbolName(self: *Coff, symbol: *coff.Symbol, name: []const u8) !void { |
| | 982 | if (name.len <= 8) { |
| | 983 | mem.copy(u8, &symbol.name, name); |
| | 984 | return; |
| | 985 | } |
| | 986 | const offset = try self.strtab.insert(self.base.allocator, name); |
| | 987 | mem.copy(u8, symbol.name[0..4], 0); |
| | 988 | _ = try fmt.bufPrint(symbol.name[4..], "{d}", .{offset}); |
| | 989 | } |