| ... | ... | @@ -55,10 +55,10 @@ debug_str_section_zig_size: u64 = 0, |
| 55 | 55 | debug_aranges_section_zig_size: u64 = 0, |
| 56 | 56 | debug_line_section_zig_size: u64 = 0, |
| 57 | 57 | |
| 58 | | /// Function offset table containing pointers to Zig generated functions. |
| 58 | /// Function jump table containing trampolines to Zcu functions. |
| 59 | 59 | /// The table is used for Zig's incremental compilation and is embedded with |
| 60 | 60 | /// the machine code section. |
| 61 | | offset_table: ?OffsetTable = null, |
| 61 | jump_table: ?JumpTable = null, |
| 62 | 62 | |
| 63 | 63 | pub const global_symbol_bit: u32 = 0x80000000; |
| 64 | 64 | pub const symbol_mask: u32 = 0x7fffffff; |
| ... | ... | @@ -128,8 +128,8 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void { |
| 128 | 128 | dw.deinit(); |
| 129 | 129 | } |
| 130 | 130 | |
| 131 | | if (self.offset_table) |*ot| { |
| 132 | | ot.deinit(allocator); |
| 131 | if (self.jump_table) |*jt| { |
| 132 | jt.deinit(allocator); |
| 133 | 133 | } |
| 134 | 134 | } |
| 135 | 135 | |
| ... | ... | @@ -917,8 +917,8 @@ fn updateNavCode( |
| 917 | 917 | |
| 918 | 918 | if (stt_bits == elf.STT_FUNC) { |
| 919 | 919 | const extra = sym.extra(elf_file); |
| 920 | | const offset_table = self.offsetTablePtr().?; |
| 921 | | offset_table.entries.items(.dirty)[extra.zig_offset_table] = true; |
| 920 | const jump_table = self.jumpTablePtr().?; |
| 921 | jump_table.entries.items(.dirty)[extra.zig_jump_table] = true; |
| 922 | 922 | } |
| 923 | 923 | } |
| 924 | 924 | } else if (code.len < old_size) { |
| ... | ... | @@ -1036,7 +1036,7 @@ pub fn updateFunc( |
| 1036 | 1036 | const ip = &zcu.intern_pool; |
| 1037 | 1037 | const gpa = elf_file.base.comp.gpa; |
| 1038 | 1038 | const func = zcu.funcInfo(func_index); |
| 1039 | | const offset_table = self.offsetTablePtr() orelse try self.initOffsetTable(gpa, elf_file); |
| 1039 | const jump_table = self.jumpTablePtr() orelse try self.initJumpTable(gpa, elf_file); |
| 1040 | 1040 | |
| 1041 | 1041 | log.debug("updateFunc {}({d})", .{ ip.getNav(func.owner_nav).fqn.fmt(ip), func.owner_nav }); |
| 1042 | 1042 | |
| ... | ... | @@ -1045,16 +1045,16 @@ pub fn updateFunc( |
| 1045 | 1045 | |
| 1046 | 1046 | { |
| 1047 | 1047 | const sym = self.symbol(sym_index); |
| 1048 | | if (!sym.flags.zig_offset_table) { |
| 1049 | | const index = try offset_table.addSymbol(gpa, sym_index); |
| 1050 | | sym.flags.zig_offset_table = true; |
| 1051 | | sym.addExtra(.{ .zig_offset_table = index }, elf_file); |
| 1052 | | try offset_table.updateSize(self, elf_file); |
| 1053 | | const old_vaddr = offset_table.address(self, elf_file); |
| 1054 | | try self.symbol(offset_table.sym_index).atom(elf_file).?.allocate(elf_file); |
| 1055 | | const new_vaddr = offset_table.address(self, elf_file); |
| 1048 | if (!sym.flags.zig_jump_table) { |
| 1049 | const index = try jump_table.addSymbol(gpa, sym_index); |
| 1050 | sym.flags.zig_jump_table = true; |
| 1051 | sym.addExtra(.{ .zig_jump_table = index }, elf_file); |
| 1052 | try jump_table.updateSize(self, elf_file); |
| 1053 | const old_vaddr = jump_table.address(self, elf_file); |
| 1054 | try self.symbol(jump_table.sym_index).atom(elf_file).?.allocate(elf_file); |
| 1055 | const new_vaddr = jump_table.address(self, elf_file); |
| 1056 | 1056 | if (old_vaddr != new_vaddr) { |
| 1057 | | offset_table.dirty = true; |
| 1057 | jump_table.dirty = true; |
| 1058 | 1058 | } |
| 1059 | 1059 | } |
| 1060 | 1060 | } |
| ... | ... | @@ -1100,21 +1100,21 @@ pub fn updateFunc( |
| 1100 | 1100 | |
| 1101 | 1101 | // Exports will be updated by `Zcu.processExports` after the update. |
| 1102 | 1102 | |
| 1103 | | if (offset_table.dirty) { |
| 1103 | if (jump_table.dirty) { |
| 1104 | 1104 | // TODO write in bulk |
| 1105 | | for (offset_table.entries.items(.dirty), 0..) |*dirty, i| { |
| 1106 | | try offset_table.writeEntry(@intCast(i), self, elf_file); |
| 1105 | for (jump_table.entries.items(.dirty), 0..) |*dirty, i| { |
| 1106 | try jump_table.writeEntry(@intCast(i), self, elf_file); |
| 1107 | 1107 | dirty.* = false; |
| 1108 | 1108 | } |
| 1109 | 1109 | } else { |
| 1110 | 1110 | const sym = self.symbol(sym_index); |
| 1111 | | const ot_index = sym.extra(elf_file).zig_offset_table; |
| 1112 | | var ot_entry = offset_table.entries.get(ot_index); |
| 1113 | | if (ot_entry.dirty) { |
| 1114 | | try offset_table.writeEntry(ot_index, self, elf_file); |
| 1115 | | ot_entry.dirty = false; |
| 1111 | const jt_index = sym.extra(elf_file).zig_jump_table; |
| 1112 | var jt_entry = jump_table.entries.get(jt_index); |
| 1113 | if (jt_entry.dirty) { |
| 1114 | try jump_table.writeEntry(jt_index, self, elf_file); |
| 1115 | jt_entry.dirty = false; |
| 1116 | 1116 | } |
| 1117 | | offset_table.entries.set(ot_index, ot_entry); |
| 1117 | jump_table.entries.set(jt_index, jt_entry); |
| 1118 | 1118 | } |
| 1119 | 1119 | } |
| 1120 | 1120 | |
| ... | ... | @@ -1470,22 +1470,22 @@ pub fn getGlobalSymbol(self: *ZigObject, elf_file: *Elf, name: []const u8, lib_n |
| 1470 | 1470 | return lookup_gop.value_ptr.*; |
| 1471 | 1471 | } |
| 1472 | 1472 | |
| 1473 | | pub fn offsetTablePtr(self: *ZigObject) ?*OffsetTable { |
| 1474 | | return if (self.offset_table) |*ot| ot else null; |
| 1473 | pub fn jumpTablePtr(self: *ZigObject) ?*JumpTable { |
| 1474 | return if (self.jump_table) |*jt| jt else null; |
| 1475 | 1475 | } |
| 1476 | 1476 | |
| 1477 | | fn initOffsetTable(self: *ZigObject, allocator: Allocator, elf_file: *Elf) error{OutOfMemory}!*OffsetTable { |
| 1478 | | const name_off = try self.addString(allocator, "__zig_offset_table"); |
| 1477 | fn initJumpTable(self: *ZigObject, allocator: Allocator, elf_file: *Elf) error{OutOfMemory}!*JumpTable { |
| 1478 | const name_off = try self.addString(allocator, "__zig_jump_table"); |
| 1479 | 1479 | const sym_index = try self.newSymbolWithAtom(allocator, name_off); |
| 1480 | 1480 | const sym = self.symbol(sym_index); |
| 1481 | 1481 | const esym = &self.symtab.items(.elf_sym)[sym.esym_index]; |
| 1482 | 1482 | esym.st_info |= elf.STT_OBJECT; |
| 1483 | 1483 | const atom_ptr = sym.atom(elf_file).?; |
| 1484 | 1484 | atom_ptr.alive = true; |
| 1485 | | atom_ptr.alignment = Atom.Alignment.fromNonzeroByteUnits(OffsetTable.alignment(elf_file.getTarget().cpu.arch)); |
| 1485 | atom_ptr.alignment = Atom.Alignment.fromNonzeroByteUnits(JumpTable.alignment(elf_file.getTarget().cpu.arch)); |
| 1486 | 1486 | atom_ptr.output_section_index = elf_file.zig_text_section_index.?; |
| 1487 | | self.offset_table = OffsetTable{ .sym_index = sym_index }; |
| 1488 | | return &(self.offset_table.?); |
| 1487 | self.jump_table = JumpTable{ .sym_index = sym_index }; |
| 1488 | return &(self.jump_table.?); |
| 1489 | 1489 | } |
| 1490 | 1490 | |
| 1491 | 1491 | pub fn asFile(self: *ZigObject) File { |
| ... | ... | @@ -1763,28 +1763,28 @@ const UavTable = std.AutoArrayHashMapUnmanaged(InternPool.Index, AvMetadata); |
| 1763 | 1763 | const LazySymbolTable = std.AutoArrayHashMapUnmanaged(InternPool.Index, LazySymbolMetadata); |
| 1764 | 1764 | const TlsTable = std.AutoArrayHashMapUnmanaged(Atom.Index, TlsVariable); |
| 1765 | 1765 | |
| 1766 | | pub const OffsetTable = struct { |
| 1766 | pub const JumpTable = struct { |
| 1767 | 1767 | sym_index: Symbol.Index, |
| 1768 | 1768 | entries: std.MultiArrayList(Entry) = .{}, |
| 1769 | 1769 | dirty: bool = false, |
| 1770 | 1770 | |
| 1771 | | pub fn deinit(ot: *OffsetTable, allocator: Allocator) void { |
| 1772 | | ot.entries.deinit(allocator); |
| 1771 | pub fn deinit(jt: *JumpTable, allocator: Allocator) void { |
| 1772 | jt.entries.deinit(allocator); |
| 1773 | 1773 | } |
| 1774 | 1774 | |
| 1775 | | pub fn addSymbol(ot: *OffsetTable, allocator: Allocator, sym_index: Symbol.Index) !Index { |
| 1776 | | const index: Index = @intCast(try ot.entries.addOne(allocator)); |
| 1777 | | ot.entries.set(index, .{ .sym_index = sym_index }); |
| 1775 | pub fn addSymbol(jt: *JumpTable, allocator: Allocator, sym_index: Symbol.Index) !Index { |
| 1776 | const index: Index = @intCast(try jt.entries.addOne(allocator)); |
| 1777 | jt.entries.set(index, .{ .sym_index = sym_index }); |
| 1778 | 1778 | return index; |
| 1779 | 1779 | } |
| 1780 | 1780 | |
| 1781 | | pub fn address(ot: OffsetTable, zo: *ZigObject, elf_file: *Elf) i64 { |
| 1782 | | const sym = zo.symbol(ot.sym_index); |
| 1781 | pub fn address(jt: JumpTable, zo: *ZigObject, elf_file: *Elf) i64 { |
| 1782 | const sym = zo.symbol(jt.sym_index); |
| 1783 | 1783 | return sym.address(.{}, elf_file); |
| 1784 | 1784 | } |
| 1785 | 1785 | |
| 1786 | | pub fn size(ot: OffsetTable, zo: *ZigObject, elf_file: *Elf) u64 { |
| 1787 | | const sym = zo.symbol(ot.sym_index); |
| 1786 | pub fn size(jt: JumpTable, zo: *ZigObject, elf_file: *Elf) u64 { |
| 1787 | const sym = zo.symbol(jt.sym_index); |
| 1788 | 1788 | return sym.atom(elf_file).?.size; |
| 1789 | 1789 | } |
| 1790 | 1790 | |
| ... | ... | @@ -1795,12 +1795,12 @@ pub const OffsetTable = struct { |
| 1795 | 1795 | }; |
| 1796 | 1796 | } |
| 1797 | 1797 | |
| 1798 | | pub fn entryAddress(ot: OffsetTable, index: Index, zo: *ZigObject, elf_file: *Elf) i64 { |
| 1799 | | return ot.address(zo, elf_file) + @as(i64, @intCast(index * entrySize(elf_file.getTarget().cpu.arch))); |
| 1798 | pub fn entryAddress(jt: JumpTable, index: Index, zo: *ZigObject, elf_file: *Elf) i64 { |
| 1799 | return jt.address(zo, elf_file) + @as(i64, @intCast(index * entrySize(elf_file.getTarget().cpu.arch))); |
| 1800 | 1800 | } |
| 1801 | 1801 | |
| 1802 | | pub fn entryOffset(ot: OffsetTable, index: Index, zo: *ZigObject, elf_file: *Elf) u64 { |
| 1803 | | const sym = zo.symbol(ot.sym_index); |
| 1802 | pub fn entryOffset(jt: JumpTable, index: Index, zo: *ZigObject, elf_file: *Elf) u64 { |
| 1803 | const sym = zo.symbol(jt.sym_index); |
| 1804 | 1804 | const atom_ptr = sym.atom(elf_file).?; |
| 1805 | 1805 | const shdr = elf_file.shdrs.items[atom_ptr.output_section_index]; |
| 1806 | 1806 | return shdr.sh_offset + @as(u64, @intCast(atom_ptr.value)) + index * entrySize(elf_file.getTarget().cpu.arch); |
| ... | ... | @@ -1815,17 +1815,17 @@ pub const OffsetTable = struct { |
| 1815 | 1815 | return seq_len; |
| 1816 | 1816 | } |
| 1817 | 1817 | |
| 1818 | | pub fn targetAddress(ot: OffsetTable, index: Index, zo: *ZigObject, elf_file: *Elf) i64 { |
| 1819 | | const sym_index = ot.entries.items(.sym_index)[index]; |
| 1818 | pub fn targetAddress(jt: JumpTable, index: Index, zo: *ZigObject, elf_file: *Elf) i64 { |
| 1819 | const sym_index = jt.entries.items(.sym_index)[index]; |
| 1820 | 1820 | return zo.symbol(sym_index).address(.{}, elf_file); |
| 1821 | 1821 | } |
| 1822 | 1822 | |
| 1823 | 1823 | const max_jump_seq_len = 12; |
| 1824 | 1824 | |
| 1825 | | pub fn writeEntry(ot: OffsetTable, index: Index, zo: *ZigObject, elf_file: *Elf) !void { |
| 1826 | | const fileoff = ot.entryOffset(index, zo, elf_file); |
| 1827 | | const source_addr = ot.entryAddress(index, zo, elf_file); |
| 1828 | | const target_addr = @as(i64, @intCast(ot.targetAddress(index, zo, elf_file))); |
| 1825 | pub fn writeEntry(jt: JumpTable, index: Index, zo: *ZigObject, elf_file: *Elf) !void { |
| 1826 | const fileoff = jt.entryOffset(index, zo, elf_file); |
| 1827 | const source_addr = jt.entryAddress(index, zo, elf_file); |
| 1828 | const target_addr = @as(i64, @intCast(jt.targetAddress(index, zo, elf_file))); |
| 1829 | 1829 | var buf: [max_jump_seq_len]u8 = undefined; |
| 1830 | 1830 | const out = switch (elf_file.getTarget().cpu.arch) { |
| 1831 | 1831 | .x86_64 => try x86_64.writeEntry(source_addr, target_addr, &buf), |
| ... | ... | @@ -1855,46 +1855,46 @@ pub const OffsetTable = struct { |
| 1855 | 1855 | } |
| 1856 | 1856 | } |
| 1857 | 1857 | |
| 1858 | | pub fn updateSize(ot: OffsetTable, zo: *ZigObject, elf_file: *Elf) !void { |
| 1859 | | const ot_size: u64 = @intCast(ot.entries.items(.sym_index).len * entrySize(elf_file.getTarget().cpu.arch)); |
| 1860 | | const sym = zo.symbol(ot.sym_index); |
| 1858 | pub fn updateSize(jt: JumpTable, zo: *ZigObject, elf_file: *Elf) !void { |
| 1859 | const jt_size: u64 = @intCast(jt.entries.items(.sym_index).len * entrySize(elf_file.getTarget().cpu.arch)); |
| 1860 | const sym = zo.symbol(jt.sym_index); |
| 1861 | 1861 | const esym = &zo.symtab.items(.elf_sym)[sym.esym_index]; |
| 1862 | | esym.st_size = ot_size; |
| 1862 | esym.st_size = jt_size; |
| 1863 | 1863 | const atom_ptr = sym.atom(elf_file).?; |
| 1864 | | atom_ptr.size = ot_size; |
| 1864 | atom_ptr.size = jt_size; |
| 1865 | 1865 | } |
| 1866 | 1866 | |
| 1867 | | const OffsetTableFormatContext = struct { OffsetTable, *ZigObject, *Elf }; |
| 1867 | const JumpTableFormatContext = struct { JumpTable, *ZigObject, *Elf }; |
| 1868 | 1868 | |
| 1869 | 1869 | pub fn format( |
| 1870 | | ot: OffsetTable, |
| 1870 | jt: JumpTable, |
| 1871 | 1871 | comptime unused_fmt_string: []const u8, |
| 1872 | 1872 | options: std.fmt.FormatOptions, |
| 1873 | 1873 | writer: anytype, |
| 1874 | 1874 | ) !void { |
| 1875 | | _ = ot; |
| 1875 | _ = jt; |
| 1876 | 1876 | _ = unused_fmt_string; |
| 1877 | 1877 | _ = options; |
| 1878 | 1878 | _ = writer; |
| 1879 | | @compileError("do not format OffsetTable directly"); |
| 1879 | @compileError("do not format JumpTable directly"); |
| 1880 | 1880 | } |
| 1881 | 1881 | |
| 1882 | | pub fn fmt(ot: OffsetTable, zo: *ZigObject, elf_file: *Elf) std.fmt.Formatter(format2) { |
| 1883 | | return .{ .data = .{ ot, zo, elf_file } }; |
| 1882 | pub fn fmt(jt: JumpTable, zo: *ZigObject, elf_file: *Elf) std.fmt.Formatter(format2) { |
| 1883 | return .{ .data = .{ jt, zo, elf_file } }; |
| 1884 | 1884 | } |
| 1885 | 1885 | |
| 1886 | 1886 | fn format2( |
| 1887 | | ctx: OffsetTableFormatContext, |
| 1887 | ctx: JumpTableFormatContext, |
| 1888 | 1888 | comptime unused_fmt_string: []const u8, |
| 1889 | 1889 | options: std.fmt.FormatOptions, |
| 1890 | 1890 | writer: anytype, |
| 1891 | 1891 | ) !void { |
| 1892 | 1892 | _ = options; |
| 1893 | 1893 | _ = unused_fmt_string; |
| 1894 | | const ot, const zo, const ef = ctx; |
| 1895 | | try writer.writeAll("offset table\n"); |
| 1896 | | try writer.print(" @{x} : size({x})\n", .{ ot.address(zo, ef), ot.size(zo, ef) }); |
| 1897 | | for (ot.entries.items(.sym_index), ot.entries.items(.dirty)) |sym_index, dirty| { |
| 1894 | const jt, const zo, const ef = ctx; |
| 1895 | try writer.writeAll("__zig_jump_table\n"); |
| 1896 | try writer.print(" @{x} : size({x})\n", .{ jt.address(zo, ef), jt.size(zo, ef) }); |
| 1897 | for (jt.entries.items(.sym_index), jt.entries.items(.dirty)) |sym_index, dirty| { |
| 1898 | 1898 | const sym = zo.symbol(sym_index); |
| 1899 | 1899 | try writer.print(" %{d} : {s} : @{x}", .{ sym_index, sym.name(ef), sym.address(.{}, ef) }); |
| 1900 | 1900 | if (dirty) try writer.writeAll(" : [!]"); |