authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-03 14:31:49+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-15 18:49:47+02:00
logceb431507d827f5ac53a18d8904886708325c0e7
tree37655e8961c04225f14f66ef99baed325a407dbd
parent989639efba0a7098819c3eb85130cb50413cbf7c

zld: resolve symbols in dylibs using new scheme


2 files changed, 89 insertions(+), 120 deletions(-)

src/link/MachO/Dylib.zig-7
...@@ -506,10 +506,3 @@ pub fn parseDependentLibs(self: *Dylib, out: *std.ArrayList(*Dylib)) !void {...@@ -506,10 +506,3 @@ pub fn parseDependentLibs(self: *Dylib, out: *std.ArrayList(*Dylib)) !void {
506 }506 }
507 }507 }
508}508}
509
510pub fn createProxy(self: *Dylib, sym_name: []const u8) !?*Symbol {
511 if (!self.symbols.contains(sym_name)) return null;
512 return Symbol.Proxy.new(self.allocator, sym_name, .{
513 .file = self,
514 });
515}
src/link/MachO/Zld.zig+89-113
...@@ -104,7 +104,6 @@ objc_data_section_index: ?u16 = null,...@@ -104,7 +104,6 @@ objc_data_section_index: ?u16 = null,
104104
105locals: std.ArrayListUnmanaged(*Symbol) = .{},105locals: std.ArrayListUnmanaged(*Symbol) = .{},
106globals: std.StringArrayHashMapUnmanaged(*Symbol) = .{},106globals: std.StringArrayHashMapUnmanaged(*Symbol) = .{},
107imports: std.StringArrayHashMapUnmanaged(*Symbol) = .{},
108107
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);
174173
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 }
15721565
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}
16911667
1692fn resolveStubsAndGotEntries(self: *Zld) !void {1668fn resolveStubsAndGotEntries(self: *Zld) !void {