authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-07-10 16:28:00+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-07-18 09:13:08+02:00
log5b4c0cc1f9c4cb047064cffb70bc649b83681814
tree596178ec6c3d67e1e55c206ea197a2cee56fd821
parentf8b5466aef4131821b259aa5f0d6b9654a5595ce

macho: update ZigObject to use new ownership model


6 files changed, 321 insertions(+), 201 deletions(-)

src/arch/x86_64/Emit.zig+8-8
...@@ -51,12 +51,12 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -51,12 +51,12 @@ pub fn emitMir(emit: *Emit) Error!void {
51 });51 });
52 } else if (emit.lower.bin_file.cast(link.File.MachO)) |macho_file| {52 } else if (emit.lower.bin_file.cast(link.File.MachO)) |macho_file| {
53 // Add relocation to the decl.53 // Add relocation to the decl.
54 const atom = macho_file.getSymbol(symbol.atom_index).getAtom(macho_file).?;54 const zo = macho_file.getZigObject().?;
55 const sym_index = macho_file.getZigObject().?.symbols.items[symbol.sym_index];55 const atom = zo.symbols.items[symbol.atom_index].getAtom(macho_file).?;
56 try atom.addReloc(macho_file, .{56 try atom.addReloc(macho_file, .{
57 .tag = .@"extern",57 .tag = .@"extern",
58 .offset = end_offset - 4,58 .offset = end_offset - 4,
59 .target = sym_index,59 .target = symbol.sym_index,
60 .addend = 0,60 .addend = 0,
61 .type = .branch,61 .type = .branch,
62 .meta = .{62 .meta = .{
...@@ -160,11 +160,11 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -160,11 +160,11 @@ pub fn emitMir(emit: *Emit) Error!void {
160 .Obj => true,160 .Obj => true,
161 .Lib => emit.lower.link_mode == .static,161 .Lib => emit.lower.link_mode == .static,
162 };162 };
163 const atom = macho_file.getSymbol(data.atom_index).getAtom(macho_file).?;163 const zo = macho_file.getZigObject().?;
164 const sym_index = macho_file.getZigObject().?.symbols.items[data.sym_index];164 const atom = zo.symbols.items[data.atom_index].getAtom(macho_file).?;
165 const sym = macho_file.getSymbol(sym_index);165 const sym = zo.symbols.items[data.sym_index];
166 if (sym.flags.needs_zig_got and !is_obj_or_static_lib) {166 if (sym.flags.needs_zig_got and !is_obj_or_static_lib) {
167 _ = try sym.getOrCreateZigGotEntry(sym_index, macho_file);167 _ = try sym.getOrCreateZigGotEntry(data.sym_index, macho_file);
168 }168 }
169 const @"type": link.File.MachO.Relocation.Type = if (sym.flags.needs_zig_got and !is_obj_or_static_lib)169 const @"type": link.File.MachO.Relocation.Type = if (sym.flags.needs_zig_got and !is_obj_or_static_lib)
170 .zig_got_load170 .zig_got_load
...@@ -179,7 +179,7 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -179,7 +179,7 @@ pub fn emitMir(emit: *Emit) Error!void {
179 try atom.addReloc(macho_file, .{179 try atom.addReloc(macho_file, .{
180 .tag = .@"extern",180 .tag = .@"extern",
181 .offset = @intCast(end_offset - 4),181 .offset = @intCast(end_offset - 4),
182 .target = sym_index,182 .target = data.sym_index,
183 .addend = 0,183 .addend = 0,
184 .type = @"type",184 .type = @"type",
185 .meta = .{185 .meta = .{
src/arch/x86_64/Lower.zig+2-2
...@@ -425,8 +425,8 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)...@@ -425,8 +425,8 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
425 else => unreachable,425 else => unreachable,
426 };426 };
427 } else if (lower.bin_file.cast(link.File.MachO)) |macho_file| {427 } else if (lower.bin_file.cast(link.File.MachO)) |macho_file| {
428 const sym_index = macho_file.getZigObject().?.symbols.items[sym.sym_index];428 const zo = macho_file.getZigObject().?;
429 const macho_sym = macho_file.getSymbol(sym_index);429 const macho_sym = zo.symbols.items[sym.sym_index];
430430
431 if (macho_sym.flags.tlv) {431 if (macho_sym.flags.tlv) {
432 _ = lower.reloc(.{ .linker_reloc = sym });432 _ = lower.reloc(.{ .linker_reloc = sym });
src/codegen.zig+5-4
...@@ -901,15 +901,16 @@ fn genDeclRef(...@@ -901,15 +901,16 @@ fn genDeclRef(
901 }901 }
902 return GenResult.mcv(.{ .load_symbol = sym.esym_index });902 return GenResult.mcv(.{ .load_symbol = sym.esym_index });
903 } else if (lf.cast(link.File.MachO)) |macho_file| {903 } else if (lf.cast(link.File.MachO)) |macho_file| {
904 const zo = macho_file.getZigObject().?;
904 if (is_extern) {905 if (is_extern) {
905 const name = decl.name.toSlice(ip);906 const name = decl.name.toSlice(ip);
906 const lib_name = if (decl.getOwnedVariable(zcu)) |ov| ov.lib_name.toSlice(ip) else null;907 const lib_name = if (decl.getOwnedVariable(zcu)) |ov| ov.lib_name.toSlice(ip) else null;
907 const sym_index = try macho_file.getGlobalSymbol(name, lib_name);908 const sym_index = try macho_file.getGlobalSymbol(name, lib_name);
908 macho_file.getSymbol(macho_file.getZigObject().?.symbols.items[sym_index]).flags.needs_got = true;909 zo.symbols.items[sym_index].flags.needs_got = true;
909 return GenResult.mcv(.{ .load_symbol = sym_index });910 return GenResult.mcv(.{ .load_symbol = sym_index });
910 }911 }
911 const sym_index = try macho_file.getZigObject().?.getOrCreateMetadataForDecl(macho_file, decl_index);912 const sym_index = try zo.getOrCreateMetadataForDecl(macho_file, decl_index);
912 const sym = macho_file.getSymbol(sym_index);913 const sym = zo.symbols.items[sym_index];
913 if (is_threadlocal) {914 if (is_threadlocal) {
914 return GenResult.mcv(.{ .load_tlv = sym.nlist_idx });915 return GenResult.mcv(.{ .load_tlv = sym.nlist_idx });
915 }916 }
...@@ -956,7 +957,7 @@ fn genUnnamedConst(...@@ -956,7 +957,7 @@ fn genUnnamedConst(
956 },957 },
957 .macho => {958 .macho => {
958 const macho_file = lf.cast(link.File.MachO).?;959 const macho_file = lf.cast(link.File.MachO).?;
959 const local = macho_file.getSymbol(local_sym_index);960 const local = macho_file.getZigObject().?.symbols.items[local_sym_index];
960 return GenResult.mcv(.{ .load_symbol = local.nlist_idx });961 return GenResult.mcv(.{ .load_symbol = local.nlist_idx });
961 },962 },
962 .coff => {963 .coff => {
src/link/MachO.zig+13-9
...@@ -290,8 +290,10 @@ pub fn deinit(self: *MachO) void {...@@ -290,8 +290,10 @@ pub fn deinit(self: *MachO) void {
290 self.dylibs.deinit(gpa);290 self.dylibs.deinit(gpa);
291291
292 self.segments.deinit(gpa);292 self.segments.deinit(gpa);
293 for (self.sections.items(.atoms)) |*list| {293 for (self.sections.items(.atoms), self.sections.items(.out), self.sections.items(.thunks)) |*atoms, *out, *thnks| {
294 list.deinit(gpa);294 atoms.deinit(gpa);
295 out.deinit(gpa);
296 thnks.deinit(gpa);
295 }297 }
296 self.sections.deinit(gpa);298 self.sections.deinit(gpa);
297299
...@@ -561,8 +563,8 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n...@@ -561,8 +563,8 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n
561 if (self.getZigObject()) |zo| {563 if (self.getZigObject()) |zo| {
562 var has_resolve_error = false;564 var has_resolve_error = false;
563565
564 for (zo.atoms.items) |atom_index| {566 for (zo.getAtoms()) |atom_index| {
565 const atom = self.getAtom(atom_index) orelse continue;567 const atom = zo.getAtom(atom_index) orelse continue;
566 if (!atom.flags.alive) continue;568 if (!atom.flags.alive) continue;
567 const sect = &self.sections.items(.header)[atom.out_n_sect];569 const sect = &self.sections.items(.header)[atom.out_n_sect];
568 if (sect.isZerofill()) continue;570 if (sect.isZerofill()) continue;
...@@ -573,7 +575,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n...@@ -573,7 +575,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n
573 const atom_size = math.cast(usize, atom.size) orelse return error.Overflow;575 const atom_size = math.cast(usize, atom.size) orelse return error.Overflow;
574 const code = try gpa.alloc(u8, atom_size);576 const code = try gpa.alloc(u8, atom_size);
575 defer gpa.free(code);577 defer gpa.free(code);
576 atom.getData(self, code) catch |err| switch (err) {578 zo.getAtomData(self, atom.*, code) catch |err| switch (err) {
577 error.InputOutput => {579 error.InputOutput => {
578 try self.reportUnexpectedError("fetching code for '{s}' failed", .{580 try self.reportUnexpectedError("fetching code for '{s}' failed", .{
579 atom.getName(self),581 atom.getName(self),
...@@ -1524,7 +1526,7 @@ fn scanRelocs(self: *MachO) !void {...@@ -1524,7 +1526,7 @@ fn scanRelocs(self: *MachO) !void {
1524 try self.getFile(index).?.object.scanRelocs(self);1526 try self.getFile(index).?.object.scanRelocs(self);
1525 }1527 }
1526 if (self.getInternalObject()) |obj| {1528 if (self.getInternalObject()) |obj| {
1527 try obj.scanRelocs(self);1529 obj.scanRelocs(self);
1528 }1530 }
15291531
1530 try self.reportUndefs();1532 try self.reportUndefs();
...@@ -2394,7 +2396,7 @@ fn writeSectionsAndUpdateLinkeditSizes(self: *MachO) !void {...@@ -2394,7 +2396,7 @@ fn writeSectionsAndUpdateLinkeditSizes(self: *MachO) !void {
2394 self.objc_stubs_sect_index,2396 self.objc_stubs_sect_index,
2395 }) |maybe_sect_id| {2397 }) |maybe_sect_id| {
2396 if (maybe_sect_id) |sect_id| {2398 if (maybe_sect_id) |sect_id| {
2397 const out = &slice.items(.out)[sect_id];2399 const out = slice.items(.out)[sect_id].items;
2398 try self.writeSyntheticSection(sect_id, out);2400 try self.writeSyntheticSection(sect_id, out);
2399 }2401 }
2400 }2402 }
...@@ -3970,9 +3972,11 @@ pub const base_tag: link.File.Tag = link.File.Tag.macho;...@@ -3970,9 +3972,11 @@ pub const base_tag: link.File.Tag = link.File.Tag.macho;
3970const Section = struct {3972const Section = struct {
3971 header: macho.section_64,3973 header: macho.section_64,
3972 segment_id: u8,3974 segment_id: u8,
3973 atoms: std.ArrayListUnmanaged(Atom.Index) = .{},3975 atoms: std.ArrayListUnmanaged(Ref) = .{},
3974 free_list: std.ArrayListUnmanaged(Atom.Index) = .{},3976 free_list: std.ArrayListUnmanaged(Atom.Index) = .{},
3975 last_atom_index: Atom.Index = 0,3977 last_atom_index: Atom.Index = 0,
3978 thunks: std.ArrayListUnmanaged(Thunk.Index) = .{},
3979 out: std.ArrayListUnmanaged(u8) = .{},
3976};3980};
39773981
3978pub const LiteralPool = struct {3982pub const LiteralPool = struct {
...@@ -4018,7 +4022,7 @@ pub const LiteralPool = struct {...@@ -4018,7 +4022,7 @@ pub const LiteralPool = struct {
4018 return .{4022 return .{
4019 .found_existing = gop.found_existing,4023 .found_existing = gop.found_existing,
4020 .index = @intCast(gop.index),4024 .index = @intCast(gop.index),
4021 .atom = &lp.values.items[gop.index],4025 .ref = &lp.values.items[gop.index],
4022 };4026 };
4023 }4027 }
40244028
src/link/MachO/Atom.zig-2
...@@ -423,7 +423,6 @@ pub fn addReloc(self: *Atom, macho_file: *MachO, reloc: Relocation) !void {...@@ -423,7 +423,6 @@ pub fn addReloc(self: *Atom, macho_file: *MachO, reloc: Relocation) !void {
423 const gpa = macho_file.base.comp.gpa;423 const gpa = macho_file.base.comp.gpa;
424 const file = self.getFile(macho_file);424 const file = self.getFile(macho_file);
425 assert(file == .zig_object);425 assert(file == .zig_object);
426 assert(self.flags.relocs);
427 var extra = self.getExtra(macho_file).?;426 var extra = self.getExtra(macho_file).?;
428 const rels = &file.zig_object.relocs.items[extra.rel_index];427 const rels = &file.zig_object.relocs.items[extra.rel_index];
429 try rels.append(gpa, reloc);428 try rels.append(gpa, reloc);
...@@ -432,7 +431,6 @@ pub fn addReloc(self: *Atom, macho_file: *MachO, reloc: Relocation) !void {...@@ -432,7 +431,6 @@ pub fn addReloc(self: *Atom, macho_file: *MachO, reloc: Relocation) !void {
432}431}
433432
434pub fn freeRelocs(self: *Atom, macho_file: *MachO) void {433pub fn freeRelocs(self: *Atom, macho_file: *MachO) void {
435 if (!self.flags.relocs) return;
436 self.getFile(macho_file).zig_object.freeAtomRelocs(self.*, macho_file);434 self.getFile(macho_file).zig_object.freeAtomRelocs(self.*, macho_file);
437 var extra = self.getExtra(macho_file).?;435 var extra = self.getExtra(macho_file).?;
438 extra.rel_count = 0;436 extra.rel_count = 0;
src/link/MachO/ZigObject.zig+293-176
...@@ -6,9 +6,15 @@ index: File.Index,...@@ -6,9 +6,15 @@ index: File.Index,
6symtab: std.MultiArrayList(Nlist) = .{},6symtab: std.MultiArrayList(Nlist) = .{},
7strtab: StringTable = .{},7strtab: StringTable = .{},
88
9symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},9symbols: std.ArrayListUnmanaged(Symbol) = .{},
10atoms: std.ArrayListUnmanaged(Atom.Index) = .{},10symbols_extra: std.ArrayListUnmanaged(u32) = .{},
11globals_lookup: std.AutoHashMapUnmanaged(u32, Symbol.Index) = .{},11globals: std.ArrayListUnmanaged(MachO.SymbolResolver.Index) = .{},
12/// Maps string index (so name) into nlist index for the global symbol defined within this
13/// module.
14globals_lookup: std.AutoHashMapUnmanaged(u32, u32) = .{},
15atoms: std.ArrayListUnmanaged(Atom) = .{},
16atoms_indexes: std.ArrayListUnmanaged(Atom.Index) = .{},
17atoms_extra: std.ArrayListUnmanaged(u32) = .{},
1218
13/// Table of tracked LazySymbols.19/// Table of tracked LazySymbols.
14lazy_syms: LazySymbolTable = .{},20lazy_syms: LazySymbolTable = .{},
...@@ -58,10 +64,13 @@ debug_info_header_dirty: bool = false,...@@ -58,10 +64,13 @@ debug_info_header_dirty: bool = false,
58debug_line_header_dirty: bool = false,64debug_line_header_dirty: bool = false,
5965
60pub fn init(self: *ZigObject, macho_file: *MachO) !void {66pub fn init(self: *ZigObject, macho_file: *MachO) !void {
67 const tracy = trace(@src());
68 defer tracy.end();
69
61 const comp = macho_file.base.comp;70 const comp = macho_file.base.comp;
62 const gpa = comp.gpa;71 const gpa = comp.gpa;
6372
64 try self.atoms.append(gpa, 0); // null input section73 try self.atoms.append(gpa, .{ .extra = try self.addAtomExtra(gpa, .{}) }); // null input section
65 try self.strtab.buffer.append(gpa, 0);74 try self.strtab.buffer.append(gpa, 0);
6675
67 switch (comp.config.debug_format) {76 switch (comp.config.debug_format) {
...@@ -84,8 +93,12 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void {...@@ -84,8 +93,12 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void {
84 self.symtab.deinit(allocator);93 self.symtab.deinit(allocator);
85 self.strtab.deinit(allocator);94 self.strtab.deinit(allocator);
86 self.symbols.deinit(allocator);95 self.symbols.deinit(allocator);
87 self.atoms.deinit(allocator);96 self.symbols_extra.deinit(allocator);
97 self.globals.deinit(allocator);
88 self.globals_lookup.deinit(allocator);98 self.globals_lookup.deinit(allocator);
99 self.atoms.deinit(allocator);
100 self.atoms_indexes.deinit(allocator);
101 self.atoms_extra.deinit(allocator);
89102
90 {103 {
91 var it = self.decls.iterator();104 var it = self.decls.iterator();
...@@ -139,32 +152,21 @@ fn addNlist(self: *ZigObject, allocator: Allocator) !Symbol.Index {...@@ -139,32 +152,21 @@ fn addNlist(self: *ZigObject, allocator: Allocator) !Symbol.Index {
139 return index;152 return index;
140}153}
141154
142pub fn addAtom(self: *ZigObject, macho_file: *MachO) !Symbol.Index {155pub fn createAtomForDecl(self: *ZigObject, allocator: Allocator, macho_file: *MachO) !Symbol.Index {
143 const gpa = macho_file.base.comp.gpa;156 const atom_index = try self.addAtom(allocator);
144 const atom_index = try macho_file.addAtom();157 const symbol_index = try self.addSymbol(allocator);
145 const symbol_index = try macho_file.addSymbol();158 const nlist_index = try self.addNlist(allocator);
146 const nlist_index = try self.addNlist(gpa);
147
148 try self.atoms.append(gpa, atom_index);
149 try self.symbols.append(gpa, symbol_index);
150
151 const atom = macho_file.getAtom(atom_index).?;
152 atom.file = self.index;
153 atom.atom_index = atom_index;
154
155 const symbol = macho_file.getSymbol(symbol_index);
156 symbol.file = self.index;
157 symbol.atom = atom_index;
158
159 self.symtab.items(.atom)[nlist_index] = atom_index;159 self.symtab.items(.atom)[nlist_index] = atom_index;
160 try self.atoms_indexes.append(allocator, atom_index);
161 const symbol = &self.symbols.items[symbol_index];
162 symbol.atom_ref = .{ .index = atom_index, .file = self.index };
160 symbol.nlist_idx = nlist_index;163 symbol.nlist_idx = nlist_index;
161164 symbol.extra = try self.addSymbolExtra(allocator, .{});
162 const relocs_index = @as(u32, @intCast(self.relocs.items.len));165 const relocs_index = @as(u32, @intCast(self.relocs.items.len));
163 const relocs = try self.relocs.addOne(gpa);166 const relocs = try self.relocs.addOne(allocator);
164 relocs.* = .{};167 relocs.* = .{};
165 try atom.addExtra(.{ .rel_index = relocs_index, .rel_count = 0 }, macho_file);168 const atom = self.getAtom(atom_index).?;
166 atom.flags.relocs = true;169 atom.addExtra(.{ .rel_index = relocs_index, .rel_count = 0 }, macho_file);
167
168 return symbol_index;170 return symbol_index;
169}171}
170172
...@@ -191,89 +193,51 @@ pub fn getAtomData(self: ZigObject, macho_file: *MachO, atom: Atom, buffer: []u8...@@ -191,89 +193,51 @@ pub fn getAtomData(self: ZigObject, macho_file: *MachO, atom: Atom, buffer: []u8
191}193}
192194
193pub fn getAtomRelocs(self: *ZigObject, atom: Atom, macho_file: *MachO) []const Relocation {195pub fn getAtomRelocs(self: *ZigObject, atom: Atom, macho_file: *MachO) []const Relocation {
194 if (!atom.flags.relocs) return &[0]Relocation{};196 const extra = atom.getExtra(macho_file);
195 const extra = atom.getExtra(macho_file).?;
196 const relocs = self.relocs.items[extra.rel_index];197 const relocs = self.relocs.items[extra.rel_index];
197 return relocs.items[0..extra.rel_count];198 return relocs.items[0..extra.rel_count];
198}199}
199200
200pub fn freeAtomRelocs(self: *ZigObject, atom: Atom, macho_file: *MachO) void {201pub fn freeAtomRelocs(self: *ZigObject, atom: Atom, macho_file: *MachO) void {
201 if (atom.flags.relocs) {202 const extra = atom.getExtra(macho_file);
202 const extra = atom.getExtra(macho_file).?;203 self.relocs.items[extra.rel_index].clearRetainingCapacity();
203 self.relocs.items[extra.rel_index].clearRetainingCapacity();
204 }
205}204}
206205
207pub fn resolveSymbols(self: *ZigObject, macho_file: *MachO) void {206pub fn resolveSymbols(self: *ZigObject, macho_file: *MachO) !void {
208 const tracy = trace(@src());207 const tracy = trace(@src());
209 defer tracy.end();208 defer tracy.end();
210209
211 for (self.symbols.items, 0..) |index, i| {210 const gpa = macho_file.base.comp.gpa;
212 const nlist_idx = @as(Symbol.Index, @intCast(i));
213 const nlist = self.symtab.items(.nlist)[nlist_idx];
214 const atom_index = self.symtab.items(.atom)[nlist_idx];
215211
212 for (self.symtab.items(.nlist), self.symtab.items(.atom), self.globals.items, 0..) |nlist, atom_index, *global, i| {
216 if (!nlist.ext()) continue;213 if (!nlist.ext()) continue;
217 if (nlist.undf() and !nlist.tentative()) continue;
218 if (nlist.sect()) {214 if (nlist.sect()) {
219 const atom = macho_file.getAtom(atom_index).?;215 const atom = self.getAtom(atom_index).?;
220 if (!atom.flags.alive) continue;216 if (!atom.flags.alive) continue;
221 }217 }
222218
223 const symbol = macho_file.getSymbol(index);219 const gop = try macho_file.resolver.getOrPut(gpa, .{
220 .index = @intCast(i),
221 .file = self.index,
222 }, macho_file);
223 if (!gop.found_existing) {
224 gop.ref.* = .{ .index = 0, .file = 0 };
225 }
226 global.* = gop.index;
227
228 if (nlist.undf() and !nlist.tentative()) continue;
229 if (gop.ref.getFile(macho_file) == null) {
230 gop.ref.* = .{ .index = @intCast(i), .file = self.index };
231 continue;
232 }
233
224 if (self.asFile().getSymbolRank(.{234 if (self.asFile().getSymbolRank(.{
225 .archive = false,235 .archive = false,
226 .weak = nlist.weakDef(),236 .weak = nlist.weakDef(),
227 .tentative = nlist.tentative(),237 .tentative = nlist.tentative(),
228 }) < symbol.getSymbolRank(macho_file)) {238 }) < gop.ref.getSymbol(macho_file).?.getSymbolRank(macho_file)) {
229 const value = if (nlist.sect()) blk: {239 gop.ref.* = .{ .index = @intCast(i), .file = self.index };
230 const atom = macho_file.getAtom(atom_index).?;
231 break :blk nlist.n_value - atom.getInputAddress(macho_file);
232 } else nlist.n_value;
233 const out_n_sect = if (nlist.sect()) macho_file.getAtom(atom_index).?.out_n_sect else 0;
234 symbol.value = value;
235 symbol.atom = atom_index;
236 symbol.out_n_sect = out_n_sect;
237 symbol.nlist_idx = nlist_idx;
238 symbol.file = self.index;
239 symbol.flags.weak = nlist.weakDef();
240 symbol.flags.abs = nlist.abs();
241 symbol.flags.tentative = nlist.tentative();
242 symbol.flags.weak_ref = false;
243 symbol.flags.dyn_ref = nlist.n_desc & macho.REFERENCED_DYNAMICALLY != 0;
244 symbol.flags.no_dead_strip = symbol.flags.no_dead_strip or nlist.noDeadStrip();
245 // TODO: symbol.flags.interposable = macho_file.base.isDynLib() and macho_file.options.namespace == .flat and !nlist.pext();
246 symbol.flags.interposable = false;
247
248 if (nlist.sect() and
249 macho_file.sections.items(.header)[nlist.n_sect - 1].type() == macho.S_THREAD_LOCAL_VARIABLES)
250 {
251 symbol.flags.tlv = true;
252 }
253 }240 }
254
255 // Regardless of who the winner is, we still merge symbol visibility here.
256 if (nlist.pext() or (nlist.weakDef() and nlist.weakRef())) {
257 if (symbol.visibility != .global) {
258 symbol.visibility = .hidden;
259 }
260 } else {
261 symbol.visibility = .global;
262 }
263 }
264}
265
266pub fn resetGlobals(self: *ZigObject, macho_file: *MachO) void {
267 for (self.symbols.items, 0..) |sym_index, nlist_idx| {
268 if (!self.symtab.items(.nlist)[nlist_idx].ext()) continue;
269 const sym = macho_file.getSymbol(sym_index);
270 const name = sym.name;
271 const global = sym.flags.global;
272 const weak_ref = sym.flags.weak_ref;
273 sym.* = .{};
274 sym.name = name;
275 sym.flags.global = global;
276 sym.flags.weak_ref = weak_ref;
277 }241 }
278}242}
279243
...@@ -281,12 +245,13 @@ pub fn markLive(self: *ZigObject, macho_file: *MachO) void {...@@ -281,12 +245,13 @@ pub fn markLive(self: *ZigObject, macho_file: *MachO) void {
281 const tracy = trace(@src());245 const tracy = trace(@src());
282 defer tracy.end();246 defer tracy.end();
283247
284 for (self.symbols.items, 0..) |index, nlist_idx| {248 for (0..self.symbols.items.len) |i| {
285 const nlist = self.symtab.items(.nlist)[nlist_idx];249 const nlist = self.symtab.items(.nlist)[i];
286 if (!nlist.ext()) continue;250 if (!nlist.ext()) continue;
287251
288 const sym = macho_file.getSymbol(index);252 const ref = self.getSymbolRef(@intCast(i), macho_file);
289 const file = sym.getFile(macho_file) orelse continue;253 const file = ref.getFile(macho_file) orelse continue;
254 const sym = ref.getSymbol(macho_file).?;
290 const should_keep = nlist.undf() or (nlist.tentative() and !sym.flags.tentative);255 const should_keep = nlist.undf() or (nlist.tentative() and !sym.flags.tentative);
291 if (should_keep and file == .object and !file.object.alive) {256 if (should_keep and file == .object and !file.object.alive) {
292 file.object.alive = true;257 file.object.alive = true;
...@@ -295,24 +260,41 @@ pub fn markLive(self: *ZigObject, macho_file: *MachO) void {...@@ -295,24 +260,41 @@ pub fn markLive(self: *ZigObject, macho_file: *MachO) void {
295 }260 }
296}261}
297262
298pub fn checkDuplicates(self: *ZigObject, dupes: anytype, macho_file: *MachO) !void {263pub fn mergeSymbolVisibility(self: *ZigObject, macho_file: *MachO) void {
299 for (self.symbols.items, 0..) |index, nlist_idx| {264 const tracy = trace(@src());
300 const sym = macho_file.getSymbol(index);265 defer tracy.end();
301 if (sym.visibility != .global) continue;266
302 const file = sym.getFile(macho_file) orelse continue;267 for (self.symbols.items, 0..) |sym, i| {
303 if (file.getIndex() == self.index) continue;268 const ref = self.getSymbolRef(@intCast(i), macho_file);
304269 const global = ref.getSymbol(macho_file) orelse continue;
305 const nlist = self.symtab.items(.nlist)[nlist_idx];270 if (global.visibility != .global) {
306 if (!nlist.undf() and !nlist.tentative() and !(nlist.weakDef() or nlist.pext())) {271 global.visibility = sym.visibility;
307 const gop = try dupes.getOrPut(index);272 }
308 if (!gop.found_existing) {273 if (sym.flags.weak_ref) {
309 gop.value_ptr.* = .{};274 global.flags.weak_ref = true;
310 }
311 try gop.value_ptr.append(macho_file.base.comp.gpa, self.index);
312 }275 }
313 }276 }
314}277}
315278
279// TODO
280// pub fn checkDuplicates(self: *ZigObject, dupes: anytype, macho_file: *MachO) !void {
281// for (self.symbols.items, 0..) |index, nlist_idx| {
282// const sym = macho_file.getSymbol(index);
283// if (sym.visibility != .global) continue;
284// const file = sym.getFile(macho_file) orelse continue;
285// if (file.getIndex() == self.index) continue;
286
287// const nlist = self.symtab.items(.nlist)[nlist_idx];
288// if (!nlist.undf() and !nlist.tentative() and !(nlist.weakDef() or nlist.pext())) {
289// const gop = try dupes.getOrPut(index);
290// if (!gop.found_existing) {
291// gop.value_ptr.* = .{};
292// }
293// try gop.value_ptr.append(macho_file.base.comp.gpa, self.index);
294// }
295// }
296// }
297
316pub fn resolveLiterals(self: *ZigObject, lp: *MachO.LiteralPool, macho_file: *MachO) !void {298pub fn resolveLiterals(self: *ZigObject, lp: *MachO.LiteralPool, macho_file: *MachO) !void {
317 _ = self;299 _ = self;
318 _ = lp;300 _ = lp;
...@@ -362,8 +344,8 @@ pub fn writeAr(self: ZigObject, ar_format: Archive.Format, writer: anytype) !voi...@@ -362,8 +344,8 @@ pub fn writeAr(self: ZigObject, ar_format: Archive.Format, writer: anytype) !voi
362}344}
363345
364pub fn scanRelocs(self: *ZigObject, macho_file: *MachO) !void {346pub fn scanRelocs(self: *ZigObject, macho_file: *MachO) !void {
365 for (self.atoms.items) |atom_index| {347 for (self.getAtoms()) |atom_index| {
366 const atom = macho_file.getAtom(atom_index) orelse continue;348 const atom = self.getAtom(atom_index) orelse continue;
367 if (!atom.flags.alive) continue;349 if (!atom.flags.alive) continue;
368 const sect = atom.getInputSection(macho_file);350 const sect = atom.getInputSection(macho_file);
369 if (sect.isZerofill()) continue;351 if (sect.isZerofill()) continue;
...@@ -371,46 +353,49 @@ pub fn scanRelocs(self: *ZigObject, macho_file: *MachO) !void {...@@ -371,46 +353,49 @@ pub fn scanRelocs(self: *ZigObject, macho_file: *MachO) !void {
371 }353 }
372}354}
373355
374pub fn calcSymtabSize(self: *ZigObject, macho_file: *MachO) !void {356pub fn calcSymtabSize(self: *ZigObject, macho_file: *MachO) void {
375 const tracy = trace(@src());357 const tracy = trace(@src());
376 defer tracy.end();358 defer tracy.end();
377359
378 for (self.symbols.items) |sym_index| {360 for (self.symbols.items, 0..) |*sym, i| {
379 const sym = macho_file.getSymbol(sym_index);361 const ref = self.getSymbolRef(@intCast(i), macho_file);
380 const file = sym.getFile(macho_file) orelse continue;362 const file = ref.getFile(macho_file) orelse continue;
381 if (file.getIndex() != self.index) continue;363 if (file.getIndex() != self.index) continue;
382 if (sym.getAtom(macho_file)) |atom| if (!atom.flags.alive) continue;364 if (sym.getAtom(macho_file)) |atom| if (!atom.flags.alive) continue;
383 sym.flags.output_symtab = true;365 sym.flags.output_symtab = true;
384 if (sym.isLocal()) {366 if (sym.isLocal()) {
385 try sym.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, macho_file);367 sym.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, macho_file);
386 self.output_symtab_ctx.nlocals += 1;368 self.output_symtab_ctx.nlocals += 1;
387 } else if (sym.flags.@"export") {369 } else if (sym.flags.@"export") {
388 try sym.addExtra(.{ .symtab = self.output_symtab_ctx.nexports }, macho_file);370 sym.addExtra(.{ .symtab = self.output_symtab_ctx.nexports }, macho_file);
389 self.output_symtab_ctx.nexports += 1;371 self.output_symtab_ctx.nexports += 1;
390 } else {372 } else {
391 assert(sym.flags.import);373 assert(sym.flags.import);
392 try sym.addExtra(.{ .symtab = self.output_symtab_ctx.nimports }, macho_file);374 sym.addExtra(.{ .symtab = self.output_symtab_ctx.nimports }, macho_file);
393 self.output_symtab_ctx.nimports += 1;375 self.output_symtab_ctx.nimports += 1;
394 }376 }
395 self.output_symtab_ctx.strsize += @as(u32, @intCast(sym.getName(macho_file).len + 1));377 self.output_symtab_ctx.strsize += @as(u32, @intCast(sym.getName(macho_file).len + 1));
396 }378 }
397}379}
398380
399pub fn writeSymtab(self: ZigObject, macho_file: *MachO, ctx: anytype) void {381pub fn writeSymtab(self: ZigObject, macho_file: *MachO) void {
400 const tracy = trace(@src());382 const tracy = trace(@src());
401 defer tracy.end();383 defer tracy.end();
402384
403 for (self.symbols.items) |sym_index| {385 var n_strx = self.output_symtab_ctx.stroff;
404 const sym = macho_file.getSymbol(sym_index);386 for (self.symbols.items, 0..) |sym, i| {
405 const file = sym.getFile(macho_file) orelse continue;387 const ref = self.getSymbolRef(@intCast(i), macho_file);
388 const file = ref.getFile(macho_file) orelse continue;
406 if (file.getIndex() != self.index) continue;389 if (file.getIndex() != self.index) continue;
407 const idx = sym.getOutputSymtabIndex(macho_file) orelse continue;390 const idx = sym.getOutputSymtabIndex(macho_file) orelse continue;
408 const n_strx = @as(u32, @intCast(ctx.strtab.items.len));391 const out_sym = &macho_file.symtab.items[idx];
409 ctx.strtab.appendSliceAssumeCapacity(sym.getName(macho_file));
410 ctx.strtab.appendAssumeCapacity(0);
411 const out_sym = &ctx.symtab.items[idx];
412 out_sym.n_strx = n_strx;392 out_sym.n_strx = n_strx;
413 sym.setOutputSym(macho_file, out_sym);393 sym.setOutputSym(macho_file, out_sym);
394 const name = sym.getName(macho_file);
395 @memcpy(macho_file.strtab.items[n_strx..][0..name.len], name);
396 n_strx += @intCast(name.len);
397 macho_file.strtab.items[n_strx] = 0;
398 n_strx += 1;
414 }399 }
415}400}
416401
...@@ -523,9 +508,9 @@ pub fn getDeclVAddr(...@@ -523,9 +508,9 @@ pub fn getDeclVAddr(
523 reloc_info: link.File.RelocInfo,508 reloc_info: link.File.RelocInfo,
524) !u64 {509) !u64 {
525 const sym_index = try self.getOrCreateMetadataForDecl(macho_file, decl_index);510 const sym_index = try self.getOrCreateMetadataForDecl(macho_file, decl_index);
526 const sym = macho_file.getSymbol(sym_index);511 const sym = self.symbols.items[sym_index];
527 const vaddr = sym.getAddress(.{}, macho_file);512 const vaddr = sym.getAddress(.{}, macho_file);
528 const parent_atom = macho_file.getSymbol(reloc_info.parent_atom_index).getAtom(macho_file).?;513 const parent_atom = self.symbols.items[reloc_info.parent_atom_index].getAtom(macho_file).?;
529 try parent_atom.addReloc(macho_file, .{514 try parent_atom.addReloc(macho_file, .{
530 .tag = .@"extern",515 .tag = .@"extern",
531 .offset = @intCast(reloc_info.offset),516 .offset = @intCast(reloc_info.offset),
...@@ -549,9 +534,9 @@ pub fn getAnonDeclVAddr(...@@ -549,9 +534,9 @@ pub fn getAnonDeclVAddr(
549 reloc_info: link.File.RelocInfo,534 reloc_info: link.File.RelocInfo,
550) !u64 {535) !u64 {
551 const sym_index = self.anon_decls.get(decl_val).?.symbol_index;536 const sym_index = self.anon_decls.get(decl_val).?.symbol_index;
552 const sym = macho_file.getSymbol(sym_index);537 const sym = self.symbols.items[sym_index];
553 const vaddr = sym.getAddress(.{}, macho_file);538 const vaddr = sym.getAddress(.{}, macho_file);
554 const parent_atom = macho_file.getSymbol(reloc_info.parent_atom_index).getAtom(macho_file).?;539 const parent_atom = self.symbols.items[reloc_info.parent_atom_index].getAtom(macho_file).?;
555 try parent_atom.addReloc(macho_file, .{540 try parent_atom.addReloc(macho_file, .{
556 .tag = .@"extern",541 .tag = .@"extern",
557 .offset = @intCast(reloc_info.offset),542 .offset = @intCast(reloc_info.offset),
...@@ -584,7 +569,7 @@ pub fn lowerAnonDecl(...@@ -584,7 +569,7 @@ pub fn lowerAnonDecl(
584 else => explicit_alignment,569 else => explicit_alignment,
585 };570 };
586 if (self.anon_decls.get(decl_val)) |metadata| {571 if (self.anon_decls.get(decl_val)) |metadata| {
587 const existing_alignment = macho_file.getSymbol(metadata.symbol_index).getAtom(macho_file).?.alignment;572 const existing_alignment = self.symbols.items[metadata.symbol_index].getAtom(macho_file).?.alignment;
588 if (decl_alignment.order(existing_alignment).compare(.lte))573 if (decl_alignment.order(existing_alignment).compare(.lte))
589 return .ok;574 return .ok;
590 }575 }
...@@ -628,13 +613,10 @@ fn freeUnnamedConsts(self: *ZigObject, macho_file: *MachO, decl_index: InternPoo...@@ -628,13 +613,10 @@ fn freeUnnamedConsts(self: *ZigObject, macho_file: *MachO, decl_index: InternPoo
628}613}
629614
630fn freeDeclMetadata(self: *ZigObject, macho_file: *MachO, sym_index: Symbol.Index) void {615fn freeDeclMetadata(self: *ZigObject, macho_file: *MachO, sym_index: Symbol.Index) void {
631 _ = self;616 const sym = self.symbols.items[sym_index];
632 const gpa = macho_file.base.comp.gpa;
633 const sym = macho_file.getSymbol(sym_index);
634 sym.getAtom(macho_file).?.free(macho_file);617 sym.getAtom(macho_file).?.free(macho_file);
635 log.debug("adding %{d} to local symbols free list", .{sym_index});618 log.debug("adding %{d} to local symbols free list", .{sym_index});
636 macho_file.symbols_free_list.append(gpa, sym_index) catch {};619 // TODO redo this
637 macho_file.symbols.items[sym_index] = .{};
638 // TODO free GOT entry here620 // TODO free GOT entry here
639}621}
640622
...@@ -675,7 +657,7 @@ pub fn updateFunc(...@@ -675,7 +657,7 @@ pub fn updateFunc(
675657
676 const sym_index = try self.getOrCreateMetadataForDecl(macho_file, decl_index);658 const sym_index = try self.getOrCreateMetadataForDecl(macho_file, decl_index);
677 self.freeUnnamedConsts(macho_file, decl_index);659 self.freeUnnamedConsts(macho_file, decl_index);
678 macho_file.getSymbol(sym_index).getAtom(macho_file).?.freeRelocs(macho_file);660 self.symbols.items[sym_index].getAtom(macho_file).?.freeRelocs(macho_file);
679661
680 var code_buffer = std.ArrayList(u8).init(gpa);662 var code_buffer = std.ArrayList(u8).init(gpa);
681 defer code_buffer.deinit();663 defer code_buffer.deinit();
...@@ -708,7 +690,7 @@ pub fn updateFunc(...@@ -708,7 +690,7 @@ pub fn updateFunc(
708 try self.updateDeclCode(macho_file, pt, decl_index, sym_index, sect_index, code);690 try self.updateDeclCode(macho_file, pt, decl_index, sym_index, sect_index, code);
709691
710 if (decl_state) |*ds| {692 if (decl_state) |*ds| {
711 const sym = macho_file.getSymbol(sym_index);693 const sym = self.symbols.items[sym_index];
712 try self.dwarf.?.commitDeclState(694 try self.dwarf.?.commitDeclState(
713 pt,695 pt,
714 decl_index,696 decl_index,
...@@ -743,13 +725,13 @@ pub fn updateDecl(...@@ -743,13 +725,13 @@ pub fn updateDecl(
743 const name = decl.name.toSlice(&mod.intern_pool);725 const name = decl.name.toSlice(&mod.intern_pool);
744 const lib_name = variable.lib_name.toSlice(&mod.intern_pool);726 const lib_name = variable.lib_name.toSlice(&mod.intern_pool);
745 const index = try self.getGlobalSymbol(macho_file, name, lib_name);727 const index = try self.getGlobalSymbol(macho_file, name, lib_name);
746 const actual_index = self.symbols.items[index];728 const sym = &self.symbols.items[index];
747 macho_file.getSymbol(actual_index).flags.needs_got = true;729 sym.flags.needs_got = true;
748 return;730 return;
749 }731 }
750732
751 const sym_index = try self.getOrCreateMetadataForDecl(macho_file, decl_index);733 const sym_index = try self.getOrCreateMetadataForDecl(macho_file, decl_index);
752 macho_file.getSymbol(sym_index).getAtom(macho_file).?.freeRelocs(macho_file);734 self.symbols.items[sym_index].getAtom(macho_file).?.freeRelocs(macho_file);
753735
754 const gpa = macho_file.base.comp.gpa;736 const gpa = macho_file.base.comp.gpa;
755 var code_buffer = std.ArrayList(u8).init(gpa);737 var code_buffer = std.ArrayList(u8).init(gpa);
...@@ -784,7 +766,7 @@ pub fn updateDecl(...@@ -784,7 +766,7 @@ pub fn updateDecl(
784 }766 }
785767
786 if (decl_state) |*ds| {768 if (decl_state) |*ds| {
787 const sym = macho_file.getSymbol(sym_index);769 const sym = self.symbols.items[sym_index];
788 try self.dwarf.?.commitDeclState(770 try self.dwarf.?.commitDeclState(
789 pt,771 pt,
790 decl_index,772 decl_index,
...@@ -816,7 +798,7 @@ fn updateDeclCode(...@@ -816,7 +798,7 @@ fn updateDeclCode(
816 const required_alignment = decl.getAlignment(pt);798 const required_alignment = decl.getAlignment(pt);
817799
818 const sect = &macho_file.sections.items(.header)[sect_index];800 const sect = &macho_file.sections.items(.header)[sect_index];
819 const sym = macho_file.getSymbol(sym_index);801 const sym = &self.symbols.items[sym_index];
820 const nlist = &self.symtab.items(.nlist)[sym.nlist_idx];802 const nlist = &self.symtab.items(.nlist)[sym.nlist_idx];
821 const atom = sym.getAtom(macho_file).?;803 const atom = sym.getAtom(macho_file).?;
822804
...@@ -850,13 +832,13 @@ fn updateDeclCode(...@@ -850,13 +832,13 @@ fn updateDeclCode(
850 if (!macho_file.base.isRelocatable()) {832 if (!macho_file.base.isRelocatable()) {
851 log.debug(" (updating offset table entry)", .{});833 log.debug(" (updating offset table entry)", .{});
852 assert(sym.flags.has_zig_got);834 assert(sym.flags.has_zig_got);
853 const extra = sym.getExtra(macho_file).?;835 const extra = sym.getExtra(macho_file);
854 try macho_file.zig_got.writeOne(macho_file, extra.zig_got);836 try macho_file.zig_got.writeOne(macho_file, extra.zig_got);
855 }837 }
856 }838 }
857 } else if (code.len < old_size) {839 } else if (code.len < old_size) {
858 atom.shrink(macho_file);840 atom.shrink(macho_file);
859 } else if (macho_file.getAtom(atom.next_index) == null) {841 } else if (self.getAtom(atom.next_index) == null) {
860 const needed_size = atom.value + code.len;842 const needed_size = atom.value + code.len;
861 sect.size = needed_size;843 sect.size = needed_size;
862 }844 }
...@@ -922,8 +904,8 @@ fn createTlvInitializer(...@@ -922,8 +904,8 @@ fn createTlvInitializer(
922 const sym_name = try std.fmt.allocPrint(gpa, "{s}$tlv$init", .{name});904 const sym_name = try std.fmt.allocPrint(gpa, "{s}$tlv$init", .{name});
923 defer gpa.free(sym_name);905 defer gpa.free(sym_name);
924906
925 const sym_index = try self.addAtom(macho_file);907 const sym_index = try self.createAtomForDecl(gpa, macho_file);
926 const sym = macho_file.getSymbol(sym_index);908 const sym = &self.symbols.items[sym_index];
927 const nlist = &self.symtab.items(.nlist)[sym.nlist_idx];909 const nlist = &self.symtab.items(.nlist)[sym.nlist_idx];
928 const atom = sym.getAtom(macho_file).?;910 const atom = sym.getAtom(macho_file).?;
929911
...@@ -945,7 +927,6 @@ fn createTlvInitializer(...@@ -945,7 +927,6 @@ fn createTlvInitializer(
945927
946 const slice = macho_file.sections.slice();928 const slice = macho_file.sections.slice();
947 const header = slice.items(.header)[sect_index];929 const header = slice.items(.header)[sect_index];
948 const atoms = &slice.items(.atoms)[sect_index];
949930
950 const gop = try self.tlv_initializers.getOrPut(gpa, atom.atom_index);931 const gop = try self.tlv_initializers.getOrPut(gpa, atom.atom_index);
951 assert(!gop.found_existing); // TODO incremental updates932 assert(!gop.found_existing); // TODO incremental updates
...@@ -956,8 +937,6 @@ fn createTlvInitializer(...@@ -956,8 +937,6 @@ fn createTlvInitializer(
956 gop.value_ptr.data = try gpa.dupe(u8, code);937 gop.value_ptr.data = try gpa.dupe(u8, code);
957 }938 }
958939
959 try atoms.append(gpa, atom.atom_index);
960
961 return sym_index;940 return sym_index;
962}941}
963942
...@@ -970,7 +949,7 @@ fn createTlvDescriptor(...@@ -970,7 +949,7 @@ fn createTlvDescriptor(
970) !void {949) !void {
971 const gpa = macho_file.base.comp.gpa;950 const gpa = macho_file.base.comp.gpa;
972951
973 const sym = macho_file.getSymbol(sym_index);952 const sym = &self.symbols.items[sym_index];
974 const nlist = &self.symtab.items(.nlist)[sym.nlist_idx];953 const nlist = &self.symtab.items(.nlist)[sym.nlist_idx];
975 const atom = sym.getAtom(macho_file).?;954 const atom = sym.getAtom(macho_file).?;
976 const alignment = Atom.Alignment.fromNonzeroByteUnits(@alignOf(u64));955 const alignment = Atom.Alignment.fromNonzeroByteUnits(@alignOf(u64));
...@@ -1000,7 +979,7 @@ fn createTlvDescriptor(...@@ -1000,7 +979,7 @@ fn createTlvDescriptor(
1000 try atom.addReloc(macho_file, .{979 try atom.addReloc(macho_file, .{
1001 .tag = .@"extern",980 .tag = .@"extern",
1002 .offset = 0,981 .offset = 0,
1003 .target = self.symbols.items[tlv_bootstrap_index],982 .target = tlv_bootstrap_index,
1004 .addend = 0,983 .addend = 0,
1005 .type = .unsigned,984 .type = .unsigned,
1006 .meta = .{985 .meta = .{
...@@ -1020,11 +999,14 @@ fn createTlvDescriptor(...@@ -1020,11 +999,14 @@ fn createTlvDescriptor(
1020 .pcrel = false,999 .pcrel = false,
1021 .has_subtractor = false,1000 .has_subtractor = false,
1022 .length = 3,1001 .length = 3,
1023 .symbolnum = @intCast(macho_file.getSymbol(init_sym_index).nlist_idx),1002 .symbolnum = @intCast(init_sym_index),
1024 },1003 },
1025 });1004 });
10261005
1027 try macho_file.sections.items(.atoms)[sect_index].append(gpa, atom.atom_index);1006 try macho_file.sections.items(.atoms)[sect_index].append(gpa, .{
1007 .index = atom.atom_index,
1008 .file = self.index,
1009 });
1028}1010}
10291011
1030fn getDeclOutputSection(1012fn getDeclOutputSection(
...@@ -1115,7 +1097,7 @@ pub fn lowerUnnamedConst(...@@ -1115,7 +1097,7 @@ pub fn lowerUnnamedConst(
1115 return error.CodegenFail;1097 return error.CodegenFail;
1116 },1098 },
1117 };1099 };
1118 const sym = macho_file.getSymbol(sym_index);1100 const sym = self.symbols.items[sym_index];
1119 try unnamed_consts.append(gpa, sym.atom);1101 try unnamed_consts.append(gpa, sym.atom);
1120 return sym_index;1102 return sym_index;
1121}1103}
...@@ -1140,7 +1122,7 @@ fn lowerConst(...@@ -1140,7 +1122,7 @@ fn lowerConst(
1140 var code_buffer = std.ArrayList(u8).init(gpa);1122 var code_buffer = std.ArrayList(u8).init(gpa);
1141 defer code_buffer.deinit();1123 defer code_buffer.deinit();
11421124
1143 const sym_index = try self.addAtom(macho_file);1125 const sym_index = try self.createAtomForDecl(gpa, macho_file);
11441126
1145 const res = try codegen.generateSymbol(&macho_file.base, pt, src_loc, val, &code_buffer, .{1127 const res = try codegen.generateSymbol(&macho_file.base, pt, src_loc, val, &code_buffer, .{
1146 .none = {},1128 .none = {},
...@@ -1152,7 +1134,7 @@ fn lowerConst(...@@ -1152,7 +1134,7 @@ fn lowerConst(
1152 .fail => |em| return .{ .fail = em },1134 .fail => |em| return .{ .fail = em },
1153 };1135 };
11541136
1155 const sym = macho_file.getSymbol(sym_index);1137 const sym = &self.symbols.items[sym_index];
1156 const name_str_index = try self.strtab.insert(gpa, name);1138 const name_str_index = try self.strtab.insert(gpa, name);
1157 sym.name = name_str_index;1139 sym.name = name_str_index;
1158 sym.out_n_sect = output_section_index;1140 sym.out_n_sect = output_section_index;
...@@ -1218,7 +1200,7 @@ pub fn updateExports(...@@ -1218,7 +1200,7 @@ pub fn updateExports(
1218 },1200 },
1219 };1201 };
1220 const sym_index = metadata.symbol_index;1202 const sym_index = metadata.symbol_index;
1221 const nlist_idx = macho_file.getSymbol(sym_index).nlist_idx;1203 const nlist_idx = self.symbols.items[sym_index].nlist_idx;
1222 const nlist = self.symtab.items(.nlist)[nlist_idx];1204 const nlist = self.symtab.items(.nlist)[nlist_idx];
12231205
1224 for (export_indices) |export_idx| {1206 for (export_indices) |export_idx| {
...@@ -1322,7 +1304,7 @@ fn updateLazySymbol(...@@ -1322,7 +1304,7 @@ fn updateLazySymbol(
1322 .code => macho_file.zig_text_sect_index.?,1304 .code => macho_file.zig_text_sect_index.?,
1323 .const_data => macho_file.zig_const_sect_index.?,1305 .const_data => macho_file.zig_const_sect_index.?,
1324 };1306 };
1325 const sym = macho_file.getSymbol(symbol_index);1307 const sym = &self.symbols.items[symbol_index];
1326 sym.name = name_str_index;1308 sym.name = name_str_index;
1327 sym.out_n_sect = output_section_index;1309 sym.out_n_sect = output_section_index;
13281310
...@@ -1382,12 +1364,12 @@ pub fn deleteExport(...@@ -1382,12 +1364,12 @@ pub fn deleteExport(
1382 const nlist = &self.symtab.items(.nlist)[nlist_index.*];1364 const nlist = &self.symtab.items(.nlist)[nlist_index.*];
1383 self.symtab.items(.size)[nlist_index.*] = 0;1365 self.symtab.items(.size)[nlist_index.*] = 0;
1384 _ = self.globals_lookup.remove(nlist.n_strx);1366 _ = self.globals_lookup.remove(nlist.n_strx);
1385 const sym_index = macho_file.globals.get(nlist.n_strx).?;1367 // TODO actually remove the export
1386 const sym = macho_file.getSymbol(sym_index);1368 // const sym_index = macho_file.globals.get(nlist.n_strx).?;
1387 if (sym.file == self.index) {1369 // const sym = &self.symbols.items[sym_index];
1388 _ = macho_file.globals.swapRemove(nlist.n_strx);1370 // if (sym.file == self.index) {
1389 sym.* = .{};1371 // sym.* = .{};
1390 }1372 // }
1391 nlist.* = MachO.null_sym;1373 nlist.* = MachO.null_sym;
1392}1374}
13931375
...@@ -1404,9 +1386,11 @@ pub fn getGlobalSymbol(self: *ZigObject, macho_file: *MachO, name: []const u8, l...@@ -1404,9 +1386,11 @@ pub fn getGlobalSymbol(self: *ZigObject, macho_file: *MachO, name: []const u8, l
1404 nlist.n_strx = off;1386 nlist.n_strx = off;
1405 nlist.n_type = macho.N_EXT;1387 nlist.n_type = macho.N_EXT;
1406 lookup_gop.value_ptr.* = nlist_index;1388 lookup_gop.value_ptr.* = nlist_index;
1407 const global_name_off = try macho_file.strings.insert(gpa, sym_name);1389 _ = try macho_file.resolver.getOrPut(gpa, .{
1408 const gop = try macho_file.getOrCreateGlobal(global_name_off);1390 .index = nlist_index,
1409 try self.symbols.append(gpa, gop.index);1391 .file = self.index,
1392 }, macho_file);
1393 try self.globals.append(gpa, nlist_index);
1410 }1394 }
1411 return lookup_gop.value_ptr.*;1395 return lookup_gop.value_ptr.*;
1412}1396}
...@@ -1420,10 +1404,10 @@ pub fn getOrCreateMetadataForDecl(...@@ -1420,10 +1404,10 @@ pub fn getOrCreateMetadataForDecl(
1420 const gop = try self.decls.getOrPut(gpa, decl_index);1404 const gop = try self.decls.getOrPut(gpa, decl_index);
1421 if (!gop.found_existing) {1405 if (!gop.found_existing) {
1422 const any_non_single_threaded = macho_file.base.comp.config.any_non_single_threaded;1406 const any_non_single_threaded = macho_file.base.comp.config.any_non_single_threaded;
1423 const sym_index = try self.addAtom(macho_file);1407 const sym_index = try self.createAtomForDecl(gpa, macho_file);
1424 const mod = macho_file.base.comp.module.?;1408 const mod = macho_file.base.comp.module.?;
1425 const decl = mod.declPtr(decl_index);1409 const decl = mod.declPtr(decl_index);
1426 const sym = macho_file.getSymbol(sym_index);1410 const sym = &self.symbols.items[sym_index];
1427 if (decl.getOwnedVariable(mod)) |variable| {1411 if (decl.getOwnedVariable(mod)) |variable| {
1428 if (variable.is_threadlocal and any_non_single_threaded) {1412 if (variable.is_threadlocal and any_non_single_threaded) {
1429 sym.flags.tlv = true;1413 sym.flags.tlv = true;
...@@ -1463,8 +1447,8 @@ pub fn getOrCreateMetadataForLazySymbol(...@@ -1463,8 +1447,8 @@ pub fn getOrCreateMetadataForLazySymbol(
1463 };1447 };
1464 switch (metadata.state.*) {1448 switch (metadata.state.*) {
1465 .unused => {1449 .unused => {
1466 const symbol_index = try self.addAtom(macho_file);1450 const symbol_index = try self.createAtomForDecl(gpa, macho_file);
1467 const sym = macho_file.getSymbol(symbol_index);1451 const sym = &self.symbols.items[symbol_index];
1468 sym.flags.needs_zig_got = true;1452 sym.flags.needs_zig_got = true;
1469 metadata.symbol_index.* = symbol_index;1453 metadata.symbol_index.* = symbol_index;
1470 },1454 },
...@@ -1478,6 +1462,130 @@ pub fn getOrCreateMetadataForLazySymbol(...@@ -1478,6 +1462,130 @@ pub fn getOrCreateMetadataForLazySymbol(
1478 return symbol_index;1462 return symbol_index;
1479}1463}
14801464
1465fn addAtom(self: *ZigObject, allocator: Allocator) !Atom.Index {
1466 const atom_index: Atom.Index = @intCast(self.atoms.items.len);
1467 const atom = try self.atoms.addOne(allocator);
1468 atom.* = .{
1469 .file = self.index,
1470 .atom_index = atom_index,
1471 .extra = try self.addAtomExtra(allocator, .{}),
1472 };
1473 return atom_index;
1474}
1475
1476pub fn getAtom(self: *ZigObject, atom_index: Atom.Index) ?*Atom {
1477 if (atom_index == 0) return null;
1478 assert(atom_index < self.atoms.items.len);
1479 return &self.atoms.items[atom_index];
1480}
1481
1482pub fn getAtoms(self: *ZigObject) []const Atom.Index {
1483 return self.atoms_indexes.items;
1484}
1485
1486fn addAtomExtra(self: *ZigObject, allocator: Allocator, extra: Atom.Extra) !u32 {
1487 const fields = @typeInfo(Atom.Extra).Struct.fields;
1488 try self.atoms_extra.ensureUnusedCapacity(allocator, fields.len);
1489 return self.addAtomExtraAssumeCapacity(extra);
1490}
1491
1492fn addAtomExtraAssumeCapacity(self: *ZigObject, extra: Atom.Extra) u32 {
1493 const index = @as(u32, @intCast(self.atoms_extra.items.len));
1494 const fields = @typeInfo(Atom.Extra).Struct.fields;
1495 inline for (fields) |field| {
1496 self.atoms_extra.appendAssumeCapacity(switch (field.type) {
1497 u32 => @field(extra, field.name),
1498 else => @compileError("bad field type"),
1499 });
1500 }
1501 return index;
1502}
1503
1504pub fn getAtomExtra(self: ZigObject, index: u32) Atom.Extra {
1505 const fields = @typeInfo(Atom.Extra).Struct.fields;
1506 var i: usize = index;
1507 var result: Atom.Extra = undefined;
1508 inline for (fields) |field| {
1509 @field(result, field.name) = switch (field.type) {
1510 u32 => self.atoms_extra.items[i],
1511 else => @compileError("bad field type"),
1512 };
1513 i += 1;
1514 }
1515 return result;
1516}
1517
1518pub fn setAtomExtra(self: *ZigObject, index: u32, extra: Atom.Extra) void {
1519 assert(index > 0);
1520 const fields = @typeInfo(Atom.Extra).Struct.fields;
1521 inline for (fields, 0..) |field, i| {
1522 self.atoms_extra.items[index + i] = switch (field.type) {
1523 u32 => @field(extra, field.name),
1524 else => @compileError("bad field type"),
1525 };
1526 }
1527}
1528
1529fn addSymbol(self: *ZigObject, allocator: Allocator) !Symbol.Index {
1530 try self.symbols.ensureUnusedCapacity(allocator, 1);
1531 return self.addSymbolAssumeCapacity();
1532}
1533
1534fn addSymbolAssumeCapacity(self: *ZigObject) Symbol.Index {
1535 const index: Symbol.Index = @intCast(self.symbols.items.len);
1536 const symbol = self.symbols.addOneAssumeCapacity();
1537 symbol.* = .{ .file = self.index };
1538 return index;
1539}
1540
1541pub fn getSymbolRef(self: ZigObject, index: Symbol.Index, macho_file: *MachO) MachO.Ref {
1542 const global_index = self.globals.items[index];
1543 if (macho_file.resolver.get(global_index)) |ref| return ref;
1544 return .{ .index = index, .file = self.index };
1545}
1546
1547pub fn addSymbolExtra(self: *ZigObject, allocator: Allocator, extra: Symbol.Extra) !u32 {
1548 const fields = @typeInfo(Symbol.Extra).Struct.fields;
1549 try self.symbols_extra.ensureUnusedCapacity(allocator, fields.len);
1550 return self.addSymbolExtraAssumeCapacity(extra);
1551}
1552
1553fn addSymbolExtraAssumeCapacity(self: *ZigObject, extra: Symbol.Extra) u32 {
1554 const index = @as(u32, @intCast(self.symbols_extra.items.len));
1555 const fields = @typeInfo(Symbol.Extra).Struct.fields;
1556 inline for (fields) |field| {
1557 self.symbols_extra.appendAssumeCapacity(switch (field.type) {
1558 u32 => @field(extra, field.name),
1559 else => @compileError("bad field type"),
1560 });
1561 }
1562 return index;
1563}
1564
1565pub fn getSymbolExtra(self: ZigObject, index: u32) Symbol.Extra {
1566 const fields = @typeInfo(Symbol.Extra).Struct.fields;
1567 var i: usize = index;
1568 var result: Symbol.Extra = undefined;
1569 inline for (fields) |field| {
1570 @field(result, field.name) = switch (field.type) {
1571 u32 => self.symbols_extra.items[i],
1572 else => @compileError("bad field type"),
1573 };
1574 i += 1;
1575 }
1576 return result;
1577}
1578
1579pub fn setSymbolExtra(self: *ZigObject, index: u32, extra: Symbol.Extra) void {
1580 const fields = @typeInfo(Symbol.Extra).Struct.fields;
1581 inline for (fields, 0..) |field, i| {
1582 self.symbols_extra.items[index + i] = switch (field.type) {
1583 u32 => @field(extra, field.name),
1584 else => @compileError("bad field type"),
1585 };
1586 }
1587}
1588
1481pub fn asFile(self: *ZigObject) File {1589pub fn asFile(self: *ZigObject) File {
1482 return .{ .zig_object = self };1590 return .{ .zig_object = self };
1483}1591}
...@@ -1503,9 +1611,16 @@ fn formatSymtab(...@@ -1503,9 +1611,16 @@ fn formatSymtab(
1503 _ = unused_fmt_string;1611 _ = unused_fmt_string;
1504 _ = options;1612 _ = options;
1505 try writer.writeAll(" symbols\n");1613 try writer.writeAll(" symbols\n");
1506 for (ctx.self.symbols.items) |index| {1614 const self = ctx.self;
1507 const sym = ctx.macho_file.getSymbol(index);1615 const macho_file = ctx.macho_file;
1508 try writer.print(" {}\n", .{sym.fmt(ctx.macho_file)});1616 for (self.symbols.items, 0) |sym, i| {
1617 const ref = self.getSymbolRef(@intCast(i), macho_file);
1618 if (ref.getFile(macho_file) == null) {
1619 // TODO any better way of handling this?
1620 try writer.print(" {s} : unclaimed\n", .{sym.getName(macho_file)});
1621 } else {
1622 try writer.print(" {}\n", .{ref.getSymbol(macho_file).?.fmt(macho_file)});
1623 }
1509 }1624 }
1510}1625}
15111626
...@@ -1524,10 +1639,12 @@ fn formatAtoms(...@@ -1524,10 +1639,12 @@ fn formatAtoms(
1524) !void {1639) !void {
1525 _ = unused_fmt_string;1640 _ = unused_fmt_string;
1526 _ = options;1641 _ = options;
1642 const self = ctx.self;
1643 const macho_file = ctx.macho_file;
1527 try writer.writeAll(" atoms\n");1644 try writer.writeAll(" atoms\n");
1528 for (ctx.self.atoms.items) |atom_index| {1645 for (self.getAtoms()) |atom_index| {
1529 const atom = ctx.macho_file.getAtom(atom_index) orelse continue;1646 const atom = self.getAtom(atom_index) orelse continue;
1530 try writer.print(" {}\n", .{atom.fmt(ctx.macho_file)});1647 try writer.print(" {}\n", .{atom.fmt(macho_file)});
1531 }1648 }
1532}1649}
15331650