authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-07-15 18:26:05+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-07-18 09:13:08+02:00
log103c16c87955facd373bd20435100fa7eb322349
treee0c905217bc9b8d2ecfdfdf774b2b62ea2238adc
parente117e05768be08078a8484eaf982cfa5347a674e

macho: clean up atom+symbol creation logic in ZigObject


2 files changed, 79 insertions(+), 66 deletions(-)

src/link/MachO/InternalObject.zig+11-11
...@@ -52,8 +52,8 @@ pub fn init(self: *InternalObject, allocator: Allocator) !void {...@@ -52,8 +52,8 @@ pub fn init(self: *InternalObject, allocator: Allocator) !void {
52}52}
5353
54pub fn initSymbols(self: *InternalObject, macho_file: *MachO) !void {54pub fn initSymbols(self: *InternalObject, macho_file: *MachO) !void {
55 const createSymbol = struct {55 const newSymbolAssumeCapacity = struct {
56 fn createSymbol(obj: *InternalObject, name: u32, args: struct {56 fn newSymbolAssumeCapacity(obj: *InternalObject, name: u32, args: struct {
57 type: u8 = macho.N_UNDF | macho.N_EXT,57 type: u8 = macho.N_UNDF | macho.N_EXT,
58 desc: u16 = 0,58 desc: u16 = 0,
59 }) Symbol.Index {59 }) Symbol.Index {
...@@ -78,7 +78,7 @@ pub fn initSymbols(self: *InternalObject, macho_file: *MachO) !void {...@@ -78,7 +78,7 @@ pub fn initSymbols(self: *InternalObject, macho_file: *MachO) !void {
78 symbol.nlist_idx = nlist_idx;78 symbol.nlist_idx = nlist_idx;
79 return index;79 return index;
80 }80 }
81 }.createSymbol;81 }.newSymbolAssumeCapacity;
8282
83 const gpa = macho_file.base.comp.gpa;83 const gpa = macho_file.base.comp.gpa;
84 var nsyms = macho_file.base.comp.force_undefined_symbols.keys().len;84 var nsyms = macho_file.base.comp.force_undefined_symbols.keys().len;
...@@ -102,28 +102,28 @@ pub fn initSymbols(self: *InternalObject, macho_file: *MachO) !void {...@@ -102,28 +102,28 @@ pub fn initSymbols(self: *InternalObject, macho_file: *MachO) !void {
102102
103 try self.force_undefined.ensureTotalCapacityPrecise(gpa, macho_file.base.comp.force_undefined_symbols.keys().len);103 try self.force_undefined.ensureTotalCapacityPrecise(gpa, macho_file.base.comp.force_undefined_symbols.keys().len);
104 for (macho_file.base.comp.force_undefined_symbols.keys()) |name| {104 for (macho_file.base.comp.force_undefined_symbols.keys()) |name| {
105 self.force_undefined.addOneAssumeCapacity().* = createSymbol(self, try self.addString(gpa, name), .{});105 self.force_undefined.addOneAssumeCapacity().* = newSymbolAssumeCapacity(self, try self.addString(gpa, name), .{});
106 }106 }
107107
108 self.dyld_stub_binder_index = createSymbol(self, try self.addString(gpa, "dyld_stub_binder"), .{});108 self.dyld_stub_binder_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "dyld_stub_binder"), .{});
109 self.objc_msg_send_index = createSymbol(self, try self.addString(gpa, "_objc_msgSend"), .{});109 self.objc_msg_send_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_objc_msgSend"), .{});
110110
111 if (!macho_file.base.isDynLib()) {111 if (!macho_file.base.isDynLib()) {
112 self.entry_index = createSymbol(self, try self.addString(gpa, macho_file.entry_name orelse "_main"), .{});112 self.entry_index = newSymbolAssumeCapacity(self, try self.addString(gpa, macho_file.entry_name orelse "_main"), .{});
113 self.mh_execute_header_index = createSymbol(self, try self.addString(gpa, "__mh_execute_header"), .{113 self.mh_execute_header_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__mh_execute_header"), .{
114 .type = macho.N_SECT | macho.N_EXT,114 .type = macho.N_SECT | macho.N_EXT,
115 .desc = macho.REFERENCED_DYNAMICALLY,115 .desc = macho.REFERENCED_DYNAMICALLY,
116 });116 });
117 } else {117 } else {
118 self.mh_dylib_header_index = createSymbol(self, try self.addString(gpa, "__mh_dylib_header"), .{118 self.mh_dylib_header_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__mh_dylib_header"), .{
119 .type = macho.N_SECT | macho.N_EXT,119 .type = macho.N_SECT | macho.N_EXT,
120 });120 });
121 }121 }
122122
123 self.dso_handle_index = createSymbol(self, try self.addString(gpa, "___dso_handle"), .{123 self.dso_handle_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "___dso_handle"), .{
124 .type = macho.N_SECT | macho.N_EXT,124 .type = macho.N_SECT | macho.N_EXT,
125 });125 });
126 self.dyld_private_index = createSymbol(self, try self.addString(gpa, "dyld_private"), .{126 self.dyld_private_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "dyld_private"), .{
127 .type = macho.N_SECT,127 .type = macho.N_SECT,
128 });128 });
129}129}
src/link/MachO/ZigObject.zig+68-55
...@@ -141,34 +141,64 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void {...@@ -141,34 +141,64 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void {
141 }141 }
142}142}
143143
144fn addNlist(self: *ZigObject, allocator: Allocator) !Symbol.Index {144fn newSymbol(self: *ZigObject, allocator: Allocator, name: u32, args: struct {
145 type: u8 = macho.N_UNDF | macho.N_EXT,
146 desc: u16 = 0,
147}) !Symbol.Index {
145 try self.symtab.ensureUnusedCapacity(allocator, 1);148 try self.symtab.ensureUnusedCapacity(allocator, 1);
146 const index = @as(Symbol.Index, @intCast(self.symtab.addOneAssumeCapacity()));149 try self.symbols.ensureUnusedCapacity(allocator, 1);
147 self.symtab.set(index, .{150 try self.symbols_extra.ensureUnusedCapacity(allocator, @sizeOf(Symbol.Extra));
148 .nlist = MachO.null_sym,151 try self.globals.ensureUnusedCapacity(allocator, 1);
152
153 const index = self.addSymbolAssumeCapacity();
154 const symbol = &self.symbols.items[index];
155 symbol.name = name;
156 symbol.extra = self.addSymbolExtraAssumeCapacity(.{});
157
158 const nlist_idx: u32 = @intCast(self.symtab.addOneAssumeCapacity());
159 self.symtab.set(nlist_idx, .{
160 .nlist = .{
161 .n_strx = name,
162 .n_type = args.type,
163 .n_sect = 0,
164 .n_desc = args.desc,
165 .n_value = 0,
166 },
149 .size = 0,167 .size = 0,
150 .atom = 0,168 .atom = 0,
151 });169 });
170 symbol.nlist_idx = nlist_idx;
171
172 self.globals.appendAssumeCapacity(0);
173
152 return index;174 return index;
153}175}
154176
155pub fn createAtomForDecl(self: *ZigObject, allocator: Allocator, macho_file: *MachO) !Symbol.Index {177fn newAtom(self: *ZigObject, allocator: Allocator, name: u32, macho_file: *MachO) !Atom.Index {
156 const atom_index = try self.addAtom(allocator);178 try self.atoms.ensureUnusedCapacity(allocator, 1);
157 const symbol_index = try self.addSymbol(allocator);179 try self.atoms_extra.ensureUnusedCapacity(allocator, @sizeOf(Atom.Extra));
158 const nlist_index = try self.addNlist(allocator);180 try self.atoms_indexes.ensureUnusedCapacity(allocator, 1);
159 self.symtab.items(.atom)[nlist_index] = atom_index;181 try self.relocs.ensureUnusedCapacity(allocator, 1);
160 try self.atoms_indexes.append(allocator, atom_index);182
161 const symbol = &self.symbols.items[symbol_index];183 const index = self.addAtomAssumeCapacity();
162 symbol.atom_ref = .{ .index = atom_index, .file = self.index };184 self.atoms_indexes.appendAssumeCapacity(index);
163 symbol.nlist_idx = nlist_index;185 const atom = self.getAtom(index).?;
164 symbol.extra = try self.addSymbolExtra(allocator, .{});186 atom.name = name;
187
165 const relocs_index = @as(u32, @intCast(self.relocs.items.len));188 const relocs_index = @as(u32, @intCast(self.relocs.items.len));
166 const relocs = try self.relocs.addOne(allocator);189 self.relocs.addOneAssumeCapacity().* = .{};
167 relocs.* = .{};
168 const atom = self.getAtom(atom_index).?;
169 atom.addExtra(.{ .rel_index = relocs_index, .rel_count = 0 }, macho_file);190 atom.addExtra(.{ .rel_index = relocs_index, .rel_count = 0 }, macho_file);
170 try self.globals.append(allocator, 0);191
171 return symbol_index;192 return index;
193}
194
195fn newSymbolWithAtom(self: *ZigObject, allocator: Allocator, name: u32, macho_file: *MachO) !Symbol.Index {
196 const atom_index = try self.newAtom(allocator, name, macho_file);
197 const sym_index = try self.newSymbol(allocator, name, .{ .type = macho.N_SECT });
198 const sym = &self.symbols.items[sym_index];
199 sym.atom_ref = .{ .index = atom_index, .file = self.index };
200 self.symtab.items(.atom)[sym.nlist_idx] = atom_index;
201 return sym_index;
172}202}
173203
174pub fn getAtomData(self: ZigObject, macho_file: *MachO, atom: Atom, buffer: []u8) !void {204pub fn getAtomData(self: ZigObject, macho_file: *MachO, atom: Atom, buffer: []u8) !void {
...@@ -1079,27 +1109,19 @@ fn createTlvInitializer(...@@ -1079,27 +1109,19 @@ fn createTlvInitializer(
1079 const gpa = macho_file.base.comp.gpa;1109 const gpa = macho_file.base.comp.gpa;
1080 const sym_name = try std.fmt.allocPrint(gpa, "{s}$tlv$init", .{name});1110 const sym_name = try std.fmt.allocPrint(gpa, "{s}$tlv$init", .{name});
1081 defer gpa.free(sym_name);1111 defer gpa.free(sym_name);
1112 const off = try self.strtab.insert(gpa, sym_name);
10821113
1083 const sym_index = try self.createAtomForDecl(gpa, macho_file);1114 const sym_index = try self.newSymbolWithAtom(gpa, off, macho_file);
1084 const sym = &self.symbols.items[sym_index];1115 const sym = &self.symbols.items[sym_index];
1085 const nlist = &self.symtab.items(.nlist)[sym.nlist_idx];1116 const nlist = &self.symtab.items(.nlist)[sym.nlist_idx];
1086 const atom = sym.getAtom(macho_file).?;1117 const atom = sym.getAtom(macho_file).?;
1087
1088 sym.out_n_sect = sect_index;1118 sym.out_n_sect = sect_index;
1089 atom.out_n_sect = sect_index;1119 atom.out_n_sect = sect_index;
1090
1091 sym.value = 0;
1092 sym.name = try self.strtab.insert(gpa, sym_name);
1093 atom.flags.alive = true;1120 atom.flags.alive = true;
1094 atom.name = sym.name;
1095 nlist.n_strx = sym.name;
1096 nlist.n_sect = sect_index + 1;
1097 nlist.n_type = macho.N_SECT;
1098 nlist.n_value = 0;
1099 self.symtab.items(.size)[sym.nlist_idx] = code.len;
1100
1101 atom.alignment = alignment;1121 atom.alignment = alignment;
1102 atom.size = code.len;1122 atom.size = code.len;
1123 nlist.n_sect = sect_index + 1;
1124 self.symtab.items(.size)[sym.nlist_idx] = code.len;
11031125
1104 const slice = macho_file.sections.slice();1126 const slice = macho_file.sections.slice();
1105 const header = slice.items(.header)[sect_index];1127 const header = slice.items(.header)[sect_index];
...@@ -1293,7 +1315,8 @@ fn lowerConst(...@@ -1293,7 +1315,8 @@ fn lowerConst(
1293 var code_buffer = std.ArrayList(u8).init(gpa);1315 var code_buffer = std.ArrayList(u8).init(gpa);
1294 defer code_buffer.deinit();1316 defer code_buffer.deinit();
12951317
1296 const sym_index = try self.createAtomForDecl(gpa, macho_file);1318 const name_str_index = try self.strtab.insert(gpa, name);
1319 const sym_index = try self.newSymbolWithAtom(gpa, name_str_index, macho_file);
12971320
1298 const res = try codegen.generateSymbol(&macho_file.base, pt, src_loc, val, &code_buffer, .{1321 const res = try codegen.generateSymbol(&macho_file.base, pt, src_loc, val, &code_buffer, .{
1299 .none = {},1322 .none = {},
...@@ -1306,19 +1329,14 @@ fn lowerConst(...@@ -1306,19 +1329,14 @@ fn lowerConst(
1306 };1329 };
13071330
1308 const sym = &self.symbols.items[sym_index];1331 const sym = &self.symbols.items[sym_index];
1309 const name_str_index = try self.strtab.insert(gpa, name);
1310 sym.name = name_str_index;
1311 sym.out_n_sect = output_section_index;1332 sym.out_n_sect = output_section_index;
13121333
1313 const nlist = &self.symtab.items(.nlist)[sym.nlist_idx];1334 const nlist = &self.symtab.items(.nlist)[sym.nlist_idx];
1314 nlist.n_strx = name_str_index;
1315 nlist.n_type = macho.N_SECT;
1316 nlist.n_sect = output_section_index + 1;1335 nlist.n_sect = output_section_index + 1;
1317 self.symtab.items(.size)[sym.nlist_idx] = code.len;1336 self.symtab.items(.size)[sym.nlist_idx] = code.len;
13181337
1319 const atom = sym.getAtom(macho_file).?;1338 const atom = sym.getAtom(macho_file).?;
1320 atom.flags.alive = true;1339 atom.flags.alive = true;
1321 atom.name = name_str_index;
1322 atom.alignment = required_alignment;1340 atom.alignment = required_alignment;
1323 atom.size = code.len;1341 atom.size = code.len;
1324 atom.out_n_sect = output_section_index;1342 atom.out_n_sect = output_section_index;
...@@ -1327,9 +1345,6 @@ fn lowerConst(...@@ -1327,9 +1345,6 @@ fn lowerConst(
1327 // TODO rename and re-audit this method1345 // TODO rename and re-audit this method
1328 errdefer self.freeDeclMetadata(macho_file, sym_index);1346 errdefer self.freeDeclMetadata(macho_file, sym_index);
13291347
1330 sym.value = 0;
1331 nlist.n_value = 0;
1332
1333 const sect = macho_file.sections.items(.header)[output_section_index];1348 const sect = macho_file.sections.items(.header)[output_section_index];
1334 const file_offset = sect.offset + atom.value;1349 const file_offset = sect.offset + atom.value;
1335 try macho_file.base.file.?.pwriteAll(code, file_offset);1350 try macho_file.base.file.?.pwriteAll(code, file_offset);
...@@ -1560,17 +1575,9 @@ pub fn getGlobalSymbol(self: *ZigObject, macho_file: *MachO, name: []const u8, l...@@ -1560,17 +1575,9 @@ pub fn getGlobalSymbol(self: *ZigObject, macho_file: *MachO, name: []const u8, l
1560 const off = try self.strtab.insert(gpa, sym_name);1575 const off = try self.strtab.insert(gpa, sym_name);
1561 const lookup_gop = try self.globals_lookup.getOrPut(gpa, off);1576 const lookup_gop = try self.globals_lookup.getOrPut(gpa, off);
1562 if (!lookup_gop.found_existing) {1577 if (!lookup_gop.found_existing) {
1563 const sym_index = try self.addSymbol(gpa);1578 const sym_index = try self.newSymbol(gpa, off, .{});
1564 const sym = &self.symbols.items[sym_index];1579 const sym = &self.symbols.items[sym_index];
1565 const nlist_index = try self.addNlist(gpa);1580 lookup_gop.value_ptr.* = sym.nlist_idx;
1566 const nlist = &self.symtab.items(.nlist)[nlist_index];
1567 nlist.n_strx = off;
1568 nlist.n_type = macho.N_EXT;
1569 sym.name = off;
1570 sym.nlist_idx = nlist_index;
1571 sym.extra = try self.addSymbolExtra(gpa, .{});
1572 lookup_gop.value_ptr.* = nlist_index;
1573 try self.globals.append(gpa, 0);
1574 }1581 }
1575 return lookup_gop.value_ptr.*;1582 return lookup_gop.value_ptr.*;
1576}1583}
...@@ -1584,10 +1591,10 @@ pub fn getOrCreateMetadataForDecl(...@@ -1584,10 +1591,10 @@ pub fn getOrCreateMetadataForDecl(
1584 const gop = try self.decls.getOrPut(gpa, decl_index);1591 const gop = try self.decls.getOrPut(gpa, decl_index);
1585 if (!gop.found_existing) {1592 if (!gop.found_existing) {
1586 const any_non_single_threaded = macho_file.base.comp.config.any_non_single_threaded;1593 const any_non_single_threaded = macho_file.base.comp.config.any_non_single_threaded;
1587 const sym_index = try self.createAtomForDecl(gpa, macho_file);1594 const sym_index = try self.newSymbolWithAtom(gpa, 0, macho_file);
1595 const sym = &self.symbols.items[sym_index];
1588 const mod = macho_file.base.comp.module.?;1596 const mod = macho_file.base.comp.module.?;
1589 const decl = mod.declPtr(decl_index);1597 const decl = mod.declPtr(decl_index);
1590 const sym = &self.symbols.items[sym_index];
1591 if (decl.getOwnedVariable(mod)) |variable| {1598 if (decl.getOwnedVariable(mod)) |variable| {
1592 if (variable.is_threadlocal and any_non_single_threaded) {1599 if (variable.is_threadlocal and any_non_single_threaded) {
1593 sym.flags.tlv = true;1600 sym.flags.tlv = true;
...@@ -1627,7 +1634,7 @@ pub fn getOrCreateMetadataForLazySymbol(...@@ -1627,7 +1634,7 @@ pub fn getOrCreateMetadataForLazySymbol(
1627 };1634 };
1628 switch (metadata.state.*) {1635 switch (metadata.state.*) {
1629 .unused => {1636 .unused => {
1630 const symbol_index = try self.createAtomForDecl(gpa, macho_file);1637 const symbol_index = try self.newSymbolWithAtom(gpa, 0, macho_file);
1631 const sym = &self.symbols.items[symbol_index];1638 const sym = &self.symbols.items[symbol_index];
1632 sym.flags.needs_zig_got = true;1639 sym.flags.needs_zig_got = true;
1633 metadata.symbol_index.* = symbol_index;1640 metadata.symbol_index.* = symbol_index;
...@@ -1643,12 +1650,18 @@ pub fn getOrCreateMetadataForLazySymbol(...@@ -1643,12 +1650,18 @@ pub fn getOrCreateMetadataForLazySymbol(
1643}1650}
16441651
1645fn addAtom(self: *ZigObject, allocator: Allocator) !Atom.Index {1652fn addAtom(self: *ZigObject, allocator: Allocator) !Atom.Index {
1653 try self.atoms.ensureUnusedCapacity(allocator, 1);
1654 try self.atoms_extra.ensureUnusedCapacity(allocator, 1);
1655 return self.addAtomAssumeCapacity();
1656}
1657
1658fn addAtomAssumeCapacity(self: *ZigObject) Atom.Index {
1646 const atom_index: Atom.Index = @intCast(self.atoms.items.len);1659 const atom_index: Atom.Index = @intCast(self.atoms.items.len);
1647 const atom = try self.atoms.addOne(allocator);1660 const atom = self.atoms.addOneAssumeCapacity();
1648 atom.* = .{1661 atom.* = .{
1649 .file = self.index,1662 .file = self.index,
1650 .atom_index = atom_index,1663 .atom_index = atom_index,
1651 .extra = try self.addAtomExtra(allocator, .{}),1664 .extra = self.addAtomExtraAssumeCapacity(.{}),
1652 };1665 };
1653 return atom_index;1666 return atom_index;
1654}1667}