authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-30 14:10:11+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-03-30 21:08:30+02:00
logd2f013085523436b51023f7d28d52a859b70a4b3
tree4ce7652b3f37aa63016d0c56009b7fecb685476e
parent39d63036441841fb81eebda97fb2932e5c3f79c4

coff: make sure we correctly slide relocation target when resolving


2 files changed, 15 insertions(+), 17 deletions(-)

src/link/Coff.zig+14-16
...@@ -788,10 +788,9 @@ fn writeAtom(self: *Coff, atom_index: Atom.Index, code: []u8) !void {...@@ -788,10 +788,9 @@ fn writeAtom(self: *Coff, atom_index: Atom.Index, code: []u8) !void {
788788
789 if (self.base.child_pid) |handle| {789 if (self.base.child_pid) |handle| {
790 const vaddr = sym.value + (self.hot_state.loaded_base_address orelse self.getImageBase());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});791 log.debug("writing to memory at address {x}", .{vaddr});
792 try debugMem(self.base.allocator, handle, vaddr, code);
793 if (section.header.flags.MEM_WRITE == 0) {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 try writeMemProtected(handle, vaddr, code);794 try writeMemProtected(handle, vaddr, code);
796 } else {795 } else {
797 try writeMem(handle, vaddr, code);796 try writeMem(handle, vaddr, code);
...@@ -859,7 +858,7 @@ fn getProcessBaseAddress(handle: std.ChildProcess.Id) !u64 {...@@ -859,7 +858,7 @@ fn getProcessBaseAddress(handle: std.ChildProcess.Id) !u64 {
859 &peb_nread,858 &peb_nread,
860 ) == 0) {859 ) == 0) {
861 const err = std.os.windows.kernel32.GetLastError();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 return error.FailedToReadPebForProcess;862 return error.FailedToReadPebForProcess;
864 }863 }
865 if (peb_nread != @sizeOf(std.os.windows.PEB)) return error.InputOutput;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,14 +879,14 @@ fn debugMem(allocator: Allocator, handle: std.ChildProcess.Id, vaddr: u64, code:
880 &nread,879 &nread,
881 ) == 0) {880 ) == 0) {
882 const err = std.os.windows.kernel32.GetLastError();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 if (nread != code.len) {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 }
888887
889 log.warn("in memory: {x}", .{std.fmt.fmtSliceHexLower(buffer)});888 log.debug("in memory: {x}", .{std.fmt.fmtSliceHexLower(buffer)});
890 log.warn("to write: {x}", .{std.fmt.fmtSliceHexLower(code)});889 log.debug("to write: {x}", .{std.fmt.fmtSliceHexLower(code)});
891}890}
892891
893fn writeMemProtected(handle: std.ChildProcess.Id, vaddr: u64, code: []const u8) !void {892fn 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,16 +895,15 @@ fn writeMemProtected(handle: std.ChildProcess.Id, vaddr: u64, code: []const u8)
896 var old_prot: std.os.windows.DWORD = undefined;895 var old_prot: std.os.windows.DWORD = undefined;
897 if (VirtualProtectEx(handle, pvaddr, code.len, new_prot, &old_prot) == 0) {896 if (VirtualProtectEx(handle, pvaddr, code.len, new_prot, &old_prot) == 0) {
898 const err = std.os.windows.kernel32.GetLastError();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 return;899 return;
901 }900 }
902 log.warn("old = {x}, new = {x}", .{ old_prot, new_prot });
903 try writeMem(handle, vaddr, code);901 try writeMem(handle, vaddr, code);
904 // TODO: We can probably just set the pages writeable and leave it at that without having to restore the attributes.902 // TODO: We can probably just set the pages writeable and leave it at that without having to restore the attributes.
905 // For that though, we want to track which page has already been modified.903 // For that though, we want to track which page has already been modified.
906 if (VirtualProtectEx(handle, pvaddr, code.len, old_prot, &new_prot) == 0) {904 if (VirtualProtectEx(handle, pvaddr, code.len, old_prot, &new_prot) == 0) {
907 const err = std.os.windows.kernel32.GetLastError();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}
911909
...@@ -919,10 +917,10 @@ fn writeMem(handle: std.ChildProcess.Id, vaddr: u64, code: []const u8) !void {...@@ -919,10 +917,10 @@ fn writeMem(handle: std.ChildProcess.Id, vaddr: u64, code: []const u8) !void {
919 &nwritten,917 &nwritten,
920 ) == 0) {918 ) == 0) {
921 const err = std.os.windows.kernel32.GetLastError();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 if (nwritten != code.len) {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}
928926
...@@ -973,15 +971,15 @@ fn resolveRelocs(self: *Coff, atom_index: Atom.Index, code: []u8) void {...@@ -973,15 +971,15 @@ fn resolveRelocs(self: *Coff, atom_index: Atom.Index, code: []u8) void {
973}971}
974972
975pub fn ptraceAttach(self: *Coff, handle: std.ChildProcess.Id) !void {973pub 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 self.hot_state.loaded_base_address = getProcessBaseAddress(handle) catch |err| {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 return;977 return;
980 };978 };
981}979}
982980
983pub fn ptraceDetach(self: *Coff, handle: std.ChildProcess.Id) void {981pub 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 self.hot_state.loaded_base_address = null;983 self.hot_state.loaded_base_address = null;
986}984}
987985
src/link/Coff/Relocation.zig+1-1
...@@ -92,7 +92,7 @@ pub fn resolve(self: Relocation, atom_index: Atom.Index, code: []u8, coff_file:...@@ -92,7 +92,7 @@ pub fn resolve(self: Relocation, atom_index: Atom.Index, code: []u8, coff_file:
92 const ctx: Context = .{92 const ctx: Context = .{
93 .source_vaddr = source_vaddr,93 .source_vaddr = source_vaddr,
94 .target_vaddr = target_vaddr_with_addend,94 .target_vaddr = target_vaddr_with_addend,
95 .image_base = coff_file.getImageBase(),95 .image_base = coff_file.hot_state.loaded_base_address orelse coff_file.getImageBase(),
96 .code = code,96 .code = code,
97 .ptr_width = coff_file.ptr_width,97 .ptr_width = coff_file.ptr_width,
98 };98 };