authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-12-08 12:42:03+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-12-08 16:58:29+01:00
logf0ec70edd1ab632ab25d48f7b27a444d9ac444bd
treeca0c95bcdb725265f1278654af0ed360010430dc
parent83a668195526df745362b1174bfd643a0cdfb128

macho: do not write null symbols into undef symbols section

Also, skip creating stub entries for resolved globally defined regular symbols.

2 files changed, 27 insertions(+), 8 deletions(-)

src/link/MachO.zig+23-8
...@@ -5400,6 +5400,21 @@ fn writeSymbolTable(self: *MachO) !void {...@@ -5400,6 +5400,21 @@ fn writeSymbolTable(self: *MachO) !void {
5400 try locals.append(sym);5400 try locals.append(sym);
5401 }5401 }
54025402
5403 // TODO How do we handle null global symbols in incremental context?
5404 var undefs = std.ArrayList(macho.nlist_64).init(self.base.allocator);
5405 defer undefs.deinit();
5406 var undefs_table = std.AutoHashMap(u32, u32).init(self.base.allocator);
5407 defer undefs_table.deinit();
5408 try undefs.ensureTotalCapacity(self.undefs.items.len);
5409 try undefs_table.ensureTotalCapacity(@intCast(u32, self.undefs.items.len));
5410
5411 for (self.undefs.items) |sym, i| {
5412 if (sym.n_strx == 0) continue;
5413 const new_index = @intCast(u32, undefs.items.len);
5414 undefs.appendAssumeCapacity(sym);
5415 undefs_table.putAssumeCapacityNoClobber(@intCast(u32, i), new_index);
5416 }
5417
5403 if (self.has_stabs) {5418 if (self.has_stabs) {
5404 for (self.objects.items) |object| {5419 for (self.objects.items) |object| {
5405 if (object.debug_info == null) continue;5420 if (object.debug_info == null) continue;
...@@ -5456,7 +5471,7 @@ fn writeSymbolTable(self: *MachO) !void {...@@ -5456,7 +5471,7 @@ fn writeSymbolTable(self: *MachO) !void {
54565471
5457 const nlocals = locals.items.len;5472 const nlocals = locals.items.len;
5458 const nexports = self.globals.items.len;5473 const nexports = self.globals.items.len;
5459 const nundefs = self.undefs.items.len;5474 const nundefs = undefs.items.len;
54605475
5461 const locals_off = symtab.symoff;5476 const locals_off = symtab.symoff;
5462 const locals_size = nlocals * @sizeOf(macho.nlist_64);5477 const locals_size = nlocals * @sizeOf(macho.nlist_64);
...@@ -5471,7 +5486,7 @@ fn writeSymbolTable(self: *MachO) !void {...@@ -5471,7 +5486,7 @@ fn writeSymbolTable(self: *MachO) !void {
5471 const undefs_off = exports_off + exports_size;5486 const undefs_off = exports_off + exports_size;
5472 const undefs_size = nundefs * @sizeOf(macho.nlist_64);5487 const undefs_size = nundefs * @sizeOf(macho.nlist_64);
5473 log.debug("writing undefined symbols from 0x{x} to 0x{x}", .{ undefs_off, undefs_size + undefs_off });5488 log.debug("writing undefined symbols from 0x{x} to 0x{x}", .{ undefs_off, undefs_size + undefs_off });
5474 try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.undefs.items), undefs_off);5489 try self.base.file.?.pwriteAll(mem.sliceAsBytes(undefs.items), undefs_off);
54755490
5476 symtab.nsyms = @intCast(u32, nlocals + nexports + nundefs);5491 symtab.nsyms = @intCast(u32, nlocals + nexports + nundefs);
5477 seg.inner.filesize += locals_size + exports_size + undefs_size;5492 seg.inner.filesize += locals_size + exports_size + undefs_size;
...@@ -5513,10 +5528,10 @@ fn writeSymbolTable(self: *MachO) !void {...@@ -5513,10 +5528,10 @@ fn writeSymbolTable(self: *MachO) !void {
55135528
5514 stubs.reserved1 = 0;5529 stubs.reserved1 = 0;
5515 for (self.stubs_map.keys()) |key| {5530 for (self.stubs_map.keys()) |key| {
5516 const resolv = self.symbol_resolver.get(key) orelse continue;5531 const resolv = self.symbol_resolver.get(key).?;
5517 switch (resolv.where) {5532 switch (resolv.where) {
5518 .global => try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL),5533 .global => try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL),
5519 .undef => try writer.writeIntLittle(u32, dysymtab.iundefsym + resolv.where_index),5534 .undef => try writer.writeIntLittle(u32, dysymtab.iundefsym + undefs_table.get(resolv.where_index).?),
5520 }5535 }
5521 }5536 }
55225537
...@@ -5525,10 +5540,10 @@ fn writeSymbolTable(self: *MachO) !void {...@@ -5525,10 +5540,10 @@ fn writeSymbolTable(self: *MachO) !void {
5525 switch (key) {5540 switch (key) {
5526 .local => try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL),5541 .local => try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL),
5527 .global => |n_strx| {5542 .global => |n_strx| {
5528 const resolv = self.symbol_resolver.get(n_strx) orelse continue;5543 const resolv = self.symbol_resolver.get(n_strx).?;
5529 switch (resolv.where) {5544 switch (resolv.where) {
5530 .global => try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL),5545 .global => try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL),
5531 .undef => try writer.writeIntLittle(u32, dysymtab.iundefsym + resolv.where_index),5546 .undef => try writer.writeIntLittle(u32, dysymtab.iundefsym + undefs_table.get(resolv.where_index).?),
5532 }5547 }
5533 },5548 },
5534 }5549 }
...@@ -5536,10 +5551,10 @@ fn writeSymbolTable(self: *MachO) !void {...@@ -5536,10 +5551,10 @@ fn writeSymbolTable(self: *MachO) !void {
55365551
5537 la_symbol_ptr.reserved1 = got.reserved1 + ngot_entries;5552 la_symbol_ptr.reserved1 = got.reserved1 + ngot_entries;
5538 for (self.stubs_map.keys()) |key| {5553 for (self.stubs_map.keys()) |key| {
5539 const resolv = self.symbol_resolver.get(key) orelse continue;5554 const resolv = self.symbol_resolver.get(key).?;
5540 switch (resolv.where) {5555 switch (resolv.where) {
5541 .global => try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL),5556 .global => try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL),
5542 .undef => try writer.writeIntLittle(u32, dysymtab.iundefsym + resolv.where_index),5557 .undef => try writer.writeIntLittle(u32, dysymtab.iundefsym + undefs_table.get(resolv.where_index).?),
5543 }5558 }
5544 }5559 }
55455560
src/link/MachO/Atom.zig+4
...@@ -571,6 +571,10 @@ fn addGotEntry(target: Relocation.Target, context: RelocContext) !void {...@@ -571,6 +571,10 @@ fn addGotEntry(target: Relocation.Target, context: RelocContext) !void {
571fn addStub(target: Relocation.Target, context: RelocContext) !void {571fn addStub(target: Relocation.Target, context: RelocContext) !void {
572 if (target != .global) return;572 if (target != .global) return;
573 if (context.macho_file.stubs_map.contains(target.global)) return;573 if (context.macho_file.stubs_map.contains(target.global)) return;
574 // If the symbol has been resolved as defined globally elsewhere (in a different translation unit),
575 // then skip creating stub entry.
576 // TODO Is this the correct for the incremental?
577 if (context.macho_file.symbol_resolver.get(target.global).?.where == .global) return;
574578
575 const value_ptr = blk: {579 const value_ptr = blk: {
576 if (context.macho_file.stubs_map_free_list.popOrNull()) |i| {580 if (context.macho_file.stubs_map_free_list.popOrNull()) |i| {