authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-08-08 21:40:17+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-08-13 13:30:24+02:00
log24b915c9f218d48fa32bf0e8c0a02d274be5ca21
tree26d1118e557fd443097981e2f602eefcc36f349d
parent67e703dc71a30989f9caaa3fa13e141d1e9584c3

elf: write offset table entry if dirty


1 files changed, 88 insertions(+), 9 deletions(-)

src/link/Elf/ZigObject.zig+88-9
...@@ -1101,6 +1101,17 @@ pub fn updateFunc(...@@ -1101,6 +1101,17 @@ pub fn updateFunc(
1101 }1101 }
11021102
1103 // Exports will be updated by `Zcu.processExports` after the update.1103 // Exports will be updated by `Zcu.processExports` after the update.
1104
1105 {
1106 const sym = self.symbol(sym_index);
1107 const ot_index = sym.extra(elf_file).zig_offset_table;
1108 var ot_entry = offset_table.entries.get(ot_index);
1109 if (ot_entry.dirty) {
1110 try offset_table.writeEntry(ot_index, self, elf_file);
1111 ot_entry.dirty = false;
1112 }
1113 offset_table.entries.set(ot_index, ot_entry);
1114 }
1104}1115}
11051116
1106pub fn updateNav(1117pub fn updateNav(
...@@ -1731,15 +1742,15 @@ const TlsTable = std.AutoArrayHashMapUnmanaged(Atom.Index, TlsVariable);...@@ -1731,15 +1742,15 @@ const TlsTable = std.AutoArrayHashMapUnmanaged(Atom.Index, TlsVariable);
17311742
1732pub const OffsetTable = struct {1743pub const OffsetTable = struct {
1733 sym_index: Symbol.Index,1744 sym_index: Symbol.Index,
1734 entries: std.ArrayListUnmanaged(Symbol.Index) = .{},1745 entries: std.MultiArrayList(Entry) = .{},
17351746
1736 pub fn deinit(ot: *OffsetTable, allocator: Allocator) void {1747 pub fn deinit(ot: *OffsetTable, allocator: Allocator) void {
1737 ot.entries.deinit(allocator);1748 ot.entries.deinit(allocator);
1738 }1749 }
17391750
1740 pub fn addSymbol(ot: *OffsetTable, allocator: Allocator, sym_index: Symbol.Index) !Index {1751 pub fn addSymbol(ot: *OffsetTable, allocator: Allocator, sym_index: Symbol.Index) !Index {
1741 const index: Index = @intCast(ot.entries.items.len);1752 const index: Index = @intCast(try ot.entries.addOne(allocator));
1742 try ot.entries.append(allocator, sym_index);1753 ot.entries.set(index, .{ .sym_index = sym_index });
1743 return index;1754 return index;
1744 }1755 }
17451756
...@@ -1753,11 +1764,72 @@ pub const OffsetTable = struct {...@@ -1753,11 +1764,72 @@ pub const OffsetTable = struct {
1753 return sym.atom(elf_file).?.size;1764 return sym.atom(elf_file).?.size;
1754 }1765 }
17551766
1767 pub fn entryAddress(ot: OffsetTable, index: Index, zo: *ZigObject, elf_file: *Elf) i64 {
1768 return ot.address(zo, elf_file) + index * elf_file.archPtrWidthBytes();
1769 }
1770
1771 pub fn entryOffset(ot: OffsetTable, index: Index, zo: *ZigObject, elf_file: *Elf) u64 {
1772 const sym = zo.symbol(ot.sym_index);
1773 const atom_ptr = sym.atom(elf_file).?;
1774 const shdr = elf_file.shdrs.items[atom_ptr.output_section_index];
1775 return shdr.sh_offset + @as(u64, @intCast(atom_ptr.value)) + index * elf_file.archPtrWidthBytes();
1776 }
1777
1778 pub fn targetAddress(ot: OffsetTable, index: Index, zo: *ZigObject, elf_file: *Elf) i64 {
1779 const sym_index = ot.entries.items(.sym_index)[index];
1780 return zo.symbol(sym_index).address(.{}, elf_file);
1781 }
1782
1783 pub fn writeEntry(ot: OffsetTable, index: Index, zo: *ZigObject, elf_file: *Elf) !void {
1784 const entry_size: u16 = elf_file.archPtrWidthBytes();
1785 const target = elf_file.getTarget();
1786 const endian = target.cpu.arch.endian();
1787 const fileoff = ot.entryOffset(index, zo, elf_file);
1788 const vaddr: u64 = @intCast(ot.entryAddress(index, zo, elf_file));
1789 const value = ot.targetAddress(index, zo, elf_file);
1790 switch (entry_size) {
1791 2 => {
1792 var buf: [2]u8 = undefined;
1793 std.mem.writeInt(u16, &buf, @intCast(value), endian);
1794 try elf_file.base.file.?.pwriteAll(&buf, fileoff);
1795 },
1796 4 => {
1797 var buf: [4]u8 = undefined;
1798 std.mem.writeInt(u32, &buf, @intCast(value), endian);
1799 try elf_file.base.file.?.pwriteAll(&buf, fileoff);
1800 },
1801 8 => {
1802 var buf: [8]u8 = undefined;
1803 std.mem.writeInt(u64, &buf, @intCast(value), endian);
1804 try elf_file.base.file.?.pwriteAll(&buf, fileoff);
1805
1806 if (elf_file.base.child_pid) |pid| {
1807 switch (builtin.os.tag) {
1808 .linux => {
1809 var local_vec: [1]std.posix.iovec_const = .{.{
1810 .base = &buf,
1811 .len = buf.len,
1812 }};
1813 var remote_vec: [1]std.posix.iovec_const = .{.{
1814 .base = @as([*]u8, @ptrFromInt(@as(usize, @intCast(vaddr)))),
1815 .len = buf.len,
1816 }};
1817 const rc = std.os.linux.process_vm_writev(pid, &local_vec, &remote_vec, 0);
1818 switch (std.os.linux.E.init(rc)) {
1819 .SUCCESS => assert(rc == buf.len),
1820 else => |errno| log.warn("process_vm_writev failure: {s}", .{@tagName(errno)}),
1821 }
1822 },
1823 else => return error.HotSwapUnavailableOnHostOperatingSystem,
1824 }
1825 }
1826 },
1827 else => unreachable,
1828 }
1829 }
1830
1756 pub fn updateSize(ot: OffsetTable, zo: *ZigObject, elf_file: *Elf) !void {1831 pub fn updateSize(ot: OffsetTable, zo: *ZigObject, elf_file: *Elf) !void {
1757 const ot_size: u64 = @intCast(ot.entries.items.len * switch (elf_file.ptr_width) {1832 const ot_size: u64 = @intCast(ot.entries.items(.sym_index).len * elf_file.archPtrWidthBytes());
1758 .p32 => @as(u64, 4),
1759 .p64 => 8,
1760 });
1761 const sym = zo.symbol(ot.sym_index);1833 const sym = zo.symbol(ot.sym_index);
1762 const esym = &zo.symtab.items(.elf_sym)[sym.esym_index];1834 const esym = &zo.symtab.items(.elf_sym)[sym.esym_index];
1763 esym.st_size = ot_size;1835 esym.st_size = ot_size;
...@@ -1795,12 +1867,19 @@ pub const OffsetTable = struct {...@@ -1795,12 +1867,19 @@ pub const OffsetTable = struct {
1795 const ot, const zo, const ef = ctx;1867 const ot, const zo, const ef = ctx;
1796 try writer.writeAll("offset table\n");1868 try writer.writeAll("offset table\n");
1797 try writer.print(" @{x} : size({x})\n", .{ ot.address(zo, ef), ot.size(zo, ef) });1869 try writer.print(" @{x} : size({x})\n", .{ ot.address(zo, ef), ot.size(zo, ef) });
1798 for (ot.entries.items) |sym_index| {1870 for (ot.entries.items(.sym_index), ot.entries.items(.dirty)) |sym_index, dirty| {
1799 const sym = zo.symbol(sym_index);1871 const sym = zo.symbol(sym_index);
1800 try writer.print(" %{d} : {s} : @{x}\n", .{ sym_index, sym.name(ef), sym.address(.{}, ef) });1872 try writer.print(" %{d} : {s} : @{x}", .{ sym_index, sym.name(ef), sym.address(.{}, ef) });
1873 if (dirty) try writer.writeAll(" : [!]");
1874 try writer.writeByte('\n');
1801 }1875 }
1802 }1876 }
18031877
1878 const Entry = struct {
1879 sym_index: Symbol.Index,
1880 dirty: bool = true,
1881 };
1882
1804 pub const Index = u32;1883 pub const Index = u32;
1805};1884};
18061885