aboutsummaryrefslogtreecommitdiff
path: root/src/link
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2023-03-17 09:25:49 +0100
committerJakub Konka <kubkon@jakubkonka.com>2023-03-18 21:53:36 +0100
commit37192bcdcb38be2266133f6d46dce5a842984c06 (patch)
treef529668b8c48d0c2b6d123bccfc0bf8556c218a1 /src/link
parentf1e25cf43ec60075a4fc6f3eceb5a3af1f9f0712 (diff)
downloadzig-37192bcdcb38be2266133f6d46dce5a842984c06.tar.gz
zig-37192bcdcb38be2266133f6d46dce5a842984c06.zip
macos: HCS PoC working
Diffstat (limited to 'src/link')
-rw-r--r--src/link/MachO.zig26
1 files changed, 18 insertions, 8 deletions
diff --git a/src/link/MachO.zig b/src/link/MachO.zig
index 274c4dd9aa..869061be38 100644
--- a/src/link/MachO.zig
+++ b/src/link/MachO.zig
@@ -587,7 +587,12 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No
try self.allocateSpecialSymbols();
for (self.relocs.keys()) |atom_index| {
- if (self.relocs.get(atom_index) == null) continue;
+ const relocs = self.relocs.get(atom_index).?;
+ const needs_update = for (relocs.items) |reloc| {
+ if (reloc.dirty) break true;
+ } else false;
+
+ if (!needs_update) continue;
const atom = self.getAtom(atom_index);
const sym = atom.getSymbol(self);
@@ -1085,7 +1090,7 @@ pub fn writeAtom(self: *MachO, atom_index: Atom.Index, code: []u8) !void {
log.warn("cannot hot swap: no Mach task acquired for child process with pid {d}", .{pid});
break :blk;
};
- self.writeAtomToMemory(task, section.segment_index, sym.n_value, code) catch |err| {
+ self.updateAtomInMemory(task, section.segment_index, sym.n_value, code) catch |err| {
log.warn("cannot hot swap: writing to memory failed: {s}", .{@errorName(err)});
};
}
@@ -1093,13 +1098,13 @@ pub fn writeAtom(self: *MachO, atom_index: Atom.Index, code: []u8) !void {
try self.base.file.?.pwriteAll(code, file_offset);
}
-fn writeAtomToMemory(self: *MachO, task: std.os.darwin.MachTask, segment_index: u8, addr: u64, code: []const u8) !void {
+fn updateAtomInMemory(self: *MachO, task: std.os.darwin.MachTask, segment_index: u8, addr: u64, code: []const u8) !void {
const segment = self.segments.items[segment_index];
- if (!segment.isWriteable()) {
- try task.setCurrProtection(addr, code.len, macho.PROT.READ | macho.PROT.WRITE | macho.PROT.COPY);
- }
- defer if (!segment.isWriteable()) task.setCurrProtection(addr, code.len, segment.initprot) catch {};
- const nwritten = try task.writeMem(addr, code, self.base.options.target.cpu.arch);
+ const cpu_arch = self.base.options.target.cpu.arch;
+ const nwritten = if (!segment.isWriteable())
+ try task.writeMemProtected(addr, code, cpu_arch)
+ else
+ try task.writeMem(addr, code, cpu_arch);
if (nwritten != code.len) return error.InputOutput;
}
@@ -1109,6 +1114,7 @@ fn writePtrWidthAtom(self: *MachO, atom_index: Atom.Index) !void {
}
fn markRelocsDirtyByTarget(self: *MachO, target: SymbolWithLoc) void {
+ log.debug("marking relocs dirty by target: {}", .{target});
// TODO: reverse-lookup might come in handy here
for (self.relocs.values()) |*relocs| {
for (relocs.items) |*reloc| {
@@ -1119,6 +1125,7 @@ fn markRelocsDirtyByTarget(self: *MachO, target: SymbolWithLoc) void {
}
fn markRelocsDirtyByAddress(self: *MachO, addr: u64) void {
+ log.debug("marking relocs dirty by address: {x}", .{addr});
for (self.relocs.values()) |*relocs| {
for (relocs.items) |*reloc| {
const target_atom_index = reloc.getTargetAtomIndex(self) orelse continue;
@@ -1743,6 +1750,8 @@ pub fn resolveDyldStubBinder(self: *MachO) !void {
if (self.dyld_stub_binder_index != null) return;
if (self.unresolved.count() == 0) return; // no need for a stub binder if we don't have any imports
+ log.debug("resolving dyld_stub_binder", .{});
+
const gpa = self.base.allocator;
const sym_index = try self.allocateSymbol();
const sym_loc = SymbolWithLoc{ .sym_index = sym_index, .file = null };
@@ -2829,6 +2838,7 @@ pub fn populateMissingMetadata(self: *MachO) !void {
if (self.linkedit_segment_cmd_index == null) {
self.linkedit_segment_cmd_index = @intCast(u8, self.segments.items.len);
+
try self.segments.append(gpa, .{
.segname = makeStaticString("__LINKEDIT"),
.maxprot = macho.PROT.READ,