| ... | ... | @@ -1,36 +1,7 @@ |
| 1 | | const Coff = @This(); |
| 2 | | |
| 3 | | const std = @import("std"); |
| 4 | | const build_options = @import("build_options"); |
| 5 | | const builtin = @import("builtin"); |
| 6 | | const assert = std.debug.assert; |
| 7 | | const coff = std.coff; |
| 8 | | const fmt = std.fmt; |
| 9 | | const log = std.log.scoped(.link); |
| 10 | | const math = std.math; |
| 11 | | const mem = std.mem; |
| 12 | | |
| 13 | | const Allocator = std.mem.Allocator; |
| 14 | | |
| 15 | | const codegen = @import("../codegen.zig"); |
| 16 | | const link = @import("../link.zig"); |
| 17 | | const lld = @import("Coff/lld.zig"); |
| 18 | | const trace = @import("../tracy.zig").trace; |
| 19 | | |
| 20 | | const Air = @import("../Air.zig"); |
| 21 | | pub const Atom = @import("Coff/Atom.zig"); |
| 22 | | const Compilation = @import("../Compilation.zig"); |
| 23 | | const Liveness = @import("../Liveness.zig"); |
| 24 | | const LlvmObject = @import("../codegen/llvm.zig").Object; |
| 25 | | const Module = @import("../Module.zig"); |
| 26 | | const Object = @import("Coff/Object.zig"); |
| 27 | | const Relocation = @import("Coff/Relocation.zig"); |
| 28 | | const StringTable = @import("strtab.zig").StringTable; |
| 29 | | const TypedValue = @import("../TypedValue.zig"); |
| 30 | | |
| 31 | | pub const base_tag: link.File.Tag = .coff; |
| 32 | | |
| 33 | | const msdos_stub = @embedFile("msdos-stub.bin"); |
| 1 | //! The main driver of the COFF linker. |
| 2 | //! Currently uses our own implementation for the incremental linker, and falls back to |
| 3 | //! LLD for traditional linking (linking relocatable object files). |
| 4 | //! LLD is also the default linker for LLVM. |
| 34 | 5 | |
| 35 | 6 | /// If this is not null, an object file is created by LLVM and linked with LLD afterwards. |
| 36 | 7 | llvm_object: ?*LlvmObject = null, |
| ... | ... | @@ -160,92 +131,6 @@ const Section = struct { |
| 160 | 131 | free_list: std.ArrayListUnmanaged(Atom.Index) = .{}, |
| 161 | 132 | }; |
| 162 | 133 | |
| 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 |
| 190 | | const 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 | | |
| 249 | 134 | const DeclMetadata = struct { |
| 250 | 135 | atom: Atom.Index, |
| 251 | 136 | section: u16, |
| ... | ... | @@ -1527,7 +1412,7 @@ pub fn flushModule(self: *Coff, comp: *Compilation, prog_node: *std.Progress.Nod |
| 1527 | 1412 | const res = try self.import_tables.getOrPut(gpa, sym.value); |
| 1528 | 1413 | const itable = res.value_ptr; |
| 1529 | 1414 | if (!res.found_existing) { |
| 1530 | | itable.* = .{ .index = @intCast(u8, self.import_tables.values().len - 1) }; |
| 1415 | itable.* = .{}; |
| 1531 | 1416 | } |
| 1532 | 1417 | if (itable.lookup.contains(global)) continue; |
| 1533 | 1418 | // TODO: we could technically write the pointer placeholder for to-be-bound import here, |
| ... | ... | @@ -2367,15 +2252,46 @@ fn logSections(self: *Coff) void { |
| 2367 | 2252 | fn logImportTables(self: *const Coff) void { |
| 2368 | 2253 | log.debug("import tables:", .{}); |
| 2369 | 2254 | for (self.import_tables.keys(), 0..) |off, i| { |
| 2370 | | const lib_name = self.temp_strtab.getAssumeExists(off); |
| 2371 | 2255 | 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 | | } |
| 2256 | log.debug("{}", .{itable.fmtDebug(.{ |
| 2257 | .coff_file = self, |
| 2258 | .index = i, |
| 2259 | .name_off = off, |
| 2260 | })}); |
| 2380 | 2261 | } |
| 2381 | 2262 | } |
| 2263 | |
| 2264 | const Coff = @This(); |
| 2265 | |
| 2266 | const std = @import("std"); |
| 2267 | const build_options = @import("build_options"); |
| 2268 | const builtin = @import("builtin"); |
| 2269 | const assert = std.debug.assert; |
| 2270 | const coff = std.coff; |
| 2271 | const fmt = std.fmt; |
| 2272 | const log = std.log.scoped(.link); |
| 2273 | const math = std.math; |
| 2274 | const mem = std.mem; |
| 2275 | |
| 2276 | const Allocator = std.mem.Allocator; |
| 2277 | |
| 2278 | const codegen = @import("../codegen.zig"); |
| 2279 | const link = @import("../link.zig"); |
| 2280 | const lld = @import("Coff/lld.zig"); |
| 2281 | const trace = @import("../tracy.zig").trace; |
| 2282 | |
| 2283 | const Air = @import("../Air.zig"); |
| 2284 | pub const Atom = @import("Coff/Atom.zig"); |
| 2285 | const Compilation = @import("../Compilation.zig"); |
| 2286 | const ImportTable = @import("Coff/ImportTable.zig"); |
| 2287 | const Liveness = @import("../Liveness.zig"); |
| 2288 | const LlvmObject = @import("../codegen/llvm.zig").Object; |
| 2289 | const Module = @import("../Module.zig"); |
| 2290 | const Object = @import("Coff/Object.zig"); |
| 2291 | const Relocation = @import("Coff/Relocation.zig"); |
| 2292 | const StringTable = @import("strtab.zig").StringTable; |
| 2293 | const TypedValue = @import("../TypedValue.zig"); |
| 2294 | |
| 2295 | pub const base_tag: link.File.Tag = .coff; |
| 2296 | |
| 2297 | const msdos_stub = @embedFile("msdos-stub.bin"); |