diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2024-07-09 19:42:20 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2024-07-18 09:13:08 +0200 |
| commit | 58997363d3c94aaa66960f0e87b40d5f98f0471b (patch) | |
| tree | 0afb5d55e60ed601a390c852f76944fea1166886 /src | |
| parent | f86a38564f5d8eb903b940ddf9b9f5685a3ca932 (diff) | |
| download | zig-58997363d3c94aaa66960f0e87b40d5f98f0471b.tar.gz zig-58997363d3c94aaa66960f0e87b40d5f98f0471b.zip | |
macho: migrate MachO.File abstraction
Diffstat (limited to 'src')
| -rw-r--r-- | src/link/MachO/file.zig | 235 |
1 files changed, 126 insertions, 109 deletions
diff --git a/src/link/MachO/file.zig b/src/link/MachO/file.zig index 60c7a70f26..c01416efd5 100644 --- a/src/link/MachO/file.zig +++ b/src/link/MachO/file.zig @@ -32,106 +32,15 @@ pub const File = union(enum) { pub fn resolveSymbols(file: File, macho_file: *MachO) void { switch (file) { - .internal => unreachable, inline else => |x| x.resolveSymbols(macho_file), } } - pub fn resetGlobals(file: File, macho_file: *MachO) void { + pub fn scanRelocs(file: File, macho_file: *MachO) !void { switch (file) { - .internal => unreachable, - inline else => |x| x.resetGlobals(macho_file), - } - } - - pub fn claimUnresolved(file: File, macho_file: *MachO) error{OutOfMemory}!void { - assert(file == .object or file == .zig_object); - - for (file.getSymbols(), 0..) |sym_index, i| { - const nlist_idx = @as(Symbol.Index, @intCast(i)); - const nlist = switch (file) { - .object => |x| x.symtab.items(.nlist)[nlist_idx], - .zig_object => |x| x.symtab.items(.nlist)[nlist_idx], - else => unreachable, - }; - if (!nlist.ext()) continue; - if (!nlist.undf()) continue; - - const sym = macho_file.getSymbol(sym_index); - if (sym.getFile(macho_file) != null) continue; - - const is_import = switch (macho_file.undefined_treatment) { - .@"error" => false, - .warn, .suppress => nlist.weakRef(), - .dynamic_lookup => true, - }; - if (is_import) { - sym.value = 0; - sym.atom = 0; - sym.nlist_idx = 0; - sym.file = macho_file.internal_object.?; - sym.flags.weak = false; - sym.flags.weak_ref = nlist.weakRef(); - sym.flags.import = is_import; - sym.visibility = .global; - try macho_file.getInternalObject().?.symbols.append(macho_file.base.comp.gpa, sym_index); - } - } - } - - pub fn claimUnresolvedRelocatable(file: File, macho_file: *MachO) void { - assert(file == .object or file == .zig_object); - - for (file.getSymbols(), 0..) |sym_index, i| { - const nlist_idx = @as(Symbol.Index, @intCast(i)); - const nlist = switch (file) { - .object => |x| x.symtab.items(.nlist)[nlist_idx], - .zig_object => |x| x.symtab.items(.nlist)[nlist_idx], - else => unreachable, - }; - if (!nlist.ext()) continue; - if (!nlist.undf()) continue; - - const sym = macho_file.getSymbol(sym_index); - if (sym.getFile(macho_file) != null) continue; - - sym.value = 0; - sym.atom = 0; - sym.nlist_idx = nlist_idx; - sym.file = file.getIndex(); - sym.flags.weak_ref = nlist.weakRef(); - sym.flags.import = true; - sym.visibility = .global; - } - } - - pub fn markImportsExports(file: File, macho_file: *MachO) void { - assert(file == .object or file == .zig_object); - - for (file.getSymbols()) |sym_index| { - const sym = macho_file.getSymbol(sym_index); - const other_file = sym.getFile(macho_file) orelse continue; - if (sym.visibility != .global) continue; - if (other_file == .dylib and !sym.flags.abs) { - sym.flags.import = true; - continue; - } - if (other_file.getIndex() == file.getIndex()) { - sym.flags.@"export" = true; - } - } - } - - pub fn markExportsRelocatable(file: File, macho_file: *MachO) void { - assert(file == .object or file == .zig_object); - - for (file.getSymbols()) |sym_index| { - const sym = macho_file.getSymbol(sym_index); - const other_file = sym.getFile(macho_file) orelse continue; - if (sym.visibility != .global) continue; - if (other_file.getIndex() == file.getIndex()) { - sym.flags.@"export" = true; - } + .dylib => unreachable, + .internal => |x| x.scanRelocs(macho_file), + inline else => |x| x.scanRelocs(macho_file), } } @@ -162,39 +71,122 @@ pub const File = union(enum) { return base + (file.getIndex() << 24); } - pub fn getSymbols(file: File) []const Symbol.Index { + pub fn getAtom(file: File, atom_index: Atom.Index) ?*Atom { return switch (file) { - inline else => |x| x.symbols.items, + .dylib => unreachable, + inline else => |x| x.getAtom(atom_index), }; } pub fn getAtoms(file: File) []const Atom.Index { return switch (file) { .dylib => unreachable, - inline else => |x| x.atoms.items, + inline else => |x| x.getAtoms(), }; } - pub fn updateArSymtab(file: File, ar_symtab: *Archive.ArSymtab, macho_file: *MachO) error{OutOfMemory}!void { + pub fn addAtomExtra(file: File, allocator: Allocator, extra: Atom.Extra) !u32 { return switch (file) { - .dylib, .internal => unreachable, - inline else => |x| x.updateArSymtab(ar_symtab, macho_file), + .dylib => unreachable, + inline else => |x| x.addAtomExtra(allocator, extra), }; } - pub fn updateArSize(file: File, macho_file: *MachO) !void { + pub fn getAtomExtra(file: File, index: u32) Atom.Extra { return switch (file) { - .dylib, .internal => unreachable, - .zig_object => |x| x.updateArSize(), - .object => |x| x.updateArSize(macho_file), + .dylib => unreachable, + inline else => |x| x.getAtomExtra(index), }; } - pub fn writeAr(file: File, ar_format: Archive.Format, macho_file: *MachO, writer: anytype) !void { + pub fn setAtomExtra(file: File, index: u32, extra: Atom.Extra) void { return switch (file) { - .dylib, .internal => unreachable, - .zig_object => |x| x.writeAr(ar_format, writer), - .object => |x| x.writeAr(ar_format, macho_file, writer), + .dylib => unreachable, + inline else => |x| x.setAtomExtra(index, extra), + }; + } + + pub fn getSymbols(file: File) []Symbol { + return switch (file) { + inline else => |x| x.symbols.items, + }; + } + + pub fn getSymbolRef(file: File, sym_index: Symbol.Index, macho_file: *MachO) MachO.Ref { + return switch (file) { + inline else => |x| x.getSymbolRef(sym_index, macho_file), + }; + } + + pub fn markImportsExports(file: File, macho_file: *MachO) void { + const nsyms = switch (file) { + .dylib => unreachable, + inline else => |x| x.symbols.items.len, + }; + for (0..nsyms) |i| { + const ref = file.getSymbolRef(@intCast(i), macho_file); + if (ref.getFile(macho_file) == null) continue; + const sym = ref.getSymbol(macho_file).?; + if (sym.visibility != .global) continue; + if (sym.getFile(macho_file).? == .dylib and !sym.flags.abs) { + sym.flags.import = true; + continue; + } + if (file.getIndex() == ref.file) { + sym.flags.@"export" = true; + } + } + } + + pub fn createSymbolIndirection(file: File, macho_file: *MachO) !void { + const nsyms = switch (file) { + inline else => |x| x.symbols.items.len, + }; + for (0..nsyms) |i| { + const ref = file.getSymbolRef(@intCast(i), macho_file); + if (ref.getFile(macho_file) == null) continue; + if (ref.file != file.getIndex()) continue; + const sym = ref.getSymbol(macho_file).?; + if (sym.getSectionFlags().got) { + log.debug("'{s}' needs GOT", .{sym.getName(macho_file)}); + try macho_file.got.addSymbol(ref, macho_file); + } + if (sym.getSectionFlags().stubs) { + log.debug("'{s}' needs STUBS", .{sym.getName(macho_file)}); + try macho_file.stubs.addSymbol(ref, macho_file); + } + if (sym.getSectionFlags().tlv_ptr) { + log.debug("'{s}' needs TLV pointer", .{sym.getName(macho_file)}); + try macho_file.tlv_ptr.addSymbol(ref, macho_file); + } + if (sym.getSectionFlags().objc_stubs) { + log.debug("'{s}' needs OBJC STUBS", .{sym.getName(macho_file)}); + try macho_file.objc_stubs.addSymbol(ref, macho_file); + } + } + } + + pub fn initOutputSections(file: File, macho_file: *MachO) !void { + const tracy = trace(@src()); + defer tracy.end(); + for (file.getAtoms()) |atom_index| { + const atom = file.getAtom(atom_index) orelse continue; + if (!atom.alive.load(.seq_cst)) continue; + atom.out_n_sect = try Atom.initOutputSection(atom.getInputSection(macho_file), macho_file); + } + } + + pub fn dedupLiterals(file: File, lp: MachO.LiteralPool, macho_file: *MachO) void { + return switch (file) { + .dylib => unreachable, + inline else => |x| x.dedupLiterals(lp, macho_file), + }; + } + + pub fn writeAtoms(file: File, macho_file: *MachO) !void { + return switch (file) { + .dylib => unreachable, + inline else => |x| x.writeAtoms(macho_file), }; } @@ -210,6 +202,29 @@ pub const File = union(enum) { }; } + pub fn updateArSymtab(file: File, ar_symtab: *Archive.ArSymtab, macho_file: *MachO) error{OutOfMemory}!void { + return switch (file) { + .dylib, .internal => unreachable, + inline else => |x| x.updateArSymtab(ar_symtab, macho_file), + }; + } + + pub fn updateArSize(file: File, macho_file: *MachO) !void { + return switch (file) { + .dylib, .internal => unreachable, + .zig_object => |x| x.updateArSize(), + .object => |x| x.updateArSize(macho_file), + }; + } + + pub fn writeAr(file: File, ar_format: Archive.Format, macho_file: *MachO, writer: anytype) !void { + return switch (file) { + .dylib, .internal => unreachable, + .zig_object => |x| x.writeAr(ar_format, writer), + .object => |x| x.writeAr(ar_format, macho_file, writer), + }; + } + pub const Index = u32; pub const Entry = union(enum) { @@ -225,8 +240,10 @@ pub const File = union(enum) { }; const assert = std.debug.assert; +const log = std.log.scoped(.link); const macho = std.macho; const std = @import("std"); +const trace = @import("../../tracy.zig").trace; const Allocator = std.mem.Allocator; const Archive = @import("Archive.zig"); |
