diff options
| -rw-r--r-- | src/arch/x86_64/CodeGen.zig | 10 | ||||
| -rw-r--r-- | src/arch/x86_64/Emit.zig | 2 | ||||
| -rw-r--r-- | src/link/MachO.zig | 65 | ||||
| -rw-r--r-- | src/link/MachO/Atom.zig | 34 | ||||
| -rw-r--r-- | src/link/MachO/DebugSymbols.zig | 12 | ||||
| -rw-r--r-- | src/link/MachO/Dylib.zig | 24 | ||||
| -rw-r--r-- | src/link/MachO/InternalObject.zig | 38 | ||||
| -rw-r--r-- | src/link/MachO/Object.zig | 254 | ||||
| -rw-r--r-- | src/link/MachO/Symbol.zig | 4 | ||||
| -rw-r--r-- | src/link/MachO/UnwindInfo.zig | 4 | ||||
| -rw-r--r-- | src/link/MachO/ZigObject.zig | 40 | ||||
| -rw-r--r-- | src/link/MachO/dyld_info/Rebase.zig | 10 | ||||
| -rw-r--r-- | src/link/MachO/dyld_info/Trie.zig | 46 | ||||
| -rw-r--r-- | src/link/MachO/dyld_info/bind.zig | 52 | ||||
| -rw-r--r-- | src/link/MachO/file.zig | 22 | ||||
| -rw-r--r-- | src/link/MachO/synthetic.zig | 10 | ||||
| -rw-r--r-- | src/link/MachO/thunks.zig | 6 |
17 files changed, 352 insertions, 281 deletions
diff --git a/src/arch/x86_64/CodeGen.zig b/src/arch/x86_64/CodeGen.zig index 1b8d84aa23..8343dec3bd 100644 --- a/src/arch/x86_64/CodeGen.zig +++ b/src/arch/x86_64/CodeGen.zig @@ -12362,8 +12362,9 @@ fn genCall(self: *Self, info: union(enum) { try self.genSetReg(.rax, Type.usize, .{ .lea_got = sym_index }, .{}); try self.asmRegister(.{ ._, .call }, .rax); } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { - const sym_index = try macho_file.getZigObject().?.getOrCreateMetadataForDecl(macho_file, func.owner_decl); - const sym = macho_file.getSymbol(sym_index); + const zo = macho_file.getZigObject().?; + const sym_index = try zo.getOrCreateMetadataForDecl(macho_file, func.owner_decl); + const sym = zo.symbols.items[sym_index]; try self.genSetReg( .rax, Type.usize, @@ -15396,9 +15397,10 @@ fn genLazySymbolRef( else => unreachable, } } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { - const sym_index = macho_file.getZigObject().?.getOrCreateMetadataForLazySymbol(macho_file, pt, lazy_sym) catch |err| + const zo = macho_file.getZigObject().?; + const sym_index = zo.getOrCreateMetadataForLazySymbol(macho_file, pt, lazy_sym) catch |err| return self.fail("{s} creating lazy symbol", .{@errorName(err)}); - const sym = macho_file.getSymbol(sym_index); + const sym = zo.symbols.items[sym_index]; switch (tag) { .lea, .call => try self.genSetReg( reg, diff --git a/src/arch/x86_64/Emit.zig b/src/arch/x86_64/Emit.zig index 2bfb4d6704..9641268a7d 100644 --- a/src/arch/x86_64/Emit.zig +++ b/src/arch/x86_64/Emit.zig @@ -162,7 +162,7 @@ pub fn emitMir(emit: *Emit) Error!void { }; const zo = macho_file.getZigObject().?; const atom = zo.symbols.items[data.atom_index].getAtom(macho_file).?; - const sym = zo.symbols.items[data.sym_index]; + const sym = &zo.symbols.items[data.sym_index]; if (sym.flags.needs_zig_got and !is_obj_or_static_lib) { _ = try sym.getOrCreateZigGotEntry(data.sym_index, macho_file); } diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 47b8eb2ce1..a00c156b35 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -529,7 +529,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n dylib.ordinal = @intCast(ord); } - try self.claimUnresolved(); + self.claimUnresolved(); self.scanRelocs() catch |err| switch (err) { error.HasUndefinedSymbols => return error.FlushFailure, @@ -603,7 +603,12 @@ pub fn flushModule(self: *MachO, arena: Allocator, tid: Zcu.PerThread.Id, prog_n if (has_resolve_error) return error.FlushFailure; } - try self.writeSectionsAndUpdateLinkeditSizes(); + self.writeSectionsAndUpdateLinkeditSizes() catch |err| { + switch (err) { + error.ResolveFailed => return error.FlushFailure, + else => |e| return e, + } + }; try self.writeSectionsToFile(); try self.allocateLinkeditSegment(); @@ -1450,12 +1455,12 @@ pub fn dedupLiterals(self: *MachO) !void { } } -fn claimUnresolved(self: *MachO) error{OutOfMemory}!void { +fn claimUnresolved(self: *MachO) void { if (self.getZigObject()) |zo| { - try zo.asFile().claimUnresolved(self); + zo.claimUnresolved(self); } for (self.objects.items) |index| { - try self.getFile(index).?.claimUnresolved(self); + self.getFile(index).?.object.claimUnresolved(self); } } @@ -2402,7 +2407,7 @@ fn writeSectionsAndUpdateLinkeditSizes(self: *MachO) !void { } if (self.la_symbol_ptr_sect_index) |_| { - try self.updatelazyBindSize(); + try self.updateLazyBindSize(); } try self.rebase.updateSize(self); @@ -2412,16 +2417,16 @@ fn writeSectionsAndUpdateLinkeditSizes(self: *MachO) !void { try self.data_in_code.updateSize(self); if (self.getZigObject()) |zo| { - zo.asFile().writeSymtab(self); + zo.asFile().writeSymtab(self, self); } for (self.objects.items) |index| { - self.getFile(index).?.writeSymtab(self); + self.getFile(index).?.writeSymtab(self, self); } for (self.dylibs.items) |index| { - self.getFile(index).?.writeSymtab(self); + self.getFile(index).?.writeSymtab(self, self); } if (self.getInternalObject()) |obj| { - obj.asFile().writeSymtab(self); + obj.asFile().writeSymtab(self, self); } } @@ -2484,7 +2489,7 @@ fn writeSectionsToFile(self: *MachO) !void { const slice = self.sections.slice(); for (slice.items(.header), slice.items(.out)) |header, out| { - try self.base.file.pwriteAll(out.items, header.offset); + try self.base.file.?.pwriteAll(out.items, header.offset); } } @@ -2501,7 +2506,7 @@ fn writeDyldInfo(self: *MachO) !void { const tracy = trace(@src()); defer tracy.end(); - const gpa = self.base.allocator; + const gpa = self.base.comp.gpa; const base_off = self.getLinkeditSegment().fileoff; const cmd = self.dyld_info_cmd; var needed_size: u32 = 0; @@ -2527,14 +2532,14 @@ fn writeDyldInfo(self: *MachO) !void { try self.lazy_bind.write(writer); try stream.seekTo(cmd.export_off - base_off); try self.export_trie.write(writer); - try self.base.file.pwriteAll(buffer, cmd.rebase_off); + try self.base.file.?.pwriteAll(buffer, cmd.rebase_off); } pub fn writeDataInCode(self: *MachO) !void { const tracy = trace(@src()); defer tracy.end(); const cmd = self.data_in_code_cmd; - try self.base.file.pwriteAll(mem.sliceAsBytes(self.data_in_code.entries.items), cmd.dataoff); + try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.data_in_code.entries.items), cmd.dataoff); } fn writeIndsymtab(self: *MachO) !void { @@ -2546,15 +2551,15 @@ fn writeIndsymtab(self: *MachO) !void { var buffer = try std.ArrayList(u8).initCapacity(gpa, needed_size); defer buffer.deinit(); try self.indsymtab.write(self, buffer.writer()); - try self.base.file.pwriteAll(buffer.items, cmd.indirectsymoff); + try self.base.file.?.pwriteAll(buffer.items, cmd.indirectsymoff); } pub fn writeSymtabToFile(self: *MachO) !void { const tracy = trace(@src()); defer tracy.end(); const cmd = self.symtab_cmd; - try self.base.file.pwriteAll(mem.sliceAsBytes(self.symtab.items), cmd.symoff); - try self.base.file.pwriteAll(self.strtab.items, cmd.stroff); + try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.symtab.items), cmd.symoff); + try self.base.file.?.pwriteAll(self.strtab.items, cmd.stroff); } fn writeUnwindInfo(self: *MachO) !void { @@ -2687,18 +2692,20 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } { try load_commands.writeDylinkerLC(writer); ncmds += 1; - if (self.entry_index) |global_index| { - const sym = self.getSymbol(global_index); - const seg = self.getTextSegment(); - const entryoff: u32 = if (sym.getFile(self) == null) - 0 - else - @as(u32, @intCast(sym.getAddress(.{ .stubs = true }, self) - seg.vmaddr)); - try writer.writeStruct(macho.entry_point_command{ - .entryoff = entryoff, - .stacksize = self.base.stack_size, - }); - ncmds += 1; + if (self.getInternalObject()) |obj| { + if (obj.getEntryRef(self)) |ref| { + const sym = ref.getSymbol(self).?; + const seg = self.getTextSegment(); + const entryoff: u32 = if (sym.getFile(self) == null) + 0 + else + @as(u32, @intCast(sym.getAddress(.{ .stubs = true }, self) - seg.vmaddr)); + try writer.writeStruct(macho.entry_point_command{ + .entryoff = entryoff, + .stacksize = self.base.stack_size, + }); + ncmds += 1; + } } if (self.base.isDynLib()) { diff --git a/src/link/MachO/Atom.zig b/src/link/MachO/Atom.zig index b1736f7339..d03727aa6a 100644 --- a/src/link/MachO/Atom.zig +++ b/src/link/MachO/Atom.zig @@ -213,7 +213,8 @@ pub fn initOutputSection(sect: macho.section_64, macho_file: *MachO) !u8 { /// File offset relocation happens transparently, so it is not included in /// this calculation. pub fn capacity(self: Atom, macho_file: *MachO) u64 { - const next_addr = if (macho_file.getAtom(self.next_index)) |next| + const zo = macho_file.getZigObject().?; + const next_addr = if (zo.getAtom(self.next_index)) |next| next.getAddress(macho_file) else std.math.maxInt(u32); @@ -222,7 +223,8 @@ pub fn capacity(self: Atom, macho_file: *MachO) u64 { pub fn freeListEligible(self: Atom, macho_file: *MachO) bool { // No need to keep a free list node for the last block. - const next = macho_file.getAtom(self.next_index) orelse return false; + const zo = macho_file.getZigObject().?; + const next = zo.getAtom(self.next_index) orelse return false; const cap = next.getAddress(macho_file) - self.getAddress(macho_file); const ideal_cap = MachO.padToIdeal(self.size); if (cap <= ideal_cap) return false; @@ -231,6 +233,7 @@ pub fn freeListEligible(self: Atom, macho_file: *MachO) bool { } pub fn allocate(self: *Atom, macho_file: *MachO) !void { + const zo = macho_file.getZigObject().?; const sect = &macho_file.sections.items(.header)[self.out_n_sect]; const free_list = &macho_file.sections.items(.free_list)[self.out_n_sect]; const last_atom_index = &macho_file.sections.items(.last_atom_index)[self.out_n_sect]; @@ -250,7 +253,7 @@ pub fn allocate(self: *Atom, macho_file: *MachO) !void { var i: usize = free_list.items.len; while (i < free_list.items.len) { const big_atom_index = free_list.items[i]; - const big_atom = macho_file.getAtom(big_atom_index).?; + const big_atom = zo.getAtom(big_atom_index).?; // We now have a pointer to a live atom that has too much capacity. // Is it enough that we could fit this new atom? const cap = big_atom.capacity(macho_file); @@ -282,7 +285,7 @@ pub fn allocate(self: *Atom, macho_file: *MachO) !void { free_list_removal = i; } break :blk new_start_vaddr; - } else if (macho_file.getAtom(last_atom_index.*)) |last| { + } else if (zo.getAtom(last_atom_index.*)) |last| { const ideal_capacity = MachO.padToIdeal(last.size); const ideal_capacity_end_vaddr = last.value + ideal_capacity; const new_start_vaddr = self.alignment.forward(ideal_capacity_end_vaddr); @@ -302,7 +305,7 @@ pub fn allocate(self: *Atom, macho_file: *MachO) !void { }); const expand_section = if (atom_placement) |placement_index| - macho_file.getAtom(placement_index).?.next_index == 0 + zo.getAtom(placement_index).?.next_index == 0 else true; if (expand_section) { @@ -327,15 +330,15 @@ pub fn allocate(self: *Atom, macho_file: *MachO) !void { // This function can also reallocate an atom. // In this case we need to "unplug" it from its previous location before // plugging it in to its new location. - if (macho_file.getAtom(self.prev_index)) |prev| { + if (zo.getAtom(self.prev_index)) |prev| { prev.next_index = self.next_index; } - if (macho_file.getAtom(self.next_index)) |next| { + if (zo.getAtom(self.next_index)) |next| { next.prev_index = self.prev_index; } if (atom_placement) |big_atom_index| { - const big_atom = macho_file.getAtom(big_atom_index).?; + const big_atom = zo.getAtom(big_atom_index).?; self.prev_index = big_atom_index; self.next_index = big_atom.next_index; big_atom.next_index = self.atom_index; @@ -365,6 +368,7 @@ pub fn free(self: *Atom, macho_file: *MachO) void { const comp = macho_file.base.comp; const gpa = comp.gpa; + const zo = macho_file.getZigObject().?; const free_list = &macho_file.sections.items(.free_list)[self.out_n_sect]; const last_atom_index = &macho_file.sections.items(.last_atom_index)[self.out_n_sect]; var already_have_free_list_node = false; @@ -383,9 +387,9 @@ pub fn free(self: *Atom, macho_file: *MachO) void { } } - if (macho_file.getAtom(last_atom_index.*)) |last_atom| { + if (zo.getAtom(last_atom_index.*)) |last_atom| { if (last_atom.atom_index == self.atom_index) { - if (macho_file.getAtom(self.prev_index)) |_| { + if (zo.getAtom(self.prev_index)) |_| { // TODO shrink the section size here last_atom_index.* = self.prev_index; } else { @@ -394,7 +398,7 @@ pub fn free(self: *Atom, macho_file: *MachO) void { } } - if (macho_file.getAtom(self.prev_index)) |prev| { + if (zo.getAtom(self.prev_index)) |prev| { prev.next_index = self.next_index; if (!already_have_free_list_node and prev.*.freeListEligible(macho_file)) { // The free list is heuristics, it doesn't have to be perfect, so we can @@ -405,7 +409,7 @@ pub fn free(self: *Atom, macho_file: *MachO) void { self.prev_index = 0; } - if (macho_file.getAtom(self.next_index)) |next| { + if (zo.getAtom(self.next_index)) |next| { next.prev_index = self.prev_index; } else { self.next_index = 0; @@ -423,7 +427,7 @@ 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); - var extra = self.getExtra(macho_file).?; + var extra = self.getExtra(macho_file); const rels = &file.zig_object.relocs.items[extra.rel_index]; try rels.append(gpa, reloc); extra.rel_count += 1; @@ -432,7 +436,7 @@ pub fn addReloc(self: *Atom, macho_file: *MachO, reloc: Relocation) !void { pub fn freeRelocs(self: *Atom, macho_file: *MachO) void { self.getFile(macho_file).zig_object.freeAtomRelocs(self.*, macho_file); - var extra = self.getExtra(macho_file).?; + var extra = self.getExtra(macho_file); extra.rel_count = 0; self.setExtra(extra, macho_file); } @@ -630,7 +634,7 @@ fn resolveRelocInner( const TLS = @as(i64, @intCast(macho_file.getTlsAddress())); const SUB = if (subtractor) |sub| @as(i64, @intCast(sub.getTargetAddress(self, macho_file))) else 0; // Address of the __got_zig table entry if any. - const ZIG_GOT = @as(i64, @intCast(rel.getZigGotTargetAddress(self, macho_file))); + const ZIG_GOT = @as(i64, @intCast(rel.getZigGotTargetAddress(macho_file))); const divExact = struct { fn divExact(atom: Atom, r: Relocation, num: u12, den: u12, ctx: *MachO) !u12 { diff --git a/src/link/MachO/DebugSymbols.zig b/src/link/MachO/DebugSymbols.zig index c022a30664..52061f325b 100644 --- a/src/link/MachO/DebugSymbols.zig +++ b/src/link/MachO/DebugSymbols.zig @@ -175,8 +175,9 @@ fn findFreeSpace(self: *DebugSymbols, object_size: u64, min_alignment: u64) u64 } pub fn flushModule(self: *DebugSymbols, macho_file: *MachO) !void { + const zo = macho_file.getZigObject().?; for (self.relocs.items) |*reloc| { - const sym = macho_file.getSymbol(reloc.target); + const sym = zo.symbols.items[reloc.target]; const sym_name = sym.getName(macho_file); const addr = switch (reloc.type) { .direct_load => sym.getAddress(.{}, macho_file), @@ -382,23 +383,22 @@ pub fn writeSymtab(self: *DebugSymbols, off: u32, macho_file: *MachO) !u32 { cmd.symoff = off; try self.symtab.resize(gpa, cmd.nsyms); - try self.strtab.ensureUnusedCapacity(gpa, cmd.strsize - 1); + try self.strtab.resize(gpa, cmd.strsize); + self.strtab.items[0] = 0; if (macho_file.getZigObject()) |zo| { zo.writeSymtab(macho_file, self); } for (macho_file.objects.items) |index| { - try macho_file.getFile(index).?.writeSymtab(macho_file, self); + macho_file.getFile(index).?.writeSymtab(macho_file, self); } for (macho_file.dylibs.items) |index| { - try macho_file.getFile(index).?.writeSymtab(macho_file, self); + macho_file.getFile(index).?.writeSymtab(macho_file, self); } if (macho_file.getInternalObject()) |internal| { internal.writeSymtab(macho_file, self); } - assert(self.strtab.items.len == cmd.strsize); - try self.file.pwriteAll(mem.sliceAsBytes(self.symtab.items), cmd.symoff); return off + cmd.nsyms * @sizeOf(macho.nlist_64); diff --git a/src/link/MachO/Dylib.zig b/src/link/MachO/Dylib.zig index 6bb3056a61..9909279190 100644 --- a/src/link/MachO/Dylib.zig +++ b/src/link/MachO/Dylib.zig @@ -6,7 +6,7 @@ strtab: std.ArrayListUnmanaged(u8) = .{}, id: ?Id = null, ordinal: u16 = 0, -symbols: std.ArrayListUnmanaged(Symbol.Index) = .{}, +symbols: std.ArrayListUnmanaged(Symbol) = .{}, symbols_extra: std.ArrayListUnmanaged(u32) = .{}, globals: std.ArrayListUnmanaged(MachO.SymbolResolver.Index) = .{}, dependents: std.ArrayListUnmanaged(Id) = .{}, @@ -516,7 +516,7 @@ pub fn initSymbols(self: *Dylib, macho_file: *MachO) !void { } } -pub fn resolveSymbols(self: *Dylib, macho_file: *MachO) void { +pub fn resolveSymbols(self: *Dylib, macho_file: *MachO) !void { const tracy = trace(@src()); defer tracy.end(); @@ -584,7 +584,7 @@ pub fn calcSymtabSize(self: *Dylib, macho_file: *MachO) void { } } -pub fn writeSymtab(self: Dylib, macho_file: *MachO) void { +pub fn writeSymtab(self: Dylib, macho_file: *MachO, ctx: anytype) void { const tracy = trace(@src()); defer tracy.end(); @@ -594,13 +594,13 @@ pub fn writeSymtab(self: Dylib, macho_file: *MachO) void { const file = ref.getFile(macho_file) orelse continue; if (file.getIndex() != self.index) continue; const idx = sym.getOutputSymtabIndex(macho_file) orelse continue; - const out_sym = &macho_file.symtab.items[idx]; + const out_sym = &ctx.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); + @memcpy(ctx.strtab.items[n_strx..][0..name.len], name); n_strx += @intCast(name.len); - macho_file.strtab.items[n_strx] = 0; + ctx.strtab.items[n_strx] = 0; n_strx += 1; } } @@ -718,10 +718,16 @@ fn formatSymtab( _ = unused_fmt_string; _ = options; const dylib = ctx.dylib; + const macho_file = ctx.macho_file; try writer.writeAll(" globals\n"); - for (dylib.symbols.items) |index| { - const global = ctx.macho_file.getSymbol(index); - try writer.print(" {}\n", .{global.fmt(ctx.macho_file)}); + for (dylib.symbols.items, 0..) |sym, i| { + const ref = dylib.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)}); + } } } diff --git a/src/link/MachO/InternalObject.zig b/src/link/MachO/InternalObject.zig index 32e89116b1..9578bc84ec 100644 --- a/src/link/MachO/InternalObject.zig +++ b/src/link/MachO/InternalObject.zig @@ -16,7 +16,7 @@ objc_selrefs: [@sizeOf(u64)]u8 = [_]u8{0} ** @sizeOf(u64), force_undefined: std.ArrayListUnmanaged(Symbol.Index) = .{}, entry_index: ?Symbol.Index = null, dyld_stub_binder_index: ?Symbol.Index = null, -dyld_private: ?Symbol.Index = null, +dyld_private_index: ?Symbol.Index = null, objc_msg_send_index: ?Symbol.Index = null, mh_execute_header_index: ?Symbol.Index = null, mh_dylib_header_index: ?Symbol.Index = null, @@ -206,7 +206,7 @@ pub fn resolveBoundarySymbols(self: *InternalObject, macho_file: *MachO) !void { const nlist_idx: u32 = @intCast(self.symtab.items.len); const nlist = self.symtab.addOneAssumeCapacity(); nlist.* = .{ - .n_strx = name_off.pos, + .n_strx = name_off, .n_type = macho.N_SECT, .n_sect = 0, .n_desc = 0, @@ -273,7 +273,7 @@ fn addObjcMethnameSection(self: *InternalObject, methname: []const u8, macho_fil const nlist_idx: u32 = @intCast(self.symtab.items.len); const nlist = try self.symtab.addOne(gpa); nlist.* = .{ - .n_strx = name_str.pos, + .n_strx = name_str, .n_type = macho.N_SECT, .n_sect = @intCast(n_sect + 1), .n_desc = 0, @@ -286,12 +286,12 @@ fn addObjcMethnameSection(self: *InternalObject, methname: []const u8, macho_fil } fn addObjcSelrefsSection(self: *InternalObject, methname_sym_index: Symbol.Index, macho_file: *MachO) !Symbol.Index { - const gpa = macho_file.base.allocator; + const gpa = macho_file.base.comp.gpa; const atom_index = try self.addAtom(gpa); try self.atoms_indexes.append(gpa, atom_index); const atom = self.getAtom(atom_index).?; atom.size = @sizeOf(u64); - atom.alignment = 3; + atom.alignment = .@"8"; const n_sect = try self.addSection(gpa, "__DATA", "__objc_selrefs"); const sect = &self.sections.items(.header)[n_sect]; @@ -389,7 +389,7 @@ pub fn resolveObjcMsgSendSymbols(self: *InternalObject, macho_file: *MachO) !voi }; sym.nlist_idx = nlist_idx; sym.extra = try self.addSymbolExtra(gpa, .{ .objc_selrefs = selrefs_index }); - sym.setSectionFlags(.{ .objc_stubs = true }); + sym.flags.objc_stubs = true; const idx = ref.getFile(macho_file).?.object.globals.items[ref.index]; try self.globals.append(gpa, idx); @@ -417,7 +417,7 @@ pub fn resolveLiterals(self: *InternalObject, lp: *MachO.LiteralPool, macho_file const target = rel.getTargetSymbol(atom.*, macho_file).getAtom(macho_file).?; try buffer.ensureUnusedCapacity(target.size); buffer.resize(target.size) catch unreachable; - @memcpy(buffer.items, self.getSectionData(target.n_sect)); + @memcpy(buffer.items, try self.getSectionData(target.n_sect)); const res = try lp.insert(gpa, header.type(), buffer.items); buffer.clearRetainingCapacity(); if (!res.found_existing) { @@ -425,7 +425,7 @@ pub fn resolveLiterals(self: *InternalObject, lp: *MachO.LiteralPool, macho_file } else { const lp_sym = lp.getSymbol(res.index, macho_file); const lp_atom = lp_sym.getAtom(macho_file).?; - lp_atom.alignment = @max(lp_atom.alignment, atom.alignment); + lp_atom.alignment = lp_atom.alignment.max(atom.alignment); atom.flags.alive = false; } atom.addExtra(.{ .literal_pool_index = res.index }, macho_file); @@ -438,7 +438,7 @@ pub fn dedupLiterals(self: *InternalObject, lp: MachO.LiteralPool, macho_file: * for (self.getAtoms()) |atom_index| { const atom = self.getAtom(atom_index) orelse continue; - if (!atom.alive.load(.seq_cst)) continue; + if (!atom.flags.alive) continue; const relocs = blk: { const extra = atom.getExtra(macho_file); @@ -463,7 +463,7 @@ pub fn dedupLiterals(self: *InternalObject, lp: MachO.LiteralPool, macho_file: * } for (self.symbols.items) |*sym| { - if (!sym.getSectionFlags().objc_stubs) continue; + if (!sym.flags.objc_stubs) continue; const extra = sym.getExtra(macho_file); const file = sym.getFile(macho_file).?; if (file.getIndex() != self.index) continue; @@ -495,14 +495,14 @@ pub fn scanRelocs(self: *InternalObject, macho_file: *MachO) void { if (self.getDyldStubBinderRef(macho_file)) |ref| { if (ref.getFile(macho_file) != null) { const sym = ref.getSymbol(macho_file).?; - sym.flags.got = true; + sym.flags.needs_got = true; } } if (self.getObjcMsgSendRef(macho_file)) |ref| { if (ref.getFile(macho_file) != null) { const sym = ref.getSymbol(macho_file).?; // TODO is it always needed, or only if we are synthesising fast stubs - sym.flags.got = true; + sym.flags.needs_got = true; } } } @@ -569,30 +569,30 @@ pub fn writeAtoms(self: *InternalObject, macho_file: *MachO) !void { for (self.getAtoms()) |atom_index| { const atom = self.getAtom(atom_index) orelse continue; - if (!atom.alive.load(.seq_cst)) continue; + if (!atom.flags.alive) continue; const sect = atom.getInputSection(macho_file); if (sect.isZerofill()) continue; const off = atom.value; const buffer = macho_file.sections.items(.out)[atom.out_n_sect].items[off..][0..atom.size]; - @memcpy(buffer, self.getSectionData(atom.n_sect)); + @memcpy(buffer, try self.getSectionData(atom.n_sect)); try atom.resolveRelocs(macho_file, buffer); } } -pub fn writeSymtab(self: InternalObject, macho_file: *MachO) void { +pub fn writeSymtab(self: InternalObject, macho_file: *MachO, ctx: anytype) void { 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 out_sym = &macho_file.symtab.items[idx]; + const out_sym = &ctx.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); + @memcpy(ctx.strtab.items[n_strx..][0..name.len], name); n_strx += @intCast(name.len); - macho_file.strtab.items[n_strx] = 0; + ctx.strtab.items[n_strx] = 0; n_strx += 1; } } @@ -640,7 +640,7 @@ pub fn asFile(self: *InternalObject) File { } pub fn getAtomRelocs(self: *const InternalObject, atom: Atom, macho_file: *MachO) []const Relocation { - const extra = atom.getExtra(macho_file).?; + const extra = atom.getExtra(macho_file); const relocs = self.sections.items(.relocs)[atom.n_sect]; return relocs.items[extra.rel_index..][0..extra.rel_count]; } diff --git a/src/link/MachO/Object.zig b/src/link/MachO/Object.zig index a668b932d9..fe99df22bd 100644 --- a/src/link/MachO/Object.zig +++ b/src/link/MachO/Object.zig @@ -11,10 +11,10 @@ sections: std.MultiArrayList(Section) = .{}, symtab: std.MultiArrayList(Nlist) = .{}, strtab: std.ArrayListUnmanaged(u8) = .{}, -symbols: std.ArrayListUnmanaged(Symbol.Index) = .{}, +symbols: std.ArrayListUnmanaged(Symbol) = .{}, symbols_extra: std.ArrayListUnmanaged(u32) = .{}, globals: std.ArrayListUnmanaged(MachO.SymbolResolver.Index) = .{}, -atoms: std.ArrayListUnmanaged(Atom.Index) = .{}, +atoms: std.ArrayListUnmanaged(Atom) = .{}, atoms_indexes: std.ArrayListUnmanaged(Atom.Index) = .{}, atoms_extra: std.ArrayListUnmanaged(u32) = .{}, @@ -228,7 +228,7 @@ pub fn parse(self: *Object, macho_file: *MachO) !void { // Parse DWARF __TEXT,__eh_frame section if (self.eh_frame_sect_index) |index| { - try self.initEhFrameRecords(index, macho_file); + try self.initEhFrameRecords(gpa, index, handle, macho_file); } // Parse Apple's __LD,__compact_unwind section @@ -261,7 +261,7 @@ pub fn parse(self: *Object, macho_file: *MachO) !void { try self.parseDebugInfo(macho_file); - for (self.atoms.items) |atom_index| { + for (self.getAtoms()) |atom_index| { const atom = self.getAtom(atom_index) orelse continue; const isec = atom.getInputSection(macho_file); if (mem.eql(u8, isec.sectName(), "__eh_frame") or @@ -606,7 +606,7 @@ fn initPointerLiterals(self: *Object, allocator: Allocator, macho_file: *MachO) } } -pub fn resolveLiterals(self: Object, lp: *MachO.LiteralPool, macho_file: *MachO) !void { +pub fn resolveLiterals(self: *Object, lp: *MachO.LiteralPool, macho_file: *MachO) !void { const tracy = trace(@src()); defer tracy.end(); @@ -646,7 +646,7 @@ pub fn resolveLiterals(self: Object, lp: *MachO.LiteralPool, macho_file: *MachO) } else { const lp_sym = lp.getSymbol(res.index, macho_file); const lp_atom = lp_sym.getAtom(macho_file).?; - lp_atom.alignment = @max(lp_atom.alignment, atom.alignment); + lp_atom.alignment = lp_atom.alignment.max(atom.alignment); atom.flags.alive = false; } atom.addExtra(.{ .literal_pool_index = res.index }, macho_file); @@ -684,7 +684,7 @@ pub fn resolveLiterals(self: Object, lp: *MachO.LiteralPool, macho_file: *MachO) } else { const lp_sym = lp.getSymbol(res.index, macho_file); const lp_atom = lp_sym.getAtom(macho_file).?; - lp_atom.alignment = @max(lp_atom.alignment, atom.alignment); + lp_atom.alignment = lp_atom.alignment.max(atom.alignment); atom.flags.alive = false; } atom.addExtra(.{ .literal_pool_index = res.index }, macho_file); @@ -823,7 +823,7 @@ fn initSymbols(self: *Object, allocator: Allocator, macho_file: *MachO) !void { const index = self.addSymbolAssumeCapacity(); const symbol = &self.symbols.items[index]; symbol.value = nlist.n_value; - symbol.name = .{ .pos = nlist.n_strx, .len = @intCast(self.getNStrx(nlist.n_strx).len + 1) }; + symbol.name = nlist.n_strx; symbol.nlist_idx = @intCast(i); symbol.extra = self.addSymbolExtraAssumeCapacity(.{}); @@ -838,7 +838,9 @@ fn initSymbols(self: *Object, allocator: Allocator, macho_file: *MachO) !void { symbol.flags.tentative = nlist.tentative(); symbol.flags.no_dead_strip = symbol.flags.no_dead_strip or nlist.noDeadStrip(); symbol.flags.dyn_ref = nlist.n_desc & macho.REFERENCED_DYNAMICALLY != 0; - symbol.flags.interposable = nlist.ext() and (nlist.sect() or nlist.abs()) and macho_file.options.dylib and macho_file.options.namespace == .flat and !nlist.pext(); + symbol.flags.interposable = nlist.ext() and (nlist.sect() or nlist.abs()) and macho_file.base.isDynLib() and !nlist.pext(); + // TODO + // symbol.flags.interposable = nlist.ext() and (nlist.sect() or nlist.abs()) and macho_file.base.isDynLib() and macho_file.options.namespace == .flat and !nlist.pext(); if (nlist.sect() and self.sections.items(.header)[nlist.n_sect - 1].type() == macho.S_THREAD_LOCAL_VARIABLES) @@ -869,7 +871,7 @@ fn initSymbolStabs(self: *Object, allocator: Allocator, nlists: anytype, macho_f fn find(fs: @This(), addr: u64) ?Symbol.Index { // TODO binary search since we have the list sorted for (fs.entries) |nlist| { - if (nlist.nlist.n_value == addr) return fs.ctx.symbols.items[nlist.idx]; + if (nlist.nlist.n_value == addr) return @intCast(nlist.idx); } return null; } @@ -920,17 +922,17 @@ fn initSymbolStabs(self: *Object, allocator: Allocator, nlists: anytype, macho_f switch (nlist.n_type) { macho.N_BNSYM => { stab.is_func = true; - stab.symbol = sym_lookup.find(nlist.n_value); + stab.index = sym_lookup.find(nlist.n_value); // TODO validate i += 3; }, macho.N_GSYM => { stab.is_func = false; - stab.symbol = sym_lookup.find(addr_lookup.get(self.getString(nlist.n_strx)).?); + stab.index = sym_lookup.find(addr_lookup.get(self.getString(nlist.n_strx)).?); }, macho.N_STSYM => { stab.is_func = false; - stab.symbol = sym_lookup.find(nlist.n_value); + stab.index = sym_lookup.find(nlist.n_value); }, else => { try macho_file.reportParseError2(self.index, "unhandled symbol stab type 0x{x}", .{ @@ -1103,9 +1105,9 @@ fn initUnwindRecords(self: *Object, allocator: Allocator, sect_id: u8, file: Fil ctx: *const Object, fn find(fs: @This(), addr: u64) ?Symbol.Index { - for (fs.ctx.symbols.items, 0..) |sym_index, i| { + for (0..fs.ctx.symbols.items.len) |i| { const nlist = fs.ctx.symtab.items(.nlist)[i]; - if (nlist.ext() and nlist.n_value == addr) return sym_index; + if (nlist.ext() and nlist.n_value == addr) return @intCast(i); } return null; } @@ -1274,7 +1276,7 @@ fn parseUnwindRecords(self: *Object, allocator: Allocator, cpu_arch: std.Target. // Create a null record const rec_index = try self.addUnwindRecord(allocator); const rec = self.getUnwindRecord(rec_index); - const atom = macho_file.getAtom(meta.atom).?; + const atom = self.getAtom(meta.atom).?; try self.unwind_records_indexes.append(allocator, rec_index); rec.length = @intCast(meta.size); rec.atom = meta.atom; @@ -1468,17 +1470,17 @@ fn findCompileUnit(self: *Object, args: struct { }; } -pub fn resolveSymbols(self: *Object, macho_file: *MachO) void { +pub fn resolveSymbols(self: *Object, macho_file: *MachO) !void { const tracy = trace(@src()); defer tracy.end(); - const gpa = macho_file.base.allocator; + 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.sect()) { const atom = self.getAtom(atom_index).?; - if (!atom.alive.load(.seq_cst)) continue; + if (!atom.flags.alive) continue; } const gop = try macho_file.resolver.getOrPut(gpa, .{ @@ -1643,7 +1645,7 @@ pub fn claimUnresolved(self: *Object, macho_file: *MachO) void { if (self.getSymbolRef(@intCast(i), macho_file).getFile(macho_file) != null) continue; - const is_import = switch (macho_file.options.undefined_treatment) { + const is_import = switch (macho_file.undefined_treatment) { .@"error" => false, .warn, .suppress => nlist.weakRef(), .dynamic_lookup => true, @@ -1682,8 +1684,8 @@ pub fn claimUnresolvedRelocatable(self: *Object, macho_file: *MachO) void { } } -fn addSection(self: *Object, allocator: Allocator, segname: []const u8, sectname: []const u8) !u32 { - const n_sect = @as(u32, @intCast(try self.sections.addOne(allocator))); +fn addSection(self: *Object, allocator: Allocator, segname: []const u8, sectname: []const u8) !u8 { + const n_sect = @as(u8, @intCast(try self.sections.addOne(allocator))); self.sections.set(n_sect, .{ .header = .{ .sectname = MachO.makeStaticString(sectname), @@ -1799,7 +1801,7 @@ pub fn writeAr(self: Object, ar_format: Archive.Format, macho_file: *MachO, writ try writer.writeAll(data); } -pub fn calcSymtabSize(self: *Object, macho_file: *MachO) !void { +pub fn calcSymtabSize(self: *Object, macho_file: *MachO) void { const tracy = trace(@src()); defer tracy.end(); @@ -1821,27 +1823,27 @@ pub fn calcSymtabSize(self: *Object, macho_file: *MachO) !void { 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)); } if (macho_file.base.comp.config.debug_format != .strip and self.hasDebugInfo()) - try self.calcStabsSize(macho_file); + self.calcStabsSize(macho_file); } -pub fn calcStabsSize(self: *Object, macho_file: *MachO) error{Overflow}!void { +pub fn calcStabsSize(self: *Object, macho_file: *MachO) void { if (self.compile_unit) |cu| { - const comp_dir = cu.getCompDir(self); - const tu_name = cu.getTuName(self); + const comp_dir = cu.getCompDir(self.*); + const tu_name = cu.getTuName(self.*); self.output_symtab_ctx.nstabs += 4; // N_SO, N_SO, N_OSO, N_SO self.output_symtab_ctx.strsize += @as(u32, @intCast(comp_dir.len + 1)); // comp_dir @@ -1876,12 +1878,12 @@ pub fn calcStabsSize(self: *Object, macho_file: *MachO) error{Overflow}!void { for (self.stab_files.items) |sf| { self.output_symtab_ctx.nstabs += 4; // N_SO, N_SO, N_OSO, N_SO - self.output_symtab_ctx.strsize += @as(u32, @intCast(sf.getCompDir(self).len + 1)); // comp_dir - self.output_symtab_ctx.strsize += @as(u32, @intCast(sf.getTuName(self).len + 1)); // tu_name - self.output_symtab_ctx.strsize += @as(u32, @intCast(sf.getOsoPath(self).len + 1)); // path + self.output_symtab_ctx.strsize += @as(u32, @intCast(sf.getCompDir(self.*).len + 1)); // comp_dir + self.output_symtab_ctx.strsize += @as(u32, @intCast(sf.getTuName(self.*).len + 1)); // tu_name + self.output_symtab_ctx.strsize += @as(u32, @intCast(sf.getOsoPath(self.*).len + 1)); // path for (sf.stabs.items) |stab| { - const sym = stab.getSymbol(macho_file) orelse continue; + const sym = stab.getSymbol(self.*) orelse continue; const file = sym.getFile(macho_file).?; if (file.getIndex() != self.index) continue; if (!sym.flags.output_symtab) continue; @@ -2065,7 +2067,7 @@ pub fn writeCompactUnwindRelocatable(self: *Object, macho_file: *MachO) !void { } } -pub fn writeSymtab(self: Object, macho_file: *MachO) void { +pub fn writeSymtab(self: Object, macho_file: *MachO, ctx: anytype) void { const tracy = trace(@src()); defer tracy.end(); @@ -2075,21 +2077,21 @@ pub fn writeSymtab(self: Object, macho_file: *MachO) void { const file = ref.getFile(macho_file) orelse continue; if (file.getIndex() != self.index) continue; const idx = sym.getOutputSymtabIndex(macho_file) orelse continue; - const out_sym = &macho_file.symtab.items[idx]; + const out_sym = &ctx.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); + @memcpy(ctx.strtab.items[n_strx..][0..name.len], name); n_strx += @intCast(name.len); - macho_file.strtab.items[n_strx] = 0; + ctx.strtab.items[n_strx] = 0; n_strx += 1; } if (macho_file.base.comp.config.debug_format != .strip and self.hasDebugInfo()) - try self.writeStabs(n_strx, macho_file); + self.writeStabs(n_strx, macho_file, ctx); } -pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void { +pub fn writeStabs(self: Object, stroff: u32, macho_file: *MachO, ctx: anytype) void { const writeFuncStab = struct { inline fn writeFuncStab( n_strx: u32, @@ -2097,7 +2099,7 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void { n_value: u64, size: u64, index: u32, - context: *MachO, + context: anytype, ) void { context.symtab.items[index] = .{ .n_strx = 0, @@ -2139,7 +2141,7 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void { // Open scope // N_SO comp_dir - macho_file.symtab.items[index] = .{ + ctx.symtab.items[index] = .{ .n_strx = n_strx, .n_type = macho.N_SO, .n_sect = 0, @@ -2147,9 +2149,9 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void { .n_value = 0, }; index += 1; - @memcpy(macho_file.strtab.items[n_strx..][0..comp_dir.len], comp_dir); + @memcpy(ctx.strtab.items[n_strx..][0..comp_dir.len], comp_dir); n_strx += @intCast(comp_dir.len); - macho_file.strtab.items[n_strx] = 0; + ctx.strtab.items[n_strx] = 0; n_strx += 1; // N_SO tu_name macho_file.symtab.items[index] = .{ @@ -2160,12 +2162,12 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void { .n_value = 0, }; index += 1; - @memcpy(macho_file.strtab.items[n_strx..][0..tu_name.len], tu_name); + @memcpy(ctx.strtab.items[n_strx..][0..tu_name.len], tu_name); n_strx += @intCast(tu_name.len); - macho_file.strtab.items[n_strx] = 0; + ctx.strtab.items[n_strx] = 0; n_strx += 1; // N_OSO path - macho_file.symtab.items[index] = .{ + ctx.symtab.items[index] = .{ .n_strx = n_strx, .n_type = macho.N_OSO, .n_sect = 0, @@ -2174,20 +2176,20 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void { }; index += 1; if (self.in_archive) |ar| { - @memcpy(macho_file.strtab.items[n_strx..][0..ar.path.len], ar.path); + @memcpy(ctx.strtab.items[n_strx..][0..ar.path.len], ar.path); n_strx += @intCast(ar.path.len); - macho_file.strtab.items[n_strx] = '('; + ctx.strtab.items[n_strx] = '('; n_strx += 1; - @memcpy(macho_file.strtab.items[n_strx..][0..self.path.len], self.path); + @memcpy(ctx.strtab.items[n_strx..][0..self.path.len], self.path); n_strx += @intCast(self.path.len); - macho_file.strtab.items[n_strx] = ')'; + ctx.strtab.items[n_strx] = ')'; n_strx += 1; - macho_file.strtab.items[n_strx] = 0; + ctx.strtab.items[n_strx] = 0; n_strx += 1; } else { - @memcpy(macho_file.strtab.items[n_strx..][0..self.path.len], self.path); + @memcpy(ctx.strtab.items[n_strx..][0..self.path.len], self.path); n_strx += @intCast(self.path.len); - macho_file.strtab.items[n_strx] = 0; + ctx.strtab.items[n_strx] = 0; n_strx += 1; } @@ -2203,17 +2205,17 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void { const sect = macho_file.sections.items(.header)[sym.getOutputSectionIndex(macho_file)]; const sym_n_strx = n_strx: { const symtab_index = sym.getOutputSymtabIndex(macho_file).?; - const osym = macho_file.symtab.items[symtab_index]; + const osym = ctx.symtab.items[symtab_index]; break :n_strx osym.n_strx; }; const sym_n_sect: u8 = if (!sym.flags.abs) @intCast(sym.getOutputSectionIndex(macho_file) + 1) else 0; const sym_n_value = sym.getAddress(.{}, macho_file); const sym_size = sym.getSize(macho_file); if (sect.isCode()) { - writeFuncStab(sym_n_strx, sym_n_sect, sym_n_value, sym_size, index, macho_file); + writeFuncStab(sym_n_strx, sym_n_sect, sym_n_value, sym_size, index, ctx); index += 4; } else if (sym.visibility == .global) { - macho_file.symtab.items[index] = .{ + ctx.symtab.items[index] = .{ .n_strx = sym_n_strx, .n_type = macho.N_GSYM, .n_sect = sym_n_sect, @@ -2222,7 +2224,7 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void { }; index += 1; } else { - macho_file.symtab.items[index] = .{ + ctx.symtab.items[index] = .{ .n_strx = sym_n_strx, .n_type = macho.N_STSYM, .n_sect = sym_n_sect, @@ -2235,7 +2237,7 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void { // Close scope // N_SO - macho_file.symtab.items[index] = .{ + ctx.symtab.items[index] = .{ .n_strx = 0, .n_type = macho.N_SO, .n_sect = 0, @@ -2246,13 +2248,13 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void { assert(self.hasSymbolStabs()); for (self.stab_files.items) |sf| { - const comp_dir = sf.getCombDir(self); + const comp_dir = sf.getCompDir(self); const tu_name = sf.getTuName(self); const oso_path = sf.getOsoPath(self); // Open scope // N_SO comp_dir - macho_file.symtab.items[index] = .{ + ctx.symtab.items[index] = .{ .n_strx = n_strx, .n_type = macho.N_SO, .n_sect = 0, @@ -2260,12 +2262,12 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void { .n_value = 0, }; index += 1; - @memcpy(macho_file.strtab.items[n_strx..][0..comp_dir.len], comp_dir); + @memcpy(ctx.strtab.items[n_strx..][0..comp_dir.len], comp_dir); n_strx += @intCast(comp_dir.len); - macho_file.strtab.items[n_strx] = 0; + ctx.strtab.items[n_strx] = 0; n_strx += 1; // N_SO tu_name - macho_file.symtab.items[index] = .{ + ctx.symtab.items[index] = .{ .n_strx = n_strx, .n_type = macho.N_SO, .n_sect = 0, @@ -2273,12 +2275,12 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void { .n_value = 0, }; index += 1; - @memcpy(macho_file.strtab.items[n_strx..][0..tu_name.len], tu_name); + @memcpy(ctx.strtab.items[n_strx..][0..tu_name.len], tu_name); n_strx += @intCast(tu_name.len); - macho_file.strtab.items[n_strx] = 0; + ctx.strtab.items[n_strx] = 0; n_strx += 1; // N_OSO path - macho_file.symtab.items[index] = .{ + ctx.symtab.items[index] = .{ .n_strx = n_strx, .n_type = macho.N_OSO, .n_sect = 0, @@ -2286,29 +2288,29 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void { .n_value = sf.getOsoModTime(self), }; index += 1; - @memcpy(macho_file.strtab.items[n_strx..][0..oso_path.len], oso_path); + @memcpy(ctx.strtab.items[n_strx..][0..oso_path.len], oso_path); n_strx += @intCast(oso_path.len); - macho_file.strtab.items[n_strx] = 0; + ctx.strtab.items[n_strx] = 0; n_strx += 1; for (sf.stabs.items) |stab| { - const sym = stab.getSymbol(macho_file) orelse continue; + const sym = stab.getSymbol(self) orelse continue; const file = sym.getFile(macho_file).?; if (file.getIndex() != self.index) continue; if (!sym.flags.output_symtab) continue; const sym_n_strx = n_strx: { const symtab_index = sym.getOutputSymtabIndex(macho_file).?; - const osym = macho_file.symtab.items[symtab_index]; + const osym = ctx.symtab.items[symtab_index]; break :n_strx osym.n_strx; }; const sym_n_sect: u8 = if (!sym.flags.abs) @intCast(sym.getOutputSectionIndex(macho_file) + 1) else 0; const sym_n_value = sym.getAddress(.{}, macho_file); const sym_size = sym.getSize(macho_file); if (stab.is_func) { - writeFuncStab(sym_n_strx, sym_n_sect, sym_n_value, sym_size, index, macho_file); + writeFuncStab(sym_n_strx, sym_n_sect, sym_n_value, sym_size, index, ctx); index += 4; } else if (sym.visibility == .global) { - macho_file.symtab.items[index] = .{ + ctx.symtab.items[index] = .{ .n_strx = sym_n_strx, .n_type = macho.N_GSYM, .n_sect = sym_n_sect, @@ -2317,7 +2319,7 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void { }; index += 1; } else { - macho_file.symtab.items[index] = .{ + ctx.symtab.items[index] = .{ .n_strx = sym_n_strx, .n_type = macho.N_STSYM, .n_sect = sym_n_sect, @@ -2330,7 +2332,7 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void { // Close scope // N_SO - macho_file.symtab.items[index] = .{ + ctx.symtab.items[index] = .{ .n_strx = 0, .n_type = macho.N_SO, .n_sect = 0, @@ -2343,7 +2345,7 @@ pub fn writeStabs(self: *const Object, stroff: u32, macho_file: *MachO) void { } pub fn getAtomRelocs(self: *const Object, atom: Atom, macho_file: *MachO) []const Relocation { - const extra = atom.getExtra(macho_file).?; + const extra = atom.getExtra(macho_file); const relocs = self.sections.items(.relocs)[atom.n_sect]; return relocs.items[extra.rel_index..][0..extra.rel_count]; } @@ -2402,7 +2404,7 @@ pub fn asFile(self: *Object) File { } const AddAtomArgs = struct { - name: MachO.String, + name: u32, n_sect: u8, off: u64, size: u64, @@ -2420,7 +2422,7 @@ fn addAtom(self: *Object, allocator: Allocator, args: AddAtomArgs) !Atom.Index { .size = args.size, .off = args.off, .extra = try self.addAtomExtra(allocator, .{}), - .alignment = args.alignment, + .alignment = Atom.Alignment.fromLog2Units(args.alignment), }; return atom_index; } @@ -2693,12 +2695,12 @@ fn formatSymtab( } for (object.stab_files.items) |sf| { try writer.print(" stabs({s},{s},{s})\n", .{ - sf.getCompDir(object), - sf.getTuName(object), - sf.getOsoPath(object), + sf.getCompDir(object.*), + sf.getTuName(object.*), + sf.getOsoPath(object.*), }); for (sf.stabs.items) |stab| { - try writer.print(" {}", .{stab.fmt(object)}); + try writer.print(" {}", .{stab.fmt(object.*)}); } } } @@ -2744,33 +2746,33 @@ const StabFile = struct { comp_dir: u32, stabs: std.ArrayListUnmanaged(Stab) = .{}, - fn getCompDir(sf: StabFile, object: *const Object) [:0]const u8 { + fn getCompDir(sf: StabFile, object: Object) [:0]const u8 { const nlist = object.symtab.items(.nlist)[sf.comp_dir]; return object.getString(nlist.n_strx); } - fn getTuName(sf: StabFile, object: *const Object) [:0]const u8 { + fn getTuName(sf: StabFile, object: Object) [:0]const u8 { const nlist = object.symtab.items(.nlist)[sf.comp_dir + 1]; return object.getString(nlist.n_strx); } - fn getOsoPath(sf: StabFile, object: *const Object) [:0]const u8 { + fn getOsoPath(sf: StabFile, object: Object) [:0]const u8 { const nlist = object.symtab.items(.nlist)[sf.comp_dir + 2]; return object.getString(nlist.n_strx); } - fn getOsoModTime(sf: StabFile, object: *const Object) u64 { + fn getOsoModTime(sf: StabFile, object: Object) u64 { const nlist = object.symtab.items(.nlist)[sf.comp_dir + 2]; return nlist.n_value; } const Stab = struct { is_func: bool = true, - symbol: ?Symbol.Index = null, + index: ?Symbol.Index = null, - fn getSymbol(stab: Stab, object: *const Object) ?*Symbol { + fn getSymbol(stab: Stab, object: Object) ?Symbol { const index = stab.index orelse return null; - return &object.symbols.items[index]; + return object.symbols.items[index]; } pub fn format( @@ -2786,9 +2788,9 @@ const StabFile = struct { @compileError("do not format stabs directly"); } - const StabFormatContext = struct { Stab, *const Object }; + const StabFormatContext = struct { Stab, Object }; - pub fn fmt(stab: Stab, object: *const Object) std.fmt.Formatter(format2) { + pub fn fmt(stab: Stab, object: Object) std.fmt.Formatter(format2) { return .{ .data = .{ stab, object } }; } @@ -2817,11 +2819,11 @@ const CompileUnit = struct { comp_dir: u32, tu_name: u32, - fn getCompDir(cu: CompileUnit, object: *const Object) [:0]const u8 { + fn getCompDir(cu: CompileUnit, object: Object) [:0]const u8 { return object.getString(cu.comp_dir); } - fn getTuName(cu: CompileUnit, object: *const Object) [:0]const u8 { + fn getTuName(cu: CompileUnit, object: Object) [:0]const u8 { return object.getString(cu.tu_name); } }; @@ -2840,15 +2842,14 @@ const CompactUnwindCtx = struct { const x86_64 = struct { fn parseRelocs( - self: *const Object, - n_sect: u8, + self: *Object, sect: macho.section_64, out: *std.ArrayListUnmanaged(Relocation), + handle: File.Handle, macho_file: *MachO, ) !void { const gpa = macho_file.base.comp.gpa; - const handle = macho_file.getFileHandle(self.file_handle); const relocs_buffer = try gpa.alloc(u8, sect.nreloc * @sizeOf(macho.relocation_info)); defer gpa.free(relocs_buffer); { @@ -2857,8 +2858,12 @@ const x86_64 = struct { } const relocs = @as([*]align(1) const macho.relocation_info, @ptrCast(relocs_buffer.ptr))[0..sect.nreloc]; - const code = try self.getSectionData(@intCast(n_sect), macho_file); + const code = try gpa.alloc(u8, sect.size); defer gpa.free(code); + { + const amt = try handle.preadAll(code, sect.offset + self.offset); + if (amt != code.len) return error.InputOutput; + } try out.ensureTotalCapacityPrecise(gpa, relocs.len); @@ -2880,8 +2885,9 @@ const x86_64 = struct { .X86_64_RELOC_SIGNED_4 => 4, else => 0, }; + var is_extern = rel.r_extern == 1; - const target = if (rel.r_extern == 0) blk: { + const target = if (!is_extern) blk: { const nsect = rel.r_symbolnum - 1; const taddr: i64 = if (rel.r_pcrel == 1) @as(i64, @intCast(sect.addr)) + rel.r_address + addend + 4 @@ -2893,9 +2899,15 @@ const x86_64 = struct { }); return error.MalformedObject; }; - addend = taddr - @as(i64, @intCast(macho_file.getAtom(target).?.getInputAddress(macho_file))); + const target_atom = self.getAtom(target).?; + addend = taddr - @as(i64, @intCast(target_atom.getInputAddress(macho_file))); + const isec = target_atom.getInputSection(macho_file); + if (isCstringLiteral(isec) or isFixedSizeLiteral(isec) or isPtrLiteral(isec)) { + is_extern = true; + break :blk target_atom.getExtra(macho_file).literal_symbol_index; + } break :blk target; - } else self.symbols.items[rel.r_symbolnum]; + } else rel.r_symbolnum; const has_subtractor = if (i > 0 and @as(macho.reloc_type_x86_64, @enumFromInt(relocs[i - 1].r_type)) == .X86_64_RELOC_SUBTRACTOR) @@ -2909,7 +2921,7 @@ const x86_64 = struct { break :blk true; } else false; - const @"type": Relocation.Type = validateRelocType(rel, rel_type) catch |err| { + const @"type": Relocation.Type = validateRelocType(rel, rel_type, is_extern) catch |err| { switch (err) { error.Pcrel => try macho_file.reportParseError2( self.index, @@ -2936,7 +2948,7 @@ const x86_64 = struct { }; out.appendAssumeCapacity(.{ - .tag = if (rel.r_extern == 1) .@"extern" else .local, + .tag = if (is_extern) .@"extern" else .local, .offset = @as(u32, @intCast(rel.r_address)), .target = target, .addend = addend, @@ -2951,7 +2963,7 @@ const x86_64 = struct { } } - fn validateRelocType(rel: macho.relocation_info, rel_type: macho.reloc_type_x86_64) !Relocation.Type { + fn validateRelocType(rel: macho.relocation_info, rel_type: macho.reloc_type_x86_64, is_extern: bool) !Relocation.Type { switch (rel_type) { .X86_64_RELOC_UNSIGNED => { if (rel.r_pcrel == 1) return error.Pcrel; @@ -2971,7 +2983,7 @@ const x86_64 = struct { => { if (rel.r_pcrel == 0) return error.NonPcrel; if (rel.r_length != 2) return error.InvalidLength; - if (rel.r_extern == 0) return error.NonExtern; + if (!is_extern) return error.NonExtern; return switch (rel_type) { .X86_64_RELOC_BRANCH => .branch, .X86_64_RELOC_GOT_LOAD => .got_load, @@ -3002,15 +3014,14 @@ const x86_64 = struct { const aarch64 = struct { fn parseRelocs( - self: *const Object, - n_sect: u8, + self: *Object, sect: macho.section_64, out: *std.ArrayListUnmanaged(Relocation), + handle: File.Handle, macho_file: *MachO, ) !void { const gpa = macho_file.base.comp.gpa; - const handle = macho_file.getFileHandle(self.file_handle); const relocs_buffer = try gpa.alloc(u8, sect.nreloc * @sizeOf(macho.relocation_info)); defer gpa.free(relocs_buffer); { @@ -3019,8 +3030,12 @@ const aarch64 = struct { } const relocs = @as([*]align(1) const macho.relocation_info, @ptrCast(relocs_buffer.ptr))[0..sect.nreloc]; - const code = try self.getSectionData(@intCast(n_sect), macho_file); + const code = try gpa.alloc(u8, sect.size); defer gpa.free(code); + { + const amt = try handle.preadAll(code, sect.offset + self.offset); + if (amt != code.len) return error.InputOutput; + } try out.ensureTotalCapacityPrecise(gpa, relocs.len); @@ -3066,8 +3081,9 @@ const aarch64 = struct { } const rel_type: macho.reloc_type_arm64 = @enumFromInt(rel.r_type); + var is_extern = rel.r_extern == 1; - const target = if (rel.r_extern == 0) blk: { + const target = if (!is_extern) blk: { const nsect = rel.r_symbolnum - 1; const taddr: i64 = if (rel.r_pcrel == 1) @as(i64, @intCast(sect.addr)) + rel.r_address + addend @@ -3079,9 +3095,15 @@ const aarch64 = struct { }); return error.MalformedObject; }; - addend = taddr - @as(i64, @intCast(macho_file.getAtom(target).?.getInputAddress(macho_file))); + const target_atom = self.getAtom(target).?; + addend = taddr - @as(i64, @intCast(target_atom.getInputAddress(macho_file))); + const isec = target_atom.getInputSection(macho_file); + if (isCstringLiteral(isec) or isFixedSizeLiteral(isec) or isPtrLiteral(isec)) { + is_extern = true; + break :blk target_atom.getExtra(macho_file).literal_symbol_index; + } break :blk target; - } else self.symbols.items[rel.r_symbolnum]; + } else rel.r_symbolnum; const has_subtractor = if (i > 0 and @as(macho.reloc_type_arm64, @enumFromInt(relocs[i - 1].r_type)) == .ARM64_RELOC_SUBTRACTOR) @@ -3095,7 +3117,7 @@ const aarch64 = struct { break :blk true; } else false; - const @"type": Relocation.Type = validateRelocType(rel, rel_type) catch |err| { + const @"type": Relocation.Type = validateRelocType(rel, rel_type, is_extern) catch |err| { switch (err) { error.Pcrel => try macho_file.reportParseError2( self.index, @@ -3122,7 +3144,7 @@ const aarch64 = struct { }; out.appendAssumeCapacity(.{ - .tag = if (rel.r_extern == 1) .@"extern" else .local, + .tag = if (is_extern) .@"extern" else .local, .offset = @as(u32, @intCast(rel.r_address)), .target = target, .addend = addend, @@ -3137,7 +3159,7 @@ const aarch64 = struct { } } - fn validateRelocType(rel: macho.relocation_info, rel_type: macho.reloc_type_arm64) !Relocation.Type { + fn validateRelocType(rel: macho.relocation_info, rel_type: macho.reloc_type_arm64, is_extern: bool) !Relocation.Type { switch (rel_type) { .ARM64_RELOC_UNSIGNED => { if (rel.r_pcrel == 1) return error.Pcrel; @@ -3158,7 +3180,7 @@ const aarch64 = struct { => { if (rel.r_pcrel == 0) return error.NonPcrel; if (rel.r_length != 2) return error.InvalidLength; - if (rel.r_extern == 0) return error.NonExtern; + if (!is_extern) return error.NonExtern; return switch (rel_type) { .ARM64_RELOC_BRANCH26 => .branch, .ARM64_RELOC_PAGE21 => .page, @@ -3175,7 +3197,7 @@ const aarch64 = struct { => { if (rel.r_pcrel == 1) return error.Pcrel; if (rel.r_length != 2) return error.InvalidLength; - if (rel.r_extern == 0) return error.NonExtern; + if (!is_extern) return error.NonExtern; return switch (rel_type) { .ARM64_RELOC_PAGEOFF12 => .pageoff, .ARM64_RELOC_GOT_LOAD_PAGEOFF12 => .got_load_pageoff, diff --git a/src/link/MachO/Symbol.zig b/src/link/MachO/Symbol.zig index 003996fc95..8cb198e7d7 100644 --- a/src/link/MachO/Symbol.zig +++ b/src/link/MachO/Symbol.zig @@ -150,7 +150,7 @@ pub fn getObjcSelrefsAddress(symbol: Symbol, macho_file: *MachO) u64 { const file = symbol.getFile(macho_file).?; return switch (file) { .dylib, .zig_object => unreachable, - .object, .internal => |x| x.symbols.items[extra.objc_selrefs].getAddress(.{}, macho_file), + inline else => |x| x.symbols.items[extra.objc_selrefs].getAddress(.{}, macho_file), }; } @@ -186,7 +186,7 @@ pub fn getOutputSymtabIndex(symbol: Symbol, macho_file: *MachO) ?u32 { const symtab_ctx = switch (file) { inline else => |x| x.output_symtab_ctx, }; - var idx = symbol.getExtra(macho_file).?.symtab; + var idx = symbol.getExtra(macho_file).symtab; if (symbol.isLocal()) { idx += symtab_ctx.ilocal; } else if (symbol.flags.@"export") { diff --git a/src/link/MachO/UnwindInfo.zig b/src/link/MachO/UnwindInfo.zig index f06db2f842..8fb4b2ce63 100644 --- a/src/link/MachO/UnwindInfo.zig +++ b/src/link/MachO/UnwindInfo.zig @@ -473,11 +473,11 @@ pub const Record = struct { } pub fn getAtom(rec: Record, macho_file: *MachO) *Atom { - return macho_file.getAtom(rec.atom).?; + return rec.getObject(macho_file).getAtom(rec.atom).?; } pub fn getLsdaAtom(rec: Record, macho_file: *MachO) ?*Atom { - return macho_file.getAtom(rec.lsda); + return rec.getObject(macho_file).getAtom(rec.lsda); } pub fn getPersonality(rec: Record, macho_file: *MachO) ?*Symbol { diff --git a/src/link/MachO/ZigObject.zig b/src/link/MachO/ZigObject.zig index dba3e4c1b1..544d778f39 100644 --- a/src/link/MachO/ZigObject.zig +++ b/src/link/MachO/ZigObject.zig @@ -343,6 +343,36 @@ pub fn writeAr(self: ZigObject, ar_format: Archive.Format, writer: anytype) !voi try writer.writeAll(self.data.items); } +pub fn claimUnresolved(self: *ZigObject, macho_file: *MachO) void { + const tracy = trace(@src()); + defer tracy.end(); + + for (self.symbols.items, 0..) |*sym, i| { + const nlist = self.symtab.items(.nlist)[i]; + if (!nlist.ext()) continue; + if (!nlist.undf()) continue; + + if (self.getSymbolRef(@intCast(i), macho_file).getFile(macho_file) != null) continue; + + const is_import = switch (macho_file.undefined_treatment) { + .@"error" => false, + .warn, .suppress => nlist.weakRef(), + .dynamic_lookup => true, + }; + if (is_import) { + sym.value = 0; + sym.atom_ref = .{ .index = 0, .file = 0 }; + sym.flags.weak = false; + sym.flags.weak_ref = nlist.weakRef(); + sym.flags.import = is_import; + sym.visibility = .global; + + const idx = self.globals.items[i]; + macho_file.resolver.values.items[idx - 1] = .{ .index = @intCast(i), .file = self.index }; + } + } +} + pub fn scanRelocs(self: *ZigObject, macho_file: *MachO) !void { for (self.getAtoms()) |atom_index| { const atom = self.getAtom(atom_index) orelse continue; @@ -378,7 +408,7 @@ pub fn calcSymtabSize(self: *ZigObject, macho_file: *MachO) void { } } -pub fn writeSymtab(self: ZigObject, macho_file: *MachO) void { +pub fn writeSymtab(self: ZigObject, macho_file: *MachO, ctx: anytype) void { const tracy = trace(@src()); defer tracy.end(); @@ -388,13 +418,13 @@ pub fn writeSymtab(self: ZigObject, macho_file: *MachO) void { const file = ref.getFile(macho_file) orelse continue; if (file.getIndex() != self.index) continue; const idx = sym.getOutputSymtabIndex(macho_file) orelse continue; - const out_sym = &macho_file.symtab.items[idx]; + const out_sym = &ctx.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); + @memcpy(ctx.strtab.items[n_strx..][0..name.len], name); n_strx += @intCast(name.len); - macho_file.strtab.items[n_strx] = 0; + ctx.strtab.items[n_strx] = 0; n_strx += 1; } } @@ -1098,7 +1128,7 @@ pub fn lowerUnnamedConst( }, }; const sym = self.symbols.items[sym_index]; - try unnamed_consts.append(gpa, sym.atom); + try unnamed_consts.append(gpa, sym.atom_ref.index); return sym_index; } diff --git a/src/link/MachO/dyld_info/Rebase.zig b/src/link/MachO/dyld_info/Rebase.zig index 9233a25e07..c0bcb42ed1 100644 --- a/src/link/MachO/dyld_info/Rebase.zig +++ b/src/link/MachO/dyld_info/Rebase.zig @@ -34,7 +34,7 @@ pub fn updateSize(rebase: *Rebase, macho_file: *MachO) !void { for (objects.items) |index| { const file = macho_file.getFile(index).?; for (file.getAtoms()) |atom_index| { - const atom = macho_file.getAtom(atom_index) orelse continue; + const atom = file.getAtom(atom_index) orelse continue; if (!atom.flags.alive) continue; if (atom.getInputSection(macho_file).isZerofill()) continue; const atom_addr = atom.getAddress(macho_file); @@ -43,7 +43,7 @@ pub fn updateSize(rebase: *Rebase, macho_file: *MachO) !void { for (atom.getRelocs(macho_file)) |rel| { if (rel.type != .unsigned or rel.meta.length != 3) continue; if (rel.tag == .@"extern") { - const sym = rel.getTargetSymbol(macho_file); + const sym = rel.getTargetSymbol(atom.*, macho_file); if (sym.isTlvInit(macho_file)) continue; if (sym.flags.import) continue; } @@ -72,7 +72,7 @@ pub fn updateSize(rebase: *Rebase, macho_file: *MachO) !void { const seg_id = macho_file.sections.items(.segment_id)[sid]; const seg = macho_file.segments.items[seg_id]; for (macho_file.got.symbols.items, 0..) |ref, idx| { - const sym = macho_file.getSymbol(ref); + const sym = ref.getSymbol(macho_file).?; const addr = macho_file.got.getAddress(@intCast(idx), macho_file); if (!sym.flags.import) { try rebase.entries.append(gpa, .{ @@ -88,7 +88,7 @@ pub fn updateSize(rebase: *Rebase, macho_file: *MachO) !void { const seg_id = macho_file.sections.items(.segment_id)[sid]; const seg = macho_file.segments.items[seg_id]; for (macho_file.stubs.symbols.items, 0..) |ref, idx| { - const sym = macho_file.getSymbol(ref); + const sym = ref.getSymbol(macho_file).?; const addr = sect.addr + idx * @sizeOf(u64); const rebase_entry = Rebase.Entry{ .offset = addr - seg.vmaddr, @@ -104,7 +104,7 @@ pub fn updateSize(rebase: *Rebase, macho_file: *MachO) !void { const seg_id = macho_file.sections.items(.segment_id)[sid]; const seg = macho_file.segments.items[seg_id]; for (macho_file.tlv_ptr.symbols.items, 0..) |ref, idx| { - const sym = macho_file.getSymbol(ref); + const sym = ref.getSymbol(macho_file).?; const addr = macho_file.tlv_ptr.getAddress(@intCast(idx), macho_file); if (!sym.flags.import) { try rebase.entries.append(gpa, .{ diff --git a/src/link/MachO/dyld_info/Trie.zig b/src/link/MachO/dyld_info/Trie.zig index aead1372f0..44e6cd4234 100644 --- a/src/link/MachO/dyld_info/Trie.zig +++ b/src/link/MachO/dyld_info/Trie.zig @@ -94,33 +94,31 @@ pub fn updateSize(self: *Trie, macho_file: *MachO) !void { const gpa = macho_file.base.comp.gpa; try self.init(gpa); - // TODO - // try self.nodes.ensureUnusedCapacity(gpa, macho_file.resolver.values.items.len * 2); - // try self.edges.ensureUnusedCapacity(gpa, macho_file.resolver.values.items.len * 2); + try self.nodes.ensureUnusedCapacity(gpa, macho_file.resolver.values.items.len * 2); + try self.edges.ensureUnusedCapacity(gpa, macho_file.resolver.values.items.len * 2); const seg = macho_file.getTextSegment(); - for (macho_file.objects.items) |index| { - for (macho_file.getFile(index).?.getSymbols()) |ref| { - const sym = macho_file.getSymbol(ref); - if (!sym.flags.@"export") continue; - if (sym.getAtom(macho_file)) |atom| if (!atom.flags.alive) continue; - var flags: u64 = if (sym.flags.abs) - macho.EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE - else if (sym.flags.tlv) - macho.EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL - else - macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR; - if (sym.flags.weak) { - flags |= macho.EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION; - macho_file.weak_defines = true; - macho_file.binds_to_weak = true; - } - try self.put(gpa, .{ - .name = sym.getName(macho_file), - .vmaddr_offset = sym.getAddress(.{ .stubs = false }, macho_file) - seg.vmaddr, - .export_flags = flags, - }); + for (macho_file.resolver.values.items) |ref| { + if (ref.getFile(macho_file) == null) continue; + const sym = ref.getSymbol(macho_file).?; + if (!sym.flags.@"export") continue; + if (sym.getAtom(macho_file)) |atom| if (!atom.flags.alive) continue; + var flags: u64 = if (sym.flags.abs) + macho.EXPORT_SYMBOL_FLAGS_KIND_ABSOLUTE + else if (sym.flags.tlv) + macho.EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL + else + macho.EXPORT_SYMBOL_FLAGS_KIND_REGULAR; + if (sym.flags.weak) { + flags |= macho.EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION; + macho_file.weak_defines = true; + macho_file.binds_to_weak = true; } + try self.put(gpa, .{ + .name = sym.getName(macho_file), + .vmaddr_offset = sym.getAddress(.{ .stubs = false }, macho_file) - seg.vmaddr, + .export_flags = flags, + }); } try self.finalize(gpa); diff --git a/src/link/MachO/dyld_info/bind.zig b/src/link/MachO/dyld_info/bind.zig index 8684c66bac..94e7c7ef29 100644 --- a/src/link/MachO/dyld_info/bind.zig +++ b/src/link/MachO/dyld_info/bind.zig @@ -1,17 +1,19 @@ pub const Entry = struct { - target: Symbol.Index, + target: MachO.Ref, offset: u64, segment_id: u8, addend: i64, pub fn lessThan(ctx: *MachO, entry: Entry, other: Entry) bool { + _ = ctx; if (entry.segment_id == other.segment_id) { - if (entry.target == other.target) { + if (entry.target.eql(other.target)) { return entry.offset < other.offset; } - const entry_name = ctx.getSymbol(entry.target).getName(ctx); - const other_name = ctx.getSymbol(other.target).getName(ctx); - return std.mem.lessThan(u8, entry_name, other_name); + if (entry.target.file == other.target.file) { + return entry.target.index < other.target.index; + } + return entry.target.file < other.target.file; } return entry.segment_id < other.segment_id; } @@ -44,7 +46,7 @@ pub const Bind = struct { for (objects.items) |index| { const file = macho_file.getFile(index).?; for (file.getAtoms()) |atom_index| { - const atom = macho_file.getAtom(atom_index) orelse continue; + const atom = file.getAtom(atom_index) orelse continue; if (!atom.flags.alive) continue; if (atom.getInputSection(macho_file).isZerofill()) continue; const atom_addr = atom.getAddress(macho_file); @@ -55,10 +57,10 @@ pub const Bind = struct { if (rel.type != .unsigned or rel.meta.length != 3 or rel.tag != .@"extern") continue; const rel_offset = rel.offset - atom.off; const addend = rel.addend + rel.getRelocAddend(cpu_arch); - const sym = rel.getTargetSymbol(macho_file); + const sym = rel.getTargetSymbol(atom.*, macho_file); if (sym.isTlvInit(macho_file)) continue; const entry = Entry{ - .target = rel.target, + .target = rel.getTargetSymbolRef(atom.*, macho_file), .offset = atom_addr + rel_offset - seg.vmaddr, .segment_id = seg_id, .addend = addend, @@ -74,7 +76,7 @@ pub const Bind = struct { const seg_id = macho_file.sections.items(.segment_id)[sid]; const seg = macho_file.segments.items[seg_id]; for (macho_file.got.symbols.items, 0..) |ref, idx| { - const sym = macho_file.getSymbol(ref); + const sym = ref.getSymbol(macho_file).?; const addr = macho_file.got.getAddress(@intCast(idx), macho_file); const entry = Entry{ .target = ref, @@ -93,7 +95,7 @@ pub const Bind = struct { const seg_id = macho_file.sections.items(.segment_id)[sid]; const seg = macho_file.segments.items[seg_id]; for (macho_file.stubs.symbols.items, 0..) |ref, idx| { - const sym = macho_file.getSymbol(ref); + const sym = ref.getSymbol(macho_file).?; const addr = sect.addr + idx * @sizeOf(u64); const bind_entry = Entry{ .target = ref, @@ -112,7 +114,7 @@ pub const Bind = struct { const seg = macho_file.segments.items[seg_id]; for (macho_file.tlv_ptr.symbols.items, 0..) |ref, idx| { - const sym = macho_file.getSymbol(ref); + const sym = ref.getSymbol(macho_file).?; const addr = macho_file.tlv_ptr.getAddress(@intCast(idx), macho_file); const entry = Entry{ .target = ref, @@ -162,7 +164,7 @@ pub const Bind = struct { var addend: i64 = 0; var count: usize = 0; var skip: u64 = 0; - var target: ?Symbol.Index = null; + var target: ?MachO.Ref = null; var state: enum { start, @@ -173,7 +175,7 @@ pub const Bind = struct { var i: usize = 0; while (i < entries.len) : (i += 1) { const current = entries[i]; - if (target == null or target.? != current.target) { + if (target == null or !target.?.eql(current.target)) { switch (state) { .start => {}, .bind_single => try doBind(writer), @@ -182,7 +184,7 @@ pub const Bind = struct { state = .start; target = current.target; - const sym = ctx.getSymbol(current.target); + const sym = current.target.getSymbol(ctx).?; const name = sym.getName(ctx); const flags: u8 = if (sym.weakRef(ctx)) macho.BIND_SYMBOL_FLAGS_WEAK_IMPORT else 0; const ordinal: i16 = ord: { @@ -296,7 +298,7 @@ pub const WeakBind = struct { for (objects.items) |index| { const file = macho_file.getFile(index).?; for (file.getAtoms()) |atom_index| { - const atom = macho_file.getAtom(atom_index) orelse continue; + const atom = file.getAtom(atom_index) orelse continue; if (!atom.flags.alive) continue; if (atom.getInputSection(macho_file).isZerofill()) continue; const atom_addr = atom.getAddress(macho_file); @@ -307,10 +309,10 @@ pub const WeakBind = struct { if (rel.type != .unsigned or rel.meta.length != 3 or rel.tag != .@"extern") continue; const rel_offset = rel.offset - atom.off; const addend = rel.addend + rel.getRelocAddend(cpu_arch); - const sym = rel.getTargetSymbol(macho_file); + const sym = rel.getTargetSymbol(atom.*, macho_file); if (sym.isTlvInit(macho_file)) continue; const entry = Entry{ - .target = rel.target, + .target = rel.getTargetSymbolRef(atom.*, macho_file), .offset = atom_addr + rel_offset - seg.vmaddr, .segment_id = seg_id, .addend = addend, @@ -326,7 +328,7 @@ pub const WeakBind = struct { const seg_id = macho_file.sections.items(.segment_id)[sid]; const seg = macho_file.segments.items[seg_id]; for (macho_file.got.symbols.items, 0..) |ref, idx| { - const sym = macho_file.getSymbol(ref); + const sym = ref.getSymbol(macho_file).?; const addr = macho_file.got.getAddress(@intCast(idx), macho_file); const entry = Entry{ .target = ref, @@ -346,7 +348,7 @@ pub const WeakBind = struct { const seg = macho_file.segments.items[seg_id]; for (macho_file.stubs.symbols.items, 0..) |ref, idx| { - const sym = macho_file.getSymbol(ref); + const sym = ref.getSymbol(macho_file).?; const addr = sect.addr + idx * @sizeOf(u64); const bind_entry = Entry{ .target = ref, @@ -365,7 +367,7 @@ pub const WeakBind = struct { const seg = macho_file.segments.items[seg_id]; for (macho_file.tlv_ptr.symbols.items, 0..) |ref, idx| { - const sym = macho_file.getSymbol(ref); + const sym = ref.getSymbol(macho_file).?; const addr = macho_file.tlv_ptr.getAddress(@intCast(idx), macho_file); const entry = Entry{ .target = ref, @@ -415,7 +417,7 @@ pub const WeakBind = struct { var addend: i64 = 0; var count: usize = 0; var skip: u64 = 0; - var target: ?Symbol.Index = null; + var target: ?MachO.Ref = null; var state: enum { start, @@ -426,7 +428,7 @@ pub const WeakBind = struct { var i: usize = 0; while (i < entries.len) : (i += 1) { const current = entries[i]; - if (target == null or target.? != current.target) { + if (target == null or !target.?.eql(current.target)) { switch (state) { .start => {}, .bind_single => try doBind(writer), @@ -435,7 +437,7 @@ pub const WeakBind = struct { state = .start; target = current.target; - const sym = ctx.getSymbol(current.target); + const sym = current.target.getSymbol(ctx).?; const name = sym.getName(ctx); const flags: u8 = 0; // TODO NON_WEAK_DEFINITION @@ -536,7 +538,7 @@ pub const LazyBind = struct { const seg = macho_file.segments.items[seg_id]; for (macho_file.stubs.symbols.items, 0..) |ref, idx| { - const sym = macho_file.getSymbol(ref); + const sym = ref.getSymbol(macho_file).?; const addr = sect.addr + idx * @sizeOf(u64); const bind_entry = Entry{ .target = ref, @@ -565,7 +567,7 @@ pub const LazyBind = struct { for (self.entries.items) |entry| { self.offsets.appendAssumeCapacity(@intCast(self.buffer.items.len)); - const sym = ctx.getSymbol(entry.target); + const sym = entry.target.getSymbol(ctx).?; const name = sym.getName(ctx); const flags: u8 = if (sym.weakRef(ctx)) macho.BIND_SYMBOL_FLAGS_WEAK_IMPORT else 0; const ordinal: i16 = ord: { diff --git a/src/link/MachO/file.zig b/src/link/MachO/file.zig index c01416efd5..c1558292f5 100644 --- a/src/link/MachO/file.zig +++ b/src/link/MachO/file.zig @@ -30,10 +30,10 @@ pub const File = union(enum) { } } - pub fn resolveSymbols(file: File, macho_file: *MachO) void { - switch (file) { + pub fn resolveSymbols(file: File, macho_file: *MachO) !void { + return switch (file) { inline else => |x| x.resolveSymbols(macho_file), - } + }; } pub fn scanRelocs(file: File, macho_file: *MachO) !void { @@ -147,19 +147,19 @@ pub const File = union(enum) { if (ref.getFile(macho_file) == null) continue; if (ref.file != file.getIndex()) continue; const sym = ref.getSymbol(macho_file).?; - if (sym.getSectionFlags().got) { + if (sym.flags.needs_got) { log.debug("'{s}' needs GOT", .{sym.getName(macho_file)}); try macho_file.got.addSymbol(ref, macho_file); } - if (sym.getSectionFlags().stubs) { + if (sym.flags.stubs) { log.debug("'{s}' needs STUBS", .{sym.getName(macho_file)}); try macho_file.stubs.addSymbol(ref, macho_file); } - if (sym.getSectionFlags().tlv_ptr) { + if (sym.flags.tlv_ptr) { log.debug("'{s}' needs TLV pointer", .{sym.getName(macho_file)}); try macho_file.tlv_ptr.addSymbol(ref, macho_file); } - if (sym.getSectionFlags().objc_stubs) { + if (sym.flags.objc_stubs) { log.debug("'{s}' needs OBJC STUBS", .{sym.getName(macho_file)}); try macho_file.objc_stubs.addSymbol(ref, macho_file); } @@ -171,7 +171,7 @@ pub const File = union(enum) { defer tracy.end(); for (file.getAtoms()) |atom_index| { const atom = file.getAtom(atom_index) orelse continue; - if (!atom.alive.load(.seq_cst)) continue; + if (!atom.flags.alive) continue; atom.out_n_sect = try Atom.initOutputSection(atom.getInputSection(macho_file), macho_file); } } @@ -185,18 +185,18 @@ pub const File = union(enum) { pub fn writeAtoms(file: File, macho_file: *MachO) !void { return switch (file) { - .dylib => unreachable, + .dylib, .zig_object => unreachable, inline else => |x| x.writeAtoms(macho_file), }; } - pub fn calcSymtabSize(file: File, macho_file: *MachO) !void { + pub fn calcSymtabSize(file: File, macho_file: *MachO) void { return switch (file) { inline else => |x| x.calcSymtabSize(macho_file), }; } - pub fn writeSymtab(file: File, macho_file: *MachO, ctx: anytype) !void { + pub fn writeSymtab(file: File, macho_file: *MachO, ctx: anytype) void { return switch (file) { inline else => |x| x.writeSymtab(macho_file, ctx), }; diff --git a/src/link/MachO/synthetic.zig b/src/link/MachO/synthetic.zig index a366fea2b9..14bc97c229 100644 --- a/src/link/MachO/synthetic.zig +++ b/src/link/MachO/synthetic.zig @@ -23,7 +23,7 @@ pub const ZigGotSection = struct { const index = try zig_got.allocateEntry(gpa); const entry = &zig_got.entries.items[index]; entry.* = sym_index; - const symbol = zo.getSymbol(sym_index); + const symbol = &zo.symbols.items[sym_index]; assert(symbol.flags.needs_zig_got); symbol.flags.has_zig_got = true; symbol.addExtra(.{ .zig_got = index }, macho_file); @@ -56,7 +56,7 @@ pub const ZigGotSection = struct { const zo = macho_file.getZigObject().?; const off = zig_got.entryOffset(index, macho_file); const entry = zig_got.entries.items[index]; - const value = zo.getSymbol(entry).getAddress(.{ .stubs = false }, macho_file); + const value = zo.symbols.items[entry].getAddress(.{ .stubs = false }, macho_file); var buf: [8]u8 = undefined; std.mem.writeInt(u64, &buf, value, .little); @@ -66,7 +66,7 @@ pub const ZigGotSection = struct { pub fn writeAll(zig_got: ZigGotSection, macho_file: *MachO, writer: anytype) !void { const zo = macho_file.getZigObject().?; for (zig_got.entries.items) |entry| { - const symbol = zo.getSymbol(entry); + const symbol = zo.symbols.items[entry]; const value = symbol.address(.{ .stubs = false }, macho_file); try writer.writeInt(u64, value, .little); } @@ -94,7 +94,7 @@ pub const ZigGotSection = struct { const zo = macho_file.getZigObject().?; try writer.writeAll("__zig_got\n"); for (zig_got.entries.items, 0..) |entry, index| { - const symbol = zo.getSymbol(entry); + const symbol = zo.symbols.items[entry]; try writer.print(" {d}@0x{x} => {d}@0x{x} ({s})\n", .{ index, zig_got.entryAddress(@intCast(index), macho_file), @@ -694,7 +694,7 @@ pub const DataInCode = struct { dices[next_dice].offset < end_off) : (next_dice += 1) {} - if (atom.alive.load(.seq_cst)) for (dices[start_dice..next_dice]) |d| { + if (atom.flags.alive) for (dices[start_dice..next_dice]) |d| { dice.entries.appendAssumeCapacity(.{ .offset = @intCast(atom.getAddress(macho_file) + d.offset - start_off - base_address), .length = d.length, diff --git a/src/link/MachO/thunks.zig b/src/link/MachO/thunks.zig index d832e6fcf6..2f2bd177e4 100644 --- a/src/link/MachO/thunks.zig +++ b/src/link/MachO/thunks.zig @@ -37,7 +37,7 @@ pub fn createThunks(sect_id: u8, macho_file: *MachO) !void { // Scan relocs in the group and create trampolines for any unreachable callsite try scanRelocs(thunk_index, gpa, atoms[start..i], macho_file); - thunk.value = try advance(header, thunk.size(), .@"4"); + thunk.value = advance(header, thunk.size(), .@"4"); log.debug("thunk({d}) : {}", .{ thunk_index, thunk.fmt(macho_file) }); } @@ -99,8 +99,8 @@ pub const Thunk = struct { return header.addr + thunk.value; } - pub fn getTargetAddress(thunk: Thunk, sym_index: Symbol.Index, macho_file: *MachO) u64 { - return thunk.getAddress(macho_file) + thunk.symbols.getIndex(sym_index).? * trampoline_size; + pub fn getTargetAddress(thunk: Thunk, ref: MachO.Ref, macho_file: *MachO) u64 { + return thunk.getAddress(macho_file) + thunk.symbols.getIndex(ref).? * trampoline_size; } pub fn write(thunk: Thunk, macho_file: *MachO, writer: anytype) !void { |
