authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-07-20 06:41:30+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-07-22 12:06:02+02:00
log2b84592858fe004fcae1372f7a5f97e10a81c2e3
treef0ebc5be3d85396d423e837b023057f6258a194a
parent5d9fd5bcdeb9f7a1af50b0eaffd22b61f3e440a6

macho: run more things in parallel


18 files changed, 564 insertions(+), 301 deletions(-)

src/arch/x86_64/Emit.zig+3-3
...@@ -163,12 +163,12 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -163,12 +163,12 @@ pub fn emitMir(emit: *Emit) Error!void {
163 const zo = macho_file.getZigObject().?;163 const zo = macho_file.getZigObject().?;
164 const atom = zo.symbols.items[data.atom_index].getAtom(macho_file).?;164 const atom = zo.symbols.items[data.atom_index].getAtom(macho_file).?;
165 const sym = &zo.symbols.items[data.sym_index];165 const sym = &zo.symbols.items[data.sym_index];
166 if (sym.flags.needs_zig_got and !is_obj_or_static_lib) {166 if (sym.getSectionFlags().needs_zig_got and !is_obj_or_static_lib) {
167 _ = try sym.getOrCreateZigGotEntry(data.sym_index, macho_file);167 _ = try sym.getOrCreateZigGotEntry(data.sym_index, macho_file);
168 }168 }
169 const @"type": link.File.MachO.Relocation.Type = if (sym.flags.needs_zig_got and !is_obj_or_static_lib)169 const @"type": link.File.MachO.Relocation.Type = if (sym.getSectionFlags().needs_zig_got and !is_obj_or_static_lib)
170 .zig_got_load170 .zig_got_load
171 else if (sym.flags.needs_got)171 else if (sym.getSectionFlags().needs_got)
172 // TODO: it is possible to emit .got_load here that can potentially be relaxed172 // TODO: it is possible to emit .got_load here that can potentially be relaxed
173 // however this requires always to use a MOVQ mnemonic173 // however this requires always to use a MOVQ mnemonic
174 .got174 .got
src/arch/x86_64/Lower.zig+1-1
...@@ -451,7 +451,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)...@@ -451,7 +451,7 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
451 break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) };451 break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) };
452 },452 },
453 .mov => {453 .mov => {
454 if (is_obj_or_static_lib and macho_sym.flags.needs_zig_got) emit_mnemonic = .lea;454 if (is_obj_or_static_lib and macho_sym.getSectionFlags().needs_zig_got) emit_mnemonic = .lea;
455 break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) };455 break :op .{ .mem = Memory.rip(mem_op.sib.ptr_size, 0) };
456 },456 },
457 else => unreachable,457 else => unreachable,
src/codegen.zig+1-1
...@@ -924,7 +924,7 @@ fn genDeclRef(...@@ -924,7 +924,7 @@ fn genDeclRef(
924 const name = decl.name.toSlice(ip);924 const name = decl.name.toSlice(ip);
925 const lib_name = if (decl.getOwnedVariable(zcu)) |ov| ov.lib_name.toSlice(ip) else null;925 const lib_name = if (decl.getOwnedVariable(zcu)) |ov| ov.lib_name.toSlice(ip) else null;
926 const sym_index = try macho_file.getGlobalSymbol(name, lib_name);926 const sym_index = try macho_file.getGlobalSymbol(name, lib_name);
927 zo.symbols.items[sym_index].flags.needs_got = true;927 zo.symbols.items[sym_index].setSectionFlags(.{ .needs_got = true });
928 return GenResult.mcv(.{ .load_symbol = sym_index });928 return GenResult.mcv(.{ .load_symbol = sym_index });
929 }929 }
930 const sym_index = try zo.getOrCreateMetadataForDecl(macho_file, decl_index);930 const sym_index = try zo.getOrCreateMetadataForDecl(macho_file, decl_index);
src/link/MachO.zig+423-180
...@@ -25,8 +25,10 @@ sections: std.MultiArrayList(Section) = .{},...@@ -25,8 +25,10 @@ sections: std.MultiArrayList(Section) = .{},
25resolver: SymbolResolver = .{},25resolver: SymbolResolver = .{},
26/// This table will be populated after `scanRelocs` has run.26/// This table will be populated after `scanRelocs` has run.
27/// Key is symbol index.27/// Key is symbol index.
28undefs: std.AutoHashMapUnmanaged(SymbolResolver.Index, std.ArrayListUnmanaged(Ref)) = .{},28undefs: std.AutoArrayHashMapUnmanaged(SymbolResolver.Index, std.ArrayListUnmanaged(Ref)) = .{},
29dupes: std.AutoHashMapUnmanaged(SymbolResolver.Index, std.ArrayListUnmanaged(File.Index)) = .{},29undefs_mutex: std.Thread.Mutex = .{},
30dupes: std.AutoArrayHashMapUnmanaged(SymbolResolver.Index, std.ArrayListUnmanaged(File.Index)) = .{},
31dupes_mutex: std.Thread.Mutex = .{},
3032
31dyld_info_cmd: macho.dyld_info_command = .{},33dyld_info_cmd: macho.dyld_info_command = .{},
32symtab_cmd: macho.symtab_command = .{},34symtab_cmd: macho.symtab_command = .{},
...@@ -93,9 +95,9 @@ debug_str_sect_index: ?u8 = null,...@@ -93,9 +95,9 @@ debug_str_sect_index: ?u8 = null,
93debug_aranges_sect_index: ?u8 = null,95debug_aranges_sect_index: ?u8 = null,
94debug_line_sect_index: ?u8 = null,96debug_line_sect_index: ?u8 = null,
9597
96has_tlv: bool = false,98has_tlv: AtomicBool = AtomicBool.init(false),
97binds_to_weak: bool = false,99binds_to_weak: AtomicBool = AtomicBool.init(false),
98weak_defines: bool = false,100weak_defines: AtomicBool = AtomicBool.init(false),
99has_errors: AtomicBool = AtomicBool.init(false),101has_errors: AtomicBool = AtomicBool.init(false),
100102
101/// Options103/// Options
...@@ -306,20 +308,15 @@ pub fn deinit(self: *MachO) void {...@@ -306,20 +308,15 @@ pub fn deinit(self: *MachO) void {
306 self.sections.deinit(gpa);308 self.sections.deinit(gpa);
307309
308 self.resolver.deinit(gpa);310 self.resolver.deinit(gpa);
309 {311
310 var it = self.undefs.iterator();312 for (self.undefs.values()) |*val| {
311 while (it.next()) |entry| {313 val.deinit(gpa);
312 entry.value_ptr.deinit(gpa);
313 }
314 self.undefs.deinit(gpa);
315 }314 }
316 {315 self.undefs.deinit(gpa);
317 var it = self.dupes.iterator();316 for (self.dupes.values()) |*val| {
318 while (it.next()) |entry| {317 val.deinit(gpa);
319 entry.value_ptr.deinit(gpa);
320 }
321 self.dupes.deinit(gpa);
322 }318 }
319 self.dupes.deinit(gpa);
323320
324 self.symtab.deinit(gpa);321 self.symtab.deinit(gpa);
325 self.strtab.deinit(gpa);322 self.strtab.deinit(gpa);
...@@ -553,12 +550,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n...@@ -553,12 +550,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n
553 else => |e| return e,550 else => |e| return e,
554 };551 };
555 }552 }
556 self.writeSectionsAndUpdateLinkeditSizes() catch |err| {553 try self.writeSectionsAndUpdateLinkeditSizes();
557 switch (err) {
558 error.ResolveFailed => return error.FlushFailure,
559 else => |e| return e,
560 }
561 };
562554
563 try self.writeSectionsToFile();555 try self.writeSectionsToFile();
564 try self.allocateLinkeditSegment();556 try self.allocateLinkeditSegment();
...@@ -907,25 +899,25 @@ pub fn parseInputFiles(self: *MachO) !void {...@@ -907,25 +899,25 @@ pub fn parseInputFiles(self: *MachO) !void {
907 defer wg.wait();899 defer wg.wait();
908900
909 for (self.objects.items) |index| {901 for (self.objects.items) |index| {
910 tp.spawnWg(&wg, parseInputFileWorker, .{ self, index });902 tp.spawnWg(&wg, parseInputFileWorker, .{ self, self.getFile(index).? });
911 }903 }
912 for (self.dylibs.items) |index| {904 for (self.dylibs.items) |index| {
913 tp.spawnWg(&wg, parseInputFileWorker, .{ self, index });905 tp.spawnWg(&wg, parseInputFileWorker, .{ self, self.getFile(index).? });
914 }906 }
915 }907 }
916908
917 if (self.has_errors.swap(false, .seq_cst)) return error.FlushFailure;909 if (self.has_errors.swap(false, .seq_cst)) return error.FlushFailure;
918}910}
919911
920fn parseInputFileWorker(self: *MachO, index: File.Index) void {912fn parseInputFileWorker(self: *MachO, file: File) void {
921 self.getFile(index).?.parse(self) catch |err| {913 file.parse(self) catch |err| {
922 switch (err) {914 switch (err) {
923 error.MalformedObject,915 error.MalformedObject,
924 error.MalformedDylib,916 error.MalformedDylib,
925 error.InvalidCpuArch,917 error.InvalidCpuArch,
926 error.InvalidTarget,918 error.InvalidTarget,
927 => {}, // already reported919 => {}, // already reported
928 else => |e| self.reportParseError2(index, "unexpected error: parsing input file failed with error {s}", .{@errorName(e)}) catch {},920 else => |e| self.reportParseError2(file.getIndex(), "unexpected error: parsing input file failed with error {s}", .{@errorName(e)}) catch {},
929 }921 }
930 _ = self.has_errors.swap(true, .seq_cst);922 _ = self.has_errors.swap(true, .seq_cst);
931 };923 };
...@@ -1286,13 +1278,50 @@ fn markLive(self: *MachO) void {...@@ -1286,13 +1278,50 @@ fn markLive(self: *MachO) void {
1286}1278}
12871279
1288fn convertTentativeDefsAndResolveSpecialSymbols(self: *MachO) !void {1280fn convertTentativeDefsAndResolveSpecialSymbols(self: *MachO) !void {
1289 for (self.objects.items) |index| {1281 const tp = self.base.comp.thread_pool;
1290 try self.getFile(index).?.object.convertTentativeDefinitions(self);1282 var wg: WaitGroup = .{};
1291 }1283 {
1292 if (self.getInternalObject()) |obj| {1284 wg.reset();
1293 try obj.resolveBoundarySymbols(self);1285 defer wg.wait();
1294 try obj.resolveObjcMsgSendSymbols(self);1286 for (self.objects.items) |index| {
1287 tp.spawnWg(&wg, convertTentativeDefinitionsWorker, .{ self, self.getFile(index).?.object });
1288 }
1289 if (self.getInternalObject()) |obj| {
1290 tp.spawnWg(&wg, resolveSpecialSymbolsWorker, .{ self, obj });
1291 }
1295 }1292 }
1293 if (self.has_errors.swap(false, .seq_cst)) return error.FlushFailure;
1294}
1295
1296fn convertTentativeDefinitionsWorker(self: *MachO, object: *Object) void {
1297 const tracy = trace(@src());
1298 defer tracy.end();
1299 object.convertTentativeDefinitions(self) catch |err| {
1300 self.reportParseError2(
1301 object.index,
1302 "unexpected error occurred while converting tentative symbols into defined symbols: {s}",
1303 .{@errorName(err)},
1304 ) catch {};
1305 _ = self.has_errors.swap(true, .seq_cst);
1306 };
1307}
1308
1309fn resolveSpecialSymbolsWorker(self: *MachO, obj: *InternalObject) void {
1310 const tracy = trace(@src());
1311 defer tracy.end();
1312 obj.resolveBoundarySymbols(self) catch |err| {
1313 self.reportUnexpectedError("unexpected error occurred while resolving boundary symbols: {s}", .{
1314 @errorName(err),
1315 }) catch {};
1316 _ = self.has_errors.swap(true, .seq_cst);
1317 return;
1318 };
1319 obj.resolveObjcMsgSendSymbols(self) catch |err| {
1320 self.reportUnexpectedError("unexpected error occurred while resolving ObjC msgsend stubs: {s}", .{
1321 @errorName(err),
1322 }) catch {};
1323 _ = self.has_errors.swap(true, .seq_cst);
1324 };
1296}1325}
12971326
1298pub fn dedupLiterals(self: *MachO) !void {1327pub fn dedupLiterals(self: *MachO) !void {
...@@ -1313,14 +1342,20 @@ pub fn dedupLiterals(self: *MachO) !void {...@@ -1313,14 +1342,20 @@ pub fn dedupLiterals(self: *MachO) !void {
1313 try object.resolveLiterals(&lp, self);1342 try object.resolveLiterals(&lp, self);
1314 }1343 }
13151344
1316 if (self.getZigObject()) |zo| {1345 const tp = self.base.comp.thread_pool;
1317 zo.dedupLiterals(lp, self);1346 var wg: WaitGroup = .{};
1318 }1347 {
1319 for (self.objects.items) |index| {1348 wg.reset();
1320 self.getFile(index).?.object.dedupLiterals(lp, self);1349 defer wg.wait();
1321 }1350 if (self.getZigObject()) |zo| {
1322 if (self.getInternalObject()) |object| {1351 tp.spawnWg(&wg, File.dedupLiterals, .{ zo.asFile(), lp, self });
1323 object.dedupLiterals(lp, self);1352 }
1353 for (self.objects.items) |index| {
1354 tp.spawnWg(&wg, File.dedupLiterals, .{ self.getFile(index).?, lp, self });
1355 }
1356 if (self.getInternalObject()) |object| {
1357 tp.spawnWg(&wg, File.dedupLiterals, .{ object.asFile(), lp, self });
1358 }
1324 }1359 }
1325}1360}
13261361
...@@ -1334,18 +1369,41 @@ fn claimUnresolved(self: *MachO) void {...@@ -1334,18 +1369,41 @@ fn claimUnresolved(self: *MachO) void {
1334}1369}
13351370
1336fn checkDuplicates(self: *MachO) !void {1371fn checkDuplicates(self: *MachO) !void {
1337 if (self.getZigObject()) |zo| {1372 const tracy = trace(@src());
1338 try zo.asFile().checkDuplicates(self);1373 defer tracy.end();
1339 }1374
1340 for (self.objects.items) |index| {1375 const tp = self.base.comp.thread_pool;
1341 try self.getFile(index).?.checkDuplicates(self);1376 var wg: WaitGroup = .{};
1342 }1377 {
1343 if (self.getInternalObject()) |obj| {1378 wg.reset();
1344 try obj.asFile().checkDuplicates(self);1379 defer wg.wait();
1380 if (self.getZigObject()) |zo| {
1381 tp.spawnWg(&wg, checkDuplicatesWorker, .{ self, zo.asFile() });
1382 }
1383 for (self.objects.items) |index| {
1384 tp.spawnWg(&wg, checkDuplicatesWorker, .{ self, self.getFile(index).? });
1385 }
1386 if (self.getInternalObject()) |obj| {
1387 tp.spawnWg(&wg, checkDuplicatesWorker, .{ self, obj.asFile() });
1388 }
1345 }1389 }
1390
1391 if (self.has_errors.swap(false, .seq_cst)) return error.FlushFailure;
1392
1346 try self.reportDuplicates();1393 try self.reportDuplicates();
1347}1394}
13481395
1396fn checkDuplicatesWorker(self: *MachO, file: File) void {
1397 const tracy = trace(@src());
1398 defer tracy.end();
1399 file.checkDuplicates(self) catch |err| {
1400 self.reportParseError2(file.getIndex(), "failed to check for duplicate definitions: {s}", .{
1401 @errorName(err),
1402 }) catch {};
1403 _ = self.has_errors.swap(true, .seq_cst);
1404 };
1405}
1406
1349fn markImportsAndExports(self: *MachO) void {1407fn markImportsAndExports(self: *MachO) void {
1350 const tracy = trace(@src());1408 const tracy = trace(@src());
1351 defer tracy.end();1409 defer tracy.end();
...@@ -1384,16 +1442,26 @@ fn scanRelocs(self: *MachO) !void {...@@ -1384,16 +1442,26 @@ fn scanRelocs(self: *MachO) !void {
1384 const tracy = trace(@src());1442 const tracy = trace(@src());
1385 defer tracy.end();1443 defer tracy.end();
13861444
1387 if (self.getZigObject()) |zo| {1445 const tp = self.base.comp.thread_pool;
1388 try zo.scanRelocs(self);1446 var wg: WaitGroup = .{};
1389 }1447
1390 for (self.objects.items) |index| {1448 {
1391 try self.getFile(index).?.object.scanRelocs(self);1449 wg.reset();
1392 }1450 defer wg.wait();
1393 if (self.getInternalObject()) |obj| {1451
1394 obj.scanRelocs(self);1452 if (self.getZigObject()) |zo| {
1453 tp.spawnWg(&wg, scanRelocsWorker, .{ self, zo.asFile() });
1454 }
1455 for (self.objects.items) |index| {
1456 tp.spawnWg(&wg, scanRelocsWorker, .{ self, self.getFile(index).? });
1457 }
1458 if (self.getInternalObject()) |obj| {
1459 tp.spawnWg(&wg, scanRelocsWorker, .{ self, obj.asFile() });
1460 }
1395 }1461 }
13961462
1463 if (self.has_errors.swap(false, .seq_cst)) return error.FlushFailure;
1464
1397 try self.reportUndefs();1465 try self.reportUndefs();
13981466
1399 if (self.getZigObject()) |zo| {1467 if (self.getZigObject()) |zo| {
...@@ -1410,25 +1478,61 @@ fn scanRelocs(self: *MachO) !void {...@@ -1410,25 +1478,61 @@ fn scanRelocs(self: *MachO) !void {
1410 }1478 }
1411}1479}
14121480
1481fn scanRelocsWorker(self: *MachO, file: File) void {
1482 file.scanRelocs(self) catch |err| {
1483 self.reportParseError2(file.getIndex(), "failed to scan relocations: {s}", .{
1484 @errorName(err),
1485 }) catch {};
1486 _ = self.has_errors.swap(true, .seq_cst);
1487 };
1488}
1489
1490fn sortGlobalSymbolsByName(self: *MachO, symbols: []SymbolResolver.Index) void {
1491 const lessThan = struct {
1492 fn lessThan(ctx: *MachO, lhs: SymbolResolver.Index, rhs: SymbolResolver.Index) bool {
1493 const lhs_name = ctx.resolver.keys.items[lhs - 1].getName(ctx);
1494 const rhs_name = ctx.resolver.keys.items[rhs - 1].getName(ctx);
1495 return mem.order(u8, lhs_name, rhs_name) == .lt;
1496 }
1497 }.lessThan;
1498 mem.sort(SymbolResolver.Index, symbols, self, lessThan);
1499}
1500
1413fn reportUndefs(self: *MachO) !void {1501fn reportUndefs(self: *MachO) !void {
1414 const tracy = trace(@src());1502 const tracy = trace(@src());
1415 defer tracy.end();1503 defer tracy.end();
14161504
1417 if (self.undefined_treatment == .suppress or1505 if (self.undefined_treatment == .suppress or
1418 self.undefined_treatment == .dynamic_lookup) return;1506 self.undefined_treatment == .dynamic_lookup) return;
1507 if (self.undefs.keys().len == 0) return; // Nothing to do
14191508
1509 const gpa = self.base.comp.gpa;
1420 const max_notes = 4;1510 const max_notes = 4;
14211511
1422 var has_undefs = false;1512 // We will sort by name, and then by file to ensure deterministic output.
1423 var it = self.undefs.iterator();1513 var keys = try std.ArrayList(SymbolResolver.Index).initCapacity(gpa, self.undefs.keys().len);
1424 while (it.next()) |entry| {1514 defer keys.deinit();
1425 const undef_sym = self.resolver.keys.items[entry.key_ptr.* - 1];1515 keys.appendSliceAssumeCapacity(self.undefs.keys());
1426 const notes = entry.value_ptr.*;1516 self.sortGlobalSymbolsByName(keys.items);
1517
1518 const refLessThan = struct {
1519 fn lessThan(ctx: void, lhs: Ref, rhs: Ref) bool {
1520 _ = ctx;
1521 return lhs.lessThan(rhs);
1522 }
1523 }.lessThan;
1524
1525 for (self.undefs.values()) |*refs| {
1526 mem.sort(Ref, refs.items, {}, refLessThan);
1527 }
1528
1529 for (keys.items) |key| {
1530 const undef_sym = self.resolver.keys.items[key - 1];
1531 const notes = self.undefs.get(key).?;
1427 const nnotes = @min(notes.items.len, max_notes) + @intFromBool(notes.items.len > max_notes);1532 const nnotes = @min(notes.items.len, max_notes) + @intFromBool(notes.items.len > max_notes);
14281533
1429 var err = try self.base.addErrorWithNotes(nnotes);1534 var err = try self.base.addErrorWithNotes(nnotes);
1430 try err.addMsg("undefined symbol: {s}", .{undef_sym.getName(self)});1535 try err.addMsg("undefined symbol: {s}", .{undef_sym.getName(self)});
1431 has_undefs = true;
14321536
1433 var inote: usize = 0;1537 var inote: usize = 0;
1434 while (inote < @min(notes.items.len, max_notes)) : (inote += 1) {1538 while (inote < @min(notes.items.len, max_notes)) : (inote += 1) {
...@@ -1443,7 +1547,8 @@ fn reportUndefs(self: *MachO) !void {...@@ -1443,7 +1547,8 @@ fn reportUndefs(self: *MachO) !void {
1443 try err.addNote("referenced {d} more times", .{remaining});1547 try err.addNote("referenced {d} more times", .{remaining});
1444 }1548 }
1445 }1549 }
1446 if (has_undefs) return error.HasUndefinedSymbols;1550
1551 return error.HasUndefinedSymbols;
1447}1552}
14481553
1449fn initOutputSections(self: *MachO) !void {1554fn initOutputSections(self: *MachO) !void {
...@@ -1679,7 +1784,7 @@ pub fn sortSections(self: *MachO) !void {...@@ -1679,7 +1784,7 @@ pub fn sortSections(self: *MachO) !void {
1679 if (self.getZigObject()) |zo| {1784 if (self.getZigObject()) |zo| {
1680 for (zo.getAtoms()) |atom_index| {1785 for (zo.getAtoms()) |atom_index| {
1681 const atom = zo.getAtom(atom_index) orelse continue;1786 const atom = zo.getAtom(atom_index) orelse continue;
1682 if (!atom.flags.alive) continue;1787 if (!atom.isAlive()) continue;
1683 atom.out_n_sect = backlinks[atom.out_n_sect];1788 atom.out_n_sect = backlinks[atom.out_n_sect];
1684 }1789 }
1685 }1790 }
...@@ -1688,7 +1793,7 @@ pub fn sortSections(self: *MachO) !void {...@@ -1688,7 +1793,7 @@ pub fn sortSections(self: *MachO) !void {
1688 const file = self.getFile(index).?;1793 const file = self.getFile(index).?;
1689 for (file.getAtoms()) |atom_index| {1794 for (file.getAtoms()) |atom_index| {
1690 const atom = file.getAtom(atom_index) orelse continue;1795 const atom = file.getAtom(atom_index) orelse continue;
1691 if (!atom.flags.alive) continue;1796 if (!atom.isAlive()) continue;
1692 atom.out_n_sect = backlinks[atom.out_n_sect];1797 atom.out_n_sect = backlinks[atom.out_n_sect];
1693 }1798 }
1694 }1799 }
...@@ -1696,7 +1801,7 @@ pub fn sortSections(self: *MachO) !void {...@@ -1696,7 +1801,7 @@ pub fn sortSections(self: *MachO) !void {
1696 if (self.getInternalObject()) |object| {1801 if (self.getInternalObject()) |object| {
1697 for (object.getAtoms()) |atom_index| {1802 for (object.getAtoms()) |atom_index| {
1698 const atom = object.getAtom(atom_index) orelse continue;1803 const atom = object.getAtom(atom_index) orelse continue;
1699 if (!atom.flags.alive) continue;1804 if (!atom.isAlive()) continue;
1700 atom.out_n_sect = backlinks[atom.out_n_sect];1805 atom.out_n_sect = backlinks[atom.out_n_sect];
1701 }1806 }
1702 }1807 }
...@@ -1737,7 +1842,7 @@ pub fn addAtomsToSections(self: *MachO) !void {...@@ -1737,7 +1842,7 @@ pub fn addAtomsToSections(self: *MachO) !void {
1737 if (self.getZigObject()) |zo| {1842 if (self.getZigObject()) |zo| {
1738 for (zo.getAtoms()) |atom_index| {1843 for (zo.getAtoms()) |atom_index| {
1739 const atom = zo.getAtom(atom_index) orelse continue;1844 const atom = zo.getAtom(atom_index) orelse continue;
1740 if (!atom.flags.alive) continue;1845 if (!atom.isAlive()) continue;
1741 if (self.isZigSection(atom.out_n_sect)) continue;1846 if (self.isZigSection(atom.out_n_sect)) continue;
1742 const atoms = &self.sections.items(.atoms)[atom.out_n_sect];1847 const atoms = &self.sections.items(.atoms)[atom.out_n_sect];
1743 try atoms.append(gpa, .{ .index = atom_index, .file = zo.index });1848 try atoms.append(gpa, .{ .index = atom_index, .file = zo.index });
...@@ -1747,7 +1852,7 @@ pub fn addAtomsToSections(self: *MachO) !void {...@@ -1747,7 +1852,7 @@ pub fn addAtomsToSections(self: *MachO) !void {
1747 const file = self.getFile(index).?;1852 const file = self.getFile(index).?;
1748 for (file.getAtoms()) |atom_index| {1853 for (file.getAtoms()) |atom_index| {
1749 const atom = file.getAtom(atom_index) orelse continue;1854 const atom = file.getAtom(atom_index) orelse continue;
1750 if (!atom.flags.alive) continue;1855 if (!atom.isAlive()) continue;
1751 const atoms = &self.sections.items(.atoms)[atom.out_n_sect];1856 const atoms = &self.sections.items(.atoms)[atom.out_n_sect];
1752 try atoms.append(gpa, .{ .index = atom_index, .file = index });1857 try atoms.append(gpa, .{ .index = atom_index, .file = index });
1753 }1858 }
...@@ -1755,7 +1860,7 @@ pub fn addAtomsToSections(self: *MachO) !void {...@@ -1755,7 +1860,7 @@ pub fn addAtomsToSections(self: *MachO) !void {
1755 if (self.getInternalObject()) |object| {1860 if (self.getInternalObject()) |object| {
1756 for (object.getAtoms()) |atom_index| {1861 for (object.getAtoms()) |atom_index| {
1757 const atom = object.getAtom(atom_index) orelse continue;1862 const atom = object.getAtom(atom_index) orelse continue;
1758 if (!atom.flags.alive) continue;1863 if (!atom.isAlive()) continue;
1759 const atoms = &self.sections.items(.atoms)[atom.out_n_sect];1864 const atoms = &self.sections.items(.atoms)[atom.out_n_sect];
1760 try atoms.append(gpa, .{ .index = atom_index, .file = object.index });1865 try atoms.append(gpa, .{ .index = atom_index, .file = object.index });
1761 }1866 }
...@@ -1774,46 +1879,43 @@ fn calcSectionSizes(self: *MachO) !void {...@@ -1774,46 +1879,43 @@ fn calcSectionSizes(self: *MachO) !void {
1774 header.@"align" = 3;1879 header.@"align" = 3;
1775 }1880 }
17761881
1777 const slice = self.sections.slice();1882 const tp = self.base.comp.thread_pool;
1778 for (slice.items(.header), slice.items(.atoms)) |*header, atoms| {1883 var wg: WaitGroup = .{};
1779 if (atoms.items.len == 0) continue;1884 {
1780 if (self.requiresThunks() and header.isCode()) continue;1885 wg.reset();
17811886 defer wg.wait();
1782 for (atoms.items) |ref| {1887 const slice = self.sections.slice();
1783 const atom = ref.getAtom(self).?;
1784 const atom_alignment = atom.alignment.toByteUnits() orelse 1;
1785 const offset = mem.alignForward(u64, header.size, atom_alignment);
1786 const padding = offset - header.size;
1787 atom.value = offset;
1788 header.size += padding + atom.size;
1789 header.@"align" = @max(header.@"align", atom.alignment.toLog2Units());
1790 }
1791 }
1792
1793 if (self.requiresThunks()) {
1794 for (slice.items(.header), slice.items(.atoms), 0..) |header, atoms, i| {1888 for (slice.items(.header), slice.items(.atoms), 0..) |header, atoms, i| {
1795 if (!header.isCode()) continue;
1796 if (atoms.items.len == 0) continue;1889 if (atoms.items.len == 0) continue;
1890 if (self.requiresThunks() and header.isCode()) continue;
1891 tp.spawnWg(&wg, calcSectionSizeWorker, .{ self, @as(u8, @intCast(i)) });
1892 }
17971893
1798 // Create jump/branch range extenders if needed.1894 if (self.requiresThunks()) {
1799 try thunks.createThunks(@intCast(i), self);1895 for (slice.items(.header), slice.items(.atoms), 0..) |header, atoms, i| {
1896 if (!header.isCode()) continue;
1897 if (atoms.items.len == 0) continue;
1898 tp.spawnWg(&wg, createThunksWorker, .{ self, @as(u8, @intCast(i)) });
1899 }
1800 }1900 }
1801 }
18021901
1803 // At this point, we can also calculate symtab and data-in-code linkedit section sizes1902 // At this point, we can also calculate symtab and data-in-code linkedit section sizes
1804 if (self.getZigObject()) |zo| {1903 if (self.getZigObject()) |zo| {
1805 zo.asFile().calcSymtabSize(self);1904 tp.spawnWg(&wg, File.calcSymtabSize, .{ zo.asFile(), self });
1806 }1905 }
1807 for (self.objects.items) |index| {1906 for (self.objects.items) |index| {
1808 self.getFile(index).?.calcSymtabSize(self);1907 tp.spawnWg(&wg, File.calcSymtabSize, .{ self.getFile(index).?, self });
1809 }1908 }
1810 for (self.dylibs.items) |index| {1909 for (self.dylibs.items) |index| {
1811 self.getFile(index).?.calcSymtabSize(self);1910 tp.spawnWg(&wg, File.calcSymtabSize, .{ self.getFile(index).?, self });
1812 }1911 }
1813 if (self.getInternalObject()) |obj| {1912 if (self.getInternalObject()) |obj| {
1814 obj.asFile().calcSymtabSize(self);1913 tp.spawnWg(&wg, File.calcSymtabSize, .{ obj.asFile(), self });
1914 }
1815 }1915 }
18161916
1917 if (self.has_errors.swap(false, .seq_cst)) return error.FlushFailure;
1918
1817 try self.calcSymtabSize();1919 try self.calcSymtabSize();
18181920
1819 if (self.got_sect_index) |idx| {1921 if (self.got_sect_index) |idx| {
...@@ -1861,6 +1963,49 @@ fn calcSectionSizes(self: *MachO) !void {...@@ -1861,6 +1963,49 @@ fn calcSectionSizes(self: *MachO) !void {
1861 }1963 }
1862}1964}
18631965
1966fn calcSectionSizeWorker(self: *MachO, sect_id: u8) void {
1967 const tracy = trace(@src());
1968 defer tracy.end();
1969 const doWork = struct {
1970 fn doWork(macho_file: *MachO, header: *macho.section_64, atoms: []const Ref) !void {
1971 for (atoms) |ref| {
1972 const atom = ref.getAtom(macho_file).?;
1973 const atom_alignment = atom.alignment.toByteUnits() orelse 1;
1974 const offset = mem.alignForward(u64, header.size, atom_alignment);
1975 const padding = offset - header.size;
1976 atom.value = offset;
1977 header.size += padding + atom.size;
1978 header.@"align" = @max(header.@"align", atom.alignment.toLog2Units());
1979 }
1980 }
1981 }.doWork;
1982 const slice = self.sections.slice();
1983 const header = &slice.items(.header)[sect_id];
1984 const atoms = slice.items(.atoms)[sect_id].items;
1985 doWork(self, header, atoms) catch |err| {
1986 self.reportUnexpectedError("failed to calculate size of section '{s},{s}': {s}", .{
1987 header.segName(),
1988 header.sectName(),
1989 @errorName(err),
1990 }) catch {};
1991 _ = self.has_errors.swap(true, .seq_cst);
1992 };
1993}
1994
1995fn createThunksWorker(self: *MachO, sect_id: u8) void {
1996 const tracy = trace(@src());
1997 defer tracy.end();
1998 thunks.createThunks(sect_id, self) catch |err| {
1999 const header = self.sections.items(.header)[sect_id];
2000 self.reportUnexpectedError("failed to create thunks and calculate size of section '{s},{s}': {s}", .{
2001 header.segName(),
2002 header.sectName(),
2003 @errorName(err),
2004 }) catch {};
2005 _ = self.has_errors.swap(true, .seq_cst);
2006 };
2007}
2008
1864fn generateUnwindInfo(self: *MachO) !void {2009fn generateUnwindInfo(self: *MachO) !void {
1865 const tracy = trace(@src());2010 const tracy = trace(@src());
1866 defer tracy.end();2011 defer tracy.end();
...@@ -2249,64 +2394,98 @@ fn writeSectionsAndUpdateLinkeditSizes(self: *MachO) !void {...@@ -2249,64 +2394,98 @@ fn writeSectionsAndUpdateLinkeditSizes(self: *MachO) !void {
2249 try self.strtab.resize(gpa, cmd.strsize);2394 try self.strtab.resize(gpa, cmd.strsize);
2250 self.strtab.items[0] = 0;2395 self.strtab.items[0] = 0;
22512396
2252 for (self.objects.items) |index| {2397 const tp = self.base.comp.thread_pool;
2253 try self.getFile(index).?.writeAtoms(self);2398 var wg: WaitGroup = .{};
2254 }2399 {
2255 if (self.getZigObject()) |zo| {2400 wg.reset();
2256 try zo.writeAtoms(self);2401 defer wg.wait();
2257 }
2258 if (self.getInternalObject()) |obj| {
2259 try obj.asFile().writeAtoms(self);
2260 }
2261 for (self.thunks.items) |thunk| {
2262 const out = self.sections.items(.out)[thunk.out_n_sect].items;
2263 const off = math.cast(usize, thunk.value) orelse return error.Overflow;
2264 const size = thunk.size();
2265 var stream = std.io.fixedBufferStream(out[off..][0..size]);
2266 try thunk.write(self, stream.writer());
2267 }
22682402
2269 const slice = self.sections.slice();2403 for (self.objects.items) |index| {
2270 for (&[_]?u8{2404 tp.spawnWg(&wg, writeAtomsWorker, .{ self, self.getFile(index).? });
2271 self.eh_frame_sect_index,2405 }
2272 self.unwind_info_sect_index,2406 if (self.getZigObject()) |zo| {
2273 self.got_sect_index,2407 tp.spawnWg(&wg, writeAtomsWorker, .{ self, zo.asFile() });
2274 self.stubs_sect_index,2408 }
2275 self.la_symbol_ptr_sect_index,2409 if (self.getInternalObject()) |obj| {
2276 self.tlv_ptr_sect_index,2410 tp.spawnWg(&wg, writeAtomsWorker, .{ self, obj.asFile() });
2277 self.objc_stubs_sect_index,2411 }
2278 }) |maybe_sect_id| {2412 for (self.thunks.items) |thunk| {
2279 if (maybe_sect_id) |sect_id| {2413 tp.spawnWg(&wg, writeThunkWorker, .{ self, thunk });
2280 const out = slice.items(.out)[sect_id].items;
2281 try self.writeSyntheticSection(sect_id, out);
2282 }2414 }
2283 }
22842415
2285 if (self.la_symbol_ptr_sect_index) |_| {2416 const slice = self.sections.slice();
2286 try self.updateLazyBindSize();2417 for (&[_]?u8{
2287 }2418 self.eh_frame_sect_index,
2419 self.unwind_info_sect_index,
2420 self.got_sect_index,
2421 self.stubs_sect_index,
2422 self.la_symbol_ptr_sect_index,
2423 self.tlv_ptr_sect_index,
2424 self.objc_stubs_sect_index,
2425 }) |maybe_sect_id| {
2426 if (maybe_sect_id) |sect_id| {
2427 const out = slice.items(.out)[sect_id].items;
2428 tp.spawnWg(&wg, writeSyntheticSectionWorker, .{ self, sect_id, out });
2429 }
2430 }
22882431
2289 try self.rebase.updateSize(self);2432 if (self.la_symbol_ptr_sect_index) |_| {
2290 try self.bind.updateSize(self);2433 tp.spawnWg(&wg, updateLazyBindSizeWorker, .{self});
2291 try self.weak_bind.updateSize(self);2434 }
2292 try self.export_trie.updateSize(self);
2293 try self.data_in_code.updateSize(self);
22942435
2295 if (self.getZigObject()) |zo| {2436 tp.spawnWg(&wg, updateLinkeditSizeWorker, .{ self, .rebase });
2296 zo.asFile().writeSymtab(self, self);2437 tp.spawnWg(&wg, updateLinkeditSizeWorker, .{ self, .bind });
2297 }2438 tp.spawnWg(&wg, updateLinkeditSizeWorker, .{ self, .weak_bind });
2298 for (self.objects.items) |index| {2439 tp.spawnWg(&wg, updateLinkeditSizeWorker, .{ self, .export_trie });
2299 self.getFile(index).?.writeSymtab(self, self);2440 tp.spawnWg(&wg, updateLinkeditSizeWorker, .{ self, .data_in_code });
2300 }2441
2301 for (self.dylibs.items) |index| {2442 if (self.getZigObject()) |zo| {
2302 self.getFile(index).?.writeSymtab(self, self);2443 tp.spawnWg(&wg, File.writeSymtab, .{ zo.asFile(), self, self });
2303 }2444 }
2304 if (self.getInternalObject()) |obj| {2445 for (self.objects.items) |index| {
2305 obj.asFile().writeSymtab(self, self);2446 tp.spawnWg(&wg, File.writeSymtab, .{ self.getFile(index).?, self, self });
2447 }
2448 for (self.dylibs.items) |index| {
2449 tp.spawnWg(&wg, File.writeSymtab, .{ self.getFile(index).?, self, self });
2450 }
2451 if (self.getInternalObject()) |obj| {
2452 tp.spawnWg(&wg, File.writeSymtab, .{ obj.asFile(), self, self });
2453 }
2306 }2454 }
2455
2456 if (self.has_errors.swap(false, .seq_cst)) return error.FlushFailure;
2457}
2458
2459fn writeAtomsWorker(self: *MachO, file: File) void {
2460 const tracy = trace(@src());
2461 defer tracy.end();
2462 file.writeAtoms(self) catch |err| {
2463 self.reportParseError2(file.getIndex(), "failed to resolve relocations and write atoms: {s}", .{
2464 @errorName(err),
2465 }) catch {};
2466 _ = self.has_errors.swap(true, .seq_cst);
2467 };
2307}2468}
23082469
2309fn writeSyntheticSection(self: *MachO, sect_id: u8, out: []u8) !void {2470fn writeThunkWorker(self: *MachO, thunk: Thunk) void {
2471 const tracy = trace(@src());
2472 defer tracy.end();
2473 const doWork = struct {
2474 fn doWork(th: Thunk, buffer: []u8, macho_file: *MachO) !void {
2475 const off = th.value;
2476 const size = th.size();
2477 var stream = std.io.fixedBufferStream(buffer[off..][0..size]);
2478 try th.write(macho_file, stream.writer());
2479 }
2480 }.doWork;
2481 const out = self.sections.items(.out)[thunk.out_n_sect].items;
2482 doWork(thunk, out, self) catch |err| {
2483 self.reportUnexpectedError("failed to write contents of thunk: {s}", .{@errorName(err)}) catch {};
2484 _ = self.has_errors.swap(true, .seq_cst);
2485 };
2486}
2487
2488fn writeSyntheticSectionWorker(self: *MachO, sect_id: u8, out: []u8) void {
2310 const tracy = trace(@src());2489 const tracy = trace(@src());
2311 defer tracy.end();2490 defer tracy.end();
23122491
...@@ -2320,6 +2499,22 @@ fn writeSyntheticSection(self: *MachO, sect_id: u8, out: []u8) !void {...@@ -2320,6 +2499,22 @@ fn writeSyntheticSection(self: *MachO, sect_id: u8, out: []u8) !void {
2320 objc_stubs,2499 objc_stubs,
2321 };2500 };
23222501
2502 const doWork = struct {
2503 fn doWork(macho_file: *MachO, tag: Tag, buffer: []u8) !void {
2504 var stream = std.io.fixedBufferStream(buffer);
2505 switch (tag) {
2506 .eh_frame => eh_frame.write(macho_file, buffer),
2507 .unwind_info => try macho_file.unwind_info.write(macho_file, buffer),
2508 .got => try macho_file.got.write(macho_file, stream.writer()),
2509 .stubs => try macho_file.stubs.write(macho_file, stream.writer()),
2510 .la_symbol_ptr => try macho_file.la_symbol_ptr.write(macho_file, stream.writer()),
2511 .tlv_ptr => try macho_file.tlv_ptr.write(macho_file, stream.writer()),
2512 .objc_stubs => try macho_file.objc_stubs.write(macho_file, stream.writer()),
2513 }
2514 }
2515 }.doWork;
2516
2517 const header = self.sections.items(.header)[sect_id];
2323 const tag: Tag = tag: {2518 const tag: Tag = tag: {
2324 if (self.eh_frame_sect_index != null and2519 if (self.eh_frame_sect_index != null and
2325 self.eh_frame_sect_index.? == sect_id) break :tag .eh_frame;2520 self.eh_frame_sect_index.? == sect_id) break :tag .eh_frame;
...@@ -2337,26 +2532,57 @@ fn writeSyntheticSection(self: *MachO, sect_id: u8, out: []u8) !void {...@@ -2337,26 +2532,57 @@ fn writeSyntheticSection(self: *MachO, sect_id: u8, out: []u8) !void {
2337 self.objc_stubs_sect_index.? == sect_id) break :tag .objc_stubs;2532 self.objc_stubs_sect_index.? == sect_id) break :tag .objc_stubs;
2338 unreachable;2533 unreachable;
2339 };2534 };
2340 var stream = std.io.fixedBufferStream(out);2535 doWork(self, tag, out) catch |err| {
2341 switch (tag) {2536 self.reportUnexpectedError("could not write section '{s},{s}': {s}", .{
2342 .eh_frame => eh_frame.write(self, out),2537 header.segName(),
2343 .unwind_info => try self.unwind_info.write(self, out),2538 header.sectName(),
2344 .got => try self.got.write(self, stream.writer()),2539 @errorName(err),
2345 .stubs => try self.stubs.write(self, stream.writer()),2540 }) catch {};
2346 .la_symbol_ptr => try self.la_symbol_ptr.write(self, stream.writer()),2541 _ = self.has_errors.swap(true, .seq_cst);
2347 .tlv_ptr => try self.tlv_ptr.write(self, stream.writer()),2542 };
2348 .objc_stubs => try self.objc_stubs.write(self, stream.writer()),
2349 }
2350}2543}
23512544
2352fn updateLazyBindSize(self: *MachO) !void {2545fn updateLazyBindSizeWorker(self: *MachO) void {
2353 const tracy = trace(@src());2546 const tracy = trace(@src());
2354 defer tracy.end();2547 defer tracy.end();
2355 try self.lazy_bind.updateSize(self);2548 const doWork = struct {
2356 const sect_id = self.stubs_helper_sect_index.?;2549 fn doWork(macho_file: *MachO) !void {
2357 const out = &self.sections.items(.out)[sect_id];2550 try macho_file.lazy_bind.updateSize(macho_file);
2358 var stream = std.io.fixedBufferStream(out.items);2551 const sect_id = macho_file.stubs_helper_sect_index.?;
2359 try self.stubs_helper.write(self, stream.writer());2552 const out = &macho_file.sections.items(.out)[sect_id];
2553 var stream = std.io.fixedBufferStream(out.items);
2554 try macho_file.stubs_helper.write(macho_file, stream.writer());
2555 }
2556 }.doWork;
2557 doWork(self) catch |err| {
2558 self.reportUnexpectedError("could not calculate size of lazy binding section: {s}", .{
2559 @errorName(err),
2560 }) catch {};
2561 _ = self.has_errors.swap(true, .seq_cst);
2562 };
2563}
2564
2565pub fn updateLinkeditSizeWorker(self: *MachO, tag: enum {
2566 rebase,
2567 bind,
2568 weak_bind,
2569 export_trie,
2570 data_in_code,
2571}) void {
2572 const res = switch (tag) {
2573 .rebase => self.rebase.updateSize(self),
2574 .bind => self.bind.updateSize(self),
2575 .weak_bind => self.weak_bind.updateSize(self),
2576 .export_trie => self.export_trie.updateSize(self),
2577 .data_in_code => self.data_in_code.updateSize(self),
2578 };
2579 res catch |err| {
2580 self.reportUnexpectedError("could not calculate size of {s} section: {s}", .{
2581 @tagName(tag),
2582 @errorName(err),
2583 }) catch {};
2584 _ = self.has_errors.swap(true, .seq_cst);
2585 };
2360}2586}
23612587
2362fn writeSectionsToFile(self: *MachO) !void {2588fn writeSectionsToFile(self: *MachO) !void {
...@@ -2684,13 +2910,13 @@ fn writeHeader(self: *MachO, ncmds: usize, sizeofcmds: usize) !void {...@@ -2684,13 +2910,13 @@ fn writeHeader(self: *MachO, ncmds: usize, sizeofcmds: usize) !void {
2684 header.flags |= macho.MH_NO_REEXPORTED_DYLIBS;2910 header.flags |= macho.MH_NO_REEXPORTED_DYLIBS;
2685 }2911 }
26862912
2687 if (self.has_tlv) {2913 if (self.has_tlv.load(.seq_cst)) {
2688 header.flags |= macho.MH_HAS_TLV_DESCRIPTORS;2914 header.flags |= macho.MH_HAS_TLV_DESCRIPTORS;
2689 }2915 }
2690 if (self.binds_to_weak) {2916 if (self.binds_to_weak.load(.seq_cst)) {
2691 header.flags |= macho.MH_BINDS_TO_WEAK;2917 header.flags |= macho.MH_BINDS_TO_WEAK;
2692 }2918 }
2693 if (self.weak_defines) {2919 if (self.weak_defines.load(.seq_cst)) {
2694 header.flags |= macho.MH_WEAK_DEFINES;2920 header.flags |= macho.MH_WEAK_DEFINES;
2695 }2921 }
26962922
...@@ -3586,19 +3812,29 @@ fn reportDuplicates(self: *MachO) error{ HasDuplicates, OutOfMemory }!void {...@@ -3586,19 +3812,29 @@ fn reportDuplicates(self: *MachO) error{ HasDuplicates, OutOfMemory }!void {
3586 const tracy = trace(@src());3812 const tracy = trace(@src());
3587 defer tracy.end();3813 defer tracy.end();
35883814
3815 if (self.dupes.keys().len == 0) return; // Nothing to do
3816
3817 const gpa = self.base.comp.gpa;
3589 const max_notes = 3;3818 const max_notes = 3;
35903819
3591 var has_dupes = false;3820 // We will sort by name, and then by file to ensure deterministic output.
3592 var it = self.dupes.iterator();3821 var keys = try std.ArrayList(SymbolResolver.Index).initCapacity(gpa, self.dupes.keys().len);
3593 while (it.next()) |entry| {3822 defer keys.deinit();
3594 const sym = self.resolver.keys.items[entry.key_ptr.* - 1];3823 keys.appendSliceAssumeCapacity(self.dupes.keys());
3595 const notes = entry.value_ptr.*;3824 self.sortGlobalSymbolsByName(keys.items);
3825
3826 for (self.dupes.values()) |*refs| {
3827 mem.sort(File.Index, refs.items, {}, std.sort.asc(File.Index));
3828 }
3829
3830 for (keys.items) |key| {
3831 const sym = self.resolver.keys.items[key - 1];
3832 const notes = self.dupes.get(key).?;
3596 const nnotes = @min(notes.items.len, max_notes) + @intFromBool(notes.items.len > max_notes);3833 const nnotes = @min(notes.items.len, max_notes) + @intFromBool(notes.items.len > max_notes);
35973834
3598 var err = try self.base.addErrorWithNotes(nnotes + 1);3835 var err = try self.base.addErrorWithNotes(nnotes + 1);
3599 try err.addMsg("duplicate symbol definition: {s}", .{sym.getName(self)});3836 try err.addMsg("duplicate symbol definition: {s}", .{sym.getName(self)});
3600 try err.addNote("defined by {}", .{sym.getFile(self).?.fmtPath()});3837 try err.addNote("defined by {}", .{sym.getFile(self).?.fmtPath()});
3601 has_dupes = true;
36023838
3603 var inote: usize = 0;3839 var inote: usize = 0;
3604 while (inote < @min(notes.items.len, max_notes)) : (inote += 1) {3840 while (inote < @min(notes.items.len, max_notes)) : (inote += 1) {
...@@ -3611,7 +3847,7 @@ fn reportDuplicates(self: *MachO) error{ HasDuplicates, OutOfMemory }!void {...@@ -3611,7 +3847,7 @@ fn reportDuplicates(self: *MachO) error{ HasDuplicates, OutOfMemory }!void {
3611 try err.addNote("defined {d} more times", .{remaining});3847 try err.addNote("defined {d} more times", .{remaining});
3612 }3848 }
3613 }3849 }
3614 if (has_dupes) return error.HasDuplicates;3850 return error.HasDuplicates;
3615}3851}
36163852
3617pub fn getDebugSymbols(self: *MachO) ?*DebugSymbols {3853pub fn getDebugSymbols(self: *MachO) ?*DebugSymbols {
...@@ -4210,6 +4446,13 @@ pub const Ref = struct {...@@ -4210,6 +4446,13 @@ pub const Ref = struct {
4210 return ref.index == other.index and ref.file == other.file;4446 return ref.index == other.index and ref.file == other.file;
4211 }4447 }
42124448
4449 pub fn lessThan(ref: Ref, other: Ref) bool {
4450 if (ref.file == other.file) {
4451 return ref.index < other.index;
4452 }
4453 return ref.file < other.file;
4454 }
4455
4213 pub fn getFile(ref: Ref, macho_file: *MachO) ?File {4456 pub fn getFile(ref: Ref, macho_file: *MachO) ?File {
4214 return macho_file.getFile(ref.file);4457 return macho_file.getFile(ref.file);
4215 }4458 }
src/link/MachO/Atom.zig+36-29
...@@ -26,7 +26,11 @@ off: u64 = 0,...@@ -26,7 +26,11 @@ off: u64 = 0,
26/// Index of this atom in the linker's atoms table.26/// Index of this atom in the linker's atoms table.
27atom_index: Index = 0,27atom_index: Index = 0,
2828
29flags: Flags = .{},29/// Specifies whether this atom is alive or has been garbage collected.
30alive: AtomicBool = AtomicBool.init(true),
31
32/// Specifies if this atom has been visited during garbage collection.
33visited: AtomicBool = AtomicBool.init(false),
3034
31/// Points to the previous and next neighbors, based on the `text_offset`.35/// Points to the previous and next neighbors, based on the `text_offset`.
32/// This can be used to find, for example, the capacity of this `TextBlock`.36/// This can be used to find, for example, the capacity of this `TextBlock`.
...@@ -98,6 +102,14 @@ pub fn markUnwindRecordsDead(self: Atom, macho_file: *MachO) void {...@@ -98,6 +102,14 @@ pub fn markUnwindRecordsDead(self: Atom, macho_file: *MachO) void {
98 }102 }
99}103}
100104
105pub fn isAlive(self: Atom) bool {
106 return self.alive.load(.seq_cst);
107}
108
109pub fn setAlive(self: *Atom, alive: bool) void {
110 _ = self.alive.swap(alive, .seq_cst);
111}
112
101pub fn getThunk(self: Atom, macho_file: *MachO) *Thunk {113pub fn getThunk(self: Atom, macho_file: *MachO) *Thunk {
102 const extra = self.getExtra(macho_file);114 const extra = self.getExtra(macho_file);
103 return macho_file.getThunk(extra.thunk);115 return macho_file.getThunk(extra.thunk);
...@@ -350,7 +362,7 @@ pub fn allocate(self: *Atom, macho_file: *MachO) !void {...@@ -350,7 +362,7 @@ pub fn allocate(self: *Atom, macho_file: *MachO) !void {
350 _ = free_list.swapRemove(i);362 _ = free_list.swapRemove(i);
351 }363 }
352364
353 self.flags.alive = true;365 self.setAlive(true);
354}366}
355367
356pub fn shrink(self: *Atom, macho_file: *MachO) void {368pub fn shrink(self: *Atom, macho_file: *MachO) void {
...@@ -444,7 +456,7 @@ pub fn freeRelocs(self: *Atom, macho_file: *MachO) void {...@@ -444,7 +456,7 @@ pub fn freeRelocs(self: *Atom, macho_file: *MachO) void {
444pub fn scanRelocs(self: Atom, macho_file: *MachO) !void {456pub fn scanRelocs(self: Atom, macho_file: *MachO) !void {
445 const tracy = trace(@src());457 const tracy = trace(@src());
446 defer tracy.end();458 defer tracy.end();
447 assert(self.flags.alive);459 assert(self.isAlive());
448460
449 const relocs = self.getRelocs(macho_file);461 const relocs = self.getRelocs(macho_file);
450462
...@@ -455,12 +467,12 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void {...@@ -455,12 +467,12 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void {
455 .branch => {467 .branch => {
456 const symbol = rel.getTargetSymbol(self, macho_file);468 const symbol = rel.getTargetSymbol(self, macho_file);
457 if (symbol.flags.import or (symbol.flags.@"export" and symbol.flags.weak) or symbol.flags.interposable) {469 if (symbol.flags.import or (symbol.flags.@"export" and symbol.flags.weak) or symbol.flags.interposable) {
458 symbol.flags.stubs = true;470 symbol.setSectionFlags(.{ .stubs = true });
459 if (symbol.flags.weak) {471 if (symbol.flags.weak) {
460 macho_file.binds_to_weak = true;472 macho_file.binds_to_weak.store(true, .seq_cst);
461 }473 }
462 } else if (mem.startsWith(u8, symbol.getName(macho_file), "_objc_msgSend$")) {474 } else if (mem.startsWith(u8, symbol.getName(macho_file), "_objc_msgSend$")) {
463 symbol.flags.objc_stubs = true;475 symbol.setSectionFlags(.{ .objc_stubs = true });
464 }476 }
465 },477 },
466478
...@@ -474,19 +486,19 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void {...@@ -474,19 +486,19 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void {
474 symbol.flags.interposable or486 symbol.flags.interposable or
475 macho_file.getTarget().cpu.arch == .aarch64) // TODO relax on arm64487 macho_file.getTarget().cpu.arch == .aarch64) // TODO relax on arm64
476 {488 {
477 symbol.flags.needs_got = true;489 symbol.setSectionFlags(.{ .needs_got = true });
478 if (symbol.flags.weak) {490 if (symbol.flags.weak) {
479 macho_file.binds_to_weak = true;491 macho_file.binds_to_weak.store(true, .seq_cst);
480 }492 }
481 }493 }
482 },494 },
483495
484 .zig_got_load => {496 .zig_got_load => {
485 assert(rel.getTargetSymbol(self, macho_file).flags.has_zig_got);497 assert(rel.getTargetSymbol(self, macho_file).getSectionFlags().has_zig_got);
486 },498 },
487499
488 .got => {500 .got => {
489 rel.getTargetSymbol(self, macho_file).flags.needs_got = true;501 rel.getTargetSymbol(self, macho_file).setSectionFlags(.{ .needs_got = true });
490 },502 },
491503
492 .tlv,504 .tlv,
...@@ -502,9 +514,9 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void {...@@ -502,9 +514,9 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void {
502 );514 );
503 }515 }
504 if (symbol.flags.import or (symbol.flags.@"export" and symbol.flags.weak) or symbol.flags.interposable) {516 if (symbol.flags.import or (symbol.flags.@"export" and symbol.flags.weak) or symbol.flags.interposable) {
505 symbol.flags.tlv_ptr = true;517 symbol.setSectionFlags(.{ .tlv_ptr = true });
506 if (symbol.flags.weak) {518 if (symbol.flags.weak) {
507 macho_file.binds_to_weak = true;519 macho_file.binds_to_weak.store(true, .seq_cst);
508 }520 }
509 }521 }
510 },522 },
...@@ -514,17 +526,17 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void {...@@ -514,17 +526,17 @@ pub fn scanRelocs(self: Atom, macho_file: *MachO) !void {
514 if (rel.tag == .@"extern") {526 if (rel.tag == .@"extern") {
515 const symbol = rel.getTargetSymbol(self, macho_file);527 const symbol = rel.getTargetSymbol(self, macho_file);
516 if (symbol.isTlvInit(macho_file)) {528 if (symbol.isTlvInit(macho_file)) {
517 macho_file.has_tlv = true;529 macho_file.has_tlv.store(true, .seq_cst);
518 continue;530 continue;
519 }531 }
520 if (symbol.flags.import) {532 if (symbol.flags.import) {
521 if (symbol.flags.weak) {533 if (symbol.flags.weak) {
522 macho_file.binds_to_weak = true;534 macho_file.binds_to_weak.store(true, .seq_cst);
523 }535 }
524 continue;536 continue;
525 }537 }
526 if (symbol.flags.@"export" and symbol.flags.weak) {538 if (symbol.flags.@"export" and symbol.flags.weak) {
527 macho_file.binds_to_weak = true;539 macho_file.binds_to_weak.store(true, .seq_cst);
528 }540 }
529 }541 }
530 }542 }
...@@ -548,6 +560,8 @@ fn reportUndefSymbol(self: Atom, rel: Relocation, macho_file: *MachO) !bool {...@@ -548,6 +560,8 @@ fn reportUndefSymbol(self: Atom, rel: Relocation, macho_file: *MachO) !bool {
548 const file = self.getFile(macho_file);560 const file = self.getFile(macho_file);
549 const ref = file.getSymbolRef(rel.target, macho_file);561 const ref = file.getSymbolRef(rel.target, macho_file);
550 if (ref.getFile(macho_file) == null) {562 if (ref.getFile(macho_file) == null) {
563 macho_file.undefs_mutex.lock();
564 defer macho_file.undefs_mutex.unlock();
551 const gpa = macho_file.base.comp.gpa;565 const gpa = macho_file.base.comp.gpa;
552 const gop = try macho_file.undefs.getOrPut(gpa, file.getGlobals()[rel.target]);566 const gop = try macho_file.undefs.getOrPut(gpa, file.getGlobals()[rel.target]);
553 if (!gop.found_existing) {567 if (!gop.found_existing) {
...@@ -724,7 +738,7 @@ fn resolveRelocInner(...@@ -724,7 +738,7 @@ fn resolveRelocInner(
724 assert(rel.tag == .@"extern");738 assert(rel.tag == .@"extern");
725 assert(rel.meta.length == 2);739 assert(rel.meta.length == 2);
726 assert(rel.meta.pcrel);740 assert(rel.meta.pcrel);
727 if (rel.getTargetSymbol(self, macho_file).flags.has_got) {741 if (rel.getTargetSymbol(self, macho_file).getSectionFlags().has_got) {
728 try writer.writeInt(i32, @intCast(G + A - P), .little);742 try writer.writeInt(i32, @intCast(G + A - P), .little);
729 } else {743 } else {
730 try x86_64.relaxGotLoad(self, code[rel_offset - 3 ..], rel, macho_file);744 try x86_64.relaxGotLoad(self, code[rel_offset - 3 ..], rel, macho_file);
...@@ -748,7 +762,7 @@ fn resolveRelocInner(...@@ -748,7 +762,7 @@ fn resolveRelocInner(
748 assert(rel.meta.length == 2);762 assert(rel.meta.length == 2);
749 assert(rel.meta.pcrel);763 assert(rel.meta.pcrel);
750 const sym = rel.getTargetSymbol(self, macho_file);764 const sym = rel.getTargetSymbol(self, macho_file);
751 if (sym.flags.tlv_ptr) {765 if (sym.getSectionFlags().tlv_ptr) {
752 const S_: i64 = @intCast(sym.getTlvPtrAddress(macho_file));766 const S_: i64 = @intCast(sym.getTlvPtrAddress(macho_file));
753 try writer.writeInt(i32, @intCast(S_ + A - P), .little);767 try writer.writeInt(i32, @intCast(S_ + A - P), .little);
754 } else {768 } else {
...@@ -776,7 +790,7 @@ fn resolveRelocInner(...@@ -776,7 +790,7 @@ fn resolveRelocInner(
776 const target = switch (rel.type) {790 const target = switch (rel.type) {
777 .page => S + A,791 .page => S + A,
778 .got_load_page => G + A,792 .got_load_page => G + A,
779 .tlvp_page => if (sym.flags.tlv_ptr) blk: {793 .tlvp_page => if (sym.getSectionFlags().tlv_ptr) blk: {
780 const S_: i64 = @intCast(sym.getTlvPtrAddress(macho_file));794 const S_: i64 = @intCast(sym.getTlvPtrAddress(macho_file));
781 break :blk S_ + A;795 break :blk S_ + A;
782 } else S + A,796 } else S + A,
...@@ -831,7 +845,7 @@ fn resolveRelocInner(...@@ -831,7 +845,7 @@ fn resolveRelocInner(
831845
832 const sym = rel.getTargetSymbol(self, macho_file);846 const sym = rel.getTargetSymbol(self, macho_file);
833 const target = target: {847 const target = target: {
834 const target = if (sym.flags.tlv_ptr) blk: {848 const target = if (sym.getSectionFlags().tlv_ptr) blk: {
835 const S_: i64 = @intCast(sym.getTlvPtrAddress(macho_file));849 const S_: i64 = @intCast(sym.getTlvPtrAddress(macho_file));
836 break :blk S_ + A;850 break :blk S_ + A;
837 } else S + A;851 } else S + A;
...@@ -869,7 +883,7 @@ fn resolveRelocInner(...@@ -869,7 +883,7 @@ fn resolveRelocInner(
869 }883 }
870 };884 };
871885
872 var inst = if (sym.flags.tlv_ptr) aarch64.Instruction{886 var inst = if (sym.getSectionFlags().tlv_ptr) aarch64.Instruction{
873 .load_store_register = .{887 .load_store_register = .{
874 .rt = reg_info.rd,888 .rt = reg_info.rd,
875 .rn = reg_info.rn,889 .rn = reg_info.rn,
...@@ -1142,7 +1156,7 @@ fn format2(...@@ -1142,7 +1156,7 @@ fn format2(
1142 atom.out_n_sect, atom.alignment, atom.size,1156 atom.out_n_sect, atom.alignment, atom.size,
1143 atom.getRelocs(macho_file).len, atom.getExtra(macho_file).thunk,1157 atom.getRelocs(macho_file).len, atom.getExtra(macho_file).thunk,
1144 });1158 });
1145 if (!atom.flags.alive) try writer.writeAll(" : [*]");1159 if (!atom.isAlive()) try writer.writeAll(" : [*]");
1146 if (atom.getUnwindRecords(macho_file).len > 0) {1160 if (atom.getUnwindRecords(macho_file).len > 0) {
1147 try writer.writeAll(" : unwind{ ");1161 try writer.writeAll(" : unwind{ ");
1148 const extra = atom.getExtra(macho_file);1162 const extra = atom.getExtra(macho_file);
...@@ -1158,14 +1172,6 @@ fn format2(...@@ -1158,14 +1172,6 @@ fn format2(
11581172
1159pub const Index = u32;1173pub const Index = u32;
11601174
1161pub const Flags = packed struct {
1162 /// Specifies whether this atom is alive or has been garbage collected.
1163 alive: bool = true,
1164
1165 /// Specifies if this atom has been visited during garbage collection.
1166 visited: bool = false,
1167};
1168
1169pub const Extra = struct {1175pub const Extra = struct {
1170 /// Index of the range extension thunk of this atom.1176 /// Index of the range extension thunk of this atom.
1171 thunk: u32 = 0,1177 thunk: u32 = 0,
...@@ -1209,6 +1215,7 @@ const trace = @import("../../tracy.zig").trace;...@@ -1209,6 +1215,7 @@ const trace = @import("../../tracy.zig").trace;
12091215
1210const Allocator = mem.Allocator;1216const Allocator = mem.Allocator;
1211const Atom = @This();1217const Atom = @This();
1218const AtomicBool = std.atomic.Value(bool);
1212const File = @import("file.zig").File;1219const File = @import("file.zig").File;
1213const MachO = @import("../MachO.zig");1220const MachO = @import("../MachO.zig");
1214const Object = @import("Object.zig");1221const Object = @import("Object.zig");
src/link/MachO/InternalObject.zig+8-8
...@@ -389,7 +389,7 @@ pub fn resolveObjcMsgSendSymbols(self: *InternalObject, macho_file: *MachO) !voi...@@ -389,7 +389,7 @@ pub fn resolveObjcMsgSendSymbols(self: *InternalObject, macho_file: *MachO) !voi
389 };389 };
390 sym.nlist_idx = nlist_idx;390 sym.nlist_idx = nlist_idx;
391 sym.extra = try self.addSymbolExtra(gpa, .{ .objc_selrefs = selrefs_index });391 sym.extra = try self.addSymbolExtra(gpa, .{ .objc_selrefs = selrefs_index });
392 sym.flags.objc_stubs = true;392 sym.setSectionFlags(.{ .objc_stubs = true });
393393
394 const idx = ref.getFile(macho_file).?.object.globals.items[ref.index];394 const idx = ref.getFile(macho_file).?.object.globals.items[ref.index];
395 try self.globals.append(gpa, idx);395 try self.globals.append(gpa, idx);
...@@ -427,7 +427,7 @@ pub fn resolveLiterals(self: *InternalObject, lp: *MachO.LiteralPool, macho_file...@@ -427,7 +427,7 @@ pub fn resolveLiterals(self: *InternalObject, lp: *MachO.LiteralPool, macho_file
427 const lp_sym = lp.getSymbol(res.index, macho_file);427 const lp_sym = lp.getSymbol(res.index, macho_file);
428 const lp_atom = lp_sym.getAtom(macho_file).?;428 const lp_atom = lp_sym.getAtom(macho_file).?;
429 lp_atom.alignment = lp_atom.alignment.max(atom.alignment);429 lp_atom.alignment = lp_atom.alignment.max(atom.alignment);
430 atom.flags.alive = false;430 atom.setAlive(false);
431 }431 }
432 atom.addExtra(.{ .literal_pool_index = res.index }, macho_file);432 atom.addExtra(.{ .literal_pool_index = res.index }, macho_file);
433 }433 }
...@@ -439,7 +439,7 @@ pub fn dedupLiterals(self: *InternalObject, lp: MachO.LiteralPool, macho_file: *...@@ -439,7 +439,7 @@ pub fn dedupLiterals(self: *InternalObject, lp: MachO.LiteralPool, macho_file: *
439439
440 for (self.getAtoms()) |atom_index| {440 for (self.getAtoms()) |atom_index| {
441 const atom = self.getAtom(atom_index) orelse continue;441 const atom = self.getAtom(atom_index) orelse continue;
442 if (!atom.flags.alive) continue;442 if (!atom.isAlive()) continue;
443443
444 const relocs = blk: {444 const relocs = blk: {
445 const extra = atom.getExtra(macho_file);445 const extra = atom.getExtra(macho_file);
...@@ -464,7 +464,7 @@ pub fn dedupLiterals(self: *InternalObject, lp: MachO.LiteralPool, macho_file: *...@@ -464,7 +464,7 @@ pub fn dedupLiterals(self: *InternalObject, lp: MachO.LiteralPool, macho_file: *
464 }464 }
465465
466 for (self.symbols.items) |*sym| {466 for (self.symbols.items) |*sym| {
467 if (!sym.flags.objc_stubs) continue;467 if (!sym.getSectionFlags().objc_stubs) continue;
468 const extra = sym.getExtra(macho_file);468 const extra = sym.getExtra(macho_file);
469 const file = sym.getFile(macho_file).?;469 const file = sym.getFile(macho_file).?;
470 if (file.getIndex() != self.index) continue;470 if (file.getIndex() != self.index) continue;
...@@ -490,20 +490,20 @@ pub fn scanRelocs(self: *InternalObject, macho_file: *MachO) void {...@@ -490,20 +490,20 @@ pub fn scanRelocs(self: *InternalObject, macho_file: *MachO) void {
490 if (self.getEntryRef(macho_file)) |ref| {490 if (self.getEntryRef(macho_file)) |ref| {
491 if (ref.getFile(macho_file) != null) {491 if (ref.getFile(macho_file) != null) {
492 const sym = ref.getSymbol(macho_file).?;492 const sym = ref.getSymbol(macho_file).?;
493 if (sym.flags.import) sym.flags.stubs = true;493 if (sym.flags.import) sym.setSectionFlags(.{ .stubs = true });
494 }494 }
495 }495 }
496 if (self.getDyldStubBinderRef(macho_file)) |ref| {496 if (self.getDyldStubBinderRef(macho_file)) |ref| {
497 if (ref.getFile(macho_file) != null) {497 if (ref.getFile(macho_file) != null) {
498 const sym = ref.getSymbol(macho_file).?;498 const sym = ref.getSymbol(macho_file).?;
499 sym.flags.needs_got = true;499 sym.setSectionFlags(.{ .needs_got = true });
500 }500 }
501 }501 }
502 if (self.getObjcMsgSendRef(macho_file)) |ref| {502 if (self.getObjcMsgSendRef(macho_file)) |ref| {
503 if (ref.getFile(macho_file) != null) {503 if (ref.getFile(macho_file) != null) {
504 const sym = ref.getSymbol(macho_file).?;504 const sym = ref.getSymbol(macho_file).?;
505 // TODO is it always needed, or only if we are synthesising fast stubs505 // TODO is it always needed, or only if we are synthesising fast stubs
506 sym.flags.needs_got = true;506 sym.setSectionFlags(.{ .needs_got = true });
507 }507 }
508 }508 }
509}509}
...@@ -570,7 +570,7 @@ pub fn writeAtoms(self: *InternalObject, macho_file: *MachO) !void {...@@ -570,7 +570,7 @@ pub fn writeAtoms(self: *InternalObject, macho_file: *MachO) !void {
570570
571 for (self.getAtoms()) |atom_index| {571 for (self.getAtoms()) |atom_index| {
572 const atom = self.getAtom(atom_index) orelse continue;572 const atom = self.getAtom(atom_index) orelse continue;
573 if (!atom.flags.alive) continue;573 if (!atom.isAlive()) continue;
574 const sect = atom.getInputSection(macho_file);574 const sect = atom.getInputSection(macho_file);
575 if (sect.isZerofill()) continue;575 if (sect.isZerofill()) continue;
576 const off = std.math.cast(usize, atom.value) orelse return error.Overflow;576 const off = std.math.cast(usize, atom.value) orelse return error.Overflow;
src/link/MachO/Object.zig+12-12
...@@ -263,7 +263,7 @@ pub fn parse(self: *Object, macho_file: *MachO) !void {...@@ -263,7 +263,7 @@ pub fn parse(self: *Object, macho_file: *MachO) !void {
263 mem.eql(u8, isec.sectName(), "__compact_unwind") or263 mem.eql(u8, isec.sectName(), "__compact_unwind") or
264 isec.attrs() & macho.S_ATTR_DEBUG != 0)264 isec.attrs() & macho.S_ATTR_DEBUG != 0)
265 {265 {
266 atom.flags.alive = false;266 atom.setAlive(false);
267 }267 }
268 }268 }
269269
...@@ -645,7 +645,7 @@ pub fn resolveLiterals(self: *Object, lp: *MachO.LiteralPool, macho_file: *MachO...@@ -645,7 +645,7 @@ pub fn resolveLiterals(self: *Object, lp: *MachO.LiteralPool, macho_file: *MachO
645 const lp_sym = lp.getSymbol(res.index, macho_file);645 const lp_sym = lp.getSymbol(res.index, macho_file);
646 const lp_atom = lp_sym.getAtom(macho_file).?;646 const lp_atom = lp_sym.getAtom(macho_file).?;
647 lp_atom.alignment = lp_atom.alignment.max(atom.alignment);647 lp_atom.alignment = lp_atom.alignment.max(atom.alignment);
648 atom.flags.alive = false;648 atom.setAlive(false);
649 }649 }
650 atom.addExtra(.{ .literal_pool_index = res.index }, macho_file);650 atom.addExtra(.{ .literal_pool_index = res.index }, macho_file);
651 }651 }
...@@ -683,7 +683,7 @@ pub fn resolveLiterals(self: *Object, lp: *MachO.LiteralPool, macho_file: *MachO...@@ -683,7 +683,7 @@ pub fn resolveLiterals(self: *Object, lp: *MachO.LiteralPool, macho_file: *MachO
683 const lp_sym = lp.getSymbol(res.index, macho_file);683 const lp_sym = lp.getSymbol(res.index, macho_file);
684 const lp_atom = lp_sym.getAtom(macho_file).?;684 const lp_atom = lp_sym.getAtom(macho_file).?;
685 lp_atom.alignment = lp_atom.alignment.max(atom.alignment);685 lp_atom.alignment = lp_atom.alignment.max(atom.alignment);
686 atom.flags.alive = false;686 atom.setAlive(false);
687 }687 }
688 atom.addExtra(.{ .literal_pool_index = res.index }, macho_file);688 atom.addExtra(.{ .literal_pool_index = res.index }, macho_file);
689 }689 }
...@@ -697,7 +697,7 @@ pub fn dedupLiterals(self: *Object, lp: MachO.LiteralPool, macho_file: *MachO) v...@@ -697,7 +697,7 @@ pub fn dedupLiterals(self: *Object, lp: MachO.LiteralPool, macho_file: *MachO) v
697697
698 for (self.getAtoms()) |atom_index| {698 for (self.getAtoms()) |atom_index| {
699 const atom = self.getAtom(atom_index) orelse continue;699 const atom = self.getAtom(atom_index) orelse continue;
700 if (!atom.flags.alive) continue;700 if (!atom.isAlive()) continue;
701701
702 const relocs = blk: {702 const relocs = blk: {
703 const extra = atom.getExtra(macho_file);703 const extra = atom.getExtra(macho_file);
...@@ -990,7 +990,7 @@ fn initRelocs(self: *Object, file: File.Handle, cpu_arch: std.Target.Cpu.Arch, m...@@ -990,7 +990,7 @@ fn initRelocs(self: *Object, file: File.Handle, cpu_arch: std.Target.Cpu.Arch, m
990 var next_reloc: u32 = 0;990 var next_reloc: u32 = 0;
991 for (subsections.items) |subsection| {991 for (subsections.items) |subsection| {
992 const atom = self.getAtom(subsection.atom).?;992 const atom = self.getAtom(subsection.atom).?;
993 if (!atom.flags.alive) continue;993 if (!atom.isAlive()) continue;
994 if (next_reloc >= relocs.items.len) break;994 if (next_reloc >= relocs.items.len) break;
995 const end_addr = atom.off + atom.size;995 const end_addr = atom.off + atom.size;
996 const rel_index = next_reloc;996 const rel_index = next_reloc;
...@@ -1483,7 +1483,7 @@ pub fn resolveSymbols(self: *Object, macho_file: *MachO) !void {...@@ -1483,7 +1483,7 @@ pub fn resolveSymbols(self: *Object, macho_file: *MachO) !void {
1483 if (!nlist.ext()) continue;1483 if (!nlist.ext()) continue;
1484 if (nlist.sect()) {1484 if (nlist.sect()) {
1485 const atom = self.getAtom(atom_index).?;1485 const atom = self.getAtom(atom_index).?;
1486 if (!atom.flags.alive) continue;1486 if (!atom.isAlive()) continue;
1487 }1487 }
14881488
1489 const gop = try macho_file.resolver.getOrPut(gpa, .{1489 const gop = try macho_file.resolver.getOrPut(gpa, .{
...@@ -1552,7 +1552,7 @@ pub fn scanRelocs(self: *Object, macho_file: *MachO) !void {...@@ -1552,7 +1552,7 @@ pub fn scanRelocs(self: *Object, macho_file: *MachO) !void {
15521552
1553 for (self.getAtoms()) |atom_index| {1553 for (self.getAtoms()) |atom_index| {
1554 const atom = self.getAtom(atom_index) orelse continue;1554 const atom = self.getAtom(atom_index) orelse continue;
1555 if (!atom.flags.alive) continue;1555 if (!atom.isAlive()) continue;
1556 const sect = atom.getInputSection(macho_file);1556 const sect = atom.getInputSection(macho_file);
1557 if (sect.isZerofill()) continue;1557 if (sect.isZerofill()) continue;
1558 try atom.scanRelocs(macho_file);1558 try atom.scanRelocs(macho_file);
...@@ -1563,10 +1563,10 @@ pub fn scanRelocs(self: *Object, macho_file: *MachO) !void {...@@ -1563,10 +1563,10 @@ pub fn scanRelocs(self: *Object, macho_file: *MachO) !void {
1563 if (!rec.alive) continue;1563 if (!rec.alive) continue;
1564 if (rec.getFde(macho_file)) |fde| {1564 if (rec.getFde(macho_file)) |fde| {
1565 if (fde.getCie(macho_file).getPersonality(macho_file)) |sym| {1565 if (fde.getCie(macho_file).getPersonality(macho_file)) |sym| {
1566 sym.flags.needs_got = true;1566 sym.setSectionFlags(.{ .needs_got = true });
1567 }1567 }
1568 } else if (rec.getPersonality(macho_file)) |sym| {1568 } else if (rec.getPersonality(macho_file)) |sym| {
1569 sym.flags.needs_got = true;1569 sym.setSectionFlags(.{ .needs_got = true });
1570 }1570 }
1571 }1571 }
1572}1572}
...@@ -1745,7 +1745,7 @@ pub fn calcSymtabSize(self: *Object, macho_file: *MachO) void {...@@ -1745,7 +1745,7 @@ pub fn calcSymtabSize(self: *Object, macho_file: *MachO) void {
1745 const ref = self.getSymbolRef(@intCast(i), macho_file);1745 const ref = self.getSymbolRef(@intCast(i), macho_file);
1746 const file = ref.getFile(macho_file) orelse continue;1746 const file = ref.getFile(macho_file) orelse continue;
1747 if (file.getIndex() != self.index) continue;1747 if (file.getIndex() != self.index) continue;
1748 if (sym.getAtom(macho_file)) |atom| if (!atom.flags.alive) continue;1748 if (sym.getAtom(macho_file)) |atom| if (!atom.isAlive()) continue;
1749 if (sym.isSymbolStab(macho_file)) continue;1749 if (sym.isSymbolStab(macho_file)) continue;
1750 const name = sym.getName(macho_file);1750 const name = sym.getName(macho_file);
1751 if (name.len == 0) continue;1751 if (name.len == 0) continue;
...@@ -1854,7 +1854,7 @@ pub fn writeAtoms(self: *Object, macho_file: *MachO) !void {...@@ -1854,7 +1854,7 @@ pub fn writeAtoms(self: *Object, macho_file: *MachO) !void {
1854 }1854 }
1855 for (self.getAtoms()) |atom_index| {1855 for (self.getAtoms()) |atom_index| {
1856 const atom = self.getAtom(atom_index) orelse continue;1856 const atom = self.getAtom(atom_index) orelse continue;
1857 if (!atom.flags.alive) continue;1857 if (!atom.isAlive()) continue;
1858 const sect = atom.getInputSection(macho_file);1858 const sect = atom.getInputSection(macho_file);
1859 if (sect.isZerofill()) continue;1859 if (sect.isZerofill()) continue;
1860 const value = math.cast(usize, atom.value) orelse return error.Overflow;1860 const value = math.cast(usize, atom.value) orelse return error.Overflow;
...@@ -1893,7 +1893,7 @@ pub fn writeAtomsRelocatable(self: *Object, macho_file: *MachO) !void {...@@ -1893,7 +1893,7 @@ pub fn writeAtomsRelocatable(self: *Object, macho_file: *MachO) !void {
1893 }1893 }
1894 for (self.getAtoms()) |atom_index| {1894 for (self.getAtoms()) |atom_index| {
1895 const atom = self.getAtom(atom_index) orelse continue;1895 const atom = self.getAtom(atom_index) orelse continue;
1896 if (!atom.flags.alive) continue;1896 if (!atom.isAlive()) continue;
1897 const sect = atom.getInputSection(macho_file);1897 const sect = atom.getInputSection(macho_file);
1898 if (sect.isZerofill()) continue;1898 if (sect.isZerofill()) continue;
1899 const value = math.cast(usize, atom.value) orelse return error.Overflow;1899 const value = math.cast(usize, atom.value) orelse return error.Overflow;
src/link/MachO/Symbol.zig+24-10
...@@ -23,6 +23,8 @@ nlist_idx: u32 = 0,...@@ -23,6 +23,8 @@ nlist_idx: u32 = 0,
23/// Misc flags for the symbol packaged as packed struct for compression.23/// Misc flags for the symbol packaged as packed struct for compression.
24flags: Flags = .{},24flags: Flags = .{},
2525
26sect_flags: std.atomic.Value(u8) = std.atomic.Value(u8).init(0),
27
26visibility: Visibility = .local,28visibility: Visibility = .local,
2729
28extra: u32 = 0,30extra: u32 = 0,
...@@ -69,6 +71,14 @@ pub fn getOutputSectionIndex(symbol: Symbol, macho_file: *MachO) u8 {...@@ -69,6 +71,14 @@ pub fn getOutputSectionIndex(symbol: Symbol, macho_file: *MachO) u8 {
69 return symbol.out_n_sect;71 return symbol.out_n_sect;
70}72}
7173
74pub fn getSectionFlags(symbol: Symbol) SectionFlags {
75 return @bitCast(symbol.sect_flags.load(.seq_cst));
76}
77
78pub fn setSectionFlags(symbol: *Symbol, flags: SectionFlags) void {
79 _ = symbol.sect_flags.fetchOr(@bitCast(flags), .seq_cst);
80}
81
72pub fn getFile(symbol: Symbol, macho_file: *MachO) ?File {82pub fn getFile(symbol: Symbol, macho_file: *MachO) ?File {
73 return macho_file.getFile(symbol.file);83 return macho_file.getFile(symbol.file);
74}84}
...@@ -116,9 +126,9 @@ pub fn getAddress(symbol: Symbol, opts: struct {...@@ -116,9 +126,9 @@ pub fn getAddress(symbol: Symbol, opts: struct {
116 stubs: bool = true,126 stubs: bool = true,
117}, macho_file: *MachO) u64 {127}, macho_file: *MachO) u64 {
118 if (opts.stubs) {128 if (opts.stubs) {
119 if (symbol.flags.stubs) {129 if (symbol.getSectionFlags().stubs) {
120 return symbol.getStubsAddress(macho_file);130 return symbol.getStubsAddress(macho_file);
121 } else if (symbol.flags.objc_stubs) {131 } else if (symbol.getSectionFlags().objc_stubs) {
122 return symbol.getObjcStubsAddress(macho_file);132 return symbol.getObjcStubsAddress(macho_file);
123 }133 }
124 }134 }
...@@ -127,25 +137,25 @@ pub fn getAddress(symbol: Symbol, opts: struct {...@@ -127,25 +137,25 @@ pub fn getAddress(symbol: Symbol, opts: struct {
127}137}
128138
129pub fn getGotAddress(symbol: Symbol, macho_file: *MachO) u64 {139pub fn getGotAddress(symbol: Symbol, macho_file: *MachO) u64 {
130 if (!symbol.flags.has_got) return 0;140 if (!symbol.getSectionFlags().has_got) return 0;
131 const extra = symbol.getExtra(macho_file);141 const extra = symbol.getExtra(macho_file);
132 return macho_file.got.getAddress(extra.got, macho_file);142 return macho_file.got.getAddress(extra.got, macho_file);
133}143}
134144
135pub fn getStubsAddress(symbol: Symbol, macho_file: *MachO) u64 {145pub fn getStubsAddress(symbol: Symbol, macho_file: *MachO) u64 {
136 if (!symbol.flags.stubs) return 0;146 if (!symbol.getSectionFlags().stubs) return 0;
137 const extra = symbol.getExtra(macho_file);147 const extra = symbol.getExtra(macho_file);
138 return macho_file.stubs.getAddress(extra.stubs, macho_file);148 return macho_file.stubs.getAddress(extra.stubs, macho_file);
139}149}
140150
141pub fn getObjcStubsAddress(symbol: Symbol, macho_file: *MachO) u64 {151pub fn getObjcStubsAddress(symbol: Symbol, macho_file: *MachO) u64 {
142 if (!symbol.flags.objc_stubs) return 0;152 if (!symbol.getSectionFlags().objc_stubs) return 0;
143 const extra = symbol.getExtra(macho_file);153 const extra = symbol.getExtra(macho_file);
144 return macho_file.objc_stubs.getAddress(extra.objc_stubs, macho_file);154 return macho_file.objc_stubs.getAddress(extra.objc_stubs, macho_file);
145}155}
146156
147pub fn getObjcSelrefsAddress(symbol: Symbol, macho_file: *MachO) u64 {157pub fn getObjcSelrefsAddress(symbol: Symbol, macho_file: *MachO) u64 {
148 if (!symbol.flags.objc_stubs) return 0;158 if (!symbol.getSectionFlags().objc_stubs) return 0;
149 const extra = symbol.getExtra(macho_file);159 const extra = symbol.getExtra(macho_file);
150 const file = symbol.getFile(macho_file).?;160 const file = symbol.getFile(macho_file).?;
151 return switch (file) {161 return switch (file) {
...@@ -155,7 +165,7 @@ pub fn getObjcSelrefsAddress(symbol: Symbol, macho_file: *MachO) u64 {...@@ -155,7 +165,7 @@ pub fn getObjcSelrefsAddress(symbol: Symbol, macho_file: *MachO) u64 {
155}165}
156166
157pub fn getTlvPtrAddress(symbol: Symbol, macho_file: *MachO) u64 {167pub fn getTlvPtrAddress(symbol: Symbol, macho_file: *MachO) u64 {
158 if (!symbol.flags.tlv_ptr) return 0;168 if (!symbol.getSectionFlags().tlv_ptr) return 0;
159 const extra = symbol.getExtra(macho_file);169 const extra = symbol.getExtra(macho_file);
160 return macho_file.tlv_ptr.getAddress(extra.tlv_ptr, macho_file);170 return macho_file.tlv_ptr.getAddress(extra.tlv_ptr, macho_file);
161}171}
...@@ -167,14 +177,14 @@ const GetOrCreateZigGotEntryResult = struct {...@@ -167,14 +177,14 @@ const GetOrCreateZigGotEntryResult = struct {
167177
168pub fn getOrCreateZigGotEntry(symbol: *Symbol, symbol_index: Index, macho_file: *MachO) !GetOrCreateZigGotEntryResult {178pub fn getOrCreateZigGotEntry(symbol: *Symbol, symbol_index: Index, macho_file: *MachO) !GetOrCreateZigGotEntryResult {
169 assert(!macho_file.base.isRelocatable());179 assert(!macho_file.base.isRelocatable());
170 assert(symbol.flags.needs_zig_got);180 assert(symbol.getSectionFlags().needs_zig_got);
171 if (symbol.flags.has_zig_got) return .{ .found_existing = true, .index = symbol.getExtra(macho_file).zig_got };181 if (symbol.getSectionFlags().has_zig_got) return .{ .found_existing = true, .index = symbol.getExtra(macho_file).zig_got };
172 const index = try macho_file.zig_got.addSymbol(symbol_index, macho_file);182 const index = try macho_file.zig_got.addSymbol(symbol_index, macho_file);
173 return .{ .found_existing = false, .index = index };183 return .{ .found_existing = false, .index = index };
174}184}
175185
176pub fn getZigGotAddress(symbol: Symbol, macho_file: *MachO) u64 {186pub fn getZigGotAddress(symbol: Symbol, macho_file: *MachO) u64 {
177 if (!symbol.flags.has_zig_got) return 0;187 if (!symbol.getSectionFlags().has_zig_got) return 0;
178 const extras = symbol.getExtra(macho_file);188 const extras = symbol.getExtra(macho_file);
179 return macho_file.zig_got.entryAddress(extras.zig_got, macho_file);189 return macho_file.zig_got.entryAddress(extras.zig_got, macho_file);
180}190}
...@@ -384,7 +394,9 @@ pub const Flags = packed struct {...@@ -384,7 +394,9 @@ pub const Flags = packed struct {
384394
385 /// Whether the symbol makes into the output symtab or not.395 /// Whether the symbol makes into the output symtab or not.
386 output_symtab: bool = false,396 output_symtab: bool = false,
397};
387398
399pub const SectionFlags = packed struct(u8) {
388 /// Whether the symbol contains __got indirection.400 /// Whether the symbol contains __got indirection.
389 needs_got: bool = false,401 needs_got: bool = false,
390 has_got: bool = false,402 has_got: bool = false,
...@@ -401,6 +413,8 @@ pub const Flags = packed struct {...@@ -401,6 +413,8 @@ pub const Flags = packed struct {
401413
402 /// Whether the symbol contains __objc_stubs indirection.414 /// Whether the symbol contains __objc_stubs indirection.
403 objc_stubs: bool = false,415 objc_stubs: bool = false,
416
417 _: u1 = 0,
404};418};
405419
406pub const Visibility = enum {420pub const Visibility = enum {
src/link/MachO/UnwindInfo.zig+1-1
...@@ -53,7 +53,7 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void {...@@ -53,7 +53,7 @@ pub fn generate(info: *UnwindInfo, macho_file: *MachO) !void {
53 for (macho_file.sections.items(.atoms)) |atoms| {53 for (macho_file.sections.items(.atoms)) |atoms| {
54 for (atoms.items) |ref| {54 for (atoms.items) |ref| {
55 const atom = ref.getAtom(macho_file) orelse continue;55 const atom = ref.getAtom(macho_file) orelse continue;
56 if (!atom.flags.alive) continue;56 if (!atom.isAlive()) continue;
57 const recs = atom.getUnwindRecords(macho_file);57 const recs = atom.getUnwindRecords(macho_file);
58 const file = atom.getFile(macho_file);58 const file = atom.getFile(macho_file);
59 try info.records.ensureUnusedCapacity(gpa, recs.len);59 try info.records.ensureUnusedCapacity(gpa, recs.len);
src/link/MachO/ZigObject.zig+19-19
...@@ -245,7 +245,7 @@ pub fn resolveSymbols(self: *ZigObject, macho_file: *MachO) !void {...@@ -245,7 +245,7 @@ pub fn resolveSymbols(self: *ZigObject, macho_file: *MachO) !void {
245 if (!nlist.ext()) continue;245 if (!nlist.ext()) continue;
246 if (nlist.sect()) {246 if (nlist.sect()) {
247 const atom = self.getAtom(atom_index).?;247 const atom = self.getAtom(atom_index).?;
248 if (!atom.flags.alive) continue;248 if (!atom.isAlive()) continue;
249 }249 }
250250
251 const gop = try macho_file.resolver.getOrPut(gpa, .{251 const gop = try macho_file.resolver.getOrPut(gpa, .{
...@@ -391,7 +391,7 @@ pub fn claimUnresolved(self: *ZigObject, macho_file: *MachO) void {...@@ -391,7 +391,7 @@ pub fn claimUnresolved(self: *ZigObject, macho_file: *MachO) void {
391pub fn scanRelocs(self: *ZigObject, macho_file: *MachO) !void {391pub fn scanRelocs(self: *ZigObject, macho_file: *MachO) !void {
392 for (self.getAtoms()) |atom_index| {392 for (self.getAtoms()) |atom_index| {
393 const atom = self.getAtom(atom_index) orelse continue;393 const atom = self.getAtom(atom_index) orelse continue;
394 if (!atom.flags.alive) continue;394 if (!atom.isAlive()) continue;
395 const sect = atom.getInputSection(macho_file);395 const sect = atom.getInputSection(macho_file);
396 if (sect.isZerofill()) continue;396 if (sect.isZerofill()) continue;
397 try atom.scanRelocs(macho_file);397 try atom.scanRelocs(macho_file);
...@@ -403,7 +403,7 @@ pub fn resolveRelocs(self: *ZigObject, macho_file: *MachO) !void {...@@ -403,7 +403,7 @@ pub fn resolveRelocs(self: *ZigObject, macho_file: *MachO) !void {
403 var has_error = false;403 var has_error = false;
404 for (self.getAtoms()) |atom_index| {404 for (self.getAtoms()) |atom_index| {
405 const atom = self.getAtom(atom_index) orelse continue;405 const atom = self.getAtom(atom_index) orelse continue;
406 if (!atom.flags.alive) continue;406 if (!atom.isAlive()) continue;
407 const sect = &macho_file.sections.items(.header)[atom.out_n_sect];407 const sect = &macho_file.sections.items(.header)[atom.out_n_sect];
408 if (sect.isZerofill()) continue;408 if (sect.isZerofill()) continue;
409 if (!macho_file.isZigSection(atom.out_n_sect)) continue; // Non-Zig sections are handled separately409 if (!macho_file.isZigSection(atom.out_n_sect)) continue; // Non-Zig sections are handled separately
...@@ -450,7 +450,7 @@ pub fn resolveRelocs(self: *ZigObject, macho_file: *MachO) !void {...@@ -450,7 +450,7 @@ pub fn resolveRelocs(self: *ZigObject, macho_file: *MachO) !void {
450pub fn calcNumRelocs(self: *ZigObject, macho_file: *MachO) void {450pub fn calcNumRelocs(self: *ZigObject, macho_file: *MachO) void {
451 for (self.getAtoms()) |atom_index| {451 for (self.getAtoms()) |atom_index| {
452 const atom = self.getAtom(atom_index) orelse continue;452 const atom = self.getAtom(atom_index) orelse continue;
453 if (!atom.flags.alive) continue;453 if (!atom.isAlive()) continue;
454 const header = &macho_file.sections.items(.header)[atom.out_n_sect];454 const header = &macho_file.sections.items(.header)[atom.out_n_sect];
455 if (header.isZerofill()) continue;455 if (header.isZerofill()) continue;
456 if (!macho_file.isZigSection(atom.out_n_sect) and !macho_file.isDebugSection(atom.out_n_sect)) continue;456 if (!macho_file.isZigSection(atom.out_n_sect) and !macho_file.isDebugSection(atom.out_n_sect)) continue;
...@@ -465,7 +465,7 @@ pub fn writeRelocs(self: *ZigObject, macho_file: *MachO) !void {...@@ -465,7 +465,7 @@ pub fn writeRelocs(self: *ZigObject, macho_file: *MachO) !void {
465465
466 for (self.getAtoms()) |atom_index| {466 for (self.getAtoms()) |atom_index| {
467 const atom = self.getAtom(atom_index) orelse continue;467 const atom = self.getAtom(atom_index) orelse continue;
468 if (!atom.flags.alive) continue;468 if (!atom.isAlive()) continue;
469 const header = macho_file.sections.items(.header)[atom.out_n_sect];469 const header = macho_file.sections.items(.header)[atom.out_n_sect];
470 const relocs = macho_file.sections.items(.relocs)[atom.out_n_sect].items;470 const relocs = macho_file.sections.items(.relocs)[atom.out_n_sect].items;
471 if (header.isZerofill()) continue;471 if (header.isZerofill()) continue;
...@@ -505,7 +505,7 @@ pub fn writeAtomsRelocatable(self: *ZigObject, macho_file: *MachO) !void {...@@ -505,7 +505,7 @@ pub fn writeAtomsRelocatable(self: *ZigObject, macho_file: *MachO) !void {
505505
506 for (self.getAtoms()) |atom_index| {506 for (self.getAtoms()) |atom_index| {
507 const atom = self.getAtom(atom_index) orelse continue;507 const atom = self.getAtom(atom_index) orelse continue;
508 if (!atom.flags.alive) continue;508 if (!atom.isAlive()) continue;
509 const sect = atom.getInputSection(macho_file);509 const sect = atom.getInputSection(macho_file);
510 if (sect.isZerofill()) continue;510 if (sect.isZerofill()) continue;
511 if (macho_file.isZigSection(atom.out_n_sect)) continue;511 if (macho_file.isZigSection(atom.out_n_sect)) continue;
...@@ -529,7 +529,7 @@ pub fn writeAtoms(self: *ZigObject, macho_file: *MachO) !void {...@@ -529,7 +529,7 @@ pub fn writeAtoms(self: *ZigObject, macho_file: *MachO) !void {
529529
530 for (self.getAtoms()) |atom_index| {530 for (self.getAtoms()) |atom_index| {
531 const atom = self.getAtom(atom_index) orelse continue;531 const atom = self.getAtom(atom_index) orelse continue;
532 if (!atom.flags.alive) continue;532 if (!atom.isAlive()) continue;
533 const sect = atom.getInputSection(macho_file);533 const sect = atom.getInputSection(macho_file);
534 if (sect.isZerofill()) continue;534 if (sect.isZerofill()) continue;
535 if (macho_file.isZigSection(atom.out_n_sect)) continue;535 if (macho_file.isZigSection(atom.out_n_sect)) continue;
...@@ -549,7 +549,7 @@ pub fn calcSymtabSize(self: *ZigObject, macho_file: *MachO) void {...@@ -549,7 +549,7 @@ pub fn calcSymtabSize(self: *ZigObject, macho_file: *MachO) void {
549 const ref = self.getSymbolRef(@intCast(i), macho_file);549 const ref = self.getSymbolRef(@intCast(i), macho_file);
550 const file = ref.getFile(macho_file) orelse continue;550 const file = ref.getFile(macho_file) orelse continue;
551 if (file.getIndex() != self.index) continue;551 if (file.getIndex() != self.index) continue;
552 if (sym.getAtom(macho_file)) |atom| if (!atom.flags.alive) continue;552 if (sym.getAtom(macho_file)) |atom| if (!atom.isAlive()) continue;
553 sym.flags.output_symtab = true;553 sym.flags.output_symtab = true;
554 if (sym.isLocal()) {554 if (sym.isLocal()) {
555 sym.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, macho_file);555 sym.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, macho_file);
...@@ -914,7 +914,7 @@ pub fn updateDecl(...@@ -914,7 +914,7 @@ pub fn updateDecl(
914 const lib_name = variable.lib_name.toSlice(&mod.intern_pool);914 const lib_name = variable.lib_name.toSlice(&mod.intern_pool);
915 const index = try self.getGlobalSymbol(macho_file, name, lib_name);915 const index = try self.getGlobalSymbol(macho_file, name, lib_name);
916 const sym = &self.symbols.items[index];916 const sym = &self.symbols.items[index];
917 sym.flags.needs_got = true;917 sym.setSectionFlags(.{ .needs_got = true });
918 return;918 return;
919 }919 }
920920
...@@ -993,7 +993,7 @@ fn updateDeclCode(...@@ -993,7 +993,7 @@ fn updateDeclCode(
993 const sym_name = try std.fmt.allocPrintZ(gpa, "_{s}", .{decl.fqn.toSlice(ip)});993 const sym_name = try std.fmt.allocPrintZ(gpa, "_{s}", .{decl.fqn.toSlice(ip)});
994 defer gpa.free(sym_name);994 defer gpa.free(sym_name);
995 sym.name = try self.strtab.insert(gpa, sym_name);995 sym.name = try self.strtab.insert(gpa, sym_name);
996 atom.flags.alive = true;996 atom.setAlive(true);
997 atom.name = sym.name;997 atom.name = sym.name;
998 nlist.n_strx = sym.name;998 nlist.n_strx = sym.name;
999 nlist.n_type = macho.N_SECT;999 nlist.n_type = macho.N_SECT;
...@@ -1018,7 +1018,7 @@ fn updateDeclCode(...@@ -1018,7 +1018,7 @@ fn updateDeclCode(
10181018
1019 if (!macho_file.base.isRelocatable()) {1019 if (!macho_file.base.isRelocatable()) {
1020 log.debug(" (updating offset table entry)", .{});1020 log.debug(" (updating offset table entry)", .{});
1021 assert(sym.flags.has_zig_got);1021 assert(sym.getSectionFlags().has_zig_got);
1022 const extra = sym.getExtra(macho_file);1022 const extra = sym.getExtra(macho_file);
1023 try macho_file.zig_got.writeOne(macho_file, extra.zig_got);1023 try macho_file.zig_got.writeOne(macho_file, extra.zig_got);
1024 }1024 }
...@@ -1034,7 +1034,7 @@ fn updateDeclCode(...@@ -1034,7 +1034,7 @@ fn updateDeclCode(
1034 errdefer self.freeDeclMetadata(macho_file, sym_index);1034 errdefer self.freeDeclMetadata(macho_file, sym_index);
10351035
1036 sym.value = 0;1036 sym.value = 0;
1037 sym.flags.needs_zig_got = true;1037 sym.setSectionFlags(.{ .needs_zig_got = true });
1038 nlist.n_value = 0;1038 nlist.n_value = 0;
10391039
1040 if (!macho_file.base.isRelocatable()) {1040 if (!macho_file.base.isRelocatable()) {
...@@ -1098,7 +1098,7 @@ fn createTlvInitializer(...@@ -1098,7 +1098,7 @@ fn createTlvInitializer(
1098 const atom = sym.getAtom(macho_file).?;1098 const atom = sym.getAtom(macho_file).?;
1099 sym.out_n_sect = sect_index;1099 sym.out_n_sect = sect_index;
1100 atom.out_n_sect = sect_index;1100 atom.out_n_sect = sect_index;
1101 atom.flags.alive = true;1101 atom.setAlive(true);
1102 atom.alignment = alignment;1102 atom.alignment = alignment;
1103 atom.size = code.len;1103 atom.size = code.len;
1104 nlist.n_sect = sect_index + 1;1104 nlist.n_sect = sect_index + 1;
...@@ -1143,7 +1143,7 @@ fn createTlvDescriptor(...@@ -1143,7 +1143,7 @@ fn createTlvDescriptor(
11431143
1144 sym.value = 0;1144 sym.value = 0;
1145 sym.name = try self.strtab.insert(gpa, name);1145 sym.name = try self.strtab.insert(gpa, name);
1146 atom.flags.alive = true;1146 atom.setAlive(true);
1147 atom.name = sym.name;1147 atom.name = sym.name;
1148 nlist.n_strx = sym.name;1148 nlist.n_strx = sym.name;
1149 nlist.n_sect = sect_index + 1;1149 nlist.n_sect = sect_index + 1;
...@@ -1317,7 +1317,7 @@ fn lowerConst(...@@ -1317,7 +1317,7 @@ fn lowerConst(
1317 self.symtab.items(.size)[sym.nlist_idx] = code.len;1317 self.symtab.items(.size)[sym.nlist_idx] = code.len;
13181318
1319 const atom = sym.getAtom(macho_file).?;1319 const atom = sym.getAtom(macho_file).?;
1320 atom.flags.alive = true;1320 atom.setAlive(true);
1321 atom.alignment = required_alignment;1321 atom.alignment = required_alignment;
1322 atom.size = code.len;1322 atom.size = code.len;
1323 atom.out_n_sect = output_section_index;1323 atom.out_n_sect = output_section_index;
...@@ -1490,7 +1490,7 @@ fn updateLazySymbol(...@@ -1490,7 +1490,7 @@ fn updateLazySymbol(
1490 self.symtab.items(.size)[sym.nlist_idx] = code.len;1490 self.symtab.items(.size)[sym.nlist_idx] = code.len;
14911491
1492 const atom = sym.getAtom(macho_file).?;1492 const atom = sym.getAtom(macho_file).?;
1493 atom.flags.alive = true;1493 atom.setAlive(true);
1494 atom.name = name_str_index;1494 atom.name = name_str_index;
1495 atom.alignment = required_alignment;1495 atom.alignment = required_alignment;
1496 atom.size = code.len;1496 atom.size = code.len;
...@@ -1500,7 +1500,7 @@ fn updateLazySymbol(...@@ -1500,7 +1500,7 @@ fn updateLazySymbol(
1500 errdefer self.freeDeclMetadata(macho_file, symbol_index);1500 errdefer self.freeDeclMetadata(macho_file, symbol_index);
15011501
1502 sym.value = 0;1502 sym.value = 0;
1503 sym.flags.needs_zig_got = true;1503 sym.setSectionFlags(.{ .needs_zig_got = true });
1504 nlist.n_value = 0;1504 nlist.n_value = 0;
15051505
1506 if (!macho_file.base.isRelocatable()) {1506 if (!macho_file.base.isRelocatable()) {
...@@ -1576,7 +1576,7 @@ pub fn getOrCreateMetadataForDecl(...@@ -1576,7 +1576,7 @@ pub fn getOrCreateMetadataForDecl(
1576 if (isThreadlocal(macho_file, decl_index)) {1576 if (isThreadlocal(macho_file, decl_index)) {
1577 sym.flags.tlv = true;1577 sym.flags.tlv = true;
1578 } else {1578 } else {
1579 sym.flags.needs_zig_got = true;1579 sym.setSectionFlags(.{ .needs_zig_got = true });
1580 }1580 }
1581 gop.value_ptr.* = .{ .symbol_index = sym_index };1581 gop.value_ptr.* = .{ .symbol_index = sym_index };
1582 }1582 }
...@@ -1611,7 +1611,7 @@ pub fn getOrCreateMetadataForLazySymbol(...@@ -1611,7 +1611,7 @@ pub fn getOrCreateMetadataForLazySymbol(
1611 .unused => {1611 .unused => {
1612 const symbol_index = try self.newSymbolWithAtom(gpa, 0, macho_file);1612 const symbol_index = try self.newSymbolWithAtom(gpa, 0, macho_file);
1613 const sym = &self.symbols.items[symbol_index];1613 const sym = &self.symbols.items[symbol_index];
1614 sym.flags.needs_zig_got = true;1614 sym.setSectionFlags(.{ .needs_zig_got = true });
1615 metadata.symbol_index.* = symbol_index;1615 metadata.symbol_index.* = symbol_index;
1616 },1616 },
1617 .pending_flush => return metadata.symbol_index.*,1617 .pending_flush => return metadata.symbol_index.*,
src/link/MachO/dead_strip.zig+10-10
...@@ -82,9 +82,8 @@ fn markSymbol(sym: *Symbol, roots: *std.ArrayList(*Atom), macho_file: *MachO) !v...@@ -82,9 +82,8 @@ fn markSymbol(sym: *Symbol, roots: *std.ArrayList(*Atom), macho_file: *MachO) !v
82}82}
8383
84fn markAtom(atom: *Atom) bool {84fn markAtom(atom: *Atom) bool {
85 const already_visited = atom.flags.visited;85 const already_visited = atom.visited.swap(true, .seq_cst);
86 atom.flags.visited = true;86 return atom.isAlive() and !already_visited;
87 return atom.flags.alive and !already_visited;
88}87}
8988
90fn mark(roots: []*Atom, objects: []const File.Index, macho_file: *MachO) void {89fn mark(roots: []*Atom, objects: []const File.Index, macho_file: *MachO) void {
...@@ -105,7 +104,7 @@ fn mark(roots: []*Atom, objects: []const File.Index, macho_file: *MachO) void {...@@ -105,7 +104,7 @@ fn mark(roots: []*Atom, objects: []const File.Index, macho_file: *MachO) void {
105 !(mem.eql(u8, isec.sectName(), "__eh_frame") or104 !(mem.eql(u8, isec.sectName(), "__eh_frame") or
106 mem.eql(u8, isec.sectName(), "__compact_unwind") or105 mem.eql(u8, isec.sectName(), "__compact_unwind") or
107 isec.attrs() & macho.S_ATTR_DEBUG != 0) and106 isec.attrs() & macho.S_ATTR_DEBUG != 0) and
108 !atom.flags.alive and refersLive(atom, macho_file))107 !atom.isAlive() and refersLive(atom, macho_file))
109 {108 {
110 markLive(atom, macho_file);109 markLive(atom, macho_file);
111 loop = true;110 loop = true;
...@@ -116,8 +115,8 @@ fn mark(roots: []*Atom, objects: []const File.Index, macho_file: *MachO) void {...@@ -116,8 +115,8 @@ fn mark(roots: []*Atom, objects: []const File.Index, macho_file: *MachO) void {
116}115}
117116
118fn markLive(atom: *Atom, macho_file: *MachO) void {117fn markLive(atom: *Atom, macho_file: *MachO) void {
119 assert(atom.flags.visited);118 assert(atom.visited.load(.seq_cst));
120 atom.flags.alive = true;119 atom.setAlive(true);
121 track_live_log.debug("{}marking live atom({d},{s})", .{120 track_live_log.debug("{}marking live atom({d},{s})", .{
122 track_live_level,121 track_live_level,
123 atom.atom_index,122 atom.atom_index,
...@@ -170,7 +169,7 @@ fn refersLive(atom: *Atom, macho_file: *MachO) bool {...@@ -170,7 +169,7 @@ fn refersLive(atom: *Atom, macho_file: *MachO) bool {
170 },169 },
171 };170 };
172 if (target_atom) |ta| {171 if (target_atom) |ta| {
173 if (ta.flags.alive) return true;172 if (ta.isAlive()) return true;
174 }173 }
175 }174 }
176 return false;175 return false;
...@@ -181,9 +180,10 @@ fn prune(objects: []const File.Index, macho_file: *MachO) void {...@@ -181,9 +180,10 @@ fn prune(objects: []const File.Index, macho_file: *MachO) void {
181 const file = macho_file.getFile(index).?;180 const file = macho_file.getFile(index).?;
182 for (file.getAtoms()) |atom_index| {181 for (file.getAtoms()) |atom_index| {
183 const atom = file.getAtom(atom_index) orelse continue;182 const atom = file.getAtom(atom_index) orelse continue;
184 if (atom.flags.alive and !atom.flags.visited) {183 if (!atom.visited.load(.seq_cst)) {
185 atom.flags.alive = false;184 if (atom.alive.cmpxchgStrong(true, false, .seq_cst, .seq_cst) == null) {
186 atom.markUnwindRecordsDead(macho_file);185 atom.markUnwindRecordsDead(macho_file);
186 }
187 }187 }
188 }188 }
189 }189 }
src/link/MachO/dyld_info/Rebase.zig+1-1
...@@ -35,7 +35,7 @@ pub fn updateSize(rebase: *Rebase, macho_file: *MachO) !void {...@@ -35,7 +35,7 @@ pub fn updateSize(rebase: *Rebase, macho_file: *MachO) !void {
35 const file = macho_file.getFile(index).?;35 const file = macho_file.getFile(index).?;
36 for (file.getAtoms()) |atom_index| {36 for (file.getAtoms()) |atom_index| {
37 const atom = file.getAtom(atom_index) orelse continue;37 const atom = file.getAtom(atom_index) orelse continue;
38 if (!atom.flags.alive) continue;38 if (!atom.isAlive()) continue;
39 if (atom.getInputSection(macho_file).isZerofill()) continue;39 if (atom.getInputSection(macho_file).isZerofill()) continue;
40 const atom_addr = atom.getAddress(macho_file);40 const atom_addr = atom.getAddress(macho_file);
41 const seg_id = macho_file.sections.items(.segment_id)[atom.out_n_sect];41 const seg_id = macho_file.sections.items(.segment_id)[atom.out_n_sect];
src/link/MachO/dyld_info/Trie.zig+3-3
...@@ -102,7 +102,7 @@ pub fn updateSize(self: *Trie, macho_file: *MachO) !void {...@@ -102,7 +102,7 @@ pub fn updateSize(self: *Trie, macho_file: *MachO) !void {
102 if (ref.getFile(macho_file) == null) continue;102 if (ref.getFile(macho_file) == null) continue;
103 const sym = ref.getSymbol(macho_file).?;103 const sym = ref.getSymbol(macho_file).?;
104 if (!sym.flags.@"export") continue;104 if (!sym.flags.@"export") continue;
105 if (sym.getAtom(macho_file)) |atom| if (!atom.flags.alive) continue;105 if (sym.getAtom(macho_file)) |atom| if (!atom.isAlive()) continue;
106 var flags: u64 = if (sym.flags.abs)106 var flags: u64 = if (sym.flags.abs)
107 macho.EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE107 macho.EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE
108 else if (sym.flags.tlv)108 else if (sym.flags.tlv)
...@@ -111,8 +111,8 @@ pub fn updateSize(self: *Trie, macho_file: *MachO) !void {...@@ -111,8 +111,8 @@ pub fn updateSize(self: *Trie, macho_file: *MachO) !void {
111 macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR;111 macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR;
112 if (sym.flags.weak) {112 if (sym.flags.weak) {
113 flags |= macho.EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION;113 flags |= macho.EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION;
114 macho_file.weak_defines = true;114 macho_file.weak_defines.store(true, .seq_cst);
115 macho_file.binds_to_weak = true;115 macho_file.binds_to_weak.store(true, .seq_cst);
116 }116 }
117 try self.put(gpa, .{117 try self.put(gpa, .{
118 .name = sym.getName(macho_file),118 .name = sym.getName(macho_file),
src/link/MachO/dyld_info/bind.zig+3-6
...@@ -10,10 +10,7 @@ pub const Entry = struct {...@@ -10,10 +10,7 @@ pub const Entry = struct {
10 if (entry.target.eql(other.target)) {10 if (entry.target.eql(other.target)) {
11 return entry.offset < other.offset;11 return entry.offset < other.offset;
12 }12 }
13 if (entry.target.file == other.target.file) {13 return entry.target.lessThan(other.target);
14 return entry.target.index < other.target.index;
15 }
16 return entry.target.file < other.target.file;
17 }14 }
18 return entry.segment_id < other.segment_id;15 return entry.segment_id < other.segment_id;
19 }16 }
...@@ -47,7 +44,7 @@ pub const Bind = struct {...@@ -47,7 +44,7 @@ pub const Bind = struct {
47 const file = macho_file.getFile(index).?;44 const file = macho_file.getFile(index).?;
48 for (file.getAtoms()) |atom_index| {45 for (file.getAtoms()) |atom_index| {
49 const atom = file.getAtom(atom_index) orelse continue;46 const atom = file.getAtom(atom_index) orelse continue;
50 if (!atom.flags.alive) continue;47 if (!atom.isAlive()) continue;
51 if (atom.getInputSection(macho_file).isZerofill()) continue;48 if (atom.getInputSection(macho_file).isZerofill()) continue;
52 const atom_addr = atom.getAddress(macho_file);49 const atom_addr = atom.getAddress(macho_file);
53 const relocs = atom.getRelocs(macho_file);50 const relocs = atom.getRelocs(macho_file);
...@@ -299,7 +296,7 @@ pub const WeakBind = struct {...@@ -299,7 +296,7 @@ pub const WeakBind = struct {
299 const file = macho_file.getFile(index).?;296 const file = macho_file.getFile(index).?;
300 for (file.getAtoms()) |atom_index| {297 for (file.getAtoms()) |atom_index| {
301 const atom = file.getAtom(atom_index) orelse continue;298 const atom = file.getAtom(atom_index) orelse continue;
302 if (!atom.flags.alive) continue;299 if (!atom.isAlive()) continue;
303 if (atom.getInputSection(macho_file).isZerofill()) continue;300 if (atom.getInputSection(macho_file).isZerofill()) continue;
304 const atom_addr = atom.getAddress(macho_file);301 const atom_addr = atom.getAddress(macho_file);
305 const relocs = atom.getRelocs(macho_file);302 const relocs = atom.getRelocs(macho_file);
src/link/MachO/file.zig+11-9
...@@ -37,11 +37,10 @@ pub const File = union(enum) {...@@ -37,11 +37,10 @@ pub const File = union(enum) {
37 }37 }
3838
39 pub fn scanRelocs(file: File, macho_file: *MachO) !void {39 pub fn scanRelocs(file: File, macho_file: *MachO) !void {
40 switch (file) {40 return switch (file) {
41 .dylib => unreachable,41 .dylib => unreachable,
42 .internal => |x| x.scanRelocs(macho_file),
43 inline else => |x| x.scanRelocs(macho_file),42 inline else => |x| x.scanRelocs(macho_file),
44 }43 };
45 }44 }
4645
47 /// Encodes symbol rank so that the following ordering applies:46 /// Encodes symbol rank so that the following ordering applies:
...@@ -182,19 +181,19 @@ pub const File = union(enum) {...@@ -182,19 +181,19 @@ pub const File = union(enum) {
182 if (ref.getFile(macho_file) == null) continue;181 if (ref.getFile(macho_file) == null) continue;
183 if (ref.file != file.getIndex()) continue;182 if (ref.file != file.getIndex()) continue;
184 const sym = ref.getSymbol(macho_file).?;183 const sym = ref.getSymbol(macho_file).?;
185 if (sym.flags.needs_got) {184 if (sym.getSectionFlags().needs_got) {
186 log.debug("'{s}' needs GOT", .{sym.getName(macho_file)});185 log.debug("'{s}' needs GOT", .{sym.getName(macho_file)});
187 try macho_file.got.addSymbol(ref, macho_file);186 try macho_file.got.addSymbol(ref, macho_file);
188 }187 }
189 if (sym.flags.stubs) {188 if (sym.getSectionFlags().stubs) {
190 log.debug("'{s}' needs STUBS", .{sym.getName(macho_file)});189 log.debug("'{s}' needs STUBS", .{sym.getName(macho_file)});
191 try macho_file.stubs.addSymbol(ref, macho_file);190 try macho_file.stubs.addSymbol(ref, macho_file);
192 }191 }
193 if (sym.flags.tlv_ptr) {192 if (sym.getSectionFlags().tlv_ptr) {
194 log.debug("'{s}' needs TLV pointer", .{sym.getName(macho_file)});193 log.debug("'{s}' needs TLV pointer", .{sym.getName(macho_file)});
195 try macho_file.tlv_ptr.addSymbol(ref, macho_file);194 try macho_file.tlv_ptr.addSymbol(ref, macho_file);
196 }195 }
197 if (sym.flags.objc_stubs) {196 if (sym.getSectionFlags().objc_stubs) {
198 log.debug("'{s}' needs OBJC STUBS", .{sym.getName(macho_file)});197 log.debug("'{s}' needs OBJC STUBS", .{sym.getName(macho_file)});
199 try macho_file.objc_stubs.addSymbol(ref, macho_file);198 try macho_file.objc_stubs.addSymbol(ref, macho_file);
200 }199 }
...@@ -268,6 +267,9 @@ pub const File = union(enum) {...@@ -268,6 +267,9 @@ pub const File = union(enum) {
268 const ref_file = ref.getFile(macho_file) orelse continue;267 const ref_file = ref.getFile(macho_file) orelse continue;
269 if (ref_file.getIndex() == file.getIndex()) continue;268 if (ref_file.getIndex() == file.getIndex()) continue;
270269
270 macho_file.dupes_mutex.lock();
271 defer macho_file.dupes_mutex.unlock();
272
271 const gop = try macho_file.dupes.getOrPut(gpa, file.getGlobals()[i]);273 const gop = try macho_file.dupes.getOrPut(gpa, file.getGlobals()[i]);
272 if (!gop.found_existing) {274 if (!gop.found_existing) {
273 gop.value_ptr.* = .{};275 gop.value_ptr.* = .{};
...@@ -281,7 +283,7 @@ pub const File = union(enum) {...@@ -281,7 +283,7 @@ pub const File = union(enum) {
281 defer tracy.end();283 defer tracy.end();
282 for (file.getAtoms()) |atom_index| {284 for (file.getAtoms()) |atom_index| {
283 const atom = file.getAtom(atom_index) orelse continue;285 const atom = file.getAtom(atom_index) orelse continue;
284 if (!atom.flags.alive) continue;286 if (!atom.isAlive()) continue;
285 atom.out_n_sect = try Atom.initOutputSection(atom.getInputSection(macho_file), macho_file);287 atom.out_n_sect = try Atom.initOutputSection(atom.getInputSection(macho_file), macho_file);
286 }288 }
287 }289 }
...@@ -295,7 +297,7 @@ pub const File = union(enum) {...@@ -295,7 +297,7 @@ pub const File = union(enum) {
295297
296 pub fn writeAtoms(file: File, macho_file: *MachO) !void {298 pub fn writeAtoms(file: File, macho_file: *MachO) !void {
297 return switch (file) {299 return switch (file) {
298 .dylib, .zig_object => unreachable,300 .dylib => unreachable,
299 inline else => |x| x.writeAtoms(macho_file),301 inline else => |x| x.writeAtoms(macho_file),
300 };302 };
301 }303 }
src/link/MachO/relocatable.zig+1-1
...@@ -261,7 +261,7 @@ fn initOutputSections(macho_file: *MachO) !void {...@@ -261,7 +261,7 @@ fn initOutputSections(macho_file: *MachO) !void {
261 const file = macho_file.getFile(index).?;261 const file = macho_file.getFile(index).?;
262 for (file.getAtoms()) |atom_index| {262 for (file.getAtoms()) |atom_index| {
263 const atom = file.getAtom(atom_index) orelse continue;263 const atom = file.getAtom(atom_index) orelse continue;
264 if (!atom.flags.alive) continue;264 if (!atom.isAlive()) continue;
265 atom.out_n_sect = try Atom.initOutputSection(atom.getInputSection(macho_file), macho_file);265 atom.out_n_sect = try Atom.initOutputSection(atom.getInputSection(macho_file), macho_file);
266 }266 }
267 }267 }
src/link/MachO/synthetic.zig+4-4
...@@ -24,8 +24,8 @@ pub const ZigGotSection = struct {...@@ -24,8 +24,8 @@ pub const ZigGotSection = struct {
24 const entry = &zig_got.entries.items[index];24 const entry = &zig_got.entries.items[index];
25 entry.* = sym_index;25 entry.* = sym_index;
26 const symbol = &zo.symbols.items[sym_index];26 const symbol = &zo.symbols.items[sym_index];
27 assert(symbol.flags.needs_zig_got);27 assert(symbol.getSectionFlags().needs_zig_got);
28 symbol.flags.has_zig_got = true;28 symbol.setSectionFlags(.{ .has_zig_got = true });
29 symbol.addExtra(.{ .zig_got = index }, macho_file);29 symbol.addExtra(.{ .zig_got = index }, macho_file);
30 return index;30 return index;
31 }31 }
...@@ -121,7 +121,7 @@ pub const GotSection = struct {...@@ -121,7 +121,7 @@ pub const GotSection = struct {
121 const entry = try got.symbols.addOne(gpa);121 const entry = try got.symbols.addOne(gpa);
122 entry.* = ref;122 entry.* = ref;
123 const symbol = ref.getSymbol(macho_file).?;123 const symbol = ref.getSymbol(macho_file).?;
124 symbol.flags.has_got = true;124 symbol.setSectionFlags(.{ .has_got = true });
125 symbol.addExtra(.{ .got = index }, macho_file);125 symbol.addExtra(.{ .got = index }, macho_file);
126 }126 }
127127
...@@ -689,7 +689,7 @@ pub const DataInCode = struct {...@@ -689,7 +689,7 @@ pub const DataInCode = struct {
689 dices[next_dice].offset < end_off) : (next_dice += 1)689 dices[next_dice].offset < end_off) : (next_dice += 1)
690 {}690 {}
691691
692 if (atom.flags.alive) for (dices[start_dice..next_dice]) |d| {692 if (atom.isAlive()) for (dices[start_dice..next_dice]) |d| {
693 dice.entries.appendAssumeCapacity(.{693 dice.entries.appendAssumeCapacity(.{
694 .atom_ref = .{ .index = atom_index, .file = index },694 .atom_ref = .{ .index = atom_index, .file = index },
695 .offset = @intCast(d.offset - start_off),695 .offset = @intCast(d.offset - start_off),
src/link/MachO/thunks.zig+3-3
...@@ -17,7 +17,7 @@ pub fn createThunks(sect_id: u8, macho_file: *MachO) !void {...@@ -17,7 +17,7 @@ pub fn createThunks(sect_id: u8, macho_file: *MachO) !void {
17 while (i < atoms.len) {17 while (i < atoms.len) {
18 const start = i;18 const start = i;
19 const start_atom = atoms[start].getAtom(macho_file).?;19 const start_atom = atoms[start].getAtom(macho_file).?;
20 assert(start_atom.flags.alive);20 assert(start_atom.isAlive());
21 start_atom.value = advance(header, start_atom.size, start_atom.alignment);21 start_atom.value = advance(header, start_atom.size, start_atom.alignment);
22 i += 1;22 i += 1;
2323
...@@ -25,7 +25,7 @@ pub fn createThunks(sect_id: u8, macho_file: *MachO) !void {...@@ -25,7 +25,7 @@ pub fn createThunks(sect_id: u8, macho_file: *MachO) !void {
25 header.size - start_atom.value < max_allowed_distance) : (i += 1)25 header.size - start_atom.value < max_allowed_distance) : (i += 1)
26 {26 {
27 const atom = atoms[i].getAtom(macho_file).?;27 const atom = atoms[i].getAtom(macho_file).?;
28 assert(atom.flags.alive);28 assert(atom.isAlive());
29 atom.value = advance(header, atom.size, atom.alignment);29 atom.value = advance(header, atom.size, atom.alignment);
30 }30 }
3131
...@@ -71,7 +71,7 @@ fn scanRelocs(thunk_index: Thunk.Index, gpa: Allocator, atoms: []const MachO.Ref...@@ -71,7 +71,7 @@ fn scanRelocs(thunk_index: Thunk.Index, gpa: Allocator, atoms: []const MachO.Ref
7171
72fn isReachable(atom: *const Atom, rel: Relocation, macho_file: *MachO) bool {72fn isReachable(atom: *const Atom, rel: Relocation, macho_file: *MachO) bool {
73 const target = rel.getTargetSymbol(atom.*, macho_file);73 const target = rel.getTargetSymbol(atom.*, macho_file);
74 if (target.flags.stubs or target.flags.objc_stubs) return false;74 if (target.getSectionFlags().stubs or target.getSectionFlags().objc_stubs) return false;
75 if (atom.out_n_sect != target.getOutputSectionIndex(macho_file)) return false;75 if (atom.out_n_sect != target.getOutputSectionIndex(macho_file)) return false;
76 const target_atom = target.getAtom(macho_file).?;76 const target_atom = target.getAtom(macho_file).?;
77 if (target_atom.value == @as(u64, @bitCast(@as(i64, -1)))) return false;77 if (target_atom.value == @as(u64, @bitCast(@as(i64, -1)))) return false;