diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2024-02-06 13:56:28 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2024-02-07 19:27:25 +0100 |
| commit | bdbb1dbe1535b727e542c80fe1f7d62a78e527fd (patch) | |
| tree | e314ac9d74ee474d12b233887aae88d8d28212e6 /src | |
| parent | 352e27c55ca32fdc31dd01e3e60893775f03a318 (diff) | |
| download | zig-bdbb1dbe1535b727e542c80fe1f7d62a78e527fd.tar.gz zig-bdbb1dbe1535b727e542c80fe1f7d62a78e527fd.zip | |
macho: refactor markExports, markImportsExports and claimUnresolved
Diffstat (limited to 'src')
| -rw-r--r-- | src/link/MachO.zig | 79 | ||||
| -rw-r--r-- | src/link/MachO/Archive.zig | 29 | ||||
| -rw-r--r-- | src/link/MachO/file.zig | 92 | ||||
| -rw-r--r-- | src/link/MachO/relocatable.zig | 61 |
4 files changed, 151 insertions, 110 deletions
diff --git a/src/link/MachO.zig b/src/link/MachO.zig index d825671b10..9416792bc0 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -379,6 +379,10 @@ pub fn deinit(self: *MachO) void { } pub fn flush(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void { + // TODO: I think this is just a temp and can be removed once we can emit static archives + if (self.base.isStaticLib() and build_options.have_llvm) { + return self.base.linkAsArchive(arena, prog_node); + } try self.flushModule(arena, prog_node); } @@ -391,6 +395,8 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node if (self.llvm_object) |llvm_object| { try self.base.emitLlvmObject(arena, llvm_object, prog_node); + // TODO: I think this is just a temp and can be removed once we can emit static archives + if (self.base.isStaticLib() and build_options.have_llvm) return; } var sub_prog_node = prog_node.start("MachO Flush", 0); @@ -571,7 +577,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node }, }; - try self.markImportsAndExports(); + self.markImportsAndExports(); self.deadStripDylibs(); for (self.dylibs.items, 1..) |index, ord| { @@ -1509,46 +1515,11 @@ fn createObjcSections(self: *MachO) !void { } fn claimUnresolved(self: *MachO) error{OutOfMemory}!void { - const gpa = self.base.comp.gpa; - - var objects = try std.ArrayList(File.Index).initCapacity(gpa, self.objects.items.len + 1); - defer objects.deinit(); - if (self.getZigObject()) |zo| objects.appendAssumeCapacity(zo.index); - objects.appendSliceAssumeCapacity(self.objects.items); - - for (objects.items) |index| { - const file = self.getFile(index).?; - - 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 = self.getSymbol(sym_index); - if (sym.getFile(self) != null) continue; - - const is_import = switch (self.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 = self.internal_object.?; - sym.flags.weak = false; - sym.flags.weak_ref = nlist.weakRef(); - sym.flags.import = is_import; - sym.visibility = .global; - try self.getInternalObject().?.symbols.append(self.base.comp.gpa, sym_index); - } - } + if (self.getZigObject()) |zo| { + try zo.asFile().claimUnresolved(self); + } + for (self.objects.items) |index| { + try self.getFile(index).?.claimUnresolved(self); } } @@ -1574,26 +1545,12 @@ fn checkDuplicates(self: *MachO) !void { try self.reportDuplicates(dupes); } -fn markImportsAndExports(self: *MachO) error{OutOfMemory}!void { - const gpa = self.base.comp.gpa; - var objects = try std.ArrayList(File.Index).initCapacity(gpa, self.objects.items.len + 1); - defer objects.deinit(); - if (self.getZigObject()) |zo| objects.appendAssumeCapacity(zo.index); - objects.appendSliceAssumeCapacity(self.objects.items); - - for (objects.items) |index| { - for (self.getFile(index).?.getSymbols()) |sym_index| { - const sym = self.getSymbol(sym_index); - const file = sym.getFile(self) orelse continue; - if (sym.visibility != .global) continue; - if (file == .dylib and !sym.flags.abs) { - sym.flags.import = true; - continue; - } - if (file.getIndex() == index) { - sym.flags.@"export" = true; - } - } +fn markImportsAndExports(self: *MachO) void { + if (self.getZigObject()) |zo| { + zo.asFile().markImportsExports(self); + } + for (self.objects.items) |index| { + self.getFile(index).?.markImportsExports(self); } for (self.undefined_symbols.items) |index| { diff --git a/src/link/MachO/Archive.zig b/src/link/MachO/Archive.zig index 449fd709d9..a5535345ef 100644 --- a/src/link/MachO/Archive.zig +++ b/src/link/MachO/Archive.zig @@ -144,8 +144,32 @@ pub fn parse(self: *Archive, macho_file: *MachO, path: []const u8, handle_index: } pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void { - _ = comp; - _ = module_obj_path; + const gpa = comp.gpa; + + var positionals = std.ArrayList(Compilation.LinkObject).init(gpa); + defer positionals.deinit(); + + try positionals.ensureUnusedCapacity(comp.objects.len); + positionals.appendSliceAssumeCapacity(comp.objects); + + for (comp.c_object_table.keys()) |key| { + try positionals.append(.{ .path = key.status.success.object_path }); + } + + if (module_obj_path) |path| try positionals.append(.{ .path = path }); + + for (positionals.items) |obj| { + // TODO: parse for archive meaning don't unpack objects + _ = obj; + } + + if (comp.link_errors.items.len > 0) return error.FlushFailure; + + // First, we flush relocatable object file generated with our backends. + if (macho_file.getZigObject()) |zo| { + zo.resolveSymbols(macho_file); + zo.asFile().claimUnresolvedRelocatable(macho_file); + } var err = try macho_file.addErrorWithNotes(0); try err.addMsg(macho_file, "TODO implement flushStaticLib", .{}); @@ -158,6 +182,7 @@ const link = @import("../../link.zig"); const log = std.log.scoped(.link); const macho = std.macho; const mem = std.mem; +const relocatable = @import("relocatable.zig"); const std = @import("std"); const Allocator = mem.Allocator; diff --git a/src/link/MachO/file.zig b/src/link/MachO/file.zig index 20f71d80fe..bfaa90fba5 100644 --- a/src/link/MachO/file.zig +++ b/src/link/MachO/file.zig @@ -44,6 +44,97 @@ pub const File = union(enum) { } } + 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; + } + } + } + /// Encodes symbol rank so that the following ordering applies: /// * strong in object /// * weak in object @@ -110,6 +201,7 @@ pub const File = union(enum) { pub const HandleIndex = Index; }; +const assert = std.debug.assert; const macho = std.macho; const std = @import("std"); diff --git a/src/link/MachO/relocatable.zig b/src/link/MachO/relocatable.zig index 5e9eb9f823..4ecd1026e6 100644 --- a/src/link/MachO/relocatable.zig +++ b/src/link/MachO/relocatable.zig @@ -46,8 +46,8 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u try macho_file.addUndefinedGlobals(); try macho_file.resolveSymbols(); - try markExports(macho_file); - try claimUnresolved(macho_file); + markExports(macho_file); + claimUnresolved(macho_file); try initOutputSections(macho_file); try macho_file.sortSections(); try macho_file.addAtomsToSections(); @@ -86,54 +86,21 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u try writeHeader(macho_file, ncmds, sizeofcmds); } -fn markExports(macho_file: *MachO) error{OutOfMemory}!void { - var objects = try std.ArrayList(File.Index).initCapacity(macho_file.base.comp.gpa, macho_file.objects.items.len + 1); - defer objects.deinit(); - if (macho_file.getZigObject()) |zo| objects.appendAssumeCapacity(zo.index); - objects.appendSliceAssumeCapacity(macho_file.objects.items); - - for (objects.items) |index| { - for (macho_file.getFile(index).?.getSymbols()) |sym_index| { - const sym = macho_file.getSymbol(sym_index); - const file = sym.getFile(macho_file) orelse continue; - if (sym.visibility != .global) continue; - if (file.getIndex() == index) { - sym.flags.@"export" = true; - } - } +fn markExports(macho_file: *MachO) void { + if (macho_file.getZigObject()) |zo| { + zo.asFile().markExportsRelocatable(macho_file); + } + for (macho_file.objects.items) |index| { + macho_file.getFile(index).?.markExportsRelocatable(macho_file); } } -fn claimUnresolved(macho_file: *MachO) error{OutOfMemory}!void { - var objects = try std.ArrayList(File.Index).initCapacity(macho_file.base.comp.gpa, macho_file.objects.items.len + 1); - defer objects.deinit(); - if (macho_file.getZigObject()) |zo| objects.appendAssumeCapacity(zo.index); - objects.appendSliceAssumeCapacity(macho_file.objects.items); - - for (objects.items) |index| { - const file = macho_file.getFile(index).?; - - 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 = index; - sym.flags.weak_ref = nlist.weakRef(); - sym.flags.import = true; - sym.visibility = .global; - } +pub fn claimUnresolved(macho_file: *MachO) void { + if (macho_file.getZigObject()) |zo| { + zo.asFile().claimUnresolvedRelocatable(macho_file); + } + for (macho_file.objects.items) |index| { + macho_file.getFile(index).?.claimUnresolvedRelocatable(macho_file); } } |
