| ... | ... | @@ -1101,6 +1101,17 @@ pub fn updateFunc( |
| 1101 | 1101 | } |
| 1102 | 1102 | |
| 1103 | 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 | } |
| 1105 | 1116 | |
| 1106 | 1117 | pub fn updateNav( |
| ... | ... | @@ -1731,15 +1742,15 @@ const TlsTable = std.AutoArrayHashMapUnmanaged(Atom.Index, TlsVariable); |
| 1731 | 1742 | |
| 1732 | 1743 | pub const OffsetTable = struct { |
| 1733 | 1744 | sym_index: Symbol.Index, |
| 1734 | | entries: std.ArrayListUnmanaged(Symbol.Index) = .{}, |
| 1745 | entries: std.MultiArrayList(Entry) = .{}, |
| 1735 | 1746 | |
| 1736 | 1747 | pub fn deinit(ot: *OffsetTable, allocator: Allocator) void { |
| 1737 | 1748 | ot.entries.deinit(allocator); |
| 1738 | 1749 | } |
| 1739 | 1750 | |
| 1740 | 1751 | pub fn addSymbol(ot: *OffsetTable, allocator: Allocator, sym_index: Symbol.Index) !Index { |
| 1741 | | const index: Index = @intCast(ot.entries.items.len); |
| 1742 | | try ot.entries.append(allocator, sym_index); |
| 1752 | const index: Index = @intCast(try ot.entries.addOne(allocator)); |
| 1753 | ot.entries.set(index, .{ .sym_index = sym_index }); |
| 1743 | 1754 | return index; |
| 1744 | 1755 | } |
| 1745 | 1756 | |
| ... | ... | @@ -1753,11 +1764,72 @@ pub const OffsetTable = struct { |
| 1753 | 1764 | return sym.atom(elf_file).?.size; |
| 1754 | 1765 | } |
| 1755 | 1766 | |
| 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 | 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) { |
| 1758 | | .p32 => @as(u64, 4), |
| 1759 | | .p64 => 8, |
| 1760 | | }); |
| 1832 | const ot_size: u64 = @intCast(ot.entries.items(.sym_index).len * elf_file.archPtrWidthBytes()); |
| 1761 | 1833 | const sym = zo.symbol(ot.sym_index); |
| 1762 | 1834 | const esym = &zo.symtab.items(.elf_sym)[sym.esym_index]; |
| 1763 | 1835 | esym.st_size = ot_size; |
| ... | ... | @@ -1795,12 +1867,19 @@ pub const OffsetTable = struct { |
| 1795 | 1867 | const ot, const zo, const ef = ctx; |
| 1796 | 1868 | try writer.writeAll("offset table\n"); |
| 1797 | 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 | 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 | } |
| 1803 | 1877 | |
| 1878 | const Entry = struct { |
| 1879 | sym_index: Symbol.Index, |
| 1880 | dirty: bool = true, |
| 1881 | }; |
| 1882 | |
| 1804 | 1883 | pub const Index = u32; |
| 1805 | 1884 | }; |
| 1806 | 1885 | |