authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-08-19 16:15:19+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-08-29 11:39:34+02:00
log7b282dffe68a7187a4fa4b5c11c82f1f67248a96
treeae1592746bfa08e3882358d7108c296f95dee003
parent702bcfecf5732eceada9bfbca0804c706c238d49

macho: unify concept of SymbolWithLoc across drivers


12 files changed, 88 insertions(+), 127 deletions(-)

src/arch/aarch64/Emit.zig+4-4
...@@ -670,7 +670,7 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -670,7 +670,7 @@ fn mirCallExtern(emit: *Emit, inst: Mir.Inst.Index) !void {
670670
671 if (emit.bin_file.cast(link.File.MachO)) |macho_file| {671 if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
672 // Add relocation to the decl.672 // Add relocation to the decl.
673 const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index, .file = null }).?;673 const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = relocation.atom_index }).?;
674 const target = macho_file.getGlobalByIndex(relocation.sym_index);674 const target = macho_file.getGlobalByIndex(relocation.sym_index);
675 try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{675 try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
676 .type = .branch,676 .type = .branch,
...@@ -885,9 +885,9 @@ fn mirLoadMemoryPie(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -885,9 +885,9 @@ fn mirLoadMemoryPie(emit: *Emit, inst: Mir.Inst.Index) !void {
885 if (emit.bin_file.cast(link.File.MachO)) |macho_file| {885 if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
886 const Atom = link.File.MachO.Atom;886 const Atom = link.File.MachO.Atom;
887 const Relocation = Atom.Relocation;887 const Relocation = Atom.Relocation;
888 const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = data.atom_index, .file = null }).?;888 const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = data.atom_index }).?;
889 try Atom.addRelocations(macho_file, atom_index, &[_]Relocation{ .{889 try Atom.addRelocations(macho_file, atom_index, &[_]Relocation{ .{
890 .target = .{ .sym_index = data.sym_index, .file = null },890 .target = .{ .sym_index = data.sym_index },
891 .offset = offset,891 .offset = offset,
892 .addend = 0,892 .addend = 0,
893 .pcrel = true,893 .pcrel = true,
...@@ -898,7 +898,7 @@ fn mirLoadMemoryPie(emit: *Emit, inst: Mir.Inst.Index) !void {...@@ -898,7 +898,7 @@ fn mirLoadMemoryPie(emit: *Emit, inst: Mir.Inst.Index) !void {
898 else => unreachable,898 else => unreachable,
899 },899 },
900 }, .{900 }, .{
901 .target = .{ .sym_index = data.sym_index, .file = null },901 .target = .{ .sym_index = data.sym_index },
902 .offset = offset + 4,902 .offset = offset + 4,
903 .addend = 0,903 .addend = 0,
904 .pcrel = false,904 .pcrel = false,
src/arch/x86_64/Emit.zig+3-8
...@@ -43,9 +43,7 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -43,9 +43,7 @@ pub fn emitMir(emit: *Emit) Error!void {
43 }),43 }),
44 .linker_extern_fn => |symbol| if (emit.bin_file.cast(link.File.MachO)) |macho_file| {44 .linker_extern_fn => |symbol| if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
45 // Add relocation to the decl.45 // Add relocation to the decl.
46 const atom_index = macho_file.getAtomIndexForSymbol(46 const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = symbol.atom_index }).?;
47 .{ .sym_index = symbol.atom_index, .file = null },
48 ).?;
49 const target = macho_file.getGlobalByIndex(symbol.sym_index);47 const target = macho_file.getGlobalByIndex(symbol.sym_index);
50 try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{48 try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
51 .type = .branch,49 .type = .branch,
...@@ -77,10 +75,7 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -77,10 +75,7 @@ pub fn emitMir(emit: *Emit) Error!void {
77 .linker_import,75 .linker_import,
78 .linker_tlv,76 .linker_tlv,
79 => |symbol| if (emit.bin_file.cast(link.File.MachO)) |macho_file| {77 => |symbol| if (emit.bin_file.cast(link.File.MachO)) |macho_file| {
80 const atom_index = macho_file.getAtomIndexForSymbol(.{78 const atom_index = macho_file.getAtomIndexForSymbol(.{ .sym_index = symbol.atom_index }).?;
81 .sym_index = symbol.atom_index,
82 .file = null,
83 }).?;
84 try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{79 try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{
85 .type = switch (lowered_relocs[0].target) {80 .type = switch (lowered_relocs[0].target) {
86 .linker_got => .got,81 .linker_got => .got,
...@@ -88,7 +83,7 @@ pub fn emitMir(emit: *Emit) Error!void {...@@ -88,7 +83,7 @@ pub fn emitMir(emit: *Emit) Error!void {
88 .linker_tlv => .tlv,83 .linker_tlv => .tlv,
89 else => unreachable,84 else => unreachable,
90 },85 },
91 .target = .{ .sym_index = symbol.sym_index, .file = null },86 .target = .{ .sym_index = symbol.sym_index },
92 .offset = @as(u32, @intCast(end_offset - 4)),87 .offset = @as(u32, @intCast(end_offset - 4)),
93 .addend = 0,88 .addend = 0,
94 .pcrel = true,89 .pcrel = true,
src/link/MachO.zig+48-43
...@@ -249,20 +249,14 @@ const DeclMetadata = struct {...@@ -249,20 +249,14 @@ const DeclMetadata = struct {
249249
250 fn getExport(m: DeclMetadata, macho_file: *const MachO, name: []const u8) ?u32 {250 fn getExport(m: DeclMetadata, macho_file: *const MachO, name: []const u8) ?u32 {
251 for (m.exports.items) |exp| {251 for (m.exports.items) |exp| {
252 if (mem.eql(u8, name, macho_file.getSymbolName(.{252 if (mem.eql(u8, name, macho_file.getSymbolName(.{ .sym_index = exp }))) return exp;
253 .sym_index = exp,
254 .file = null,
255 }))) return exp;
256 }253 }
257 return null;254 return null;
258 }255 }
259256
260 fn getExportPtr(m: *DeclMetadata, macho_file: *MachO, name: []const u8) ?*u32 {257 fn getExportPtr(m: *DeclMetadata, macho_file: *MachO, name: []const u8) ?*u32 {
261 for (m.exports.items) |*exp| {258 for (m.exports.items) |*exp| {
262 if (mem.eql(u8, name, macho_file.getSymbolName(.{259 if (mem.eql(u8, name, macho_file.getSymbolName(.{ .sym_index = exp.* }))) return exp;
263 .sym_index = exp.*,
264 .file = null,
265 }))) return exp;
266 }260 }
267 return null;261 return null;
268 }262 }
...@@ -284,21 +278,20 @@ const ResolveAction = struct {...@@ -284,21 +278,20 @@ const ResolveAction = struct {
284 };278 };
285};279};
286280
287pub const SymbolWithLoc = struct {281pub const SymbolWithLoc = extern struct {
288 // Index into the respective symbol table.282 // Index into the respective symbol table.
289 sym_index: u32,283 sym_index: u32,
290284
291 // null means it's a synthetic global.285 // 0 means it's a synthetic global.
292 file: ?u32 = null,286 file: u32 = 0,
293287
294 pub fn eql(this: SymbolWithLoc, other: SymbolWithLoc) bool {288 pub fn getFile(self: SymbolWithLoc) ?u32 {
295 if (this.file == null and other.file == null) {289 if (self.file == 0) return null;
296 return this.sym_index == other.sym_index;290 return self.file - 1;
297 }291 }
298 if (this.file != null and other.file != null) {292
299 return this.sym_index == other.sym_index and this.file.? == other.file.?;293 pub fn eql(self: SymbolWithLoc, other: SymbolWithLoc) bool {
300 }294 return self.file == other.file and self.sym_index == other.sym_index;
301 return false;
302 }295 }
303};296};
304297
...@@ -1576,7 +1569,7 @@ pub fn allocateSpecialSymbols(self: *MachO) !void {...@@ -1576,7 +1569,7 @@ pub fn allocateSpecialSymbols(self: *MachO) !void {
1576 "__mh_execute_header",1569 "__mh_execute_header",
1577 }) |name| {1570 }) |name| {
1578 const global = self.getGlobal(name) orelse continue;1571 const global = self.getGlobal(name) orelse continue;
1579 if (global.file != null) continue;1572 if (global.getFile() != null) continue;
1580 const sym = self.getSymbolPtr(global);1573 const sym = self.getSymbolPtr(global);
1581 const seg = self.getSegment(self.text_section_index.?);1574 const seg = self.getSegment(self.text_section_index.?);
1582 sym.n_sect = 1;1575 sym.n_sect = 1;
...@@ -1597,7 +1590,7 @@ pub fn createAtom(self: *MachO) !Atom.Index {...@@ -1597,7 +1590,7 @@ pub fn createAtom(self: *MachO) !Atom.Index {
1597 try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom_index);1590 try self.atom_by_index_table.putNoClobber(gpa, sym_index, atom_index);
1598 atom.* = .{1591 atom.* = .{
1599 .sym_index = sym_index,1592 .sym_index = sym_index,
1600 .file = null,1593 .file = 0,
1601 .size = 0,1594 .size = 0,
1602 .prev_index = null,1595 .prev_index = null,
1603 .next_index = null,1596 .next_index = null,
...@@ -1664,7 +1657,7 @@ fn createMhExecuteHeaderSymbol(self: *MachO) !void {...@@ -1664,7 +1657,7 @@ fn createMhExecuteHeaderSymbol(self: *MachO) !void {
16641657
1665 const gpa = self.base.allocator;1658 const gpa = self.base.allocator;
1666 const sym_index = try self.allocateSymbol();1659 const sym_index = try self.allocateSymbol();
1667 const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null };1660 const sym_loc = SymbolWithLoc{ .sym_index = sym_index };
1668 const sym = self.getSymbolPtr(sym_loc);1661 const sym = self.getSymbolPtr(sym_loc);
1669 sym.* = .{1662 sym.* = .{
1670 .n_strx = try self.strtab.insert(gpa, "__mh_execute_header"),1663 .n_strx = try self.strtab.insert(gpa, "__mh_execute_header"),
...@@ -1684,7 +1677,7 @@ fn createDsoHandleSymbol(self: *MachO) !void {...@@ -1684,7 +1677,7 @@ fn createDsoHandleSymbol(self: *MachO) !void {
16841677
1685 const gpa = self.base.allocator;1678 const gpa = self.base.allocator;
1686 const sym_index = try self.allocateSymbol();1679 const sym_index = try self.allocateSymbol();
1687 const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null };1680 const sym_loc = SymbolWithLoc{ .sym_index = sym_index };
1688 const sym = self.getSymbolPtr(sym_loc);1681 const sym = self.getSymbolPtr(sym_loc);
1689 sym.* = .{1682 sym.* = .{
1690 .n_strx = try self.strtab.insert(gpa, "___dso_handle"),1683 .n_strx = try self.strtab.insert(gpa, "___dso_handle"),
...@@ -1998,10 +1991,7 @@ fn allocateGlobal(self: *MachO) !u32 {...@@ -1998,10 +1991,7 @@ fn allocateGlobal(self: *MachO) !u32 {
1998 }1991 }
1999 };1992 };
20001993
2001 self.globals.items[index] = .{1994 self.globals.items[index] = .{ .sym_index = 0 };
2002 .sym_index = 0,
2003 .file = null,
2004 };
20051995
2006 return index;1996 return index;
2007}1997}
...@@ -2613,7 +2603,7 @@ pub fn updateDeclExports(...@@ -2613,7 +2603,7 @@ pub fn updateDeclExports(
2613 try decl_metadata.exports.append(gpa, sym_index);2603 try decl_metadata.exports.append(gpa, sym_index);
2614 break :blk sym_index;2604 break :blk sym_index;
2615 };2605 };
2616 const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null };2606 const sym_loc = SymbolWithLoc{ .sym_index = sym_index };
2617 const sym = self.getSymbolPtr(sym_loc);2607 const sym = self.getSymbolPtr(sym_loc);
2618 sym.* = .{2608 sym.* = .{
2619 .n_strx = try self.strtab.insert(gpa, exp_name),2609 .n_strx = try self.strtab.insert(gpa, exp_name),
...@@ -2643,7 +2633,7 @@ pub fn updateDeclExports(...@@ -2643,7 +2633,7 @@ pub fn updateDeclExports(
2643 error.MultipleSymbolDefinitions => {2633 error.MultipleSymbolDefinitions => {
2644 // TODO: this needs rethinking2634 // TODO: this needs rethinking
2645 const global = self.getGlobal(exp_name).?;2635 const global = self.getGlobal(exp_name).?;
2646 if (sym_loc.sym_index != global.sym_index and global.file != null) {2636 if (sym_loc.sym_index != global.sym_index and global.getFile() != null) {
2647 _ = try mod.failed_exports.put(mod.gpa, exp, try Module.ErrorMsg.create(2637 _ = try mod.failed_exports.put(mod.gpa, exp, try Module.ErrorMsg.create(
2648 gpa,2638 gpa,
2649 decl.srcLoc(mod),2639 decl.srcLoc(mod),
...@@ -2672,7 +2662,7 @@ pub fn deleteDeclExport(...@@ -2672,7 +2662,7 @@ pub fn deleteDeclExport(
2672 defer gpa.free(exp_name);2662 defer gpa.free(exp_name);
2673 const sym_index = metadata.getExportPtr(self, exp_name) orelse return;2663 const sym_index = metadata.getExportPtr(self, exp_name) orelse return;
26742664
2675 const sym_loc = SymbolWithLoc{ .sym_index = sym_index.*, .file = null };2665 const sym_loc = SymbolWithLoc{ .sym_index = sym_index.* };
2676 const sym = self.getSymbolPtr(sym_loc);2666 const sym = self.getSymbolPtr(sym_loc);
2677 log.debug("deleting export '{s}'", .{exp_name});2667 log.debug("deleting export '{s}'", .{exp_name});
2678 assert(sym.sect() and sym.ext());2668 assert(sym.sect() and sym.ext());
...@@ -2688,10 +2678,7 @@ pub fn deleteDeclExport(...@@ -2688,10 +2678,7 @@ pub fn deleteDeclExport(
2688 if (self.resolver.fetchRemove(exp_name)) |entry| {2678 if (self.resolver.fetchRemove(exp_name)) |entry| {
2689 defer gpa.free(entry.key);2679 defer gpa.free(entry.key);
2690 self.globals_free_list.append(gpa, entry.value) catch {};2680 self.globals_free_list.append(gpa, entry.value) catch {};
2691 self.globals.items[entry.value] = .{2681 self.globals.items[entry.value] = .{ .sym_index = 0 };
2692 .sym_index = 0,
2693 .file = null,
2694 };
2695 }2682 }
26962683
2697 sym_index.* = 0;2684 sym_index.* = 0;
...@@ -2730,10 +2717,10 @@ pub fn getDeclVAddr(self: *MachO, decl_index: Module.Decl.Index, reloc_info: Fil...@@ -2730,10 +2717,10 @@ pub fn getDeclVAddr(self: *MachO, decl_index: Module.Decl.Index, reloc_info: Fil
27302717
2731 const this_atom_index = try self.getOrCreateAtomForDecl(decl_index);2718 const this_atom_index = try self.getOrCreateAtomForDecl(decl_index);
2732 const sym_index = self.getAtom(this_atom_index).getSymbolIndex().?;2719 const sym_index = self.getAtom(this_atom_index).getSymbolIndex().?;
2733 const atom_index = self.getAtomIndexForSymbol(.{ .sym_index = reloc_info.parent_atom_index, .file = null }).?;2720 const atom_index = self.getAtomIndexForSymbol(.{ .sym_index = reloc_info.parent_atom_index }).?;
2734 try Atom.addRelocation(self, atom_index, .{2721 try Atom.addRelocation(self, atom_index, .{
2735 .type = .unsigned,2722 .type = .unsigned,
2736 .target = .{ .sym_index = sym_index, .file = null },2723 .target = .{ .sym_index = sym_index },
2737 .offset = @as(u32, @intCast(reloc_info.offset)),2724 .offset = @as(u32, @intCast(reloc_info.offset)),
2738 .addend = reloc_info.addend,2725 .addend = reloc_info.addend,
2739 .pcrel = false,2726 .pcrel = false,
...@@ -3514,7 +3501,7 @@ fn writeSymtab(self: *MachO) !SymtabCtx {...@@ -3514,7 +3501,7 @@ fn writeSymtab(self: *MachO) !SymtabCtx {
35143501
3515 for (self.locals.items, 0..) |sym, sym_id| {3502 for (self.locals.items, 0..) |sym, sym_id| {
3516 if (sym.n_strx == 0) continue; // no name, skip3503 if (sym.n_strx == 0) continue; // no name, skip
3517 const sym_loc = SymbolWithLoc{ .sym_index = @as(u32, @intCast(sym_id)), .file = null };3504 const sym_loc = SymbolWithLoc{ .sym_index = @as(u32, @intCast(sym_id)) };
3518 if (self.symbolIsTemp(sym_loc)) continue; // local temp symbol, skip3505 if (self.symbolIsTemp(sym_loc)) continue; // local temp symbol, skip
3519 if (self.getGlobal(self.getSymbolName(sym_loc)) != null) continue; // global symbol is either an export or import, skip3506 if (self.getGlobal(self.getSymbolName(sym_loc)) != null) continue; // global symbol is either an export or import, skip
3520 try locals.append(sym);3507 try locals.append(sym);
...@@ -3934,13 +3921,13 @@ pub fn symbolIsTemp(self: *MachO, sym_with_loc: SymbolWithLoc) bool {...@@ -3934,13 +3921,13 @@ pub fn symbolIsTemp(self: *MachO, sym_with_loc: SymbolWithLoc) bool {
39343921
3935/// Returns pointer-to-symbol described by `sym_with_loc` descriptor.3922/// Returns pointer-to-symbol described by `sym_with_loc` descriptor.
3936pub fn getSymbolPtr(self: *MachO, sym_with_loc: SymbolWithLoc) *macho.nlist_64 {3923pub fn getSymbolPtr(self: *MachO, sym_with_loc: SymbolWithLoc) *macho.nlist_64 {
3937 assert(sym_with_loc.file == null);3924 assert(sym_with_loc.getFile() == null);
3938 return &self.locals.items[sym_with_loc.sym_index];3925 return &self.locals.items[sym_with_loc.sym_index];
3939}3926}
39403927
3941/// Returns symbol described by `sym_with_loc` descriptor.3928/// Returns symbol described by `sym_with_loc` descriptor.
3942pub fn getSymbol(self: *const MachO, sym_with_loc: SymbolWithLoc) macho.nlist_64 {3929pub fn getSymbol(self: *const MachO, sym_with_loc: SymbolWithLoc) macho.nlist_64 {
3943 assert(sym_with_loc.file == null);3930 assert(sym_with_loc.getFile() == null);
3944 return self.locals.items[sym_with_loc.sym_index];3931 return self.locals.items[sym_with_loc.sym_index];
3945}3932}
39463933
...@@ -4006,7 +3993,7 @@ pub fn getAtomPtr(self: *MachO, atom_index: Atom.Index) *Atom {...@@ -4006,7 +3993,7 @@ pub fn getAtomPtr(self: *MachO, atom_index: Atom.Index) *Atom {
4006/// Returns atom if there is an atom referenced by the symbol described by `sym_with_loc` descriptor.3993/// Returns atom if there is an atom referenced by the symbol described by `sym_with_loc` descriptor.
4007/// Returns null on failure.3994/// Returns null on failure.
4008pub fn getAtomIndexForSymbol(self: *MachO, sym_with_loc: SymbolWithLoc) ?Atom.Index {3995pub fn getAtomIndexForSymbol(self: *MachO, sym_with_loc: SymbolWithLoc) ?Atom.Index {
4009 assert(sym_with_loc.file == null);3996 assert(sym_with_loc.getFile() == null);
4010 return self.atom_by_index_table.get(sym_with_loc.sym_index);3997 return self.atom_by_index_table.get(sym_with_loc.sym_index);
4011}3998}
40123999
...@@ -4034,13 +4021,31 @@ pub inline fn getPageSize(cpu_arch: std.Target.Cpu.Arch) u16 {...@@ -4034,13 +4021,31 @@ pub inline fn getPageSize(cpu_arch: std.Target.Cpu.Arch) u16 {
4034 };4021 };
4035}4022}
40364023
4037pub fn findFirst(comptime T: type, haystack: []align(1) const T, start: usize, predicate: anytype) usize {4024/// Binary search
4025pub fn bsearch(comptime T: type, haystack: []align(1) const T, predicate: anytype) usize {
4038 if (!@hasDecl(@TypeOf(predicate), "predicate"))4026 if (!@hasDecl(@TypeOf(predicate), "predicate"))
4039 @compileError("Predicate is required to define fn predicate(@This(), T) bool");4027 @compileError("Predicate is required to define fn predicate(@This(), T) bool");
40404028
4041 if (start == haystack.len) return start;4029 var min: usize = 0;
4030 var max: usize = haystack.len;
4031 while (min < max) {
4032 const index = (min + max) / 2;
4033 const curr = haystack[index];
4034 if (predicate.predicate(curr)) {
4035 min = index + 1;
4036 } else {
4037 max = index;
4038 }
4039 }
4040 return min;
4041}
4042
4043/// Linear search
4044pub fn lsearch(comptime T: type, haystack: []align(1) const T, predicate: anytype) usize {
4045 if (!@hasDecl(@TypeOf(predicate), "predicate"))
4046 @compileError("Predicate is required to define fn predicate(@This(), T) bool");
40424047
4043 var i = start;4048 var i: usize = 0;
4044 while (i < haystack.len) : (i += 1) {4049 while (i < haystack.len) : (i += 1) {
4045 if (predicate.predicate(haystack[i])) break;4050 if (predicate.predicate(haystack[i])) break;
4046 }4051 }
src/link/MachO/Atom.zig+9-6
...@@ -17,16 +17,19 @@ const MachO = @import("../MachO.zig");...@@ -17,16 +17,19 @@ const MachO = @import("../MachO.zig");
17pub const Relocation = @import("Relocation.zig");17pub const Relocation = @import("Relocation.zig");
18const SymbolWithLoc = MachO.SymbolWithLoc;18const SymbolWithLoc = MachO.SymbolWithLoc;
1919
20/// Each decl always gets a local symbol with the fully qualified name.20/// Each Atom always gets a symbol with the fully qualified name.
21/// The vaddr and size are found here directly.21/// The symbol can reside in any object file context structure in `symtab` array
22/// The file offset is found by computing the vaddr offset from the section vaddr22/// (see `Object`), or if the symbol is a synthetic symbol such as a GOT cell or
23/// the symbol references, and adding that to the file offset of the section.23/// a stub trampoline, it can be found in the linkers `locals` arraylist.
24/// If this field is 0, it means the codegen size = 0 and there is no symbol or24/// If this field is 0, it means the codegen size = 0 and there is no symbol or
25/// offset table entry.25/// offset table entry.
26sym_index: u32,26sym_index: u32,
2727
28/// null means symbol defined by Zig source.28/// 0 means an Atom is a synthetic Atom such as a GOT cell defined by the linker.
29file: ?u32,29/// Otherwise, it is the index into appropriate object file (indexing from 1).
30/// Prefer using `getFile()` helper to get the file index out rather than using
31/// the field directly.
32file: u32,
3033
31/// Size and alignment of this atom34/// Size and alignment of this atom
32/// Unlike in Elf, we need to store the size of this symbol as part of35/// Unlike in Elf, we need to store the size of this symbol as part of
src/link/MachO/DebugSymbols.zig+1-1
...@@ -475,7 +475,7 @@ fn writeSymtab(self: *DebugSymbols, macho_file: *MachO) !void {...@@ -475,7 +475,7 @@ fn writeSymtab(self: *DebugSymbols, macho_file: *MachO) !void {
475475
476 for (macho_file.locals.items, 0..) |sym, sym_id| {476 for (macho_file.locals.items, 0..) |sym, sym_id| {
477 if (sym.n_strx == 0) continue; // no name, skip477 if (sym.n_strx == 0) continue; // no name, skip
478 const sym_loc = MachO.SymbolWithLoc{ .sym_index = @as(u32, @intCast(sym_id)), .file = null };478 const sym_loc = MachO.SymbolWithLoc{ .sym_index = @as(u32, @intCast(sym_id)) };
479 if (macho_file.symbolIsTemp(sym_loc)) continue; // local temp symbol, skip479 if (macho_file.symbolIsTemp(sym_loc)) continue; // local temp symbol, skip
480 if (macho_file.getGlobal(macho_file.getSymbolName(sym_loc)) != null) continue; // global symbol is either an export or import, skip480 if (macho_file.getGlobal(macho_file.getSymbolName(sym_loc)) != null) continue; // global symbol is either an export or import, skip
481 var out_sym = sym;481 var out_sym = sym;
src/link/MachO/Object.zig+11-10
...@@ -23,9 +23,10 @@ const Atom = @import("ZldAtom.zig");...@@ -23,9 +23,10 @@ const Atom = @import("ZldAtom.zig");
23const AtomIndex = @import("zld.zig").AtomIndex;23const AtomIndex = @import("zld.zig").AtomIndex;
24const DwarfInfo = @import("DwarfInfo.zig");24const DwarfInfo = @import("DwarfInfo.zig");
25const LoadCommandIterator = macho.LoadCommandIterator;25const LoadCommandIterator = macho.LoadCommandIterator;
26const Zld = @import("zld.zig").Zld;26const MachO = @import("../MachO.zig");
27const SymbolWithLoc = @import("zld.zig").SymbolWithLoc;27const SymbolWithLoc = MachO.SymbolWithLoc;
28const UnwindInfo = @import("UnwindInfo.zig");28const UnwindInfo = @import("UnwindInfo.zig");
29const Zld = @import("zld.zig").Zld;
2930
30name: []const u8,31name: []const u8,
31mtime: u64,32mtime: u64,
...@@ -314,10 +315,10 @@ fn filterSymbolsBySection(symbols: []macho.nlist_64, n_sect: u8) struct {...@@ -314,10 +315,10 @@ fn filterSymbolsBySection(symbols: []macho.nlist_64, n_sect: u8) struct {
314 }315 }
315 };316 };
316317
317 const index = @import("zld.zig").lsearch(macho.nlist_64, symbols, FirstMatch{318 const index = MachO.lsearch(macho.nlist_64, symbols, FirstMatch{
318 .n_sect = n_sect,319 .n_sect = n_sect,
319 });320 });
320 const len = @import("zld.zig").lsearch(macho.nlist_64, symbols[index..], FirstNonMatch{321 const len = MachO.lsearch(macho.nlist_64, symbols[index..], FirstNonMatch{
321 .n_sect = n_sect,322 .n_sect = n_sect,
322 });323 });
323324
...@@ -336,10 +337,10 @@ fn filterSymbolsByAddress(symbols: []macho.nlist_64, start_addr: u64, end_addr:...@@ -336,10 +337,10 @@ fn filterSymbolsByAddress(symbols: []macho.nlist_64, start_addr: u64, end_addr:
336 }337 }
337 };338 };
338339
339 const index = @import("zld.zig").lsearch(macho.nlist_64, symbols, Predicate{340 const index = MachO.lsearch(macho.nlist_64, symbols, Predicate{
340 .addr = start_addr,341 .addr = start_addr,
341 });342 });
342 const len = @import("zld.zig").lsearch(macho.nlist_64, symbols[index..], Predicate{343 const len = MachO.lsearch(macho.nlist_64, symbols[index..], Predicate{
343 .addr = end_addr,344 .addr = end_addr,
344 });345 });
345346
...@@ -631,8 +632,8 @@ fn filterRelocs(...@@ -631,8 +632,8 @@ fn filterRelocs(
631 }632 }
632 };633 };
633634
634 const start = @import("zld.zig").bsearch(macho.relocation_info, relocs, Predicate{ .addr = end_addr });635 const start = MachO.bsearch(macho.relocation_info, relocs, Predicate{ .addr = end_addr });
635 const len = @import("zld.zig").lsearch(macho.relocation_info, relocs[start..], LPredicate{ .addr = start_addr });636 const len = MachO.lsearch(macho.relocation_info, relocs[start..], LPredicate{ .addr = start_addr });
636637
637 return .{ .start = @as(u32, @intCast(start)), .len = @as(u32, @intCast(len)) };638 return .{ .start = @as(u32, @intCast(start)), .len = @as(u32, @intCast(len)) };
638}639}
...@@ -1031,7 +1032,7 @@ pub fn getSymbolByAddress(self: Object, addr: u64, sect_hint: ?u8) u32 {...@@ -1031,7 +1032,7 @@ pub fn getSymbolByAddress(self: Object, addr: u64, sect_hint: ?u8) u32 {
1031 if (sect_hint) |sect_id| {1032 if (sect_hint) |sect_id| {
1032 if (self.source_section_index_lookup[sect_id].len > 0) {1033 if (self.source_section_index_lookup[sect_id].len > 0) {
1033 const lookup = self.source_section_index_lookup[sect_id];1034 const lookup = self.source_section_index_lookup[sect_id];
1034 const target_sym_index = @import("zld.zig").lsearch(1035 const target_sym_index = MachO.lsearch(
1035 i64,1036 i64,
1036 self.source_address_lookup[lookup.start..][0..lookup.len],1037 self.source_address_lookup[lookup.start..][0..lookup.len],
1037 Predicate{ .addr = @as(i64, @intCast(addr)) },1038 Predicate{ .addr = @as(i64, @intCast(addr)) },
...@@ -1046,7 +1047,7 @@ pub fn getSymbolByAddress(self: Object, addr: u64, sect_hint: ?u8) u32 {...@@ -1046,7 +1047,7 @@ pub fn getSymbolByAddress(self: Object, addr: u64, sect_hint: ?u8) u32 {
1046 return self.getSectionAliasSymbolIndex(sect_id);1047 return self.getSectionAliasSymbolIndex(sect_id);
1047 }1048 }
10481049
1049 const target_sym_index = @import("zld.zig").lsearch(i64, self.source_address_lookup, Predicate{1050 const target_sym_index = MachO.lsearch(i64, self.source_address_lookup, Predicate{
1050 .addr = @as(i64, @intCast(addr)),1051 .addr = @as(i64, @intCast(addr)),
1051 });1052 });
1052 assert(target_sym_index > 0);1053 assert(target_sym_index > 0);
src/link/MachO/UnwindInfo.zig+2-1
...@@ -15,8 +15,9 @@ const Allocator = mem.Allocator;...@@ -15,8 +15,9 @@ const Allocator = mem.Allocator;
15const Atom = @import("ZldAtom.zig");15const Atom = @import("ZldAtom.zig");
16const AtomIndex = @import("zld.zig").AtomIndex;16const AtomIndex = @import("zld.zig").AtomIndex;
17const EhFrameRecord = eh_frame.EhFrameRecord;17const EhFrameRecord = eh_frame.EhFrameRecord;
18const MachO = @import("../MachO.zig");
18const Object = @import("Object.zig");19const Object = @import("Object.zig");
19const SymbolWithLoc = @import("zld.zig").SymbolWithLoc;20const SymbolWithLoc = MachO.SymbolWithLoc;
20const Zld = @import("zld.zig").Zld;21const Zld = @import("zld.zig").Zld;
2122
22const N_DEAD = @import("zld.zig").N_DEAD;23const N_DEAD = @import("zld.zig").N_DEAD;
src/link/MachO/ZldAtom.zig+1-1
...@@ -22,7 +22,7 @@ const Arch = std.Target.Cpu.Arch;...@@ -22,7 +22,7 @@ const Arch = std.Target.Cpu.Arch;
22const AtomIndex = @import("zld.zig").AtomIndex;22const AtomIndex = @import("zld.zig").AtomIndex;
23const Object = @import("Object.zig");23const Object = @import("Object.zig");
24const Relocation = @import("Relocation.zig");24const Relocation = @import("Relocation.zig");
25const SymbolWithLoc = @import("zld.zig").SymbolWithLoc;25const SymbolWithLoc = @import("../MachO.zig").SymbolWithLoc;
26const Zld = @import("zld.zig").Zld;26const Zld = @import("zld.zig").Zld;
2727
28/// Each Atom always gets a symbol with the fully qualified name.28/// Each Atom always gets a symbol with the fully qualified name.
src/link/MachO/dead_strip.zig+2-1
...@@ -11,7 +11,8 @@ const mem = std.mem;...@@ -11,7 +11,8 @@ const mem = std.mem;
11const Allocator = mem.Allocator;11const Allocator = mem.Allocator;
12const AtomIndex = @import("zld.zig").AtomIndex;12const AtomIndex = @import("zld.zig").AtomIndex;
13const Atom = @import("ZldAtom.zig");13const Atom = @import("ZldAtom.zig");
14const SymbolWithLoc = @import("zld.zig").SymbolWithLoc;14const MachO = @import("../MachO.zig");
15const SymbolWithLoc = MachO.SymbolWithLoc;
15const SymbolResolver = @import("zld.zig").SymbolResolver;16const SymbolResolver = @import("zld.zig").SymbolResolver;
16const UnwindInfo = @import("UnwindInfo.zig");17const UnwindInfo = @import("UnwindInfo.zig");
17const Zld = @import("zld.zig").Zld;18const Zld = @import("zld.zig").Zld;
src/link/MachO/eh_frame.zig+2-1
...@@ -9,8 +9,9 @@ const log = std.log.scoped(.eh_frame);...@@ -9,8 +9,9 @@ const log = std.log.scoped(.eh_frame);
9const Allocator = mem.Allocator;9const Allocator = mem.Allocator;
10const AtomIndex = @import("zld.zig").AtomIndex;10const AtomIndex = @import("zld.zig").AtomIndex;
11const Atom = @import("ZldAtom.zig");11const Atom = @import("ZldAtom.zig");
12const MachO = @import("../MachO.zig");
12const Relocation = @import("Relocation.zig");13const Relocation = @import("Relocation.zig");
13const SymbolWithLoc = @import("zld.zig").SymbolWithLoc;14const SymbolWithLoc = MachO.SymbolWithLoc;
14const UnwindInfo = @import("UnwindInfo.zig");15const UnwindInfo = @import("UnwindInfo.zig");
15const Zld = @import("zld.zig").Zld;16const Zld = @import("zld.zig").Zld;
1617
src/link/MachO/thunks.zig+2-1
...@@ -17,8 +17,9 @@ const aarch64 = @import("../../arch/aarch64/bits.zig");...@@ -17,8 +17,9 @@ const aarch64 = @import("../../arch/aarch64/bits.zig");
17const Allocator = mem.Allocator;17const Allocator = mem.Allocator;
18const Atom = @import("ZldAtom.zig");18const Atom = @import("ZldAtom.zig");
19const AtomIndex = @import("zld.zig").AtomIndex;19const AtomIndex = @import("zld.zig").AtomIndex;
20const MachO = @import("../MachO.zig");
20const Relocation = @import("Relocation.zig");21const Relocation = @import("Relocation.zig");
21const SymbolWithLoc = @import("zld.zig").SymbolWithLoc;22const SymbolWithLoc = MachO.SymbolWithLoc;
22const Zld = @import("zld.zig").Zld;23const Zld = @import("zld.zig").Zld;
2324
24pub const ThunkIndex = u32;25pub const ThunkIndex = u32;
src/link/MachO/zld.zig+3-50
...@@ -32,6 +32,7 @@ const Md5 = std.crypto.hash.Md5;...@@ -32,6 +32,7 @@ const Md5 = std.crypto.hash.Md5;
32const LibStub = @import("../tapi.zig").LibStub;32const LibStub = @import("../tapi.zig").LibStub;
33const Object = @import("Object.zig");33const Object = @import("Object.zig");
34const StringTable = @import("../strtab.zig").StringTable;34const StringTable = @import("../strtab.zig").StringTable;
35const SymbolWithLoc = MachO.SymbolWithLoc;
35const Trie = @import("Trie.zig");36const Trie = @import("Trie.zig");
36const UnwindInfo = @import("UnwindInfo.zig");37const UnwindInfo = @import("UnwindInfo.zig");
3738
...@@ -2038,8 +2039,8 @@ pub const Zld = struct {...@@ -2038,8 +2039,8 @@ pub const Zld = struct {
2038 }2039 }
2039 };2040 };
20402041
2041 const start = lsearch(macho.data_in_code_entry, dices, Predicate{ .addr = start_addr });2042 const start = MachO.lsearch(macho.data_in_code_entry, dices, Predicate{ .addr = start_addr });
2042 const end = lsearch(macho.data_in_code_entry, dices[start..], Predicate{ .addr = end_addr }) + start;2043 const end = MachO.lsearch(macho.data_in_code_entry, dices[start..], Predicate{ .addr = end_addr }) + start;
20432044
2044 return dices[start..end];2045 return dices[start..end];
2045 }2046 }
...@@ -3021,23 +3022,6 @@ const IndirectPointer = struct {...@@ -3021,23 +3022,6 @@ const IndirectPointer = struct {
3021 }3022 }
3022};3023};
30233024
3024pub const SymbolWithLoc = extern struct {
3025 // Index into the respective symbol table.
3026 sym_index: u32,
3027
3028 // 0 means it's a synthetic global.
3029 file: u32 = 0,
3030
3031 pub fn getFile(self: SymbolWithLoc) ?u32 {
3032 if (self.file == 0) return null;
3033 return self.file - 1;
3034 }
3035
3036 pub fn eql(self: SymbolWithLoc, other: SymbolWithLoc) bool {
3037 return self.file == other.file and self.sym_index == other.sym_index;
3038 }
3039};
3040
3041pub const SymbolResolver = struct {3025pub const SymbolResolver = struct {
3042 arena: Allocator,3026 arena: Allocator,
3043 table: std.StringHashMap(u32),3027 table: std.StringHashMap(u32),
...@@ -3636,34 +3620,3 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr...@@ -3636,34 +3620,3 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
3636 macho_file.base.lock = man.toOwnedLock();3620 macho_file.base.lock = man.toOwnedLock();
3637 }3621 }
3638}3622}
3639
3640/// Binary search
3641pub fn bsearch(comptime T: type, haystack: []align(1) const T, predicate: anytype) usize {
3642 if (!@hasDecl(@TypeOf(predicate), "predicate"))
3643 @compileError("Predicate is required to define fn predicate(@This(), T) bool");
3644
3645 var min: usize = 0;
3646 var max: usize = haystack.len;
3647 while (min < max) {
3648 const index = (min + max) / 2;
3649 const curr = haystack[index];
3650 if (predicate.predicate(curr)) {
3651 min = index + 1;
3652 } else {
3653 max = index;
3654 }
3655 }
3656 return min;
3657}
3658
3659/// Linear search
3660pub fn lsearch(comptime T: type, haystack: []align(1) const T, predicate: anytype) usize {
3661 if (!@hasDecl(@TypeOf(predicate), "predicate"))
3662 @compileError("Predicate is required to define fn predicate(@This(), T) bool");
3663
3664 var i: usize = 0;
3665 while (i < haystack.len) : (i += 1) {
3666 if (predicate.predicate(haystack[i])) break;
3667 }
3668 return i;
3669}