| ... | ... | @@ -788,10 +788,9 @@ fn writeAtom(self: *Coff, atom_index: Atom.Index, code: []u8) !void { |
| 788 | 788 | |
| 789 | 789 | if (self.base.child_pid) |handle| { |
| 790 | 790 | const vaddr = sym.value + (self.hot_state.loaded_base_address orelse self.getImageBase()); |
| 791 | | log.warn("hcs: writing to memory at address {x}", .{vaddr}); |
| 792 | | try debugMem(self.base.allocator, handle, vaddr, code); |
| 791 | log.debug("writing to memory at address {x}", .{vaddr}); |
| 793 | 792 | if (section.header.flags.MEM_WRITE == 0) { |
| 794 | | log.warn(" page not mapped for write access; re-mapping...", .{}); |
| 793 | log.debug("page not mapped for write access; re-mapping...", .{}); |
| 795 | 794 | try writeMemProtected(handle, vaddr, code); |
| 796 | 795 | } else { |
| 797 | 796 | try writeMem(handle, vaddr, code); |
| ... | ... | @@ -859,7 +858,7 @@ fn getProcessBaseAddress(handle: std.ChildProcess.Id) !u64 { |
| 859 | 858 | &peb_nread, |
| 860 | 859 | ) == 0) { |
| 861 | 860 | const err = std.os.windows.kernel32.GetLastError(); |
| 862 | | log.warn("hcs: reading from process memory failed with err: {s}({x})", .{ @tagName(err), @enumToInt(err) }); |
| 861 | log.warn("reading from process memory failed with err: {s}({x})", .{ @tagName(err), @enumToInt(err) }); |
| 863 | 862 | return error.FailedToReadPebForProcess; |
| 864 | 863 | } |
| 865 | 864 | if (peb_nread != @sizeOf(std.os.windows.PEB)) return error.InputOutput; |
| ... | ... | @@ -880,14 +879,14 @@ fn debugMem(allocator: Allocator, handle: std.ChildProcess.Id, vaddr: u64, code: |
| 880 | 879 | &nread, |
| 881 | 880 | ) == 0) { |
| 882 | 881 | const err = std.os.windows.kernel32.GetLastError(); |
| 883 | | log.warn("hcs: reading from process memory failed with err: {s}({x})", .{ @tagName(err), @enumToInt(err) }); |
| 882 | log.warn("reading from process memory failed with err: {s}({x})", .{ @tagName(err), @enumToInt(err) }); |
| 884 | 883 | } |
| 885 | 884 | if (nread != code.len) { |
| 886 | | log.warn("hcs: reading from process memory InputOutput error: read != requested: {x} != {x}", .{ nread, code.len }); |
| 885 | log.warn("reading from process memory InputOutput error: read != requested: {x} != {x}", .{ nread, code.len }); |
| 887 | 886 | } |
| 888 | 887 | |
| 889 | | log.warn("in memory: {x}", .{std.fmt.fmtSliceHexLower(buffer)}); |
| 890 | | log.warn("to write: {x}", .{std.fmt.fmtSliceHexLower(code)}); |
| 888 | log.debug("in memory: {x}", .{std.fmt.fmtSliceHexLower(buffer)}); |
| 889 | log.debug("to write: {x}", .{std.fmt.fmtSliceHexLower(code)}); |
| 891 | 890 | } |
| 892 | 891 | |
| 893 | 892 | fn writeMemProtected(handle: std.ChildProcess.Id, vaddr: u64, code: []const u8) !void { |
| ... | ... | @@ -896,16 +895,15 @@ fn writeMemProtected(handle: std.ChildProcess.Id, vaddr: u64, code: []const u8) |
| 896 | 895 | var old_prot: std.os.windows.DWORD = undefined; |
| 897 | 896 | if (VirtualProtectEx(handle, pvaddr, code.len, new_prot, &old_prot) == 0) { |
| 898 | 897 | const err = std.os.windows.kernel32.GetLastError(); |
| 899 | | log.warn("hcs: making page(s) writeable failed with error: {s}({x})", .{ @tagName(err), @enumToInt(err) }); |
| 898 | log.warn("making page(s) writeable failed with error: {s}({x})", .{ @tagName(err), @enumToInt(err) }); |
| 900 | 899 | return; |
| 901 | 900 | } |
| 902 | | log.warn("old = {x}, new = {x}", .{ old_prot, new_prot }); |
| 903 | 901 | try writeMem(handle, vaddr, code); |
| 904 | 902 | // TODO: We can probably just set the pages writeable and leave it at that without having to restore the attributes. |
| 905 | 903 | // For that though, we want to track which page has already been modified. |
| 906 | 904 | if (VirtualProtectEx(handle, pvaddr, code.len, old_prot, &new_prot) == 0) { |
| 907 | 905 | const err = std.os.windows.kernel32.GetLastError(); |
| 908 | | log.warn("hcs: restoring page(s) attributes failed with error: {s}({x})", .{ @tagName(err), @enumToInt(err) }); |
| 906 | log.warn("restoring page(s) attributes failed with error: {s}({x})", .{ @tagName(err), @enumToInt(err) }); |
| 909 | 907 | } |
| 910 | 908 | } |
| 911 | 909 | |
| ... | ... | @@ -919,10 +917,10 @@ fn writeMem(handle: std.ChildProcess.Id, vaddr: u64, code: []const u8) !void { |
| 919 | 917 | &nwritten, |
| 920 | 918 | ) == 0) { |
| 921 | 919 | const err = std.os.windows.kernel32.GetLastError(); |
| 922 | | log.warn("hcs: writing to process memory failed with err: {s}({x})", .{ @tagName(err), @enumToInt(err) }); |
| 920 | log.warn("writing to process memory failed with err: {s}({x})", .{ @tagName(err), @enumToInt(err) }); |
| 923 | 921 | } |
| 924 | 922 | if (nwritten != code.len) { |
| 925 | | log.warn("hcs: writing to process memory InputOutput error: written != requested: {x} != {x}", .{ nwritten, code.len }); |
| 923 | log.warn("writing to process memory InputOutput error: written != requested: {x} != {x}", .{ nwritten, code.len }); |
| 926 | 924 | } |
| 927 | 925 | } |
| 928 | 926 | |
| ... | ... | @@ -973,15 +971,15 @@ fn resolveRelocs(self: *Coff, atom_index: Atom.Index, code: []u8) void { |
| 973 | 971 | } |
| 974 | 972 | |
| 975 | 973 | pub fn ptraceAttach(self: *Coff, handle: std.ChildProcess.Id) !void { |
| 976 | | log.warn("hcs: attaching to process with handle {*}", .{handle}); |
| 974 | log.debug("attaching to process with handle {*}", .{handle}); |
| 977 | 975 | self.hot_state.loaded_base_address = getProcessBaseAddress(handle) catch |err| { |
| 978 | | log.warn("hcs: failed to get base address for the process with error: {s}", .{@errorName(err)}); |
| 976 | log.warn("failed to get base address for the process with error: {s}", .{@errorName(err)}); |
| 979 | 977 | return; |
| 980 | 978 | }; |
| 981 | 979 | } |
| 982 | 980 | |
| 983 | 981 | pub fn ptraceDetach(self: *Coff, handle: std.ChildProcess.Id) void { |
| 984 | | log.warn("hcs: detaching from process with handle {*}", .{handle}); |
| 982 | log.debug("detaching from process with handle {*}", .{handle}); |
| 985 | 983 | self.hot_state.loaded_base_address = null; |
| 986 | 984 | } |
| 987 | 985 | |