macho: clean up atom+symbol creation logic in ZigObject

This commit is contained in:
Jakub Konka 2024-07-15 18:26:05 +02:00
parent e117e05768
commit 103c16c879
2 changed files with 79 additions and 66 deletions

View File

@ -52,8 +52,8 @@ pub fn init(self: *InternalObject, allocator: Allocator) !void {
}
pub fn initSymbols(self: *InternalObject, macho_file: *MachO) !void {
const createSymbol = struct {
fn createSymbol(obj: *InternalObject, name: u32, args: struct {
const newSymbolAssumeCapacity = struct {
fn newSymbolAssumeCapacity(obj: *InternalObject, name: u32, args: struct {
type: u8 = macho.N_UNDF | macho.N_EXT,
desc: u16 = 0,
}) Symbol.Index {
@ -78,7 +78,7 @@ pub fn initSymbols(self: *InternalObject, macho_file: *MachO) !void {
symbol.nlist_idx = nlist_idx;
return index;
}
}.createSymbol;
}.newSymbolAssumeCapacity;
const gpa = macho_file.base.comp.gpa;
var nsyms = macho_file.base.comp.force_undefined_symbols.keys().len;
@ -102,28 +102,28 @@ pub fn initSymbols(self: *InternalObject, macho_file: *MachO) !void {
try self.force_undefined.ensureTotalCapacityPrecise(gpa, macho_file.base.comp.force_undefined_symbols.keys().len);
for (macho_file.base.comp.force_undefined_symbols.keys()) |name| {
self.force_undefined.addOneAssumeCapacity().* = createSymbol(self, try self.addString(gpa, name), .{});
self.force_undefined.addOneAssumeCapacity().* = newSymbolAssumeCapacity(self, try self.addString(gpa, name), .{});
}
self.dyld_stub_binder_index = createSymbol(self, try self.addString(gpa, "dyld_stub_binder"), .{});
self.objc_msg_send_index = createSymbol(self, try self.addString(gpa, "_objc_msgSend"), .{});
self.dyld_stub_binder_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "dyld_stub_binder"), .{});
self.objc_msg_send_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "_objc_msgSend"), .{});
if (!macho_file.base.isDynLib()) {
self.entry_index = createSymbol(self, try self.addString(gpa, macho_file.entry_name orelse "_main"), .{});
self.mh_execute_header_index = createSymbol(self, try self.addString(gpa, "__mh_execute_header"), .{
self.entry_index = newSymbolAssumeCapacity(self, try self.addString(gpa, macho_file.entry_name orelse "_main"), .{});
self.mh_execute_header_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__mh_execute_header"), .{
.type = macho.N_SECT | macho.N_EXT,
.desc = macho.REFERENCED_DYNAMICALLY,
});
} else {
self.mh_dylib_header_index = createSymbol(self, try self.addString(gpa, "__mh_dylib_header"), .{
self.mh_dylib_header_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "__mh_dylib_header"), .{
.type = macho.N_SECT | macho.N_EXT,
});
}
self.dso_handle_index = createSymbol(self, try self.addString(gpa, "___dso_handle"), .{
self.dso_handle_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "___dso_handle"), .{
.type = macho.N_SECT | macho.N_EXT,
});
self.dyld_private_index = createSymbol(self, try self.addString(gpa, "dyld_private"), .{
self.dyld_private_index = newSymbolAssumeCapacity(self, try self.addString(gpa, "dyld_private"), .{
.type = macho.N_SECT,
});
}

View File

@ -141,34 +141,64 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void {
}
}
fn addNlist(self: *ZigObject, allocator: Allocator) !Symbol.Index {
fn newSymbol(self: *ZigObject, allocator: Allocator, name: u32, args: struct {
type: u8 = macho.N_UNDF | macho.N_EXT,
desc: u16 = 0,
}) !Symbol.Index {
try self.symtab.ensureUnusedCapacity(allocator, 1);
const index = @as(Symbol.Index, @intCast(self.symtab.addOneAssumeCapacity()));
self.symtab.set(index, .{
.nlist = MachO.null_sym,
try self.symbols.ensureUnusedCapacity(allocator, 1);
try self.symbols_extra.ensureUnusedCapacity(allocator, @sizeOf(Symbol.Extra));
try self.globals.ensureUnusedCapacity(allocator, 1);
const index = self.addSymbolAssumeCapacity();
const symbol = &self.symbols.items[index];
symbol.name = name;
symbol.extra = self.addSymbolExtraAssumeCapacity(.{});
const nlist_idx: u32 = @intCast(self.symtab.addOneAssumeCapacity());
self.symtab.set(nlist_idx, .{
.nlist = .{
.n_strx = name,
.n_type = args.type,
.n_sect = 0,
.n_desc = args.desc,
.n_value = 0,
},
.size = 0,
.atom = 0,
});
symbol.nlist_idx = nlist_idx;
self.globals.appendAssumeCapacity(0);
return 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, .{});
fn newAtom(self: *ZigObject, allocator: Allocator, name: u32, macho_file: *MachO) !Atom.Index {
try self.atoms.ensureUnusedCapacity(allocator, 1);
try self.atoms_extra.ensureUnusedCapacity(allocator, @sizeOf(Atom.Extra));
try self.atoms_indexes.ensureUnusedCapacity(allocator, 1);
try self.relocs.ensureUnusedCapacity(allocator, 1);
const index = self.addAtomAssumeCapacity();
self.atoms_indexes.appendAssumeCapacity(index);
const atom = self.getAtom(index).?;
atom.name = name;
const relocs_index = @as(u32, @intCast(self.relocs.items.len));
const relocs = try self.relocs.addOne(allocator);
relocs.* = .{};
const atom = self.getAtom(atom_index).?;
self.relocs.addOneAssumeCapacity().* = .{};
atom.addExtra(.{ .rel_index = relocs_index, .rel_count = 0 }, macho_file);
try self.globals.append(allocator, 0);
return symbol_index;
return index;
}
fn newSymbolWithAtom(self: *ZigObject, allocator: Allocator, name: u32, macho_file: *MachO) !Symbol.Index {
const atom_index = try self.newAtom(allocator, name, macho_file);
const sym_index = try self.newSymbol(allocator, name, .{ .type = macho.N_SECT });
const sym = &self.symbols.items[sym_index];
sym.atom_ref = .{ .index = atom_index, .file = self.index };
self.symtab.items(.atom)[sym.nlist_idx] = atom_index;
return sym_index;
}
pub fn getAtomData(self: ZigObject, macho_file: *MachO, atom: Atom, buffer: []u8) !void {
@ -1079,27 +1109,19 @@ fn createTlvInitializer(
const gpa = macho_file.base.comp.gpa;
const sym_name = try std.fmt.allocPrint(gpa, "{s}$tlv$init", .{name});
defer gpa.free(sym_name);
const off = try self.strtab.insert(gpa, sym_name);
const sym_index = try self.createAtomForDecl(gpa, macho_file);
const sym_index = try self.newSymbolWithAtom(gpa, off, macho_file);
const sym = &self.symbols.items[sym_index];
const nlist = &self.symtab.items(.nlist)[sym.nlist_idx];
const atom = sym.getAtom(macho_file).?;
sym.out_n_sect = sect_index;
atom.out_n_sect = sect_index;
sym.value = 0;
sym.name = try self.strtab.insert(gpa, sym_name);
atom.flags.alive = true;
atom.name = sym.name;
nlist.n_strx = sym.name;
nlist.n_sect = sect_index + 1;
nlist.n_type = macho.N_SECT;
nlist.n_value = 0;
self.symtab.items(.size)[sym.nlist_idx] = code.len;
atom.alignment = alignment;
atom.size = code.len;
nlist.n_sect = sect_index + 1;
self.symtab.items(.size)[sym.nlist_idx] = code.len;
const slice = macho_file.sections.slice();
const header = slice.items(.header)[sect_index];
@ -1293,7 +1315,8 @@ fn lowerConst(
var code_buffer = std.ArrayList(u8).init(gpa);
defer code_buffer.deinit();
const sym_index = try self.createAtomForDecl(gpa, macho_file);
const name_str_index = try self.strtab.insert(gpa, name);
const sym_index = try self.newSymbolWithAtom(gpa, name_str_index, macho_file);
const res = try codegen.generateSymbol(&macho_file.base, pt, src_loc, val, &code_buffer, .{
.none = {},
@ -1306,19 +1329,14 @@ fn lowerConst(
};
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;
const nlist = &self.symtab.items(.nlist)[sym.nlist_idx];
nlist.n_strx = name_str_index;
nlist.n_type = macho.N_SECT;
nlist.n_sect = output_section_index + 1;
self.symtab.items(.size)[sym.nlist_idx] = code.len;
const atom = sym.getAtom(macho_file).?;
atom.flags.alive = true;
atom.name = name_str_index;
atom.alignment = required_alignment;
atom.size = code.len;
atom.out_n_sect = output_section_index;
@ -1327,9 +1345,6 @@ fn lowerConst(
// TODO rename and re-audit this method
errdefer self.freeDeclMetadata(macho_file, sym_index);
sym.value = 0;
nlist.n_value = 0;
const sect = macho_file.sections.items(.header)[output_section_index];
const file_offset = sect.offset + atom.value;
try macho_file.base.file.?.pwriteAll(code, file_offset);
@ -1560,17 +1575,9 @@ pub fn getGlobalSymbol(self: *ZigObject, macho_file: *MachO, name: []const u8, l
const off = try self.strtab.insert(gpa, sym_name);
const lookup_gop = try self.globals_lookup.getOrPut(gpa, off);
if (!lookup_gop.found_existing) {
const sym_index = try self.addSymbol(gpa);
const sym_index = try self.newSymbol(gpa, off, .{});
const sym = &self.symbols.items[sym_index];
const nlist_index = try self.addNlist(gpa);
const nlist = &self.symtab.items(.nlist)[nlist_index];
nlist.n_strx = off;
nlist.n_type = macho.N_EXT;
sym.name = off;
sym.nlist_idx = nlist_index;
sym.extra = try self.addSymbolExtra(gpa, .{});
lookup_gop.value_ptr.* = nlist_index;
try self.globals.append(gpa, 0);
lookup_gop.value_ptr.* = sym.nlist_idx;
}
return lookup_gop.value_ptr.*;
}
@ -1584,10 +1591,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.createAtomForDecl(gpa, macho_file);
const sym_index = try self.newSymbolWithAtom(gpa, 0, macho_file);
const sym = &self.symbols.items[sym_index];
const mod = macho_file.base.comp.module.?;
const decl = mod.declPtr(decl_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;
@ -1627,7 +1634,7 @@ pub fn getOrCreateMetadataForLazySymbol(
};
switch (metadata.state.*) {
.unused => {
const symbol_index = try self.createAtomForDecl(gpa, macho_file);
const symbol_index = try self.newSymbolWithAtom(gpa, 0, macho_file);
const sym = &self.symbols.items[symbol_index];
sym.flags.needs_zig_got = true;
metadata.symbol_index.* = symbol_index;
@ -1643,12 +1650,18 @@ pub fn getOrCreateMetadataForLazySymbol(
}
fn addAtom(self: *ZigObject, allocator: Allocator) !Atom.Index {
try self.atoms.ensureUnusedCapacity(allocator, 1);
try self.atoms_extra.ensureUnusedCapacity(allocator, 1);
return self.addAtomAssumeCapacity();
}
fn addAtomAssumeCapacity(self: *ZigObject) Atom.Index {
const atom_index: Atom.Index = @intCast(self.atoms.items.len);
const atom = try self.atoms.addOne(allocator);
const atom = self.atoms.addOneAssumeCapacity();
atom.* = .{
.file = self.index,
.atom_index = atom_index,
.extra = try self.addAtomExtra(allocator, .{}),
.extra = self.addAtomExtraAssumeCapacity(.{}),
};
return atom_index;
}