| ... | @@ -1101,6 +1101,17 @@ pub fn updateFunc( | ... | @@ -1101,6 +1101,17 @@ pub fn updateFunc( |
| 1101 | } | 1101 | } |
| 1102 | | 1102 | |
| 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 | } |
| 1105 | | 1116 | |
| 1106 | pub fn updateNav( | 1117 | pub fn updateNav( |
| ... | @@ -1731,15 +1742,15 @@ const TlsTable = std.AutoArrayHashMapUnmanaged(Atom.Index, TlsVariable); | ... | @@ -1731,15 +1742,15 @@ const TlsTable = std.AutoArrayHashMapUnmanaged(Atom.Index, TlsVariable); |
| 1731 | | 1742 | |
| 1732 | pub const OffsetTable = struct { | 1743 | pub const OffsetTable = struct { |
| 1733 | sym_index: Symbol.Index, | 1744 | sym_index: Symbol.Index, |
| 1734 | entries: std.ArrayListUnmanaged(Symbol.Index) = .{}, | 1745 | entries: std.MultiArrayList(Entry) = .{}, |
| 1735 | | 1746 | |
| 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 | } |
| 1739 | | 1750 | |
| 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 | } |
| 1745 | | 1756 | |
| ... | @@ -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 | } |
| 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 | 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 | } |
| 1803 | | 1877 | |
| | 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 | }; |
| 1806 | | 1885 | |