authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-15 06:47:13+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-07-15 18:49:47+02:00
logec874a9b2bf24bb37f1e90558153bbf04ac5f22a
tree2b8544cf3422b200cde70f9ced99f2207fa00f75
parent0135b4665988530c0bd6b36ef7cb93ecaf999776

zld: move tracking binding for proxies into TextBlock

which is the source of binding rather than its target. That is, we now track by source.

3 files changed, 44 insertions(+), 48 deletions(-)

src/link/MachO/Symbol.zig+2-19
......@@ -121,20 +121,11 @@ pub const Tentative = struct {
121121};
122122
123123pub const Proxy = struct {
124 /// Dynamic binding info - spots within the final
125 /// executable where this proxy is referenced from.
126 bind_info: std.ArrayListUnmanaged(struct {
127 local_sym_index: u32,
128 offset: u32,
129 }) = .{},
130
131124 /// Dylib where to locate this symbol.
132125 /// null means self-reference.
133126 file: ?*Dylib = null,
134127
135 pub fn deinit(proxy: *Proxy, allocator: *Allocator) void {
136 proxy.bind_info.deinit(allocator);
137 }
128 local_sym_index: u32 = 0,
138129
139130 pub fn dylibOrdinal(proxy: Proxy) u16 {
140131 const dylib = proxy.file orelse return 0;
......@@ -145,13 +136,10 @@ pub const Proxy = struct {
145136 _ = fmt;
146137 _ = options;
147138 try std.fmt.format(writer, "Proxy {{ ", .{});
148 if (self.bind_info.items.len > 0) {
149 // TODO
150 try std.fmt.format(writer, ".bind_info = {}, ", .{self.bind_info.items.len});
151 }
152139 if (self.file) |file| {
153140 try std.fmt.format(writer, ".file = {s}, ", .{file.name.?});
154141 }
142 try std.fmt.format(writer, ".local_sym_index = {d}, ", .{self.local_sym_index});
155143 try std.fmt.format(writer, "}}", .{});
156144 }
157145};
......@@ -284,11 +272,6 @@ pub fn asNlist(symbol: *Symbol, zld: *Zld) !macho.nlist_64 {
284272
285273pub fn deinit(symbol: *Symbol, allocator: *Allocator) void {
286274 allocator.free(symbol.name);
287
288 switch (symbol.payload) {
289 .proxy => |*proxy| proxy.deinit(allocator),
290 else => {},
291 }
292275}
293276
294277pub fn isStab(sym: macho.nlist_64) bool {
src/link/MachO/Zld.zig+37-15
......@@ -136,6 +136,7 @@ pub const TextBlock = struct {
136136 size: u64,
137137 alignment: u32,
138138 rebases: std.ArrayList(u64),
139 bindings: std.ArrayList(SymbolAtOffset),
139140 dices: std.ArrayList(macho.data_in_code_entry),
140141 next: ?*TextBlock = null,
141142 prev: ?*TextBlock = null,
......@@ -226,6 +227,7 @@ pub const TextBlock = struct {
226227 .size = undefined,
227228 .alignment = undefined,
228229 .rebases = std.ArrayList(u64).init(allocator),
230 .bindings = std.ArrayList(SymbolAtOffset).init(allocator),
229231 .dices = std.ArrayList(macho.data_in_code_entry).init(allocator),
230232 };
231233 }
......@@ -239,6 +241,7 @@ pub const TextBlock = struct {
239241 self.allocator.free(self.code);
240242 self.relocs.deinit();
241243 self.rebases.deinit();
244 self.bindings.deinit();
242245 self.dices.deinit();
243246 }
244247
......@@ -293,6 +296,9 @@ pub const TextBlock = struct {
293296 if (self.rebases.items.len > 0) {
294297 log.warn(" rebases: {any}", .{self.rebases.items});
295298 }
299 if (self.bindings.items.len > 0) {
300 log.warn(" bindings: {any}", .{self.bindings.items});
301 }
296302 if (self.dices.items.len > 0) {
297303 log.warn(" dices: {any}", .{self.dices.items});
298304 }
......@@ -1745,9 +1751,11 @@ fn resolveSymbols(self: *Zld) !void {
17451751 if (!dylib.symbols.contains(symbol.name)) continue;
17461752
17471753 try referenced.put(dylib, {});
1754 const index = @intCast(u32, self.imports.items.len);
17481755 symbol.payload = .{
17491756 .proxy = .{
17501757 .file = dylib,
1758 .local_sym_index = index,
17511759 },
17521760 };
17531761 try self.imports.append(self.allocator, symbol);
......@@ -2341,23 +2349,37 @@ fn writeBindInfoTable(self: *Zld) !void {
23412349 }
23422350 }
23432351
2344 for (self.globals.values()) |sym| {
2345 if (sym.payload != .proxy) continue;
2352 {
2353 var it = self.blocks.iterator();
2354 while (it.next()) |entry| {
2355 const match = entry.key_ptr.*;
2356 var block: *TextBlock = entry.value_ptr.*;
23462357
2347 const proxy = sym.payload.proxy;
2348 for (proxy.bind_info.items) |info| {
2349 const bind_sym = self.locals.items[info.local_sym_index];
2350 assert(bind_sym.payload == .regular);
2351 const reg = bind_sym.payload.regular;
2352 const base_address = self.load_commands.items[reg.segment_id].Segment.inner.vmaddr;
2353 const offset = reg.address + info.offset - base_address;
2358 if (match.seg == self.text_segment_cmd_index.?) continue; // __TEXT is non-writable
23542359
2355 try pointers.append(.{
2356 .offset = offset,
2357 .segment_id = reg.segment_id,
2358 .dylib_ordinal = proxy.dylibOrdinal(),
2359 .name = sym.name,
2360 });
2360 const seg = self.load_commands.items[match.seg].Segment;
2361
2362 while (true) {
2363 const sym = self.locals.items[block.local_sym_index];
2364 assert(sym.payload == .regular);
2365 const base_offset = sym.payload.regular.address - seg.inner.vmaddr;
2366
2367 for (block.bindings.items) |binding| {
2368 const bind_sym = self.imports.items[binding.local_sym_index];
2369 const proxy = bind_sym.payload.proxy;
2370
2371 try pointers.append(.{
2372 .offset = binding.offset + base_offset,
2373 .segment_id = match.seg,
2374 .dylib_ordinal = proxy.dylibOrdinal(),
2375 .name = bind_sym.name,
2376 });
2377 }
2378
2379 if (block.prev) |prev| {
2380 block = prev;
2381 } else break;
2382 }
23612383 }
23622384 }
23632385
src/link/MachO/reloc.zig+5-14
......@@ -449,22 +449,13 @@ pub const Relocation = struct {
449449 .proxy => |proxy| {
450450 if (mem.eql(u8, self.target.name, "__tlv_bootstrap")) {
451451 break :blk 0; // Dynamically bound by dyld.
452 // const segment = zld.load_commands.items[zld.data_segment_cmd_index.?].Segment;
453 // const tlv = segment.sections.items[zld.tlv_section_index.?];
454 // break :blk tlv.addr;
455452 }
456453
457454 const segment = zld.load_commands.items[zld.text_segment_cmd_index.?].Segment;
458455 const stubs = segment.sections.items[zld.stubs_section_index.?];
459456 const stubs_index = self.target.stubs_index orelse {
460 if (proxy.bind_info.items.len > 0) {
461 break :blk 0; // Dynamically bound by dyld.
462 }
463 log.err("expected stubs index or dynamic bind address for symbol '{s}'", .{
464 self.target.name,
465 });
466 log.err(" this is an internal linker error", .{});
467 return error.FailedToResolveRelocationTarget;
457 // TODO verify in TextBlock that the symbol is indeed dynamically bound.
458 break :blk 0; // Dynamically bound by dyld.
468459 };
469460 break :blk stubs.addr + stubs_index * stubs.reserved2;
470461 },
......@@ -647,9 +638,9 @@ pub const Parser = struct {
647638 } else if (out_rel.payload == .unsigned) {
648639 const sym = out_rel.target;
649640 switch (sym.payload) {
650 .proxy => {
651 try sym.payload.proxy.bind_info.append(self.zld.allocator, .{
652 .local_sym_index = self.block.local_sym_index,
641 .proxy => |proxy| {
642 try self.block.bindings.append(.{
643 .local_sym_index = proxy.local_sym_index,
653644 .offset = out_rel.offset,
654645 });
655646 },