| 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,6 +379,10 @@ pub fn deinit(self: *MachO) void { |
| 379 | } | 379 | } |
| 380 | 380 | ||
| 381 | pub fn flush(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node) link.File.FlushError!void { | 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 | try self.flushModule(arena, prog_node); | 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,6 +395,8 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node |
| 391 | 395 | ||
| 392 | if (self.llvm_object) |llvm_object| { | 396 | if (self.llvm_object) |llvm_object| { |
| 393 | try self.base.emitLlvmObject(arena, llvm_object, prog_node); | 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 | var sub_prog_node = prog_node.start("MachO Flush", 0); | 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,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 | self.deadStripDylibs(); | 581 | self.deadStripDylibs(); |
| 576 | 582 | ||
| 577 | for (self.dylibs.items, 1..) |index, ord| { | 583 | for (self.dylibs.items, 1..) |index, ord| { |
| ... | @@ -1509,46 +1515,11 @@ fn createObjcSections(self: *MachO) !void { | ... | @@ -1509,46 +1515,11 @@ fn createObjcSections(self: *MachO) !void { |
| 1509 | } | 1515 | } |
| 1510 | 1516 | ||
| 1511 | fn claimUnresolved(self: *MachO) error{OutOfMemory}!void { | 1517 | fn claimUnresolved(self: *MachO) error{OutOfMemory}!void { |
| 1512 | const gpa = self.base.comp.gpa; | 1518 | if (self.getZigObject()) |zo| { |
| 1513 | 1519 | try zo.asFile().claimUnresolved(self); | |
| 1514 | var objects = try std.ArrayList(File.Index).initCapacity(gpa, self.objects.items.len + 1); | 1520 | } |
| 1515 | defer objects.deinit(); | 1521 | for (self.objects.items) |index| { |
| 1516 | if (self.getZigObject()) |zo| objects.appendAssumeCapacity(zo.index); | 1522 | try self.getFile(index).?.claimUnresolved(self); |
| 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 | } | ||
| 1552 | } | 1523 | } |
| 1553 | } | 1524 | } |
| 1554 | 1525 | ||
| ... | @@ -1574,26 +1545,12 @@ fn checkDuplicates(self: *MachO) !void { | ... | @@ -1574,26 +1545,12 @@ fn checkDuplicates(self: *MachO) !void { |
| 1574 | try self.reportDuplicates(dupes); | 1545 | try self.reportDuplicates(dupes); |
| 1575 | } | 1546 | } |
| 1576 | 1547 | ||
| 1577 | fn markImportsAndExports(self: *MachO) error{OutOfMemory}!void { | 1548 | fn markImportsAndExports(self: *MachO) void { |
| 1578 | const gpa = self.base.comp.gpa; | 1549 | if (self.getZigObject()) |zo| { |
| 1579 | var objects = try std.ArrayList(File.Index).initCapacity(gpa, self.objects.items.len + 1); | 1550 | zo.asFile().markImportsExports(self); |
| 1580 | defer objects.deinit(); | 1551 | } |
| 1581 | if (self.getZigObject()) |zo| objects.appendAssumeCapacity(zo.index); | 1552 | for (self.objects.items) |index| { |
| 1582 | objects.appendSliceAssumeCapacity(self.objects.items); | 1553 | self.getFile(index).?.markImportsExports(self); |
| 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 | } | ||
| 1597 | } | 1554 | } |
| 1598 | 1555 | ||
| 1599 | for (self.undefined_symbols.items) |index| { | 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,8 +144,32 @@ pub fn parse(self: *Archive, macho_file: *MachO, path: []const u8, handle_index: |
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void { | 146 | pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u8) link.File.FlushError!void { |
| 147 | _ = comp; | 147 | const gpa = comp.gpa; |
| 148 | _ = module_obj_path; | 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 | var err = try macho_file.addErrorWithNotes(0); | 174 | var err = try macho_file.addErrorWithNotes(0); |
| 151 | try err.addMsg(macho_file, "TODO implement flushStaticLib", .{}); | 175 | try err.addMsg(macho_file, "TODO implement flushStaticLib", .{}); |
| ... | @@ -158,6 +182,7 @@ const link = @import("../../link.zig"); | ... | @@ -158,6 +182,7 @@ const link = @import("../../link.zig"); |
| 158 | const log = std.log.scoped(.link); | 182 | const log = std.log.scoped(.link); |
| 159 | const macho = std.macho; | 183 | const macho = std.macho; |
| 160 | const mem = std.mem; | 184 | const mem = std.mem; |
| 185 | const relocatable = @import("relocatable.zig"); | ||
| 161 | const std = @import("std"); | 186 | const std = @import("std"); |
| 162 | 187 | ||
| 163 | const Allocator = mem.Allocator; | 188 | const Allocator = mem.Allocator; |
src/link/MachO/file.zig+92| ... | @@ -44,6 +44,97 @@ pub const File = union(enum) { | ... | @@ -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 | /// Encodes symbol rank so that the following ordering applies: | 138 | /// Encodes symbol rank so that the following ordering applies: |
| 48 | /// * strong in object | 139 | /// * strong in object |
| 49 | /// * weak in object | 140 | /// * weak in object |
| ... | @@ -110,6 +201,7 @@ pub const File = union(enum) { | ... | @@ -110,6 +201,7 @@ pub const File = union(enum) { |
| 110 | pub const HandleIndex = Index; | 201 | pub const HandleIndex = Index; |
| 111 | }; | 202 | }; |
| 112 | 203 | ||
| 204 | const assert = std.debug.assert; | ||
| 113 | const macho = std.macho; | 205 | const macho = std.macho; |
| 114 | const std = @import("std"); | 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,8 +46,8 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u |
| 46 | 46 | ||
| 47 | try macho_file.addUndefinedGlobals(); | 47 | try macho_file.addUndefinedGlobals(); |
| 48 | try macho_file.resolveSymbols(); | 48 | try macho_file.resolveSymbols(); |
| 49 | try markExports(macho_file); | 49 | markExports(macho_file); |
| 50 | try claimUnresolved(macho_file); | 50 | claimUnresolved(macho_file); |
| 51 | try initOutputSections(macho_file); | 51 | try initOutputSections(macho_file); |
| 52 | try macho_file.sortSections(); | 52 | try macho_file.sortSections(); |
| 53 | try macho_file.addAtomsToSections(); | 53 | try macho_file.addAtomsToSections(); |
| ... | @@ -86,54 +86,21 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u | ... | @@ -86,54 +86,21 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u |
| 86 | try writeHeader(macho_file, ncmds, sizeofcmds); | 86 | try writeHeader(macho_file, ncmds, sizeofcmds); |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | fn markExports(macho_file: *MachO) error{OutOfMemory}!void { | 89 | fn markExports(macho_file: *MachO) void { |
| 90 | var objects = try std.ArrayList(File.Index).initCapacity(macho_file.base.comp.gpa, macho_file.objects.items.len + 1); | 90 | if (macho_file.getZigObject()) |zo| { |
| 91 | defer objects.deinit(); | 91 | zo.asFile().markExportsRelocatable(macho_file); |
| 92 | if (macho_file.getZigObject()) |zo| objects.appendAssumeCapacity(zo.index); | 92 | } |
| 93 | objects.appendSliceAssumeCapacity(macho_file.objects.items); | 93 | for (macho_file.objects.items) |index| { |
| 94 | 94 | macho_file.getFile(index).?.markExportsRelocatable(macho_file); | |
| 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 | } | ||
| 104 | } | 95 | } |
| 105 | } | 96 | } |
| 106 | 97 | ||
| 107 | fn claimUnresolved(macho_file: *MachO) error{OutOfMemory}!void { | 98 | pub fn claimUnresolved(macho_file: *MachO) void { |
| 108 | var objects = try std.ArrayList(File.Index).initCapacity(macho_file.base.comp.gpa, macho_file.objects.items.len + 1); | 99 | if (macho_file.getZigObject()) |zo| { |
| 109 | defer objects.deinit(); | 100 | zo.asFile().claimUnresolvedRelocatable(macho_file); |
| 110 | if (macho_file.getZigObject()) |zo| objects.appendAssumeCapacity(zo.index); | 101 | } |
| 111 | objects.appendSliceAssumeCapacity(macho_file.objects.items); | 102 | for (macho_file.objects.items) |index| { |
| 112 | 103 | macho_file.getFile(index).?.claimUnresolvedRelocatable(macho_file); | |
| 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 | } | ||
| 137 | } | 104 | } |
| 138 | } | 105 | } |
| 139 | 106 |