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 {
40984098
40994099 // The exports this Decl performs will be re-discovered, so we remove them here
41004100 // prior to re-analysis.
4101 mod.deleteDeclExports(decl_index);
4101 try mod.deleteDeclExports(decl_index);
41024102
41034103 // Similarly, `@setAlignStack` invocations will be re-discovered.
41044104 if (decl.getFunction()) |func| {
......@@ -5265,7 +5265,7 @@ pub fn clearDecl(
52655265 assert(emit_h.decl_table.swapRemove(decl_index));
52665266 }
52675267 _ = mod.compile_log_decls.swapRemove(decl_index);
5268 mod.deleteDeclExports(decl_index);
5268 try mod.deleteDeclExports(decl_index);
52695269
52705270 if (decl.has_tv) {
52715271 if (decl.ty.isFnOrHasRuntimeBits()) {
......@@ -5276,7 +5276,7 @@ pub fn clearDecl(
52765276 decl.link = switch (mod.comp.bin_file.tag) {
52775277 .coff => .{ .coff = link.File.Coff.Atom.empty },
52785278 .elf => .{ .elf = link.File.Elf.TextBlock.empty },
5279 .macho => .{ .macho = link.File.MachO.Atom.empty },
5279 .macho => .{ .macho = {} },
52805280 .plan9 => .{ .plan9 = link.File.Plan9.DeclBlock.empty },
52815281 .c => .{ .c = {} },
52825282 .wasm => .{ .wasm = link.File.Wasm.DeclBlock.empty },
......@@ -5358,7 +5358,7 @@ pub fn abortAnonDecl(mod: *Module, decl_index: Decl.Index) void {
53585358
53595359/// Delete all the Export objects that are caused by this Decl. Re-analysis of
53605360/// 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 {
53625362 var export_owners = (mod.export_owners.fetchSwapRemove(decl_index) orelse return).value;
53635363
53645364 for (export_owners.items) |exp| {
......@@ -5384,7 +5384,7 @@ fn deleteDeclExports(mod: *Module, decl_index: Decl.Index) void {
53845384 elf.deleteExport(exp.link.elf);
53855385 }
53865386 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);
53885388 }
53895389 if (mod.comp.bin_file.cast(link.File.Wasm)) |wasm| {
53905390 wasm.deleteExport(exp.link.wasm);
......@@ -5696,7 +5696,7 @@ pub fn allocateNewDecl(
56965696 .link = switch (mod.comp.bin_file.tag) {
56975697 .coff => .{ .coff = link.File.Coff.Atom.empty },
56985698 .elf => .{ .elf = link.File.Elf.TextBlock.empty },
5699 .macho => .{ .macho = link.File.MachO.Atom.empty },
5699 .macho => .{ .macho = {} },
57005700 .plan9 => .{ .plan9 = link.File.Plan9.DeclBlock.empty },
57015701 .c => .{ .c = {} },
57025702 .wasm => .{ .wasm = link.File.Wasm.DeclBlock.empty },
src/Sema.zig+1-1
......@@ -5567,7 +5567,7 @@ pub fn analyzeExport(
55675567 .link = switch (mod.comp.bin_file.tag) {
55685568 .coff => .{ .coff = .{} },
55695569 .elf => .{ .elf = .{} },
5570 .macho => .{ .macho = .{} },
5570 .macho => .{ .macho = {} },
55715571 .plan9 => .{ .plan9 = null },
55725572 .c => .{ .c = {} },
55735573 .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
40224022 const mod = self.bin_file.options.module.?;
40234023 const owner_decl = mod.declPtr(self.mod_fn.owner_decl);
40244024 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 },
40264030 .coff => owner_decl.link.coff.getSymbolIndex().?,
40274031 else => unreachable, // unsupported target format
40284032 };
......@@ -4308,11 +4312,12 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
43084312 const got_addr = @intCast(u32, fn_owner_decl.link.elf.getOffsetTableAddress(elf_file));
43094313 try self.genSetReg(Type.initTag(.usize), .x30, .{ .memory = got_addr });
43104314 } 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().?;
43124317 try self.genSetReg(Type.initTag(.u64), .x30, .{
43134318 .linker_load = .{
43144319 .type = .got,
4315 .sym_index = fn_owner_decl.link.macho.getSymbolIndex().?,
4320 .sym_index = sym_index,
43164321 },
43174322 });
43184323 } 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
43494354
43504355 if (self.bin_file.cast(link.File.MachO)) |macho_file| {
43514356 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().?;
43524359 _ = try self.addInst(.{
43534360 .tag = .call_extern,
43544361 .data = .{
43554362 .relocation = .{
4356 .atom_index = mod.declPtr(self.mod_fn.owner_decl).link.macho.getSymbolIndex().?,
4363 .atom_index = atom_index,
43574364 .sym_index = sym_index,
43584365 },
43594366 },
......@@ -5491,7 +5498,11 @@ fn genSetStack(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) InnerErro
54915498 const mod = self.bin_file.options.module.?;
54925499 const owner_decl = mod.declPtr(self.mod_fn.owner_decl);
54935500 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 },
54955506 .coff => owner_decl.link.coff.getSymbolIndex().?,
54965507 else => unreachable, // unsupported target format
54975508 };
......@@ -5605,7 +5616,11 @@ fn genSetReg(self: *Self, ty: Type, reg: Register, mcv: MCValue) InnerError!void
56055616 const mod = self.bin_file.options.module.?;
56065617 const owner_decl = mod.declPtr(self.mod_fn.owner_decl);
56075618 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 },
56095624 .coff => owner_decl.link.coff.getSymbolIndex().?,
56105625 else => unreachable, // unsupported target format
56115626 };
......@@ -5799,7 +5814,11 @@ fn genSetStackArgument(self: *Self, ty: Type, stack_offset: u32, mcv: MCValue) I
57995814 const mod = self.bin_file.options.module.?;
58005815 const owner_decl = mod.declPtr(self.mod_fn.owner_decl);
58015816 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 },
58035822 .coff => owner_decl.link.coff.getSymbolIndex().?,
58045823 else => unreachable, // unsupported target format
58055824 };
......@@ -6122,10 +6141,11 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne
61226141 try decl.link.elf.ensureInitialized(elf_file);
61236142 return MCValue{ .memory = decl.link.elf.getOffsetTableAddress(elf_file) };
61246143 } 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().?;
61266146 return MCValue{ .linker_load = .{
61276147 .type = .got,
6128 .sym_index = decl.link.macho.getSymbolIndex().?,
6148 .sym_index = sym_index,
61296149 } };
61306150 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
61316151 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 {
670670
671671 if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
672672 // 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 }).?;
674674 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, .{
676676 .type = @enumToInt(std.macho.reloc_type_arm64.ARM64_RELOC_BRANCH26),
677677 .target = target,
678678 .offset = offset,
......@@ -883,10 +883,10 @@ fn mirLoadMemoryPie(emit: *Emit, inst: Mir.Inst.Index) !void {
883883 }
884884
885885 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 }).?;
887887 // TODO this causes segfault in stage1
888888 // try atom.addRelocations(macho_file, 2, .{
889 try atom.addRelocation(macho_file, .{
889 try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
890890 .target = .{ .sym_index = data.sym_index, .file = null },
891891 .offset = offset,
892892 .addend = 0,
......@@ -902,7 +902,7 @@ fn mirLoadMemoryPie(emit: *Emit, inst: Mir.Inst.Index) !void {
902902 else => unreachable,
903903 },
904904 });
905 try atom.addRelocation(macho_file, .{
905 try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
906906 .target = .{ .sym_index = data.sym_index, .file = null },
907907 .offset = offset + 4,
908908 .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
25562556 try decl.link.elf.ensureInitialized(elf_file);
25572557 return MCValue{ .memory = decl.link.elf.getOffsetTableAddress(elf_file) };
25582558 } else if (self.bin_file.cast(link.File.MachO)) |_| {
2559 // TODO I'm hacking my way through here by repurposing .memory for storing
2560 // index to the GOT target symbol index.
2561 return MCValue{ .memory = decl.link.macho.sym_index };
2559 unreachable;
25622560 } else if (self.bin_file.cast(link.File.Coff)) |_| {
25632561 return self.fail("TODO codegen COFF const Decl pointer", .{});
25642562 } 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
26702670 const abi_size = @intCast(u32, ptr_ty.abiSize(self.target.*));
26712671 const mod = self.bin_file.options.module.?;
26722672 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)
2674 fn_owner_decl.link.macho.getSymbolIndex().?
2675 else
2676 fn_owner_decl.link.coff.getSymbolIndex().?;
2673 const atom_index = if (self.bin_file.cast(link.File.MachO)) |macho_file| blk: {
2674 const atom = try macho_file.getOrCreateAtomForDecl(self.mod_fn.owner_decl);
2675 break :blk macho_file.getAtom(atom).getSymbolIndex().?;
2676 } else if (self.bin_file.cast(link.File.Coff)) |_| blk: {
2677 break :blk fn_owner_decl.link.coff.getSymbolIndex().?;
2678 } else unreachable;
26772679 const flags: u2 = switch (load_struct.type) {
26782680 .got => 0b00,
26792681 .direct => 0b01,
......@@ -4023,8 +4025,8 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
40234025 .data = undefined,
40244026 });
40254027 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
4026 try fn_owner_decl.link.macho.ensureInitialized(macho_file);
4027 const sym_index = fn_owner_decl.link.macho.getSymbolIndex().?;
4028 const atom_index = try macho_file.getOrCreateAtomForDecl(func.owner_decl);
4029 const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?;
40284030 try self.genSetReg(Type.initTag(.usize), .rax, .{
40294031 .linker_load = .{
40304032 .type = .got,
......@@ -4080,15 +4082,15 @@ fn airCall(self: *Self, inst: Air.Inst.Index, modifier: std.builtin.CallModifier
40804082 });
40814083 } else if (self.bin_file.cast(link.File.MachO)) |macho_file| {
40824084 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().?;
40834087 _ = try self.addInst(.{
40844088 .tag = .call_extern,
40854089 .ops = undefined,
4086 .data = .{
4087 .relocation = .{
4088 .atom_index = mod.declPtr(self.mod_fn.owner_decl).link.macho.getSymbolIndex().?,
4089 .sym_index = sym_index,
4090 },
4091 },
4090 .data = .{ .relocation = .{
4091 .atom_index = atom_index,
4092 .sym_index = sym_index,
4093 } },
40924094 });
40934095 } else {
40944096 return self.fail("TODO implement calling extern functions", .{});
......@@ -6722,10 +6724,11 @@ fn lowerDeclRef(self: *Self, tv: TypedValue, decl_index: Module.Decl.Index) Inne
67226724 try decl.link.elf.ensureInitialized(elf_file);
67236725 return MCValue{ .memory = decl.link.elf.getOffsetTableAddress(elf_file) };
67246726 } 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().?;
67266729 return MCValue{ .linker_load = .{
67276730 .type = .got,
6728 .sym_index = decl.link.macho.getSymbolIndex().?,
6731 .sym_index = sym_index,
67296732 } };
67306733 } else if (self.bin_file.cast(link.File.Coff)) |coff_file| {
67316734 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 {
10011001 0b01 => @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_SIGNED),
10021002 else => unreachable,
10031003 };
1004 const atom = macho_file.getAtomForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
1005 try atom.addRelocation(macho_file, .{
1004 const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;
1005 try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
10061006 .type = reloc_type,
10071007 .target = .{ .sym_index = relocation.sym_index, .file = null },
10081008 .offset = @intCast(u32, end_offset - 4),
......@@ -1140,9 +1140,9 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) InnerError!void {
11401140
11411141 if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
11421142 // 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 }).?;
11441144 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, .{
11461146 .type = @enumToInt(std.macho.reloc_type_x86_64.X86_64_RELOC_BRANCH),
11471147 .target = target,
11481148 .offset = offset,
src/link.zig+2-2
......@@ -264,7 +264,7 @@ pub const File = struct {
264264 pub const LinkBlock = union {
265265 elf: Elf.TextBlock,
266266 coff: Coff.Atom,
267 macho: MachO.Atom,
267 macho: void,
268268 plan9: Plan9.DeclBlock,
269269 c: void,
270270 wasm: Wasm.DeclBlock,
......@@ -286,7 +286,7 @@ pub const File = struct {
286286 pub const Export = union {
287287 elf: Elf.Export,
288288 coff: Coff.Export,
289 macho: MachO.Export,
289 macho: void,
290290 plan9: Plan9.Export,
291291 c: void,
292292 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
26392639 const decl = mod.declPtr(decl_index);
26402640 return switch (tag) {
26412641 .elf => &decl.link.elf.dbg_info_atom,
2642 .macho => &decl.link.macho.dbg_info_atom,
2642 .macho => unreachable,
26432643 .wasm => &decl.link.wasm.dbg_info_atom,
26442644 else => unreachable,
26452645 };
src/link/MachO.zig+377-342
......@@ -66,7 +66,7 @@ const Section = struct {
6666
6767 // TODO is null here necessary, or can we do away with tracking via section
6868 // size in incremental context?
69 last_atom: ?*Atom = null,
69 last_atom_index: ?Atom.Index = null,
7070
7171 /// A list of atoms that have surplus capacity. This list can have false
7272 /// positives, as functions grow and shrink over time, only sometimes being added
......@@ -83,7 +83,7 @@ const Section = struct {
8383 /// overcapacity can be negative. A simple way to have negative overcapacity is to
8484 /// allocate a fresh atom, which will have ideal capacity, and then grow it
8585 /// by 1 byte. It will then have -1 overcapacity.
86 free_list: std.ArrayListUnmanaged(*Atom) = .{},
86 free_list: std.ArrayListUnmanaged(Atom.Index) = .{},
8787};
8888
8989base: File,
......@@ -140,8 +140,8 @@ locals_free_list: std.ArrayListUnmanaged(u32) = .{},
140140globals_free_list: std.ArrayListUnmanaged(u32) = .{},
141141
142142dyld_stub_binder_index: ?u32 = null,
143dyld_private_atom: ?*Atom = null,
144stub_helper_preamble_atom: ?*Atom = null,
143dyld_private_atom_index: ?Atom.Index = null,
144stub_helper_preamble_atom_index: ?Atom.Index = null,
145145
146146strtab: StringTable(.strtab) = .{},
147147
......@@ -164,10 +164,10 @@ segment_table_dirty: bool = false,
164164cold_start: bool = true,
165165
166166/// 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
169169/// 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
172172/// Table of unnamed constants associated with a parent `Decl`.
173173/// We store them here so that we can free the constants whenever the `Decl`
......@@ -210,11 +210,36 @@ bindings: BindingTable = .{},
210210/// this will be a table indexed by index into the list of Atoms.
211211lazy_bindings: BindingTable = .{},
212212
213/// Table of Decls that are currently alive.
214/// We store them here so that we can properly dispose of any allocated
215/// memory within the atom in the incremental linker.
216/// TODO consolidate this.
217decls: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, ?u8) = .{},
213/// Table of tracked Decls.
214decls: std.AutoArrayHashMapUnmanaged(Module.Decl.Index, DeclMetadata) = .{},
215
216const DeclMetadata = struct {
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
219244const Entry = struct {
220245 target: SymbolWithLoc,
......@@ -229,8 +254,8 @@ const Entry = struct {
229254 return macho_file.getSymbolPtr(.{ .sym_index = entry.sym_index, .file = null });
230255 }
231256
232 pub fn getAtom(entry: Entry, macho_file: *MachO) ?*Atom {
233 return macho_file.getAtomForSymbol(.{ .sym_index = entry.sym_index, .file = null });
257 pub fn getAtomIndex(entry: Entry, macho_file: *MachO) ?Atom.Index {
258 return macho_file.getAtomIndexForSymbol(.{ .sym_index = entry.sym_index, .file = null });
234259 }
235260
236261 pub fn getName(entry: Entry, macho_file: *MachO) []const u8 {
......@@ -238,10 +263,10 @@ const Entry = struct {
238263 }
239264};
240265
241const BindingTable = std.AutoArrayHashMapUnmanaged(*Atom, std.ArrayListUnmanaged(Atom.Binding));
242const UnnamedConstTable = std.AutoArrayHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(*Atom));
243const RebaseTable = std.AutoArrayHashMapUnmanaged(*Atom, std.ArrayListUnmanaged(u32));
244const RelocationTable = std.AutoArrayHashMapUnmanaged(*Atom, std.ArrayListUnmanaged(Relocation));
266const BindingTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(Atom.Binding));
267const UnnamedConstTable = std.AutoArrayHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(Atom.Index));
268const RebaseTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(u32));
269const RelocationTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(Relocation));
245270
246271const PendingUpdate = union(enum) {
247272 resolve_undef: u32,
......@@ -286,10 +311,6 @@ pub const default_pagezero_vmsize: u64 = 0x100000000;
286311/// potential future extensions.
287312pub const default_headerpad_size: u32 = 0x1000;
288313
289pub const Export = struct {
290 sym_index: ?u32 = null,
291};
292
293314pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {
294315 assert(options.target.ofmt == .macho);
295316
......@@ -451,9 +472,9 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
451472
452473 const module = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented;
453474
454 if (self.d_sym) |*d_sym| {
455 try d_sym.dwarf.flushModule(module);
456 }
475 // if (self.d_sym) |*d_sym| {
476 // try d_sym.dwarf.flushModule(module);
477 // }
457478
458479 var libs = std.StringArrayHashMap(link.SystemLib).init(arena);
459480 try resolveLibSystem(
......@@ -547,8 +568,8 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
547568
548569 try self.allocateSpecialSymbols();
549570
550 for (self.relocs.keys()) |atom| {
551 try atom.resolveRelocations(self);
571 for (self.relocs.keys()) |atom_index| {
572 try Atom.resolveRelocations(self, atom_index);
552573 }
553574
554575 if (build_options.enable_logging) {
......@@ -643,10 +664,10 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
643664 try self.writeCodeSignature(comp, csig); // code signing always comes last
644665 }
645666
646 if (self.d_sym) |*d_sym| {
647 // Flush debug symbols bundle.
648 try d_sym.flushModule(self);
649 }
667 // if (self.d_sym) |*d_sym| {
668 // // Flush debug symbols bundle.
669 // try d_sym.flushModule(self);
670 // }
650671
651672 // if (build_options.enable_link_snapshots) {
652673 // if (self.base.options.enable_link_snapshots)
......@@ -999,18 +1020,19 @@ pub fn parseDependentLibs(self: *MachO, syslibroot: ?[]const u8, dependent_libs:
9991020 }
10001021}
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);
10031025 const sym = atom.getSymbol(self);
10041026 const section = self.sections.get(sym.n_sect - 1);
10051027 const file_offset = section.header.offset + sym.n_value - section.header.addr;
10061028 log.debug("writing atom for symbol {s} at file offset 0x{x}", .{ atom.getName(self), file_offset });
10071029 try self.base.file.?.pwriteAll(code, file_offset);
1008 try atom.resolveRelocations(self);
1030 try Atom.resolveRelocations(self, atom_index);
10091031}
10101032
1011fn writePtrWidthAtom(self: *MachO, atom: *Atom) !void {
1033fn writePtrWidthAtom(self: *MachO, atom_index: Atom.Index) !void {
10121034 var buffer: [@sizeOf(u64)]u8 = [_]u8{0} ** @sizeOf(u64);
1013 try self.writeAtom(atom, &buffer);
1035 try self.writeAtom(atom_index, &buffer);
10141036}
10151037
10161038fn markRelocsDirtyByTarget(self: *MachO, target: SymbolWithLoc) void {
......@@ -1026,7 +1048,8 @@ fn markRelocsDirtyByTarget(self: *MachO, target: SymbolWithLoc) void {
10261048fn markRelocsDirtyByAddress(self: *MachO, addr: u64) void {
10271049 for (self.relocs.values()) |*relocs| {
10281050 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);
10301053 const target_sym = target_atom.getSymbol(self);
10311054 if (target_sym.n_value < addr) continue;
10321055 reloc.dirty = true;
......@@ -1053,26 +1076,39 @@ pub fn allocateSpecialSymbols(self: *MachO) !void {
10531076 }
10541077}
10551078
1056pub fn createGotAtom(self: *MachO, target: SymbolWithLoc) !*Atom {
1079pub fn createAtom(self: *MachO) !Atom.Index {
10571080 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);
1060 atom.* = Atom.empty;
1061 try atom.ensureInitialized(self);
1098pub fn createGotAtom(self: *MachO, target: SymbolWithLoc) !Atom.Index {
1099 const atom_index = try self.createAtom();
1100 const atom = self.getAtomPtr(atom_index);
10621101 atom.size = @sizeOf(u64);
10631102 atom.alignment = @alignOf(u64);
1064 errdefer gpa.destroy(atom);
1065
1066 try self.managed_atoms.append(gpa, atom);
10671103
10681104 const sym = atom.getSymbolPtr(self);
10691105 sym.n_type = macho.N_SECT;
10701106 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
10731109 log.debug("allocated GOT atom at 0x{x}", .{sym.n_value});
10741110
1075 try atom.addRelocation(self, .{
1111 try Atom.addRelocation(self, atom_index, .{
10761112 .type = switch (self.base.options.target.cpu.arch) {
10771113 .aarch64 => @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_UNSIGNED),
10781114 .x86_64 => @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_UNSIGNED),
......@@ -1087,45 +1123,39 @@ pub fn createGotAtom(self: *MachO, target: SymbolWithLoc) !*Atom {
10871123
10881124 const target_sym = self.getSymbol(target);
10891125 if (target_sym.undf()) {
1090 try atom.addBinding(self, .{
1126 try Atom.addBinding(self, atom_index, .{
10911127 .target = self.getGlobal(self.getSymbolName(target)).?,
10921128 .offset = 0,
10931129 });
10941130 } else {
1095 try atom.addRebase(self, 0);
1131 try Atom.addRebase(self, atom_index, 0);
10961132 }
10971133
1098 return atom;
1134 return atom_index;
10991135}
11001136
11011137pub fn createDyldPrivateAtom(self: *MachO) !void {
11021138 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;
1106
1107 const atom = try gpa.create(Atom);
1108 atom.* = Atom.empty;
1109 try atom.ensureInitialized(self);
1141 const atom_index = try self.createAtom();
1142 const atom = self.getAtomPtr(atom_index);
11101143 atom.size = @sizeOf(u64);
11111144 atom.alignment = @alignOf(u64);
1112 errdefer gpa.destroy(atom);
11131145
11141146 const sym = atom.getSymbolPtr(self);
11151147 sym.n_type = macho.N_SECT;
11161148 sym.n_sect = self.data_section_index.? + 1;
1117 self.dyld_private_atom = atom;
1118
1119 try self.managed_atoms.append(gpa, atom);
1149 self.dyld_private_atom_index = atom_index;
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));
11221152 log.debug("allocated dyld_private atom at 0x{x}", .{sym.n_value});
1123 try self.writePtrWidthAtom(atom);
1153 try self.writePtrWidthAtom(atom_index);
11241154}
11251155
11261156pub fn createStubHelperPreambleAtom(self: *MachO) !void {
11271157 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
11301160 const gpa = self.base.allocator;
11311161 const arch = self.base.options.target.cpu.arch;
......@@ -1134,22 +1164,23 @@ pub fn createStubHelperPreambleAtom(self: *MachO) !void {
11341164 .aarch64 => 6 * @sizeOf(u32),
11351165 else => unreachable,
11361166 };
1137 const atom = try gpa.create(Atom);
1138 atom.* = Atom.empty;
1139 try atom.ensureInitialized(self);
1167 const atom_index = try self.createAtom();
1168 const atom = self.getAtomPtr(atom_index);
11401169 atom.size = size;
11411170 atom.alignment = switch (arch) {
11421171 .x86_64 => 1,
11431172 .aarch64 => @alignOf(u32),
11441173 else => unreachable,
11451174 };
1146 errdefer gpa.destroy(atom);
11471175
11481176 const sym = atom.getSymbolPtr(self);
11491177 sym.n_type = macho.N_SECT;
11501178 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
11541185 const code = try gpa.alloc(u8, size);
11551186 defer gpa.free(code);
......@@ -1168,7 +1199,7 @@ pub fn createStubHelperPreambleAtom(self: *MachO) !void {
11681199 code[9] = 0xff;
11691200 code[10] = 0x25;
11701201
1171 try atom.addRelocations(self, 2, .{ .{
1202 try Atom.addRelocations(self, atom_index, 2, .{ .{
11721203 .type = @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_SIGNED),
11731204 .target = .{ .sym_index = dyld_private_sym_index, .file = null },
11741205 .offset = 3,
......@@ -1208,7 +1239,7 @@ pub fn createStubHelperPreambleAtom(self: *MachO) !void {
12081239 // br x16
12091240 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, .{ .{
12121243 .type = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_PAGE21),
12131244 .target = .{ .sym_index = dyld_private_sym_index, .file = null },
12141245 .offset = 0,
......@@ -1241,16 +1272,14 @@ pub fn createStubHelperPreambleAtom(self: *MachO) !void {
12411272
12421273 else => unreachable,
12431274 }
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);
1247
1248 sym.n_value = try self.allocateAtom(atom, size, atom.alignment);
1277 sym.n_value = try self.allocateAtom(atom_index, size, atom.alignment);
12491278 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);
12511280}
12521281
1253pub fn createStubHelperAtom(self: *MachO) !*Atom {
1282pub fn createStubHelperAtom(self: *MachO) !Atom.Index {
12541283 const gpa = self.base.allocator;
12551284 const arch = self.base.options.target.cpu.arch;
12561285 const size: u4 = switch (arch) {
......@@ -1258,16 +1287,14 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom {
12581287 .aarch64 => 3 * @sizeOf(u32),
12591288 else => unreachable,
12601289 };
1261 const atom = try gpa.create(Atom);
1262 atom.* = Atom.empty;
1263 try atom.ensureInitialized(self);
1290 const atom_index = try self.createAtom();
1291 const atom = self.getAtomPtr(atom_index);
12641292 atom.size = size;
12651293 atom.alignment = switch (arch) {
12661294 .x86_64 => 1,
12671295 .aarch64 => @alignOf(u32),
12681296 else => unreachable,
12691297 };
1270 errdefer gpa.destroy(atom);
12711298
12721299 const sym = atom.getSymbolPtr(self);
12731300 sym.n_type = macho.N_SECT;
......@@ -1277,6 +1304,11 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom {
12771304 defer gpa.free(code);
12781305 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
12801312 switch (arch) {
12811313 .x86_64 => {
12821314 // pushq
......@@ -1285,9 +1317,9 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom {
12851317 // jmpq
12861318 code[5] = 0xe9;
12871319
1288 try atom.addRelocation(self, .{
1320 try Atom.addRelocation(self, atom_index, .{
12891321 .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 },
12911323 .offset = 6,
12921324 .addend = 0,
12931325 .pcrel = true,
......@@ -1308,9 +1340,9 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom {
13081340 mem.writeIntLittle(u32, code[4..8], aarch64.Instruction.b(0).toU32());
13091341 // 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, .{
13121344 .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 },
13141346 .offset = 4,
13151347 .addend = 0,
13161348 .pcrel = true,
......@@ -1320,29 +1352,24 @@ pub fn createStubHelperAtom(self: *MachO) !*Atom {
13201352 else => unreachable,
13211353 }
13221354
1323 try self.managed_atoms.append(gpa, atom);
1324
1325 sym.n_value = try self.allocateAtom(atom, size, atom.alignment);
1355 sym.n_value = try self.allocateAtom(atom_index, size, atom.alignment);
13261356 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;
13301360}
13311361
1332pub fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32, target: SymbolWithLoc) !*Atom {
1333 const gpa = self.base.allocator;
1334 const atom = try gpa.create(Atom);
1335 atom.* = Atom.empty;
1336 try atom.ensureInitialized(self);
1362pub fn createLazyPointerAtom(self: *MachO, stub_sym_index: u32, target: SymbolWithLoc) !Atom.Index {
1363 const atom_index = try self.createAtom();
1364 const atom = self.getAtomPtr(atom_index);
13371365 atom.size = @sizeOf(u64);
13381366 atom.alignment = @alignOf(u64);
1339 errdefer gpa.destroy(atom);
13401367
13411368 const sym = atom.getSymbolPtr(self);
13421369 sym.n_type = macho.N_SECT;
13431370 sym.n_sect = self.la_symbol_ptr_section_index.? + 1;
13441371
1345 try atom.addRelocation(self, .{
1372 try Atom.addRelocation(self, atom_index, .{
13461373 .type = switch (self.base.options.target.cpu.arch) {
13471374 .aarch64 => @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_UNSIGNED),
13481375 .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
13541381 .pcrel = false,
13551382 .length = 3,
13561383 });
1357 try atom.addRebase(self, 0);
1358 try atom.addLazyBinding(self, .{
1384 try Atom.addRebase(self, atom_index, 0);
1385 try Atom.addLazyBinding(self, atom_index, .{
13591386 .target = self.getGlobal(self.getSymbolName(target)).?,
13601387 .offset = 0,
13611388 });
13621389
1363 try self.managed_atoms.append(gpa, atom);
1364
1365 sym.n_value = try self.allocateAtom(atom, atom.size, @alignOf(u64));
1390 sym.n_value = try self.allocateAtom(atom_index, atom.size, @alignOf(u64));
13661391 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;
13701395}
13711396
1372pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom {
1397pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !Atom.Index {
13731398 const gpa = self.base.allocator;
13741399 const arch = self.base.options.target.cpu.arch;
13751400 const size: u4 = switch (arch) {
......@@ -1377,9 +1402,8 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom {
13771402 .aarch64 => 3 * @sizeOf(u32),
13781403 else => unreachable, // unhandled architecture type
13791404 };
1380 const atom = try gpa.create(Atom);
1381 atom.* = Atom.empty;
1382 try atom.ensureInitialized(self);
1405 const atom_index = try self.createAtom();
1406 const atom = self.getAtomPtr(atom_index);
13831407 atom.size = size;
13841408 atom.alignment = switch (arch) {
13851409 .x86_64 => 1,
......@@ -1387,7 +1411,6 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom {
13871411 else => unreachable, // unhandled architecture type
13881412
13891413 };
1390 errdefer gpa.destroy(atom);
13911414
13921415 const sym = atom.getSymbolPtr(self);
13931416 sym.n_type = macho.N_SECT;
......@@ -1403,7 +1426,7 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom {
14031426 code[0] = 0xff;
14041427 code[1] = 0x25;
14051428
1406 try atom.addRelocation(self, .{
1429 try Atom.addRelocation(self, atom_index, .{
14071430 .type = @enumToInt(macho.reloc_type_x86_64.X86_64_RELOC_BRANCH),
14081431 .target = .{ .sym_index = laptr_sym_index, .file = null },
14091432 .offset = 2,
......@@ -1424,7 +1447,7 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom {
14241447 // br x16
14251448 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, .{
14281451 .{
14291452 .type = @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_PAGE21),
14301453 .target = .{ .sym_index = laptr_sym_index, .file = null },
......@@ -1446,13 +1469,11 @@ pub fn createStubAtom(self: *MachO, laptr_sym_index: u32) !*Atom {
14461469 else => unreachable,
14471470 }
14481471
1449 try self.managed_atoms.append(gpa, atom);
1450
1451 sym.n_value = try self.allocateAtom(atom, size, atom.alignment);
1472 sym.n_value = try self.allocateAtom(atom_index, size, atom.alignment);
14521473 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;
14561477}
14571478
14581479pub fn createMhExecuteHeaderSymbol(self: *MachO) !void {
......@@ -1586,9 +1607,12 @@ pub fn resolveSymbolsInDylibs(self: *MachO) !void {
15861607 if (self.stubs_table.contains(global)) break :blk;
15871608
15881609 const stub_index = try self.allocateStubEntry(global);
1589 const stub_helper_atom = try self.createStubHelperAtom();
1590 const laptr_atom = try self.createLazyPointerAtom(stub_helper_atom.getSymbolIndex().?, global);
1591 const stub_atom = try self.createStubAtom(laptr_atom.getSymbolIndex().?);
1610 const stub_helper_atom_index = try self.createStubHelperAtom();
1611 const stub_helper_atom = self.getAtom(stub_helper_atom_index);
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);
15921616 self.stubs.items[stub_index].sym_index = stub_atom.getSymbolIndex().?;
15931617 self.markRelocsDirtyByTarget(global);
15941618 }
......@@ -1686,10 +1710,11 @@ pub fn resolveDyldStubBinder(self: *MachO) !void {
16861710
16871711 // Add dyld_stub_binder as the final GOT entry.
16881712 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);
16901715 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);
16931718}
16941719
16951720pub fn deinit(self: *MachO) void {
......@@ -1699,9 +1724,9 @@ pub fn deinit(self: *MachO) void {
16991724 if (self.llvm_object) |llvm_object| llvm_object.destroy(gpa);
17001725 }
17011726
1702 if (self.d_sym) |*d_sym| {
1703 d_sym.deinit();
1704 }
1727 // if (self.d_sym) |*d_sym| {
1728 // d_sym.deinit();
1729 // }
17051730
17061731 self.got_entries.deinit(gpa);
17071732 self.got_entries_free_list.deinit(gpa);
......@@ -1739,12 +1764,12 @@ pub fn deinit(self: *MachO) void {
17391764 }
17401765 self.sections.deinit(gpa);
17411766
1742 for (self.managed_atoms.items) |atom| {
1743 gpa.destroy(atom);
1744 }
1745 self.managed_atoms.deinit(gpa);
1767 self.atoms.deinit(gpa);
17461768
17471769 if (self.base.options.module) |_| {
1770 for (self.decls.values()) |*m| {
1771 m.exports.deinit(gpa);
1772 }
17481773 self.decls.deinit(gpa);
17491774 } else {
17501775 assert(self.decls.count() == 0);
......@@ -1778,14 +1803,15 @@ pub fn deinit(self: *MachO) void {
17781803 self.lazy_bindings.deinit(gpa);
17791804}
17801805
1781fn freeAtom(self: *MachO, atom: *Atom) void {
1782 log.debug("freeAtom {*}", .{atom});
1806fn freeAtom(self: *MachO, atom_index: Atom.Index) void {
1807 log.debug("freeAtom {d}", .{atom_index});
17831808
17841809 const gpa = self.base.allocator;
17851810
17861811 // 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);
17891815 const sect_id = atom.getSymbol(self).n_sect - 1;
17901816 const free_list = &self.sections.items(.free_list)[sect_id];
17911817 var already_have_free_list_node = false;
......@@ -1793,45 +1819,46 @@ fn freeAtom(self: *MachO, atom: *Atom) void {
17931819 var i: usize = 0;
17941820 // TODO turn free_list into a hash map
17951821 while (i < free_list.items.len) {
1796 if (free_list.items[i] == atom) {
1822 if (free_list.items[i] == atom_index) {
17971823 _ = free_list.swapRemove(i);
17981824 continue;
17991825 }
1800 if (free_list.items[i] == atom.prev) {
1826 if (free_list.items[i] == atom.prev_index) {
18011827 already_have_free_list_node = true;
18021828 }
18031829 i += 1;
18041830 }
18051831 }
18061832
1807 const maybe_last_atom = &self.sections.items(.last_atom)[sect_id];
1808 if (maybe_last_atom.*) |last_atom| {
1809 if (last_atom == atom) {
1810 if (atom.prev) |prev| {
1833 const maybe_last_atom_index = &self.sections.items(.last_atom_index)[sect_id];
1834 if (maybe_last_atom_index.*) |last_atom_index| {
1835 if (last_atom_index == atom_index) {
1836 if (atom.prev_index) |prev_index| {
18111837 // TODO shrink the section size here
1812 maybe_last_atom.* = prev;
1838 maybe_last_atom_index.* = prev_index;
18131839 } else {
1814 maybe_last_atom.* = null;
1840 maybe_last_atom_index.* = null;
18151841 }
18161842 }
18171843 }
18181844
1819 if (atom.prev) |prev| {
1820 prev.next = atom.next;
1845 if (atom.prev_index) |prev_index| {
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)) {
18231850 // The free list is heuristics, it doesn't have to be perfect, so we can ignore
18241851 // the OOM here.
1825 free_list.append(gpa, prev) catch {};
1852 free_list.append(gpa, prev_index) catch {};
18261853 }
18271854 } else {
1828 atom.prev = null;
1855 self.getAtomPtr(atom_index).prev_index = null;
18291856 }
18301857
1831 if (atom.next) |next| {
1832 next.prev = atom.prev;
1858 if (atom.next_index) |next_index| {
1859 self.getAtomPtr(next_index).prev_index = atom.prev_index;
18331860 } else {
1834 atom.next = null;
1861 self.getAtomPtr(atom_index).next_index = null;
18351862 }
18361863
18371864 // 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 {
18491876 };
18501877 _ = self.got_entries_table.remove(got_target);
18511878
1852 if (self.d_sym) |*d_sym| {
1853 d_sym.swapRemoveRelocs(sym_index);
1854 }
1879 // if (self.d_sym) |*d_sym| {
1880 // d_sym.swapRemoveRelocs(sym_index);
1881 // }
18551882
18561883 log.debug(" adding GOT index {d} to free list (target local@{d})", .{ got_index, sym_index });
18571884 }
......@@ -1859,27 +1886,28 @@ fn freeAtom(self: *MachO, atom: *Atom) void {
18591886 self.locals.items[sym_index].n_type = 0;
18601887 _ = self.atom_by_index_table.remove(sym_index);
18611888 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| {
1865 d_sym.dwarf.freeAtom(&atom.dbg_info_atom);
1866 }
1891 // if (self.d_sym) |*d_sym| {
1892 // d_sym.dwarf.freeAtom(&atom.dbg_info_atom);
1893 // }
18671894}
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 {
18701897 _ = self;
1871 _ = atom;
1898 _ = atom_index;
18721899 _ = new_block_size;
18731900 // TODO check the new capacity, and if it crosses the size threshold into a big enough
18741901 // capacity, insert a free list node for it.
18751902}
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);
18781906 const sym = atom.getSymbol(self);
18791907 const align_ok = mem.alignBackwardGeneric(u64, sym.n_value, alignment) == sym.n_value;
18801908 const need_realloc = !align_ok or new_atom_size > atom.capacity(self);
18811909 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);
18831911}
18841912
18851913pub fn allocateSymbol(self: *MachO) !u32 {
......@@ -1986,31 +2014,29 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv
19862014
19872015 const decl_index = func.owner_decl;
19882016 const decl = module.declPtr(decl_index);
1989 const atom = &decl.link.macho;
1990 try atom.ensureInitialized(self);
1991 const gop = try self.decls.getOrPut(self.base.allocator, decl_index);
1992 if (gop.found_existing) {
1993 self.freeUnnamedConsts(decl_index);
1994 self.freeRelocationsForAtom(atom);
1995 } else {
1996 gop.value_ptr.* = null;
1997 }
2017
2018 const atom_index = try self.getOrCreateAtomForDecl(decl_index);
2019 self.freeUnnamedConsts(decl_index);
2020 Atom.freeRelocations(self, atom_index);
2021
2022 const atom = self.getAtom(atom_index);
2023 _ = atom;
19982024
19992025 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
20002026 defer code_buffer.deinit();
20012027
2002 var decl_state = if (self.d_sym) |*d_sym|
2003 try d_sym.dwarf.initDeclState(module, decl_index)
2004 else
2005 null;
2006 defer if (decl_state) |*ds| ds.deinit();
2028 // var decl_state = if (self.d_sym) |*d_sym|
2029 // try d_sym.dwarf.initDeclState(module, decl_index)
2030 // else
2031 // null;
2032 // defer if (decl_state) |*ds| ds.deinit();
20072033
2008 const res = if (decl_state) |*ds|
2009 try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .{
2010 .dwarf = ds,
2011 })
2012 else
2013 try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .none);
2034 // const res = if (decl_state) |*ds|
2035 // try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .{
2036 // .dwarf = ds,
2037 // })
2038 // else
2039 const res = try codegen.generateFunction(&self.base, decl.srcLoc(), func, air, liveness, &code_buffer, .none);
20142040
20152041 const code = switch (res) {
20162042 .ok => code_buffer.items,
......@@ -2022,16 +2048,11 @@ pub fn updateFunc(self: *MachO, module: *Module, func: *Module.Fn, air: Air, liv
20222048 };
20232049
20242050 const addr = try self.updateDeclCode(decl_index, code);
2051 _ = addr;
20252052
2026 if (decl_state) |*ds| {
2027 try self.d_sym.?.dwarf.commitDeclState(
2028 module,
2029 decl_index,
2030 addr,
2031 decl.link.macho.size,
2032 ds,
2033 );
2034 }
2053 // if (decl_state) |*ds| {
2054 // try self.d_sym.?.dwarf.commitDeclState(module, decl_index, addr, atom.size, ds);
2055 // }
20352056
20362057 // Since we updated the vaddr and the size, each corresponding export symbol also
20372058 // needs to be updated.
......@@ -2065,11 +2086,8 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu
20652086
20662087 log.debug("allocating symbol indexes for {?s}", .{name});
20672088
2068 const atom = try gpa.create(Atom);
2069 errdefer gpa.destroy(atom);
2070 atom.* = Atom.empty;
2071 try atom.ensureInitialized(self);
2072 try self.managed_atoms.append(gpa, atom);
2089 const atom_index = try self.createAtom();
2090 const atom = self.getAtomPtr(atom_index);
20732091
20742092 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), typed_value, &code_buffer, .none, .{
20752093 .parent_atom_index = atom.getSymbolIndex().?,
......@@ -2088,21 +2106,21 @@ pub fn lowerUnnamedConst(self: *MachO, typed_value: TypedValue, decl_index: Modu
20882106 atom.size = code.len;
20892107 atom.alignment = required_alignment;
20902108 // 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);
20922110 const sect_id = self.data_const_section_index.?;
20932111 const symbol = atom.getSymbolPtr(self);
20942112 symbol.n_strx = name_str_index;
20952113 symbol.n_type = macho.N_SECT;
20962114 symbol.n_sect = sect_id + 1;
2097 symbol.n_value = try self.allocateAtom(atom, code.len, required_alignment);
2098 errdefer self.freeAtom(atom);
2115 symbol.n_value = try self.allocateAtom(atom_index, code.len, required_alignment);
2116 errdefer self.freeAtom(atom_index);
20992117
2100 try unnamed_consts.append(gpa, atom);
2118 try unnamed_consts.append(gpa, atom_index);
21012119
21022120 log.debug("allocated atom for {?s} at 0x{x}", .{ name, symbol.n_value });
21032121 log.debug(" (required alignment 0x{x})", .{required_alignment});
21042122
2105 try self.writeAtom(atom, code);
2123 try self.writeAtom(atom_index, code);
21062124
21072125 return atom.getSymbolIndex().?;
21082126}
......@@ -2129,41 +2147,36 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index)
21292147 }
21302148 }
21312149
2132 const atom = &decl.link.macho;
2133 try atom.ensureInitialized(self);
2134 const gop = try self.decls.getOrPut(self.base.allocator, decl_index);
2135 if (gop.found_existing) {
2136 self.freeRelocationsForAtom(atom);
2137 } else {
2138 gop.value_ptr.* = null;
2139 }
2150 const atom_index = try self.getOrCreateAtomForDecl(decl_index);
2151 Atom.freeRelocations(self, atom_index);
2152 const atom = self.getAtom(atom_index);
21402153
21412154 var code_buffer = std.ArrayList(u8).init(self.base.allocator);
21422155 defer code_buffer.deinit();
21432156
2144 var decl_state: ?Dwarf.DeclState = if (self.d_sym) |*d_sym|
2145 try d_sym.dwarf.initDeclState(module, decl_index)
2146 else
2147 null;
2148 defer if (decl_state) |*ds| ds.deinit();
2157 // var decl_state: ?Dwarf.DeclState = if (self.d_sym) |*d_sym|
2158 // try d_sym.dwarf.initDeclState(module, decl_index)
2159 // else
2160 // null;
2161 // defer if (decl_state) |*ds| ds.deinit();
21492162
21502163 const decl_val = if (decl.val.castTag(.variable)) |payload| payload.data.init else decl.val;
2151 const res = if (decl_state) |*ds|
2152 try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
2153 .ty = decl.ty,
2154 .val = decl_val,
2155 }, &code_buffer, .{
2156 .dwarf = ds,
2157 }, .{
2158 .parent_atom_index = decl.link.macho.getSymbolIndex().?,
2159 })
2160 else
2161 try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
2162 .ty = decl.ty,
2163 .val = decl_val,
2164 }, &code_buffer, .none, .{
2165 .parent_atom_index = decl.link.macho.getSymbolIndex().?,
2166 });
2164 // const res = if (decl_state) |*ds|
2165 // try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
2166 // .ty = decl.ty,
2167 // .val = decl_val,
2168 // }, &code_buffer, .{
2169 // .dwarf = ds,
2170 // }, .{
2171 // .parent_atom_index = atom.getSymbolIndex().?,
2172 // })
2173 // else
2174 const res = try codegen.generateSymbol(&self.base, decl.srcLoc(), .{
2175 .ty = decl.ty,
2176 .val = decl_val,
2177 }, &code_buffer, .none, .{
2178 .parent_atom_index = atom.getSymbolIndex().?,
2179 });
21672180
21682181 const code = switch (res) {
21692182 .ok => code_buffer.items,
......@@ -2174,23 +2187,31 @@ pub fn updateDecl(self: *MachO, module: *Module, decl_index: Module.Decl.Index)
21742187 },
21752188 };
21762189 const addr = try self.updateDeclCode(decl_index, code);
2190 _ = addr;
21772191
2178 if (decl_state) |*ds| {
2179 try self.d_sym.?.dwarf.commitDeclState(
2180 module,
2181 decl_index,
2182 addr,
2183 decl.link.macho.size,
2184 ds,
2185 );
2186 }
2192 // if (decl_state) |*ds| {
2193 // try self.d_sym.?.dwarf.commitDeclState(module, decl_index, addr, atom.size, ds);
2194 // }
21872195
21882196 // Since we updated the vaddr and the size, each corresponding export symbol also
21892197 // needs to be updated.
21902198 try self.updateDeclExports(module, decl_index, module.getDeclExports(decl_index));
21912199}
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);
21942215 const ty = decl.ty;
21952216 const val = decl.val;
21962217 const zig_ty = ty.zigTypeTag();
......@@ -2341,13 +2362,11 @@ fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []const u8)
23412362 const sym_name = try decl.getFullyQualifiedName(mod);
23422363 defer self.base.allocator.free(sym_name);
23432364
2344 const atom = &decl.link.macho;
2345 const sym_index = atom.getSymbolIndex().?; // Atom was not initialized
2346 const decl_ptr = self.decls.getPtr(decl_index).?;
2347 if (decl_ptr.* == null) {
2348 decl_ptr.* = self.getDeclOutputSection(decl);
2349 }
2350 const sect_id = decl_ptr.*.?;
2365 const decl_metadata = self.decls.get(decl_index).?;
2366 const atom_index = decl_metadata.atom;
2367 const atom = self.getAtom(atom_index);
2368 const sym_index = atom.getSymbolIndex().?;
2369 const sect_id = decl_metadata.section;
23512370 const code_len = code.len;
23522371
23532372 if (atom.size != 0) {
......@@ -2357,11 +2376,11 @@ fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []const u8)
23572376 sym.n_sect = sect_id + 1;
23582377 sym.n_desc = 0;
23592378
2360 const capacity = decl.link.macho.capacity(self);
2379 const capacity = atom.capacity(self);
23612380 const need_realloc = code_len > capacity or !mem.isAlignedGeneric(u64, sym.n_value, required_alignment);
23622381
23632382 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);
23652384 log.debug("growing {s} and moving from 0x{x} to 0x{x}", .{ sym_name, sym.n_value, vaddr });
23662385 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)
23692388 sym.n_value = vaddr;
23702389 log.debug(" (updating GOT entry)", .{});
23712390 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).?;
23732392 self.markRelocsDirtyByTarget(got_target);
2374 try self.writePtrWidthAtom(got_atom);
2393 try self.writePtrWidthAtom(got_atom_index);
23752394 }
23762395 } else if (code_len < atom.size) {
2377 self.shrinkAtom(atom, code_len);
2378 } else if (atom.next == null) {
2396 self.shrinkAtom(atom_index, code_len);
2397 } else if (atom.next_index == null) {
23792398 const header = &self.sections.items(.header)[sect_id];
23802399 const segment = self.getSegment(sect_id);
23812400 const needed_size = (sym.n_value + code_len) - segment.vmaddr;
23822401 header.size = needed_size;
23832402 }
2384 atom.size = code_len;
2403 self.getAtomPtr(atom_index).size = code_len;
23852404 } else {
23862405 const name_str_index = try self.strtab.insert(gpa, sym_name);
23872406 const sym = atom.getSymbolPtr(self);
......@@ -2390,33 +2409,36 @@ fn updateDeclCode(self: *MachO, decl_index: Module.Decl.Index, code: []const u8)
23902409 sym.n_sect = sect_id + 1;
23912410 sym.n_desc = 0;
23922411
2393 const vaddr = try self.allocateAtom(atom, code_len, required_alignment);
2394 errdefer self.freeAtom(atom);
2412 const vaddr = try self.allocateAtom(atom_index, code_len, required_alignment);
2413 errdefer self.freeAtom(atom_index);
23952414
23962415 log.debug("allocated atom for {s} at 0x{x}", .{ sym_name, vaddr });
23972416 log.debug(" (required alignment 0x{x})", .{required_alignment});
23982417
2399 atom.size = code_len;
2418 self.getAtomPtr(atom_index).size = code_len;
24002419 sym.n_value = vaddr;
24012420
24022421 const got_target = SymbolWithLoc{ .sym_index = sym_index, .file = null };
24032422 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);
24052425 self.got_entries.items[got_index].sym_index = got_atom.getSymbolIndex().?;
2406 try self.writePtrWidthAtom(got_atom);
2426 try self.writePtrWidthAtom(got_atom_index);
24072427 }
24082428
24092429 self.markRelocsDirtyByTarget(atom.getSymbolWithLoc());
2410 try self.writeAtom(atom, code);
2430 try self.writeAtom(atom_index, code);
24112431
24122432 return atom.getSymbol(self).n_value;
24132433}
24142434
24152435pub fn updateDeclLineNumber(self: *MachO, module: *Module, decl: *const Module.Decl) !void {
2436 _ = decl;
2437 _ = self;
24162438 _ = module;
2417 if (self.d_sym) |*d_sym| {
2418 try d_sym.dwarf.updateDeclLineNumber(decl);
2419 }
2439 // if (self.d_sym) |*d_sym| {
2440 // try d_sym.dwarf.updateDeclLineNumber(decl);
2441 // }
24202442}
24212443
24222444pub fn updateDeclExports(
......@@ -2432,22 +2454,17 @@ pub fn updateDeclExports(
24322454 if (self.llvm_object) |llvm_object|
24332455 return llvm_object.updateDeclExports(module, decl_index, exports);
24342456 }
2457
24352458 const tracy = trace(@src());
24362459 defer tracy.end();
24372460
24382461 const gpa = self.base.allocator;
24392462
24402463 const decl = module.declPtr(decl_index);
2441 const atom = &decl.link.macho;
2442
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
2464 const atom_index = try self.getOrCreateAtomForDecl(decl_index);
2465 const atom = self.getAtom(atom_index);
24502466 const decl_sym = atom.getSymbol(self);
2467 const decl_metadata = self.decls.getPtr(decl_index).?;
24512468
24522469 for (exports) |exp| {
24532470 const exp_name = try std.fmt.allocPrint(gpa, "_{s}", .{exp.options.name});
......@@ -2485,9 +2502,9 @@ pub fn updateDeclExports(
24852502 continue;
24862503 }
24872504
2488 const sym_index = exp.link.macho.sym_index orelse blk: {
2505 const sym_index = decl_metadata.getExport(self, exp_name) orelse blk: {
24892506 const sym_index = try self.allocateSymbol();
2490 exp.link.macho.sym_index = sym_index;
2507 try decl_metadata.exports.append(gpa, sym_index);
24912508 break :blk sym_index;
24922509 };
24932510 const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null };
......@@ -2535,16 +2552,18 @@ pub fn updateDeclExports(
25352552 }
25362553}
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 {
25392556 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
25422559 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 };
25452565 const sym = self.getSymbolPtr(sym_loc);
2546 const sym_name = self.getSymbolName(sym_loc);
2547 log.debug("deleting export '{s}'", .{sym_name});
2566 log.debug("deleting export '{s}'", .{exp_name});
25482567 assert(sym.sect() and sym.ext());
25492568 sym.* = .{
25502569 .n_strx = 0,
......@@ -2553,9 +2572,9 @@ pub fn deleteExport(self: *MachO, exp: Export) void {
25532572 .n_desc = 0,
25542573 .n_value = 0,
25552574 };
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| {
25592578 defer gpa.free(entry.key);
25602579 self.globals_free_list.append(gpa, entry.value) catch {};
25612580 self.globals.items[entry.value] = .{
......@@ -2563,17 +2582,8 @@ pub fn deleteExport(self: *MachO, exp: Export) void {
25632582 .file = null,
25642583 };
25652584 }
2566}
25672585
2568fn freeRelocationsForAtom(self: *MachO, atom: *Atom) void {
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);
2586 sym_index.* = 0;
25772587}
25782588
25792589fn freeUnnamedConsts(self: *MachO, decl_index: Module.Decl.Index) void {
......@@ -2595,28 +2605,22 @@ pub fn freeDecl(self: *MachO, decl_index: Module.Decl.Index) void {
25952605 log.debug("freeDecl {*}", .{decl});
25962606
25972607 if (self.decls.fetchSwapRemove(decl_index)) |kv| {
2598 if (kv.value) |_| {
2599 self.freeAtom(&decl.link.macho);
2600 self.freeUnnamedConsts(decl_index);
2601 }
2608 self.freeAtom(kv.value.atom);
2609 self.freeUnnamedConsts(decl_index);
26022610 }
26032611
2604 if (self.d_sym) |*d_sym| {
2605 d_sym.dwarf.freeDecl(decl);
2606 }
2612 // if (self.d_sym) |*d_sym| {
2613 // d_sym.dwarf.freeDecl(decl);
2614 // }
26072615}
26082616
26092617pub 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
26132618 assert(self.llvm_object == null);
26142619
2615 try decl.link.macho.ensureInitialized(self);
2616 const sym_index = decl.link.macho.getSymbolIndex().?;
2617
2618 const atom = self.getAtomForSymbol(.{ .sym_index = reloc_info.parent_atom_index, .file = null }).?;
2619 try atom.addRelocation(self, .{
2620 const this_atom_index = try self.getOrCreateAtomForDecl(decl_index);
2621 const sym_index = self.getAtom(this_atom_index).getSymbolIndex().?;
2622 const atom_index = self.getAtomIndexForSymbol(.{ .sym_index = reloc_info.parent_atom_index, .file = null }).?;
2623 try Atom.addRelocation(self, atom_index, .{
26202624 .type = switch (self.base.options.target.cpu.arch) {
26212625 .aarch64 => @enumToInt(macho.reloc_type_arm64.ARM64_RELOC_UNSIGNED),
26222626 .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
26282632 .pcrel = false,
26292633 .length = 3,
26302634 });
2631 try atom.addRebase(self, @intCast(u32, reloc_info.offset));
2635 try Atom.addRebase(self, atom_index, @intCast(u32, reloc_info.offset));
26322636
26332637 return 0;
26342638}
......@@ -2860,34 +2864,36 @@ fn moveSectionInVirtualMemory(self: *MachO, sect_id: u8, needed_size: u64) !void
28602864 // TODO: enforce order by increasing VM addresses in self.sections container.
28612865 for (self.sections.items(.header)[sect_id + 1 ..]) |*next_header, next_sect_id| {
28622866 const index = @intCast(u8, sect_id + 1 + next_sect_id);
2863 const maybe_last_atom = &self.sections.items(.last_atom)[index];
28642867 const next_segment = self.getSegmentPtr(index);
28652868 next_header.addr += diff;
28662869 next_segment.vmaddr += diff;
28672870
2868 if (maybe_last_atom.*) |last_atom| {
2869 var atom = last_atom;
2871 const maybe_last_atom_index = &self.sections.items(.last_atom_index)[index];
2872 if (maybe_last_atom_index.*) |last_atom_index| {
2873 var atom_index = last_atom_index;
28702874 while (true) {
2875 const atom = self.getAtom(atom_index);
28712876 const sym = atom.getSymbolPtr(self);
28722877 sym.n_value += diff;
28732878
2874 if (atom.prev) |prev| {
2875 atom = prev;
2879 if (atom.prev_index) |prev_index| {
2880 atom_index = prev_index;
28762881 } else break;
28772882 }
28782883 }
28792884 }
28802885}
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 {
28832888 const tracy = trace(@src());
28842889 defer tracy.end();
28852890
2891 const atom = self.getAtom(atom_index);
28862892 const sect_id = atom.getSymbol(self).n_sect - 1;
28872893 const segment = self.getSegmentPtr(sect_id);
28882894 const header = &self.sections.items(.header)[sect_id];
28892895 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];
28912897 const requires_padding = blk: {
28922898 if (!header.isCode()) break :blk false;
28932899 if (header.isSymbolStubs()) break :blk false;
......@@ -2901,7 +2907,7 @@ fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64) !
29012907 // It would be simpler to do it inside the for loop below, but that would cause a
29022908 // problem if an error was returned later in the function. So this action
29032909 // 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;
29052911 var free_list_removal: ?usize = null;
29062912
29072913 // 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) !
29092915 var vaddr = blk: {
29102916 var i: usize = 0;
29112917 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);
29132920 // We now have a pointer to a live atom that has too much capacity.
29142921 // Is it enough that we could fit this new atom?
29152922 const sym = big_atom.getSymbol(self);
......@@ -2937,30 +2944,35 @@ fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64) !
29372944 const keep_free_list_node = remaining_capacity >= min_text_capacity;
29382945
29392946 // Set up the metadata to be updated, after errors are no longer possible.
2940 atom_placement = big_atom;
2947 atom_placement = big_atom_index;
29412948 if (!keep_free_list_node) {
29422949 free_list_removal = i;
29432950 }
29442951 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);
29462954 const last_symbol = last.getSymbol(self);
29472955 const ideal_capacity = if (requires_padding) padToIdeal(last.size) else last.size;
29482956 const ideal_capacity_end_vaddr = last_symbol.n_value + ideal_capacity;
29492957 const new_start_vaddr = mem.alignForwardGeneric(u64, ideal_capacity_end_vaddr, alignment);
2950 atom_placement = last;
2958 atom_placement = last_index;
29512959 break :blk new_start_vaddr;
29522960 } else {
29532961 break :blk mem.alignForwardGeneric(u64, segment.vmaddr, alignment);
29542962 }
29552963 };
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;
29582969 if (expand_section) {
29592970 const sect_capacity = self.allocatedSize(header.offset);
29602971 const needed_size = (vaddr + new_atom_size) - segment.vmaddr;
29612972 if (needed_size > sect_capacity) {
29622973 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);
29642976 const sym = last_atom.getSymbol(self);
29652977 break :blk (sym.n_value + last_atom.size) - segment.vmaddr;
29662978 } else 0;
......@@ -2992,7 +3004,7 @@ fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64) !
29923004 header.size = needed_size;
29933005 segment.filesize = mem.alignForwardGeneric(u64, needed_size, self.page_size);
29943006 segment.vmsize = mem.alignForwardGeneric(u64, needed_size, self.page_size);
2995 maybe_last_atom.* = atom;
3007 maybe_last_atom_index.* = atom_index;
29963008
29973009 self.segment_table_dirty = true;
29983010 }
......@@ -3002,20 +3014,25 @@ fn allocateAtom(self: *MachO, atom: *Atom, new_atom_size: u64, alignment: u64) !
30023014 header.@"align" = align_pow;
30033015 }
30043016
3005 if (atom.prev) |prev| {
3006 prev.next = atom.next;
3017 if (atom.prev_index) |prev_index| {
3018 const prev = self.getAtomPtr(prev_index);
3019 prev.next_index = atom.next_index;
30073020 }
3008 if (atom.next) |next| {
3009 next.prev = atom.prev;
3021 if (atom.next_index) |next_index| {
3022 const next = self.getAtomPtr(next_index);
3023 next.prev_index = atom.prev_index;
30103024 }
30113025
3012 if (atom_placement) |big_atom| {
3013 atom.prev = big_atom;
3014 atom.next = big_atom.next;
3015 big_atom.next = atom;
3026 if (atom_placement) |big_atom_index| {
3027 const big_atom = self.getAtomPtr(big_atom_index);
3028 const atom_ptr = self.getAtomPtr(atom_index);
3029 atom_ptr.prev_index = big_atom_index;
3030 atom_ptr.next_index = big_atom.next_index;
3031 big_atom.next_index = atom_index;
30163032 } else {
3017 atom.prev = null;
3018 atom.next = null;
3033 const atom_ptr = self.getAtomPtr(atom_index);
3034 atom_ptr.prev_index = null;
3035 atom_ptr.next_index = null;
30193036 }
30203037 if (free_list_removal) |i| {
30213038 _ = free_list.swapRemove(i);
......@@ -3155,7 +3172,8 @@ fn collectRebaseData(self: *MachO, rebase: *Rebase) !void {
31553172 const gpa = self.base.allocator;
31563173 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);
31593177 log.debug(" ATOM(%{?d}, '{s}')", .{ atom.getSymbolIndex(), atom.getName(self) });
31603178
31613179 const sym = atom.getSymbol(self);
......@@ -3184,7 +3202,8 @@ fn collectBindData(self: *MachO, bind: anytype, raw_bindings: anytype) !void {
31843202 const gpa = self.base.allocator;
31853203 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);
31883207 log.debug(" ATOM(%{?d}, '{s}')", .{ atom.getSymbolIndex(), atom.getName(self) });
31893208
31903209 const sym = atom.getSymbol(self);
......@@ -3359,7 +3378,7 @@ fn populateLazyBindOffsetsInStubHelper(self: *MachO, lazy_bind: LazyBind) !void
33593378 if (lazy_bind.size() == 0) return;
33603379
33613380 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
33643383 const section = self.sections.get(stub_helper_section_index);
33653384
......@@ -3369,10 +3388,11 @@ fn populateLazyBindOffsetsInStubHelper(self: *MachO, lazy_bind: LazyBind) !void
33693388 else => unreachable,
33703389 };
33713390 const header = section.header;
3372 var atom = section.last_atom.?;
3391 var atom_index = section.last_atom_index.?;
33733392
33743393 var index: usize = lazy_bind.offsets.items.len;
33753394 while (index > 0) : (index -= 1) {
3395 const atom = self.getAtom(atom_index);
33763396 const sym = atom.getSymbol(self);
33773397 const file_offset = header.offset + sym.n_value - header.addr + stub_offset;
33783398 const bind_offset = lazy_bind.offsets.items[index - 1];
......@@ -3385,7 +3405,7 @@ fn populateLazyBindOffsetsInStubHelper(self: *MachO, lazy_bind: LazyBind) !void
33853405
33863406 try self.base.file.?.pwriteAll(mem.asBytes(&bind_offset), file_offset);
33873407
3388 atom = atom.prev.?;
3408 atom_index = atom.prev_index.?;
33893409 }
33903410}
33913411
......@@ -3828,25 +3848,35 @@ pub fn getOrPutGlobalPtr(self: *MachO, name: []const u8) !GetOrPutGlobalPtrResul
38283848 return GetOrPutGlobalPtrResult{ .found_existing = false, .value_ptr = ptr };
38293849}
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
38313861/// Returns atom if there is an atom referenced by the symbol described by `sym_with_loc` descriptor.
38323862/// 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 {
38343864 assert(sym_with_loc.file == null);
38353865 return self.atom_by_index_table.get(sym_with_loc.sym_index);
38363866}
38373867
38383868/// Returns GOT atom that references `sym_with_loc` if one exists.
38393869/// Returns null otherwise.
3840pub fn getGotAtomForSymbol(self: *MachO, sym_with_loc: SymbolWithLoc) ?*Atom {
3870pub fn getGotAtomIndexForSymbol(self: *MachO, sym_with_loc: SymbolWithLoc) ?Atom.Index {
38413871 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);
38433873}
38443874
38453875/// Returns stubs atom that references `sym_with_loc` if one exists.
38463876/// Returns null otherwise.
3847pub fn getStubsAtomForSymbol(self: *MachO, sym_with_loc: SymbolWithLoc) ?*Atom {
3877pub fn getStubsAtomIndexForSymbol(self: *MachO, sym_with_loc: SymbolWithLoc) ?Atom.Index {
38483878 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);
38503880}
38513881
38523882/// Returns symbol location corresponding to the set entrypoint.
......@@ -4232,26 +4262,31 @@ pub fn logAtoms(self: *MachO) void {
42324262 log.debug("atoms:", .{});
42334263
42344264 const slice = self.sections.slice();
4235 for (slice.items(.last_atom)) |last, i| {
4236 var atom = last orelse continue;
4265 for (slice.items(.last_atom_index)) |last_atom_index, i| {
4266 var atom_index = last_atom_index orelse continue;
42374267 const header = slice.items(.header)[i];
42384268
4239 while (atom.prev) |prev| {
4240 atom = prev;
4269 while (true) {
4270 const atom = self.getAtom(atom_index);
4271 if (atom.prev_index) |prev_index| {
4272 atom_index = prev_index;
4273 } else break;
42414274 }
42424275
42434276 log.debug("{s},{s}", .{ header.segName(), header.sectName() });
42444277
42454278 while (true) {
4246 self.logAtom(atom);
4247 if (atom.next) |next| {
4248 atom = next;
4279 self.logAtom(atom_index);
4280 const atom = self.getAtom(atom_index);
4281 if (atom.next_index) |next_index| {
4282 atom_index = next_index;
42494283 } else break;
42504284 }
42514285 }
42524286}
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);
42554290 const sym = atom.getSymbol(self);
42564291 const sym_name = atom.getName(self);
42574292 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,
3939alignment: u32,
4040
4141/// Points to the previous and next neighbours
42next: ?*Atom,
43prev: ?*Atom,
42/// TODO use the same trick as with symbols: reserve index 0 as null atom
43next_index: ?Atom.Index,
44prev_index: ?Atom.Index,
4445
4546dbg_info_atom: Dwarf.Atom,
4647
48pub const Index = u32;
49
4750pub const Binding = struct {
4851 target: SymbolWithLoc,
4952 offset: u64,
......@@ -54,22 +57,6 @@ pub const SymbolAtOffset = struct {
5457 offset: u64,
5558};
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
7360pub fn getSymbolIndex(self: Atom) ?u32 {
7461 if (self.sym_index == 0) return null;
7562 return self.sym_index;
......@@ -108,7 +95,8 @@ pub fn getName(self: Atom, macho_file: *MachO) []const u8 {
10895/// this calculation.
10996pub fn capacity(self: Atom, macho_file: *MachO) u64 {
11097 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);
112100 const next_sym = next.getSymbol(macho_file);
113101 return next_sym.n_value - self_sym.n_value;
114102 } else {
......@@ -120,7 +108,8 @@ pub fn capacity(self: Atom, macho_file: *MachO) u64 {
120108
121109pub fn freeListEligible(self: Atom, macho_file: *MachO) bool {
122110 // 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);
124113 const self_sym = self.getSymbol(macho_file);
125114 const next_sym = next.getSymbol(macho_file);
126115 const cap = next_sym.n_value - self_sym.n_value;
......@@ -130,19 +119,19 @@ pub fn freeListEligible(self: Atom, macho_file: *MachO) bool {
130119 return surplus >= MachO.min_text_capacity;
131120}
132121
133pub fn addRelocation(self: *Atom, macho_file: *MachO, reloc: Relocation) !void {
134 return self.addRelocations(macho_file, 1, .{reloc});
122pub fn addRelocation(macho_file: *MachO, atom_index: Atom.Index, reloc: Relocation) !void {
123 return addRelocations(macho_file, atom_index, 1, .{reloc});
135124}
136125
137126pub fn addRelocations(
138 self: *Atom,
139127 macho_file: *MachO,
128 atom_index: Atom.Index,
140129 comptime count: comptime_int,
141130 relocs: [count]Relocation,
142131) !void {
143132 const gpa = macho_file.base.allocator;
144133 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);
146135 if (!gop.found_existing) {
147136 gop.value_ptr.* = .{};
148137 }
......@@ -156,56 +145,72 @@ pub fn addRelocations(
156145 }
157146}
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 {
160149 const gpa = macho_file.base.allocator;
161 log.debug(" (adding rebase at offset 0x{x} in %{?d})", .{ offset, self.getSymbolIndex() });
162 const gop = try macho_file.rebases.getOrPut(gpa, self);
150 const atom = macho_file.getAtom(atom_index);
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);
163153 if (!gop.found_existing) {
164154 gop.value_ptr.* = .{};
165155 }
166156 try gop.value_ptr.append(gpa, offset);
167157}
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 {
170160 const gpa = macho_file.base.allocator;
161 const atom = macho_file.getAtom(atom_index);
171162 log.debug(" (adding binding to symbol {s} at offset 0x{x} in %{?d})", .{
172163 macho_file.getSymbolName(binding.target),
173164 binding.offset,
174 self.getSymbolIndex(),
165 atom.getSymbolIndex(),
175166 });
176 const gop = try macho_file.bindings.getOrPut(gpa, self);
167 const gop = try macho_file.bindings.getOrPut(gpa, atom_index);
177168 if (!gop.found_existing) {
178169 gop.value_ptr.* = .{};
179170 }
180171 try gop.value_ptr.append(gpa, binding);
181172}
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 {
184175 const gpa = macho_file.base.allocator;
176 const atom = macho_file.getAtom(atom_index);
185177 log.debug(" (adding lazy binding to symbol {s} at offset 0x{x} in %{?d})", .{
186178 macho_file.getSymbolName(binding.target),
187179 binding.offset,
188 self.getSymbolIndex(),
180 atom.getSymbolIndex(),
189181 });
190 const gop = try macho_file.lazy_bindings.getOrPut(gpa, self);
182 const gop = try macho_file.lazy_bindings.getOrPut(gpa, atom_index);
191183 if (!gop.found_existing) {
192184 gop.value_ptr.* = .{};
193185 }
194186 try gop.value_ptr.append(gpa, binding);
195187}
196188
197pub fn resolveRelocations(self: *Atom, macho_file: *MachO) !void {
198 const relocs = macho_file.relocs.get(self) orelse return;
199 const source_sym = self.getSymbol(macho_file);
189pub fn resolveRelocations(macho_file: *MachO, atom_index: Atom.Index) !void {
190 const atom = macho_file.getAtom(atom_index);
191 const relocs = macho_file.relocs.get(atom_index) orelse return;
192 const source_sym = atom.getSymbol(macho_file);
200193 const source_section = macho_file.sections.get(source_sym.n_sect - 1).header;
201194 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
205198 for (relocs.items) |*reloc| {
206199 if (!reloc.dirty) continue;
207200
208 try reloc.resolve(self, macho_file, file_offset);
201 try reloc.resolve(macho_file, atom_index, file_offset);
209202 reloc.dirty = false;
210203 }
211204}
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 {
2929 }
3030}
3131
32pub fn getTargetAtom(self: Relocation, macho_file: *MachO) ?*Atom {
32pub fn getTargetAtomIndex(self: Relocation, macho_file: *MachO) ?Atom.Index {
3333 switch (macho_file.base.options.target.cpu.arch) {
3434 .aarch64 => switch (@intToEnum(macho.reloc_type_arm64, self.type)) {
3535 .ARM64_RELOC_GOT_LOAD_PAGE21,
3636 .ARM64_RELOC_GOT_LOAD_PAGEOFF12,
3737 .ARM64_RELOC_POINTER_TO_GOT,
38 => return macho_file.getGotAtomForSymbol(self.target),
38 => return macho_file.getGotAtomIndexForSymbol(self.target),
3939 else => {},
4040 },
4141 .x86_64 => switch (@intToEnum(macho.reloc_type_x86_64, self.type)) {
4242 .X86_64_RELOC_GOT,
4343 .X86_64_RELOC_GOT_LOAD,
44 => return macho_file.getGotAtomForSymbol(self.target),
44 => return macho_file.getGotAtomIndexForSymbol(self.target),
4545 else => {},
4646 },
4747 else => unreachable,
4848 }
49 if (macho_file.getStubsAtomForSymbol(self.target)) |stubs_atom| return stubs_atom;
50 return macho_file.getAtomForSymbol(self.target);
49 if (macho_file.getStubsAtomIndexForSymbol(self.target)) |stubs_atom| return stubs_atom;
50 return macho_file.getAtomIndexForSymbol(self.target);
5151}
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 {
5454 const arch = macho_file.base.options.target.cpu.arch;
55 const atom = macho_file.getAtom(atom_index);
5556 const source_sym = atom.getSymbol(macho_file);
5657 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);
5961 const target_addr = @intCast(i64, target_atom.getSymbol(macho_file).n_value) + self.addend;
6062
6163 log.debug(" ({x}: [() => 0x{x} ({s})) ({s})", .{