authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-01-30 18:22:50+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-01-31 00:43:25+01:00
logd42a93105142e3e8f1d02efeecc0c0e52457a5d9
tree2ea425b3a763ce455bcc3c7a36416d0a26e26f4b
parent23b7d28896609e3f01765730599119baf53a56c9

link: make MachO atoms fully owned by the linker


12 files changed, 495 insertions(+), 432 deletions(-)

src/Module.zig+6-6
...@@ -4098,7 +4098,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {...@@ -4098,7 +4098,7 @@ pub fn ensureDeclAnalyzed(mod: *Module, decl_index: Decl.Index) SemaError!void {
40984098
4099 // The exports this Decl performs will be re-discovered, so we remove them here4099 // The exports this Decl performs will be re-discovered, so we remove them here
4100 // prior to re-analysis.4100 // prior to re-analysis.
4101 mod.deleteDeclExports(decl_index);4101 try mod.deleteDeclExports(decl_index);
41024102
4103 // Similarly, `@setAlignStack` invocations will be re-discovered.4103 // Similarly, `@setAlignStack` invocations will be re-discovered.
4104 if (decl.getFunction()) |func| {4104 if (decl.getFunction()) |func| {
...@@ -5265,7 +5265,7 @@ pub fn clearDecl(...@@ -5265,7 +5265,7 @@ pub fn clearDecl(
5265 assert(emit_h.decl_table.swapRemove(decl_index));5265 assert(emit_h.decl_table.swapRemove(decl_index));
5266 }5266 }
5267 _ = mod.compile_log_decls.swapRemove(decl_index);5267 _ = mod.compile_log_decls.swapRemove(decl_index);
5268 mod.deleteDeclExports(decl_index);5268 try mod.deleteDeclExports(decl_index);
52695269
5270 if (decl.has_tv) {5270 if (decl.has_tv) {
5271 if (decl.ty.isFnOrHasRuntimeBits()) {5271 if (decl.ty.isFnOrHasRuntimeBits()) {
...@@ -5276,7 +5276,7 @@ pub fn clearDecl(...@@ -5276,7 +5276,7 @@ pub fn clearDecl(
5276 decl.link = switch (mod.comp.bin_file.tag) {5276 decl.link = switch (mod.comp.bin_file.tag) {
5277 .coff => .{ .coff = link.File.Coff.Atom.empty },5277 .coff => .{ .coff = link.File.Coff.Atom.empty },
5278 .elf => .{ .elf = link.File.Elf.TextBlock.empty },5278 .elf => .{ .elf = link.File.Elf.TextBlock.empty },
5279 .macho => .{ .macho = link.File.MachO.Atom.empty },5279 .macho => .{ .macho = {} },
5280 .plan9 => .{ .plan9 = link.File.Plan9.DeclBlock.empty },5280 .plan9 => .{ .plan9 = link.File.Plan9.DeclBlock.empty },
5281 .c => .{ .c = {} },5281 .c => .{ .c = {} },
5282 .wasm => .{ .wasm = link.File.Wasm.DeclBlock.empty },5282 .wasm => .{ .wasm = link.File.Wasm.DeclBlock.empty },
...@@ -5358,7 +5358,7 @@ pub fn abortAnonDecl(mod: *Module, decl_index: Decl.Index) void {...@@ -5358,7 +5358,7 @@ pub fn abortAnonDecl(mod: *Module, decl_index: Decl.Index) void {
53585358
5359/// Delete all the Export objects that are caused by this Decl. Re-analysis of5359/// Delete all the Export objects that are caused by this Decl. Re-analysis of
5360/// this Decl will cause them to be re-created (or not).5360/// this Decl will cause them to be re-created (or not).
5361fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) void {5361fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) Allocator.Error!void {
5362 var export_owners = (mod.export_owners.fetchSwapRemove(decl_index) orelse return).value;5362 var export_owners = (mod.export_owners.fetchSwapRemove(decl_index) orelse return).value;
53635363
5364 for (export_owners.items) |exp| {5364 for (export_owners.items) |exp| {
...@@ -5384,7 +5384,7 @@ fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) void {...@@ -5384,7 +5384,7 @@ fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) void {
5384 elf.deleteExport(exp.link.elf);5384 elf.deleteExport(exp.link.elf);
5385 }5385 }
5386 if (mod.comp.bin_file.cast(link.File.MachO)) |macho| {5386 if (mod.comp.bin_file.cast(link.File.MachO)) |macho| {
5387 macho.deleteExport(exp.link.macho);5387 try macho.deleteDeclExport(decl_index, exp.options.name);
5388 }5388 }
5389 if (mod.comp.bin_file.cast(link.File.Wasm)) |wasm| {5389 if (mod.comp.bin_file.cast(link.File.Wasm)) |wasm| {
5390 wasm.deleteExport(exp.link.wasm);5390 wasm.deleteExport(exp.link.wasm);
...@@ -5696,7 +5696,7 @@ pub fn allocateNewDecl(...@@ -5696,7 +5696,7 @@ pub fn allocateNewDecl(
5696 .link = switch (mod.comp.bin_file.tag) {5696 .link = switch (mod.comp.bin_file.tag) {
5697 .coff => .{ .coff = link.File.Coff.Atom.empty },5697 .coff => .{ .coff = link.File.Coff.Atom.empty },
5698 .elf => .{ .elf = link.File.Elf.TextBlock.empty },5698 .elf => .{ .elf = link.File.Elf.TextBlock.empty },
5699 .macho => .{ .macho = link.File.MachO.Atom.empty },5699 .macho => .{ .macho = {} },
5700 .plan9 => .{ .plan9 = link.File.Plan9.DeclBlock.empty },5700 .plan9 => .{ .plan9 = link.File.Plan9.DeclBlock.empty },
5701 .c => .{ .c = {} },5701 .c => .{ .c = {} },
5702 .wasm => .{ .wasm = link.File.Wasm.DeclBlock.empty },5702 .wasm => .{ .wasm = link.File.Wasm.DeclBlock.empty },
src/Sema.zig+1-1
...@@ -5567,7 +5567,7 @@ pub fn analyzeExport(...@@ -5567,7 +5567,7 @@ pub fn analyzeExport(
5567 .link = switch (mod.comp.bin_file.tag) {5567 .link = switch (mod.comp.bin_file.tag) {
5568 .coff => .{ .coff = .{} },5568 .coff => .{ .coff = .{} },
5569 .elf => .{ .elf = .{} },5569 .elf => .{ .elf = .{} },
5570 .macho => .{ .macho = .{} },5570 .macho => .{ .macho = {} },
5571 .plan9 => .{ .plan9 = null },5571 .plan9 => .{ .plan9 = null },
5572 .c => .{ .c = {} },5572 .c => .{ .c = {} },
5573 .wasm => .{ .wasm = .{} },5573 .wasm => .{ .wasm = .{} },
src/arch/aarch64/CodeGen.zig+29-9
...@@ -4022,7 +4022,11 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type...@@ -4022,7 +4022,11 @@ fn store(self: *Self, ptr: MCValue, value: MCValue, ptr_ty: Type, value_ty: Type
4022 const mod = self.bin_file.options.module.?;4022 const mod = self.bin_file.options.module.?;
4023 const owner_decl = mod.declPtr(self.mod_fn.owner_decl);4023 const owner_decl = mod.declPtr(self.mod_fn.owner_decl);
4024 const atom_index = switch (self.bin_file.tag) {4024 const atom_index = switch (self.bin_file.tag) {
4025 .macho => owner_decl.link.macho.getSymbolIndex().?,4025 .macho => blk: {
4026 const macho_file = self.bin_file.cast(link.File.MachO).?;
4027 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
4028 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
4029 },
4026 .coff => owner_decl.link.coff.getSymbolIndex().?,4030 .coff => owner_decl.link.coff.getSymbolIndex().?,
4027 else => unreachable, // unsupported target format4031 else => unreachable, // unsupported target format
4028 };4032 };
...@@ -4308,11 +4312,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4308,11 +4312,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4308 const got_addr = @intCast(u32, fn_owner_decl.link.elf.getOffsetTableAddress(elf_file));4312 const got_addr = @intCast(u32, fn_owner_decl.link.elf.getOffsetTableAddress(elf_file));
4309 try self.genSetReg(Type.initTag(.usize), .x30, .{ .memory = got_addr });4313 try self.genSetReg(Type.initTag(.usize), .x30, .{ .memory = got_addr });
4310 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {4314 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
4311 try fn_owner_decl.link.macho.ensureInitialized(macho_file);4315 const atom = try macho_file.getOrCreateAtomForDecl(func.owner_decl);
4316 const sym_index = macho_file.getAtom(atom).getSymbolIndex().?;
4312 try self.genSetReg(Type.initTag(.u64), .x30, .{4317 try self.genSetReg(Type.initTag(.u64), .x30, .{
4313 .linker_load = .{4318 .linker_load = .{
4314 .type = .got,4319 .type = .got,
4315 .sym_index = fn_owner_decl.link.macho.getSymbolIndex().?,4320 .sym_index = sym_index,
4316 },4321 },
4317 });4322 });
4318 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {4323 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
...@@ -4349,11 +4354,13 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4349,11 +4354,13 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
43494354
4350 if (self.bin_file.cast(link.File.MachO)) |macho_file| {4355 if (self.bin_file.cast(link.File.MachO)) |macho_file| {
4351 const sym_index = try macho_file.getGlobalSymbol(mem.sliceTo(decl_name, 0));4356 const sym_index = try macho_file.getGlobalSymbol(mem.sliceTo(decl_name, 0));
4357 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
4358 const atom_index = macho_file.getAtom(atom).getSymbolIndex().?;
4352 _ = try self.addInst(.{4359 _ = try self.addInst(.{
4353 .tag = .call_extern,4360 .tag = .call_extern,
4354 .data = .{4361 .data = .{
4355 .relocation = .{4362 .relocation = .{
4356 .atom_index = mod.declPtr(self.mod_fn.owner_decl).link.macho.getSymbolIndex().?,4363 .atom_index = atom_index,
4357 .sym_index = sym_index,4364 .sym_index = sym_index,
4358 },4365 },
4359 },4366 },
...@@ -5491,7 +5498,11 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro...@@ -5491,7 +5498,11 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
5491 const mod = self.bin_file.options.module.?;5498 const mod = self.bin_file.options.module.?;
5492 const owner_decl = mod.declPtr(self.mod_fn.owner_decl);5499 const owner_decl = mod.declPtr(self.mod_fn.owner_decl);
5493 const atom_index = switch (self.bin_file.tag) {5500 const atom_index = switch (self.bin_file.tag) {
5494 .macho => owner_decl.link.macho.getSymbolIndex().?,5501 .macho => blk: {
5502 const macho_file = self.bin_file.cast(link.File.MachO).?;
5503 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
5504 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
5505 },
5495 .coff => owner_decl.link.coff.getSymbolIndex().?,5506 .coff => owner_decl.link.coff.getSymbolIndex().?,
5496 else => unreachable, // unsupported target format5507 else => unreachable, // unsupported target format
5497 };5508 };
...@@ -5605,7 +5616,11 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void...@@ -5605,7 +5616,11 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
5605 const mod = self.bin_file.options.module.?;5616 const mod = self.bin_file.options.module.?;
5606 const owner_decl = mod.declPtr(self.mod_fn.owner_decl);5617 const owner_decl = mod.declPtr(self.mod_fn.owner_decl);
5607 const atom_index = switch (self.bin_file.tag) {5618 const atom_index = switch (self.bin_file.tag) {
5608 .macho => owner_decl.link.macho.getSymbolIndex().?,5619 .macho => blk: {
5620 const macho_file = self.bin_file.cast(link.File.MachO).?;
5621 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
5622 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
5623 },
5609 .coff => owner_decl.link.coff.getSymbolIndex().?,5624 .coff => owner_decl.link.coff.getSymbolIndex().?,
5610 else => unreachable, // unsupported target format5625 else => unreachable, // unsupported target format
5611 };5626 };
...@@ -5799,7 +5814,11 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I...@@ -5799,7 +5814,11 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
5799 const mod = self.bin_file.options.module.?;5814 const mod = self.bin_file.options.module.?;
5800 const owner_decl = mod.declPtr(self.mod_fn.owner_decl);5815 const owner_decl = mod.declPtr(self.mod_fn.owner_decl);
5801 const atom_index = switch (self.bin_file.tag) {5816 const atom_index = switch (self.bin_file.tag) {
5802 .macho => owner_decl.link.macho.getSymbolIndex().?,5817 .macho => blk: {
5818 const macho_file = self.bin_file.cast(link.File.MachO).?;
5819 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
5820 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
5821 },
5803 .coff => owner_decl.link.coff.getSymbolIndex().?,5822 .coff => owner_decl.link.coff.getSymbolIndex().?,
5804 else => unreachable, // unsupported target format5823 else => unreachable, // unsupported target format
5805 };5824 };
...@@ -6122,10 +6141,11 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne...@@ -6122,10 +6141,11 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne
6122 try decl.link.elf.ensureInitialized(elf_file);6141 try decl.link.elf.ensureInitialized(elf_file);
6123 return MCValue{ .memory = decl.link.elf.getOffsetTableAddress(elf_file) };6142 return MCValue{ .memory = decl.link.elf.getOffsetTableAddress(elf_file) };
6124 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {6143 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
6125 try decl.link.macho.ensureInitialized(macho_file);6144 const atom = try macho_file.getOrCreateAtomForDecl(decl_index);
6145 const sym_index = macho_file.getAtom(atom).getSymbolIndex().?;
6126 return MCValue{ .linker_load = .{6146 return MCValue{ .linker_load = .{
6127 .type = .got,6147 .type = .got,
6128 .sym_index = decl.link.macho.getSymbolIndex().?,6148 .sym_index = sym_index,
6129 } };6149 } };
6130 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {6150 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
6131 try decl.link.coff.ensureInitialized(coff_file);6151 try decl.link.coff.ensureInitialized(coff_file);
src/arch/aarch64/Emit.zig+5-5
...@@ -670,9 +670,9 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -670,9 +670,9 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) !void {
670670
671 if (emit.bin_file.cast(link.File.MachO)) |macho_file| {671 if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
672 // Add relocation to the decl.672 // Add relocation to the decl.
673 const atom = macho_file.getAtomForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;673 const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
674 const target = macho_file.getGlobalByIndex(relocation.sym_index);674 const target = macho_file.getGlobalByIndex(relocation.sym_index);
675 try atom.addRelocation(macho_file, .{675 try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
676 .type = @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_BRANCH26),676 .type = @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_BRANCH26),
677 .target = target,677 .target = target,
678 .offset = offset,678 .offset = offset,
...@@ -883,10 +883,10 @@ fn mirLoadMemoryPie(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -883,10 +883,10 @@ fn mirLoadMemoryPie(emit: *Emit, inst: Mir.Inst.Index) !void {
883 }883 }
884884
885 if (emit.bin_file.cast(link.File.MachO)) |macho_file| {885 if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
886 const atom = macho_file.getAtomForSymbol(.{ .sym_index = data.atom_index, .file = null }).?;886 const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = data.atom_index, .file = null }).?;
887 // TODO this causes segfault in stage1887 // TODO this causes segfault in stage1
888 // try atom.addRelocations(macho_file, 2, .{888 // try atom.addRelocations(macho_file, 2, .{
889 try atom.addRelocation(macho_file, .{889 try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
890 .target = .{ .sym_index = data.sym_index, .file = null },890 .target = .{ .sym_index = data.sym_index, .file = null },
891 .offset = offset,891 .offset = offset,
892 .addend = 0,892 .addend = 0,
...@@ -902,7 +902,7 @@ fn mirLoadMemoryPie(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -902,7 +902,7 @@ fn mirLoadMemoryPie(emit: *Emit, inst: Mir.Inst.Index) !void {
902 else => unreachable,902 else => unreachable,
903 },903 },
904 });904 });
905 try atom.addRelocation(macho_file, .{905 try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
906 .target = .{ .sym_index = data.sym_index, .file = null },906 .target = .{ .sym_index = data.sym_index, .file = null },
907 .offset = offset + 4,907 .offset = offset + 4,
908 .addend = 0,908 .addend = 0,
src/arch/riscv64/CodeGen.zig+1-3
...@@ -2556,9 +2556,7 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne...@@ -2556,9 +2556,7 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne
2556 try decl.link.elf.ensureInitialized(elf_file);2556 try decl.link.elf.ensureInitialized(elf_file);
2557 return MCValue{ .memory = decl.link.elf.getOffsetTableAddress(elf_file) };2557 return MCValue{ .memory = decl.link.elf.getOffsetTableAddress(elf_file) };
2558 } else if (self.bin_file.cast(link.File.MachO)) |_| {2558 } else if (self.bin_file.cast(link.File.MachO)) |_| {
2559 // TODO I'm hacking my way through here by repurposing .memory for storing2559 unreachable;
2560 // index to the GOT target symbol index.
2561 return MCValue{ .memory = decl.link.macho.sym_index };
2562 } else if (self.bin_file.cast(link.File.Coff)) |_| {2560 } else if (self.bin_file.cast(link.File.Coff)) |_| {
2563 return self.fail("TODO codegen COFF const Decl pointer", .{});2561 return self.fail("TODO codegen COFF const Decl pointer", .{});
2564 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {2562 } else if (self.bin_file.cast(link.File.Plan9)) |p9| {
src/arch/x86_64/CodeGen.zig+17-14
...@@ -2670,10 +2670,12 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue...@@ -2670,10 +2670,12 @@ fn loadMemPtrIntoRegister(self: *Self, reg: Register, ptr_ty: Type, ptr: MCValue
2670 const abi_size = @intCast(u32, ptr_ty.abiSize(self.target.*));2670 const abi_size = @intCast(u32, ptr_ty.abiSize(self.target.*));
2671 const mod = self.bin_file.options.module.?;2671 const mod = self.bin_file.options.module.?;
2672 const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl);2672 const fn_owner_decl = mod.declPtr(self.mod_fn.owner_decl);
2673 const atom_index = if (self.bin_file.tag == link.File.MachO.base_tag)2673 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
2674 fn_owner_decl.link.macho.getSymbolIndex().?2674 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
2675 else2675 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
2676 fn_owner_decl.link.coff.getSymbolIndex().?;2676 } else if (self.bin_file.cast(link.File.Coff)) |_| blk: {
2677 break :blk fn_owner_decl.link.coff.getSymbolIndex().?;
2678 } else unreachable;
2677 const flags: u2 = switch (load_struct.type) {2679 const flags: u2 = switch (load_struct.type) {
2678 .got => 0b00,2680 .got => 0b00,
2679 .direct => 0b01,2681 .direct => 0b01,
...@@ -4023,8 +4025,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4023,8 +4025,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4023 .data = undefined,4025 .data = undefined,
4024 });4026 });
4025 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {4027 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
4026 try fn_owner_decl.link.macho.ensureInitialized(macho_file);4028 const atom_index = try macho_file.getOrCreateAtomForDecl(func.owner_decl);
4027 const sym_index = fn_owner_decl.link.macho.getSymbolIndex().?;4029 const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
4028 try self.genSetReg(Type.initTag(.usize), .rax, .{4030 try self.genSetReg(Type.initTag(.usize), .rax, .{
4029 .linker_load = .{4031 .linker_load = .{
4030 .type = .got,4032 .type = .got,
...@@ -4080,15 +4082,15 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier...@@ -4080,15 +4082,15 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
4080 });4082 });
4081 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {4083 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
4082 const sym_index = try macho_file.getGlobalSymbol(mem.sliceTo(decl_name, 0));4084 const sym_index = try macho_file.getGlobalSymbol(mem.sliceTo(decl_name, 0));
4085 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
4086 const atom_index = macho_file.getAtom(atom).getSymbolIndex().?;
4083 _ = try self.addInst(.{4087 _ = try self.addInst(.{
4084 .tag = .call_extern,4088 .tag = .call_extern,
4085 .ops = undefined,4089 .ops = undefined,
4086 .data = .{4090 .data = .{ .relocation = .{
4087 .relocation = .{4091 .atom_index = atom_index,
4088 .atom_index = mod.declPtr(self.mod_fn.owner_decl).link.macho.getSymbolIndex().?,4092 .sym_index = sym_index,
4089 .sym_index = sym_index,4093 } },
4090 },
4091 },
4092 });4094 });
4093 } else {4095 } else {
4094 return self.fail("TODO implement calling extern functions", .{});4096 return self.fail("TODO implement calling extern functions", .{});
...@@ -6722,10 +6724,11 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne...@@ -6722,10 +6724,11 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne
6722 try decl.link.elf.ensureInitialized(elf_file);6724 try decl.link.elf.ensureInitialized(elf_file);
6723 return MCValue{ .memory = decl.link.elf.getOffsetTableAddress(elf_file) };6725 return MCValue{ .memory = decl.link.elf.getOffsetTableAddress(elf_file) };
6724 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {6726 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
6725 try decl.link.macho.ensureInitialized(macho_file);6727 const atom_index = try macho_file.getOrCreateAtomForDecl(decl_index);
6728 const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
6726 return MCValue{ .linker_load = .{6729 return MCValue{ .linker_load = .{
6727 .type = .got,6730 .type = .got,
6728 .sym_index = decl.link.macho.getSymbolIndex().?,6731 .sym_index = sym_index,
6729 } };6732 } };
6730 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {6733 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
6731 try decl.link.coff.ensureInitialized(coff_file);6734 try decl.link.coff.ensureInitialized(coff_file);
src/arch/x86_64/Emit.zig+4-4
...@@ -1001,8 +1001,8 @@ fn mirLeaPic(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {...@@ -1001,8 +1001,8 @@ fn mirLeaPic(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
1001 0b01 => @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_SIGNED),1001 0b01 => @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_SIGNED),
1002 else => unreachable,1002 else => unreachable,
1003 };1003 };
1004 const atom = macho_file.getAtomForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;1004 const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
1005 try atom.addRelocation(macho_file, .{1005 try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
1006 .type = reloc_type,1006 .type = reloc_type,
1007 .target = .{ .sym_index = relocation.sym_index, .file = null },1007 .target = .{ .sym_index = relocation.sym_index, .file = null },
1008 .offset = @intCast(u32, end_offset - 4),1008 .offset = @intCast(u32, end_offset - 4),
...@@ -1140,9 +1140,9 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {...@@ -1140,9 +1140,9 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
11401140
1141 if (emit.bin_file.cast(link.File.MachO)) |macho_file| {1141 if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
1142 // Add relocation to the decl.1142 // Add relocation to the decl.
1143 const atom = macho_file.getAtomForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;1143 const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
1144 const target = macho_file.getGlobalByIndex(relocation.sym_index);1144 const target = macho_file.getGlobalByIndex(relocation.sym_index);
1145 try atom.addRelocation(macho_file, .{1145 try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
1146 .type = @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_BRANCH),1146 .type = @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_BRANCH),
1147 .target = target,1147 .target = target,
1148 .offset = offset,1148 .offset = offset,
src/link.zig+2-2
...@@ -264,7 +264,7 @@ pub const File = struct {...@@ -264,7 +264,7 @@ pub const File = struct {
264 pub const LinkBlock = union {264 pub const LinkBlock = union {
265 elf: Elf.TextBlock,265 elf: Elf.TextBlock,
266 coff: Coff.Atom,266 coff: Coff.Atom,
267 macho: MachO.Atom,267 macho: void,
268 plan9: Plan9.DeclBlock,268 plan9: Plan9.DeclBlock,
269 c: void,269 c: void,
270 wasm: Wasm.DeclBlock,270 wasm: Wasm.DeclBlock,
...@@ -286,7 +286,7 @@ pub const File = struct {...@@ -286,7 +286,7 @@ pub const File = struct {
286 pub const Export = union {286 pub const Export = union {
287 elf: Elf.Export,287 elf: Elf.Export,
288 coff: Coff.Export,288 coff: Coff.Export,
289 macho: MachO.Export,289 macho: void,
290 plan9: Plan9.Export,290 plan9: Plan9.Export,
291 c: void,291 c: void,
292 wasm: Wasm.Export,292 wasm: Wasm.Export,
src/link/Dwarf.zig+1-1
...@@ -2639,7 +2639,7 @@ fn getDbgInfoAtom(tag: File.Tag, mod: *Module, decl_index: Module.Decl.Index) *A...@@ -2639,7 +2639,7 @@ fn getDbgInfoAtom(tag: File.Tag, mod: *Module, decl_index: Module.Decl.Index) *A
2639 const decl = mod.declPtr(decl_index);2639 const decl = mod.declPtr(decl_index);
2640 return switch (tag) {2640 return switch (tag) {
2641 .elf => &decl.link.elf.dbg_info_atom,2641 .elf => &decl.link.elf.dbg_info_atom,
2642 .macho => &decl.link.macho.dbg_info_atom,2642 .macho => unreachable,
2643 .wasm => &decl.link.wasm.dbg_info_atom,2643 .wasm => &decl.link.wasm.dbg_info_atom,
2644 else => unreachable,2644 else => unreachable,
2645 };2645 };
src/link/MachO.zig+377-342
...@@ -66,7 +66,7 @@ const Section = struct {...@@ -66,7 +66,7 @@ const Section = struct {
6666
67 // TODO is null here necessary, or can we do away with tracking via section67 // TODO is null here necessary, or can we do away with tracking via section
68 // size in incremental context?68 // size in incremental context?
69 last_atom: ?*Atom = null,69 last_atom_index: ?Atom.Index = null,
7070
71 /// A list of atoms that have surplus capacity. This list can have false71 /// A list of atoms that have surplus capacity. This list can have false
72 /// positives, as functions grow and shrink over time, only sometimes being added72 /// positives, as functions grow and shrink over time, only sometimes being added
...@@ -83,7 +83,7 @@ const Section = struct {...@@ -83,7 +83,7 @@ const Section = struct {
83 /// overcapacity can be negative. A simple way to have negative overcapacity is to83 /// overcapacity can be negative. A simple way to have negative overcapacity is to
84 /// allocate a fresh atom, which will have ideal capacity, and then grow it84 /// allocate a fresh atom, which will have ideal capacity, and then grow it
85 /// by 1 byte. It will then have -1 overcapacity.85 /// by 1 byte. It will then have -1 overcapacity.
86 free_list: std.ArrayListUnmanaged(*Atom) = .{},86 free_list: std.ArrayListUnmanaged(Atom.Index) = .{},
87};87};
8888
89base: File,89base: File,
...@@ -140,8 +140,8 @@ locals_free_list: std.ArrayListUnmanaged(u32) = .{},...@@ -140,8 +140,8 @@ locals_free_list: std.ArrayListUnmanaged(u32) = .{},
140globals_free_list: std.ArrayListUnmanaged(u32) = .{},140globals_free_list: std.ArrayListUnmanaged(u32) = .{},
141141
142dyld_stub_binder_index: ?u32 = null,142dyld_stub_binder_index: ?u32 = null,
143dyld_private_atom: ?*Atom = null,143dyld_private_atom_index: ?Atom.Index = null,
144stub_helper_preamble_atom: ?*Atom = null,144stub_helper_preamble_atom_index: ?Atom.Index = null,
145145
146strtab: StringTable(.strtab) = .{},146strtab: StringTable(.strtab) = .{},
147147
...@@ -164,10 +164,10 @@ segment_table_dirty: bool = false,...@@ -164,10 +164,10 @@ segment_table_dirty: bool = false,
164cold_start: bool = true,164cold_start: bool = true,
165165
166/// List of atoms that are either synthetic or map directly to the Zig source program.166/// List of atoms that are either synthetic or map directly to the Zig source program.
167managed_atoms: std.ArrayListUnmanaged(*Atom) = .{},167atoms: std.ArrayListUnmanaged(Atom) = .{},
168168
169/// Table of atoms indexed by the symbol index.169/// Table of atoms indexed by the symbol index.
170atom_by_index_table: std.AutoHashMapUnmanaged(u32, *Atom) = .{},170atom_by_index_table: std.AutoHashMapUnmanaged(u32, Atom.Index) = .{},
171171
172/// Table of unnamed constants associated with a parent `Decl`.172/// Table of unnamed constants associated with a parent `Decl`.
173/// We store them here so that we can free the constants whenever the `Decl`173/// We store them here so that we can free the constants whenever the `Decl`
...@@ -210,11 +210,36 @@ bindings: BindingTable = .{},...@@ -210,11 +210,36 @@ bindings: BindingTable = .{},
210/// this will be a table indexed by index into the list of Atoms.210/// this will be a table indexed by index into the list of Atoms.
211lazy_bindings: BindingTable = .{},211lazy_bindings: BindingTable = .{},
212212
213/// Table of Decls that are currently alive.213/// Table of tracked Decls.
214/// We store them here so that we can properly dispose of any allocated214decls: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, DeclMetadata) = .{},
215/// memory within the atom in the incremental linker.215
216/// TODO consolidate this.216const DeclMetadata = struct {
217decls: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, ?u8) = .{},217 atom: Atom.Index,
218 section: u8,
219 /// A list of all exports aliases of this Decl.
220 /// TODO do we actually need this at all?
221 exports: std.ArrayListUnmanaged(u32) = .{},
222
223 fn getExport(m: DeclMetadata, macho_file: *const MachO, name: []const u8) ?u32 {
224 for (m.exports.items) |exp| {
225 if (mem.eql(u8, name, macho_file.getSymbolName(.{
226 .sym_index = exp,
227 .file = null,
228 }))) return exp;
229 }
230 return null;
231 }
232
233 fn getExportPtr(m: *DeclMetadata, macho_file: *MachO, name: []const u8) ?*u32 {
234 for (m.exports.items) |*exp| {
235 if (mem.eql(u8, name, macho_file.getSymbolName(.{
236 .sym_index = exp.*,
237 .file = null,
238 }))) return exp;
239 }
240 return null;
241 }
242};
218243
219const Entry = struct {244const Entry = struct {
220 target: SymbolWithLoc,245 target: SymbolWithLoc,
...@@ -229,8 +254,8 @@ const Entry = struct {...@@ -229,8 +254,8 @@ const Entry = struct {
229 return macho_file.getSymbolPtr(.{ .sym_index = entry.sym_index, .file = null });254 return macho_file.getSymbolPtr(.{ .sym_index = entry.sym_index, .file = null });
230 }255 }
231256
232 pub fn getAtom(entry: Entry, macho_file: *MachO) ?*Atom {257 pub fn getAtomIndex(entry: Entry, macho_file: *MachO) ?Atom.Index {
233 return macho_file.getAtomForSymbol(.{ .sym_index = entry.sym_index, .file = null });258 return macho_file.getAtomIndexForSymbol(.{ .sym_index = entry.sym_index, .file = null });
234 }259 }
235260
236 pub fn getName(entry: Entry, macho_file: *MachO) []const u8 {261 pub fn getName(entry: Entry, macho_file: *MachO) []const u8 {
...@@ -238,10 +263,10 @@ const Entry = struct {...@@ -238,10 +263,10 @@ const Entry = struct {
238 }263 }
239};264};
240265
241const BindingTable = std.AutoArrayHashMapUnmanaged(*Atom, std.ArrayListUnmanaged(Atom.Binding));266const BindingTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(Atom.Binding));
242const UnnamedConstTable = std.AutoArrayHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(*Atom));267const UnnamedConstTable = std.AutoArrayHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(Atom.Index));
243const RebaseTable = std.AutoArrayHashMapUnmanaged(*Atom, std.ArrayListUnmanaged(u32));268const RebaseTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(u32));
244const RelocationTable = std.AutoArrayHashMapUnmanaged(*Atom, std.ArrayListUnmanaged(Relocation));269const RelocationTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(Relocation));
245270
246const PendingUpdate = union(enum) {271const PendingUpdate = union(enum) {
247 resolve_undef: u32,272 resolve_undef: u32,
...@@ -286,10 +311,6 @@ pub const default_pagezero_vmsize: u64 = 0x100000000;...@@ -286,10 +311,6 @@ pub const default_pagezero_vmsize: u64 = 0x100000000;
286/// potential future extensions.311/// potential future extensions.
287pub const default_headerpad_size: u32 = 0x1000;312pub const default_headerpad_size: u32 = 0x1000;
288313
289pub const Export = struct {
290 sym_index: ?u32 = null,
291};
292
293pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {314pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {
294 assert(options.target.ofmt == .macho);315 assert(options.target.ofmt == .macho);
295316
...@@ -451,9 +472,9 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No...@@ -451,9 +472,9 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
451472
452 const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented;473 const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented;
453474
454 if (self.d_sym) |*d_sym| {475 // if (self.d_sym) |*d_sym| {
455 try d_sym.dwarf.flushModule(module);476 // try d_sym.dwarf.flushModule(module);
456 }477 // }
457478
458 var libs = std.StringArrayHashMap(link.SystemLib).init(arena);479 var libs = std.StringArrayHashMap(link.SystemLib).init(arena);
459 try resolveLibSystem(480 try resolveLibSystem(
...@@ -547,8 +568,8 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No...@@ -547,8 +568,8 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
547568
548 try self.allocateSpecialSymbols();569 try self.allocateSpecialSymbols();
549570
550 for (self.relocs.keys()) |atom| {571 for (self.relocs.keys()) |atom_index| {
551 try atom.resolveRelocations(self);572 try Atom.resolveRelocations(self, atom_index);
552 }573 }
553574
554 if (build_options.enable_logging) {575 if (build_options.enable_logging) {
...@@ -643,10 +664,10 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No...@@ -643,10 +664,10 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
643 try self.writeCodeSignature(comp, csig); // code signing always comes last664 try self.writeCodeSignature(comp, csig); // code signing always comes last
644 }665 }
645666
646 if (self.d_sym) |*d_sym| {667 // if (self.d_sym) |*d_sym| {
647 // Flush debug symbols bundle.668 // // Flush debug symbols bundle.
648 try d_sym.flushModule(self);669 // try d_sym.flushModule(self);
649 }670 // }
650671
651 // if (build_options.enable_link_snapshots) {672 // if (build_options.enable_link_snapshots) {
652 // if (self.base.options.enable_link_snapshots)673 // if (self.base.options.enable_link_snapshots)
...@@ -999,18 +1020,19 @@ pub fn parseDependentLibs(self: *MachO, syslibroot: ?[]const u8, dependent_libs:...@@ -999,18 +1020,19 @@ pub fn parseDependentLibs(self: *MachO, syslibroot: ?[]const u8, dependent_libs:
999 }1020 }
1000}1021}
10011022
1002pub fn writeAtom(self: *MachO, atom: *Atom, code: []const u8) !void {1023pub fn writeAtom(self: *MachO, atom_index: Atom.Index, code: []const u8) !void {
1024 const atom = self.getAtom(atom_index);
1003 const sym = atom.getSymbol(self);1025 const sym = atom.getSymbol(self);
1004 const section = self.sections.get(sym.n_sect - 1);1026 const section = self.sections.get(sym.n_sect - 1);
1005 const file_offset = section.header.offset + sym.n_value - section.header.addr;1027 const file_offset = section.header.offset + sym.n_value - section.header.addr;
1006 log.debug("writing atom for symbol {s} at file offset 0x{x}", .{ atom.getName(self), file_offset });1028 log.debug("writing atom for symbol {s} at file offset 0x{x}", .{ atom.getName(self), file_offset });
1007 try self.base.file.?.pwriteAll(code, file_offset);1029 try self.base.file.?.pwriteAll(code, file_offset);
1008 try atom.resolveRelocations(self);1030 try Atom.resolveRelocations(self, atom_index);
1009}1031}
10101032
1011fn writePtrWidthAtom(self: *MachO, atom: *Atom) !void {1033fn writePtrWidthAtom(self: *MachO, atom_index: Atom.Index) !void {
1012 var buffer: [@sizeOf(u64)]u8 = [_]u8{0} ** @sizeOf(u64);1034 var buffer: [@sizeOf(u64)]u8 = [_]u8{0} ** @sizeOf(u64);
1013 try self.writeAtom(atom, &buffer);1035 try self.writeAtom(atom_index, &buffer);
1014}1036}
10151037
1016fn markRelocsDirtyByTarget(self: *MachO, target: SymbolWithLoc) void {1038fn markRelocsDirtyByTarget(self: *MachO, target: SymbolWithLoc) void {
...@@ -1026,7 +1048,8 @@ fn markRelocsDirtyByTarget(self: *MachO, target: SymbolWithLoc) void {...@@ -1026,7 +1048,8 @@ fn markRelocsDirtyByTarget(self: *MachO, target: SymbolWithLoc) void {
1026fn markRelocsDirtyByAddress(self: *MachO, addr: u64) void {1048fn markRelocsDirtyByAddress(self: *MachO, addr: u64) void {
1027 for (self.relocs.values()) |*relocs| {1049 for (self.relocs.values()) |*relocs| {
1028 for (relocs.items) |*reloc| {1050 for (relocs.items) |*reloc| {
1029 const target_atom = reloc.getTargetAtom(self) orelse continue;1051 const target_atom_index = reloc.getTargetAtomIndex(self) orelse continue;
1052 const target_atom = self.getAtom(target_atom_index);
1030 const target_sym = target_atom.getSymbol(self);1053 const target_sym = target_atom.getSymbol(self);
1031 if (target_sym.n_value < addr) continue;1054 if (target_sym.n_value < addr) continue;
1032 reloc.dirty = true;1055 reloc.dirty = true;
...@@ -1053,26 +1076,39 @@ pub fn allocateSpecialSymbols(self: *MachO) !void {...@@ -1053,26 +1076,39 @@ pub fn allocateSpecialSymbols(self: *MachO) !void {
1053 }1076 }
1054}1077}
10551078
1056pub fn createGotAtom(self: *MachO, target: SymbolWithLoc) !*Atom {1079pub fn createAtom(self: *MachO) !Atom.Index {
1057 const gpa = self.base.allocator;1080 const gpa = self.base.allocator;
1081 const atom_index = @intCast(Atom.Index, self.atoms.items.len);
1082 const atom = try self.atoms.addOne(gpa);
1083 const sym_index = try self.allocateSymbol();
1084 try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom_index);
1085 atom.* = .{
1086 .sym_index = sym_index,
1087 .file = null,
1088 .size = 0,
1089 .alignment = 0,
1090 .prev_index = null,
1091 .next_index = null,
1092 .dbg_info_atom = undefined,
1093 };
1094 log.debug("creating ATOM(%{d}) at index {d}", .{ sym_index, atom_index });
1095 return atom_index;
1096}
10581097
1059 const atom = try gpa.create(Atom);1098pub fn createGotAtom(self: *MachO, target: SymbolWithLoc) !Atom.Index {
1060 atom.* = Atom.empty;1099 const atom_index = try self.createAtom();
1061 try atom.ensureInitialized(self);1100 const atom = self.getAtomPtr(atom_index);
1062 atom.size = @sizeOf(u64);1101 atom.size = @sizeOf(u64);
1063 atom.alignment = @alignOf(u64);1102 atom.alignment = @alignOf(u64);
1064 errdefer gpa.destroy(atom);
1065
1066 try self.managed_atoms.append(gpa, atom);
10671103
1068 const sym = atom.getSymbolPtr(self);1104 const sym = atom.getSymbolPtr(self);
1069 sym.n_type = macho.N_SECT;1105 sym.n_type = macho.N_SECT;
1070 sym.n_sect = self.got_section_index.? + 1;1106 sym.n_sect = self.got_section_index.? + 1;
1071 sym.n_value = try self.allocateAtom(atom, atom.size, @alignOf(u64));1107 sym.n_value = try self.allocateAtom(atom_index, atom.size, @alignOf(u64));
10721108
1073 log.debug("allocated GOT atom at 0x{x}", .{sym.n_value});1109 log.debug("allocated GOT atom at 0x{x}", .{sym.n_value});
10741110
1075 try atom.addRelocation(self, .{1111 try Atom.addRelocation(self, atom_index, .{
1076 .type = switch (self.base.options.target.cpu.arch) {1112 .type = switch (self.base.options.target.cpu.arch) {
1077 .aarch64 => @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_UNSIGNED),1113 .aarch64 => @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_UNSIGNED),
1078 .x86_64 => @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_UNSIGNED),1114 .x86_64 => @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_UNSIGNED),
...@@ -1087,45 +1123,39 @@ pub fn createGotAtom(self: *MachO, target: SymbolWithLoc) !*Atom {...@@ -1087,45 +1123,39 @@ pub fn createGotAtom(self: *MachO, target: SymbolWithLoc) !*Atom {
10871123
1088 const target_sym = self.getSymbol(target);1124 const target_sym = self.getSymbol(target);
1089 if (target_sym.undf()) {1125 if (target_sym.undf()) {
1090 try atom.addBinding(self, .{1126 try Atom.addBinding(self, atom_index, .{
1091 .target = self.getGlobal(self.getSymbolName(target)).?,1127 .target = self.getGlobal(self.getSymbolName(target)).?,
1092 .offset = 0,1128 .offset = 0,
1093 });1129 });
1094 } else {1130 } else {
1095 try atom.addRebase(self, 0);1131 try Atom.addRebase(self, atom_index, 0);
1096 }1132 }
10971133
1098 return atom;1134 return atom_index;
1099}1135}
11001136
1101pub fn createDyldPrivateAtom(self: *MachO) !void {1137pub fn createDyldPrivateAtom(self: *MachO) !void {
1102 if (self.dyld_stub_binder_index == null) return;1138 if (self.dyld_stub_binder_index == null) return;
1103 if (self.dyld_private_atom != null) return;1139 if (self.dyld_private_atom_index != null) return;
11041140
1105 const gpa = self.base.allocator;1141 const atom_index = try self.createAtom();
11061142 const atom = self.getAtomPtr(atom_index);
1107 const atom = try gpa.create(Atom);
1108 atom.* = Atom.empty;
1109 try atom.ensureInitialized(self);
1110 atom.size = @sizeOf(u64);1143 atom.size = @sizeOf(u64);
1111 atom.alignment = @alignOf(u64);1144 atom.alignment = @alignOf(u64);
1112 errdefer gpa.destroy(atom);
11131145
1114 const sym = atom.getSymbolPtr(self);1146 const sym = atom.getSymbolPtr(self);
1115 sym.n_type = macho.N_SECT;1147 sym.n_type = macho.N_SECT;
1116 sym.n_sect = self.data_section_index.? + 1;1148 sym.n_sect = self.data_section_index.? + 1;
1117 self.dyld_private_atom = atom;1149 self.dyld_private_atom_index = atom_index;
1118
1119 try self.managed_atoms.append(gpa, atom);
11201150
1121 sym.n_value = try self.allocateAtom(atom, atom.size, @alignOf(u64));1151 sym.n_value = try self.allocateAtom(atom_index, atom.size, @alignOf(u64));
1122 log.debug("allocated dyld_private atom at 0x{x}", .{sym.n_value});1152 log.debug("allocated dyld_private atom at 0x{x}", .{sym.n_value});
1123 try self.writePtrWidthAtom(atom);1153 try self.writePtrWidthAtom(atom_index);
1124}1154}
11251155
1126pub fn createStubHelperPreambleAtom(self: *MachO) !void {1156pub fn createStubHelperPreambleAtom(self: *MachO) !void {
1127 if (self.dyld_stub_binder_index == null) return;1157 if (self.dyld_stub_binder_index == null) return;
1128 if (self.stub_helper_preamble_atom != null) return;1158 if (self.stub_helper_preamble_atom_index != null) return;
11291159
1130 const gpa = self.base.allocator;1160 const gpa = self.base.allocator;
1131 const arch = self.base.options.target.cpu.arch;1161 const arch = self.base.options.target.cpu.arch;
...@@ -1134,22 +1164,23 @@ pub fn createStubHelperPreambleAtom(self: *MachO) !void {...@@ -1134,22 +1164,23 @@ pub fn createStubHelperPreambleAtom(self: *MachO) !void {
1134 .aarch64 => 6 * @sizeOf(u32),1164 .aarch64 => 6 * @sizeOf(u32),
1135 else => unreachable,1165 else => unreachable,
1136 };1166 };
1137 const atom = try gpa.create(Atom);1167 const atom_index = try self.createAtom();
1138 atom.* = Atom.empty;1168 const atom = self.getAtomPtr(atom_index);
1139 try atom.ensureInitialized(self);
1140 atom.size = size;1169 atom.size = size;
1141 atom.alignment = switch (arch) {1170 atom.alignment = switch (arch) {
1142 .x86_64 => 1,1171 .x86_64 => 1,
1143 .aarch64 => @alignOf(u32),1172 .aarch64 => @alignOf(u32),
1144 else => unreachable,1173 else => unreachable,
1145 };1174 };
1146 errdefer gpa.destroy(atom);
11471175
1148 const sym = atom.getSymbolPtr(self);1176 const sym = atom.getSymbolPtr(self);
1149 sym.n_type = macho.N_SECT;1177 sym.n_type = macho.N_SECT;
1150 sym.n_sect = self.stub_helper_section_index.? + 1;1178 sym.n_sect = self.stub_helper_section_index.? + 1;
11511179
1152 const dyld_private_sym_index = self.dyld_private_atom.?.getSymbolIndex().?;1180 const dyld_private_sym_index = if (self.dyld_private_atom_index) |dyld_index|
1181 self.getAtom(dyld_index).getSymbolIndex().?
1182 else
1183 unreachable;
11531184
1154 const code = try gpa.alloc(u8, size);1185 const code = try gpa.alloc(u8, size);
1155 defer gpa.free(code);1186 defer gpa.free(code);
...@@ -1168,7 +1199,7 @@ pub fn createStubHelperPreambleAtom(self: *MachO) !void {...@@ -1168,7 +1199,7 @@ pub fn createStubHelperPreambleAtom(self: *MachO) !void {
1168 code[9] = 0xff;1199 code[9] = 0xff;
1169 code[10] = 0x25;1200 code[10] = 0x25;
11701201
1171 try atom.addRelocations(self, 2, .{ .{1202 try Atom.addRelocations(self, atom_index, 2, .{ .{
1172 .type = @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_SIGNED),1203 .type = @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_SIGNED),
1173 .target = .{ .sym_index = dyld_private_sym_index, .file = null },1204 .target = .{ .sym_index = dyld_private_sym_index, .file = null },
1174 .offset = 3,1205 .offset = 3,
...@@ -1208,7 +1239,7 @@ pub fn createStubHelperPreambleAtom(self: *MachO) !void {...@@ -1208,7 +1239,7 @@ pub fn createStubHelperPreambleAtom(self: *MachO) !void {
1208 // br x161239 // br x16
1209 mem.writeIntLittle(u32, code[20..][0..4], aarch64.Instruction.br(.x16).toU32());1240 mem.writeIntLittle(u32, code[20..][0..4], aarch64.Instruction.br(.x16).toU32());
12101241
1211 try atom.addRelocations(self, 4, .{ .{1242 try Atom.addRelocations(self, atom_index, 4, .{ .{
1212 .type = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_PAGE21),1243 .type = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_PAGE21),
1213 .target = .{ .sym_index = dyld_private_sym_index, .file = null },1244 .target = .{ .sym_index = dyld_private_sym_index, .file = null },
1214 .offset = 0,1245 .offset = 0,
...@@ -1241,16 +1272,14 @@ pub fn createStubHelperPreambleAtom(self: *MachO) !void {...@@ -1241,16 +1272,14 @@ pub fn createStubHelperPreambleAtom(self: *MachO) !void {
12411272
1242 else => unreachable,1273 else => unreachable,
1243 }1274 }
1244 self.stub_helper_preamble_atom = atom;1275 self.stub_helper_preamble_atom_index = atom_index;
12451276
1246 try self.managed_atoms.append(gpa, atom);1277 sym.n_value = try self.allocateAtom(atom_index, size, atom.alignment);
1247
1248 sym.n_value = try self.allocateAtom(atom, size, atom.alignment);
1249 log.debug("allocated stub preamble atom at 0x{x}", .{sym.n_value});1278 log.debug("allocated stub preamble atom at 0x{x}", .{sym.n_value});
1250 try self.writeAtom(atom, code);1279 try self.writeAtom(atom_index, code);
1251}1280}
12521281
1253pub fn createStubHelperAtom(self: *MachO) !*Atom {1282pub fn createStubHelperAtom(self: *MachO) !Atom.Index {
1254 const gpa = self.base.allocator;1283 const gpa = self.base.allocator;
1255 const arch = self.base.options.target.cpu.arch;1284 const arch = self.base.options.target.cpu.arch;
1256 const size: u4 = switch (arch) {1285 const size: u4 = switch (arch) {
...@@ -1258,16 +1287,14 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom {...@@ -1258,16 +1287,14 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom {
1258 .aarch64 => 3 * @sizeOf(u32),1287 .aarch64 => 3 * @sizeOf(u32),
1259 else => unreachable,1288 else => unreachable,
1260 };1289 };
1261 const atom = try gpa.create(Atom);1290 const atom_index = try self.createAtom();
1262 atom.* = Atom.empty;1291 const atom = self.getAtomPtr(atom_index);
1263 try atom.ensureInitialized(self);
1264 atom.size = size;1292 atom.size = size;
1265 atom.alignment = switch (arch) {1293 atom.alignment = switch (arch) {
1266 .x86_64 => 1,1294 .x86_64 => 1,
1267 .aarch64 => @alignOf(u32),1295 .aarch64 => @alignOf(u32),
1268 else => unreachable,1296 else => unreachable,
1269 };1297 };
1270 errdefer gpa.destroy(atom);
12711298
1272 const sym = atom.getSymbolPtr(self);1299 const sym = atom.getSymbolPtr(self);
1273 sym.n_type = macho.N_SECT;1300 sym.n_type = macho.N_SECT;
...@@ -1277,6 +1304,11 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom {...@@ -1277,6 +1304,11 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom {
1277 defer gpa.free(code);1304 defer gpa.free(code);
1278 mem.set(u8, code, 0);1305 mem.set(u8, code, 0);
12791306
1307 const stub_helper_preamble_atom_sym_index = if (self.stub_helper_preamble_atom_index) |stub_index|
1308 self.getAtom(stub_index).getSymbolIndex().?
1309 else
1310 unreachable;
1311
1280 switch (arch) {1312 switch (arch) {
1281 .x86_64 => {1313 .x86_64 => {
1282 // pushq1314 // pushq
...@@ -1285,9 +1317,9 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom {...@@ -1285,9 +1317,9 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom {
1285 // jmpq1317 // jmpq
1286 code[5] = 0xe9;1318 code[5] = 0xe9;
12871319
1288 try atom.addRelocation(self, .{1320 try Atom.addRelocation(self, atom_index, .{
1289 .type = @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_BRANCH),1321 .type = @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_BRANCH),
1290 .target = .{ .sym_index = self.stub_helper_preamble_atom.?.getSymbolIndex().?, .file = null },1322 .target = .{ .sym_index = stub_helper_preamble_atom_sym_index, .file = null },
1291 .offset = 6,1323 .offset = 6,
1292 .addend = 0,1324 .addend = 0,
1293 .pcrel = true,1325 .pcrel = true,
...@@ -1308,9 +1340,9 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom {...@@ -1308,9 +1340,9 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom {
1308 mem.writeIntLittle(u32, code[4..8], aarch64.Instruction.b(0).toU32());1340 mem.writeIntLittle(u32, code[4..8], aarch64.Instruction.b(0).toU32());
1309 // Next 4 bytes 8..12 are just a placeholder populated in `populateLazyBindOffsetsInStubHelper`.1341 // Next 4 bytes 8..12 are just a placeholder populated in `populateLazyBindOffsetsInStubHelper`.
13101342
1311 try atom.addRelocation(self, .{1343 try Atom.addRelocation(self, atom_index, .{
1312 .type = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_BRANCH26),1344 .type = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_BRANCH26),
1313 .target = .{ .sym_index = self.stub_helper_preamble_atom.?.getSymbolIndex().?, .file = null },1345 .target = .{ .sym_index = stub_helper_preamble_atom_sym_index, .file = null },
1314 .offset = 4,1346 .offset = 4,
1315 .addend = 0,1347 .addend = 0,
1316 .pcrel = true,1348 .pcrel = true,
...@@ -1320,29 +1352,24 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom {...@@ -1320,29 +1352,24 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom {
1320 else => unreachable,1352 else => unreachable,
1321 }1353 }
13221354
1323 try self.managed_atoms.append(gpa, atom);1355 sym.n_value = try self.allocateAtom(atom_index, size, atom.alignment);
1324
1325 sym.n_value = try self.allocateAtom(atom, size, atom.alignment);
1326 log.debug("allocated stub helper atom at 0x{x}", .{sym.n_value});1356 log.debug("allocated stub helper atom at 0x{x}", .{sym.n_value});
1327 try self.writeAtom(atom, code);1357 try self.writeAtom(atom_index, code);
13281358
1329 return atom;1359 return atom_index;
1330}1360}
13311361
1332pub fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32, target: SymbolWithLoc) !*Atom {1362pub fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32, target: SymbolWithLoc) !Atom.Index {
1333 const gpa = self.base.allocator;1363 const atom_index = try self.createAtom();
1334 const atom = try gpa.create(Atom);1364 const atom = self.getAtomPtr(atom_index);
1335 atom.* = Atom.empty;
1336 try atom.ensureInitialized(self);
1337 atom.size = @sizeOf(u64);1365 atom.size = @sizeOf(u64);
1338 atom.alignment = @alignOf(u64);1366 atom.alignment = @alignOf(u64);
1339 errdefer gpa.destroy(atom);
13401367
1341 const sym = atom.getSymbolPtr(self);1368 const sym = atom.getSymbolPtr(self);
1342 sym.n_type = macho.N_SECT;1369 sym.n_type = macho.N_SECT;
1343 sym.n_sect = self.la_symbol_ptr_section_index.? + 1;1370 sym.n_sect = self.la_symbol_ptr_section_index.? + 1;
13441371
1345 try atom.addRelocation(self, .{1372 try Atom.addRelocation(self, atom_index, .{
1346 .type = switch (self.base.options.target.cpu.arch) {1373 .type = switch (self.base.options.target.cpu.arch) {
1347 .aarch64 => @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_UNSIGNED),1374 .aarch64 => @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_UNSIGNED),
1348 .x86_64 => @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_UNSIGNED),1375 .x86_64 => @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_UNSIGNED),
...@@ -1354,22 +1381,20 @@ pub fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32, target: SymbolWi...@@ -1354,22 +1381,20 @@ pub fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32, target: SymbolWi
1354 .pcrel = false,1381 .pcrel = false,
1355 .length = 3,1382 .length = 3,
1356 });1383 });
1357 try atom.addRebase(self, 0);1384 try Atom.addRebase(self, atom_index, 0);
1358 try atom.addLazyBinding(self, .{1385 try Atom.addLazyBinding(self, atom_index, .{
1359 .target = self.getGlobal(self.getSymbolName(target)).?,1386 .target = self.getGlobal(self.getSymbolName(target)).?,
1360 .offset = 0,1387 .offset = 0,
1361 });1388 });
13621389
1363 try self.managed_atoms.append(gpa, atom);1390 sym.n_value = try self.allocateAtom(atom_index, atom.size, @alignOf(u64));
1364
1365 sym.n_value = try self.allocateAtom(atom, atom.size, @alignOf(u64));
1366 log.debug("allocated lazy pointer atom at 0x{x} ({s})", .{ sym.n_value, self.getSymbolName(target) });1391 log.debug("allocated lazy pointer atom at 0x{x} ({s})", .{ sym.n_value, self.getSymbolName(target) });
1367 try self.writePtrWidthAtom(atom);1392 try self.writePtrWidthAtom(atom_index);
13681393
1369 return atom;1394 return atom_index;
1370}1395}
13711396
1372pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom {1397pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !Atom.Index {
1373 const gpa = self.base.allocator;1398 const gpa = self.base.allocator;
1374 const arch = self.base.options.target.cpu.arch;1399 const arch = self.base.options.target.cpu.arch;
1375 const size: u4 = switch (arch) {1400 const size: u4 = switch (arch) {
...@@ -1377,9 +1402,8 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom {...@@ -1377,9 +1402,8 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom {
1377 .aarch64 => 3 * @sizeOf(u32),1402 .aarch64 => 3 * @sizeOf(u32),
1378 else => unreachable, // unhandled architecture type1403 else => unreachable, // unhandled architecture type
1379 };1404 };
1380 const atom = try gpa.create(Atom);1405 const atom_index = try self.createAtom();
1381 atom.* = Atom.empty;1406 const atom = self.getAtomPtr(atom_index);
1382 try atom.ensureInitialized(self);
1383 atom.size = size;1407 atom.size = size;
1384 atom.alignment = switch (arch) {1408 atom.alignment = switch (arch) {
1385 .x86_64 => 1,1409 .x86_64 => 1,
...@@ -1387,7 +1411,6 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom {...@@ -1387,7 +1411,6 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom {
1387 else => unreachable, // unhandled architecture type1411 else => unreachable, // unhandled architecture type
13881412
1389 };1413 };
1390 errdefer gpa.destroy(atom);
13911414
1392 const sym = atom.getSymbolPtr(self);1415 const sym = atom.getSymbolPtr(self);
1393 sym.n_type = macho.N_SECT;1416 sym.n_type = macho.N_SECT;
...@@ -1403,7 +1426,7 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom {...@@ -1403,7 +1426,7 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom {
1403 code[0] = 0xff;1426 code[0] = 0xff;
1404 code[1] = 0x25;1427 code[1] = 0x25;
14051428
1406 try atom.addRelocation(self, .{1429 try Atom.addRelocation(self, atom_index, .{
1407 .type = @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_BRANCH),1430 .type = @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_BRANCH),
1408 .target = .{ .sym_index = laptr_sym_index, .file = null },1431 .target = .{ .sym_index = laptr_sym_index, .file = null },
1409 .offset = 2,1432 .offset = 2,
...@@ -1424,7 +1447,7 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom {...@@ -1424,7 +1447,7 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom {
1424 // br x161447 // br x16
1425 mem.writeIntLittle(u32, code[8..12], aarch64.Instruction.br(.x16).toU32());1448 mem.writeIntLittle(u32, code[8..12], aarch64.Instruction.br(.x16).toU32());
14261449
1427 try atom.addRelocations(self, 2, .{1450 try Atom.addRelocations(self, atom_index, 2, .{
1428 .{1451 .{
1429 .type = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_PAGE21),1452 .type = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_PAGE21),
1430 .target = .{ .sym_index = laptr_sym_index, .file = null },1453 .target = .{ .sym_index = laptr_sym_index, .file = null },
...@@ -1446,13 +1469,11 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom {...@@ -1446,13 +1469,11 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom {
1446 else => unreachable,1469 else => unreachable,
1447 }1470 }
14481471
1449 try self.managed_atoms.append(gpa, atom);1472 sym.n_value = try self.allocateAtom(atom_index, size, atom.alignment);
1450
1451 sym.n_value = try self.allocateAtom(atom, size, atom.alignment);
1452 log.debug("allocated stub atom at 0x{x}", .{sym.n_value});1473 log.debug("allocated stub atom at 0x{x}", .{sym.n_value});
1453 try self.writeAtom(atom, code);1474 try self.writeAtom(atom_index, code);
14541475
1455 return atom;1476 return atom_index;
1456}1477}
14571478
1458pub fn createMhExecuteHeaderSymbol(self: *MachO) !void {1479pub fn createMhExecuteHeaderSymbol(self: *MachO) !void {
...@@ -1586,9 +1607,12 @@ pub fn resolveSymbolsInDylibs(self: *MachO) !void {...@@ -1586,9 +1607,12 @@ pub fn resolveSymbolsInDylibs(self: *MachO) !void {
1586 if (self.stubs_table.contains(global)) break :blk;1607 if (self.stubs_table.contains(global)) break :blk;
15871608
1588 const stub_index = try self.allocateStubEntry(global);1609 const stub_index = try self.allocateStubEntry(global);
1589 const stub_helper_atom = try self.createStubHelperAtom();1610 const stub_helper_atom_index = try self.createStubHelperAtom();
1590 const laptr_atom = try self.createLazyPointerAtom(stub_helper_atom.getSymbolIndex().?, global);1611 const stub_helper_atom = self.getAtom(stub_helper_atom_index);
1591 const stub_atom = try self.createStubAtom(laptr_atom.getSymbolIndex().?);1612 const laptr_atom_index = try self.createLazyPointerAtom(stub_helper_atom.getSymbolIndex().?, global);
1613 const laptr_atom = self.getAtom(laptr_atom_index);
1614 const stub_atom_index = try self.createStubAtom(laptr_atom.getSymbolIndex().?);
1615 const stub_atom = self.getAtom(stub_atom_index);
1592 self.stubs.items[stub_index].sym_index = stub_atom.getSymbolIndex().?;1616 self.stubs.items[stub_index].sym_index = stub_atom.getSymbolIndex().?;
1593 self.markRelocsDirtyByTarget(global);1617 self.markRelocsDirtyByTarget(global);
1594 }1618 }
...@@ -1686,10 +1710,11 @@ pub fn resolveDyldStubBinder(self: *MachO) !void {...@@ -1686,10 +1710,11 @@ pub fn resolveDyldStubBinder(self: *MachO) !void {
16861710
1687 // Add dyld_stub_binder as the final GOT entry.1711 // Add dyld_stub_binder as the final GOT entry.
1688 const got_index = try self.allocateGotEntry(global);1712 const got_index = try self.allocateGotEntry(global);
1689 const got_atom = try self.createGotAtom(global);1713 const got_atom_index = try self.createGotAtom(global);
1714 const got_atom = self.getAtom(got_atom_index);
1690 self.got_entries.items[got_index].sym_index = got_atom.getSymbolIndex().?;1715 self.got_entries.items[got_index].sym_index = got_atom.getSymbolIndex().?;
16911716
1692 try self.writePtrWidthAtom(got_atom);1717 try self.writePtrWidthAtom(got_atom_index);
1693}1718}
16941719
1695pub fn deinit(self: *MachO) void {1720pub fn deinit(self: *MachO) void {
...@@ -1699,9 +1724,9 @@ pub fn deinit(self: *MachO) void {...@@ -1699,9 +1724,9 @@ pub fn deinit(self: *MachO) void {
1699 if (self.llvm_object) |llvm_object| llvm_object.destroy(gpa);1724 if (self.llvm_object) |llvm_object| llvm_object.destroy(gpa);
1700 }1725 }
17011726
1702 if (self.d_sym) |*d_sym| {1727 // if (self.d_sym) |*d_sym| {
1703 d_sym.deinit();1728 // d_sym.deinit();
1704 }1729 // }
17051730
1706 self.got_entries.deinit(gpa);1731 self.got_entries.deinit(gpa);
1707 self.got_entries_free_list.deinit(gpa);1732 self.got_entries_free_list.deinit(gpa);
...@@ -1739,12 +1764,12 @@ pub fn deinit(self: *MachO) void {...@@ -1739,12 +1764,12 @@ pub fn deinit(self: *MachO) void {
1739 }1764 }
1740 self.sections.deinit(gpa);1765 self.sections.deinit(gpa);
17411766
1742 for (self.managed_atoms.items) |atom| {1767 self.atoms.deinit(gpa);
1743 gpa.destroy(atom);
1744 }
1745 self.managed_atoms.deinit(gpa);
17461768
1747 if (self.base.options.module) |_| {1769 if (self.base.options.module) |_| {
1770 for (self.decls.values()) |*m| {
1771 m.exports.deinit(gpa);
1772 }
1748 self.decls.deinit(gpa);1773 self.decls.deinit(gpa);
1749 } else {1774 } else {
1750 assert(self.decls.count() == 0);1775 assert(self.decls.count() == 0);
...@@ -1778,14 +1803,15 @@ pub fn deinit(self: *MachO) void {...@@ -1778,14 +1803,15 @@ pub fn deinit(self: *MachO) void {
1778 self.lazy_bindings.deinit(gpa);1803 self.lazy_bindings.deinit(gpa);
1779}1804}
17801805
1781fn freeAtom(self: *MachO, atom: *Atom) void {1806fn freeAtom(self: *MachO, atom_index: Atom.Index) void {
1782 log.debug("freeAtom {*}", .{atom});1807 log.debug("freeAtom {d}", .{atom_index});
17831808
1784 const gpa = self.base.allocator;1809 const gpa = self.base.allocator;
17851810
1786 // Remove any relocs and base relocs associated with this Atom1811 // Remove any relocs and base relocs associated with this Atom
1787 self.freeRelocationsForAtom(atom);1812 Atom.freeRelocations(self, atom_index);
17881813
1814 const atom = self.getAtom(atom_index);
1789 const sect_id = atom.getSymbol(self).n_sect - 1;1815 const sect_id = atom.getSymbol(self).n_sect - 1;
1790 const free_list = &self.sections.items(.free_list)[sect_id];1816 const free_list = &self.sections.items(.free_list)[sect_id];
1791 var already_have_free_list_node = false;1817 var already_have_free_list_node = false;
...@@ -1793,45 +1819,46 @@ fn freeAtom(self: *MachO, atom: *Atom) void {...@@ -1793,45 +1819,46 @@ fn freeAtom(self: *MachO, atom: *Atom) void {
1793 var i: usize = 0;1819 var i: usize = 0;
1794 // TODO turn free_list into a hash map1820 // TODO turn free_list into a hash map
1795 while (i < free_list.items.len) {1821 while (i < free_list.items.len) {
1796 if (free_list.items[i] == atom) {1822 if (free_list.items[i] == atom_index) {
1797 _ = free_list.swapRemove(i);1823 _ = free_list.swapRemove(i);
1798 continue;1824 continue;
1799 }1825 }
1800 if (free_list.items[i] == atom.prev) {1826 if (free_list.items[i] == atom.prev_index) {
1801 already_have_free_list_node = true;1827 already_have_free_list_node = true;
1802 }1828 }
1803 i += 1;1829 i += 1;
1804 }1830 }
1805 }1831 }
18061832
1807 const maybe_last_atom = &self.sections.items(.last_atom)[sect_id];1833 const maybe_last_atom_index = &self.sections.items(.last_atom_index)[sect_id];
1808 if (maybe_last_atom.*) |last_atom| {1834 if (maybe_last_atom_index.*) |last_atom_index| {
1809 if (last_atom == atom) {1835 if (last_atom_index == atom_index) {
1810 if (atom.prev) |prev| {1836 if (atom.prev_index) |prev_index| {
1811 // TODO shrink the section size here1837 // TODO shrink the section size here
1812 maybe_last_atom.* = prev;1838 maybe_last_atom_index.* = prev_index;
1813 } else {1839 } else {
1814 maybe_last_atom.* = null;1840 maybe_last_atom_index.* = null;
1815 }1841 }
1816 }1842 }
1817 }1843 }
18181844
1819 if (atom.prev) |prev| {1845 if (atom.prev_index) |prev_index| {
1820 prev.next = atom.next;1846 const prev = self.getAtomPtr(prev_index);
1847 prev.next_index = atom.next_index;
18211848
1822 if (!already_have_free_list_node and prev.freeListEligible(self)) {1849 if (!already_have_free_list_node and prev.*.freeListEligible(self)) {
1823 // The free list is heuristics, it doesn't have to be perfect, so we can ignore1850 // The free list is heuristics, it doesn't have to be perfect, so we can ignore
1824 // the OOM here.1851 // the OOM here.
1825 free_list.append(gpa, prev) catch {};1852 free_list.append(gpa, prev_index) catch {};
1826 }1853 }
1827 } else {1854 } else {
1828 atom.prev = null;1855 self.getAtomPtr(atom_index).prev_index = null;
1829 }1856 }
18301857
1831 if (atom.next) |next| {1858 if (atom.next_index) |next_index| {
1832 next.prev = atom.prev;1859 self.getAtomPtr(next_index).prev_index = atom.prev_index;
1833 } else {1860 } else {
1834 atom.next = null;1861 self.getAtomPtr(atom_index).next_index = null;
1835 }1862 }
18361863
1837 // Appending to free lists is allowed to fail because the free lists are heuristics based anyway.1864 // Appending to free lists is allowed to fail because the free lists are heuristics based anyway.
...@@ -1849,9 +1876,9 @@ fn freeAtom(self: *MachO, atom: *Atom) void {...@@ -1849,9 +1876,9 @@ fn freeAtom(self: *MachO, atom: *Atom) void {
1849 };1876 };
1850 _ = self.got_entries_table.remove(got_target);1877 _ = self.got_entries_table.remove(got_target);
18511878
1852 if (self.d_sym) |*d_sym| {1879 // if (self.d_sym) |*d_sym| {
1853 d_sym.swapRemoveRelocs(sym_index);1880 // d_sym.swapRemoveRelocs(sym_index);
1854 }1881 // }
18551882
1856 log.debug(" adding GOT index {d} to free list (target local@{d})", .{ got_index, sym_index });1883 log.debug(" adding GOT index {d} to free list (target local@{d})", .{ got_index, sym_index });
1857 }1884 }
...@@ -1859,27 +1886,28 @@ fn freeAtom(self: *MachO, atom: *Atom) void {...@@ -1859,27 +1886,28 @@ fn freeAtom(self: *MachO, atom: *Atom) void {
1859 self.locals.items[sym_index].n_type = 0;1886 self.locals.items[sym_index].n_type = 0;
1860 _ = self.atom_by_index_table.remove(sym_index);1887 _ = self.atom_by_index_table.remove(sym_index);
1861 log.debug(" adding local symbol index {d} to free list", .{sym_index});1888 log.debug(" adding local symbol index {d} to free list", .{sym_index});
1862 atom.sym_index = 0;1889 self.getAtomPtr(atom_index).sym_index = 0;
18631890
1864 if (self.d_sym) |*d_sym| {1891 // if (self.d_sym) |*d_sym| {
1865 d_sym.dwarf.freeAtom(&atom.dbg_info_atom);1892 // d_sym.dwarf.freeAtom(&atom.dbg_info_atom);
1866 }1893 // }
1867}1894}
18681895
1869fn shrinkAtom(self: *MachO, atom: *Atom, new_block_size: u64) void {1896fn shrinkAtom(self: *MachO, atom_index: Atom.Index, new_block_size: u64) void {
1870 _ = self;1897 _ = self;
1871 _ = atom;1898 _ = atom_index;
1872 _ = new_block_size;1899 _ = new_block_size;
1873 // TODO check the new capacity, and if it crosses the size threshold into a big enough1900 // TODO check the new capacity, and if it crosses the size threshold into a big enough
1874 // capacity, insert a free list node for it.1901 // capacity, insert a free list node for it.
1875}1902}
18761903
1877fn growAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64) !u64 {1904fn growAtom(self: *MachO, atom_index: Atom.Index, new_atom_size: u64, alignment: u64) !u64 {
1905 const atom = self.getAtom(atom_index);
1878 const sym = atom.getSymbol(self);1906 const sym = atom.getSymbol(self);
1879 const align_ok = mem.alignBackwardGeneric(u64, sym.n_value, alignment) == sym.n_value;1907 const align_ok = mem.alignBackwardGeneric(u64, sym.n_value, alignment) == sym.n_value;
1880 const need_realloc = !align_ok or new_atom_size > atom.capacity(self);1908 const need_realloc = !align_ok or new_atom_size > atom.capacity(self);
1881 if (!need_realloc) return sym.n_value;1909 if (!need_realloc) return sym.n_value;
1882 return self.allocateAtom(atom, new_atom_size, alignment);1910 return self.allocateAtom(atom_index, new_atom_size, alignment);
1883}1911}
18841912
1885pub fn allocateSymbol(self: *MachO) !u32 {1913pub fn allocateSymbol(self: *MachO) !u32 {
...@@ -1986,31 +2014,29 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv...@@ -1986,31 +2014,29 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv
19862014
1987 const decl_index = func.owner_decl;2015 const decl_index = func.owner_decl;
1988 const decl = module.declPtr(decl_index);2016 const decl = module.declPtr(decl_index);
1989 const atom = &decl.link.macho;2017
1990 try atom.ensureInitialized(self);2018 const atom_index = try self.getOrCreateAtomForDecl(decl_index);
1991 const gop = try self.decls.getOrPut(self.base.allocator, decl_index);2019 self.freeUnnamedConsts(decl_index);
1992 if (gop.found_existing) {2020 Atom.freeRelocations(self, atom_index);
1993 self.freeUnnamedConsts(decl_index);2021
1994 self.freeRelocationsForAtom(atom);2022 const atom = self.getAtom(atom_index);
1995 } else {2023 _ = atom;
1996 gop.value_ptr.* = null;
1997 }
19982024
1999 var code_buffer = std.ArrayList(u8).init(self.base.allocator);2025 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
2000 defer code_buffer.deinit();2026 defer code_buffer.deinit();
20012027
2002 var decl_state = if (self.d_sym) |*d_sym|2028 // var decl_state = if (self.d_sym) |*d_sym|
2003 try d_sym.dwarf.initDeclState(module, decl_index)2029 // try d_sym.dwarf.initDeclState(module, decl_index)
2004 else2030 // else
2005 null;2031 // null;
2006 defer if (decl_state) |*ds| ds.deinit();2032 // defer if (decl_state) |*ds| ds.deinit();
20072033
2008 const res = if (decl_state) |*ds|2034 // const res = if (decl_state) |*ds|
2009 try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .{2035 // try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .{
2010 .dwarf = ds,2036 // .dwarf = ds,
2011 })2037 // })
2012 else2038 // else
2013 try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .none);2039 const res = try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .none);
20142040
2015 const code = switch (res) {2041 const code = switch (res) {
2016 .ok => code_buffer.items,2042 .ok => code_buffer.items,
...@@ -2022,16 +2048,11 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv...@@ -2022,16 +2048,11 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv
2022 };2048 };
20232049
2024 const addr = try self.updateDeclCode(decl_index, code);2050 const addr = try self.updateDeclCode(decl_index, code);
2051 _ = addr;
20252052
2026 if (decl_state) |*ds| {2053 // if (decl_state) |*ds| {
2027 try self.d_sym.?.dwarf.commitDeclState(2054 // try self.d_sym.?.dwarf.commitDeclState(module, decl_index, addr, atom.size, ds);
2028 module,2055 // }
2029 decl_index,
2030 addr,
2031 decl.link.macho.size,
2032 ds,
2033 );
2034 }
20352056
2036 // Since we updated the vaddr and the size, each corresponding export symbol also2057 // Since we updated the vaddr and the size, each corresponding export symbol also
2037 // needs to be updated.2058 // needs to be updated.
...@@ -2065,11 +2086,8 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu...@@ -2065,11 +2086,8 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu
20652086
2066 log.debug("allocating symbol indexes for {?s}", .{name});2087 log.debug("allocating symbol indexes for {?s}", .{name});
20672088
2068 const atom = try gpa.create(Atom);2089 const atom_index = try self.createAtom();
2069 errdefer gpa.destroy(atom);2090 const atom = self.getAtomPtr(atom_index);
2070 atom.* = Atom.empty;
2071 try atom.ensureInitialized(self);
2072 try self.managed_atoms.append(gpa, atom);
20732091
2074 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .none, .{2092 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .none, .{
2075 .parent_atom_index = atom.getSymbolIndex().?,2093 .parent_atom_index = atom.getSymbolIndex().?,
...@@ -2088,21 +2106,21 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu...@@ -2088,21 +2106,21 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu
2088 atom.size = code.len;2106 atom.size = code.len;
2089 atom.alignment = required_alignment;2107 atom.alignment = required_alignment;
2090 // TODO: work out logic for disambiguating functions from function pointers2108 // TODO: work out logic for disambiguating functions from function pointers
2091 // const sect_id = self.getDeclOutputSection(decl);2109 // const sect_id = self.getDeclOutputSection(decl_index);
2092 const sect_id = self.data_const_section_index.?;2110 const sect_id = self.data_const_section_index.?;
2093 const symbol = atom.getSymbolPtr(self);2111 const symbol = atom.getSymbolPtr(self);
2094 symbol.n_strx = name_str_index;2112 symbol.n_strx = name_str_index;
2095 symbol.n_type = macho.N_SECT;2113 symbol.n_type = macho.N_SECT;
2096 symbol.n_sect = sect_id + 1;2114 symbol.n_sect = sect_id + 1;
2097 symbol.n_value = try self.allocateAtom(atom, code.len, required_alignment);2115 symbol.n_value = try self.allocateAtom(atom_index, code.len, required_alignment);
2098 errdefer self.freeAtom(atom);2116 errdefer self.freeAtom(atom_index);
20992117
2100 try unnamed_consts.append(gpa, atom);2118 try unnamed_consts.append(gpa, atom_index);
21012119
2102 log.debug("allocated atom for {?s} at 0x{x}", .{ name, symbol.n_value });2120 log.debug("allocated atom for {?s} at 0x{x}", .{ name, symbol.n_value });
2103 log.debug(" (required alignment 0x{x})", .{required_alignment});2121 log.debug(" (required alignment 0x{x})", .{required_alignment});
21042122
2105 try self.writeAtom(atom, code);2123 try self.writeAtom(atom_index, code);
21062124
2107 return atom.getSymbolIndex().?;2125 return atom.getSymbolIndex().?;
2108}2126}
...@@ -2129,41 +2147,36 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index)...@@ -2129,41 +2147,36 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index)
2129 }2147 }
2130 }2148 }
21312149
2132 const atom = &decl.link.macho;2150 const atom_index = try self.getOrCreateAtomForDecl(decl_index);
2133 try atom.ensureInitialized(self);2151 Atom.freeRelocations(self, atom_index);
2134 const gop = try self.decls.getOrPut(self.base.allocator, decl_index);2152 const atom = self.getAtom(atom_index);
2135 if (gop.found_existing) {
2136 self.freeRelocationsForAtom(atom);
2137 } else {
2138 gop.value_ptr.* = null;
2139 }
21402153
2141 var code_buffer = std.ArrayList(u8).init(self.base.allocator);2154 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
2142 defer code_buffer.deinit();2155 defer code_buffer.deinit();
21432156
2144 var decl_state: ?Dwarf.DeclState = if (self.d_sym) |*d_sym|2157 // var decl_state: ?Dwarf.DeclState = if (self.d_sym) |*d_sym|
2145 try d_sym.dwarf.initDeclState(module, decl_index)2158 // try d_sym.dwarf.initDeclState(module, decl_index)
2146 else2159 // else
2147 null;2160 // null;
2148 defer if (decl_state) |*ds| ds.deinit();2161 // defer if (decl_state) |*ds| ds.deinit();
21492162
2150 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;2163 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
2151 const res = if (decl_state) |*ds|2164 // const res = if (decl_state) |*ds|
2152 try codegen.generateSymbol(&self.base, decl.srcLoc(), .{2165 // try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
2153 .ty = decl.ty,2166 // .ty = decl.ty,
2154 .val = decl_val,2167 // .val = decl_val,
2155 }, &code_buffer, .{2168 // }, &code_buffer, .{
2156 .dwarf = ds,2169 // .dwarf = ds,
2157 }, .{2170 // }, .{
2158 .parent_atom_index = decl.link.macho.getSymbolIndex().?,2171 // .parent_atom_index = atom.getSymbolIndex().?,
2159 })2172 // })
2160 else2173 // else
2161 try codegen.generateSymbol(&self.base, decl.srcLoc(), .{2174 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
2162 .ty = decl.ty,2175 .ty = decl.ty,
2163 .val = decl_val,2176 .val = decl_val,
2164 }, &code_buffer, .none, .{2177 }, &code_buffer, .none, .{
2165 .parent_atom_index = decl.link.macho.getSymbolIndex().?,2178 .parent_atom_index = atom.getSymbolIndex().?,
2166 });2179 });
21672180
2168 const code = switch (res) {2181 const code = switch (res) {
2169 .ok => code_buffer.items,2182 .ok => code_buffer.items,
...@@ -2174,23 +2187,31 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index)...@@ -2174,23 +2187,31 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index)
2174 },2187 },
2175 };2188 };
2176 const addr = try self.updateDeclCode(decl_index, code);2189 const addr = try self.updateDeclCode(decl_index, code);
2190 _ = addr;
21772191
2178 if (decl_state) |*ds| {2192 // if (decl_state) |*ds| {
2179 try self.d_sym.?.dwarf.commitDeclState(2193 // try self.d_sym.?.dwarf.commitDeclState(module, decl_index, addr, atom.size, ds);
2180 module,2194 // }
2181 decl_index,
2182 addr,
2183 decl.link.macho.size,
2184 ds,
2185 );
2186 }
21872195
2188 // Since we updated the vaddr and the size, each corresponding export symbol also2196 // Since we updated the vaddr and the size, each corresponding export symbol also
2189 // needs to be updated.2197 // needs to be updated.
2190 try self.updateDeclExports(module, decl_index, module.getDeclExports(decl_index));2198 try self.updateDeclExports(module, decl_index, module.getDeclExports(decl_index));
2191}2199}
21922200
2193fn getDeclOutputSection(self: *MachO, decl: *Module.Decl) u8 {2201pub fn getOrCreateAtomForDecl(self: *MachO, decl_index: Module.Decl.Index) !Atom.Index {
2202 const gop = try self.decls.getOrPut(self.base.allocator, decl_index);
2203 if (!gop.found_existing) {
2204 gop.value_ptr.* = .{
2205 .atom = try self.createAtom(),
2206 .section = self.getDeclOutputSection(decl_index),
2207 .exports = .{},
2208 };
2209 }
2210 return gop.value_ptr.atom;
2211}
2212
2213fn getDeclOutputSection(self: *MachO, decl_index: Module.Decl.Index) u8 {
2214 const decl = self.base.options.module.?.declPtr(decl_index);
2194 const ty = decl.ty;2215 const ty = decl.ty;
2195 const val = decl.val;2216 const val = decl.val;
2196 const zig_ty = ty.zigTypeTag();2217 const zig_ty = ty.zigTypeTag();
...@@ -2341,13 +2362,11 @@ fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []const u8)...@@ -2341,13 +2362,11 @@ fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []const u8)
2341 const sym_name = try decl.getFullyQualifiedName(mod);2362 const sym_name = try decl.getFullyQualifiedName(mod);
2342 defer self.base.allocator.free(sym_name);2363 defer self.base.allocator.free(sym_name);
23432364
2344 const atom = &decl.link.macho;2365 const decl_metadata = self.decls.get(decl_index).?;
2345 const sym_index = atom.getSymbolIndex().?; // Atom was not initialized2366 const atom_index = decl_metadata.atom;
2346 const decl_ptr = self.decls.getPtr(decl_index).?;2367 const atom = self.getAtom(atom_index);
2347 if (decl_ptr.* == null) {2368 const sym_index = atom.getSymbolIndex().?;
2348 decl_ptr.* = self.getDeclOutputSection(decl);2369 const sect_id = decl_metadata.section;
2349 }
2350 const sect_id = decl_ptr.*.?;
2351 const code_len = code.len;2370 const code_len = code.len;
23522371
2353 if (atom.size != 0) {2372 if (atom.size != 0) {
...@@ -2357,11 +2376,11 @@ fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []const u8)...@@ -2357,11 +2376,11 @@ fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []const u8)
2357 sym.n_sect = sect_id + 1;2376 sym.n_sect = sect_id + 1;
2358 sym.n_desc = 0;2377 sym.n_desc = 0;
23592378
2360 const capacity = decl.link.macho.capacity(self);2379 const capacity = atom.capacity(self);
2361 const need_realloc = code_len > capacity or !mem.isAlignedGeneric(u64, sym.n_value, required_alignment);2380 const need_realloc = code_len > capacity or !mem.isAlignedGeneric(u64, sym.n_value, required_alignment);
23622381
2363 if (need_realloc) {2382 if (need_realloc) {
2364 const vaddr = try self.growAtom(atom, code_len, required_alignment);2383 const vaddr = try self.growAtom(atom_index, code_len, required_alignment);
2365 log.debug("growing {s} and moving from 0x{x} to 0x{x}", .{ sym_name, sym.n_value, vaddr });2384 log.debug("growing {s} and moving from 0x{x} to 0x{x}", .{ sym_name, sym.n_value, vaddr });
2366 log.debug(" (required alignment 0x{x})", .{required_alignment});2385 log.debug(" (required alignment 0x{x})", .{required_alignment});
23672386
...@@ -2369,19 +2388,19 @@ fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []const u8)...@@ -2369,19 +2388,19 @@ fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []const u8)
2369 sym.n_value = vaddr;2388 sym.n_value = vaddr;
2370 log.debug(" (updating GOT entry)", .{});2389 log.debug(" (updating GOT entry)", .{});
2371 const got_target = SymbolWithLoc{ .sym_index = sym_index, .file = null };2390 const got_target = SymbolWithLoc{ .sym_index = sym_index, .file = null };
2372 const got_atom = self.getGotAtomForSymbol(got_target).?;2391 const got_atom_index = self.getGotAtomIndexForSymbol(got_target).?;
2373 self.markRelocsDirtyByTarget(got_target);2392 self.markRelocsDirtyByTarget(got_target);
2374 try self.writePtrWidthAtom(got_atom);2393 try self.writePtrWidthAtom(got_atom_index);
2375 }2394 }
2376 } else if (code_len < atom.size) {2395 } else if (code_len < atom.size) {
2377 self.shrinkAtom(atom, code_len);2396 self.shrinkAtom(atom_index, code_len);
2378 } else if (atom.next == null) {2397 } else if (atom.next_index == null) {
2379 const header = &self.sections.items(.header)[sect_id];2398 const header = &self.sections.items(.header)[sect_id];
2380 const segment = self.getSegment(sect_id);2399 const segment = self.getSegment(sect_id);
2381 const needed_size = (sym.n_value + code_len) - segment.vmaddr;2400 const needed_size = (sym.n_value + code_len) - segment.vmaddr;
2382 header.size = needed_size;2401 header.size = needed_size;
2383 }2402 }
2384 atom.size = code_len;2403 self.getAtomPtr(atom_index).size = code_len;
2385 } else {2404 } else {
2386 const name_str_index = try self.strtab.insert(gpa, sym_name);2405 const name_str_index = try self.strtab.insert(gpa, sym_name);
2387 const sym = atom.getSymbolPtr(self);2406 const sym = atom.getSymbolPtr(self);
...@@ -2390,33 +2409,36 @@ fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []const u8)...@@ -2390,33 +2409,36 @@ fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []const u8)
2390 sym.n_sect = sect_id + 1;2409 sym.n_sect = sect_id + 1;
2391 sym.n_desc = 0;2410 sym.n_desc = 0;
23922411
2393 const vaddr = try self.allocateAtom(atom, code_len, required_alignment);2412 const vaddr = try self.allocateAtom(atom_index, code_len, required_alignment);
2394 errdefer self.freeAtom(atom);2413 errdefer self.freeAtom(atom_index);
23952414
2396 log.debug("allocated atom for {s} at 0x{x}", .{ sym_name, vaddr });2415 log.debug("allocated atom for {s} at 0x{x}", .{ sym_name, vaddr });
2397 log.debug(" (required alignment 0x{x})", .{required_alignment});2416 log.debug(" (required alignment 0x{x})", .{required_alignment});
23982417
2399 atom.size = code_len;2418 self.getAtomPtr(atom_index).size = code_len;
2400 sym.n_value = vaddr;2419 sym.n_value = vaddr;
24012420
2402 const got_target = SymbolWithLoc{ .sym_index = sym_index, .file = null };2421 const got_target = SymbolWithLoc{ .sym_index = sym_index, .file = null };
2403 const got_index = try self.allocateGotEntry(got_target);2422 const got_index = try self.allocateGotEntry(got_target);
2404 const got_atom = try self.createGotAtom(got_target);2423 const got_atom_index = try self.createGotAtom(got_target);
2424 const got_atom = self.getAtom(got_atom_index);
2405 self.got_entries.items[got_index].sym_index = got_atom.getSymbolIndex().?;2425 self.got_entries.items[got_index].sym_index = got_atom.getSymbolIndex().?;
2406 try self.writePtrWidthAtom(got_atom);2426 try self.writePtrWidthAtom(got_atom_index);
2407 }2427 }
24082428
2409 self.markRelocsDirtyByTarget(atom.getSymbolWithLoc());2429 self.markRelocsDirtyByTarget(atom.getSymbolWithLoc());
2410 try self.writeAtom(atom, code);2430 try self.writeAtom(atom_index, code);
24112431
2412 return atom.getSymbol(self).n_value;2432 return atom.getSymbol(self).n_value;
2413}2433}
24142434
2415pub fn updateDeclLineNumber(self: *MachO, module: *Module, decl: *const Module.Decl) !void {2435pub fn updateDeclLineNumber(self: *MachO, module: *Module, decl: *const Module.Decl) !void {
2436 _ = decl;
2437 _ = self;
2416 _ = module;2438 _ = module;
2417 if (self.d_sym) |*d_sym| {2439 // if (self.d_sym) |*d_sym| {
2418 try d_sym.dwarf.updateDeclLineNumber(decl);2440 // try d_sym.dwarf.updateDeclLineNumber(decl);
2419 }2441 // }
2420}2442}
24212443
2422pub fn updateDeclExports(2444pub fn updateDeclExports(
...@@ -2432,22 +2454,17 @@ pub fn updateDeclExports(...@@ -2432,22 +2454,17 @@ pub fn updateDeclExports(
2432 if (self.llvm_object) |llvm_object|2454 if (self.llvm_object) |llvm_object|
2433 return llvm_object.updateDeclExports(module, decl_index, exports);2455 return llvm_object.updateDeclExports(module, decl_index, exports);
2434 }2456 }
2457
2435 const tracy = trace(@src());2458 const tracy = trace(@src());
2436 defer tracy.end();2459 defer tracy.end();
24372460
2438 const gpa = self.base.allocator;2461 const gpa = self.base.allocator;
24392462
2440 const decl = module.declPtr(decl_index);2463 const decl = module.declPtr(decl_index);
2441 const atom = &decl.link.macho;2464 const atom_index = try self.getOrCreateAtomForDecl(decl_index);
24422465 const atom = self.getAtom(atom_index);
2443 if (atom.getSymbolIndex() == null) return;
2444
2445 const gop = try self.decls.getOrPut(gpa, decl_index);
2446 if (!gop.found_existing) {
2447 gop.value_ptr.* = self.getDeclOutputSection(decl);
2448 }
2449
2450 const decl_sym = atom.getSymbol(self);2466 const decl_sym = atom.getSymbol(self);
2467 const decl_metadata = self.decls.getPtr(decl_index).?;
24512468
2452 for (exports) |exp| {2469 for (exports) |exp| {
2453 const exp_name = try std.fmt.allocPrint(gpa, "_{s}", .{exp.options.name});2470 const exp_name = try std.fmt.allocPrint(gpa, "_{s}", .{exp.options.name});
...@@ -2485,9 +2502,9 @@ pub fn updateDeclExports(...@@ -2485,9 +2502,9 @@ pub fn updateDeclExports(
2485 continue;2502 continue;
2486 }2503 }
24872504
2488 const sym_index = exp.link.macho.sym_index orelse blk: {2505 const sym_index = decl_metadata.getExport(self, exp_name) orelse blk: {
2489 const sym_index = try self.allocateSymbol();2506 const sym_index = try self.allocateSymbol();
2490 exp.link.macho.sym_index = sym_index;2507 try decl_metadata.exports.append(gpa, sym_index);
2491 break :blk sym_index;2508 break :blk sym_index;
2492 };2509 };
2493 const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null };2510 const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null };
...@@ -2535,16 +2552,18 @@ pub fn updateDeclExports(...@@ -2535,16 +2552,18 @@ pub fn updateDeclExports(
2535 }2552 }
2536}2553}
25372554
2538pub fn deleteExport(self: *MachO, exp: Export) void {2555pub fn deleteDeclExport(self: *MachO, decl_index: Module.Decl.Index, name: []const u8) Allocator.Error!void {
2539 if (self.llvm_object) |_| return;2556 if (self.llvm_object) |_| return;
2540 const sym_index = exp.sym_index orelse return;2557 const metadata = self.decls.getPtr(decl_index) orelse return;
25412558
2542 const gpa = self.base.allocator;2559 const gpa = self.base.allocator;
2560 const exp_name = try std.fmt.allocPrint(gpa, "_{s}", .{name});
2561 defer gpa.free(exp_name);
2562 const sym_index = metadata.getExportPtr(self, exp_name) orelse return;
25432563
2544 const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null };2564 const sym_loc = SymbolWithLoc{ .sym_index = sym_index.*, .file = null };
2545 const sym = self.getSymbolPtr(sym_loc);2565 const sym = self.getSymbolPtr(sym_loc);
2546 const sym_name = self.getSymbolName(sym_loc);2566 log.debug("deleting export '{s}'", .{exp_name});
2547 log.debug("deleting export '{s}'", .{sym_name});
2548 assert(sym.sect() and sym.ext());2567 assert(sym.sect() and sym.ext());
2549 sym.* = .{2568 sym.* = .{
2550 .n_strx = 0,2569 .n_strx = 0,
...@@ -2553,9 +2572,9 @@ pub fn deleteExport(self: *MachO, exp: Export) void {...@@ -2553,9 +2572,9 @@ pub fn deleteExport(self: *MachO, exp: Export) void {
2553 .n_desc = 0,2572 .n_desc = 0,
2554 .n_value = 0,2573 .n_value = 0,
2555 };2574 };
2556 self.locals_free_list.append(gpa, sym_index) catch {};2575 self.locals_free_list.append(gpa, sym_index.*) catch {};
25572576
2558 if (self.resolver.fetchRemove(sym_name)) |entry| {2577 if (self.resolver.fetchRemove(exp_name)) |entry| {
2559 defer gpa.free(entry.key);2578 defer gpa.free(entry.key);
2560 self.globals_free_list.append(gpa, entry.value) catch {};2579 self.globals_free_list.append(gpa, entry.value) catch {};
2561 self.globals.items[entry.value] = .{2580 self.globals.items[entry.value] = .{
...@@ -2563,17 +2582,8 @@ pub fn deleteExport(self: *MachO, exp: Export) void {...@@ -2563,17 +2582,8 @@ pub fn deleteExport(self: *MachO, exp: Export) void {
2563 .file = null,2582 .file = null,
2564 };2583 };
2565 }2584 }
2566}
25672585
2568fn freeRelocationsForAtom(self: *MachO, atom: *Atom) void {2586 sym_index.* = 0;
2569 var removed_relocs = self.relocs.fetchOrderedRemove(atom);
2570 if (removed_relocs) |*relocs| relocs.value.deinit(self.base.allocator);
2571 var removed_rebases = self.rebases.fetchOrderedRemove(atom);
2572 if (removed_rebases) |*rebases| rebases.value.deinit(self.base.allocator);
2573 var removed_bindings = self.bindings.fetchOrderedRemove(atom);
2574 if (removed_bindings) |*bindings| bindings.value.deinit(self.base.allocator);
2575 var removed_lazy_bindings = self.lazy_bindings.fetchOrderedRemove(atom);
2576 if (removed_lazy_bindings) |*lazy_bindings| lazy_bindings.value.deinit(self.base.allocator);
2577}2587}
25782588
2579fn freeUnnamedConsts(self: *MachO, decl_index: Module.Decl.Index) void {2589fn freeUnnamedConsts(self: *MachO, decl_index: Module.Decl.Index) void {
...@@ -2595,28 +2605,22 @@ pub fn freeDecl(self: *MachO, decl_index: Module.Decl.Index) void {...@@ -2595,28 +2605,22 @@ pub fn freeDecl(self: *MachO, decl_index: Module.Decl.Index) void {
2595 log.debug("freeDecl {*}", .{decl});2605 log.debug("freeDecl {*}", .{decl});
25962606
2597 if (self.decls.fetchSwapRemove(decl_index)) |kv| {2607 if (self.decls.fetchSwapRemove(decl_index)) |kv| {
2598 if (kv.value) |_| {2608 self.freeAtom(kv.value.atom);
2599 self.freeAtom(&decl.link.macho);2609 self.freeUnnamedConsts(decl_index);
2600 self.freeUnnamedConsts(decl_index);
2601 }
2602 }2610 }
26032611
2604 if (self.d_sym) |*d_sym| {2612 // if (self.d_sym) |*d_sym| {
2605 d_sym.dwarf.freeDecl(decl);2613 // d_sym.dwarf.freeDecl(decl);
2606 }2614 // }
2607}2615}
26082616
2609pub fn getDeclVAddr(self: *MachO, decl_index: Module.Decl.Index, reloc_info: File.RelocInfo) !u64 {2617pub fn getDeclVAddr(self: *MachO, decl_index: Module.Decl.Index, reloc_info: File.RelocInfo) !u64 {
2610 const mod = self.base.options.module.?;
2611 const decl = mod.declPtr(decl_index);
2612
2613 assert(self.llvm_object == null);2618 assert(self.llvm_object == null);
26142619
2615 try decl.link.macho.ensureInitialized(self);2620 const this_atom_index = try self.getOrCreateAtomForDecl(decl_index);
2616 const sym_index = decl.link.macho.getSymbolIndex().?;2621 const sym_index = self.getAtom(this_atom_index).getSymbolIndex().?;
26172622 const atom_index = self.getAtomIndexForSymbol(.{ .sym_index = reloc_info.parent_atom_index, .file = null }).?;
2618 const atom = self.getAtomForSymbol(.{ .sym_index = reloc_info.parent_atom_index, .file = null }).?;2623 try Atom.addRelocation(self, atom_index, .{
2619 try atom.addRelocation(self, .{
2620 .type = switch (self.base.options.target.cpu.arch) {2624 .type = switch (self.base.options.target.cpu.arch) {
2621 .aarch64 => @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_UNSIGNED),2625 .aarch64 => @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_UNSIGNED),
2622 .x86_64 => @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_UNSIGNED),2626 .x86_64 => @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_UNSIGNED),
...@@ -2628,7 +2632,7 @@ pub fn getDeclVAddr(self: *MachO, decl_index: Module.Decl.Index, reloc_info: Fil...@@ -2628,7 +2632,7 @@ pub fn getDeclVAddr(self: *MachO, decl_index: Module.Decl.Index, reloc_info: Fil
2628 .pcrel = false,2632 .pcrel = false,
2629 .length = 3,2633 .length = 3,
2630 });2634 });
2631 try atom.addRebase(self, @intCast(u32, reloc_info.offset));2635 try Atom.addRebase(self, atom_index, @intCast(u32, reloc_info.offset));
26322636
2633 return 0;2637 return 0;
2634}2638}
...@@ -2860,34 +2864,36 @@ fn moveSectionInVirtualMemory(self: *MachO, sect_id: u8, needed_size: u64) !void...@@ -2860,34 +2864,36 @@ fn moveSectionInVirtualMemory(self: *MachO, sect_id: u8, needed_size: u64) !void
2860 // TODO: enforce order by increasing VM addresses in self.sections container.2864 // TODO: enforce order by increasing VM addresses in self.sections container.
2861 for (self.sections.items(.header)[sect_id + 1 ..]) |*next_header, next_sect_id| {2865 for (self.sections.items(.header)[sect_id + 1 ..]) |*next_header, next_sect_id| {
2862 const index = @intCast(u8, sect_id + 1 + next_sect_id);2866 const index = @intCast(u8, sect_id + 1 + next_sect_id);
2863 const maybe_last_atom = &self.sections.items(.last_atom)[index];
2864 const next_segment = self.getSegmentPtr(index);2867 const next_segment = self.getSegmentPtr(index);
2865 next_header.addr += diff;2868 next_header.addr += diff;
2866 next_segment.vmaddr += diff;2869 next_segment.vmaddr += diff;
28672870
2868 if (maybe_last_atom.*) |last_atom| {2871 const maybe_last_atom_index = &self.sections.items(.last_atom_index)[index];
2869 var atom = last_atom;2872 if (maybe_last_atom_index.*) |last_atom_index| {
2873 var atom_index = last_atom_index;
2870 while (true) {2874 while (true) {
2875 const atom = self.getAtom(atom_index);
2871 const sym = atom.getSymbolPtr(self);2876 const sym = atom.getSymbolPtr(self);
2872 sym.n_value += diff;2877 sym.n_value += diff;
28732878
2874 if (atom.prev) |prev| {2879 if (atom.prev_index) |prev_index| {
2875 atom = prev;2880 atom_index = prev_index;
2876 } else break;2881 } else break;
2877 }2882 }
2878 }2883 }
2879 }2884 }
2880}2885}
28812886
2882fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64) !u64 {2887fn allocateAtom(self: *MachO, atom_index: Atom.Index, new_atom_size: u64, alignment: u64) !u64 {
2883 const tracy = trace(@src());2888 const tracy = trace(@src());
2884 defer tracy.end();2889 defer tracy.end();
28852890
2891 const atom = self.getAtom(atom_index);
2886 const sect_id = atom.getSymbol(self).n_sect - 1;2892 const sect_id = atom.getSymbol(self).n_sect - 1;
2887 const segment = self.getSegmentPtr(sect_id);2893 const segment = self.getSegmentPtr(sect_id);
2888 const header = &self.sections.items(.header)[sect_id];2894 const header = &self.sections.items(.header)[sect_id];
2889 const free_list = &self.sections.items(.free_list)[sect_id];2895 const free_list = &self.sections.items(.free_list)[sect_id];
2890 const maybe_last_atom = &self.sections.items(.last_atom)[sect_id];2896 const maybe_last_atom_index = &self.sections.items(.last_atom_index)[sect_id];
2891 const requires_padding = blk: {2897 const requires_padding = blk: {
2892 if (!header.isCode()) break :blk false;2898 if (!header.isCode()) break :blk false;
2893 if (header.isSymbolStubs()) break :blk false;2899 if (header.isSymbolStubs()) break :blk false;
...@@ -2901,7 +2907,7 @@ fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64) !...@@ -2901,7 +2907,7 @@ fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64) !
2901 // It would be simpler to do it inside the for loop below, but that would cause a2907 // It would be simpler to do it inside the for loop below, but that would cause a
2902 // problem if an error was returned later in the function. So this action2908 // problem if an error was returned later in the function. So this action
2903 // is actually carried out at the end of the function, when errors are no longer possible.2909 // is actually carried out at the end of the function, when errors are no longer possible.
2904 var atom_placement: ?*Atom = null;2910 var atom_placement: ?Atom.Index = null;
2905 var free_list_removal: ?usize = null;2911 var free_list_removal: ?usize = null;
29062912
2907 // First we look for an appropriately sized free list node.2913 // First we look for an appropriately sized free list node.
...@@ -2909,7 +2915,8 @@ fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64) !...@@ -2909,7 +2915,8 @@ fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64) !
2909 var vaddr = blk: {2915 var vaddr = blk: {
2910 var i: usize = 0;2916 var i: usize = 0;
2911 while (i < free_list.items.len) {2917 while (i < free_list.items.len) {
2912 const big_atom = free_list.items[i];2918 const big_atom_index = free_list.items[i];
2919 const big_atom = self.getAtom(big_atom_index);
2913 // We now have a pointer to a live atom that has too much capacity.2920 // We now have a pointer to a live atom that has too much capacity.
2914 // Is it enough that we could fit this new atom?2921 // Is it enough that we could fit this new atom?
2915 const sym = big_atom.getSymbol(self);2922 const sym = big_atom.getSymbol(self);
...@@ -2937,30 +2944,35 @@ fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64) !...@@ -2937,30 +2944,35 @@ fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64) !
2937 const keep_free_list_node = remaining_capacity >= min_text_capacity;2944 const keep_free_list_node = remaining_capacity >= min_text_capacity;
29382945
2939 // Set up the metadata to be updated, after errors are no longer possible.2946 // Set up the metadata to be updated, after errors are no longer possible.
2940 atom_placement = big_atom;2947 atom_placement = big_atom_index;
2941 if (!keep_free_list_node) {2948 if (!keep_free_list_node) {
2942 free_list_removal = i;2949 free_list_removal = i;
2943 }2950 }
2944 break :blk new_start_vaddr;2951 break :blk new_start_vaddr;
2945 } else if (maybe_last_atom.*) |last| {2952 } else if (maybe_last_atom_index.*) |last_index| {
2953 const last = self.getAtom(last_index);
2946 const last_symbol = last.getSymbol(self);2954 const last_symbol = last.getSymbol(self);
2947 const ideal_capacity = if (requires_padding) padToIdeal(last.size) else last.size;2955 const ideal_capacity = if (requires_padding) padToIdeal(last.size) else last.size;
2948 const ideal_capacity_end_vaddr = last_symbol.n_value + ideal_capacity;2956 const ideal_capacity_end_vaddr = last_symbol.n_value + ideal_capacity;
2949 const new_start_vaddr = mem.alignForwardGeneric(u64, ideal_capacity_end_vaddr, alignment);2957 const new_start_vaddr = mem.alignForwardGeneric(u64, ideal_capacity_end_vaddr, alignment);
2950 atom_placement = last;2958 atom_placement = last_index;
2951 break :blk new_start_vaddr;2959 break :blk new_start_vaddr;
2952 } else {2960 } else {
2953 break :blk mem.alignForwardGeneric(u64, segment.vmaddr, alignment);2961 break :blk mem.alignForwardGeneric(u64, segment.vmaddr, alignment);
2954 }2962 }
2955 };2963 };
29562964
2957 const expand_section = atom_placement == null or atom_placement.?.next == null;2965 const expand_section = if (atom_placement) |placement_index|
2966 self.getAtom(placement_index).next_index == null
2967 else
2968 true;
2958 if (expand_section) {2969 if (expand_section) {
2959 const sect_capacity = self.allocatedSize(header.offset);2970 const sect_capacity = self.allocatedSize(header.offset);
2960 const needed_size = (vaddr + new_atom_size) - segment.vmaddr;2971 const needed_size = (vaddr + new_atom_size) - segment.vmaddr;
2961 if (needed_size > sect_capacity) {2972 if (needed_size > sect_capacity) {
2962 const new_offset = self.findFreeSpace(needed_size, self.page_size);2973 const new_offset = self.findFreeSpace(needed_size, self.page_size);
2963 const current_size = if (maybe_last_atom.*) |last_atom| blk: {2974 const current_size = if (maybe_last_atom_index.*) |last_atom_index| blk: {
2975 const last_atom = self.getAtom(last_atom_index);
2964 const sym = last_atom.getSymbol(self);2976 const sym = last_atom.getSymbol(self);
2965 break :blk (sym.n_value + last_atom.size) - segment.vmaddr;2977 break :blk (sym.n_value + last_atom.size) - segment.vmaddr;
2966 } else 0;2978 } else 0;
...@@ -2992,7 +3004,7 @@ fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64) !...@@ -2992,7 +3004,7 @@ fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64) !
2992 header.size = needed_size;3004 header.size = needed_size;
2993 segment.filesize = mem.alignForwardGeneric(u64, needed_size, self.page_size);3005 segment.filesize = mem.alignForwardGeneric(u64, needed_size, self.page_size);
2994 segment.vmsize = mem.alignForwardGeneric(u64, needed_size, self.page_size);3006 segment.vmsize = mem.alignForwardGeneric(u64, needed_size, self.page_size);
2995 maybe_last_atom.* = atom;3007 maybe_last_atom_index.* = atom_index;
29963008
2997 self.segment_table_dirty = true;3009 self.segment_table_dirty = true;
2998 }3010 }
...@@ -3002,20 +3014,25 @@ fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64) !...@@ -3002,20 +3014,25 @@ fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64) !
3002 header.@"align" = align_pow;3014 header.@"align" = align_pow;
3003 }3015 }
30043016
3005 if (atom.prev) |prev| {3017 if (atom.prev_index) |prev_index| {
3006 prev.next = atom.next;3018 const prev = self.getAtomPtr(prev_index);
3019 prev.next_index = atom.next_index;
3007 }3020 }
3008 if (atom.next) |next| {3021 if (atom.next_index) |next_index| {
3009 next.prev = atom.prev;3022 const next = self.getAtomPtr(next_index);
3023 next.prev_index = atom.prev_index;
3010 }3024 }
30113025
3012 if (atom_placement) |big_atom| {3026 if (atom_placement) |big_atom_index| {
3013 atom.prev = big_atom;3027 const big_atom = self.getAtomPtr(big_atom_index);
3014 atom.next = big_atom.next;3028 const atom_ptr = self.getAtomPtr(atom_index);
3015 big_atom.next = atom;3029 atom_ptr.prev_index = big_atom_index;
3030 atom_ptr.next_index = big_atom.next_index;
3031 big_atom.next_index = atom_index;
3016 } else {3032 } else {
3017 atom.prev = null;3033 const atom_ptr = self.getAtomPtr(atom_index);
3018 atom.next = null;3034 atom_ptr.prev_index = null;
3035 atom_ptr.next_index = null;
3019 }3036 }
3020 if (free_list_removal) |i| {3037 if (free_list_removal) |i| {
3021 _ = free_list.swapRemove(i);3038 _ = free_list.swapRemove(i);
...@@ -3155,7 +3172,8 @@ fn collectRebaseData(self: *MachO, rebase: *Rebase) !void {...@@ -3155,7 +3172,8 @@ fn collectRebaseData(self: *MachO, rebase: *Rebase) !void {
3155 const gpa = self.base.allocator;3172 const gpa = self.base.allocator;
3156 const slice = self.sections.slice();3173 const slice = self.sections.slice();
31573174
3158 for (self.rebases.keys()) |atom, i| {3175 for (self.rebases.keys()) |atom_index, i| {
3176 const atom = self.getAtom(atom_index);
3159 log.debug(" ATOM(%{?d}, '{s}')", .{ atom.getSymbolIndex(), atom.getName(self) });3177 log.debug(" ATOM(%{?d}, '{s}')", .{ atom.getSymbolIndex(), atom.getName(self) });
31603178
3161 const sym = atom.getSymbol(self);3179 const sym = atom.getSymbol(self);
...@@ -3184,7 +3202,8 @@ fn collectBindData(self: *MachO, bind: anytype, raw_bindings: anytype) !void {...@@ -3184,7 +3202,8 @@ fn collectBindData(self: *MachO, bind: anytype, raw_bindings: anytype) !void {
3184 const gpa = self.base.allocator;3202 const gpa = self.base.allocator;
3185 const slice = self.sections.slice();3203 const slice = self.sections.slice();
31863204
3187 for (raw_bindings.keys()) |atom, i| {3205 for (raw_bindings.keys()) |atom_index, i| {
3206 const atom = self.getAtom(atom_index);
3188 log.debug(" ATOM(%{?d}, '{s}')", .{ atom.getSymbolIndex(), atom.getName(self) });3207 log.debug(" ATOM(%{?d}, '{s}')", .{ atom.getSymbolIndex(), atom.getName(self) });
31893208
3190 const sym = atom.getSymbol(self);3209 const sym = atom.getSymbol(self);
...@@ -3359,7 +3378,7 @@ fn populateLazyBindOffsetsInStubHelper(self: *MachO, lazy_bind: LazyBind) !void...@@ -3359,7 +3378,7 @@ fn populateLazyBindOffsetsInStubHelper(self: *MachO, lazy_bind: LazyBind) !void
3359 if (lazy_bind.size() == 0) return;3378 if (lazy_bind.size() == 0) return;
33603379
3361 const stub_helper_section_index = self.stub_helper_section_index.?;3380 const stub_helper_section_index = self.stub_helper_section_index.?;
3362 assert(self.stub_helper_preamble_atom != null);3381 assert(self.stub_helper_preamble_atom_index != null);
33633382
3364 const section = self.sections.get(stub_helper_section_index);3383 const section = self.sections.get(stub_helper_section_index);
33653384
...@@ -3369,10 +3388,11 @@ fn populateLazyBindOffsetsInStubHelper(self: *MachO, lazy_bind: LazyBind) !void...@@ -3369,10 +3388,11 @@ fn populateLazyBindOffsetsInStubHelper(self: *MachO, lazy_bind: LazyBind) !void
3369 else => unreachable,3388 else => unreachable,
3370 };3389 };
3371 const header = section.header;3390 const header = section.header;
3372 var atom = section.last_atom.?;3391 var atom_index = section.last_atom_index.?;
33733392
3374 var index: usize = lazy_bind.offsets.items.len;3393 var index: usize = lazy_bind.offsets.items.len;
3375 while (index > 0) : (index -= 1) {3394 while (index > 0) : (index -= 1) {
3395 const atom = self.getAtom(atom_index);
3376 const sym = atom.getSymbol(self);3396 const sym = atom.getSymbol(self);
3377 const file_offset = header.offset + sym.n_value - header.addr + stub_offset;3397 const file_offset = header.offset + sym.n_value - header.addr + stub_offset;
3378 const bind_offset = lazy_bind.offsets.items[index - 1];3398 const bind_offset = lazy_bind.offsets.items[index - 1];
...@@ -3385,7 +3405,7 @@ fn populateLazyBindOffsetsInStubHelper(self: *MachO, lazy_bind: LazyBind) !void...@@ -3385,7 +3405,7 @@ fn populateLazyBindOffsetsInStubHelper(self: *MachO, lazy_bind: LazyBind) !void
33853405
3386 try self.base.file.?.pwriteAll(mem.asBytes(&bind_offset), file_offset);3406 try self.base.file.?.pwriteAll(mem.asBytes(&bind_offset), file_offset);
33873407
3388 atom = atom.prev.?;3408 atom_index = atom.prev_index.?;
3389 }3409 }
3390}3410}
33913411
...@@ -3828,25 +3848,35 @@ pub fn getOrPutGlobalPtr(self: *MachO, name: []const u8) !GetOrPutGlobalPtrResul...@@ -3828,25 +3848,35 @@ pub fn getOrPutGlobalPtr(self: *MachO, name: []const u8) !GetOrPutGlobalPtrResul
3828 return GetOrPutGlobalPtrResult{ .found_existing = false, .value_ptr = ptr };3848 return GetOrPutGlobalPtrResult{ .found_existing = false, .value_ptr = ptr };
3829}3849}
38303850
3851pub fn getAtom(self: *MachO, atom_index: Atom.Index) Atom {
3852 assert(atom_index < self.atoms.items.len);
3853 return self.atoms.items[atom_index];
3854}
3855
3856pub fn getAtomPtr(self: *MachO, atom_index: Atom.Index) *Atom {
3857 assert(atom_index < self.atoms.items.len);
3858 return &self.atoms.items[atom_index];
3859}
3860
3831/// Returns atom if there is an atom referenced by the symbol described by `sym_with_loc` descriptor.3861/// Returns atom if there is an atom referenced by the symbol described by `sym_with_loc` descriptor.
3832/// Returns null on failure.3862/// Returns null on failure.
3833pub fn getAtomForSymbol(self: *MachO, sym_with_loc: SymbolWithLoc) ?*Atom {3863pub fn getAtomIndexForSymbol(self: *MachO, sym_with_loc: SymbolWithLoc) ?Atom.Index {
3834 assert(sym_with_loc.file == null);3864 assert(sym_with_loc.file == null);
3835 return self.atom_by_index_table.get(sym_with_loc.sym_index);3865 return self.atom_by_index_table.get(sym_with_loc.sym_index);
3836}3866}
38373867
3838/// Returns GOT atom that references `sym_with_loc` if one exists.3868/// Returns GOT atom that references `sym_with_loc` if one exists.
3839/// Returns null otherwise.3869/// Returns null otherwise.
3840pub fn getGotAtomForSymbol(self: *MachO, sym_with_loc: SymbolWithLoc) ?*Atom {3870pub fn getGotAtomIndexForSymbol(self: *MachO, sym_with_loc: SymbolWithLoc) ?Atom.Index {
3841 const got_index = self.got_entries_table.get(sym_with_loc) orelse return null;3871 const got_index = self.got_entries_table.get(sym_with_loc) orelse return null;
3842 return self.got_entries.items[got_index].getAtom(self);3872 return self.got_entries.items[got_index].getAtomIndex(self);
3843}3873}
38443874
3845/// Returns stubs atom that references `sym_with_loc` if one exists.3875/// Returns stubs atom that references `sym_with_loc` if one exists.
3846/// Returns null otherwise.3876/// Returns null otherwise.
3847pub fn getStubsAtomForSymbol(self: *MachO, sym_with_loc: SymbolWithLoc) ?*Atom {3877pub fn getStubsAtomIndexForSymbol(self: *MachO, sym_with_loc: SymbolWithLoc) ?Atom.Index {
3848 const stubs_index = self.stubs_table.get(sym_with_loc) orelse return null;3878 const stubs_index = self.stubs_table.get(sym_with_loc) orelse return null;
3849 return self.stubs.items[stubs_index].getAtom(self);3879 return self.stubs.items[stubs_index].getAtomIndex(self);
3850}3880}
38513881
3852/// Returns symbol location corresponding to the set entrypoint.3882/// Returns symbol location corresponding to the set entrypoint.
...@@ -4232,26 +4262,31 @@ pub fn logAtoms(self: *MachO) void {...@@ -4232,26 +4262,31 @@ pub fn logAtoms(self: *MachO) void {
4232 log.debug("atoms:", .{});4262 log.debug("atoms:", .{});
42334263
4234 const slice = self.sections.slice();4264 const slice = self.sections.slice();
4235 for (slice.items(.last_atom)) |last, i| {4265 for (slice.items(.last_atom_index)) |last_atom_index, i| {
4236 var atom = last orelse continue;4266 var atom_index = last_atom_index orelse continue;
4237 const header = slice.items(.header)[i];4267 const header = slice.items(.header)[i];
42384268
4239 while (atom.prev) |prev| {4269 while (true) {
4240 atom = prev;4270 const atom = self.getAtom(atom_index);
4271 if (atom.prev_index) |prev_index| {
4272 atom_index = prev_index;
4273 } else break;
4241 }4274 }
42424275
4243 log.debug("{s},{s}", .{ header.segName(), header.sectName() });4276 log.debug("{s},{s}", .{ header.segName(), header.sectName() });
42444277
4245 while (true) {4278 while (true) {
4246 self.logAtom(atom);4279 self.logAtom(atom_index);
4247 if (atom.next) |next| {4280 const atom = self.getAtom(atom_index);
4248 atom = next;4281 if (atom.next_index) |next_index| {
4282 atom_index = next_index;
4249 } else break;4283 } else break;
4250 }4284 }
4251 }4285 }
4252}4286}
42534287
4254pub fn logAtom(self: *MachO, atom: *const Atom) void {4288pub fn logAtom(self: *MachO, atom_index: Atom.Index) void {
4289 const atom = self.getAtom(atom_index);
4255 const sym = atom.getSymbol(self);4290 const sym = atom.getSymbol(self);
4256 const sym_name = atom.getName(self);4291 const sym_name = atom.getName(self);
4257 log.debug(" ATOM(%{?d}, '{s}') @ {x} (sizeof({x}), alignof({x})) in object({?d}) in sect({d})", .{4292 log.debug(" ATOM(%{?d}, '{s}') @ {x} (sizeof({x}), alignof({x})) in object({?d}) in sect({d})", .{
src/link/MachO/Atom.zig+43-38
...@@ -39,11 +39,14 @@ size: u64,...@@ -39,11 +39,14 @@ size: u64,
39alignment: u32,39alignment: u32,
4040
41/// Points to the previous and next neighbours41/// Points to the previous and next neighbours
42next: ?*Atom,42/// TODO use the same trick as with symbols: reserve index 0 as null atom
43prev: ?*Atom,43next_index: ?Atom.Index,
44prev_index: ?Atom.Index,
4445
45dbg_info_atom: Dwarf.Atom,46dbg_info_atom: Dwarf.Atom,
4647
48pub const Index = u32;
49
47pub const Binding = struct {50pub const Binding = struct {
48 target: SymbolWithLoc,51 target: SymbolWithLoc,
49 offset: u64,52 offset: u64,
...@@ -54,22 +57,6 @@ pub const SymbolAtOffset = struct {...@@ -54,22 +57,6 @@ pub const SymbolAtOffset = struct {
54 offset: u64,57 offset: u64,
55};58};
5659
57pub const empty = Atom{
58 .sym_index = 0,
59 .file = null,
60 .size = 0,
61 .alignment = 0,
62 .prev = null,
63 .next = null,
64 .dbg_info_atom = undefined,
65};
66
67pub fn ensureInitialized(self: *Atom, macho_file: *MachO) !void {
68 if (self.getSymbolIndex() != null) return; // Already initialized
69 self.sym_index = try macho_file.allocateSymbol();
70 try macho_file.atom_by_index_table.putNoClobber(macho_file.base.allocator, self.sym_index, self);
71}
72
73pub fn getSymbolIndex(self: Atom) ?u32 {60pub fn getSymbolIndex(self: Atom) ?u32 {
74 if (self.sym_index == 0) return null;61 if (self.sym_index == 0) return null;
75 return self.sym_index;62 return self.sym_index;
...@@ -108,7 +95,8 @@ pub fn getName(self: Atom, macho_file: *MachO) []const u8 {...@@ -108,7 +95,8 @@ pub fn getName(self: Atom, macho_file: *MachO) []const u8 {
108/// this calculation.95/// this calculation.
109pub fn capacity(self: Atom, macho_file: *MachO) u64 {96pub fn capacity(self: Atom, macho_file: *MachO) u64 {
110 const self_sym = self.getSymbol(macho_file);97 const self_sym = self.getSymbol(macho_file);
111 if (self.next) |next| {98 if (self.next_index) |next_index| {
99 const next = macho_file.getAtom(next_index);
112 const next_sym = next.getSymbol(macho_file);100 const next_sym = next.getSymbol(macho_file);
113 return next_sym.n_value - self_sym.n_value;101 return next_sym.n_value - self_sym.n_value;
114 } else {102 } else {
...@@ -120,7 +108,8 @@ pub fn capacity(self: Atom, macho_file: *MachO) u64 {...@@ -120,7 +108,8 @@ pub fn capacity(self: Atom, macho_file: *MachO) u64 {
120108
121pub fn freeListEligible(self: Atom, macho_file: *MachO) bool {109pub fn freeListEligible(self: Atom, macho_file: *MachO) bool {
122 // No need to keep a free list node for the last atom.110 // No need to keep a free list node for the last atom.
123 const next = self.next orelse return false;111 const next_index = self.next_index orelse return false;
112 const next = macho_file.getAtom(next_index);
124 const self_sym = self.getSymbol(macho_file);113 const self_sym = self.getSymbol(macho_file);
125 const next_sym = next.getSymbol(macho_file);114 const next_sym = next.getSymbol(macho_file);
126 const cap = next_sym.n_value - self_sym.n_value;115 const cap = next_sym.n_value - self_sym.n_value;
...@@ -130,19 +119,19 @@ pub fn freeListEligible(self: Atom, macho_file: *MachO) bool {...@@ -130,19 +119,19 @@ pub fn freeListEligible(self: Atom, macho_file: *MachO) bool {
130 return surplus >= MachO.min_text_capacity;119 return surplus >= MachO.min_text_capacity;
131}120}
132121
133pub fn addRelocation(self: *Atom, macho_file: *MachO, reloc: Relocation) !void {122pub fn addRelocation(macho_file: *MachO, atom_index: Atom.Index, reloc: Relocation) !void {
134 return self.addRelocations(macho_file, 1, .{reloc});123 return addRelocations(macho_file, atom_index, 1, .{reloc});
135}124}
136125
137pub fn addRelocations(126pub fn addRelocations(
138 self: *Atom,
139 macho_file: *MachO,127 macho_file: *MachO,
128 atom_index: Atom.Index,
140 comptime count: comptime_int,129 comptime count: comptime_int,
141 relocs: [count]Relocation,130 relocs: [count]Relocation,
142) !void {131) !void {
143 const gpa = macho_file.base.allocator;132 const gpa = macho_file.base.allocator;
144 const target = macho_file.base.options.target;133 const target = macho_file.base.options.target;
145 const gop = try macho_file.relocs.getOrPut(gpa, self);134 const gop = try macho_file.relocs.getOrPut(gpa, atom_index);
146 if (!gop.found_existing) {135 if (!gop.found_existing) {
147 gop.value_ptr.* = .{};136 gop.value_ptr.* = .{};
148 }137 }
...@@ -156,56 +145,72 @@ pub fn addRelocations(...@@ -156,56 +145,72 @@ pub fn addRelocations(
156 }145 }
157}146}
158147
159pub fn addRebase(self: *Atom, macho_file: *MachO, offset: u32) !void {148pub fn addRebase(macho_file: *MachO, atom_index: Atom.Index, offset: u32) !void {
160 const gpa = macho_file.base.allocator;149 const gpa = macho_file.base.allocator;
161 log.debug(" (adding rebase at offset 0x{x} in %{?d})", .{ offset, self.getSymbolIndex() });150 const atom = macho_file.getAtom(atom_index);
162 const gop = try macho_file.rebases.getOrPut(gpa, self);151 log.debug(" (adding rebase at offset 0x{x} in %{?d})", .{ offset, atom.getSymbolIndex() });
152 const gop = try macho_file.rebases.getOrPut(gpa, atom_index);
163 if (!gop.found_existing) {153 if (!gop.found_existing) {
164 gop.value_ptr.* = .{};154 gop.value_ptr.* = .{};
165 }155 }
166 try gop.value_ptr.append(gpa, offset);156 try gop.value_ptr.append(gpa, offset);
167}157}
168158
169pub fn addBinding(self: *Atom, macho_file: *MachO, binding: Binding) !void {159pub fn addBinding(macho_file: *MachO, atom_index: Atom.Index, binding: Binding) !void {
170 const gpa = macho_file.base.allocator;160 const gpa = macho_file.base.allocator;
161 const atom = macho_file.getAtom(atom_index);
171 log.debug(" (adding binding to symbol {s} at offset 0x{x} in %{?d})", .{162 log.debug(" (adding binding to symbol {s} at offset 0x{x} in %{?d})", .{
172 macho_file.getSymbolName(binding.target),163 macho_file.getSymbolName(binding.target),
173 binding.offset,164 binding.offset,
174 self.getSymbolIndex(),165 atom.getSymbolIndex(),
175 });166 });
176 const gop = try macho_file.bindings.getOrPut(gpa, self);167 const gop = try macho_file.bindings.getOrPut(gpa, atom_index);
177 if (!gop.found_existing) {168 if (!gop.found_existing) {
178 gop.value_ptr.* = .{};169 gop.value_ptr.* = .{};
179 }170 }
180 try gop.value_ptr.append(gpa, binding);171 try gop.value_ptr.append(gpa, binding);
181}172}
182173
183pub fn addLazyBinding(self: *Atom, macho_file: *MachO, binding: Binding) !void {174pub fn addLazyBinding(macho_file: *MachO, atom_index: Atom.Index, binding: Binding) !void {
184 const gpa = macho_file.base.allocator;175 const gpa = macho_file.base.allocator;
176 const atom = macho_file.getAtom(atom_index);
185 log.debug(" (adding lazy binding to symbol {s} at offset 0x{x} in %{?d})", .{177 log.debug(" (adding lazy binding to symbol {s} at offset 0x{x} in %{?d})", .{
186 macho_file.getSymbolName(binding.target),178 macho_file.getSymbolName(binding.target),
187 binding.offset,179 binding.offset,
188 self.getSymbolIndex(),180 atom.getSymbolIndex(),
189 });181 });
190 const gop = try macho_file.lazy_bindings.getOrPut(gpa, self);182 const gop = try macho_file.lazy_bindings.getOrPut(gpa, atom_index);
191 if (!gop.found_existing) {183 if (!gop.found_existing) {
192 gop.value_ptr.* = .{};184 gop.value_ptr.* = .{};
193 }185 }
194 try gop.value_ptr.append(gpa, binding);186 try gop.value_ptr.append(gpa, binding);
195}187}
196188
197pub fn resolveRelocations(self: *Atom, macho_file: *MachO) !void {189pub fn resolveRelocations(macho_file: *MachO, atom_index: Atom.Index) !void {
198 const relocs = macho_file.relocs.get(self) orelse return;190 const atom = macho_file.getAtom(atom_index);
199 const source_sym = self.getSymbol(macho_file);191 const relocs = macho_file.relocs.get(atom_index) orelse return;
192 const source_sym = atom.getSymbol(macho_file);
200 const source_section = macho_file.sections.get(source_sym.n_sect - 1).header;193 const source_section = macho_file.sections.get(source_sym.n_sect - 1).header;
201 const file_offset = source_section.offset + source_sym.n_value - source_section.addr;194 const file_offset = source_section.offset + source_sym.n_value - source_section.addr;
202195
203 log.debug("relocating '{s}'", .{self.getName(macho_file)});196 log.debug("relocating '{s}'", .{atom.getName(macho_file)});
204197
205 for (relocs.items) |*reloc| {198 for (relocs.items) |*reloc| {
206 if (!reloc.dirty) continue;199 if (!reloc.dirty) continue;
207200
208 try reloc.resolve(self, macho_file, file_offset);201 try reloc.resolve(macho_file, atom_index, file_offset);
209 reloc.dirty = false;202 reloc.dirty = false;
210 }203 }
211}204}
205
206pub fn freeRelocations(macho_file: *MachO, atom_index: Atom.Index) void {
207 const gpa = macho_file.base.allocator;
208 var removed_relocs = macho_file.relocs.fetchOrderedRemove(atom_index);
209 if (removed_relocs) |*relocs| relocs.value.deinit(gpa);
210 var removed_rebases = macho_file.rebases.fetchOrderedRemove(atom_index);
211 if (removed_rebases) |*rebases| rebases.value.deinit(gpa);
212 var removed_bindings = macho_file.bindings.fetchOrderedRemove(atom_index);
213 if (removed_bindings) |*bindings| bindings.value.deinit(gpa);
214 var removed_lazy_bindings = macho_file.lazy_bindings.fetchOrderedRemove(atom_index);
215 if (removed_lazy_bindings) |*lazy_bindings| lazy_bindings.value.deinit(gpa);
216}
src/link/MachO/Relocation.zig+9-7
...@@ -29,33 +29,35 @@ pub fn fmtType(self: Relocation, target: std.Target) []const u8 {...@@ -29,33 +29,35 @@ pub fn fmtType(self: Relocation, target: std.Target) []const u8 {
29 }29 }
30}30}
3131
32pub fn getTargetAtom(self: Relocation, macho_file: *MachO) ?*Atom {32pub fn getTargetAtomIndex(self: Relocation, macho_file: *MachO) ?Atom.Index {
33 switch (macho_file.base.options.target.cpu.arch) {33 switch (macho_file.base.options.target.cpu.arch) {
34 .aarch64 => switch (@intToEnum(macho.reloc_type_arm64, self.type)) {34 .aarch64 => switch (@intToEnum(macho.reloc_type_arm64, self.type)) {
35 .ARM64_RELOC_GOT_LOAD_PAGE21,35 .ARM64_RELOC_GOT_LOAD_PAGE21,
36 .ARM64_RELOC_GOT_LOAD_PAGEOFF12,36 .ARM64_RELOC_GOT_LOAD_PAGEOFF12,
37 .ARM64_RELOC_POINTER_TO_GOT,37 .ARM64_RELOC_POINTER_TO_GOT,
38 => return macho_file.getGotAtomForSymbol(self.target),38 => return macho_file.getGotAtomIndexForSymbol(self.target),
39 else => {},39 else => {},
40 },40 },
41 .x86_64 => switch (@intToEnum(macho.reloc_type_x86_64, self.type)) {41 .x86_64 => switch (@intToEnum(macho.reloc_type_x86_64, self.type)) {
42 .X86_64_RELOC_GOT,42 .X86_64_RELOC_GOT,
43 .X86_64_RELOC_GOT_LOAD,43 .X86_64_RELOC_GOT_LOAD,
44 => return macho_file.getGotAtomForSymbol(self.target),44 => return macho_file.getGotAtomIndexForSymbol(self.target),
45 else => {},45 else => {},
46 },46 },
47 else => unreachable,47 else => unreachable,
48 }48 }
49 if (macho_file.getStubsAtomForSymbol(self.target)) |stubs_atom| return stubs_atom;49 if (macho_file.getStubsAtomIndexForSymbol(self.target)) |stubs_atom| return stubs_atom;
50 return macho_file.getAtomForSymbol(self.target);50 return macho_file.getAtomIndexForSymbol(self.target);
51}51}
5252
53pub fn resolve(self: Relocation, atom: *Atom, macho_file: *MachO, base_offset: u64) !void {53pub fn resolve(self: Relocation, macho_file: *MachO, atom_index: Atom.Index, base_offset: u64) !void {
54 const arch = macho_file.base.options.target.cpu.arch;54 const arch = macho_file.base.options.target.cpu.arch;
55 const atom = macho_file.getAtom(atom_index);
55 const source_sym = atom.getSymbol(macho_file);56 const source_sym = atom.getSymbol(macho_file);
56 const source_addr = source_sym.n_value + self.offset;57 const source_addr = source_sym.n_value + self.offset;
5758
58 const target_atom = self.getTargetAtom(macho_file) orelse return;59 const target_atom_index = self.getTargetAtomIndex(macho_file) orelse return;
60 const target_atom = macho_file.getAtom(target_atom_index);
59 const target_addr = @intCast(i64, target_atom.getSymbol(macho_file).n_value) + self.addend;61 const target_addr = @intCast(i64, target_atom.getSymbol(macho_file).n_value) + self.addend;
6062
61 log.debug(" ({x}: [() => 0x{x} ({s})) ({s})", .{63 log.debug(" ({x}: [() => 0x{x} ({s})) ({s})", .{