Commit 5b4c0cc1f9
Changed files (6)
src
src/arch/x86_64/Emit.zig
@@ -51,12 +51,12 @@ pub fn emitMir(emit: *Emit) Error!void {
});
} else if (emit.lower.bin_file.cast(link.File.MachO)) |macho_file| {
// Add relocation to the decl.
- const atom = macho_file.getSymbol(symbol.atom_index).getAtom(macho_file).?;
- const sym_index = macho_file.getZigObject().?.symbols.items[symbol.sym_index];
+ const zo = macho_file.getZigObject().?;
+ const atom = zo.symbols.items[symbol.atom_index].getAtom(macho_file).?;
try atom.addReloc(macho_file, .{
.tag = .@"extern",
.offset = end_offset - 4,
- .target = sym_index,
+ .target = symbol.sym_index,
.addend = 0,
.type = .branch,
.meta = .{
@@ -160,11 +160,11 @@ pub fn emitMir(emit: *Emit) Error!void {
.Obj => true,
.Lib => emit.lower.link_mode == .static,
};
- const atom = macho_file.getSymbol(data.atom_index).getAtom(macho_file).?;
- const sym_index = macho_file.getZigObject().?.symbols.items[data.sym_index];
- const sym = macho_file.getSymbol(sym_index);
+ const zo = macho_file.getZigObject().?;
+ const atom = zo.symbols.items[data.atom_index].getAtom(macho_file).?;
+ const sym = zo.symbols.items[data.sym_index];
if (sym.flags.needs_zig_got and !is_obj_or_static_lib) {
- _ = try sym.getOrCreateZigGotEntry(sym_index, macho_file);
+ _ = try sym.getOrCreateZigGotEntry(data.sym_index, macho_file);
}
const @"type": link.File.MachO.Relocation.Type = if (sym.flags.needs_zig_got and !is_obj_or_static_lib)
.zig_got_load
@@ -179,7 +179,7 @@ pub fn emitMir(emit: *Emit) Error!void {
try atom.addReloc(macho_file, .{
.tag = .@"extern",
.offset = @intCast(end_offset - 4),
- .target = sym_index,
+ .target = data.sym_index,
.addend = 0,
.type = @"type",
.meta = .{
src/arch/x86_64/Lower.zig
@@ -425,8 +425,8 @@ fn emit(lower: *Lower, prefix: Prefix, mnemonic: Mnemonic, ops: []const Operand)
else => unreachable,
};
} else if (lower.bin_file.cast(link.File.MachO)) |macho_file| {
- const sym_index = macho_file.getZigObject().?.symbols.items[sym.sym_index];
- const macho_sym = macho_file.getSymbol(sym_index);
+ const zo = macho_file.getZigObject().?;
+ const macho_sym = zo.symbols.items[sym.sym_index];
if (macho_sym.flags.tlv) {
_ = lower.reloc(.{ .linker_reloc = sym });
src/link/MachO/Atom.zig
@@ -423,7 +423,6 @@ pub fn addReloc(self: *Atom, macho_file: *MachO, reloc: Relocation) !void {
const gpa = macho_file.base.comp.gpa;
const file = self.getFile(macho_file);
assert(file == .zig_object);
- assert(self.flags.relocs);
var extra = self.getExtra(macho_file).?;
const rels = &file.zig_object.relocs.items[extra.rel_index];
try rels.append(gpa, reloc);
@@ -432,7 +431,6 @@ pub fn addReloc(self: *Atom, macho_file: *MachO, reloc: Relocation) !void {
}
pub fn freeRelocs(self: *Atom, macho_file: *MachO) void {
- if (!self.flags.relocs) return;
self.getFile(macho_file).zig_object.freeAtomRelocs(self.*, macho_file);
var extra = self.getExtra(macho_file).?;
extra.rel_count = 0;
src/link/MachO/ZigObject.zig
@@ -6,9 +6,15 @@ index: File.Index,
symtab: std.MultiArrayList(Nlist) = .{},
strtab: StringTable = .{},
-symbols: std.ArrayListUnmanaged(Symbol.Index) = .{},
-atoms: std.ArrayListUnmanaged(Atom.Index) = .{},
-globals_lookup: std.AutoHashMapUnmanaged(u32, Symbol.Index) = .{},
+symbols: std.ArrayListUnmanaged(Symbol) = .{},
+symbols_extra: std.ArrayListUnmanaged(u32) = .{},
+globals: std.ArrayListUnmanaged(MachO.SymbolResolver.Index) = .{},
+/// Maps string index (so name) into nlist index for the global symbol defined within this
+/// module.
+globals_lookup: std.AutoHashMapUnmanaged(u32, u32) = .{},
+atoms: std.ArrayListUnmanaged(Atom) = .{},
+atoms_indexes: std.ArrayListUnmanaged(Atom.Index) = .{},
+atoms_extra: std.ArrayListUnmanaged(u32) = .{},
/// Table of tracked LazySymbols.
lazy_syms: LazySymbolTable = .{},
@@ -58,10 +64,13 @@ debug_info_header_dirty: bool = false,
debug_line_header_dirty: bool = false,
pub fn init(self: *ZigObject, macho_file: *MachO) !void {
+ const tracy = trace(@src());
+ defer tracy.end();
+
const comp = macho_file.base.comp;
const gpa = comp.gpa;
- try self.atoms.append(gpa, 0); // null input section
+ try self.atoms.append(gpa, .{ .extra = try self.addAtomExtra(gpa, .{}) }); // null input section
try self.strtab.buffer.append(gpa, 0);
switch (comp.config.debug_format) {
@@ -84,8 +93,12 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void {
self.symtab.deinit(allocator);
self.strtab.deinit(allocator);
self.symbols.deinit(allocator);
- self.atoms.deinit(allocator);
+ self.symbols_extra.deinit(allocator);
+ self.globals.deinit(allocator);
self.globals_lookup.deinit(allocator);
+ self.atoms.deinit(allocator);
+ self.atoms_indexes.deinit(allocator);
+ self.atoms_extra.deinit(allocator);
{
var it = self.decls.iterator();
@@ -139,32 +152,21 @@ fn addNlist(self: *ZigObject, allocator: Allocator) !Symbol.Index {
return index;
}
-pub fn addAtom(self: *ZigObject, macho_file: *MachO) !Symbol.Index {
- const gpa = macho_file.base.comp.gpa;
- const atom_index = try macho_file.addAtom();
- const symbol_index = try macho_file.addSymbol();
- const nlist_index = try self.addNlist(gpa);
-
- try self.atoms.append(gpa, atom_index);
- try self.symbols.append(gpa, symbol_index);
-
- const atom = macho_file.getAtom(atom_index).?;
- atom.file = self.index;
- atom.atom_index = atom_index;
-
- const symbol = macho_file.getSymbol(symbol_index);
- symbol.file = self.index;
- symbol.atom = atom_index;
-
+pub fn createAtomForDecl(self: *ZigObject, allocator: Allocator, macho_file: *MachO) !Symbol.Index {
+ const atom_index = try self.addAtom(allocator);
+ const symbol_index = try self.addSymbol(allocator);
+ const nlist_index = try self.addNlist(allocator);
self.symtab.items(.atom)[nlist_index] = atom_index;
+ try self.atoms_indexes.append(allocator, atom_index);
+ const symbol = &self.symbols.items[symbol_index];
+ symbol.atom_ref = .{ .index = atom_index, .file = self.index };
symbol.nlist_idx = nlist_index;
-
+ symbol.extra = try self.addSymbolExtra(allocator, .{});
const relocs_index = @as(u32, @intCast(self.relocs.items.len));
- const relocs = try self.relocs.addOne(gpa);
+ const relocs = try self.relocs.addOne(allocator);
relocs.* = .{};
- try atom.addExtra(.{ .rel_index = relocs_index, .rel_count = 0 }, macho_file);
- atom.flags.relocs = true;
-
+ const atom = self.getAtom(atom_index).?;
+ atom.addExtra(.{ .rel_index = relocs_index, .rel_count = 0 }, macho_file);
return symbol_index;
}
@@ -191,89 +193,51 @@ pub fn getAtomData(self: ZigObject, macho_file: *MachO, atom: Atom, buffer: []u8
}
pub fn getAtomRelocs(self: *ZigObject, atom: Atom, macho_file: *MachO) []const Relocation {
- if (!atom.flags.relocs) return &[0]Relocation{};
- const extra = atom.getExtra(macho_file).?;
+ const extra = atom.getExtra(macho_file);
const relocs = self.relocs.items[extra.rel_index];
return relocs.items[0..extra.rel_count];
}
pub fn freeAtomRelocs(self: *ZigObject, atom: Atom, macho_file: *MachO) void {
- if (atom.flags.relocs) {
- const extra = atom.getExtra(macho_file).?;
- self.relocs.items[extra.rel_index].clearRetainingCapacity();
- }
+ const extra = atom.getExtra(macho_file);
+ self.relocs.items[extra.rel_index].clearRetainingCapacity();
}
-pub fn resolveSymbols(self: *ZigObject, macho_file: *MachO) void {
+pub fn resolveSymbols(self: *ZigObject, macho_file: *MachO) !void {
const tracy = trace(@src());
defer tracy.end();
- for (self.symbols.items, 0..) |index, i| {
- const nlist_idx = @as(Symbol.Index, @intCast(i));
- const nlist = self.symtab.items(.nlist)[nlist_idx];
- const atom_index = self.symtab.items(.atom)[nlist_idx];
+ const gpa = macho_file.base.comp.gpa;
+ for (self.symtab.items(.nlist), self.symtab.items(.atom), self.globals.items, 0..) |nlist, atom_index, *global, i| {
if (!nlist.ext()) continue;
- if (nlist.undf() and !nlist.tentative()) continue;
if (nlist.sect()) {
- const atom = macho_file.getAtom(atom_index).?;
+ const atom = self.getAtom(atom_index).?;
if (!atom.flags.alive) continue;
}
- const symbol = macho_file.getSymbol(index);
+ const gop = try macho_file.resolver.getOrPut(gpa, .{
+ .index = @intCast(i),
+ .file = self.index,
+ }, macho_file);
+ if (!gop.found_existing) {
+ gop.ref.* = .{ .index = 0, .file = 0 };
+ }
+ global.* = gop.index;
+
+ if (nlist.undf() and !nlist.tentative()) continue;
+ if (gop.ref.getFile(macho_file) == null) {
+ gop.ref.* = .{ .index = @intCast(i), .file = self.index };
+ continue;
+ }
+
if (self.asFile().getSymbolRank(.{
.archive = false,
.weak = nlist.weakDef(),
.tentative = nlist.tentative(),
- }) < symbol.getSymbolRank(macho_file)) {
- const value = if (nlist.sect()) blk: {
- const atom = macho_file.getAtom(atom_index).?;
- break :blk nlist.n_value - atom.getInputAddress(macho_file);
- } else nlist.n_value;
- const out_n_sect = if (nlist.sect()) macho_file.getAtom(atom_index).?.out_n_sect else 0;
- symbol.value = value;
- symbol.atom = atom_index;
- symbol.out_n_sect = out_n_sect;
- symbol.nlist_idx = nlist_idx;
- symbol.file = self.index;
- symbol.flags.weak = nlist.weakDef();
- symbol.flags.abs = nlist.abs();
- symbol.flags.tentative = nlist.tentative();
- symbol.flags.weak_ref = false;
- symbol.flags.dyn_ref = nlist.n_desc & macho.REFERENCED_DYNAMICALLY != 0;
- symbol.flags.no_dead_strip = symbol.flags.no_dead_strip or nlist.noDeadStrip();
- // TODO: symbol.flags.interposable = macho_file.base.isDynLib() and macho_file.options.namespace == .flat and !nlist.pext();
- symbol.flags.interposable = false;
-
- if (nlist.sect() and
- macho_file.sections.items(.header)[nlist.n_sect - 1].type() == macho.S_THREAD_LOCAL_VARIABLES)
- {
- symbol.flags.tlv = true;
- }
+ }) < gop.ref.getSymbol(macho_file).?.getSymbolRank(macho_file)) {
+ gop.ref.* = .{ .index = @intCast(i), .file = self.index };
}
-
- // Regardless of who the winner is, we still merge symbol visibility here.
- if (nlist.pext() or (nlist.weakDef() and nlist.weakRef())) {
- if (symbol.visibility != .global) {
- symbol.visibility = .hidden;
- }
- } else {
- symbol.visibility = .global;
- }
- }
-}
-
-pub fn resetGlobals(self: *ZigObject, macho_file: *MachO) void {
- for (self.symbols.items, 0..) |sym_index, nlist_idx| {
- if (!self.symtab.items(.nlist)[nlist_idx].ext()) continue;
- const sym = macho_file.getSymbol(sym_index);
- const name = sym.name;
- const global = sym.flags.global;
- const weak_ref = sym.flags.weak_ref;
- sym.* = .{};
- sym.name = name;
- sym.flags.global = global;
- sym.flags.weak_ref = weak_ref;
}
}
@@ -281,12 +245,13 @@ pub fn markLive(self: *ZigObject, macho_file: *MachO) void {
const tracy = trace(@src());
defer tracy.end();
- for (self.symbols.items, 0..) |index, nlist_idx| {
- const nlist = self.symtab.items(.nlist)[nlist_idx];
+ for (0..self.symbols.items.len) |i| {
+ const nlist = self.symtab.items(.nlist)[i];
if (!nlist.ext()) continue;
- const sym = macho_file.getSymbol(index);
- const file = sym.getFile(macho_file) orelse continue;
+ const ref = self.getSymbolRef(@intCast(i), macho_file);
+ const file = ref.getFile(macho_file) orelse continue;
+ const sym = ref.getSymbol(macho_file).?;
const should_keep = nlist.undf() or (nlist.tentative() and !sym.flags.tentative);
if (should_keep and file == .object and !file.object.alive) {
file.object.alive = true;
@@ -295,24 +260,41 @@ pub fn markLive(self: *ZigObject, macho_file: *MachO) void {
}
}
-pub fn checkDuplicates(self: *ZigObject, dupes: anytype, macho_file: *MachO) !void {
- for (self.symbols.items, 0..) |index, nlist_idx| {
- const sym = macho_file.getSymbol(index);
- if (sym.visibility != .global) continue;
- const file = sym.getFile(macho_file) orelse continue;
- if (file.getIndex() == self.index) continue;
-
- const nlist = self.symtab.items(.nlist)[nlist_idx];
- if (!nlist.undf() and !nlist.tentative() and !(nlist.weakDef() or nlist.pext())) {
- const gop = try dupes.getOrPut(index);
- if (!gop.found_existing) {
- gop.value_ptr.* = .{};
- }
- try gop.value_ptr.append(macho_file.base.comp.gpa, self.index);
+pub fn mergeSymbolVisibility(self: *ZigObject, macho_file: *MachO) void {
+ const tracy = trace(@src());
+ defer tracy.end();
+
+ for (self.symbols.items, 0..) |sym, i| {
+ const ref = self.getSymbolRef(@intCast(i), macho_file);
+ const global = ref.getSymbol(macho_file) orelse continue;
+ if (global.visibility != .global) {
+ global.visibility = sym.visibility;
+ }
+ if (sym.flags.weak_ref) {
+ global.flags.weak_ref = true;
}
}
}
+// TODO
+// pub fn checkDuplicates(self: *ZigObject, dupes: anytype, macho_file: *MachO) !void {
+// for (self.symbols.items, 0..) |index, nlist_idx| {
+// const sym = macho_file.getSymbol(index);
+// if (sym.visibility != .global) continue;
+// const file = sym.getFile(macho_file) orelse continue;
+// if (file.getIndex() == self.index) continue;
+
+// const nlist = self.symtab.items(.nlist)[nlist_idx];
+// if (!nlist.undf() and !nlist.tentative() and !(nlist.weakDef() or nlist.pext())) {
+// const gop = try dupes.getOrPut(index);
+// if (!gop.found_existing) {
+// gop.value_ptr.* = .{};
+// }
+// try gop.value_ptr.append(macho_file.base.comp.gpa, self.index);
+// }
+// }
+// }
+
pub fn resolveLiterals(self: *ZigObject, lp: *MachO.LiteralPool, macho_file: *MachO) !void {
_ = self;
_ = lp;
@@ -362,8 +344,8 @@ pub fn writeAr(self: ZigObject, ar_format: Archive.Format, writer: anytype) !voi
}
pub fn scanRelocs(self: *ZigObject, macho_file: *MachO) !void {
- for (self.atoms.items) |atom_index| {
- const atom = macho_file.getAtom(atom_index) orelse continue;
+ for (self.getAtoms()) |atom_index| {
+ const atom = self.getAtom(atom_index) orelse continue;
if (!atom.flags.alive) continue;
const sect = atom.getInputSection(macho_file);
if (sect.isZerofill()) continue;
@@ -371,46 +353,49 @@ pub fn scanRelocs(self: *ZigObject, macho_file: *MachO) !void {
}
}
-pub fn calcSymtabSize(self: *ZigObject, macho_file: *MachO) !void {
+pub fn calcSymtabSize(self: *ZigObject, macho_file: *MachO) void {
const tracy = trace(@src());
defer tracy.end();
- for (self.symbols.items) |sym_index| {
- const sym = macho_file.getSymbol(sym_index);
- const file = sym.getFile(macho_file) orelse continue;
+ for (self.symbols.items, 0..) |*sym, i| {
+ const ref = self.getSymbolRef(@intCast(i), macho_file);
+ const file = ref.getFile(macho_file) orelse continue;
if (file.getIndex() != self.index) continue;
if (sym.getAtom(macho_file)) |atom| if (!atom.flags.alive) continue;
sym.flags.output_symtab = true;
if (sym.isLocal()) {
- try sym.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, macho_file);
+ sym.addExtra(.{ .symtab = self.output_symtab_ctx.nlocals }, macho_file);
self.output_symtab_ctx.nlocals += 1;
} else if (sym.flags.@"export") {
- try sym.addExtra(.{ .symtab = self.output_symtab_ctx.nexports }, macho_file);
+ sym.addExtra(.{ .symtab = self.output_symtab_ctx.nexports }, macho_file);
self.output_symtab_ctx.nexports += 1;
} else {
assert(sym.flags.import);
- try sym.addExtra(.{ .symtab = self.output_symtab_ctx.nimports }, macho_file);
+ sym.addExtra(.{ .symtab = self.output_symtab_ctx.nimports }, macho_file);
self.output_symtab_ctx.nimports += 1;
}
self.output_symtab_ctx.strsize += @as(u32, @intCast(sym.getName(macho_file).len + 1));
}
}
-pub fn writeSymtab(self: ZigObject, macho_file: *MachO, ctx: anytype) void {
+pub fn writeSymtab(self: ZigObject, macho_file: *MachO) void {
const tracy = trace(@src());
defer tracy.end();
- for (self.symbols.items) |sym_index| {
- const sym = macho_file.getSymbol(sym_index);
- const file = sym.getFile(macho_file) orelse continue;
+ var n_strx = self.output_symtab_ctx.stroff;
+ for (self.symbols.items, 0..) |sym, i| {
+ const ref = self.getSymbolRef(@intCast(i), macho_file);
+ const file = ref.getFile(macho_file) orelse continue;
if (file.getIndex() != self.index) continue;
const idx = sym.getOutputSymtabIndex(macho_file) orelse continue;
- const n_strx = @as(u32, @intCast(ctx.strtab.items.len));
- ctx.strtab.appendSliceAssumeCapacity(sym.getName(macho_file));
- ctx.strtab.appendAssumeCapacity(0);
- const out_sym = &ctx.symtab.items[idx];
+ const out_sym = &macho_file.symtab.items[idx];
out_sym.n_strx = n_strx;
sym.setOutputSym(macho_file, out_sym);
+ const name = sym.getName(macho_file);
+ @memcpy(macho_file.strtab.items[n_strx..][0..name.len], name);
+ n_strx += @intCast(name.len);
+ macho_file.strtab.items[n_strx] = 0;
+ n_strx += 1;
}
}
@@ -523,9 +508,9 @@ pub fn getDeclVAddr(
reloc_info: link.File.RelocInfo,
) !u64 {
const sym_index = try self.getOrCreateMetadataForDecl(macho_file, decl_index);
- const sym = macho_file.getSymbol(sym_index);
+ const sym = self.symbols.items[sym_index];
const vaddr = sym.getAddress(.{}, macho_file);
- const parent_atom = macho_file.getSymbol(reloc_info.parent_atom_index).getAtom(macho_file).?;
+ const parent_atom = self.symbols.items[reloc_info.parent_atom_index].getAtom(macho_file).?;
try parent_atom.addReloc(macho_file, .{
.tag = .@"extern",
.offset = @intCast(reloc_info.offset),
@@ -549,9 +534,9 @@ pub fn getAnonDeclVAddr(
reloc_info: link.File.RelocInfo,
) !u64 {
const sym_index = self.anon_decls.get(decl_val).?.symbol_index;
- const sym = macho_file.getSymbol(sym_index);
+ const sym = self.symbols.items[sym_index];
const vaddr = sym.getAddress(.{}, macho_file);
- const parent_atom = macho_file.getSymbol(reloc_info.parent_atom_index).getAtom(macho_file).?;
+ const parent_atom = self.symbols.items[reloc_info.parent_atom_index].getAtom(macho_file).?;
try parent_atom.addReloc(macho_file, .{
.tag = .@"extern",
.offset = @intCast(reloc_info.offset),
@@ -584,7 +569,7 @@ pub fn lowerAnonDecl(
else => explicit_alignment,
};
if (self.anon_decls.get(decl_val)) |metadata| {
- const existing_alignment = macho_file.getSymbol(metadata.symbol_index).getAtom(macho_file).?.alignment;
+ const existing_alignment = self.symbols.items[metadata.symbol_index].getAtom(macho_file).?.alignment;
if (decl_alignment.order(existing_alignment).compare(.lte))
return .ok;
}
@@ -628,13 +613,10 @@ fn freeUnnamedConsts(self: *ZigObject, macho_file: *MachO, decl_index: InternPoo
}
fn freeDeclMetadata(self: *ZigObject, macho_file: *MachO, sym_index: Symbol.Index) void {
- _ = self;
- const gpa = macho_file.base.comp.gpa;
- const sym = macho_file.getSymbol(sym_index);
+ const sym = self.symbols.items[sym_index];
sym.getAtom(macho_file).?.free(macho_file);
log.debug("adding %{d} to local symbols free list", .{sym_index});
- macho_file.symbols_free_list.append(gpa, sym_index) catch {};
- macho_file.symbols.items[sym_index] = .{};
+ // TODO redo this
// TODO free GOT entry here
}
@@ -675,7 +657,7 @@ pub fn updateFunc(
const sym_index = try self.getOrCreateMetadataForDecl(macho_file, decl_index);
self.freeUnnamedConsts(macho_file, decl_index);
- macho_file.getSymbol(sym_index).getAtom(macho_file).?.freeRelocs(macho_file);
+ self.symbols.items[sym_index].getAtom(macho_file).?.freeRelocs(macho_file);
var code_buffer = std.ArrayList(u8).init(gpa);
defer code_buffer.deinit();
@@ -708,7 +690,7 @@ pub fn updateFunc(
try self.updateDeclCode(macho_file, pt, decl_index, sym_index, sect_index, code);
if (decl_state) |*ds| {
- const sym = macho_file.getSymbol(sym_index);
+ const sym = self.symbols.items[sym_index];
try self.dwarf.?.commitDeclState(
pt,
decl_index,
@@ -743,13 +725,13 @@ pub fn updateDecl(
const name = decl.name.toSlice(&mod.intern_pool);
const lib_name = variable.lib_name.toSlice(&mod.intern_pool);
const index = try self.getGlobalSymbol(macho_file, name, lib_name);
- const actual_index = self.symbols.items[index];
- macho_file.getSymbol(actual_index).flags.needs_got = true;
+ const sym = &self.symbols.items[index];
+ sym.flags.needs_got = true;
return;
}
const sym_index = try self.getOrCreateMetadataForDecl(macho_file, decl_index);
- macho_file.getSymbol(sym_index).getAtom(macho_file).?.freeRelocs(macho_file);
+ self.symbols.items[sym_index].getAtom(macho_file).?.freeRelocs(macho_file);
const gpa = macho_file.base.comp.gpa;
var code_buffer = std.ArrayList(u8).init(gpa);
@@ -784,7 +766,7 @@ pub fn updateDecl(
}
if (decl_state) |*ds| {
- const sym = macho_file.getSymbol(sym_index);
+ const sym = self.symbols.items[sym_index];
try self.dwarf.?.commitDeclState(
pt,
decl_index,
@@ -816,7 +798,7 @@ fn updateDeclCode(
const required_alignment = decl.getAlignment(pt);
const sect = &macho_file.sections.items(.header)[sect_index];
- const sym = macho_file.getSymbol(sym_index);
+ const sym = &self.symbols.items[sym_index];
const nlist = &self.symtab.items(.nlist)[sym.nlist_idx];
const atom = sym.getAtom(macho_file).?;
@@ -850,13 +832,13 @@ fn updateDeclCode(
if (!macho_file.base.isRelocatable()) {
log.debug(" (updating offset table entry)", .{});
assert(sym.flags.has_zig_got);
- const extra = sym.getExtra(macho_file).?;
+ const extra = sym.getExtra(macho_file);
try macho_file.zig_got.writeOne(macho_file, extra.zig_got);
}
}
} else if (code.len < old_size) {
atom.shrink(macho_file);
- } else if (macho_file.getAtom(atom.next_index) == null) {
+ } else if (self.getAtom(atom.next_index) == null) {
const needed_size = atom.value + code.len;
sect.size = needed_size;
}
@@ -922,8 +904,8 @@ fn createTlvInitializer(
const sym_name = try std.fmt.allocPrint(gpa, "{s}$tlv$init", .{name});
defer gpa.free(sym_name);
- const sym_index = try self.addAtom(macho_file);
- const sym = macho_file.getSymbol(sym_index);
+ const sym_index = try self.createAtomForDecl(gpa, macho_file);
+ const sym = &self.symbols.items[sym_index];
const nlist = &self.symtab.items(.nlist)[sym.nlist_idx];
const atom = sym.getAtom(macho_file).?;
@@ -945,7 +927,6 @@ fn createTlvInitializer(
const slice = macho_file.sections.slice();
const header = slice.items(.header)[sect_index];
- const atoms = &slice.items(.atoms)[sect_index];
const gop = try self.tlv_initializers.getOrPut(gpa, atom.atom_index);
assert(!gop.found_existing); // TODO incremental updates
@@ -956,8 +937,6 @@ fn createTlvInitializer(
gop.value_ptr.data = try gpa.dupe(u8, code);
}
- try atoms.append(gpa, atom.atom_index);
-
return sym_index;
}
@@ -970,7 +949,7 @@ fn createTlvDescriptor(
) !void {
const gpa = macho_file.base.comp.gpa;
- const sym = macho_file.getSymbol(sym_index);
+ const sym = &self.symbols.items[sym_index];
const nlist = &self.symtab.items(.nlist)[sym.nlist_idx];
const atom = sym.getAtom(macho_file).?;
const alignment = Atom.Alignment.fromNonzeroByteUnits(@alignOf(u64));
@@ -1000,7 +979,7 @@ fn createTlvDescriptor(
try atom.addReloc(macho_file, .{
.tag = .@"extern",
.offset = 0,
- .target = self.symbols.items[tlv_bootstrap_index],
+ .target = tlv_bootstrap_index,
.addend = 0,
.type = .unsigned,
.meta = .{
@@ -1020,11 +999,14 @@ fn createTlvDescriptor(
.pcrel = false,
.has_subtractor = false,
.length = 3,
- .symbolnum = @intCast(macho_file.getSymbol(init_sym_index).nlist_idx),
+ .symbolnum = @intCast(init_sym_index),
},
});
- try macho_file.sections.items(.atoms)[sect_index].append(gpa, atom.atom_index);
+ try macho_file.sections.items(.atoms)[sect_index].append(gpa, .{
+ .index = atom.atom_index,
+ .file = self.index,
+ });
}
fn getDeclOutputSection(
@@ -1115,7 +1097,7 @@ pub fn lowerUnnamedConst(
return error.CodegenFail;
},
};
- const sym = macho_file.getSymbol(sym_index);
+ const sym = self.symbols.items[sym_index];
try unnamed_consts.append(gpa, sym.atom);
return sym_index;
}
@@ -1140,7 +1122,7 @@ fn lowerConst(
var code_buffer = std.ArrayList(u8).init(gpa);
defer code_buffer.deinit();
- const sym_index = try self.addAtom(macho_file);
+ const sym_index = try self.createAtomForDecl(gpa, macho_file);
const res = try codegen.generateSymbol(&macho_file.base, pt, src_loc, val, &code_buffer, .{
.none = {},
@@ -1152,7 +1134,7 @@ fn lowerConst(
.fail => |em| return .{ .fail = em },
};
- const sym = macho_file.getSymbol(sym_index);
+ const sym = &self.symbols.items[sym_index];
const name_str_index = try self.strtab.insert(gpa, name);
sym.name = name_str_index;
sym.out_n_sect = output_section_index;
@@ -1218,7 +1200,7 @@ pub fn updateExports(
},
};
const sym_index = metadata.symbol_index;
- const nlist_idx = macho_file.getSymbol(sym_index).nlist_idx;
+ const nlist_idx = self.symbols.items[sym_index].nlist_idx;
const nlist = self.symtab.items(.nlist)[nlist_idx];
for (export_indices) |export_idx| {
@@ -1322,7 +1304,7 @@ fn updateLazySymbol(
.code => macho_file.zig_text_sect_index.?,
.const_data => macho_file.zig_const_sect_index.?,
};
- const sym = macho_file.getSymbol(symbol_index);
+ const sym = &self.symbols.items[symbol_index];
sym.name = name_str_index;
sym.out_n_sect = output_section_index;
@@ -1382,12 +1364,12 @@ pub fn deleteExport(
const nlist = &self.symtab.items(.nlist)[nlist_index.*];
self.symtab.items(.size)[nlist_index.*] = 0;
_ = self.globals_lookup.remove(nlist.n_strx);
- const sym_index = macho_file.globals.get(nlist.n_strx).?;
- const sym = macho_file.getSymbol(sym_index);
- if (sym.file == self.index) {
- _ = macho_file.globals.swapRemove(nlist.n_strx);
- sym.* = .{};
- }
+ // TODO actually remove the export
+ // const sym_index = macho_file.globals.get(nlist.n_strx).?;
+ // const sym = &self.symbols.items[sym_index];
+ // if (sym.file == self.index) {
+ // sym.* = .{};
+ // }
nlist.* = MachO.null_sym;
}
@@ -1404,9 +1386,11 @@ pub fn getGlobalSymbol(self: *ZigObject, macho_file: *MachO, name: []const u8, l
nlist.n_strx = off;
nlist.n_type = macho.N_EXT;
lookup_gop.value_ptr.* = nlist_index;
- const global_name_off = try macho_file.strings.insert(gpa, sym_name);
- const gop = try macho_file.getOrCreateGlobal(global_name_off);
- try self.symbols.append(gpa, gop.index);
+ _ = try macho_file.resolver.getOrPut(gpa, .{
+ .index = nlist_index,
+ .file = self.index,
+ }, macho_file);
+ try self.globals.append(gpa, nlist_index);
}
return lookup_gop.value_ptr.*;
}
@@ -1420,10 +1404,10 @@ pub fn getOrCreateMetadataForDecl(
const gop = try self.decls.getOrPut(gpa, decl_index);
if (!gop.found_existing) {
const any_non_single_threaded = macho_file.base.comp.config.any_non_single_threaded;
- const sym_index = try self.addAtom(macho_file);
+ const sym_index = try self.createAtomForDecl(gpa, macho_file);
const mod = macho_file.base.comp.module.?;
const decl = mod.declPtr(decl_index);
- const sym = macho_file.getSymbol(sym_index);
+ const sym = &self.symbols.items[sym_index];
if (decl.getOwnedVariable(mod)) |variable| {
if (variable.is_threadlocal and any_non_single_threaded) {
sym.flags.tlv = true;
@@ -1463,8 +1447,8 @@ pub fn getOrCreateMetadataForLazySymbol(
};
switch (metadata.state.*) {
.unused => {
- const symbol_index = try self.addAtom(macho_file);
- const sym = macho_file.getSymbol(symbol_index);
+ const symbol_index = try self.createAtomForDecl(gpa, macho_file);
+ const sym = &self.symbols.items[symbol_index];
sym.flags.needs_zig_got = true;
metadata.symbol_index.* = symbol_index;
},
@@ -1478,6 +1462,130 @@ pub fn getOrCreateMetadataForLazySymbol(
return symbol_index;
}
+fn addAtom(self: *ZigObject, allocator: Allocator) !Atom.Index {
+ const atom_index: Atom.Index = @intCast(self.atoms.items.len);
+ const atom = try self.atoms.addOne(allocator);
+ atom.* = .{
+ .file = self.index,
+ .atom_index = atom_index,
+ .extra = try self.addAtomExtra(allocator, .{}),
+ };
+ return atom_index;
+}
+
+pub fn getAtom(self: *ZigObject, atom_index: Atom.Index) ?*Atom {
+ if (atom_index == 0) return null;
+ assert(atom_index < self.atoms.items.len);
+ return &self.atoms.items[atom_index];
+}
+
+pub fn getAtoms(self: *ZigObject) []const Atom.Index {
+ return self.atoms_indexes.items;
+}
+
+fn addAtomExtra(self: *ZigObject, allocator: Allocator, extra: Atom.Extra) !u32 {
+ const fields = @typeInfo(Atom.Extra).Struct.fields;
+ try self.atoms_extra.ensureUnusedCapacity(allocator, fields.len);
+ return self.addAtomExtraAssumeCapacity(extra);
+}
+
+fn addAtomExtraAssumeCapacity(self: *ZigObject, extra: Atom.Extra) u32 {
+ const index = @as(u32, @intCast(self.atoms_extra.items.len));
+ const fields = @typeInfo(Atom.Extra).Struct.fields;
+ inline for (fields) |field| {
+ self.atoms_extra.appendAssumeCapacity(switch (field.type) {
+ u32 => @field(extra, field.name),
+ else => @compileError("bad field type"),
+ });
+ }
+ return index;
+}
+
+pub fn getAtomExtra(self: ZigObject, index: u32) Atom.Extra {
+ const fields = @typeInfo(Atom.Extra).Struct.fields;
+ var i: usize = index;
+ var result: Atom.Extra = undefined;
+ inline for (fields) |field| {
+ @field(result, field.name) = switch (field.type) {
+ u32 => self.atoms_extra.items[i],
+ else => @compileError("bad field type"),
+ };
+ i += 1;
+ }
+ return result;
+}
+
+pub fn setAtomExtra(self: *ZigObject, index: u32, extra: Atom.Extra) void {
+ assert(index > 0);
+ const fields = @typeInfo(Atom.Extra).Struct.fields;
+ inline for (fields, 0..) |field, i| {
+ self.atoms_extra.items[index + i] = switch (field.type) {
+ u32 => @field(extra, field.name),
+ else => @compileError("bad field type"),
+ };
+ }
+}
+
+fn addSymbol(self: *ZigObject, allocator: Allocator) !Symbol.Index {
+ try self.symbols.ensureUnusedCapacity(allocator, 1);
+ return self.addSymbolAssumeCapacity();
+}
+
+fn addSymbolAssumeCapacity(self: *ZigObject) Symbol.Index {
+ const index: Symbol.Index = @intCast(self.symbols.items.len);
+ const symbol = self.symbols.addOneAssumeCapacity();
+ symbol.* = .{ .file = self.index };
+ return index;
+}
+
+pub fn getSymbolRef(self: ZigObject, index: Symbol.Index, macho_file: *MachO) MachO.Ref {
+ const global_index = self.globals.items[index];
+ if (macho_file.resolver.get(global_index)) |ref| return ref;
+ return .{ .index = index, .file = self.index };
+}
+
+pub fn addSymbolExtra(self: *ZigObject, allocator: Allocator, extra: Symbol.Extra) !u32 {
+ const fields = @typeInfo(Symbol.Extra).Struct.fields;
+ try self.symbols_extra.ensureUnusedCapacity(allocator, fields.len);
+ return self.addSymbolExtraAssumeCapacity(extra);
+}
+
+fn addSymbolExtraAssumeCapacity(self: *ZigObject, extra: Symbol.Extra) u32 {
+ const index = @as(u32, @intCast(self.symbols_extra.items.len));
+ const fields = @typeInfo(Symbol.Extra).Struct.fields;
+ inline for (fields) |field| {
+ self.symbols_extra.appendAssumeCapacity(switch (field.type) {
+ u32 => @field(extra, field.name),
+ else => @compileError("bad field type"),
+ });
+ }
+ return index;
+}
+
+pub fn getSymbolExtra(self: ZigObject, index: u32) Symbol.Extra {
+ const fields = @typeInfo(Symbol.Extra).Struct.fields;
+ var i: usize = index;
+ var result: Symbol.Extra = undefined;
+ inline for (fields) |field| {
+ @field(result, field.name) = switch (field.type) {
+ u32 => self.symbols_extra.items[i],
+ else => @compileError("bad field type"),
+ };
+ i += 1;
+ }
+ return result;
+}
+
+pub fn setSymbolExtra(self: *ZigObject, index: u32, extra: Symbol.Extra) void {
+ const fields = @typeInfo(Symbol.Extra).Struct.fields;
+ inline for (fields, 0..) |field, i| {
+ self.symbols_extra.items[index + i] = switch (field.type) {
+ u32 => @field(extra, field.name),
+ else => @compileError("bad field type"),
+ };
+ }
+}
+
pub fn asFile(self: *ZigObject) File {
return .{ .zig_object = self };
}
@@ -1503,9 +1611,16 @@ fn formatSymtab(
_ = unused_fmt_string;
_ = options;
try writer.writeAll(" symbols\n");
- for (ctx.self.symbols.items) |index| {
- const sym = ctx.macho_file.getSymbol(index);
- try writer.print(" {}\n", .{sym.fmt(ctx.macho_file)});
+ const self = ctx.self;
+ const macho_file = ctx.macho_file;
+ for (self.symbols.items, 0) |sym, i| {
+ const ref = self.getSymbolRef(@intCast(i), macho_file);
+ if (ref.getFile(macho_file) == null) {
+ // TODO any better way of handling this?
+ try writer.print(" {s} : unclaimed\n", .{sym.getName(macho_file)});
+ } else {
+ try writer.print(" {}\n", .{ref.getSymbol(macho_file).?.fmt(macho_file)});
+ }
}
}
@@ -1524,10 +1639,12 @@ fn formatAtoms(
) !void {
_ = unused_fmt_string;
_ = options;
+ const self = ctx.self;
+ const macho_file = ctx.macho_file;
try writer.writeAll(" atoms\n");
- for (ctx.self.atoms.items) |atom_index| {
- const atom = ctx.macho_file.getAtom(atom_index) orelse continue;
- try writer.print(" {}\n", .{atom.fmt(ctx.macho_file)});
+ for (self.getAtoms()) |atom_index| {
+ const atom = self.getAtom(atom_index) orelse continue;
+ try writer.print(" {}\n", .{atom.fmt(macho_file)});
}
}
src/link/MachO.zig
@@ -290,8 +290,10 @@ pub fn deinit(self: *MachO) void {
self.dylibs.deinit(gpa);
self.segments.deinit(gpa);
- for (self.sections.items(.atoms)) |*list| {
- list.deinit(gpa);
+ for (self.sections.items(.atoms), self.sections.items(.out), self.sections.items(.thunks)) |*atoms, *out, *thnks| {
+ atoms.deinit(gpa);
+ out.deinit(gpa);
+ thnks.deinit(gpa);
}
self.sections.deinit(gpa);
@@ -561,8 +563,8 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n
if (self.getZigObject()) |zo| {
var has_resolve_error = false;
- for (zo.atoms.items) |atom_index| {
- const atom = self.getAtom(atom_index) orelse continue;
+ for (zo.getAtoms()) |atom_index| {
+ const atom = zo.getAtom(atom_index) orelse continue;
if (!atom.flags.alive) continue;
const sect = &self.sections.items(.header)[atom.out_n_sect];
if (sect.isZerofill()) continue;
@@ -573,7 +575,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n
const atom_size = math.cast(usize, atom.size) orelse return error.Overflow;
const code = try gpa.alloc(u8, atom_size);
defer gpa.free(code);
- atom.getData(self, code) catch |err| switch (err) {
+ zo.getAtomData(self, atom.*, code) catch |err| switch (err) {
error.InputOutput => {
try self.reportUnexpectedError("fetching code for '{s}' failed", .{
atom.getName(self),
@@ -1524,7 +1526,7 @@ fn scanRelocs(self: *MachO) !void {
try self.getFile(index).?.object.scanRelocs(self);
}
if (self.getInternalObject()) |obj| {
- try obj.scanRelocs(self);
+ obj.scanRelocs(self);
}
try self.reportUndefs();
@@ -2394,7 +2396,7 @@ fn writeSectionsAndUpdateLinkeditSizes(self: *MachO) !void {
self.objc_stubs_sect_index,
}) |maybe_sect_id| {
if (maybe_sect_id) |sect_id| {
- const out = &slice.items(.out)[sect_id];
+ const out = slice.items(.out)[sect_id].items;
try self.writeSyntheticSection(sect_id, out);
}
}
@@ -3970,9 +3972,11 @@ pub const base_tag: link.File.Tag = link.File.Tag.macho;
const Section = struct {
header: macho.section_64,
segment_id: u8,
- atoms: std.ArrayListUnmanaged(Atom.Index) = .{},
+ atoms: std.ArrayListUnmanaged(Ref) = .{},
free_list: std.ArrayListUnmanaged(Atom.Index) = .{},
last_atom_index: Atom.Index = 0,
+ thunks: std.ArrayListUnmanaged(Thunk.Index) = .{},
+ out: std.ArrayListUnmanaged(u8) = .{},
};
pub const LiteralPool = struct {
@@ -4018,7 +4022,7 @@ pub const LiteralPool = struct {
return .{
.found_existing = gop.found_existing,
.index = @intCast(gop.index),
- .atom = &lp.values.items[gop.index],
+ .ref = &lp.values.items[gop.index],
};
}
src/codegen.zig
@@ -901,15 +901,16 @@ fn genDeclRef(
}
return GenResult.mcv(.{ .load_symbol = sym.esym_index });
} else if (lf.cast(link.File.MachO)) |macho_file| {
+ const zo = macho_file.getZigObject().?;
if (is_extern) {
const name = decl.name.toSlice(ip);
const lib_name = if (decl.getOwnedVariable(zcu)) |ov| ov.lib_name.toSlice(ip) else null;
const sym_index = try macho_file.getGlobalSymbol(name, lib_name);
- macho_file.getSymbol(macho_file.getZigObject().?.symbols.items[sym_index]).flags.needs_got = true;
+ zo.symbols.items[sym_index].flags.needs_got = true;
return GenResult.mcv(.{ .load_symbol = sym_index });
}
- const sym_index = try macho_file.getZigObject().?.getOrCreateMetadataForDecl(macho_file, decl_index);
- const sym = macho_file.getSymbol(sym_index);
+ const sym_index = try zo.getOrCreateMetadataForDecl(macho_file, decl_index);
+ const sym = zo.symbols.items[sym_index];
if (is_threadlocal) {
return GenResult.mcv(.{ .load_tlv = sym.nlist_idx });
}
@@ -956,7 +957,7 @@ fn genUnnamedConst(
},
.macho => {
const macho_file = lf.cast(link.File.MachO).?;
- const local = macho_file.getSymbol(local_sym_index);
+ const local = macho_file.getZigObject().?.symbols.items[local_sym_index];
return GenResult.mcv(.{ .load_symbol = local.nlist_idx });
},
.coff => {