authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-05-03 14:33:13+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-05-04 13:09:32+02:00
logfcd57f08574fd89cf68080f2de6a1300375c83e5
treed29e70ebbe4c72a8076a76e5f5122df96afd91c2
parent68ebc7cba0cb6089be3eb4511a05615830f132ae

zld: resolve GOT loads and stubs


2 files changed, 35 insertions(+), 43 deletions(-)

src/link/MachO/Symbol.zig+7
...@@ -97,6 +97,13 @@ pub fn cast(base: *Symbol, comptime T: type) ?*T {...@@ -97,6 +97,13 @@ pub fn cast(base: *Symbol, comptime T: type) ?*T {
97 return @fieldParentPtr(T, "base", base);97 return @fieldParentPtr(T, "base", base);
98}98}
9999
100pub fn getTopmostAlias(base: *Symbol) *Symbol {
101 if (base.alias) |alias| {
102 return alias.getTopmostAlias();
103 }
104 return base;
105}
106
100pub fn isStab(sym: macho.nlist_64) bool {107pub fn isStab(sym: macho.nlist_64) bool {
101 return (macho.N_STAB & sym.n_type) != 0;108 return (macho.N_STAB & sym.n_type) != 0;
102}109}
src/link/MachO/Zld.zig+28-43
...@@ -83,8 +83,8 @@ strtab_dir: std.StringHashMapUnmanaged(u32) = .{},...@@ -83,8 +83,8 @@ strtab_dir: std.StringHashMapUnmanaged(u32) = .{},
8383
84threadlocal_offsets: std.ArrayListUnmanaged(u64) = .{},84threadlocal_offsets: std.ArrayListUnmanaged(u64) = .{},
85local_rebases: std.ArrayListUnmanaged(Pointer) = .{},85local_rebases: std.ArrayListUnmanaged(Pointer) = .{},
86stubs: std.StringArrayHashMapUnmanaged(*Symbol) = .{},86stubs: std.ArrayListUnmanaged(*Symbol) = .{},
87got_entries: std.StringArrayHashMapUnmanaged(*Symbol) = .{},87got_entries: std.ArrayListUnmanaged(*Symbol) = .{},
8888
89stub_helper_stubs_start_off: ?u64 = null,89stub_helper_stubs_start_off: ?u64 = null,
9090
...@@ -200,9 +200,9 @@ pub fn link(self: *Zld, files: []const []const u8, out_path: []const u8) !void {...@@ -200,9 +200,9 @@ pub fn link(self: *Zld, files: []const []const u8, out_path: []const u8) !void {
200 try self.populateMetadata();200 try self.populateMetadata();
201 try self.parseInputFiles(files);201 try self.parseInputFiles(files);
202 try self.resolveSymbols();202 try self.resolveSymbols();
203 self.printSymbols();203 // self.printSymbols();
204 try self.resolveStubsAndGotEntries();
204 return error.Unfinished;205 return error.Unfinished;
205 // try self.resolveStubsAndGotEntries();
206 // try self.updateMetadata();206 // try self.updateMetadata();
207 // try self.sortSections();207 // try self.sortSections();
208 // try self.allocateTextSegment();208 // try self.allocateTextSegment();
...@@ -1413,8 +1413,8 @@ fn resolveSymbols(self: *Zld) !void {...@@ -1413,8 +1413,8 @@ fn resolveSymbols(self: *Zld) !void {
1413}1413}
14141414
1415fn resolveStubsAndGotEntries(self: *Zld) !void {1415fn resolveStubsAndGotEntries(self: *Zld) !void {
1416 for (self.objects.items) |object, object_id| {1416 for (self.objects.items) |object| {
1417 log.debug("resolving stubs and got entries from {s}", .{object.name});1417 log.warn("resolving stubs and got entries from {s}", .{object.name});
14181418
1419 for (object.sections.items) |sect| {1419 for (object.sections.items) |sect| {
1420 const relocs = sect.relocs orelse continue;1420 const relocs = sect.relocs orelse continue;
...@@ -1422,42 +1422,31 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {...@@ -1422,42 +1422,31 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {
1422 switch (rel.@"type") {1422 switch (rel.@"type") {
1423 .unsigned => continue,1423 .unsigned => continue,
1424 .got_page, .got_page_off, .got_load, .got => {1424 .got_page, .got_page_off, .got_load, .got => {
1425 const sym = object.symtab.items[rel.target.symbol];1425 const sym = rel.target.symbol.getTopmostAlias();
1426 const sym_name = object.getString(sym.n_strx);1426 if (sym.got_index != null) continue;
14271427
1428 if (self.got_entries.contains(sym_name)) continue;1428 const index = @intCast(u32, self.got_entries.items.len);
14291429 sym.got_index = index;
1430 // TODO clean this up1430 try self.got_entries.append(self.allocator, sym);
1431 const is_import = self.symtab.get(sym_name).?.tag == .import;
1432 var name = try self.allocator.dupe(u8, sym_name);
1433 const index = @intCast(u32, self.got_entries.items().len);
1434 try self.got_entries.putNoClobber(self.allocator, name, .{
1435 .tag = if (is_import) .import else .local,
1436 .index = index,
1437 .target_addr = 0,
1438 .file = if (is_import) 0 else @intCast(u16, object_id),
1439 });
14401431
1441 log.debug(" | found GOT entry {s}: {}", .{ sym_name, self.got_entries.get(sym_name) });1432 log.warn(" | found GOT entry {s}: {*}", .{ sym.name, sym });
1442 },1433 },
1443 else => {1434 else => {
1444 if (rel.target != .symbol) continue;1435 if (rel.target != .symbol) continue;
14451436
1446 const sym = object.symtab.items[rel.target.symbol];1437 const sym = rel.target.symbol.getTopmostAlias();
1447 const sym_name = object.getString(sym.n_strx);1438 assert(sym.@"type" != .unresolved);
14481439
1449 if (!Symbol.isUndef(sym)) continue;1440 if (sym.stubs_index != null) continue;
1441 if (sym.cast(Symbol.Regular)) |reg| {
1442 if (!reg.weak_ref) continue;
1443 }
14501444
1451 const in_globals = self.symtab.get(sym_name) orelse unreachable;1445 const index = @intCast(u32, self.stubs.items.len);
1446 sym.stubs_index = index;
1447 try self.stubs.append(self.allocator, sym);
14521448
1453 if (in_globals.tag != .import) continue;1449 log.warn(" | found stub {s}: {*}", .{ sym.name, sym });
1454 if (self.stubs.contains(sym_name)) continue;
1455
1456 var name = try self.allocator.dupe(u8, sym_name);
1457 const index = @intCast(u32, self.stubs.items().len);
1458 try self.stubs.putNoClobber(self.allocator, name, index);
1459
1460 log.debug(" | found stub {s}: {}", .{ sym_name, self.stubs.get(sym_name) });
1461 },1450 },
1462 }1451 }
1463 }1452 }
...@@ -1465,16 +1454,12 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {...@@ -1465,16 +1454,12 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {
1465 }1454 }
14661455
1467 // Finally, put dyld_stub_binder as the final GOT entry1456 // Finally, put dyld_stub_binder as the final GOT entry
1468 var name = try self.allocator.dupe(u8, "dyld_stub_binder");1457 const sym = self.imports.get("dyld_stub_binder") orelse unreachable;
1469 const index = @intCast(u32, self.got_entries.items().len);1458 const index = @intCast(u32, self.got_entries.items.len);
1470 try self.got_entries.putNoClobber(self.allocator, name, .{1459 sym.got_index = index;
1471 .tag = .import,1460 try self.got_entries.append(self.allocator, sym);
1472 .index = index,
1473 .target_addr = 0,
1474 .file = 0,
1475 });
14761461
1477 log.debug(" | found GOT entry dyld_stub_binder: {}", .{self.got_entries.get("dyld_stub_binder")});1462 log.warn(" | found GOT entry {s}: {*}", .{ sym.name, sym });
1478}1463}
14791464
1480fn resolveRelocsAndWriteSections(self: *Zld) !void {1465fn resolveRelocsAndWriteSections(self: *Zld) !void {