| author | |
| committer | |
| log | bdbb1dbe1535b727e542c80fe1f7d62a78e527fd |
| tree | e314ac9d74ee474d12b233887aae88d8d28212e6 |
| parent | 352e27c55ca32fdc31dd01e3e60893775f03a318 |
4 files changed, 151 insertions(+), 110 deletions(-)
src/link/MachO.zig+18-61| ... | ... | @@ -379,6 +379,10 @@ pub fn deinit(self: *MachO) void { |
| 379 | 379 | } |
| 380 | 380 | |
| 381 | 381 | pub fn flush(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void { |
| 382 | // TODO: I think this is just a temp and can be removed once we can emit static archives | |
| 383 | if (self.base.isStaticLib() and build_options.have_llvm) { | |
| 384 | return self.base.linkAsArchive(arena, prog_node); | |
| 385 | } | |
| 382 | 386 | try self.flushModule(arena, prog_node); |
| 383 | 387 | } |
| 384 | 388 | |
| ... | ... | @@ -391,6 +395,8 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node |
| 391 | 395 | |
| 392 | 396 | if (self.llvm_object) |llvm_object| { |
| 393 | 397 | try self.base.emitLlvmObject(arena, llvm_object, prog_node); |
| 398 | // TODO: I think this is just a temp and can be removed once we can emit static archives | |
| 399 | if (self.base.isStaticLib() and build_options.have_llvm) return; | |
| 394 | 400 | } |
| 395 | 401 | |
| 396 | 402 | 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 |
| 571 | 577 | }, |
| 572 | 578 | }; |
| 573 | 579 | |
| 574 | try self.markImportsAndExports(); | |
| 580 | self.markImportsAndExports(); | |
| 575 | 581 | self.deadStripDylibs(); |
| 576 | 582 | |
| 577 | 583 | for (self.dylibs.items, 1..) |index, ord| { |
| ... | ... | @@ -1509,46 +1515,11 @@ fn createObjcSections(self: *MachO) !void { |
| 1509 | 1515 | } |
| 1510 | 1516 | |
| 1511 | 1517 | fn claimUnresolved(self: *MachO) error{OutOfMemory}!void { |
| 1512 | const gpa = self.base.comp.gpa; | |
| 1513 | ||
| 1514 | var objects = try std.ArrayList(File.Index).initCapacity(gpa, self.objects.items.len + 1); | |
| 1515 | defer objects.deinit(); | |
| 1516 | if (self.getZigObject()) |zo| objects.appendAssumeCapacity(zo.index); | |
| 1517 | objects.appendSliceAssumeCapacity(self.objects.items); | |
| 1518 | ||
| 1519 | for (objects.items) |index| { | |
| 1520 | const file = self.getFile(index).?; | |
| 1521 | ||
| 1522 | for (file.getSymbols(), 0..) |sym_index, i| { | |
| 1523 | const nlist_idx = @as(Symbol.Index, @intCast(i)); | |
| 1524 | const nlist = switch (file) { | |
| 1525 | .object => |x| x.symtab.items(.nlist)[nlist_idx], | |
| 1526 | .zig_object => |x| x.symtab.items(.nlist)[nlist_idx], | |
| 1527 | else => unreachable, | |
| 1528 | }; | |
| 1529 | if (!nlist.ext()) continue; | |
| 1530 | if (!nlist.undf()) continue; | |
| 1531 | ||
| 1532 | const sym = self.getSymbol(sym_index); | |
| 1533 | if (sym.getFile(self) != null) continue; | |
| 1534 | ||
| 1535 | const is_import = switch (self.undefined_treatment) { | |
| 1536 | .@"error" => false, | |
| 1537 | .warn, .suppress => nlist.weakRef(), | |
| 1538 | .dynamic_lookup => true, | |
| 1539 | }; | |
| 1540 | if (is_import) { | |
| 1541 | sym.value = 0; | |
| 1542 | sym.atom = 0; | |
| 1543 | sym.nlist_idx = 0; | |
| 1544 | sym.file = self.internal_object.?; | |
| 1545 | sym.flags.weak = false; | |
| 1546 | sym.flags.weak_ref = nlist.weakRef(); | |
| 1547 | sym.flags.import = is_import; | |
| 1548 | sym.visibility = .global; | |
| 1549 | try self.getInternalObject().?.symbols.append(self.base.comp.gpa, sym_index); | |
| 1550 | } | |
| 1551 | } | |
| 1518 | if (self.getZigObject()) |zo| { | |
| 1519 | try zo.asFile().claimUnresolved(self); | |
| 1520 | } | |
| 1521 | for (self.objects.items) |index| { | |
| 1522 | try self.getFile(index).?.claimUnresolved(self); | |
| 1552 | 1523 | } |
| 1553 | 1524 | } |
| 1554 | 1525 | |
| ... | ... | @@ -1574,26 +1545,12 @@ fn checkDuplicates(self: *MachO) !void { |
| 1574 | 1545 | try self.reportDuplicates(dupes); |
| 1575 | 1546 | } |
| 1576 | 1547 | |
| 1577 | fn markImportsAndExports(self: *MachO) error{OutOfMemory}!void { | |
| 1578 | const gpa = self.base.comp.gpa; | |
| 1579 | var objects = try std.ArrayList(File.Index).initCapacity(gpa, self.objects.items.len + 1); | |
| 1580 | defer objects.deinit(); | |
| 1581 | if (self.getZigObject()) |zo| objects.appendAssumeCapacity(zo.index); | |
| 1582 | objects.appendSliceAssumeCapacity(self.objects.items); | |
| 1583 | ||
| 1584 | for (objects.items) |index| { | |
| 1585 | for (self.getFile(index).?.getSymbols()) |sym_index| { | |
| 1586 | const sym = self.getSymbol(sym_index); | |
| 1587 | const file = sym.getFile(self) orelse continue; | |
| 1588 | if (sym.visibility != .global) continue; | |
| 1589 | if (file == .dylib and !sym.flags.abs) { | |
| 1590 | sym.flags.import = true; | |
| 1591 | continue; | |
| 1592 | } | |
| 1593 | if (file.getIndex() == index) { | |
| 1594 | sym.flags.@"export" = true; | |
| 1595 | } | |
| 1596 | } | |
| 1548 | fn markImportsAndExports(self: *MachO) void { | |
| 1549 | if (self.getZigObject()) |zo| { | |
| 1550 | zo.asFile().markImportsExports(self); | |
| 1551 | } | |
| 1552 | for (self.objects.items) |index| { | |
| 1553 | self.getFile(index).?.markImportsExports(self); | |
| 1597 | 1554 | } |
| 1598 | 1555 | |
| 1599 | 1556 | for (self.undefined_symbols.items) |index| { |
src/link/MachO/Archive.zig+27-2| ... | ... | @@ -144,8 +144,32 @@ pub fn parse(self: *Archive, macho_file: *MachO, path: []const u8, handle_index: |
| 144 | 144 | } |
| 145 | 145 | |
| 146 | 146 | pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void { |
| 147 | _ = comp; | |
| 148 | _ = module_obj_path; | |
| 147 | const gpa = comp.gpa; | |
| 148 | ||
| 149 | var positionals = std.ArrayList(Compilation.LinkObject).init(gpa); | |
| 150 | defer positionals.deinit(); | |
| 151 | ||
| 152 | try positionals.ensureUnusedCapacity(comp.objects.len); | |
| 153 | positionals.appendSliceAssumeCapacity(comp.objects); | |
| 154 | ||
| 155 | for (comp.c_object_table.keys()) |key| { | |
| 156 | try positionals.append(.{ .path = key.status.success.object_path }); | |
| 157 | } | |
| 158 | ||
| 159 | if (module_obj_path) |path| try positionals.append(.{ .path = path }); | |
| 160 | ||
| 161 | for (positionals.items) |obj| { | |
| 162 | // TODO: parse for archive meaning don't unpack objects | |
| 163 | _ = obj; | |
| 164 | } | |
| 165 | ||
| 166 | if (comp.link_errors.items.len > 0) return error.FlushFailure; | |
| 167 | ||
| 168 | // First, we flush relocatable object file generated with our backends. | |
| 169 | if (macho_file.getZigObject()) |zo| { | |
| 170 | zo.resolveSymbols(macho_file); | |
| 171 | zo.asFile().claimUnresolvedRelocatable(macho_file); | |
| 172 | } | |
| 149 | 173 | |
| 150 | 174 | var err = try macho_file.addErrorWithNotes(0); |
| 151 | 175 | try err.addMsg(macho_file, "TODO implement flushStaticLib", .{}); |
| ... | ... | @@ -158,6 +182,7 @@ const link = @import("../../link.zig"); |
| 158 | 182 | const log = std.log.scoped(.link); |
| 159 | 183 | const macho = std.macho; |
| 160 | 184 | const mem = std.mem; |
| 185 | const relocatable = @import("relocatable.zig"); | |
| 161 | 186 | const std = @import("std"); |
| 162 | 187 | |
| 163 | 188 | const Allocator = mem.Allocator; |
src/link/MachO/file.zig+92| ... | ... | @@ -44,6 +44,97 @@ pub const File = union(enum) { |
| 44 | 44 | } |
| 45 | 45 | } |
| 46 | 46 | |
| 47 | pub fn claimUnresolved(file: File, macho_file: *MachO) error{OutOfMemory}!void { | |
| 48 | assert(file == .object or file == .zig_object); | |
| 49 | ||
| 50 | for (file.getSymbols(), 0..) |sym_index, i| { | |
| 51 | const nlist_idx = @as(Symbol.Index, @intCast(i)); | |
| 52 | const nlist = switch (file) { | |
| 53 | .object => |x| x.symtab.items(.nlist)[nlist_idx], | |
| 54 | .zig_object => |x| x.symtab.items(.nlist)[nlist_idx], | |
| 55 | else => unreachable, | |
| 56 | }; | |
| 57 | if (!nlist.ext()) continue; | |
| 58 | if (!nlist.undf()) continue; | |
| 59 | ||
| 60 | const sym = macho_file.getSymbol(sym_index); | |
| 61 | if (sym.getFile(macho_file) != null) continue; | |
| 62 | ||
| 63 | const is_import = switch (macho_file.undefined_treatment) { | |
| 64 | .@"error" => false, | |
| 65 | .warn, .suppress => nlist.weakRef(), | |
| 66 | .dynamic_lookup => true, | |
| 67 | }; | |
| 68 | if (is_import) { | |
| 69 | sym.value = 0; | |
| 70 | sym.atom = 0; | |
| 71 | sym.nlist_idx = 0; | |
| 72 | sym.file = macho_file.internal_object.?; | |
| 73 | sym.flags.weak = false; | |
| 74 | sym.flags.weak_ref = nlist.weakRef(); | |
| 75 | sym.flags.import = is_import; | |
| 76 | sym.visibility = .global; | |
| 77 | try macho_file.getInternalObject().?.symbols.append(macho_file.base.comp.gpa, sym_index); | |
| 78 | } | |
| 79 | } | |
| 80 | } | |
| 81 | ||
| 82 | pub fn claimUnresolvedRelocatable(file: File, macho_file: *MachO) void { | |
| 83 | assert(file == .object or file == .zig_object); | |
| 84 | ||
| 85 | for (file.getSymbols(), 0..) |sym_index, i| { | |
| 86 | const nlist_idx = @as(Symbol.Index, @intCast(i)); | |
| 87 | const nlist = switch (file) { | |
| 88 | .object => |x| x.symtab.items(.nlist)[nlist_idx], | |
| 89 | .zig_object => |x| x.symtab.items(.nlist)[nlist_idx], | |
| 90 | else => unreachable, | |
| 91 | }; | |
| 92 | if (!nlist.ext()) continue; | |
| 93 | if (!nlist.undf()) continue; | |
| 94 | ||
| 95 | const sym = macho_file.getSymbol(sym_index); | |
| 96 | if (sym.getFile(macho_file) != null) continue; | |
| 97 | ||
| 98 | sym.value = 0; | |
| 99 | sym.atom = 0; | |
| 100 | sym.nlist_idx = nlist_idx; | |
| 101 | sym.file = file.getIndex(); | |
| 102 | sym.flags.weak_ref = nlist.weakRef(); | |
| 103 | sym.flags.import = true; | |
| 104 | sym.visibility = .global; | |
| 105 | } | |
| 106 | } | |
| 107 | ||
| 108 | pub fn markImportsExports(file: File, macho_file: *MachO) void { | |
| 109 | assert(file == .object or file == .zig_object); | |
| 110 | ||
| 111 | for (file.getSymbols()) |sym_index| { | |
| 112 | const sym = macho_file.getSymbol(sym_index); | |
| 113 | const other_file = sym.getFile(macho_file) orelse continue; | |
| 114 | if (sym.visibility != .global) continue; | |
| 115 | if (other_file == .dylib and !sym.flags.abs) { | |
| 116 | sym.flags.import = true; | |
| 117 | continue; | |
| 118 | } | |
| 119 | if (other_file.getIndex() == file.getIndex()) { | |
| 120 | sym.flags.@"export" = true; | |
| 121 | } | |
| 122 | } | |
| 123 | } | |
| 124 | ||
| 125 | pub fn markExportsRelocatable(file: File, macho_file: *MachO) void { | |
| 126 | assert(file == .object or file == .zig_object); | |
| 127 | ||
| 128 | for (file.getSymbols()) |sym_index| { | |
| 129 | const sym = macho_file.getSymbol(sym_index); | |
| 130 | const other_file = sym.getFile(macho_file) orelse continue; | |
| 131 | if (sym.visibility != .global) continue; | |
| 132 | if (other_file.getIndex() == file.getIndex()) { | |
| 133 | sym.flags.@"export" = true; | |
| 134 | } | |
| 135 | } | |
| 136 | } | |
| 137 | ||
| 47 | 138 | /// Encodes symbol rank so that the following ordering applies: |
| 48 | 139 | /// * strong in object |
| 49 | 140 | /// * weak in object |
| ... | ... | @@ -110,6 +201,7 @@ pub const File = union(enum) { |
| 110 | 201 | pub const HandleIndex = Index; |
| 111 | 202 | }; |
| 112 | 203 | |
| 204 | const assert = std.debug.assert; | |
| 113 | 205 | const macho = std.macho; |
| 114 | 206 | const std = @import("std"); |
| 115 | 207 |
src/link/MachO/relocatable.zig+14-47| ... | ... | @@ -46,8 +46,8 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u |
| 46 | 46 | |
| 47 | 47 | try macho_file.addUndefinedGlobals(); |
| 48 | 48 | try macho_file.resolveSymbols(); |
| 49 | try markExports(macho_file); | |
| 50 | try claimUnresolved(macho_file); | |
| 49 | markExports(macho_file); | |
| 50 | claimUnresolved(macho_file); | |
| 51 | 51 | try initOutputSections(macho_file); |
| 52 | 52 | try macho_file.sortSections(); |
| 53 | 53 | try macho_file.addAtomsToSections(); |
| ... | ... | @@ -86,54 +86,21 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u |
| 86 | 86 | try writeHeader(macho_file, ncmds, sizeofcmds); |
| 87 | 87 | } |
| 88 | 88 | |
| 89 | fn markExports(macho_file: *MachO) error{OutOfMemory}!void { | |
| 90 | var objects = try std.ArrayList(File.Index).initCapacity(macho_file.base.comp.gpa, macho_file.objects.items.len + 1); | |
| 91 | defer objects.deinit(); | |
| 92 | if (macho_file.getZigObject()) |zo| objects.appendAssumeCapacity(zo.index); | |
| 93 | objects.appendSliceAssumeCapacity(macho_file.objects.items); | |
| 94 | ||
| 95 | for (objects.items) |index| { | |
| 96 | for (macho_file.getFile(index).?.getSymbols()) |sym_index| { | |
| 97 | const sym = macho_file.getSymbol(sym_index); | |
| 98 | const file = sym.getFile(macho_file) orelse continue; | |
| 99 | if (sym.visibility != .global) continue; | |
| 100 | if (file.getIndex() == index) { | |
| 101 | sym.flags.@"export" = true; | |
| 102 | } | |
| 103 | } | |
| 89 | fn markExports(macho_file: *MachO) void { | |
| 90 | if (macho_file.getZigObject()) |zo| { | |
| 91 | zo.asFile().markExportsRelocatable(macho_file); | |
| 92 | } | |
| 93 | for (macho_file.objects.items) |index| { | |
| 94 | macho_file.getFile(index).?.markExportsRelocatable(macho_file); | |
| 104 | 95 | } |
| 105 | 96 | } |
| 106 | 97 | |
| 107 | fn claimUnresolved(macho_file: *MachO) error{OutOfMemory}!void { | |
| 108 | var objects = try std.ArrayList(File.Index).initCapacity(macho_file.base.comp.gpa, macho_file.objects.items.len + 1); | |
| 109 | defer objects.deinit(); | |
| 110 | if (macho_file.getZigObject()) |zo| objects.appendAssumeCapacity(zo.index); | |
| 111 | objects.appendSliceAssumeCapacity(macho_file.objects.items); | |
| 112 | ||
| 113 | for (objects.items) |index| { | |
| 114 | const file = macho_file.getFile(index).?; | |
| 115 | ||
| 116 | for (file.getSymbols(), 0..) |sym_index, i| { | |
| 117 | const nlist_idx = @as(Symbol.Index, @intCast(i)); | |
| 118 | const nlist = switch (file) { | |
| 119 | .object => |x| x.symtab.items(.nlist)[nlist_idx], | |
| 120 | .zig_object => |x| x.symtab.items(.nlist)[nlist_idx], | |
| 121 | else => unreachable, | |
| 122 | }; | |
| 123 | if (!nlist.ext()) continue; | |
| 124 | if (!nlist.undf()) continue; | |
| 125 | ||
| 126 | const sym = macho_file.getSymbol(sym_index); | |
| 127 | if (sym.getFile(macho_file) != null) continue; | |
| 128 | ||
| 129 | sym.value = 0; | |
| 130 | sym.atom = 0; | |
| 131 | sym.nlist_idx = nlist_idx; | |
| 132 | sym.file = index; | |
| 133 | sym.flags.weak_ref = nlist.weakRef(); | |
| 134 | sym.flags.import = true; | |
| 135 | sym.visibility = .global; | |
| 136 | } | |
| 98 | pub fn claimUnresolved(macho_file: *MachO) void { | |
| 99 | if (macho_file.getZigObject()) |zo| { | |
| 100 | zo.asFile().claimUnresolvedRelocatable(macho_file); | |
| 101 | } | |
| 102 | for (macho_file.objects.items) |index| { | |
| 103 | macho_file.getFile(index).?.claimUnresolvedRelocatable(macho_file); | |
| 137 | 104 | } |
| 138 | 105 | } |
| 139 | 106 |