| author | |
| committer | |
| log | 2e690f5c74cbfd16757cc301ac0d899caa8b2fb3 |
| tree | ad622a039430932b24f69d968d73c3e4fb8c8ed8 |
| parent | 71dfea1f174b0531139e33e8aa4fe86ccd9f23dd |
7 files changed, 121 insertions(+), 73 deletions(-)
src/arch/x86_64/CodeGen.zig+2-1| ... | @@ -13080,12 +13080,13 @@ fn genExternSymbolRef( | ... | @@ -13080,12 +13080,13 @@ fn genExternSymbolRef( |
| 13080 | else => unreachable, | 13080 | else => unreachable, |
| 13081 | } | 13081 | } |
| 13082 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { | 13082 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { |
| 13083 | const global_index = try macho_file.getGlobalSymbol(callee, lib); | ||
| 13083 | _ = try self.addInst(.{ | 13084 | _ = try self.addInst(.{ |
| 13084 | .tag = .call, | 13085 | .tag = .call, |
| 13085 | .ops = .extern_fn_reloc, | 13086 | .ops = .extern_fn_reloc, |
| 13086 | .data = .{ .reloc = .{ | 13087 | .data = .{ .reloc = .{ |
| 13087 | .atom_index = atom_index, | 13088 | .atom_index = atom_index, |
| 13088 | .sym_index = try macho_file.getGlobalSymbol(callee, lib), | 13089 | .sym_index = link.File.MachO.global_symbol_bit | global_index, |
| 13089 | } }, | 13090 | } }, |
| 13090 | }); | 13091 | }); |
| 13091 | } else return self.fail("TODO implement calling extern functions", .{}); | 13092 | } else return self.fail("TODO implement calling extern functions", .{}); |
src/arch/x86_64/Emit.zig+9-2| ... | @@ -52,7 +52,10 @@ pub fn emitMir(emit: *Emit) Error!void { | ... | @@ -52,7 +52,10 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 52 | // Add relocation to the decl. | 52 | // Add relocation to the decl. |
| 53 | const atom_index = | 53 | const atom_index = |
| 54 | macho_file.getAtomIndexForSymbol(.{ .sym_index = symbol.atom_index }).?; | 54 | macho_file.getAtomIndexForSymbol(.{ .sym_index = symbol.atom_index }).?; |
| 55 | const target = macho_file.getGlobalByIndex(symbol.sym_index); | 55 | const target = if (link.File.MachO.global_symbol_bit & symbol.sym_index != 0) |
| 56 | macho_file.getGlobalByIndex(link.File.MachO.global_symbol_mask & symbol.sym_index) | ||
| 57 | else | ||
| 58 | link.File.MachO.SymbolWithLoc{ .sym_index = symbol.sym_index }; | ||
| 56 | try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{ | 59 | try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{ |
| 57 | .type = .branch, | 60 | .type = .branch, |
| 58 | .target = target, | 61 | .target = target, |
| ... | @@ -116,6 +119,10 @@ pub fn emitMir(emit: *Emit) Error!void { | ... | @@ -116,6 +119,10 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 116 | } else if (emit.lower.bin_file.cast(link.File.MachO)) |macho_file| { | 119 | } else if (emit.lower.bin_file.cast(link.File.MachO)) |macho_file| { |
| 117 | const atom_index = | 120 | const atom_index = |
| 118 | macho_file.getAtomIndexForSymbol(.{ .sym_index = symbol.atom_index }).?; | 121 | macho_file.getAtomIndexForSymbol(.{ .sym_index = symbol.atom_index }).?; |
| 122 | const target = if (link.File.MachO.global_symbol_bit & symbol.sym_index != 0) | ||
| 123 | macho_file.getGlobalByIndex(link.File.MachO.global_symbol_mask & symbol.sym_index) | ||
| 124 | else | ||
| 125 | link.File.MachO.SymbolWithLoc{ .sym_index = symbol.sym_index }; | ||
| 119 | try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{ | 126 | try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{ |
| 120 | .type = switch (lowered_relocs[0].target) { | 127 | .type = switch (lowered_relocs[0].target) { |
| 121 | .linker_got => .got, | 128 | .linker_got => .got, |
| ... | @@ -123,7 +130,7 @@ pub fn emitMir(emit: *Emit) Error!void { | ... | @@ -123,7 +130,7 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 123 | .linker_tlv => .tlv, | 130 | .linker_tlv => .tlv, |
| 124 | else => unreachable, | 131 | else => unreachable, |
| 125 | }, | 132 | }, |
| 126 | .target = .{ .sym_index = symbol.sym_index }, | 133 | .target = target, |
| 127 | .offset = @as(u32, @intCast(end_offset - 4)), | 134 | .offset = @as(u32, @intCast(end_offset - 4)), |
| 128 | .addend = 0, | 135 | .addend = 0, |
| 129 | .pcrel = true, | 136 | .pcrel = true, |
src/codegen.zig+9| ... | @@ -721,6 +721,7 @@ fn lowerAnonDeclRef( | ... | @@ -721,6 +721,7 @@ fn lowerAnonDeclRef( |
| 721 | const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8); | 721 | const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8); |
| 722 | const decl_val = anon_decl.val; | 722 | const decl_val = anon_decl.val; |
| 723 | const decl_ty = mod.intern_pool.typeOf(decl_val).toType(); | 723 | const decl_ty = mod.intern_pool.typeOf(decl_val).toType(); |
| 724 | log.debug("lowerAnonDecl: ty = {}", .{decl_ty.fmt(mod)}); | ||
| 724 | const is_fn_body = decl_ty.zigTypeTag(mod) == .Fn; | 725 | const is_fn_body = decl_ty.zigTypeTag(mod) == .Fn; |
| 725 | if (!is_fn_body and !decl_ty.hasRuntimeBits(mod)) { | 726 | if (!is_fn_body and !decl_ty.hasRuntimeBits(mod)) { |
| 726 | try code.appendNTimes(0xaa, ptr_width_bytes); | 727 | try code.appendNTimes(0xaa, ptr_width_bytes); |
| ... | @@ -911,6 +912,14 @@ fn genDeclRef( | ... | @@ -911,6 +912,14 @@ fn genDeclRef( |
| 911 | _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file); | 912 | _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file); |
| 912 | return GenResult.mcv(.{ .load_symbol = sym.esym_index }); | 913 | return GenResult.mcv(.{ .load_symbol = sym.esym_index }); |
| 913 | } else if (bin_file.cast(link.File.MachO)) |macho_file| { | 914 | } else if (bin_file.cast(link.File.MachO)) |macho_file| { |
| 915 | if (is_extern) { | ||
| 916 | // TODO make this part of getGlobalSymbol | ||
| 917 | const name = mod.intern_pool.stringToSlice(decl.name); | ||
| 918 | const sym_name = try std.fmt.allocPrint(bin_file.allocator, "_{s}", .{name}); | ||
| 919 | defer bin_file.allocator.free(sym_name); | ||
| 920 | const global_index = try macho_file.addUndefined(sym_name, .{ .add_got = true }); | ||
| 921 | return GenResult.mcv(.{ .load_got = link.File.MachO.global_symbol_bit | global_index }); | ||
| 922 | } | ||
| 914 | const atom_index = try macho_file.getOrCreateAtomForDecl(decl_index); | 923 | const atom_index = try macho_file.getOrCreateAtomForDecl(decl_index); |
| 915 | const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?; | 924 | const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?; |
| 916 | if (is_threadlocal) { | 925 | if (is_threadlocal) { |
src/link/MachO.zig+74-42| ... | @@ -50,7 +50,7 @@ tlv_ptr_section_index: ?u8 = null, | ... | @@ -50,7 +50,7 @@ tlv_ptr_section_index: ?u8 = null, |
| 50 | locals: std.ArrayListUnmanaged(macho.nlist_64) = .{}, | 50 | locals: std.ArrayListUnmanaged(macho.nlist_64) = .{}, |
| 51 | globals: std.ArrayListUnmanaged(SymbolWithLoc) = .{}, | 51 | globals: std.ArrayListUnmanaged(SymbolWithLoc) = .{}, |
| 52 | resolver: std.StringHashMapUnmanaged(u32) = .{}, | 52 | resolver: std.StringHashMapUnmanaged(u32) = .{}, |
| 53 | unresolved: std.AutoArrayHashMapUnmanaged(u32, ResolveAction.Kind) = .{}, | 53 | unresolved: std.AutoArrayHashMapUnmanaged(u32, void) = .{}, |
| 54 | 54 | ||
| 55 | locals_free_list: std.ArrayListUnmanaged(u32) = .{}, | 55 | locals_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| 56 | globals_free_list: std.ArrayListUnmanaged(u32) = .{}, | 56 | globals_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| ... | @@ -115,6 +115,10 @@ anon_decls: AnonDeclTable = .{}, | ... | @@ -115,6 +115,10 @@ anon_decls: AnonDeclTable = .{}, |
| 115 | /// Note that once we refactor `Atom`'s lifetime and ownership rules, | 115 | /// Note that once we refactor `Atom`'s lifetime and ownership rules, |
| 116 | /// this will be a table indexed by index into the list of Atoms. | 116 | /// this will be a table indexed by index into the list of Atoms. |
| 117 | relocs: RelocationTable = .{}, | 117 | relocs: RelocationTable = .{}, |
| 118 | /// TODO I do not have time to make this right but this will go once | ||
| 119 | /// MachO linker is rewritten more-or-less to feature the same resolution | ||
| 120 | /// mechanism as the ELF linker. | ||
| 121 | actions: ActionTable = .{}, | ||
| 118 | 122 | ||
| 119 | /// A table of rebases indexed by the owning them `Atom`. | 123 | /// A table of rebases indexed by the owning them `Atom`. |
| 120 | /// Note that once we refactor `Atom`'s lifetime and ownership rules, | 124 | /// Note that once we refactor `Atom`'s lifetime and ownership rules, |
| ... | @@ -417,9 +421,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No | ... | @@ -417,9 +421,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No |
| 417 | try self.parseDependentLibs(&dependent_libs); | 421 | try self.parseDependentLibs(&dependent_libs); |
| 418 | } | 422 | } |
| 419 | 423 | ||
| 420 | var actions = std.ArrayList(ResolveAction).init(self.base.allocator); | 424 | try self.resolveSymbols(); |
| 421 | defer actions.deinit(); | ||
| 422 | try self.resolveSymbols(&actions); | ||
| 423 | 425 | ||
| 424 | if (self.getEntryPoint() == null) { | 426 | if (self.getEntryPoint() == null) { |
| 425 | self.error_flags.no_entry_point_found = true; | 427 | self.error_flags.no_entry_point_found = true; |
| ... | @@ -429,11 +431,16 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No | ... | @@ -429,11 +431,16 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No |
| 429 | return error.FlushFailure; | 431 | return error.FlushFailure; |
| 430 | } | 432 | } |
| 431 | 433 | ||
| 432 | for (actions.items) |action| switch (action.kind) { | 434 | { |
| 433 | .none => {}, | 435 | var it = self.actions.iterator(); |
| 434 | .add_got => try self.addGotEntry(action.target), | 436 | while (it.next()) |entry| { |
| 435 | .add_stub => try self.addStubEntry(action.target), | 437 | const global_index = entry.key_ptr.*; |
| 436 | }; | 438 | const global = self.globals.items[global_index]; |
| 439 | const flags = entry.value_ptr.*; | ||
| 440 | if (flags.add_got) try self.addGotEntry(global); | ||
| 441 | if (flags.add_stub) try self.addStubEntry(global); | ||
| 442 | } | ||
| 443 | } | ||
| 437 | 444 | ||
| 438 | try self.createDyldPrivateAtom(); | 445 | try self.createDyldPrivateAtom(); |
| 439 | try self.writeStubHelperPreamble(); | 446 | try self.writeStubHelperPreamble(); |
| ... | @@ -1589,18 +1596,18 @@ pub fn createDsoHandleSymbol(self: *MachO) !void { | ... | @@ -1589,18 +1596,18 @@ pub fn createDsoHandleSymbol(self: *MachO) !void { |
| 1589 | _ = self.unresolved.swapRemove(self.getGlobalIndex("___dso_handle").?); | 1596 | _ = self.unresolved.swapRemove(self.getGlobalIndex("___dso_handle").?); |
| 1590 | } | 1597 | } |
| 1591 | 1598 | ||
| 1592 | pub fn resolveSymbols(self: *MachO, actions: *std.ArrayList(ResolveAction)) !void { | 1599 | pub fn resolveSymbols(self: *MachO) !void { |
| 1593 | // We add the specified entrypoint as the first unresolved symbols so that | 1600 | // We add the specified entrypoint as the first unresolved symbols so that |
| 1594 | // we search for it in libraries should there be no object files specified | 1601 | // we search for it in libraries should there be no object files specified |
| 1595 | // on the linker line. | 1602 | // on the linker line. |
| 1596 | if (self.base.options.output_mode == .Exe) { | 1603 | if (self.base.options.output_mode == .Exe) { |
| 1597 | const entry_name = self.base.options.entry orelse load_commands.default_entry_point; | 1604 | const entry_name = self.base.options.entry orelse load_commands.default_entry_point; |
| 1598 | _ = try self.addUndefined(entry_name, .none); | 1605 | _ = try self.addUndefined(entry_name, .{}); |
| 1599 | } | 1606 | } |
| 1600 | 1607 | ||
| 1601 | // Force resolution of any symbols requested by the user. | 1608 | // Force resolution of any symbols requested by the user. |
| 1602 | for (self.base.options.force_undefined_symbols.keys()) |sym_name| { | 1609 | for (self.base.options.force_undefined_symbols.keys()) |sym_name| { |
| 1603 | _ = try self.addUndefined(sym_name, .none); | 1610 | _ = try self.addUndefined(sym_name, .{}); |
| 1604 | } | 1611 | } |
| 1605 | 1612 | ||
| 1606 | for (self.objects.items, 0..) |_, object_id| { | 1613 | for (self.objects.items, 0..) |_, object_id| { |
| ... | @@ -1612,13 +1619,13 @@ pub fn resolveSymbols(self: *MachO, actions: *std.ArrayList(ResolveAction)) !voi | ... | @@ -1612,13 +1619,13 @@ pub fn resolveSymbols(self: *MachO, actions: *std.ArrayList(ResolveAction)) !voi |
| 1612 | // Finally, force resolution of dyld_stub_binder if there are imports | 1619 | // Finally, force resolution of dyld_stub_binder if there are imports |
| 1613 | // requested. | 1620 | // requested. |
| 1614 | if (self.unresolved.count() > 0 and self.dyld_stub_binder_index == null) { | 1621 | if (self.unresolved.count() > 0 and self.dyld_stub_binder_index == null) { |
| 1615 | self.dyld_stub_binder_index = try self.addUndefined("dyld_stub_binder", .add_got); | 1622 | self.dyld_stub_binder_index = try self.addUndefined("dyld_stub_binder", .{ .add_got = true }); |
| 1616 | } | 1623 | } |
| 1617 | if (!self.base.options.single_threaded and self.mode == .incremental) { | 1624 | if (!self.base.options.single_threaded and self.mode == .incremental) { |
| 1618 | _ = try self.addUndefined("__tlv_bootstrap", .none); | 1625 | _ = try self.addUndefined("__tlv_bootstrap", .{}); |
| 1619 | } | 1626 | } |
| 1620 | 1627 | ||
| 1621 | try self.resolveSymbolsInDylibs(actions); | 1628 | try self.resolveSymbolsInDylibs(); |
| 1622 | 1629 | ||
| 1623 | try self.createMhExecuteHeaderSymbol(); | 1630 | try self.createMhExecuteHeaderSymbol(); |
| 1624 | try self.createDsoHandleSymbol(); | 1631 | try self.createDsoHandleSymbol(); |
| ... | @@ -1634,7 +1641,7 @@ fn resolveGlobalSymbol(self: *MachO, current: SymbolWithLoc) !void { | ... | @@ -1634,7 +1641,7 @@ fn resolveGlobalSymbol(self: *MachO, current: SymbolWithLoc) !void { |
| 1634 | if (!gop.found_existing) { | 1641 | if (!gop.found_existing) { |
| 1635 | gop.value_ptr.* = current; | 1642 | gop.value_ptr.* = current; |
| 1636 | if (sym.undf() and !sym.tentative()) { | 1643 | if (sym.undf() and !sym.tentative()) { |
| 1637 | try self.unresolved.putNoClobber(gpa, self.getGlobalIndex(sym_name).?, .none); | 1644 | try self.unresolved.putNoClobber(gpa, self.getGlobalIndex(sym_name).?, {}); |
| 1638 | } | 1645 | } |
| 1639 | return; | 1646 | return; |
| 1640 | } | 1647 | } |
| ... | @@ -1766,7 +1773,7 @@ fn resolveSymbolsInArchives(self: *MachO) !void { | ... | @@ -1766,7 +1773,7 @@ fn resolveSymbolsInArchives(self: *MachO) !void { |
| 1766 | } | 1773 | } |
| 1767 | } | 1774 | } |
| 1768 | 1775 | ||
| 1769 | fn resolveSymbolsInDylibs(self: *MachO, actions: *std.ArrayList(ResolveAction)) !void { | 1776 | fn resolveSymbolsInDylibs(self: *MachO) !void { |
| 1770 | if (self.dylibs.items.len == 0) return; | 1777 | if (self.dylibs.items.len == 0) return; |
| 1771 | 1778 | ||
| 1772 | const gpa = self.base.allocator; | 1779 | const gpa = self.base.allocator; |
| ... | @@ -1793,11 +1800,7 @@ fn resolveSymbolsInDylibs(self: *MachO, actions: *std.ArrayList(ResolveAction)) | ... | @@ -1793,11 +1800,7 @@ fn resolveSymbolsInDylibs(self: *MachO, actions: *std.ArrayList(ResolveAction)) |
| 1793 | sym.n_desc |= macho.N_WEAK_REF; | 1800 | sym.n_desc |= macho.N_WEAK_REF; |
| 1794 | } | 1801 | } |
| 1795 | 1802 | ||
| 1796 | if (self.unresolved.fetchSwapRemove(global_index)) |entry| blk: { | 1803 | _ = self.unresolved.swapRemove(global_index); |
| 1797 | if (!sym.undf()) break :blk; | ||
| 1798 | if (self.mode == .zld) break :blk; | ||
| 1799 | try actions.append(.{ .kind = entry.value, .target = global }); | ||
| 1800 | } | ||
| 1801 | 1804 | ||
| 1802 | continue :loop; | 1805 | continue :loop; |
| 1803 | } | 1806 | } |
| ... | @@ -1927,6 +1930,7 @@ pub fn deinit(self: *MachO) void { | ... | @@ -1927,6 +1930,7 @@ pub fn deinit(self: *MachO) void { |
| 1927 | relocs.deinit(gpa); | 1930 | relocs.deinit(gpa); |
| 1928 | } | 1931 | } |
| 1929 | self.relocs.deinit(gpa); | 1932 | self.relocs.deinit(gpa); |
| 1933 | self.actions.deinit(gpa); | ||
| 1930 | 1934 | ||
| 1931 | for (self.rebases.values()) |*rebases| { | 1935 | for (self.rebases.values()) |*rebases| { |
| 1932 | rebases.deinit(gpa); | 1936 | rebases.deinit(gpa); |
| ... | @@ -2266,6 +2270,7 @@ fn lowerConst( | ... | @@ -2266,6 +2270,7 @@ fn lowerConst( |
| 2266 | log.debug(" (required alignment 0x{x})", .{required_alignment}); | 2270 | log.debug(" (required alignment 0x{x})", .{required_alignment}); |
| 2267 | 2271 | ||
| 2268 | try self.writeAtom(atom_index, code); | 2272 | try self.writeAtom(atom_index, code); |
| 2273 | self.markRelocsDirtyByTarget(atom.getSymbolWithLoc()); | ||
| 2269 | 2274 | ||
| 2270 | return .{ .ok = atom_index }; | 2275 | return .{ .ok = atom_index }; |
| 2271 | } | 2276 | } |
| ... | @@ -2281,12 +2286,16 @@ pub fn updateDecl(self: *MachO, mod: *Module, decl_index: Module.Decl.Index) !vo | ... | @@ -2281,12 +2286,16 @@ pub fn updateDecl(self: *MachO, mod: *Module, decl_index: Module.Decl.Index) !vo |
| 2281 | const decl = mod.declPtr(decl_index); | 2286 | const decl = mod.declPtr(decl_index); |
| 2282 | 2287 | ||
| 2283 | if (decl.val.getExternFunc(mod)) |_| { | 2288 | if (decl.val.getExternFunc(mod)) |_| { |
| 2284 | return; // TODO Should we do more when front-end analyzed extern decl? | 2289 | return; |
| 2285 | } | 2290 | } |
| 2286 | if (decl.val.getVariable(mod)) |variable| { | 2291 | |
| 2287 | if (variable.is_extern) { | 2292 | if (decl.isExtern(mod)) { |
| 2288 | return; // TODO Should we do more when front-end analyzed extern decl? | 2293 | // TODO make this part of getGlobalSymbol |
| 2289 | } | 2294 | const name = mod.intern_pool.stringToSlice(decl.name); |
| 2295 | const sym_name = try std.fmt.allocPrint(self.base.allocator, "_{s}", .{name}); | ||
| 2296 | defer self.base.allocator.free(sym_name); | ||
| 2297 | _ = try self.addUndefined(sym_name, .{ .add_got = true }); | ||
| 2298 | return; | ||
| 2290 | } | 2299 | } |
| 2291 | 2300 | ||
| 2292 | const is_threadlocal = if (decl.val.getVariable(mod)) |variable| | 2301 | const is_threadlocal = if (decl.val.getVariable(mod)) |variable| |
| ... | @@ -2753,7 +2762,17 @@ pub fn updateExports( | ... | @@ -2753,7 +2762,17 @@ pub fn updateExports( |
| 2753 | } | 2762 | } |
| 2754 | 2763 | ||
| 2755 | const global_sym_index = metadata.getExport(self, exp_name) orelse blk: { | 2764 | const global_sym_index = metadata.getExport(self, exp_name) orelse blk: { |
| 2756 | const global_sym_index = try self.allocateSymbol(); | 2765 | const global_sym_index = if (self.getGlobalIndex(exp_name)) |global_index| ind: { |
| 2766 | const global = self.globals.items[global_index]; | ||
| 2767 | // TODO this is just plain wrong as it all should happen in a single `resolveSymbols` | ||
| 2768 | // pass. This will go away once we abstact away Zig's incremental compilation into | ||
| 2769 | // its own module. | ||
| 2770 | if (global.getFile() == null and self.getSymbol(global).undf()) { | ||
| 2771 | _ = self.unresolved.swapRemove(global_index); | ||
| 2772 | break :ind global.sym_index; | ||
| 2773 | } | ||
| 2774 | break :ind try self.allocateSymbol(); | ||
| 2775 | } else try self.allocateSymbol(); | ||
| 2757 | try metadata.exports.append(gpa, global_sym_index); | 2776 | try metadata.exports.append(gpa, global_sym_index); |
| 2758 | break :blk global_sym_index; | 2777 | break :blk global_sym_index; |
| 2759 | }; | 2778 | }; |
| ... | @@ -3422,7 +3441,7 @@ pub fn getGlobalSymbol(self: *MachO, name: []const u8, lib_name: ?[]const u8) !u | ... | @@ -3422,7 +3441,7 @@ pub fn getGlobalSymbol(self: *MachO, name: []const u8, lib_name: ?[]const u8) !u |
| 3422 | const gpa = self.base.allocator; | 3441 | const gpa = self.base.allocator; |
| 3423 | const sym_name = try std.fmt.allocPrint(gpa, "_{s}", .{name}); | 3442 | const sym_name = try std.fmt.allocPrint(gpa, "_{s}", .{name}); |
| 3424 | defer gpa.free(sym_name); | 3443 | defer gpa.free(sym_name); |
| 3425 | return self.addUndefined(sym_name, .add_stub); | 3444 | return self.addUndefined(sym_name, .{ .add_stub = true }); |
| 3426 | } | 3445 | } |
| 3427 | 3446 | ||
| 3428 | pub fn writeSegmentHeaders(self: *MachO, writer: anytype) !void { | 3447 | pub fn writeSegmentHeaders(self: *MachO, writer: anytype) !void { |
| ... | @@ -4706,13 +4725,16 @@ pub fn ptraceDetach(self: *MachO, pid: std.os.pid_t) !void { | ... | @@ -4706,13 +4725,16 @@ pub fn ptraceDetach(self: *MachO, pid: std.os.pid_t) !void { |
| 4706 | self.hot_state.mach_task = null; | 4725 | self.hot_state.mach_task = null; |
| 4707 | } | 4726 | } |
| 4708 | 4727 | ||
| 4709 | fn addUndefined(self: *MachO, name: []const u8, action: ResolveAction.Kind) !u32 { | 4728 | pub fn addUndefined(self: *MachO, name: []const u8, flags: RelocFlags) !u32 { |
| 4710 | const gpa = self.base.allocator; | 4729 | const gpa = self.base.allocator; |
| 4711 | 4730 | ||
| 4712 | const gop = try self.getOrPutGlobalPtr(name); | 4731 | const gop = try self.getOrPutGlobalPtr(name); |
| 4713 | const global_index = self.getGlobalIndex(name).?; | 4732 | const global_index = self.getGlobalIndex(name).?; |
| 4714 | 4733 | ||
| 4715 | if (gop.found_existing) return global_index; | 4734 | if (gop.found_existing) { |
| 4735 | try self.updateRelocActions(global_index, flags); | ||
| 4736 | return global_index; | ||
| 4737 | } | ||
| 4716 | 4738 | ||
| 4717 | const sym_index = try self.allocateSymbol(); | 4739 | const sym_index = try self.allocateSymbol(); |
| 4718 | const sym_loc = SymbolWithLoc{ .sym_index = sym_index }; | 4740 | const sym_loc = SymbolWithLoc{ .sym_index = sym_index }; |
| ... | @@ -4720,13 +4742,23 @@ fn addUndefined(self: *MachO, name: []const u8, action: ResolveAction.Kind) !u32 | ... | @@ -4720,13 +4742,23 @@ fn addUndefined(self: *MachO, name: []const u8, action: ResolveAction.Kind) !u32 |
| 4720 | 4742 | ||
| 4721 | const sym = self.getSymbolPtr(sym_loc); | 4743 | const sym = self.getSymbolPtr(sym_loc); |
| 4722 | sym.n_strx = try self.strtab.insert(gpa, name); | 4744 | sym.n_strx = try self.strtab.insert(gpa, name); |
| 4723 | sym.n_type = macho.N_UNDF; | 4745 | sym.n_type = macho.N_EXT | macho.N_UNDF; |
| 4724 | 4746 | ||
| 4725 | try self.unresolved.putNoClobber(gpa, global_index, action); | 4747 | try self.unresolved.putNoClobber(gpa, global_index, {}); |
| 4748 | try self.updateRelocActions(global_index, flags); | ||
| 4726 | 4749 | ||
| 4727 | return global_index; | 4750 | return global_index; |
| 4728 | } | 4751 | } |
| 4729 | 4752 | ||
| 4753 | fn updateRelocActions(self: *MachO, global_index: u32, flags: RelocFlags) !void { | ||
| 4754 | const act_gop = try self.actions.getOrPut(self.base.allocator, global_index); | ||
| 4755 | if (!act_gop.found_existing) { | ||
| 4756 | act_gop.value_ptr.* = .{}; | ||
| 4757 | } | ||
| 4758 | act_gop.value_ptr.add_got = act_gop.value_ptr.add_got or flags.add_got; | ||
| 4759 | act_gop.value_ptr.add_stub = act_gop.value_ptr.add_stub or flags.add_stub; | ||
| 4760 | } | ||
| 4761 | |||
| 4730 | pub fn makeStaticString(bytes: []const u8) [16]u8 { | 4762 | pub fn makeStaticString(bytes: []const u8) [16]u8 { |
| 4731 | var buf = [_]u8{0} ** 16; | 4763 | var buf = [_]u8{0} ** 16; |
| 4732 | @memcpy(buf[0..bytes.len], bytes); | 4764 | @memcpy(buf[0..bytes.len], bytes); |
| ... | @@ -4838,6 +4870,11 @@ const GetOrPutGlobalPtrResult = struct { | ... | @@ -4838,6 +4870,11 @@ const GetOrPutGlobalPtrResult = struct { |
| 4838 | value_ptr: *SymbolWithLoc, | 4870 | value_ptr: *SymbolWithLoc, |
| 4839 | }; | 4871 | }; |
| 4840 | 4872 | ||
| 4873 | /// Used only for disambiguating local from global at relocation level. | ||
| 4874 | /// TODO this must go away. | ||
| 4875 | pub const global_symbol_bit: u32 = 0x80000000; | ||
| 4876 | pub const global_symbol_mask: u32 = 0x7fffffff; | ||
| 4877 | |||
| 4841 | /// Return pointer to the global entry for `name` if one exists. | 4878 | /// Return pointer to the global entry for `name` if one exists. |
| 4842 | /// Puts a new global entry for `name` if one doesn't exist, and | 4879 | /// Puts a new global entry for `name` if one doesn't exist, and |
| 4843 | /// returns a pointer to it. | 4880 | /// returns a pointer to it. |
| ... | @@ -5510,16 +5547,11 @@ const BindingTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnma | ... | @@ -5510,16 +5547,11 @@ const BindingTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnma |
| 5510 | const UnnamedConstTable = std.AutoArrayHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(Atom.Index)); | 5547 | const UnnamedConstTable = std.AutoArrayHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(Atom.Index)); |
| 5511 | const RebaseTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(u32)); | 5548 | const RebaseTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(u32)); |
| 5512 | const RelocationTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(Relocation)); | 5549 | const RelocationTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(Relocation)); |
| 5550 | const ActionTable = std.AutoHashMapUnmanaged(u32, RelocFlags); | ||
| 5513 | 5551 | ||
| 5514 | pub const ResolveAction = struct { | 5552 | pub const RelocFlags = packed struct { |
| 5515 | kind: Kind, | 5553 | add_got: bool = false, |
| 5516 | target: SymbolWithLoc, | 5554 | add_stub: bool = false, |
| 5517 | |||
| 5518 | const Kind = enum { | ||
| 5519 | none, | ||
| 5520 | add_got, | ||
| 5521 | add_stub, | ||
| 5522 | }; | ||
| 5523 | }; | 5555 | }; |
| 5524 | 5556 | ||
| 5525 | pub const SymbolWithLoc = extern struct { | 5557 | pub const SymbolWithLoc = extern struct { |
src/link/MachO/Atom.zig+24-23| ... | @@ -300,7 +300,7 @@ pub fn resolveRelocations( | ... | @@ -300,7 +300,7 @@ pub fn resolveRelocations( |
| 300 | relocs: []*const Relocation, | 300 | relocs: []*const Relocation, |
| 301 | code: []u8, | 301 | code: []u8, |
| 302 | ) void { | 302 | ) void { |
| 303 | log.debug("relocating '{s}'", .{macho_file.getAtom(atom_index).getName(macho_file)}); | 303 | relocs_log.debug("relocating '{s}'", .{macho_file.getAtom(atom_index).getName(macho_file)}); |
| 304 | for (relocs) |reloc| { | 304 | for (relocs) |reloc| { |
| 305 | reloc.resolve(macho_file, atom_index, code); | 305 | reloc.resolve(macho_file, atom_index, code); |
| 306 | } | 306 | } |
| ... | @@ -603,7 +603,7 @@ pub fn resolveRelocs( | ... | @@ -603,7 +603,7 @@ pub fn resolveRelocs( |
| 603 | const atom = macho_file.getAtom(atom_index); | 603 | const atom = macho_file.getAtom(atom_index); |
| 604 | assert(atom.getFile() != null); // synthetic atoms do not have relocs | 604 | assert(atom.getFile() != null); // synthetic atoms do not have relocs |
| 605 | 605 | ||
| 606 | log.debug("resolving relocations in ATOM(%{d}, '{s}')", .{ | 606 | relocs_log.debug("resolving relocations in ATOM(%{d}, '{s}')", .{ |
| 607 | atom.sym_index, | 607 | atom.sym_index, |
| 608 | macho_file.getSymbolName(atom.getSymbolWithLoc()), | 608 | macho_file.getSymbolName(atom.getSymbolWithLoc()), |
| 609 | }); | 609 | }); |
| ... | @@ -683,7 +683,7 @@ fn resolveRelocsArm64( | ... | @@ -683,7 +683,7 @@ fn resolveRelocsArm64( |
| 683 | .ARM64_RELOC_ADDEND => { | 683 | .ARM64_RELOC_ADDEND => { |
| 684 | assert(addend == null); | 684 | assert(addend == null); |
| 685 | 685 | ||
| 686 | log.debug(" RELA({s}) @ {x} => {x}", .{ @tagName(rel_type), rel.r_address, rel.r_symbolnum }); | 686 | relocs_log.debug(" RELA({s}) @ {x} => {x}", .{ @tagName(rel_type), rel.r_address, rel.r_symbolnum }); |
| 687 | 687 | ||
| 688 | addend = rel.r_symbolnum; | 688 | addend = rel.r_symbolnum; |
| 689 | continue; | 689 | continue; |
| ... | @@ -691,7 +691,7 @@ fn resolveRelocsArm64( | ... | @@ -691,7 +691,7 @@ fn resolveRelocsArm64( |
| 691 | .ARM64_RELOC_SUBTRACTOR => { | 691 | .ARM64_RELOC_SUBTRACTOR => { |
| 692 | assert(subtractor == null); | 692 | assert(subtractor == null); |
| 693 | 693 | ||
| 694 | log.debug(" RELA({s}) @ {x} => %{d} in object({?d})", .{ | 694 | relocs_log.debug(" RELA({s}) @ {x} => %{d} in object({?d})", .{ |
| 695 | @tagName(rel_type), | 695 | @tagName(rel_type), |
| 696 | rel.r_address, | 696 | rel.r_address, |
| 697 | rel.r_symbolnum, | 697 | rel.r_symbolnum, |
| ... | @@ -719,7 +719,7 @@ fn resolveRelocsArm64( | ... | @@ -719,7 +719,7 @@ fn resolveRelocsArm64( |
| 719 | }); | 719 | }); |
| 720 | const rel_offset = @as(u32, @intCast(rel.r_address - context.base_offset)); | 720 | const rel_offset = @as(u32, @intCast(rel.r_address - context.base_offset)); |
| 721 | 721 | ||
| 722 | log.debug(" RELA({s}) @ {x} => %{d} ('{s}') in object({?})", .{ | 722 | relocs_log.debug(" RELA({s}) @ {x} => %{d} ('{s}') in object({?})", .{ |
| 723 | @tagName(rel_type), | 723 | @tagName(rel_type), |
| 724 | rel.r_address, | 724 | rel.r_address, |
| 725 | target.sym_index, | 725 | target.sym_index, |
| ... | @@ -745,11 +745,11 @@ fn resolveRelocsArm64( | ... | @@ -745,11 +745,11 @@ fn resolveRelocsArm64( |
| 745 | break :blk getRelocTargetAddress(macho_file, target, is_tlv); | 745 | break :blk getRelocTargetAddress(macho_file, target, is_tlv); |
| 746 | }; | 746 | }; |
| 747 | 747 | ||
| 748 | log.debug(" | source_addr = 0x{x}", .{source_addr}); | 748 | relocs_log.debug(" | source_addr = 0x{x}", .{source_addr}); |
| 749 | 749 | ||
| 750 | switch (rel_type) { | 750 | switch (rel_type) { |
| 751 | .ARM64_RELOC_BRANCH26 => { | 751 | .ARM64_RELOC_BRANCH26 => { |
| 752 | log.debug(" source {s} (object({?})), target {s}", .{ | 752 | relocs_log.debug(" source {s} (object({?})), target {s}", .{ |
| 753 | macho_file.getSymbolName(atom.getSymbolWithLoc()), | 753 | macho_file.getSymbolName(atom.getSymbolWithLoc()), |
| 754 | atom.getFile(), | 754 | atom.getFile(), |
| 755 | macho_file.getSymbolName(target), | 755 | macho_file.getSymbolName(target), |
| ... | @@ -759,7 +759,7 @@ fn resolveRelocsArm64( | ... | @@ -759,7 +759,7 @@ fn resolveRelocsArm64( |
| 759 | source_addr, | 759 | source_addr, |
| 760 | target_addr, | 760 | target_addr, |
| 761 | )) |disp| blk: { | 761 | )) |disp| blk: { |
| 762 | log.debug(" | target_addr = 0x{x}", .{target_addr}); | 762 | relocs_log.debug(" | target_addr = 0x{x}", .{target_addr}); |
| 763 | break :blk disp; | 763 | break :blk disp; |
| 764 | } else |_| blk: { | 764 | } else |_| blk: { |
| 765 | const thunk_index = macho_file.thunk_table.get(atom_index).?; | 765 | const thunk_index = macho_file.thunk_table.get(atom_index).?; |
| ... | @@ -769,7 +769,7 @@ fn resolveRelocsArm64( | ... | @@ -769,7 +769,7 @@ fn resolveRelocsArm64( |
| 769 | else | 769 | else |
| 770 | thunk.getTrampoline(macho_file, .atom, target).?; | 770 | thunk.getTrampoline(macho_file, .atom, target).?; |
| 771 | const thunk_addr = macho_file.getSymbol(thunk_sym_loc).n_value; | 771 | const thunk_addr = macho_file.getSymbol(thunk_sym_loc).n_value; |
| 772 | log.debug(" | target_addr = 0x{x} (thunk)", .{thunk_addr}); | 772 | relocs_log.debug(" | target_addr = 0x{x} (thunk)", .{thunk_addr}); |
| 773 | break :blk try Relocation.calcPcRelativeDisplacementArm64(source_addr, thunk_addr); | 773 | break :blk try Relocation.calcPcRelativeDisplacementArm64(source_addr, thunk_addr); |
| 774 | }; | 774 | }; |
| 775 | 775 | ||
| ... | @@ -790,7 +790,7 @@ fn resolveRelocsArm64( | ... | @@ -790,7 +790,7 @@ fn resolveRelocsArm64( |
| 790 | => { | 790 | => { |
| 791 | const adjusted_target_addr = @as(u64, @intCast(@as(i64, @intCast(target_addr)) + (addend orelse 0))); | 791 | const adjusted_target_addr = @as(u64, @intCast(@as(i64, @intCast(target_addr)) + (addend orelse 0))); |
| 792 | 792 | ||
| 793 | log.debug(" | target_addr = 0x{x}", .{adjusted_target_addr}); | 793 | relocs_log.debug(" | target_addr = 0x{x}", .{adjusted_target_addr}); |
| 794 | 794 | ||
| 795 | const pages = @as(u21, @bitCast(Relocation.calcNumberOfPages(source_addr, adjusted_target_addr))); | 795 | const pages = @as(u21, @bitCast(Relocation.calcNumberOfPages(source_addr, adjusted_target_addr))); |
| 796 | const code = atom_code[rel_offset..][0..4]; | 796 | const code = atom_code[rel_offset..][0..4]; |
| ... | @@ -809,7 +809,7 @@ fn resolveRelocsArm64( | ... | @@ -809,7 +809,7 @@ fn resolveRelocsArm64( |
| 809 | .ARM64_RELOC_PAGEOFF12 => { | 809 | .ARM64_RELOC_PAGEOFF12 => { |
| 810 | const adjusted_target_addr = @as(u64, @intCast(@as(i64, @intCast(target_addr)) + (addend orelse 0))); | 810 | const adjusted_target_addr = @as(u64, @intCast(@as(i64, @intCast(target_addr)) + (addend orelse 0))); |
| 811 | 811 | ||
| 812 | log.debug(" | target_addr = 0x{x}", .{adjusted_target_addr}); | 812 | relocs_log.debug(" | target_addr = 0x{x}", .{adjusted_target_addr}); |
| 813 | 813 | ||
| 814 | const code = atom_code[rel_offset..][0..4]; | 814 | const code = atom_code[rel_offset..][0..4]; |
| 815 | if (Relocation.isArithmeticOp(code)) { | 815 | if (Relocation.isArithmeticOp(code)) { |
| ... | @@ -848,7 +848,7 @@ fn resolveRelocsArm64( | ... | @@ -848,7 +848,7 @@ fn resolveRelocsArm64( |
| 848 | const code = atom_code[rel_offset..][0..4]; | 848 | const code = atom_code[rel_offset..][0..4]; |
| 849 | const adjusted_target_addr = @as(u64, @intCast(@as(i64, @intCast(target_addr)) + (addend orelse 0))); | 849 | const adjusted_target_addr = @as(u64, @intCast(@as(i64, @intCast(target_addr)) + (addend orelse 0))); |
| 850 | 850 | ||
| 851 | log.debug(" | target_addr = 0x{x}", .{adjusted_target_addr}); | 851 | relocs_log.debug(" | target_addr = 0x{x}", .{adjusted_target_addr}); |
| 852 | 852 | ||
| 853 | const off = try Relocation.calcPageOffset(adjusted_target_addr, .load_store_64); | 853 | const off = try Relocation.calcPageOffset(adjusted_target_addr, .load_store_64); |
| 854 | var inst: aarch64.Instruction = .{ | 854 | var inst: aarch64.Instruction = .{ |
| ... | @@ -866,7 +866,7 @@ fn resolveRelocsArm64( | ... | @@ -866,7 +866,7 @@ fn resolveRelocsArm64( |
| 866 | const code = atom_code[rel_offset..][0..4]; | 866 | const code = atom_code[rel_offset..][0..4]; |
| 867 | const adjusted_target_addr = @as(u64, @intCast(@as(i64, @intCast(target_addr)) + (addend orelse 0))); | 867 | const adjusted_target_addr = @as(u64, @intCast(@as(i64, @intCast(target_addr)) + (addend orelse 0))); |
| 868 | 868 | ||
| 869 | log.debug(" | target_addr = 0x{x}", .{adjusted_target_addr}); | 869 | relocs_log.debug(" | target_addr = 0x{x}", .{adjusted_target_addr}); |
| 870 | 870 | ||
| 871 | const RegInfo = struct { | 871 | const RegInfo = struct { |
| 872 | rd: u5, | 872 | rd: u5, |
| ... | @@ -923,7 +923,7 @@ fn resolveRelocsArm64( | ... | @@ -923,7 +923,7 @@ fn resolveRelocsArm64( |
| 923 | }, | 923 | }, |
| 924 | 924 | ||
| 925 | .ARM64_RELOC_POINTER_TO_GOT => { | 925 | .ARM64_RELOC_POINTER_TO_GOT => { |
| 926 | log.debug(" | target_addr = 0x{x}", .{target_addr}); | 926 | relocs_log.debug(" | target_addr = 0x{x}", .{target_addr}); |
| 927 | const result = math.cast(i32, @as(i64, @intCast(target_addr)) - @as(i64, @intCast(source_addr))) orelse | 927 | const result = math.cast(i32, @as(i64, @intCast(target_addr)) - @as(i64, @intCast(source_addr))) orelse |
| 928 | return error.Overflow; | 928 | return error.Overflow; |
| 929 | mem.writeIntLittle(u32, atom_code[rel_offset..][0..4], @as(u32, @bitCast(result))); | 929 | mem.writeIntLittle(u32, atom_code[rel_offset..][0..4], @as(u32, @bitCast(result))); |
| ... | @@ -951,7 +951,7 @@ fn resolveRelocsArm64( | ... | @@ -951,7 +951,7 @@ fn resolveRelocsArm64( |
| 951 | break :blk @as(i64, @intCast(target_addr)) + ptr_addend; | 951 | break :blk @as(i64, @intCast(target_addr)) + ptr_addend; |
| 952 | } | 952 | } |
| 953 | }; | 953 | }; |
| 954 | log.debug(" | target_addr = 0x{x}", .{result}); | 954 | relocs_log.debug(" | target_addr = 0x{x}", .{result}); |
| 955 | 955 | ||
| 956 | if (rel.r_length == 3) { | 956 | if (rel.r_length == 3) { |
| 957 | mem.writeIntLittle(u64, atom_code[rel_offset..][0..8], @as(u64, @bitCast(result))); | 957 | mem.writeIntLittle(u64, atom_code[rel_offset..][0..8], @as(u64, @bitCast(result))); |
| ... | @@ -987,7 +987,7 @@ fn resolveRelocsX86( | ... | @@ -987,7 +987,7 @@ fn resolveRelocsX86( |
| 987 | .X86_64_RELOC_SUBTRACTOR => { | 987 | .X86_64_RELOC_SUBTRACTOR => { |
| 988 | assert(subtractor == null); | 988 | assert(subtractor == null); |
| 989 | 989 | ||
| 990 | log.debug(" RELA({s}) @ {x} => %{d} in object({?d})", .{ | 990 | relocs_log.debug(" RELA({s}) @ {x} => %{d} in object({?d})", .{ |
| 991 | @tagName(rel_type), | 991 | @tagName(rel_type), |
| 992 | rel.r_address, | 992 | rel.r_address, |
| 993 | rel.r_symbolnum, | 993 | rel.r_symbolnum, |
| ... | @@ -1015,7 +1015,7 @@ fn resolveRelocsX86( | ... | @@ -1015,7 +1015,7 @@ fn resolveRelocsX86( |
| 1015 | }); | 1015 | }); |
| 1016 | const rel_offset = @as(u32, @intCast(rel.r_address - context.base_offset)); | 1016 | const rel_offset = @as(u32, @intCast(rel.r_address - context.base_offset)); |
| 1017 | 1017 | ||
| 1018 | log.debug(" RELA({s}) @ {x} => %{d} ('{s}') in object({?})", .{ | 1018 | relocs_log.debug(" RELA({s}) @ {x} => %{d} ('{s}') in object({?})", .{ |
| 1019 | @tagName(rel_type), | 1019 | @tagName(rel_type), |
| 1020 | rel.r_address, | 1020 | rel.r_address, |
| 1021 | target.sym_index, | 1021 | target.sym_index, |
| ... | @@ -1041,13 +1041,13 @@ fn resolveRelocsX86( | ... | @@ -1041,13 +1041,13 @@ fn resolveRelocsX86( |
| 1041 | break :blk getRelocTargetAddress(macho_file, target, is_tlv); | 1041 | break :blk getRelocTargetAddress(macho_file, target, is_tlv); |
| 1042 | }; | 1042 | }; |
| 1043 | 1043 | ||
| 1044 | log.debug(" | source_addr = 0x{x}", .{source_addr}); | 1044 | relocs_log.debug(" | source_addr = 0x{x}", .{source_addr}); |
| 1045 | 1045 | ||
| 1046 | switch (rel_type) { | 1046 | switch (rel_type) { |
| 1047 | .X86_64_RELOC_BRANCH => { | 1047 | .X86_64_RELOC_BRANCH => { |
| 1048 | const addend = mem.readIntLittle(i32, atom_code[rel_offset..][0..4]); | 1048 | const addend = mem.readIntLittle(i32, atom_code[rel_offset..][0..4]); |
| 1049 | const adjusted_target_addr = @as(u64, @intCast(@as(i64, @intCast(target_addr)) + addend)); | 1049 | const adjusted_target_addr = @as(u64, @intCast(@as(i64, @intCast(target_addr)) + addend)); |
| 1050 | log.debug(" | target_addr = 0x{x}", .{adjusted_target_addr}); | 1050 | relocs_log.debug(" | target_addr = 0x{x}", .{adjusted_target_addr}); |
| 1051 | const disp = try Relocation.calcPcRelativeDisplacementX86(source_addr, adjusted_target_addr, 0); | 1051 | const disp = try Relocation.calcPcRelativeDisplacementX86(source_addr, adjusted_target_addr, 0); |
| 1052 | mem.writeIntLittle(i32, atom_code[rel_offset..][0..4], disp); | 1052 | mem.writeIntLittle(i32, atom_code[rel_offset..][0..4], disp); |
| 1053 | }, | 1053 | }, |
| ... | @@ -1057,7 +1057,7 @@ fn resolveRelocsX86( | ... | @@ -1057,7 +1057,7 @@ fn resolveRelocsX86( |
| 1057 | => { | 1057 | => { |
| 1058 | const addend = mem.readIntLittle(i32, atom_code[rel_offset..][0..4]); | 1058 | const addend = mem.readIntLittle(i32, atom_code[rel_offset..][0..4]); |
| 1059 | const adjusted_target_addr = @as(u64, @intCast(@as(i64, @intCast(target_addr)) + addend)); | 1059 | const adjusted_target_addr = @as(u64, @intCast(@as(i64, @intCast(target_addr)) + addend)); |
| 1060 | log.debug(" | target_addr = 0x{x}", .{adjusted_target_addr}); | 1060 | relocs_log.debug(" | target_addr = 0x{x}", .{adjusted_target_addr}); |
| 1061 | const disp = try Relocation.calcPcRelativeDisplacementX86(source_addr, adjusted_target_addr, 0); | 1061 | const disp = try Relocation.calcPcRelativeDisplacementX86(source_addr, adjusted_target_addr, 0); |
| 1062 | mem.writeIntLittle(i32, atom_code[rel_offset..][0..4], disp); | 1062 | mem.writeIntLittle(i32, atom_code[rel_offset..][0..4], disp); |
| 1063 | }, | 1063 | }, |
| ... | @@ -1065,7 +1065,7 @@ fn resolveRelocsX86( | ... | @@ -1065,7 +1065,7 @@ fn resolveRelocsX86( |
| 1065 | .X86_64_RELOC_TLV => { | 1065 | .X86_64_RELOC_TLV => { |
| 1066 | const addend = mem.readIntLittle(i32, atom_code[rel_offset..][0..4]); | 1066 | const addend = mem.readIntLittle(i32, atom_code[rel_offset..][0..4]); |
| 1067 | const adjusted_target_addr = @as(u64, @intCast(@as(i64, @intCast(target_addr)) + addend)); | 1067 | const adjusted_target_addr = @as(u64, @intCast(@as(i64, @intCast(target_addr)) + addend)); |
| 1068 | log.debug(" | target_addr = 0x{x}", .{adjusted_target_addr}); | 1068 | relocs_log.debug(" | target_addr = 0x{x}", .{adjusted_target_addr}); |
| 1069 | const disp = try Relocation.calcPcRelativeDisplacementX86(source_addr, adjusted_target_addr, 0); | 1069 | const disp = try Relocation.calcPcRelativeDisplacementX86(source_addr, adjusted_target_addr, 0); |
| 1070 | 1070 | ||
| 1071 | if (macho_file.tlv_ptr_table.lookup.get(target) == null) { | 1071 | if (macho_file.tlv_ptr_table.lookup.get(target) == null) { |
| ... | @@ -1101,7 +1101,7 @@ fn resolveRelocsX86( | ... | @@ -1101,7 +1101,7 @@ fn resolveRelocsX86( |
| 1101 | 1101 | ||
| 1102 | const adjusted_target_addr = @as(u64, @intCast(@as(i64, @intCast(target_addr)) + addend)); | 1102 | const adjusted_target_addr = @as(u64, @intCast(@as(i64, @intCast(target_addr)) + addend)); |
| 1103 | 1103 | ||
| 1104 | log.debug(" | target_addr = 0x{x}", .{adjusted_target_addr}); | 1104 | relocs_log.debug(" | target_addr = 0x{x}", .{adjusted_target_addr}); |
| 1105 | 1105 | ||
| 1106 | const disp = try Relocation.calcPcRelativeDisplacementX86(source_addr, adjusted_target_addr, correction); | 1106 | const disp = try Relocation.calcPcRelativeDisplacementX86(source_addr, adjusted_target_addr, correction); |
| 1107 | mem.writeIntLittle(i32, atom_code[rel_offset..][0..4], disp); | 1107 | mem.writeIntLittle(i32, atom_code[rel_offset..][0..4], disp); |
| ... | @@ -1129,7 +1129,7 @@ fn resolveRelocsX86( | ... | @@ -1129,7 +1129,7 @@ fn resolveRelocsX86( |
| 1129 | break :blk @as(i64, @intCast(target_addr)) + addend; | 1129 | break :blk @as(i64, @intCast(target_addr)) + addend; |
| 1130 | } | 1130 | } |
| 1131 | }; | 1131 | }; |
| 1132 | log.debug(" | target_addr = 0x{x}", .{result}); | 1132 | relocs_log.debug(" | target_addr = 0x{x}", .{result}); |
| 1133 | 1133 | ||
| 1134 | if (rel.r_length == 3) { | 1134 | if (rel.r_length == 3) { |
| 1135 | mem.writeIntLittle(u64, atom_code[rel_offset..][0..8], @as(u64, @bitCast(result))); | 1135 | mem.writeIntLittle(u64, atom_code[rel_offset..][0..8], @as(u64, @bitCast(result))); |
| ... | @@ -1247,6 +1247,7 @@ const build_options = @import("build_options"); | ... | @@ -1247,6 +1247,7 @@ const build_options = @import("build_options"); |
| 1247 | const aarch64 = @import("../../arch/aarch64/bits.zig"); | 1247 | const aarch64 = @import("../../arch/aarch64/bits.zig"); |
| 1248 | const assert = std.debug.assert; | 1248 | const assert = std.debug.assert; |
| 1249 | const log = std.log.scoped(.link); | 1249 | const log = std.log.scoped(.link); |
| 1250 | const relocs_log = std.log.scoped(.link_relocs); | ||
| 1250 | const macho = std.macho; | 1251 | const macho = std.macho; |
| 1251 | const math = std.math; | 1252 | const math = std.math; |
| 1252 | const mem = std.mem; | 1253 | const mem = std.mem; |
src/link/MachO/Relocation.zig+2-2| ... | @@ -99,7 +99,7 @@ pub fn resolve(self: Relocation, macho_file: *MachO, atom_index: Atom.Index, cod | ... | @@ -99,7 +99,7 @@ pub fn resolve(self: Relocation, macho_file: *MachO, atom_index: Atom.Index, cod |
| 99 | else => @as(i64, @intCast(target_base_addr)) + self.addend, | 99 | else => @as(i64, @intCast(target_base_addr)) + self.addend, |
| 100 | }; | 100 | }; |
| 101 | 101 | ||
| 102 | log.debug(" ({x}: [() => 0x{x} ({s})) ({s})", .{ | 102 | relocs_log.debug(" ({x}: [() => 0x{x} ({s})) ({s})", .{ |
| 103 | source_addr, | 103 | source_addr, |
| 104 | target_addr, | 104 | target_addr, |
| 105 | macho_file.getSymbolName(self.target), | 105 | macho_file.getSymbolName(self.target), |
| ... | @@ -256,7 +256,7 @@ const Relocation = @This(); | ... | @@ -256,7 +256,7 @@ const Relocation = @This(); |
| 256 | const std = @import("std"); | 256 | const std = @import("std"); |
| 257 | const aarch64 = @import("../../arch/aarch64/bits.zig"); | 257 | const aarch64 = @import("../../arch/aarch64/bits.zig"); |
| 258 | const assert = std.debug.assert; | 258 | const assert = std.debug.assert; |
| 259 | const log = std.log.scoped(.link); | 259 | const relocs_log = std.log.scoped(.link_relocs); |
| 260 | const macho = std.macho; | 260 | const macho = std.macho; |
| 261 | const math = std.math; | 261 | const math = std.math; |
| 262 | const mem = std.mem; | 262 | const mem = std.mem; |
src/link/MachO/zld.zig+1-3| ... | @@ -390,9 +390,7 @@ pub fn linkWithZld( | ... | @@ -390,9 +390,7 @@ pub fn linkWithZld( |
| 390 | 390 | ||
| 391 | try macho_file.parseDependentLibs(&dependent_libs); | 391 | try macho_file.parseDependentLibs(&dependent_libs); |
| 392 | 392 | ||
| 393 | var actions = std.ArrayList(MachO.ResolveAction).init(gpa); | 393 | try macho_file.resolveSymbols(); |
| 394 | defer actions.deinit(); | ||
| 395 | try macho_file.resolveSymbols(&actions); | ||
| 396 | if (macho_file.unresolved.count() > 0) { | 394 | if (macho_file.unresolved.count() > 0) { |
| 397 | try macho_file.reportUndefined(); | 395 | try macho_file.reportUndefined(); |
| 398 | return error.FlushFailure; | 396 | return error.FlushFailure; |