| ... | @@ -30,7 +30,6 @@ const TypedValue = @import("../TypedValue.zig"); | ... | @@ -30,7 +30,6 @@ const TypedValue = @import("../TypedValue.zig"); |
| 30 | pub const base_tag: link.File.Tag = .coff; | 30 | pub const base_tag: link.File.Tag = .coff; |
| 31 | | 31 | |
| 32 | const msdos_stub = @embedFile("msdos-stub.bin"); | 32 | const msdos_stub = @embedFile("msdos-stub.bin"); |
| 33 | const N_DATA_DIRS: u5 = 16; | | |
| 34 | | 33 | |
| 35 | /// If this is not null, an object file is created by LLVM and linked with LLD afterwards. | 34 | /// If this is not null, an object file is created by LLVM and linked with LLD afterwards. |
| 36 | llvm_object: ?*LlvmObject = null, | 35 | llvm_object: ?*LlvmObject = null, |
| ... | @@ -44,7 +43,7 @@ page_size: u32, | ... | @@ -44,7 +43,7 @@ page_size: u32, |
| 44 | objects: std.ArrayListUnmanaged(Object) = .{}, | 43 | objects: std.ArrayListUnmanaged(Object) = .{}, |
| 45 | | 44 | |
| 46 | sections: std.MultiArrayList(Section) = .{}, | 45 | sections: std.MultiArrayList(Section) = .{}, |
| 47 | data_directories: [N_DATA_DIRS]coff.ImageDataDirectory, | 46 | data_directories: [coff.IMAGE_NUMBEROF_DIRECTORY_ENTRIES]coff.ImageDataDirectory, |
| 48 | | 47 | |
| 49 | text_section_index: ?u16 = null, | 48 | text_section_index: ?u16 = null, |
| 50 | got_section_index: ?u16 = null, | 49 | got_section_index: ?u16 = null, |
| ... | @@ -259,7 +258,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Coff { | ... | @@ -259,7 +258,7 @@ pub fn createEmpty(gpa: Allocator, options: link.Options) !*Coff { |
| 259 | }, | 258 | }, |
| 260 | .ptr_width = ptr_width, | 259 | .ptr_width = ptr_width, |
| 261 | .page_size = page_size, | 260 | .page_size = page_size, |
| 262 | .data_directories = comptime mem.zeroes([N_DATA_DIRS]coff.ImageDataDirectory), | 261 | .data_directories = comptime mem.zeroes([coff.IMAGE_NUMBEROF_DIRECTORY_ENTRIES]coff.ImageDataDirectory), |
| 263 | }; | 262 | }; |
| 264 | | 263 | |
| 265 | const use_llvm = build_options.have_llvm and options.use_llvm; | 264 | const use_llvm = build_options.have_llvm and options.use_llvm; |
| ... | @@ -421,7 +420,12 @@ fn populateMissingMetadata(self: *Coff) !void { | ... | @@ -421,7 +420,12 @@ fn populateMissingMetadata(self: *Coff) !void { |
| 421 | fn allocateSection(self: *Coff, name: []const u8, size: u32, flags: coff.SectionHeaderFlags) !u16 { | 420 | fn allocateSection(self: *Coff, name: []const u8, size: u32, flags: coff.SectionHeaderFlags) !u16 { |
| 422 | const index = @intCast(u16, self.sections.slice().len); | 421 | const index = @intCast(u16, self.sections.slice().len); |
| 423 | const off = self.findFreeSpace(size, default_file_alignment); | 422 | const off = self.findFreeSpace(size, default_file_alignment); |
| 424 | const vaddr = self.findFreeSpaceVM(size, self.page_size); | 423 | // Memory is always allocated in sequence |
| | 424 | const vaddr = blk: { |
| | 425 | if (index == 0) break :blk self.page_size; |
| | 426 | const prev_header = self.sections.items(.header)[index - 1]; |
| | 427 | break :blk mem.alignForwardGeneric(u32, prev_header.virtual_address + prev_header.virtual_size, self.page_size); |
| | 428 | }; |
| 425 | log.debug("found {s} free space 0x{x} to 0x{x} (0x{x} - 0x{x})", .{ | 429 | log.debug("found {s} free space 0x{x} to 0x{x} (0x{x} - 0x{x})", .{ |
| 426 | name, | 430 | name, |
| 427 | off, | 431 | off, |
| ... | @@ -574,7 +578,7 @@ fn allocateAtom(self: *Coff, atom: *Atom, new_atom_size: u32, alignment: u32) !u | ... | @@ -574,7 +578,7 @@ fn allocateAtom(self: *Coff, atom: *Atom, new_atom_size: u32, alignment: u32) !u |
| 574 | header.pointer_to_raw_data = new_offset; | 578 | header.pointer_to_raw_data = new_offset; |
| 575 | } | 579 | } |
| 576 | | 580 | |
| 577 | const sect_vm_capacity = self.allocatedSizeVM(header.virtual_address); | 581 | const sect_vm_capacity = self.allocatedVirtualSize(header.virtual_address); |
| 578 | if (needed_size > sect_vm_capacity) { | 582 | if (needed_size > sect_vm_capacity) { |
| 579 | try self.growSectionVM(sect_id, needed_size); | 583 | try self.growSectionVM(sect_id, needed_size); |
| 580 | self.markRelocsDirtyByAddress(header.virtual_address + needed_size); | 584 | self.markRelocsDirtyByAddress(header.virtual_address + needed_size); |
| ... | @@ -857,10 +861,9 @@ fn resolveRelocs(self: *Coff, atom: *Atom) !void { | ... | @@ -857,10 +861,9 @@ fn resolveRelocs(self: *Coff, atom: *Atom) !void { |
| 857 | fn freeAtom(self: *Coff, atom: *Atom) void { | 861 | fn freeAtom(self: *Coff, atom: *Atom) void { |
| 858 | log.debug("freeAtom {*}", .{atom}); | 862 | log.debug("freeAtom {*}", .{atom}); |
| 859 | | 863 | |
| 860 | // TODO hashmap | 864 | // Remove any relocs and base relocs associated with this Atom |
| 861 | for (self.managed_atoms.items) |owned| { | 865 | _ = self.relocs.remove(atom); |
| 862 | if (owned == atom) break; | 866 | _ = self.base_relocs.remove(atom); |
| 863 | } else atom.deinit(self.base.allocator); | | |
| 864 | | 867 | |
| 865 | const sym = atom.getSymbol(self); | 868 | const sym = atom.getSymbol(self); |
| 866 | const sect_id = @enumToInt(sym.section_number) - 1; | 869 | const sect_id = @enumToInt(sym.section_number) - 1; |
| ... | @@ -1577,7 +1580,7 @@ fn writeBaseRelocations(self: *Coff) !void { | ... | @@ -1577,7 +1580,7 @@ fn writeBaseRelocations(self: *Coff) !void { |
| 1577 | }); | 1580 | }); |
| 1578 | header.pointer_to_raw_data = new_offset; | 1581 | header.pointer_to_raw_data = new_offset; |
| 1579 | | 1582 | |
| 1580 | const sect_vm_capacity = self.allocatedSizeVM(header.virtual_address); | 1583 | const sect_vm_capacity = self.allocatedVirtualSize(header.virtual_address); |
| 1581 | if (needed_size > sect_vm_capacity) { | 1584 | if (needed_size > sect_vm_capacity) { |
| 1582 | // TODO: we want to enforce .reloc after every alloc section. | 1585 | // TODO: we want to enforce .reloc after every alloc section. |
| 1583 | try self.growSectionVM(self.reloc_section_index.?, needed_size); | 1586 | try self.growSectionVM(self.reloc_section_index.?, needed_size); |
| ... | @@ -1862,7 +1865,7 @@ pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { | ... | @@ -1862,7 +1865,7 @@ pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { |
| 1862 | } | 1865 | } |
| 1863 | | 1866 | |
| 1864 | fn detectAllocCollision(self: *Coff, start: u32, size: u32) ?u32 { | 1867 | fn detectAllocCollision(self: *Coff, start: u32, size: u32) ?u32 { |
| 1865 | const headers_size = @maximum(self.getSizeOfHeaders(), 0x1000); | 1868 | const headers_size = @maximum(self.getSizeOfHeaders(), self.page_size); |
| 1866 | if (start < headers_size) | 1869 | if (start < headers_size) |
| 1867 | return headers_size; | 1870 | return headers_size; |
| 1868 | | 1871 | |
| ... | @@ -1911,7 +1914,7 @@ fn findFreeSpace(self: *Coff, object_size: u32, min_alignment: u32) u32 { | ... | @@ -1911,7 +1914,7 @@ fn findFreeSpace(self: *Coff, object_size: u32, min_alignment: u32) u32 { |
| 1911 | return start; | 1914 | return start; |
| 1912 | } | 1915 | } |
| 1913 | | 1916 | |
| 1914 | fn allocatedSizeVM(self: *Coff, start: u32) u32 { | 1917 | fn allocatedVirtualSize(self: *Coff, start: u32) u32 { |
| 1915 | if (start == 0) | 1918 | if (start == 0) |
| 1916 | return 0; | 1919 | return 0; |
| 1917 | var min_pos: u32 = std.math.maxInt(u32); | 1920 | var min_pos: u32 = std.math.maxInt(u32); |
| ... | @@ -1922,39 +1925,6 @@ fn allocatedSizeVM(self: *Coff, start: u32) u32 { | ... | @@ -1922,39 +1925,6 @@ fn allocatedSizeVM(self: *Coff, start: u32) u32 { |
| 1922 | return min_pos - start; | 1925 | return min_pos - start; |
| 1923 | } | 1926 | } |
| 1924 | | 1927 | |
| 1925 | fn detectAllocCollisionVM(self: *Coff, start: u32, size: u32) ?u32 { | | |
| 1926 | const headers_size = @maximum(self.getSizeOfHeaders(), 0x1000); | | |
| 1927 | if (start < headers_size) | | |
| 1928 | return headers_size; | | |
| 1929 | | | |
| 1930 | const end = start + size; | | |
| 1931 | | | |
| 1932 | if (self.strtab_offset) |off| { | | |
| 1933 | const increased_size = @intCast(u32, self.strtab.len()); | | |
| 1934 | const test_end = off + increased_size; | | |
| 1935 | if (end > off and start < test_end) { | | |
| 1936 | return test_end; | | |
| 1937 | } | | |
| 1938 | } | | |
| 1939 | | | |
| 1940 | for (self.sections.items(.header)) |header| { | | |
| 1941 | const increased_size = header.virtual_size; | | |
| 1942 | const test_end = header.virtual_address + increased_size; | | |
| 1943 | if (end > header.virtual_address and start < test_end) { | | |
| 1944 | return test_end; | | |
| 1945 | } | | |
| 1946 | } | | |
| 1947 | return null; | | |
| 1948 | } | | |
| 1949 | | | |
| 1950 | fn findFreeSpaceVM(self: *Coff, object_size: u32, min_alignment: u32) u32 { | | |
| 1951 | var start: u32 = 0; | | |
| 1952 | while (self.detectAllocCollisionVM(start, object_size)) |item_end| { | | |
| 1953 | start = mem.alignForwardGeneric(u32, item_end, min_alignment); | | |
| 1954 | } | | |
| 1955 | return start; | | |
| 1956 | } | | |
| 1957 | | | |
| 1958 | inline fn getSizeOfHeaders(self: Coff) u32 { | 1928 | inline fn getSizeOfHeaders(self: Coff) u32 { |
| 1959 | const msdos_hdr_size = msdos_stub.len + 4; | 1929 | const msdos_hdr_size = msdos_stub.len + 4; |
| 1960 | return @intCast(u32, msdos_hdr_size + @sizeOf(coff.CoffHeader) + self.getOptionalHeaderSize() + | 1930 | return @intCast(u32, msdos_hdr_size + @sizeOf(coff.CoffHeader) + self.getOptionalHeaderSize() + |