authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-28 10:40:19+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-28 13:28:48+02:00
logfb3345e346d26cfac01e45e3662385c587ec3462
tree7e1d14e03b444e44ca163c7cb52f8426e66c01cc
parent2a5c4ea8f08d212b10d4dc8748fbaf5beddecbb6

coff: do not use atoms for synthetic import address table

Instead, introduce a custom ImportTable structure which will act as a thunk in the MachO linker, and we will use that to calculate the address of a pointer on-the-fly. Additionally, fix logic in writeImportTables to allow for multiple DLLs.

2 files changed, 259 insertions(+), 147 deletions(-)

src/link/Coff.zig+240-128
......@@ -70,9 +70,10 @@ got_entries: std.ArrayListUnmanaged(Entry) = .{},
7070got_entries_free_list: std.ArrayListUnmanaged(u32) = .{},
7171got_entries_table: std.AutoHashMapUnmanaged(SymbolWithLoc, u32) = .{},
7272
73imports: std.ArrayListUnmanaged(Entry) = .{},
74imports_free_list: std.ArrayListUnmanaged(u32) = .{},
75imports_table: std.AutoHashMapUnmanaged(SymbolWithLoc, u32) = .{},
73/// A table of ImportTables partitioned by the library name.
74/// Key is an offset into the interning string table `temp_strtab`.
75import_tables: std.AutoArrayHashMapUnmanaged(u32, ImportTable) = .{},
76imports_count_dirty: bool = true,
7677
7778/// Virtual address of the entry point procedure relative to image base.
7879entry_addr: ?u32 = null,
......@@ -159,6 +160,92 @@ const Section = struct {
159160 free_list: std.ArrayListUnmanaged(Atom.Index) = .{},
160161};
161162
163/// Represents an import table in the .idata section where each contained pointer
164/// is to a symbol from the same DLL.
165///
166/// The layout of .idata section is as follows:
167///
168/// --- ADDR1 : IAT (all import tables concatenated together)
169/// ptr
170/// ptr
171/// 0 sentinel
172/// ptr
173/// 0 sentinel
174/// --- ADDR2: headers
175/// ImportDirectoryEntry header
176/// ImportDirectoryEntry header
177/// sentinel
178/// --- ADDR2: lookup tables
179/// Lookup table
180/// 0 sentinel
181/// Lookup table
182/// 0 sentinel
183/// --- ADDR3: name hint tables
184/// hint-symname
185/// hint-symname
186/// --- ADDR4: DLL names
187/// DLL#1 name
188/// DLL#2 name
189/// --- END
190const ImportTable = struct {
191 entries: std.ArrayListUnmanaged(SymbolWithLoc) = .{},
192 free_list: std.ArrayListUnmanaged(u32) = .{},
193 lookup: std.AutoHashMapUnmanaged(SymbolWithLoc, u32) = .{},
194 index: u8,
195
196 const ITable = @This();
197
198 fn deinit(itab: *ITable, allocator: Allocator) void {
199 itab.entries.deinit(allocator);
200 itab.free_list.deinit(allocator);
201 itab.lookup.deinit(allocator);
202 }
203
204 fn size(itab: ITable) u32 {
205 return @intCast(u32, itab.entries.items.len) * @sizeOf(u64);
206 }
207
208 fn addImport(itab: *ITable, allocator: Allocator, target: SymbolWithLoc) !u32 {
209 try itab.entries.ensureUnusedCapacity(allocator, 1);
210 const index: u32 = blk: {
211 if (itab.free_list.popOrNull()) |index| {
212 log.debug(" (reusing import entry index {d})", .{index});
213 break :blk index;
214 } else {
215 log.debug(" (allocating import entry at index {d})", .{itab.entries.items.len});
216 const index = @intCast(u32, itab.entries.items.len);
217 _ = itab.entries.addOneAssumeCapacity();
218 break :blk index;
219 }
220 };
221 itab.entries.items[index] = target;
222 try itab.lookup.putNoClobber(allocator, target, index);
223 return index;
224 }
225
226 fn getBaseAddress(itab: *const ITable, coff_file: *const Coff) u32 {
227 const header = coff_file.sections.items(.header)[coff_file.idata_section_index.?];
228 var addr = header.virtual_address;
229 for (coff_file.import_tables.values(), 0..) |other_itab, i| {
230 if (itab.index == i) break;
231 addr += @intCast(u32, other_itab.entries.items.len * @sizeOf(u64)) + 8;
232 }
233 return addr;
234 }
235
236 pub fn getImportAddress(itab: *const ITable, coff_file: *const Coff, target: SymbolWithLoc) ?u32 {
237 const index = itab.lookup.get(target) orelse return null;
238 const base_vaddr = itab.getBaseAddress(coff_file);
239 return base_vaddr + index * @sizeOf(u64);
240 }
241
242 pub fn write(itab: ITable, writer: anytype) !void {
243 for (itab.entries.items) |_| {
244 try writer.writeIntLittle(u64, 0);
245 }
246 }
247};
248
162249const DeclMetadata = struct {
163250 atom: Atom.Index,
164251 section: u16,
......@@ -315,9 +402,11 @@ pub fn deinit(self: *Coff) void {
315402 self.got_entries.deinit(gpa);
316403 self.got_entries_free_list.deinit(gpa);
317404 self.got_entries_table.deinit(gpa);
318 self.imports.deinit(gpa);
319 self.imports_free_list.deinit(gpa);
320 self.imports_table.deinit(gpa);
405
406 for (self.import_tables.values()) |*itab| {
407 itab.deinit(gpa);
408 }
409 self.import_tables.deinit(gpa);
321410
322411 {
323412 var it = self.decls.iterator();
......@@ -730,28 +819,6 @@ pub fn allocateGotEntry(self: *Coff, target: SymbolWithLoc) !u32 {
730819 return index;
731820}
732821
733pub fn allocateImportEntry(self: *Coff, target: SymbolWithLoc) !u32 {
734 const gpa = self.base.allocator;
735 try self.imports.ensureUnusedCapacity(gpa, 1);
736
737 const index: u32 = blk: {
738 if (self.imports_free_list.popOrNull()) |index| {
739 log.debug(" (reusing import entry index {d})", .{index});
740 break :blk index;
741 } else {
742 log.debug(" (allocating import entry at index {d})", .{self.imports.items.len});
743 const index = @intCast(u32, self.imports.items.len);
744 _ = self.imports.addOneAssumeCapacity();
745 break :blk index;
746 }
747 };
748
749 self.imports.items[index] = .{ .target = target, .sym_index = 0 };
750 try self.imports_table.putNoClobber(gpa, target, index);
751
752 return index;
753}
754
755822pub fn createAtom(self: *Coff) !Atom.Index {
756823 const gpa = self.base.allocator;
757824 const atom_index = @intCast(Atom.Index, self.atoms.items.len);
......@@ -802,21 +869,6 @@ fn createGotAtom(self: *Coff, target: SymbolWithLoc) !Atom.Index {
802869 return atom_index;
803870}
804871
805fn createImportAtom(self: *Coff) !Atom.Index {
806 const atom_index = try self.createAtom();
807 const atom = self.getAtomPtr(atom_index);
808 atom.size = @sizeOf(u64);
809 atom.alignment = @alignOf(u64);
810
811 const sym = atom.getSymbolPtr(self);
812 sym.section_number = @intToEnum(coff.SectionNumber, self.idata_section_index.? + 1);
813 sym.value = try self.allocateAtom(atom_index, atom.size, atom.alignment);
814
815 log.debug("allocated import atom at 0x{x}", .{sym.value});
816
817 return atom_index;
818}
819
820872fn growAtom(self: *Coff, atom_index: Atom.Index, new_atom_size: u32, alignment: u32) !u32 {
821873 const atom = self.getAtom(atom_index);
822874 const sym = atom.getSymbol(self);
......@@ -876,10 +928,8 @@ fn markRelocsDirtyByAddress(self: *Coff, addr: u32) void {
876928 var it = self.relocs.valueIterator();
877929 while (it.next()) |relocs| {
878930 for (relocs.items) |*reloc| {
879 const target_atom_index = reloc.getTargetAtomIndex(self) orelse continue;
880 const target_atom = self.getAtom(target_atom_index);
881 const target_sym = target_atom.getSymbol(self);
882 if (target_sym.value < addr) continue;
931 const target_vaddr = reloc.getTargetAddress(self) orelse continue;
932 if (target_vaddr < addr) continue;
883933 reloc.dirty = true;
884934 }
885935 }
......@@ -1468,35 +1518,42 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod
14681518 sub_prog_node.activate();
14691519 defer sub_prog_node.end();
14701520
1521 const gpa = self.base.allocator;
1522
14711523 while (self.unresolved.popOrNull()) |entry| {
14721524 assert(entry.value); // We only expect imports generated by the incremental linker for now.
14731525 const global = self.globals.items[entry.key];
1474 if (self.imports_table.contains(global)) continue;
1475
1476 const import_index = try self.allocateImportEntry(global);
1477 const import_atom_index = try self.createImportAtom();
1478 const import_atom = self.getAtom(import_atom_index);
1479 self.imports.items[import_index].sym_index = import_atom.getSymbolIndex().?;
1480 try self.writePtrWidthAtom(import_atom_index);
1481 }
1482
1483 if (build_options.enable_logging) {
1484 self.logSymtab();
1526 const sym = self.getSymbol(global);
1527 const res = try self.import_tables.getOrPut(gpa, sym.value);
1528 const itable = res.value_ptr;
1529 if (!res.found_existing) {
1530 itable.* = .{ .index = @intCast(u8, self.import_tables.values().len - 1) };
1531 }
1532 if (itable.lookup.contains(global)) continue;
1533 // TODO: we could technically write the pointer placeholder for to-be-bound import here,
1534 // but since this happens in flush, there is currently no point.
1535 _ = try itable.addImport(gpa, global);
1536 self.imports_count_dirty = true;
14851537 }
14861538
1539 try self.writeImportTables();
14871540 {
14881541 var it = self.relocs.keyIterator();
14891542 while (it.next()) |atom| {
14901543 try self.resolveRelocs(atom.*);
14911544 }
14921545 }
1493 try self.writeImportTable();
14941546 try self.writeBaseRelocations();
14951547
14961548 if (self.getEntryPoint()) |entry_sym_loc| {
14971549 self.entry_addr = self.getSymbol(entry_sym_loc).value;
14981550 }
14991551
1552 if (build_options.enable_logging) {
1553 self.logSymtab();
1554 self.logImportTables();
1555 }
1556
15001557 try self.writeStrtab();
15011558 try self.writeDataDirectoriesHeaders();
15021559 try self.writeSectionHeaders();
......@@ -1660,53 +1717,36 @@ fn writeBaseRelocations(self: *Coff) !void {
16601717 };
16611718}
16621719
1663fn writeImportTable(self: *Coff) !void {
1720fn writeImportTables(self: *Coff) !void {
16641721 if (self.idata_section_index == null) return;
1722 if (!self.imports_count_dirty) return;
16651723
16661724 const gpa = self.base.allocator;
16671725
1668 const last_atom_index = self.sections.items(.last_atom_index)[self.idata_section_index.?] orelse return;
1726 const ext = ".dll";
16691727 const header = &self.sections.items(.header)[self.idata_section_index.?];
1670 const last_atom = self.getAtom(last_atom_index);
1671
1672 const iat_rva = header.virtual_address;
1673 const iat_size = last_atom.getSymbol(self).value + last_atom.size * 2 - iat_rva; // account for sentinel zero pointer
16741728
1675 const dll_name = "KERNEL32.dll";
1676
1677 var import_dir_entry = coff.ImportDirectoryEntry{
1678 .import_lookup_table_rva = @sizeOf(coff.ImportDirectoryEntry) * 2,
1679 .time_date_stamp = 0,
1680 .forwarder_chain = 0,
1681 .name_rva = 0,
1682 .import_address_table_rva = iat_rva,
1683 };
1684
1685 // TODO: we currently assume there's only one (implicit) DLL - ntdll
1686 var lookup_table = std.ArrayList(coff.ImportLookupEntry64.ByName).init(gpa);
1687 defer lookup_table.deinit();
1688
1689 var names_table = std.ArrayList(u8).init(gpa);
1690 defer names_table.deinit();
1691
1692 // TODO: check if import is still valid
1693 for (self.imports.items) |entry| {
1694 const target_name = self.getSymbolName(entry.target);
1695 const start = names_table.items.len;
1696 mem.writeIntLittle(u16, try names_table.addManyAsArray(2), 0); // TODO: currently, hint is set to 0 as we haven't yet parsed any DLL
1697 try names_table.appendSlice(target_name);
1698 try names_table.append(0);
1699 const end = names_table.items.len;
1700 if (!mem.isAlignedGeneric(usize, end - start, @sizeOf(u16))) {
1701 try names_table.append(0);
1729 // Calculate needed size
1730 var iat_size: u32 = 0;
1731 var dir_table_size: u32 = @sizeOf(coff.ImportDirectoryEntry); // sentinel
1732 var lookup_table_size: u32 = 0;
1733 var names_table_size: u32 = 0;
1734 var dll_names_size: u32 = 0;
1735 for (self.import_tables.keys(), 0..) |off, i| {
1736 const lib_name = self.temp_strtab.getAssumeExists(off);
1737 const itable = self.import_tables.values()[i];
1738 iat_size += itable.size() + 8;
1739 dir_table_size += @sizeOf(coff.ImportDirectoryEntry);
1740 lookup_table_size += @intCast(u32, itable.entries.items.len + 1) * @sizeOf(coff.ImportLookupEntry64.ByName);
1741 for (itable.entries.items) |entry| {
1742 const sym_name = self.getSymbolName(entry);
1743 names_table_size += 2 + mem.alignForwardGeneric(u32, @intCast(u32, sym_name.len + 1), 2);
17021744 }
1703 try lookup_table.append(.{ .name_table_rva = @intCast(u31, start) });
1745 dll_names_size += @intCast(u32, lib_name.len + ext.len + 1);
17041746 }
1705 try lookup_table.append(.{ .name_table_rva = 0 }); // the sentinel
17061747
1707 const dir_entry_size = @sizeOf(coff.ImportDirectoryEntry) + lookup_table.items.len * @sizeOf(coff.ImportLookupEntry64.ByName) + names_table.items.len + dll_name.len + 1;
1748 const needed_size = iat_size + dir_table_size + lookup_table_size + names_table_size + dll_names_size;
17081749 const sect_capacity = self.allocatedSize(header.pointer_to_raw_data);
1709 const needed_size = @intCast(u32, iat_size + dir_entry_size + @sizeOf(coff.ImportDirectoryEntry));
17101750 if (needed_size > sect_capacity) {
17111751 const new_offset = self.findFreeSpace(needed_size, default_file_alignment);
17121752 log.debug("moving .idata from 0x{x} to 0x{x}", .{ header.pointer_to_raw_data, new_offset });
......@@ -1716,41 +1756,105 @@ fn writeImportTable(self: *Coff) !void {
17161756 if (needed_size > sect_vm_capacity) {
17171757 try self.growSectionVM(self.idata_section_index.?, needed_size);
17181758 }
1719 }
1720
1721 // Fixup offsets
1722 const base_rva = iat_rva + iat_size;
1723 import_dir_entry.import_lookup_table_rva += base_rva;
1724 import_dir_entry.name_rva = @intCast(u32, base_rva + dir_entry_size + @sizeOf(coff.ImportDirectoryEntry) - dll_name.len - 1);
17251759
1726 for (lookup_table.items[0 .. lookup_table.items.len - 1]) |*lk| {
1727 lk.name_table_rva += @intCast(u31, base_rva + @sizeOf(coff.ImportDirectoryEntry) * 2 + lookup_table.items.len * @sizeOf(coff.ImportLookupEntry64.ByName));
1760 header.virtual_size = @max(header.virtual_size, needed_size);
1761 header.size_of_raw_data = needed_size;
17281762 }
17291763
1764 // Do the actual writes
17301765 var buffer = std.ArrayList(u8).init(gpa);
17311766 defer buffer.deinit();
1732 try buffer.ensureTotalCapacity(dir_entry_size + @sizeOf(coff.ImportDirectoryEntry));
1733 buffer.appendSliceAssumeCapacity(mem.asBytes(&import_dir_entry));
1734 buffer.appendNTimesAssumeCapacity(0, @sizeOf(coff.ImportDirectoryEntry)); // the sentinel; TODO: I think doing all of the above on bytes directly might be cleaner
1735 buffer.appendSliceAssumeCapacity(mem.sliceAsBytes(lookup_table.items));
1736 buffer.appendSliceAssumeCapacity(names_table.items);
1737 buffer.appendSliceAssumeCapacity(dll_name);
1738 buffer.appendAssumeCapacity(0);
1739
1740 try self.base.file.?.pwriteAll(buffer.items, header.pointer_to_raw_data + iat_size);
1741 // Override the IAT atoms
1742 // TODO: we should rewrite only dirtied atoms, but that's for way later
1743 try self.base.file.?.pwriteAll(mem.sliceAsBytes(lookup_table.items), header.pointer_to_raw_data);
1767 try buffer.ensureTotalCapacityPrecise(needed_size);
1768 buffer.resize(needed_size) catch unreachable;
1769
1770 const dir_header_size = @sizeOf(coff.ImportDirectoryEntry);
1771 const lookup_entry_size = @sizeOf(coff.ImportLookupEntry64.ByName);
1772
1773 var iat_offset: u32 = 0;
1774 var dir_table_offset = iat_size;
1775 var lookup_table_offset = dir_table_offset + dir_table_size;
1776 var names_table_offset = lookup_table_offset + lookup_table_size;
1777 var dll_names_offset = names_table_offset + names_table_size;
1778 for (self.import_tables.keys(), 0..) |off, i| {
1779 const lib_name = self.temp_strtab.getAssumeExists(off);
1780 const itable = self.import_tables.values()[i];
1781
1782 // Lookup table header
1783 const lookup_header = coff.ImportDirectoryEntry{
1784 .import_lookup_table_rva = header.virtual_address + lookup_table_offset,
1785 .time_date_stamp = 0,
1786 .forwarder_chain = 0,
1787 .name_rva = header.virtual_address + dll_names_offset,
1788 .import_address_table_rva = header.virtual_address + iat_offset,
1789 };
1790 mem.copy(u8, buffer.items[dir_table_offset..], mem.asBytes(&lookup_header));
1791 dir_table_offset += dir_header_size;
1792
1793 for (itable.entries.items) |entry| {
1794 const import_name = self.getSymbolName(entry);
1795
1796 // IAT and lookup table entry
1797 const lookup = coff.ImportLookupEntry64.ByName{ .name_table_rva = @intCast(u31, header.virtual_address + names_table_offset) };
1798 mem.copy(u8, buffer.items[iat_offset..], mem.asBytes(&lookup));
1799 iat_offset += lookup_entry_size;
1800 mem.copy(u8, buffer.items[lookup_table_offset..], mem.asBytes(&lookup));
1801 lookup_table_offset += lookup_entry_size;
1802
1803 // Names table entry
1804 mem.writeIntLittle(u16, buffer.items[names_table_offset..][0..2], 0); // Hint set to 0 until we learn how to parse DLLs
1805 names_table_offset += 2;
1806 mem.copy(u8, buffer.items[names_table_offset..], import_name);
1807 names_table_offset += @intCast(u32, import_name.len);
1808 buffer.items[names_table_offset] = 0;
1809 names_table_offset += 1;
1810 if (!mem.isAlignedGeneric(usize, names_table_offset, @sizeOf(u16))) {
1811 buffer.items[names_table_offset] = 0;
1812 names_table_offset += 1;
1813 }
1814 }
17441815
1745 self.data_directories[@enumToInt(coff.DirectoryEntry.IMPORT)] = .{
1746 .virtual_address = iat_rva + iat_size,
1747 .size = @intCast(u32, @sizeOf(coff.ImportDirectoryEntry) * 2),
1816 // IAT sentinel
1817 mem.writeIntLittle(u64, buffer.items[iat_offset..][0..lookup_entry_size], 0);
1818 iat_offset += 8;
1819
1820 // Lookup table sentinel
1821 mem.copy(u8, buffer.items[lookup_table_offset..], mem.asBytes(&coff.ImportLookupEntry64.ByName{ .name_table_rva = 0 }));
1822 lookup_table_offset += lookup_entry_size;
1823
1824 // DLL name
1825 mem.copy(u8, buffer.items[dll_names_offset..], lib_name);
1826 dll_names_offset += @intCast(u32, lib_name.len);
1827 mem.copy(u8, buffer.items[dll_names_offset..], ext);
1828 dll_names_offset += @intCast(u32, ext.len);
1829 buffer.items[dll_names_offset] = 0;
1830 dll_names_offset += 1;
1831 }
1832
1833 // Sentinel
1834 const lookup_header = coff.ImportDirectoryEntry{
1835 .import_lookup_table_rva = 0,
1836 .time_date_stamp = 0,
1837 .forwarder_chain = 0,
1838 .name_rva = 0,
1839 .import_address_table_rva = 0,
17481840 };
1841 mem.copy(u8, buffer.items[dir_table_offset..], mem.asBytes(&lookup_header));
1842 dir_table_offset += dir_header_size;
1843
1844 assert(dll_names_offset == needed_size);
17491845
1846 try self.base.file.?.pwriteAll(buffer.items, header.pointer_to_raw_data);
1847
1848 self.data_directories[@enumToInt(coff.DirectoryEntry.IMPORT)] = .{
1849 .virtual_address = header.virtual_address + iat_size,
1850 .size = dir_table_size,
1851 };
17501852 self.data_directories[@enumToInt(coff.DirectoryEntry.IAT)] = .{
1751 .virtual_address = iat_rva,
1853 .virtual_address = header.virtual_address,
17521854 .size = iat_size,
17531855 };
1856
1857 self.imports_count_dirty = false;
17541858}
17551859
17561860fn writeStrtab(self: *Coff) !void {
......@@ -2139,14 +2243,6 @@ pub fn getGotAtomIndexForSymbol(self: *const Coff, sym_loc: SymbolWithLoc) ?Atom
21392243 return self.getAtomIndexForSymbol(.{ .sym_index = got_entry.sym_index, .file = null });
21402244}
21412245
2142/// Returns import atom that references `sym_loc` if one exists.
2143/// Returns null otherwise.
2144pub fn getImportAtomIndexForSymbol(self: *const Coff, sym_loc: SymbolWithLoc) ?Atom.Index {
2145 const imports_index = self.imports_table.get(sym_loc) orelse return null;
2146 const imports_entry = self.imports.items[imports_index];
2147 return self.getAtomIndexForSymbol(.{ .sym_index = imports_entry.sym_index, .file = null });
2148}
2149
21502246fn setSectionName(self: *Coff, header: *coff.SectionHeader, name: []const u8) !void {
21512247 if (name.len <= 8) {
21522248 mem.copy(u8, &header.name, name);
......@@ -2267,3 +2363,19 @@ fn logSections(self: *Coff) void {
22672363 });
22682364 }
22692365}
2366
2367fn logImportTables(self: *const Coff) void {
2368 log.debug("import tables:", .{});
2369 for (self.import_tables.keys(), 0..) |off, i| {
2370 const lib_name = self.temp_strtab.getAssumeExists(off);
2371 const itable = self.import_tables.values()[i];
2372 log.debug("IAT({s}) @{x}:", .{ lib_name, itable.getBaseAddress(self) });
2373 for (itable.entries.items, 0..) |entry, j| {
2374 log.debug(" {d}@{?x} => {s}", .{
2375 j,
2376 itable.getImportAddress(self, entry),
2377 self.getSymbolName(entry),
2378 });
2379 }
2380 }
2381}
src/link/Coff/Relocation.zig+19-19
......@@ -45,23 +45,25 @@ pcrel: bool,
4545length: u2,
4646dirty: bool = true,
4747
48/// Returns an Atom which is the target node of this relocation edge (if any).
49pub fn getTargetAtomIndex(self: Relocation, coff_file: *const Coff) ?Atom.Index {
48/// Returns address of the target if any.
49pub fn getTargetAddress(self: Relocation, coff_file: *const Coff) ?u32 {
5050 switch (self.type) {
51 .got,
52 .got_page,
53 .got_pageoff,
54 => return coff_file.getGotAtomIndexForSymbol(self.target),
55
56 .direct,
57 .page,
58 .pageoff,
59 => return coff_file.getAtomIndexForSymbol(self.target),
60
61 .import,
62 .import_page,
63 .import_pageoff,
64 => return coff_file.getImportAtomIndexForSymbol(self.target),
51 .got, .got_page, .got_pageoff, .direct, .page, .pageoff => {
52 const maybe_target_atom_index = switch (self.type) {
53 .got, .got_page, .got_pageoff => coff_file.getGotAtomIndexForSymbol(self.target),
54 .direct, .page, .pageoff => coff_file.getAtomIndexForSymbol(self.target),
55 else => unreachable,
56 };
57 const target_atom_index = maybe_target_atom_index orelse return null;
58 const target_atom = coff_file.getAtom(target_atom_index);
59 return target_atom.getSymbol(coff_file).value;
60 },
61
62 .import, .import_page, .import_pageoff => {
63 const sym = coff_file.getSymbol(self.target);
64 const itab = coff_file.import_tables.get(sym.value) orelse return null;
65 return itab.getImportAddress(coff_file, self.target);
66 },
6567 }
6668}
6769
......@@ -73,9 +75,7 @@ pub fn resolve(self: *Relocation, atom_index: Atom.Index, coff_file: *Coff) !voi
7375
7476 const file_offset = source_section.pointer_to_raw_data + source_sym.value - source_section.virtual_address;
7577
76 const target_atom_index = self.getTargetAtomIndex(coff_file) orelse return;
77 const target_atom = coff_file.getAtom(target_atom_index);
78 const target_vaddr = target_atom.getSymbol(coff_file).value;
78 const target_vaddr = self.getTargetAddress(coff_file) orelse return;
7979 const target_vaddr_with_addend = target_vaddr + self.addend;
8080
8181 log.debug(" ({x}: [() => 0x{x} ({s})) ({s}) (in file at 0x{x})", .{