macho: migrate some of MachO driver

This commit is contained in:
Jakub Konka 2024-07-09 11:34:38 +02:00
parent b9bac32a25
commit 355992cbdf
2 changed files with 32 additions and 83 deletions

View File

@ -224,15 +224,8 @@ pub fn createEmpty(
// Append null file
try self.files.append(gpa, .null);
// Atom at index 0 is reserved as null atom
try self.atoms.append(gpa, .{});
try self.atoms_extra.append(gpa, 0);
// Append empty string to string tables
try self.strings.buffer.append(gpa, 0);
try self.strtab.append(gpa, 0);
// Append null symbols
try self.symbols.append(gpa, .{});
try self.symbols_extra.append(gpa, 0);
if (opt_zcu) |zcu| {
if (!use_llvm) {
@ -301,10 +294,7 @@ pub fn deinit(self: *MachO) void {
}
self.sections.deinit(gpa);
self.symbols.deinit(gpa);
self.symbols_extra.deinit(gpa);
self.symbols_free_list.deinit(gpa);
self.globals.deinit(gpa);
self.resolver.deinit(gpa);
{
var it = self.undefs.iterator();
while (it.next()) |entry| {
@ -312,10 +302,7 @@ pub fn deinit(self: *MachO) void {
}
self.undefs.deinit(gpa);
}
self.undefined_symbols.deinit(gpa);
self.boundary_symbols.deinit(gpa);
self.strings.deinit(gpa);
self.symtab.deinit(gpa);
self.strtab.deinit(gpa);
self.got.deinit(gpa);
@ -330,11 +317,6 @@ pub fn deinit(self: *MachO) void {
self.export_trie.deinit(gpa);
self.unwind_info.deinit(gpa);
self.atoms.deinit(gpa);
self.atoms_extra.deinit(gpa);
for (self.thunks.items) |*thunk| {
thunk.deinit(gpa);
}
self.thunks.deinit(gpa);
}
@ -513,17 +495,14 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n
const index = @as(File.Index, @intCast(try self.files.addOne(gpa)));
self.files.set(index, .{ .internal = .{ .index = index } });
self.internal_object = index;
const object = self.getInternalObject().?;
try object.init(gpa);
try object.initSymbols(self);
}
try self.addUndefinedGlobals();
try self.resolveSymbols();
try self.parseDebugInfo();
try self.resolveSyntheticSymbols();
try self.convertTentativeDefinitions();
try self.createObjcSections();
try self.convertTentativeDefsAndResolveSpecialSymbols();
try self.dedupLiterals();
try self.claimUnresolved();
if (self.base.gc_sections) {
try dead_strip.gcAtoms(self);
@ -546,6 +525,8 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n
dylib.ordinal = @intCast(ord);
}
try self.claimUnresolved();
self.scanRelocs() catch |err| switch (err) {
error.HasUndefinedSymbols => return error.FlushFailure,
else => |e| {
@ -1307,35 +1288,6 @@ fn parseDependentDylibs(self: *MachO) !void {
if (has_errors) return error.MissingLibraryDependencies;
}
pub fn addUndefinedGlobals(self: *MachO) !void {
const gpa = self.base.comp.gpa;
try self.undefined_symbols.ensureUnusedCapacity(gpa, self.base.comp.force_undefined_symbols.keys().len);
for (self.base.comp.force_undefined_symbols.keys()) |name| {
const off = try self.strings.insert(gpa, name);
const gop = try self.getOrCreateGlobal(off);
self.undefined_symbols.appendAssumeCapacity(gop.index);
}
if (!self.base.isDynLib() and self.entry_name != null) {
const off = try self.strings.insert(gpa, self.entry_name.?);
const gop = try self.getOrCreateGlobal(off);
self.entry_index = gop.index;
}
{
const off = try self.strings.insert(gpa, "dyld_stub_binder");
const gop = try self.getOrCreateGlobal(off);
self.dyld_stub_binder_index = gop.index;
}
{
const off = try self.strings.insert(gpa, "_objc_msgSend");
const gop = try self.getOrCreateGlobal(off);
self.objc_msg_send_index = gop.index;
}
}
/// When resolving symbols, we approach the problem similarly to `mold`.
/// 1. Resolve symbols across all objects (including those preemptively extracted archives).
/// 2. Resolve symbols across all shared objects.
@ -1348,18 +1300,17 @@ pub fn resolveSymbols(self: *MachO) !void {
defer tracy.end();
// Resolve symbols in the ZigObject. For now, we assume that it's always live.
if (self.getZigObject()) |zo| zo.asFile().resolveSymbols(self);
if (self.getZigObject()) |zo| try zo.asFile().resolveSymbols(self);
// Resolve symbols on the set of all objects and shared objects (even if some are unneeded).
for (self.objects.items) |index| self.getFile(index).?.resolveSymbols(self);
for (self.dylibs.items) |index| self.getFile(index).?.resolveSymbols(self);
for (self.objects.items) |index| try self.getFile(index).?.resolveSymbols(self);
for (self.dylibs.items) |index| try self.getFile(index).?.resolveSymbols(self);
if (self.getInternalObject()) |obj| try obj.resolveSymbols(self);
// Mark live objects.
self.markLive();
// Reset state of all globals after marking live objects.
if (self.getZigObject()) |zo| zo.asFile().resetGlobals(self);
for (self.objects.items) |index| self.getFile(index).?.resetGlobals(self);
for (self.dylibs.items) |index| self.getFile(index).?.resetGlobals(self);
self.resolver.reset();
// Prune dead objects.
var i: usize = 0;
@ -1373,37 +1324,26 @@ pub fn resolveSymbols(self: *MachO) !void {
}
// Re-resolve the symbols.
if (self.getZigObject()) |zo| zo.resolveSymbols(self);
for (self.objects.items) |index| self.getFile(index).?.resolveSymbols(self);
for (self.dylibs.items) |index| self.getFile(index).?.resolveSymbols(self);
if (self.getZigObject()) |zo| try zo.resolveSymbols(self);
for (self.objects.items) |index| try self.getFile(index).?.resolveSymbols(self);
for (self.dylibs.items) |index| try self.getFile(index).?.resolveSymbols(self);
if (self.getInternalObject()) |obj| try obj.resolveSymbols(self);
// Merge symbol visibility
if (self.getZigObject()) |zo| zo.mergeSymbolVisibility(self);
for (self.objects.items) |index| self.getFile(index).?.object.mergeSymbolVisibility(self);
}
fn markLive(self: *MachO) void {
const tracy = trace(@src());
defer tracy.end();
for (self.undefined_symbols.items) |index| {
if (self.getSymbol(index).getFile(self)) |file| {
if (file == .object) file.object.alive = true;
}
}
if (self.entry_index) |index| {
const sym = self.getSymbol(index);
if (sym.getFile(self)) |file| {
if (file == .object) file.object.alive = true;
}
}
if (self.getZigObject()) |zo| zo.markLive(self);
for (self.objects.items) |index| {
const object = self.getFile(index).?.object;
if (object.alive) object.markLive(self);
}
}
pub fn parseDebugInfo(self: *MachO) !void {
for (self.objects.items) |index| {
try self.getFile(index).?.object.parseDebugInfo(self);
}
if (self.getInternalObject()) |obj| obj.markLive(self);
}
fn resolveSyntheticSymbols(self: *MachO) !void {
@ -1453,10 +1393,14 @@ fn resolveSyntheticSymbols(self: *MachO) !void {
}
}
fn convertTentativeDefinitions(self: *MachO) !void {
fn convertTentativeDefsAndResolveSpecialSymbols(self: *MachO) !void {
for (self.objects.items) |index| {
try self.getFile(index).?.object.convertTentativeDefinitions(self);
}
if (self.getInternalObject()) |obj| {
try obj.resolveBoundarySymbols(self);
try obj.resolveObjcMsgSendSymbols(self);
}
}
fn createObjcSections(self: *MachO) !void {
@ -1494,6 +1438,9 @@ fn createObjcSections(self: *MachO) !void {
}
pub fn dedupLiterals(self: *MachO) !void {
const tracy = trace(@src());
defer tracy.end();
const gpa = self.base.comp.gpa;
var lp: LiteralPool = .{};
defer lp.deinit(gpa);

View File

@ -259,6 +259,8 @@ pub fn parse(self: *Object, macho_file: *MachO) !void {
// }
}
try self.parseDebugInfo(macho_file);
for (self.atoms.items) |atom_index| {
const atom = self.getAtom(atom_index) orelse continue;
const isec = atom.getInputSection(macho_file);
@ -1317,7 +1319,7 @@ fn parseUnwindRecords(self: *Object, allocator: Allocator, cpu_arch: std.Target.
/// and record that so that we can emit symbol stabs.
/// TODO in the future, we want parse debug info and debug line sections so that
/// we can provide nice error locations to the user.
pub fn parseDebugInfo(self: *Object, macho_file: *MachO) !void {
fn parseDebugInfo(self: *Object, macho_file: *MachO) !void {
const tracy = trace(@src());
defer tracy.end();