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 {...@@ -121,20 +121,11 @@ pub const Tentative = struct {
121};121};
122122
123pub const Proxy = struct {123pub 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
131 /// Dylib where to locate this symbol.124 /// Dylib where to locate this symbol.
132 /// null means self-reference.125 /// null means self-reference.
133 file: ?*Dylib = null,126 file: ?*Dylib = null,
134127
135 pub fn deinit(proxy: *Proxy, allocator: *Allocator) void {128 local_sym_index: u32 = 0,
136 proxy.bind_info.deinit(allocator);
137 }
138129
139 pub fn dylibOrdinal(proxy: Proxy) u16 {130 pub fn dylibOrdinal(proxy: Proxy) u16 {
140 const dylib = proxy.file orelse return 0;131 const dylib = proxy.file orelse return 0;
...@@ -145,13 +136,10 @@ pub const Proxy = struct {...@@ -145,13 +136,10 @@ pub const Proxy = struct {
145 _ = fmt;136 _ = fmt;
146 _ = options;137 _ = options;
147 try std.fmt.format(writer, "Proxy {{ ", .{});138 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 }
152 if (self.file) |file| {139 if (self.file) |file| {
153 try std.fmt.format(writer, ".file = {s}, ", .{file.name.?});140 try std.fmt.format(writer, ".file = {s}, ", .{file.name.?});
154 }141 }
142 try std.fmt.format(writer, ".local_sym_index = {d}, ", .{self.local_sym_index});
155 try std.fmt.format(writer, "}}", .{});143 try std.fmt.format(writer, "}}", .{});
156 }144 }
157};145};
...@@ -284,11 +272,6 @@ pub fn asNlist(symbol: *Symbol, zld: *Zld) !macho.nlist_64 {...@@ -284,11 +272,6 @@ pub fn asNlist(symbol: *Symbol, zld: *Zld) !macho.nlist_64 {
284272
285pub fn deinit(symbol: *Symbol, allocator: *Allocator) void {273pub fn deinit(symbol: *Symbol, allocator: *Allocator) void {
286 allocator.free(symbol.name);274 allocator.free(symbol.name);
287
288 switch (symbol.payload) {
289 .proxy => |*proxy| proxy.deinit(allocator),
290 else => {},
291 }
292}275}
293276
294pub fn isStab(sym: macho.nlist_64) bool {277pub fn isStab(sym: macho.nlist_64) bool {
src/link/MachO/Zld.zig+37-15
...@@ -136,6 +136,7 @@ pub const TextBlock = struct {...@@ -136,6 +136,7 @@ pub const TextBlock = struct {
136 size: u64,136 size: u64,
137 alignment: u32,137 alignment: u32,
138 rebases: std.ArrayList(u64),138 rebases: std.ArrayList(u64),
139 bindings: std.ArrayList(SymbolAtOffset),
139 dices: std.ArrayList(macho.data_in_code_entry),140 dices: std.ArrayList(macho.data_in_code_entry),
140 next: ?*TextBlock = null,141 next: ?*TextBlock = null,
141 prev: ?*TextBlock = null,142 prev: ?*TextBlock = null,
...@@ -226,6 +227,7 @@ pub const TextBlock = struct {...@@ -226,6 +227,7 @@ pub const TextBlock = struct {
226 .size = undefined,227 .size = undefined,
227 .alignment = undefined,228 .alignment = undefined,
228 .rebases = std.ArrayList(u64).init(allocator),229 .rebases = std.ArrayList(u64).init(allocator),
230 .bindings = std.ArrayList(SymbolAtOffset).init(allocator),
229 .dices = std.ArrayList(macho.data_in_code_entry).init(allocator),231 .dices = std.ArrayList(macho.data_in_code_entry).init(allocator),
230 };232 };
231 }233 }
...@@ -239,6 +241,7 @@ pub const TextBlock = struct {...@@ -239,6 +241,7 @@ pub const TextBlock = struct {
239 self.allocator.free(self.code);241 self.allocator.free(self.code);
240 self.relocs.deinit();242 self.relocs.deinit();
241 self.rebases.deinit();243 self.rebases.deinit();
244 self.bindings.deinit();
242 self.dices.deinit();245 self.dices.deinit();
243 }246 }
244247
...@@ -293,6 +296,9 @@ pub const TextBlock = struct {...@@ -293,6 +296,9 @@ pub const TextBlock = struct {
293 if (self.rebases.items.len > 0) {296 if (self.rebases.items.len > 0) {
294 log.warn(" rebases: {any}", .{self.rebases.items});297 log.warn(" rebases: {any}", .{self.rebases.items});
295 }298 }
299 if (self.bindings.items.len > 0) {
300 log.warn(" bindings: {any}", .{self.bindings.items});
301 }
296 if (self.dices.items.len > 0) {302 if (self.dices.items.len > 0) {
297 log.warn(" dices: {any}", .{self.dices.items});303 log.warn(" dices: {any}", .{self.dices.items});
298 }304 }
...@@ -1745,9 +1751,11 @@ fn resolveSymbols(self: *Zld) !void {...@@ -1745,9 +1751,11 @@ fn resolveSymbols(self: *Zld) !void {
1745 if (!dylib.symbols.contains(symbol.name)) continue;1751 if (!dylib.symbols.contains(symbol.name)) continue;
17461752
1747 try referenced.put(dylib, {});1753 try referenced.put(dylib, {});
1754 const index = @intCast(u32, self.imports.items.len);
1748 symbol.payload = .{1755 symbol.payload = .{
1749 .proxy = .{1756 .proxy = .{
1750 .file = dylib,1757 .file = dylib,
1758 .local_sym_index = index,
1751 },1759 },
1752 };1760 };
1753 try self.imports.append(self.allocator, symbol);1761 try self.imports.append(self.allocator, symbol);
...@@ -2341,23 +2349,37 @@ fn writeBindInfoTable(self: *Zld) !void {...@@ -2341,23 +2349,37 @@ fn writeBindInfoTable(self: *Zld) !void {
2341 }2349 }
2342 }2350 }
23432351
2344 for (self.globals.values()) |sym| {2352 {
2345 if (sym.payload != .proxy) continue;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;2358 if (match.seg == self.text_segment_cmd_index.?) continue; // __TEXT is non-writable
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;
23542359
2355 try pointers.append(.{2360 const seg = self.load_commands.items[match.seg].Segment;
2356 .offset = offset,2361
2357 .segment_id = reg.segment_id,2362 while (true) {
2358 .dylib_ordinal = proxy.dylibOrdinal(),2363 const sym = self.locals.items[block.local_sym_index];
2359 .name = sym.name,2364 assert(sym.payload == .regular);
2360 });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 }
2361 }2383 }
2362 }2384 }
23632385
src/link/MachO/reloc.zig+5-14
...@@ -449,22 +449,13 @@ pub const Relocation = struct {...@@ -449,22 +449,13 @@ pub const Relocation = struct {
449 .proxy => |proxy| {449 .proxy => |proxy| {
450 if (mem.eql(u8, self.target.name, "__tlv_bootstrap")) {450 if (mem.eql(u8, self.target.name, "__tlv_bootstrap")) {
451 break :blk 0; // Dynamically bound by dyld.451 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;
455 }452 }
456453
457 const segment = zld.load_commands.items[zld.text_segment_cmd_index.?].Segment;454 const segment = zld.load_commands.items[zld.text_segment_cmd_index.?].Segment;
458 const stubs = segment.sections.items[zld.stubs_section_index.?];455 const stubs = segment.sections.items[zld.stubs_section_index.?];
459 const stubs_index = self.target.stubs_index orelse {456 const stubs_index = self.target.stubs_index orelse {
460 if (proxy.bind_info.items.len > 0) {457 // TODO verify in TextBlock that the symbol is indeed dynamically bound.
461 break :blk 0; // Dynamically bound by dyld.458 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;
468 };459 };
469 break :blk stubs.addr + stubs_index * stubs.reserved2;460 break :blk stubs.addr + stubs_index * stubs.reserved2;
470 },461 },
...@@ -647,9 +638,9 @@ pub const Parser = struct {...@@ -647,9 +638,9 @@ pub const Parser = struct {
647 } else if (out_rel.payload == .unsigned) {638 } else if (out_rel.payload == .unsigned) {
648 const sym = out_rel.target;639 const sym = out_rel.target;
649 switch (sym.payload) {640 switch (sym.payload) {
650 .proxy => {641 .proxy => |proxy| {
651 try sym.payload.proxy.bind_info.append(self.zld.allocator, .{642 try self.block.bindings.append(.{
652 .local_sym_index = self.block.local_sym_index,643 .local_sym_index = proxy.local_sym_index,
653 .offset = out_rel.offset,644 .offset = out_rel.offset,
654 });645 });
655 },646 },