diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2023-03-17 09:25:49 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2023-03-18 21:53:36 +0100 |
| commit | 37192bcdcb38be2266133f6d46dce5a842984c06 (patch) | |
| tree | f529668b8c48d0c2b6d123bccfc0bf8556c218a1 | |
| parent | f1e25cf43ec60075a4fc6f3eceb5a3af1f9f0712 (diff) | |
| download | zig-37192bcdcb38be2266133f6d46dce5a842984c06.tar.gz zig-37192bcdcb38be2266133f6d46dce5a842984c06.zip | |
macos: HCS PoC working
| -rw-r--r-- | lib/std/c/darwin.zig | 2 | ||||
| -rw-r--r-- | src/link.zig | 15 | ||||
| -rw-r--r-- | src/link/MachO.zig | 26 | ||||
| -rw-r--r-- | src/main.zig | 33 |
4 files changed, 43 insertions, 33 deletions
diff --git a/lib/std/c/darwin.zig b/lib/std/c/darwin.zig index ef31bc6d53..4e5bc73c38 100644 --- a/lib/std/c/darwin.zig +++ b/lib/std/c/darwin.zig @@ -3316,7 +3316,7 @@ pub fn getKernError(err: kern_return_t) KernE { pub fn unexpectedKernError(err: KernE) std.os.UnexpectedError { if (std.os.unexpected_error_tracing) { - std.debug.print("unexpected errno: {d}\n", .{@enumToInt(err)}); + std.debug.print("unexpected error: {d}\n", .{@enumToInt(err)}); std.debug.dumpCurrentStackTrace(null); } return error.Unexpected; diff --git a/src/link.zig b/src/link.zig index f1846f184c..c87d5b5dd5 100644 --- a/src/link.zig +++ b/src/link.zig @@ -397,9 +397,10 @@ pub const File = struct { if (macho.mach_task == null) { if (std.os.darwin.machTaskForPid(pid)) |task| { macho.mach_task = task; - std.os.ptrace(std.os.darwin.PT.ATTACHEXC, pid, 0, 0) catch |err| { - log.warn("ptrace failure: {s}", .{@errorName(err)}); - }; + // TODO enable ones we register for exceptions + // std.os.ptrace(std.os.darwin.PT.ATTACHEXC, pid, 0, 0) catch |err| { + // log.warn("ptrace failure: {s}", .{@errorName(err)}); + // }; } else |err| { log.warn("failed to acquire Mach task for child process: {s}", .{@errorName(err)}); } @@ -443,9 +444,11 @@ pub const File = struct { .linux => std.os.ptrace(std.os.linux.PTRACE.DETACH, pid, 0, 0) catch |err| { log.warn("ptrace failure: {s}", .{@errorName(err)}); }, - .macos => std.os.ptrace(std.os.darwin.PT.KILL, pid, 0, 0) catch |err| { - log.warn("ptrace failure: {s}", .{@errorName(err)}); - }, + .macos => {}, + // TODO see comment above in makeWritable + // .macos => std.os.ptrace(std.os.darwin.PT.DETACH, pid, 0, 0) catch |err| { + // log.warn("ptrace failure: {s}", .{@errorName(err)}); + // }, else => return error.HotSwapUnavailableOnHostOperatingSystem, } } 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, diff --git a/src/main.zig b/src/main.zig index 7d46f10a22..551bd55c42 100644 --- a/src/main.zig +++ b/src/main.zig @@ -3320,21 +3320,20 @@ fn buildOutputType( try server.listen(.{ .in = ip4_addr }); - while (true) { - const conn = try server.accept(); - defer conn.stream.close(); - - try serve( - comp, - .{ .handle = conn.stream.handle }, - .{ .handle = conn.stream.handle }, - test_exec_args.items, - self_exe_path, - arg_mode, - all_args, - runtime_args_start, - ); - } + const conn = try server.accept(); + defer conn.stream.close(); + + try serve( + comp, + .{ .handle = conn.stream.handle }, + .{ .handle = conn.stream.handle }, + test_exec_args.items, + self_exe_path, + arg_mode, + all_args, + runtime_args_start, + ); + return cleanExit(); }, } @@ -3465,9 +3464,7 @@ fn serve( const hdr = try server.receiveMessage(); switch (hdr.tag) { - .exit => { - return cleanExit(); - }, + .exit => return, .update => { assert(main_progress_node.recently_updated_child == null); tracy.frameMark(); |
