Commit 24b915c9f2
Changed files (1)
src
link
src/link/Elf/ZigObject.zig
@@ -1101,6 +1101,17 @@ pub fn updateFunc(
}
// Exports will be updated by `Zcu.processExports` after the update.
+
+ {
+ const sym = self.symbol(sym_index);
+ const ot_index = sym.extra(elf_file).zig_offset_table;
+ var ot_entry = offset_table.entries.get(ot_index);
+ if (ot_entry.dirty) {
+ try offset_table.writeEntry(ot_index, self, elf_file);
+ ot_entry.dirty = false;
+ }
+ offset_table.entries.set(ot_index, ot_entry);
+ }
}
pub fn updateNav(
@@ -1731,15 +1742,15 @@ const TlsTable = std.AutoArrayHashMapUnmanaged(Atom.Index, TlsVariable);
pub const OffsetTable = struct {
sym_index: Symbol.Index,
- entries: std.ArrayListUnmanaged(Symbol.Index) = .{},
+ entries: std.MultiArrayList(Entry) = .{},
pub fn deinit(ot: *OffsetTable, allocator: Allocator) void {
ot.entries.deinit(allocator);
}
pub fn addSymbol(ot: *OffsetTable, allocator: Allocator, sym_index: Symbol.Index) !Index {
- const index: Index = @intCast(ot.entries.items.len);
- try ot.entries.append(allocator, sym_index);
+ const index: Index = @intCast(try ot.entries.addOne(allocator));
+ ot.entries.set(index, .{ .sym_index = sym_index });
return index;
}
@@ -1753,11 +1764,72 @@ pub const OffsetTable = struct {
return sym.atom(elf_file).?.size;
}
+ pub fn entryAddress(ot: OffsetTable, index: Index, zo: *ZigObject, elf_file: *Elf) i64 {
+ return ot.address(zo, elf_file) + index * elf_file.archPtrWidthBytes();
+ }
+
+ pub fn entryOffset(ot: OffsetTable, index: Index, zo: *ZigObject, elf_file: *Elf) u64 {
+ const sym = zo.symbol(ot.sym_index);
+ const atom_ptr = sym.atom(elf_file).?;
+ const shdr = elf_file.shdrs.items[atom_ptr.output_section_index];
+ return shdr.sh_offset + @as(u64, @intCast(atom_ptr.value)) + index * elf_file.archPtrWidthBytes();
+ }
+
+ pub fn targetAddress(ot: OffsetTable, index: Index, zo: *ZigObject, elf_file: *Elf) i64 {
+ const sym_index = ot.entries.items(.sym_index)[index];
+ return zo.symbol(sym_index).address(.{}, elf_file);
+ }
+
+ pub fn writeEntry(ot: OffsetTable, index: Index, zo: *ZigObject, elf_file: *Elf) !void {
+ const entry_size: u16 = elf_file.archPtrWidthBytes();
+ const target = elf_file.getTarget();
+ const endian = target.cpu.arch.endian();
+ const fileoff = ot.entryOffset(index, zo, elf_file);
+ const vaddr: u64 = @intCast(ot.entryAddress(index, zo, elf_file));
+ const value = ot.targetAddress(index, zo, elf_file);
+ switch (entry_size) {
+ 2 => {
+ var buf: [2]u8 = undefined;
+ std.mem.writeInt(u16, &buf, @intCast(value), endian);
+ try elf_file.base.file.?.pwriteAll(&buf, fileoff);
+ },
+ 4 => {
+ var buf: [4]u8 = undefined;
+ std.mem.writeInt(u32, &buf, @intCast(value), endian);
+ try elf_file.base.file.?.pwriteAll(&buf, fileoff);
+ },
+ 8 => {
+ var buf: [8]u8 = undefined;
+ std.mem.writeInt(u64, &buf, @intCast(value), endian);
+ try elf_file.base.file.?.pwriteAll(&buf, fileoff);
+
+ if (elf_file.base.child_pid) |pid| {
+ switch (builtin.os.tag) {
+ .linux => {
+ var local_vec: [1]std.posix.iovec_const = .{.{
+ .base = &buf,
+ .len = buf.len,
+ }};
+ var remote_vec: [1]std.posix.iovec_const = .{.{
+ .base = @as([*]u8, @ptrFromInt(@as(usize, @intCast(vaddr)))),
+ .len = buf.len,
+ }};
+ const rc = std.os.linux.process_vm_writev(pid, &local_vec, &remote_vec, 0);
+ switch (std.os.linux.E.init(rc)) {
+ .SUCCESS => assert(rc == buf.len),
+ else => |errno| log.warn("process_vm_writev failure: {s}", .{@tagName(errno)}),
+ }
+ },
+ else => return error.HotSwapUnavailableOnHostOperatingSystem,
+ }
+ }
+ },
+ else => unreachable,
+ }
+ }
+
pub fn updateSize(ot: OffsetTable, zo: *ZigObject, elf_file: *Elf) !void {
- const ot_size: u64 = @intCast(ot.entries.items.len * switch (elf_file.ptr_width) {
- .p32 => @as(u64, 4),
- .p64 => 8,
- });
+ const ot_size: u64 = @intCast(ot.entries.items(.sym_index).len * elf_file.archPtrWidthBytes());
const sym = zo.symbol(ot.sym_index);
const esym = &zo.symtab.items(.elf_sym)[sym.esym_index];
esym.st_size = ot_size;
@@ -1795,12 +1867,19 @@ pub const OffsetTable = struct {
const ot, const zo, const ef = ctx;
try writer.writeAll("offset table\n");
try writer.print(" @{x} : size({x})\n", .{ ot.address(zo, ef), ot.size(zo, ef) });
- for (ot.entries.items) |sym_index| {
+ for (ot.entries.items(.sym_index), ot.entries.items(.dirty)) |sym_index, dirty| {
const sym = zo.symbol(sym_index);
- try writer.print(" %{d} : {s} : @{x}\n", .{ sym_index, sym.name(ef), sym.address(.{}, ef) });
+ try writer.print(" %{d} : {s} : @{x}", .{ sym_index, sym.name(ef), sym.address(.{}, ef) });
+ if (dirty) try writer.writeAll(" : [!]");
+ try writer.writeByte('\n');
}
}
+ const Entry = struct {
+ sym_index: Symbol.Index,
+ dirty: bool = true,
+ };
+
pub const Index = u32;
};