mirror of
https://github.com/ziglang/zig.git
synced 2026-01-21 06:45:24 +00:00
hot code swapping PoC working
- improve fn prototypes of process_vm_writev - make the memory writable in the ELF file - force the linker to always append the function - write updates with process_vm_writev
This commit is contained in:
parent
50a2bb58d2
commit
4f4ddf5ef2
@ -1716,26 +1716,26 @@ pub fn pidfd_send_signal(pidfd: fd_t, sig: i32, info: ?*siginfo_t, flags: u32) u
|
||||
);
|
||||
}
|
||||
|
||||
pub fn process_vm_readv(pid: pid_t, local: [*]const iovec, local_count: usize, remote: [*]const iovec, remote_count: usize, flags: usize) usize {
|
||||
pub fn process_vm_readv(pid: pid_t, local: []iovec, remote: []const iovec_const, flags: usize) usize {
|
||||
return syscall6(
|
||||
.process_vm_readv,
|
||||
@bitCast(usize, @as(isize, pid)),
|
||||
@ptrToInt(local),
|
||||
local_count,
|
||||
@ptrToInt(remote),
|
||||
remote_count,
|
||||
@ptrToInt(local.ptr),
|
||||
local.len,
|
||||
@ptrToInt(remote.ptr),
|
||||
remote.len,
|
||||
flags,
|
||||
);
|
||||
}
|
||||
|
||||
pub fn process_vm_writev(pid: pid_t, local: [*]const iovec, local_count: usize, remote: [*]const iovec, remote_count: usize, flags: usize) usize {
|
||||
pub fn process_vm_writev(pid: pid_t, local: []const iovec_const, remote: []const iovec_const, flags: usize) usize {
|
||||
return syscall6(
|
||||
.process_vm_writev,
|
||||
@bitCast(usize, @as(isize, pid)),
|
||||
@ptrToInt(local),
|
||||
local_count,
|
||||
@ptrToInt(remote),
|
||||
remote_count,
|
||||
@ptrToInt(local.ptr),
|
||||
local.len,
|
||||
@ptrToInt(remote.ptr),
|
||||
remote.len,
|
||||
flags,
|
||||
);
|
||||
}
|
||||
|
||||
@ -467,7 +467,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {
|
||||
.p_paddr = entry_addr,
|
||||
.p_memsz = file_size,
|
||||
.p_align = p_align,
|
||||
.p_flags = elf.PF_X | elf.PF_R,
|
||||
.p_flags = elf.PF_X | elf.PF_R | elf.PF_W,
|
||||
});
|
||||
self.entry_addr = null;
|
||||
self.phdr_table_dirty = true;
|
||||
@ -493,7 +493,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {
|
||||
.p_paddr = got_addr,
|
||||
.p_memsz = file_size,
|
||||
.p_align = p_align,
|
||||
.p_flags = elf.PF_R,
|
||||
.p_flags = elf.PF_R | elf.PF_W,
|
||||
});
|
||||
self.phdr_table_dirty = true;
|
||||
}
|
||||
@ -516,7 +516,7 @@ pub fn populateMissingMetadata(self: *Elf) !void {
|
||||
.p_paddr = rodata_addr,
|
||||
.p_memsz = file_size,
|
||||
.p_align = p_align,
|
||||
.p_flags = elf.PF_R,
|
||||
.p_flags = elf.PF_R | elf.PF_W,
|
||||
});
|
||||
self.phdr_table_dirty = true;
|
||||
}
|
||||
@ -2451,6 +2451,23 @@ fn updateDeclCode(self: *Elf, decl_index: Module.Decl.Index, code: []const u8, s
|
||||
const phdr_index = self.sections.items(.phdr_index)[shdr_index];
|
||||
const section_offset = local_sym.st_value - self.program_headers.items[phdr_index].p_vaddr;
|
||||
const file_offset = self.sections.items(.shdr)[shdr_index].sh_offset + section_offset;
|
||||
|
||||
if (self.base.child_pid) |pid| {
|
||||
var code_vec: [1]std.os.iovec_const = .{.{
|
||||
.iov_base = code.ptr,
|
||||
.iov_len = code.len,
|
||||
}};
|
||||
var remote_vec: [1]std.os.iovec_const = .{.{
|
||||
.iov_base = @intToPtr([*]u8, local_sym.st_value),
|
||||
.iov_len = code.len,
|
||||
}};
|
||||
const rc = std.os.linux.process_vm_writev(pid, &code_vec, &remote_vec, 0);
|
||||
switch (std.os.errno(rc)) {
|
||||
.SUCCESS => assert(rc == code.len),
|
||||
else => |errno| log.warn("process_vm_writev failure: {s}", .{@tagName(errno)}),
|
||||
}
|
||||
}
|
||||
|
||||
try self.base.file.?.pwriteAll(code, file_offset);
|
||||
|
||||
return local_sym;
|
||||
@ -2820,6 +2837,8 @@ fn writeOffsetTableEntry(self: *Elf, index: usize) !void {
|
||||
const endian = self.base.options.target.cpu.arch.endian();
|
||||
const shdr = &self.sections.items(.shdr)[self.got_section_index.?];
|
||||
const off = shdr.sh_offset + @as(u64, entry_size) * index;
|
||||
const phdr = &self.program_headers.items[self.phdr_got_index.?];
|
||||
const vaddr = phdr.p_vaddr + @as(u64, entry_size) * index;
|
||||
switch (entry_size) {
|
||||
2 => {
|
||||
var buf: [2]u8 = undefined;
|
||||
@ -2835,6 +2854,22 @@ fn writeOffsetTableEntry(self: *Elf, index: usize) !void {
|
||||
var buf: [8]u8 = undefined;
|
||||
mem.writeInt(u64, &buf, self.offset_table.items[index], endian);
|
||||
try self.base.file.?.pwriteAll(&buf, off);
|
||||
|
||||
if (self.base.child_pid) |pid| {
|
||||
var local_vec: [1]std.os.iovec_const = .{.{
|
||||
.iov_base = &buf,
|
||||
.iov_len = buf.len,
|
||||
}};
|
||||
var remote_vec: [1]std.os.iovec_const = .{.{
|
||||
.iov_base = @intToPtr([*]u8, vaddr),
|
||||
.iov_len = buf.len,
|
||||
}};
|
||||
const rc = std.os.linux.process_vm_writev(pid, &local_vec, &remote_vec, 0);
|
||||
switch (std.os.errno(rc)) {
|
||||
.SUCCESS => assert(rc == buf.len),
|
||||
else => |errno| log.warn("process_vm_writev failure: {s}", .{@tagName(errno)}),
|
||||
}
|
||||
}
|
||||
},
|
||||
else => unreachable,
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user