| 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 | 13080 | else => unreachable, |
| 13081 | 13081 | } |
| 13082 | 13082 | } else if (self.bin_file.cast(link.File.MachO)) |macho_file| { |
| 13083 | const global_index = try macho_file.getGlobalSymbol(callee, lib); | |
| 13083 | 13084 | _ = try self.addInst(.{ |
| 13084 | 13085 | .tag = .call, |
| 13085 | 13086 | .ops = .extern_fn_reloc, |
| 13086 | 13087 | .data = .{ .reloc = .{ |
| 13087 | 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 | 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 | 52 | // Add relocation to the decl. |
| 53 | 53 | const atom_index = |
| 54 | 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 | 59 | try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{ |
| 57 | 60 | .type = .branch, |
| 58 | 61 | .target = target, |
| ... | ... | @@ -116,6 +119,10 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 116 | 119 | } else if (emit.lower.bin_file.cast(link.File.MachO)) |macho_file| { |
| 117 | 120 | const atom_index = |
| 118 | 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 | 126 | try link.File.MachO.Atom.addRelocation(macho_file, atom_index, .{ |
| 120 | 127 | .type = switch (lowered_relocs[0].target) { |
| 121 | 128 | .linker_got => .got, |
| ... | ... | @@ -123,7 +130,7 @@ pub fn emitMir(emit: *Emit) Error!void { |
| 123 | 130 | .linker_tlv => .tlv, |
| 124 | 131 | else => unreachable, |
| 125 | 132 | }, |
| 126 | .target = .{ .sym_index = symbol.sym_index }, | |
| 133 | .target = target, | |
| 127 | 134 | .offset = @as(u32, @intCast(end_offset - 4)), |
| 128 | 135 | .addend = 0, |
| 129 | 136 | .pcrel = true, |
src/codegen.zig+9| ... | ... | @@ -721,6 +721,7 @@ fn lowerAnonDeclRef( |
| 721 | 721 | const ptr_width_bytes = @divExact(target.ptrBitWidth(), 8); |
| 722 | 722 | const decl_val = anon_decl.val; |
| 723 | 723 | const decl_ty = mod.intern_pool.typeOf(decl_val).toType(); |
| 724 | log.debug("lowerAnonDecl: ty = {}", .{decl_ty.fmt(mod)}); | |
| 724 | 725 | const is_fn_body = decl_ty.zigTypeTag(mod) == .Fn; |
| 725 | 726 | if (!is_fn_body and !decl_ty.hasRuntimeBits(mod)) { |
| 726 | 727 | try code.appendNTimes(0xaa, ptr_width_bytes); |
| ... | ... | @@ -911,6 +912,14 @@ fn genDeclRef( |
| 911 | 912 | _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file); |
| 912 | 913 | return GenResult.mcv(.{ .load_symbol = sym.esym_index }); |
| 913 | 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 | 923 | const atom_index = try macho_file.getOrCreateAtomForDecl(decl_index); |
| 915 | 924 | const sym_index = macho_file.getAtom(atom_index).getSymbolIndex().?; |
| 916 | 925 | if (is_threadlocal) { |
src/link/MachO.zig+74-42| ... | ... | @@ -50,7 +50,7 @@ tlv_ptr_section_index: ?u8 = null, |
| 50 | 50 | locals: std.ArrayListUnmanaged(macho.nlist_64) = .{}, |
| 51 | 51 | globals: std.ArrayListUnmanaged(SymbolWithLoc) = .{}, |
| 52 | 52 | resolver: std.StringHashMapUnmanaged(u32) = .{}, |
| 53 | unresolved: std.AutoArrayHashMapUnmanaged(u32, ResolveAction.Kind) = .{}, | |
| 53 | unresolved: std.AutoArrayHashMapUnmanaged(u32, void) = .{}, | |
| 54 | 54 | |
| 55 | 55 | locals_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| 56 | 56 | globals_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| ... | ... | @@ -115,6 +115,10 @@ anon_decls: AnonDeclTable = .{}, |
| 115 | 115 | /// Note that once we refactor `Atom`'s lifetime and ownership rules, |
| 116 | 116 | /// this will be a table indexed by index into the list of Atoms. |
| 117 | 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 | 123 | /// A table of rebases indexed by the owning them `Atom`. |
| 120 | 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 | 421 | try self.parseDependentLibs(&dependent_libs); |
| 418 | 422 | } |
| 419 | 423 | |
| 420 | var actions = std.ArrayList(ResolveAction).init(self.base.allocator); | |
| 421 | defer actions.deinit(); | |
| 422 | try self.resolveSymbols(&actions); | |
| 424 | try self.resolveSymbols(); | |
| 423 | 425 | |
| 424 | 426 | if (self.getEntryPoint() == null) { |
| 425 | 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 | 431 | return error.FlushFailure; |
| 430 | 432 | } |
| 431 | 433 | |
| 432 | for (actions.items) |action| switch (action.kind) { | |
| 433 | .none => {}, | |
| 434 | .add_got => try self.addGotEntry(action.target), | |
| 435 | .add_stub => try self.addStubEntry(action.target), | |
| 436 | }; | |
| 434 | { | |
| 435 | var it = self.actions.iterator(); | |
| 436 | while (it.next()) |entry| { | |
| 437 | const global_index = entry.key_ptr.*; | |
| 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 | 445 | try self.createDyldPrivateAtom(); |
| 439 | 446 | try self.writeStubHelperPreamble(); |
| ... | ... | @@ -1589,18 +1596,18 @@ pub fn createDsoHandleSymbol(self: *MachO) !void { |
| 1589 | 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 | 1600 | // We add the specified entrypoint as the first unresolved symbols so that |
| 1594 | 1601 | // we search for it in libraries should there be no object files specified |
| 1595 | 1602 | // on the linker line. |
| 1596 | 1603 | if (self.base.options.output_mode == .Exe) { |
| 1597 | 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 | 1608 | // Force resolution of any symbols requested by the user. |
| 1602 | 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 | 1613 | for (self.objects.items, 0..) |_, object_id| { |
| ... | ... | @@ -1612,13 +1619,13 @@ pub fn resolveSymbols(self: *MachO, actions: *std.ArrayList(ResolveAction)) !voi |
| 1612 | 1619 | // Finally, force resolution of dyld_stub_binder if there are imports |
| 1613 | 1620 | // requested. |
| 1614 | 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 | 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 | 1630 | try self.createMhExecuteHeaderSymbol(); |
| 1624 | 1631 | try self.createDsoHandleSymbol(); |
| ... | ... | @@ -1634,7 +1641,7 @@ fn resolveGlobalSymbol(self: *MachO, current: SymbolWithLoc) !void { |
| 1634 | 1641 | if (!gop.found_existing) { |
| 1635 | 1642 | gop.value_ptr.* = current; |
| 1636 | 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 | 1646 | return; |
| 1640 | 1647 | } |
| ... | ... | @@ -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 | 1777 | if (self.dylibs.items.len == 0) return; |
| 1771 | 1778 | |
| 1772 | 1779 | const gpa = self.base.allocator; |
| ... | ... | @@ -1793,11 +1800,7 @@ fn resolveSymbolsInDylibs(self: *MachO, actions: *std.ArrayList(ResolveAction)) |
| 1793 | 1800 | sym.n_desc |= macho.N_WEAK_REF; |
| 1794 | 1801 | } |
| 1795 | 1802 | |
| 1796 | if (self.unresolved.fetchSwapRemove(global_index)) |entry| blk: { | |
| 1797 | if (!sym.undf()) break :blk; | |
| 1798 | if (self.mode == .zld) break :blk; | |
| 1799 | try actions.append(.{ .kind = entry.value, .target = global }); | |
| 1800 | } | |
| 1803 | _ = self.unresolved.swapRemove(global_index); | |
| 1801 | 1804 | |
| 1802 | 1805 | continue :loop; |
| 1803 | 1806 | } |
| ... | ... | @@ -1927,6 +1930,7 @@ pub fn deinit(self: *MachO) void { |
| 1927 | 1930 | relocs.deinit(gpa); |
| 1928 | 1931 | } |
| 1929 | 1932 | self.relocs.deinit(gpa); |
| 1933 | self.actions.deinit(gpa); | |
| 1930 | 1934 | |
| 1931 | 1935 | for (self.rebases.values()) |*rebases| { |
| 1932 | 1936 | rebases.deinit(gpa); |
| ... | ... | @@ -2266,6 +2270,7 @@ fn lowerConst( |
| 2266 | 2270 | log.debug(" (required alignment 0x{x})", .{required_alignment}); |
| 2267 | 2271 | |
| 2268 | 2272 | try self.writeAtom(atom_index, code); |
| 2273 | self.markRelocsDirtyByTarget(atom.getSymbolWithLoc()); | |
| 2269 | 2274 | |
| 2270 | 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 | 2286 | const decl = mod.declPtr(decl_index); |
| 2282 | 2287 | |
| 2283 | 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| { | |
| 2287 | if (variable.is_extern) { | |
| 2288 | return; // TODO Should we do more when front-end analyzed extern decl? | |
| 2289 | } | |
| 2291 | ||
| 2292 | if (decl.isExtern(mod)) { | |
| 2293 | // TODO make this part of getGlobalSymbol | |
| 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 | 2301 | const is_threadlocal = if (decl.val.getVariable(mod)) |variable| |
| ... | ... | @@ -2753,7 +2762,17 @@ pub fn updateExports( |
| 2753 | 2762 | } |
| 2754 | 2763 | |
| 2755 | 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 | 2776 | try metadata.exports.append(gpa, global_sym_index); |
| 2758 | 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 | 3441 | const gpa = self.base.allocator; |
| 3423 | 3442 | const sym_name = try std.fmt.allocPrint(gpa, "_{s}", .{name}); |
| 3424 | 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 | 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 | 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 | 4729 | const gpa = self.base.allocator; |
| 4711 | 4730 | |
| 4712 | 4731 | const gop = try self.getOrPutGlobalPtr(name); |
| 4713 | 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 | 4739 | const sym_index = try self.allocateSymbol(); |
| 4718 | 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 | 4742 | |
| 4721 | 4743 | const sym = self.getSymbolPtr(sym_loc); |
| 4722 | 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 | 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 | 4762 | pub fn makeStaticString(bytes: []const u8) [16]u8 { |
| 4731 | 4763 | var buf = [_]u8{0} ** 16; |
| 4732 | 4764 | @memcpy(buf[0..bytes.len], bytes); |
| ... | ... | @@ -4838,6 +4870,11 @@ const GetOrPutGlobalPtrResult = struct { |
| 4838 | 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 | 4878 | /// Return pointer to the global entry for `name` if one exists. |
| 4842 | 4879 | /// Puts a new global entry for `name` if one doesn't exist, and |
| 4843 | 4880 | /// returns a pointer to it. |
| ... | ... | @@ -5510,16 +5547,11 @@ const BindingTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnma |
| 5510 | 5547 | const UnnamedConstTable = std.AutoArrayHashMapUnmanaged(Module.Decl.Index, std.ArrayListUnmanaged(Atom.Index)); |
| 5511 | 5548 | const RebaseTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(u32)); |
| 5512 | 5549 | const RelocationTable = std.AutoArrayHashMapUnmanaged(Atom.Index, std.ArrayListUnmanaged(Relocation)); |
| 5550 | const ActionTable = std.AutoHashMapUnmanaged(u32, RelocFlags); | |
| 5513 | 5551 | |
| 5514 | pub const ResolveAction = struct { | |
| 5515 | kind: Kind, | |
| 5516 | target: SymbolWithLoc, | |
| 5517 | ||
| 5518 | const Kind = enum { | |
| 5519 | none, | |
| 5520 | add_got, | |
| 5521 | add_stub, | |
| 5522 | }; | |
| 5552 | pub const RelocFlags = packed struct { | |
| 5553 | add_got: bool = false, | |
| 5554 | add_stub: bool = false, | |
| 5523 | 5555 | }; |
| 5524 | 5556 | |
| 5525 | 5557 | pub const SymbolWithLoc = extern struct { |
src/link/MachO/Atom.zig+24-23| ... | ... | @@ -300,7 +300,7 @@ pub fn resolveRelocations( |
| 300 | 300 | relocs: []*const Relocation, |
| 301 | 301 | code: []u8, |
| 302 | 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 | 304 | for (relocs) |reloc| { |
| 305 | 305 | reloc.resolve(macho_file, atom_index, code); |
| 306 | 306 | } |
| ... | ... | @@ -603,7 +603,7 @@ pub fn resolveRelocs( |
| 603 | 603 | const atom = macho_file.getAtom(atom_index); |
| 604 | 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 | 607 | atom.sym_index, |
| 608 | 608 | macho_file.getSymbolName(atom.getSymbolWithLoc()), |
| 609 | 609 | }); |
| ... | ... | @@ -683,7 +683,7 @@ fn resolveRelocsArm64( |
| 683 | 683 | .ARM64_RELOC_ADDEND => { |
| 684 | 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 | 688 | addend = rel.r_symbolnum; |
| 689 | 689 | continue; |
| ... | ... | @@ -691,7 +691,7 @@ fn resolveRelocsArm64( |
| 691 | 691 | .ARM64_RELOC_SUBTRACTOR => { |
| 692 | 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 | 695 | @tagName(rel_type), |
| 696 | 696 | rel.r_address, |
| 697 | 697 | rel.r_symbolnum, |
| ... | ... | @@ -719,7 +719,7 @@ fn resolveRelocsArm64( |
| 719 | 719 | }); |
| 720 | 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 | 723 | @tagName(rel_type), |
| 724 | 724 | rel.r_address, |
| 725 | 725 | target.sym_index, |
| ... | ... | @@ -745,11 +745,11 @@ fn resolveRelocsArm64( |
| 745 | 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 | 750 | switch (rel_type) { |
| 751 | 751 | .ARM64_RELOC_BRANCH26 => { |
| 752 | log.debug(" source {s} (object({?})), target {s}", .{ | |
| 752 | relocs_log.debug(" source {s} (object({?})), target {s}", .{ | |
| 753 | 753 | macho_file.getSymbolName(atom.getSymbolWithLoc()), |
| 754 | 754 | atom.getFile(), |
| 755 | 755 | macho_file.getSymbolName(target), |
| ... | ... | @@ -759,7 +759,7 @@ fn resolveRelocsArm64( |
| 759 | 759 | source_addr, |
| 760 | 760 | target_addr, |
| 761 | 761 | )) |disp| blk: { |
| 762 | log.debug(" | target_addr = 0x{x}", .{target_addr}); | |
| 762 | relocs_log.debug(" | target_addr = 0x{x}", .{target_addr}); | |
| 763 | 763 | break :blk disp; |
| 764 | 764 | } else |_| blk: { |
| 765 | 765 | const thunk_index = macho_file.thunk_table.get(atom_index).?; |
| ... | ... | @@ -769,7 +769,7 @@ fn resolveRelocsArm64( |
| 769 | 769 | else |
| 770 | 770 | thunk.getTrampoline(macho_file, .atom, target).?; |
| 771 | 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 | 773 | break :blk try Relocation.calcPcRelativeDisplacementArm64(source_addr, thunk_addr); |
| 774 | 774 | }; |
| 775 | 775 | |
| ... | ... | @@ -790,7 +790,7 @@ fn resolveRelocsArm64( |
| 790 | 790 | => { |
| 791 | 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 | 795 | const pages = @as(u21, @bitCast(Relocation.calcNumberOfPages(source_addr, adjusted_target_addr))); |
| 796 | 796 | const code = atom_code[rel_offset..][0..4]; |
| ... | ... | @@ -809,7 +809,7 @@ fn resolveRelocsArm64( |
| 809 | 809 | .ARM64_RELOC_PAGEOFF12 => { |
| 810 | 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 | 814 | const code = atom_code[rel_offset..][0..4]; |
| 815 | 815 | if (Relocation.isArithmeticOp(code)) { |
| ... | ... | @@ -848,7 +848,7 @@ fn resolveRelocsArm64( |
| 848 | 848 | const code = atom_code[rel_offset..][0..4]; |
| 849 | 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 | 853 | const off = try Relocation.calcPageOffset(adjusted_target_addr, .load_store_64); |
| 854 | 854 | var inst: aarch64.Instruction = .{ |
| ... | ... | @@ -866,7 +866,7 @@ fn resolveRelocsArm64( |
| 866 | 866 | const code = atom_code[rel_offset..][0..4]; |
| 867 | 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 | 871 | const RegInfo = struct { |
| 872 | 872 | rd: u5, |
| ... | ... | @@ -923,7 +923,7 @@ fn resolveRelocsArm64( |
| 923 | 923 | }, |
| 924 | 924 | |
| 925 | 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 | 927 | const result = math.cast(i32, @as(i64, @intCast(target_addr)) - @as(i64, @intCast(source_addr))) orelse |
| 928 | 928 | return error.Overflow; |
| 929 | 929 | mem.writeIntLittle(u32, atom_code[rel_offset..][0..4], @as(u32, @bitCast(result))); |
| ... | ... | @@ -951,7 +951,7 @@ fn resolveRelocsArm64( |
| 951 | 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 | 956 | if (rel.r_length == 3) { |
| 957 | 957 | mem.writeIntLittle(u64, atom_code[rel_offset..][0..8], @as(u64, @bitCast(result))); |
| ... | ... | @@ -987,7 +987,7 @@ fn resolveRelocsX86( |
| 987 | 987 | .X86_64_RELOC_SUBTRACTOR => { |
| 988 | 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 | 991 | @tagName(rel_type), |
| 992 | 992 | rel.r_address, |
| 993 | 993 | rel.r_symbolnum, |
| ... | ... | @@ -1015,7 +1015,7 @@ fn resolveRelocsX86( |
| 1015 | 1015 | }); |
| 1016 | 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 | 1019 | @tagName(rel_type), |
| 1020 | 1020 | rel.r_address, |
| 1021 | 1021 | target.sym_index, |
| ... | ... | @@ -1041,13 +1041,13 @@ fn resolveRelocsX86( |
| 1041 | 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 | 1046 | switch (rel_type) { |
| 1047 | 1047 | .X86_64_RELOC_BRANCH => { |
| 1048 | 1048 | const addend = mem.readIntLittle(i32, atom_code[rel_offset..][0..4]); |
| 1049 | 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 | 1051 | const disp = try Relocation.calcPcRelativeDisplacementX86(source_addr, adjusted_target_addr, 0); |
| 1052 | 1052 | mem.writeIntLittle(i32, atom_code[rel_offset..][0..4], disp); |
| 1053 | 1053 | }, |
| ... | ... | @@ -1057,7 +1057,7 @@ fn resolveRelocsX86( |
| 1057 | 1057 | => { |
| 1058 | 1058 | const addend = mem.readIntLittle(i32, atom_code[rel_offset..][0..4]); |
| 1059 | 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 | 1061 | const disp = try Relocation.calcPcRelativeDisplacementX86(source_addr, adjusted_target_addr, 0); |
| 1062 | 1062 | mem.writeIntLittle(i32, atom_code[rel_offset..][0..4], disp); |
| 1063 | 1063 | }, |
| ... | ... | @@ -1065,7 +1065,7 @@ fn resolveRelocsX86( |
| 1065 | 1065 | .X86_64_RELOC_TLV => { |
| 1066 | 1066 | const addend = mem.readIntLittle(i32, atom_code[rel_offset..][0..4]); |
| 1067 | 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 | 1069 | const disp = try Relocation.calcPcRelativeDisplacementX86(source_addr, adjusted_target_addr, 0); |
| 1070 | 1070 | |
| 1071 | 1071 | if (macho_file.tlv_ptr_table.lookup.get(target) == null) { |
| ... | ... | @@ -1101,7 +1101,7 @@ fn resolveRelocsX86( |
| 1101 | 1101 | |
| 1102 | 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 | 1106 | const disp = try Relocation.calcPcRelativeDisplacementX86(source_addr, adjusted_target_addr, correction); |
| 1107 | 1107 | mem.writeIntLittle(i32, atom_code[rel_offset..][0..4], disp); |
| ... | ... | @@ -1129,7 +1129,7 @@ fn resolveRelocsX86( |
| 1129 | 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 | 1134 | if (rel.r_length == 3) { |
| 1135 | 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 | 1247 | const aarch64 = @import("../../arch/aarch64/bits.zig"); |
| 1248 | 1248 | const assert = std.debug.assert; |
| 1249 | 1249 | const log = std.log.scoped(.link); |
| 1250 | const relocs_log = std.log.scoped(.link_relocs); | |
| 1250 | 1251 | const macho = std.macho; |
| 1251 | 1252 | const math = std.math; |
| 1252 | 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 | 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 | 103 | source_addr, |
| 104 | 104 | target_addr, |
| 105 | 105 | macho_file.getSymbolName(self.target), |
| ... | ... | @@ -256,7 +256,7 @@ const Relocation = @This(); |
| 256 | 256 | const std = @import("std"); |
| 257 | 257 | const aarch64 = @import("../../arch/aarch64/bits.zig"); |
| 258 | 258 | const assert = std.debug.assert; |
| 259 | const log = std.log.scoped(.link); | |
| 259 | const relocs_log = std.log.scoped(.link_relocs); | |
| 260 | 260 | const macho = std.macho; |
| 261 | 261 | const math = std.math; |
| 262 | 262 | const mem = std.mem; |
src/link/MachO/zld.zig+1-3| ... | ... | @@ -390,9 +390,7 @@ pub fn linkWithZld( |
| 390 | 390 | |
| 391 | 391 | try macho_file.parseDependentLibs(&dependent_libs); |
| 392 | 392 | |
| 393 | var actions = std.ArrayList(MachO.ResolveAction).init(gpa); | |
| 394 | defer actions.deinit(); | |
| 395 | try macho_file.resolveSymbols(&actions); | |
| 393 | try macho_file.resolveSymbols(); | |
| 396 | 394 | if (macho_file.unresolved.count() > 0) { |
| 397 | 395 | try macho_file.reportUndefined(); |
| 398 | 396 | return error.FlushFailure; |