| ... | @@ -497,6 +497,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node | ... | @@ -497,6 +497,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node |
| 497 | } | 497 | } |
| 498 | | 498 | |
| 499 | try self.addUndefinedGlobals(); | 499 | try self.addUndefinedGlobals(); |
| | 500 | try self.resolveSymbols(); |
| 500 | | 501 | |
| 501 | state_log.debug("{}", .{self.dumpState()}); | 502 | state_log.debug("{}", .{self.dumpState()}); |
| 502 | | 503 | |
| ... | @@ -1157,6 +1158,63 @@ fn addUndefinedGlobals(self: *MachO) !void { | ... | @@ -1157,6 +1158,63 @@ fn addUndefinedGlobals(self: *MachO) !void { |
| 1157 | } | 1158 | } |
| 1158 | } | 1159 | } |
| 1159 | | 1160 | |
| | 1161 | /// When resolving symbols, we approach the problem similarly to `mold`. |
| | 1162 | /// 1. Resolve symbols across all objects (including those preemptively extracted archives). |
| | 1163 | /// 2. Resolve symbols across all shared objects. |
| | 1164 | /// 3. Mark live objects (see `MachO.markLive`) |
| | 1165 | /// 4. Reset state of all resolved globals since we will redo this bit on the pruned set. |
| | 1166 | /// 5. Remove references to dead objects/shared objects |
| | 1167 | /// 6. Re-run symbol resolution on pruned objects and shared objects sets. |
| | 1168 | pub fn resolveSymbols(self: *MachO) !void { |
| | 1169 | const tracy = trace(@src()); |
| | 1170 | defer tracy.end(); |
| | 1171 | |
| | 1172 | // Resolve symbols on the set of all objects and shared objects (even if some are unneeded). |
| | 1173 | for (self.objects.items) |index| self.getFile(index).?.resolveSymbols(self); |
| | 1174 | for (self.dylibs.items) |index| self.getFile(index).?.resolveSymbols(self); |
| | 1175 | |
| | 1176 | // Mark live objects. |
| | 1177 | self.markLive(); |
| | 1178 | |
| | 1179 | // Reset state of all globals after marking live objects. |
| | 1180 | for (self.objects.items) |index| self.getFile(index).?.resetGlobals(self); |
| | 1181 | for (self.dylibs.items) |index| self.getFile(index).?.resetGlobals(self); |
| | 1182 | |
| | 1183 | // Prune dead objects. |
| | 1184 | var i: usize = 0; |
| | 1185 | while (i < self.objects.items.len) { |
| | 1186 | const index = self.objects.items[i]; |
| | 1187 | if (!self.getFile(index).?.object.alive) { |
| | 1188 | _ = self.objects.orderedRemove(i); |
| | 1189 | } else i += 1; |
| | 1190 | } |
| | 1191 | |
| | 1192 | // Re-resolve the symbols. |
| | 1193 | for (self.objects.items) |index| self.getFile(index).?.resolveSymbols(self); |
| | 1194 | for (self.dylibs.items) |index| self.getFile(index).?.resolveSymbols(self); |
| | 1195 | } |
| | 1196 | |
| | 1197 | fn markLive(self: *MachO) void { |
| | 1198 | const tracy = trace(@src()); |
| | 1199 | defer tracy.end(); |
| | 1200 | |
| | 1201 | for (self.undefined_symbols.items) |index| { |
| | 1202 | if (self.getSymbol(index).getFile(self)) |file| { |
| | 1203 | if (file == .object) file.object.alive = true; |
| | 1204 | } |
| | 1205 | } |
| | 1206 | if (self.entry_index) |index| { |
| | 1207 | const sym = self.getSymbol(index); |
| | 1208 | if (sym.getFile(self)) |file| { |
| | 1209 | if (file == .object) file.object.alive = true; |
| | 1210 | } |
| | 1211 | } |
| | 1212 | for (self.objects.items) |index| { |
| | 1213 | const object = self.getFile(index).?.object; |
| | 1214 | if (object.alive) object.markLive(self); |
| | 1215 | } |
| | 1216 | } |
| | 1217 | |
| 1160 | fn shrinkAtom(self: *MachO, atom_index: Atom.Index, new_block_size: u64) void { | 1218 | fn shrinkAtom(self: *MachO, atom_index: Atom.Index, new_block_size: u64) void { |
| 1161 | _ = self; | 1219 | _ = self; |
| 1162 | _ = atom_index; | 1220 | _ = atom_index; |
| ... | @@ -1791,18 +1849,18 @@ fn fmtDumpState( | ... | @@ -1791,18 +1849,18 @@ fn fmtDumpState( |
| 1791 | object.fmtSymtab(self), | 1849 | object.fmtSymtab(self), |
| 1792 | }); | 1850 | }); |
| 1793 | } | 1851 | } |
| 1794 | // for (self.dylibs.items) |index| { | 1852 | for (self.dylibs.items) |index| { |
| 1795 | // const dylib = self.getFile(index).?.dylib; | 1853 | const dylib = self.getFile(index).?.dylib; |
| 1796 | // try writer.print("dylib({d}) : {s} : needed({}) : weak({})", .{ | 1854 | try writer.print("dylib({d}) : {s} : needed({}) : weak({})", .{ |
| 1797 | // index, | 1855 | index, |
| 1798 | // dylib.path, | 1856 | dylib.path, |
| 1799 | // dylib.needed, | 1857 | dylib.needed, |
| 1800 | // dylib.weak, | 1858 | dylib.weak, |
| 1801 | // }); | 1859 | }); |
| 1802 | // if (!dylib.isAlive(self)) try writer.writeAll(" : ([*])"); | 1860 | if (!dylib.isAlive(self)) try writer.writeAll(" : ([*])"); |
| 1803 | // try writer.writeByte('\n'); | 1861 | try writer.writeByte('\n'); |
| 1804 | // try writer.print("{}\n", .{dylib.fmtSymtab(self)}); | 1862 | try writer.print("{}\n", .{dylib.fmtSymtab(self)}); |
| 1805 | // } | 1863 | } |
| 1806 | if (self.getInternalObject()) |internal| { | 1864 | if (self.getInternalObject()) |internal| { |
| 1807 | try writer.print("internal({d}) : internal\n", .{internal.index}); | 1865 | try writer.print("internal({d}) : internal\n", .{internal.index}); |
| 1808 | try writer.print("{}{}\n", .{ internal.fmtAtoms(self), internal.fmtSymtab(self) }); | 1866 | try writer.print("{}{}\n", .{ internal.fmtAtoms(self), internal.fmtSymtab(self) }); |