| ... | @@ -104,7 +104,6 @@ objc_data_section_index: ?u16 = null, | ... | @@ -104,7 +104,6 @@ objc_data_section_index: ?u16 = null, |
| 104 | | 104 | |
| 105 | locals: std.ArrayListUnmanaged(*Symbol) = .{}, | 105 | locals: std.ArrayListUnmanaged(*Symbol) = .{}, |
| 106 | globals: std.StringArrayHashMapUnmanaged(*Symbol) = .{}, | 106 | globals: std.StringArrayHashMapUnmanaged(*Symbol) = .{}, |
| 107 | imports: std.StringArrayHashMapUnmanaged(*Symbol) = .{}, | | |
| 108 | | 107 | |
| 109 | /// Offset into __DATA,__common section. | 108 | /// Offset into __DATA,__common section. |
| 110 | /// Set if the linker found tentative definitions in any of the objects. | 109 | /// Set if the linker found tentative definitions in any of the objects. |
| ... | @@ -172,12 +171,6 @@ pub fn deinit(self: *Zld) void { | ... | @@ -172,12 +171,6 @@ pub fn deinit(self: *Zld) void { |
| 172 | } | 171 | } |
| 173 | self.dylibs.deinit(self.allocator); | 172 | self.dylibs.deinit(self.allocator); |
| 174 | | 173 | |
| 175 | for (self.imports.values()) |sym| { | | |
| 176 | sym.deinit(self.allocator); | | |
| 177 | self.allocator.destroy(sym); | | |
| 178 | } | | |
| 179 | self.imports.deinit(self.allocator); | | |
| 180 | | | |
| 181 | for (self.globals.values()) |sym| { | 174 | for (self.globals.values()) |sym| { |
| 182 | sym.deinit(self.allocator); | 175 | sym.deinit(self.allocator); |
| 183 | self.allocator.destroy(sym); | 176 | self.allocator.destroy(sym); |
| ... | @@ -1570,6 +1563,95 @@ fn resolveSymbols(self: *Zld) !void { | ... | @@ -1570,6 +1563,95 @@ fn resolveSymbols(self: *Zld) !void { |
| 1570 | try self.resolveSymbolsInObject(object); | 1563 | try self.resolveSymbolsInObject(object); |
| 1571 | } | 1564 | } |
| 1572 | | 1565 | |
| | 1566 | // Second pass, resolve symbols in static libraries. |
| | 1567 | var sym_it = self.globals.iterator(); |
| | 1568 | while (sym_it.next()) |entry| { |
| | 1569 | const symbol = entry.value_ptr.*; |
| | 1570 | if (symbol.payload != .undef) continue; |
| | 1571 | |
| | 1572 | for (self.archives.items) |archive| { |
| | 1573 | // Check if the entry exists in a static archive. |
| | 1574 | const offsets = archive.toc.get(symbol.name) orelse { |
| | 1575 | // No hit. |
| | 1576 | continue; |
| | 1577 | }; |
| | 1578 | assert(offsets.items.len > 0); |
| | 1579 | |
| | 1580 | const object = try archive.parseObject(offsets.items[0]); |
| | 1581 | try self.objects.append(self.allocator, object); |
| | 1582 | try self.resolveSymbolsInObject(object); |
| | 1583 | |
| | 1584 | sym_it = self.globals.iterator(); |
| | 1585 | break; |
| | 1586 | } |
| | 1587 | } |
| | 1588 | |
| | 1589 | // Third pass, resolve symbols in dynamic libraries. |
| | 1590 | { |
| | 1591 | // Put dyld_stub_binder as an undefined special symbol. |
| | 1592 | const symbol = try Symbol.new(self.allocator, "dyld_stub_binder"); |
| | 1593 | try self.globals.putNoClobber(self.allocator, symbol.name, symbol); |
| | 1594 | } |
| | 1595 | |
| | 1596 | var referenced = std.AutoHashMap(*Dylib, void).init(self.allocator); |
| | 1597 | defer referenced.deinit(); |
| | 1598 | |
| | 1599 | loop: for (self.globals.values()) |symbol| { |
| | 1600 | if (symbol.payload != .undef) continue; |
| | 1601 | |
| | 1602 | for (self.dylibs.items) |dylib| { |
| | 1603 | if (!dylib.symbols.contains(symbol.name)) continue; |
| | 1604 | |
| | 1605 | try referenced.put(dylib, {}); |
| | 1606 | symbol.payload = .{ |
| | 1607 | .proxy = .{ |
| | 1608 | .file = dylib, |
| | 1609 | }, |
| | 1610 | }; |
| | 1611 | continue :loop; |
| | 1612 | } |
| | 1613 | } |
| | 1614 | |
| | 1615 | // Add LC_LOAD_DYLIB load command for each referenced dylib/stub. |
| | 1616 | var it = referenced.iterator(); |
| | 1617 | while (it.next()) |entry| { |
| | 1618 | const dylib = entry.key_ptr.*; |
| | 1619 | dylib.ordinal = self.next_dylib_ordinal; |
| | 1620 | const dylib_id = dylib.id orelse unreachable; |
| | 1621 | var dylib_cmd = try createLoadDylibCommand( |
| | 1622 | self.allocator, |
| | 1623 | dylib_id.name, |
| | 1624 | dylib_id.timestamp, |
| | 1625 | dylib_id.current_version, |
| | 1626 | dylib_id.compatibility_version, |
| | 1627 | ); |
| | 1628 | errdefer dylib_cmd.deinit(self.allocator); |
| | 1629 | try self.load_commands.append(self.allocator, .{ .Dylib = dylib_cmd }); |
| | 1630 | self.next_dylib_ordinal += 1; |
| | 1631 | } |
| | 1632 | |
| | 1633 | // Fourth pass, handle synthetic symbols and flag any undefined references. |
| | 1634 | if (self.globals.get("___dso_handle")) |symbol| { |
| | 1635 | if (symbol.payload == .undef) { |
| | 1636 | symbol.payload = .{ |
| | 1637 | .proxy = .{}, |
| | 1638 | }; |
| | 1639 | } |
| | 1640 | } |
| | 1641 | |
| | 1642 | var has_undefined = false; |
| | 1643 | for (self.globals.values()) |symbol| { |
| | 1644 | if (symbol.payload != .undef) continue; |
| | 1645 | |
| | 1646 | log.err("undefined reference to symbol '{s}'", .{symbol.name}); |
| | 1647 | if (symbol.payload.undef.file) |file| { |
| | 1648 | log.err(" | referenced in {s}", .{file.name.?}); |
| | 1649 | } |
| | 1650 | has_undefined = true; |
| | 1651 | } |
| | 1652 | |
| | 1653 | if (has_undefined) return error.UndefinedSymbolReference; |
| | 1654 | |
| 1573 | log.warn("globals", .{}); | 1655 | log.warn("globals", .{}); |
| 1574 | for (self.globals.values()) |value| { | 1656 | for (self.globals.values()) |value| { |
| 1575 | log.warn(" | {s}: {}", .{ value.name, value.payload }); | 1657 | log.warn(" | {s}: {}", .{ value.name, value.payload }); |
| ... | @@ -1581,112 +1663,6 @@ fn resolveSymbols(self: *Zld) !void { | ... | @@ -1581,112 +1663,6 @@ fn resolveSymbols(self: *Zld) !void { |
| 1581 | log.warn(" | {s}: {}", .{ sym.name, sym.payload }); | 1663 | log.warn(" | {s}: {}", .{ sym.name, sym.payload }); |
| 1582 | } | 1664 | } |
| 1583 | } | 1665 | } |
| 1584 | | | |
| 1585 | // // Second pass, resolve symbols in static libraries. | | |
| 1586 | // var next_sym: usize = 0; | | |
| 1587 | // while (true) { | | |
| 1588 | // if (next_sym == self.unresolved.count()) break; | | |
| 1589 | | | |
| 1590 | // const sym = self.unresolved.values()[next_sym]; | | |
| 1591 | | | |
| 1592 | // var reset: bool = false; | | |
| 1593 | // for (self.archives.items) |archive| { | | |
| 1594 | // // Check if the entry exists in a static archive. | | |
| 1595 | // const offsets = archive.toc.get(sym.name) orelse { | | |
| 1596 | // // No hit. | | |
| 1597 | // continue; | | |
| 1598 | // }; | | |
| 1599 | // assert(offsets.items.len > 0); | | |
| 1600 | | | |
| 1601 | // const object = try archive.parseObject(offsets.items[0]); | | |
| 1602 | // try self.objects.append(self.allocator, object); | | |
| 1603 | // try self.resolveSymbolsInObject(object); | | |
| 1604 | | | |
| 1605 | // reset = true; | | |
| 1606 | // break; | | |
| 1607 | // } | | |
| 1608 | | | |
| 1609 | // if (reset) { | | |
| 1610 | // next_sym = 0; | | |
| 1611 | // } else { | | |
| 1612 | // next_sym += 1; | | |
| 1613 | // } | | |
| 1614 | // } | | |
| 1615 | | | |
| 1616 | // // Third pass, resolve symbols in dynamic libraries. | | |
| 1617 | // var unresolved = std.ArrayList(*Symbol).init(self.allocator); | | |
| 1618 | // defer unresolved.deinit(); | | |
| 1619 | | | |
| 1620 | // try unresolved.ensureCapacity(self.unresolved.count()); | | |
| 1621 | // for (self.unresolved.values()) |value| { | | |
| 1622 | // unresolved.appendAssumeCapacity(value); | | |
| 1623 | // } | | |
| 1624 | // self.unresolved.clearRetainingCapacity(); | | |
| 1625 | | | |
| 1626 | // // Put dyld_stub_binder as an unresolved special symbol. | | |
| 1627 | // { | | |
| 1628 | // const name = try self.allocator.dupe(u8, "dyld_stub_binder"); | | |
| 1629 | // errdefer self.allocator.free(name); | | |
| 1630 | // const undef = try Symbol.Unresolved.new(self.allocator, name, .{}); | | |
| 1631 | // try unresolved.append(undef); | | |
| 1632 | // } | | |
| 1633 | | | |
| 1634 | // var referenced = std.AutoHashMap(*Dylib, void).init(self.allocator); | | |
| 1635 | // defer referenced.deinit(); | | |
| 1636 | | | |
| 1637 | // loop: while (unresolved.popOrNull()) |undef| { | | |
| 1638 | // const proxy = self.imports.get(undef.name) orelse outer: { | | |
| 1639 | // const proxy = inner: { | | |
| 1640 | // for (self.dylibs.items) |dylib| { | | |
| 1641 | // const proxy = (try dylib.createProxy(undef.name)) orelse continue; | | |
| 1642 | // try referenced.put(dylib, {}); | | |
| 1643 | // break :inner proxy; | | |
| 1644 | // } | | |
| 1645 | // if (mem.eql(u8, undef.name, "___dso_handle")) { | | |
| 1646 | // // TODO this is just a temp patch until I work out what to actually | | |
| 1647 | // // do with ___dso_handle and __mh_execute_header symbols which are | | |
| 1648 | // // synthetically created by the linker on macOS. | | |
| 1649 | // break :inner try Symbol.Proxy.new(self.allocator, undef.name, .{}); | | |
| 1650 | // } | | |
| 1651 | | | |
| 1652 | // self.unresolved.putAssumeCapacityNoClobber(undef.name, undef); | | |
| 1653 | // continue :loop; | | |
| 1654 | // }; | | |
| 1655 | | | |
| 1656 | // try self.imports.putNoClobber(self.allocator, proxy.name, proxy); | | |
| 1657 | // break :outer proxy; | | |
| 1658 | // }; | | |
| 1659 | // undef.alias = proxy; | | |
| 1660 | // } | | |
| 1661 | | | |
| 1662 | // // Add LC_LOAD_DYLIB load command for each referenced dylib/stub. | | |
| 1663 | // var it = referenced.iterator(); | | |
| 1664 | // while (it.next()) |entry| { | | |
| 1665 | // const dylib = entry.key_ptr.*; | | |
| 1666 | // dylib.ordinal = self.next_dylib_ordinal; | | |
| 1667 | // const dylib_id = dylib.id orelse unreachable; | | |
| 1668 | // var dylib_cmd = try createLoadDylibCommand( | | |
| 1669 | // self.allocator, | | |
| 1670 | // dylib_id.name, | | |
| 1671 | // dylib_id.timestamp, | | |
| 1672 | // dylib_id.current_version, | | |
| 1673 | // dylib_id.compatibility_version, | | |
| 1674 | // ); | | |
| 1675 | // errdefer dylib_cmd.deinit(self.allocator); | | |
| 1676 | // try self.load_commands.append(self.allocator, .{ .Dylib = dylib_cmd }); | | |
| 1677 | // self.next_dylib_ordinal += 1; | | |
| 1678 | // } | | |
| 1679 | | | |
| 1680 | // if (self.unresolved.count() > 0) { | | |
| 1681 | // for (self.unresolved.values()) |undef| { | | |
| 1682 | // log.err("undefined reference to symbol '{s}'", .{undef.name}); | | |
| 1683 | // if (undef.cast(Symbol.Unresolved).?.file) |file| { | | |
| 1684 | // log.err(" | referenced in {s}", .{file.name.?}); | | |
| 1685 | // } | | |
| 1686 | // } | | |
| 1687 | | | |
| 1688 | // return error.UndefinedSymbolReference; | | |
| 1689 | // } | | |
| 1690 | } | 1666 | } |
| 1691 | | 1667 | |
| 1692 | fn resolveStubsAndGotEntries(self: *Zld) !void { | 1668 | fn resolveStubsAndGotEntries(self: *Zld) !void { |