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 {
9797 return @fieldParentPtr(T, "base", base);
9898}
9999
100pub fn getTopmostAlias(base: *Symbol) *Symbol {
101 if (base.alias) |alias| {
102 return alias.getTopmostAlias();
103 }
104 return base;
105}
106
100107pub fn isStab(sym: macho.nlist_64) bool {
101108 return (macho.N_STAB & sym.n_type) != 0;
102109}
src/link/MachO/Zld.zig+28-43
......@@ -83,8 +83,8 @@ strtab_dir: std.StringHashMapUnmanaged(u32) = .{},
8383
8484threadlocal_offsets: std.ArrayListUnmanaged(u64) = .{},
8585local_rebases: std.ArrayListUnmanaged(Pointer) = .{},
86stubs: std.StringArrayHashMapUnmanaged(*Symbol) = .{},
87got_entries: std.StringArrayHashMapUnmanaged(*Symbol) = .{},
86stubs: std.ArrayListUnmanaged(*Symbol) = .{},
87got_entries: std.ArrayListUnmanaged(*Symbol) = .{},
8888
8989stub_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 {
200200 try self.populateMetadata();
201201 try self.parseInputFiles(files);
202202 try self.resolveSymbols();
203 self.printSymbols();
203 // self.printSymbols();
204 try self.resolveStubsAndGotEntries();
204205 return error.Unfinished;
205 // try self.resolveStubsAndGotEntries();
206206 // try self.updateMetadata();
207207 // try self.sortSections();
208208 // try self.allocateTextSegment();
......@@ -1413,8 +1413,8 @@ fn resolveSymbols(self: *Zld) !void {
14131413}
14141414
14151415fn resolveStubsAndGotEntries(self: *Zld) !void {
1416 for (self.objects.items) |object, object_id| {
1417 log.debug("resolving stubs and got entries from {s}", .{object.name});
1416 for (self.objects.items) |object| {
1417 log.warn("resolving stubs and got entries from {s}", .{object.name});
14181418
14191419 for (object.sections.items) |sect| {
14201420 const relocs = sect.relocs orelse continue;
......@@ -1422,42 +1422,31 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {
14221422 switch (rel.@"type") {
14231423 .unsigned => continue,
14241424 .got_page, .got_page_off, .got_load, .got => {
1425 const sym = object.symtab.items[rel.target.symbol];
1426 const sym_name = object.getString(sym.n_strx);
1427
1428 if (self.got_entries.contains(sym_name)) continue;
1429
1430 // TODO clean this up
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 });
1425 const sym = rel.target.symbol.getTopmostAlias();
1426 if (sym.got_index != null) continue;
1427
1428 const index = @intCast(u32, self.got_entries.items.len);
1429 sym.got_index = index;
1430 try self.got_entries.append(self.allocator, sym);
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 });
14421433 },
14431434 else => {
14441435 if (rel.target != .symbol) continue;
14451436
1446 const sym = object.symtab.items[rel.target.symbol];
1447 const sym_name = object.getString(sym.n_strx);
1437 const sym = rel.target.symbol.getTopmostAlias();
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;
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) });
1449 log.warn(" | found stub {s}: {*}", .{ sym.name, sym });
14611450 },
14621451 }
14631452 }
......@@ -1465,16 +1454,12 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {
14651454 }
14661455
14671456 // Finally, put dyld_stub_binder as the final GOT entry
1468 var name = try self.allocator.dupe(u8, "dyld_stub_binder");
1469 const index = @intCast(u32, self.got_entries.items().len);
1470 try self.got_entries.putNoClobber(self.allocator, name, .{
1471 .tag = .import,
1472 .index = index,
1473 .target_addr = 0,
1474 .file = 0,
1475 });
1457 const sym = self.imports.get("dyld_stub_binder") orelse unreachable;
1458 const index = @intCast(u32, self.got_entries.items.len);
1459 sym.got_index = index;
1460 try self.got_entries.append(self.allocator, sym);
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 });
14781463}
14791464
14801465fn resolveRelocsAndWriteSections(self: *Zld) !void {