| ... | @@ -587,7 +587,12 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No | ... | @@ -587,7 +587,12 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No |
| 587 | try self.allocateSpecialSymbols(); | 587 | try self.allocateSpecialSymbols(); |
| 588 | | 588 | |
| 589 | for (self.relocs.keys()) |atom_index| { | 589 | for (self.relocs.keys()) |atom_index| { |
| 590 | if (self.relocs.get(atom_index) == null) continue; | 590 | const relocs = self.relocs.get(atom_index).?; |
| | 591 | const needs_update = for (relocs.items) |reloc| { |
| | 592 | if (reloc.dirty) break true; |
| | 593 | } else false; |
| | 594 | |
| | 595 | if (!needs_update) continue; |
| 591 | | 596 | |
| 592 | const atom = self.getAtom(atom_index); | 597 | const atom = self.getAtom(atom_index); |
| 593 | const sym = atom.getSymbol(self); | 598 | const sym = atom.getSymbol(self); |
| ... | @@ -1085,7 +1090,7 @@ pub fn writeAtom(self: *MachO, atom_index: Atom.Index, code: []u8) !void { | ... | @@ -1085,7 +1090,7 @@ pub fn writeAtom(self: *MachO, atom_index: Atom.Index, code: []u8) !void { |
| 1085 | log.warn("cannot hot swap: no Mach task acquired for child process with pid {d}", .{pid}); | 1090 | log.warn("cannot hot swap: no Mach task acquired for child process with pid {d}", .{pid}); |
| 1086 | break :blk; | 1091 | break :blk; |
| 1087 | }; | 1092 | }; |
| 1088 | self.writeAtomToMemory(task, section.segment_index, sym.n_value, code) catch |err| { | 1093 | self.updateAtomInMemory(task, section.segment_index, sym.n_value, code) catch |err| { |
| 1089 | log.warn("cannot hot swap: writing to memory failed: {s}", .{@errorName(err)}); | 1094 | log.warn("cannot hot swap: writing to memory failed: {s}", .{@errorName(err)}); |
| 1090 | }; | 1095 | }; |
| 1091 | } | 1096 | } |
| ... | @@ -1093,13 +1098,13 @@ pub fn writeAtom(self: *MachO, atom_index: Atom.Index, code: []u8) !void { | ... | @@ -1093,13 +1098,13 @@ pub fn writeAtom(self: *MachO, atom_index: Atom.Index, code: []u8) !void { |
| 1093 | try self.base.file.?.pwriteAll(code, file_offset); | 1098 | try self.base.file.?.pwriteAll(code, file_offset); |
| 1094 | } | 1099 | } |
| 1095 | | 1100 | |
| 1096 | fn writeAtomToMemory(self: *MachO, task: std.os.darwin.MachTask, segment_index: u8, addr: u64, code: []const u8) !void { | 1101 | fn updateAtomInMemory(self: *MachO, task: std.os.darwin.MachTask, segment_index: u8, addr: u64, code: []const u8) !void { |
| 1097 | const segment = self.segments.items[segment_index]; | 1102 | const segment = self.segments.items[segment_index]; |
| 1098 | if (!segment.isWriteable()) { | 1103 | const cpu_arch = self.base.options.target.cpu.arch; |
| 1099 | try task.setCurrProtection(addr, code.len, macho.PROT.READ | macho.PROT.WRITE | macho.PROT.COPY); | 1104 | const nwritten = if (!segment.isWriteable()) |
| 1100 | } | 1105 | try task.writeMemProtected(addr, code, cpu_arch) |
| 1101 | defer if (!segment.isWriteable()) task.setCurrProtection(addr, code.len, segment.initprot) catch {}; | 1106 | else |
| 1102 | const nwritten = try task.writeMem(addr, code, self.base.options.target.cpu.arch); | 1107 | try task.writeMem(addr, code, cpu_arch); |
| 1103 | if (nwritten != code.len) return error.InputOutput; | 1108 | if (nwritten != code.len) return error.InputOutput; |
| 1104 | } | 1109 | } |
| 1105 | | 1110 | |
| ... | @@ -1109,6 +1114,7 @@ fn writePtrWidthAtom(self: *MachO, atom_index: Atom.Index) !void { | ... | @@ -1109,6 +1114,7 @@ fn writePtrWidthAtom(self: *MachO, atom_index: Atom.Index) !void { |
| 1109 | } | 1114 | } |
| 1110 | | 1115 | |
| 1111 | fn markRelocsDirtyByTarget(self: *MachO, target: SymbolWithLoc) void { | 1116 | fn markRelocsDirtyByTarget(self: *MachO, target: SymbolWithLoc) void { |
| | 1117 | log.debug("marking relocs dirty by target: {}", .{target}); |
| 1112 | // TODO: reverse-lookup might come in handy here | 1118 | // TODO: reverse-lookup might come in handy here |
| 1113 | for (self.relocs.values()) |*relocs| { | 1119 | for (self.relocs.values()) |*relocs| { |
| 1114 | for (relocs.items) |*reloc| { | 1120 | for (relocs.items) |*reloc| { |
| ... | @@ -1119,6 +1125,7 @@ fn markRelocsDirtyByTarget(self: *MachO, target: SymbolWithLoc) void { | ... | @@ -1119,6 +1125,7 @@ fn markRelocsDirtyByTarget(self: *MachO, target: SymbolWithLoc) void { |
| 1119 | } | 1125 | } |
| 1120 | | 1126 | |
| 1121 | fn markRelocsDirtyByAddress(self: *MachO, addr: u64) void { | 1127 | fn markRelocsDirtyByAddress(self: *MachO, addr: u64) void { |
| | 1128 | log.debug("marking relocs dirty by address: {x}", .{addr}); |
| 1122 | for (self.relocs.values()) |*relocs| { | 1129 | for (self.relocs.values()) |*relocs| { |
| 1123 | for (relocs.items) |*reloc| { | 1130 | for (relocs.items) |*reloc| { |
| 1124 | const target_atom_index = reloc.getTargetAtomIndex(self) orelse continue; | 1131 | const target_atom_index = reloc.getTargetAtomIndex(self) orelse continue; |
| ... | @@ -1743,6 +1750,8 @@ pub fn resolveDyldStubBinder(self: *MachO) !void { | ... | @@ -1743,6 +1750,8 @@ pub fn resolveDyldStubBinder(self: *MachO) !void { |
| 1743 | if (self.dyld_stub_binder_index != null) return; | 1750 | if (self.dyld_stub_binder_index != null) return; |
| 1744 | if (self.unresolved.count() == 0) return; // no need for a stub binder if we don't have any imports | 1751 | if (self.unresolved.count() == 0) return; // no need for a stub binder if we don't have any imports |
| 1745 | | 1752 | |
| | 1753 | log.debug("resolving dyld_stub_binder", .{}); |
| | 1754 | |
| 1746 | const gpa = self.base.allocator; | 1755 | const gpa = self.base.allocator; |
| 1747 | const sym_index = try self.allocateSymbol(); | 1756 | const sym_index = try self.allocateSymbol(); |
| 1748 | const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null }; | 1757 | const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null }; |
| ... | @@ -2829,6 +2838,7 @@ pub fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -2829,6 +2838,7 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 2829 | | 2838 | |
| 2830 | if (self.linkedit_segment_cmd_index == null) { | 2839 | if (self.linkedit_segment_cmd_index == null) { |
| 2831 | self.linkedit_segment_cmd_index = @intCast(u8, self.segments.items.len); | 2840 | self.linkedit_segment_cmd_index = @intCast(u8, self.segments.items.len); |
| | 2841 | |
| 2832 | try self.segments.append(gpa, .{ | 2842 | try self.segments.append(gpa, .{ |
| 2833 | .segname = makeStaticString("__LINKEDIT"), | 2843 | .segname = makeStaticString("__LINKEDIT"), |
| 2834 | .maxprot = macho.PROT.READ, | 2844 | .maxprot = macho.PROT.READ, |