| ... | @@ -55,7 +55,10 @@ debug_str_section_zig_size: u64 = 0, | ... | @@ -55,7 +55,10 @@ debug_str_section_zig_size: u64 = 0, |
| 55 | debug_aranges_section_zig_size: u64 = 0, | 55 | debug_aranges_section_zig_size: u64 = 0, |
| 56 | debug_line_section_zig_size: u64 = 0, | 56 | debug_line_section_zig_size: u64 = 0, |
| 57 | | 57 | |
| 58 | func_offset_table: ?OffsetTable = null, | 58 | /// Function offset table containing pointers to Zig generated functions. |
| | 59 | /// The table is used for Zig's incremental compilation and is embedded with |
| | 60 | /// the machine code section. |
| | 61 | offset_table: ?OffsetTable = null, |
| 59 | | 62 | |
| 60 | pub const global_symbol_bit: u32 = 0x80000000; | 63 | pub const global_symbol_bit: u32 = 0x80000000; |
| 61 | pub const symbol_mask: u32 = 0x7fffffff; | 64 | pub const symbol_mask: u32 = 0x7fffffff; |
| ... | @@ -131,7 +134,7 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void { | ... | @@ -131,7 +134,7 @@ pub fn deinit(self: *ZigObject, allocator: Allocator) void { |
| 131 | dw.deinit(); | 134 | dw.deinit(); |
| 132 | } | 135 | } |
| 133 | | 136 | |
| 134 | if (self.func_offset_table) |*ot| { | 137 | if (self.offset_table) |*ot| { |
| 135 | ot.deinit(allocator); | 138 | ot.deinit(allocator); |
| 136 | } | 139 | } |
| 137 | } | 140 | } |
| ... | @@ -1040,12 +1043,24 @@ pub fn updateFunc( | ... | @@ -1040,12 +1043,24 @@ pub fn updateFunc( |
| 1040 | const ip = &zcu.intern_pool; | 1043 | const ip = &zcu.intern_pool; |
| 1041 | const gpa = elf_file.base.comp.gpa; | 1044 | const gpa = elf_file.base.comp.gpa; |
| 1042 | const func = zcu.funcInfo(func_index); | 1045 | const func = zcu.funcInfo(func_index); |
| | 1046 | const offset_table = self.offsetTablePtr() orelse try self.initOffsetTable(gpa, elf_file); |
| 1043 | | 1047 | |
| 1044 | log.debug("updateFunc {}({d})", .{ ip.getNav(func.owner_nav).fqn.fmt(ip), func.owner_nav }); | 1048 | log.debug("updateFunc {}({d})", .{ ip.getNav(func.owner_nav).fqn.fmt(ip), func.owner_nav }); |
| 1045 | | 1049 | |
| 1046 | const sym_index = try self.getOrCreateMetadataForNav(elf_file, func.owner_nav); | 1050 | const sym_index = try self.getOrCreateMetadataForNav(elf_file, func.owner_nav); |
| 1047 | self.symbol(sym_index).atom(elf_file).?.freeRelocs(elf_file); | 1051 | self.symbol(sym_index).atom(elf_file).?.freeRelocs(elf_file); |
| 1048 | | 1052 | |
| | 1053 | { |
| | 1054 | const sym = self.symbol(sym_index); |
| | 1055 | if (!sym.flags.zig_offset_table) { |
| | 1056 | const index = try offset_table.addSymbol(gpa, sym_index); |
| | 1057 | sym.flags.zig_offset_table = true; |
| | 1058 | sym.addExtra(.{ .zig_offset_table = index }, elf_file); |
| | 1059 | try offset_table.updateSize(self, elf_file); |
| | 1060 | try self.symbol(offset_table.sym_index).atom(elf_file).?.allocate(elf_file); |
| | 1061 | } |
| | 1062 | } |
| | 1063 | |
| 1049 | var code_buffer = std.ArrayList(u8).init(gpa); | 1064 | var code_buffer = std.ArrayList(u8).init(gpa); |
| 1050 | defer code_buffer.deinit(); | 1065 | defer code_buffer.deinit(); |
| 1051 | | 1066 | |
| ... | @@ -1446,6 +1461,27 @@ pub fn getGlobalSymbol(self: *ZigObject, elf_file: *Elf, name: []const u8, lib_n | ... | @@ -1446,6 +1461,27 @@ pub fn getGlobalSymbol(self: *ZigObject, elf_file: *Elf, name: []const u8, lib_n |
| 1446 | return lookup_gop.value_ptr.*; | 1461 | return lookup_gop.value_ptr.*; |
| 1447 | } | 1462 | } |
| 1448 | | 1463 | |
| | 1464 | fn offsetTablePtr(self: *ZigObject) ?*OffsetTable { |
| | 1465 | return if (self.offset_table) |*ot| ot else null; |
| | 1466 | } |
| | 1467 | |
| | 1468 | fn initOffsetTable(self: *ZigObject, allocator: Allocator, elf_file: *Elf) error{OutOfMemory}!*OffsetTable { |
| | 1469 | const name_off = try self.addString(allocator, "__zig_offset_table"); |
| | 1470 | const sym_index = try self.newSymbolWithAtom(allocator, name_off); |
| | 1471 | const sym = self.symbol(sym_index); |
| | 1472 | const esym = &self.symtab.items(.elf_sym)[sym.esym_index]; |
| | 1473 | esym.st_info |= elf.STT_OBJECT; |
| | 1474 | const atom_ptr = sym.atom(elf_file).?; |
| | 1475 | atom_ptr.alive = true; |
| | 1476 | atom_ptr.alignment = Atom.Alignment.fromNonzeroByteUnits(switch (elf_file.ptr_width) { |
| | 1477 | .p32 => 4, |
| | 1478 | .p64 => 8, |
| | 1479 | }); |
| | 1480 | atom_ptr.output_section_index = elf_file.zig_text_section_index.?; |
| | 1481 | self.offset_table = OffsetTable{ .sym_index = sym_index }; |
| | 1482 | return &(self.offset_table.?); |
| | 1483 | } |
| | 1484 | |
| 1449 | pub fn asFile(self: *ZigObject) File { | 1485 | pub fn asFile(self: *ZigObject) File { |
| 1450 | return .{ .zig_object = self }; | 1486 | return .{ .zig_object = self }; |
| 1451 | } | 1487 | } |
| ... | @@ -1694,18 +1730,39 @@ const LazySymbolTable = std.AutoArrayHashMapUnmanaged(InternPool.Index, LazySymb | ... | @@ -1694,18 +1730,39 @@ const LazySymbolTable = std.AutoArrayHashMapUnmanaged(InternPool.Index, LazySymb |
| 1694 | const TlsTable = std.AutoArrayHashMapUnmanaged(Atom.Index, TlsVariable); | 1730 | const TlsTable = std.AutoArrayHashMapUnmanaged(Atom.Index, TlsVariable); |
| 1695 | | 1731 | |
| 1696 | pub const OffsetTable = struct { | 1732 | pub const OffsetTable = struct { |
| 1697 | atom_index: Atom.Index, | 1733 | sym_index: Symbol.Index, |
| 1698 | entries: std.ArrayListUnmanaged(Symbol.Index) = .{}, | 1734 | entries: std.ArrayListUnmanaged(Symbol.Index) = .{}, |
| 1699 | | 1735 | |
| 1700 | pub fn deinit(ot: *OffsetTable, allocator: Allocator) void { | 1736 | pub fn deinit(ot: *OffsetTable, allocator: Allocator) void { |
| 1701 | ot.entries.deinit(allocator); | 1737 | ot.entries.deinit(allocator); |
| 1702 | } | 1738 | } |
| 1703 | | 1739 | |
| 1704 | pub fn size(ot: OffsetTable, elf_file: *Elf) usize { | 1740 | pub fn addSymbol(ot: *OffsetTable, allocator: Allocator, sym_index: Symbol.Index) !Index { |
| 1705 | return ot.entries.items.len * switch (elf_file.ptr_width) { | 1741 | const index: Index = @intCast(ot.entries.items.len); |
| 1706 | .p32 => @as(usize, 4), | 1742 | try ot.entries.append(allocator, sym_index); |
| | 1743 | return index; |
| | 1744 | } |
| | 1745 | |
| | 1746 | pub fn address(ot: OffsetTable, zo: *ZigObject, elf_file: *Elf) i64 { |
| | 1747 | const sym = zo.symbol(ot.sym_index); |
| | 1748 | return sym.address(.{}, elf_file); |
| | 1749 | } |
| | 1750 | |
| | 1751 | pub fn size(ot: OffsetTable, zo: *ZigObject, elf_file: *Elf) u64 { |
| | 1752 | const sym = zo.symbol(ot.sym_index); |
| | 1753 | return sym.atom(elf_file).?.size; |
| | 1754 | } |
| | 1755 | |
| | 1756 | 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), |
| 1707 | .p64 => 8, | 1759 | .p64 => 8, |
| 1708 | }; | 1760 | }); |
| | 1761 | const sym = zo.symbol(ot.sym_index); |
| | 1762 | const esym = &zo.symtab.items(.elf_sym)[sym.esym_index]; |
| | 1763 | esym.st_size = ot_size; |
| | 1764 | const atom_ptr = sym.atom(elf_file).?; |
| | 1765 | atom_ptr.size = ot_size; |
| 1709 | } | 1766 | } |
| 1710 | | 1767 | |
| 1711 | const OffsetTableFormatContext = struct { OffsetTable, *ZigObject, *Elf }; | 1768 | const OffsetTableFormatContext = struct { OffsetTable, *ZigObject, *Elf }; |
| ... | @@ -1736,13 +1793,15 @@ pub const OffsetTable = struct { | ... | @@ -1736,13 +1793,15 @@ pub const OffsetTable = struct { |
| 1736 | _ = options; | 1793 | _ = options; |
| 1737 | _ = unused_fmt_string; | 1794 | _ = unused_fmt_string; |
| 1738 | const ot, const zo, const ef = ctx; | 1795 | const ot, const zo, const ef = ctx; |
| 1739 | const atom_ptr = zo.atom(ot.atom_index).?; | 1796 | try writer.writeAll("offset table\n"); |
| 1740 | try writer.print("@{x} : size({x})\n", .{ atom_ptr.address(ef), ot.size(ef) }); | 1797 | try writer.print(" @{x} : size({x})\n", .{ ot.address(zo, ef), ot.size(zo, ef) }); |
| 1741 | for (ot.entries.items) |sym_index| { | 1798 | for (ot.entries.items) |sym_index| { |
| 1742 | const sym = zo.symbol(sym_index); | 1799 | const sym = zo.symbol(sym_index); |
| 1743 | try writer.print(" %{d} : {s} : @{x}\n", .{ sym_index, sym.name(ef), sym.value }); | 1800 | try writer.print(" %{d} : {s} : @{x}\n", .{ sym_index, sym.name(ef), sym.address(.{}, ef) }); |
| 1744 | } | 1801 | } |
| 1745 | } | 1802 | } |
| | 1803 | |
| | 1804 | pub const Index = u32; |
| 1746 | }; | 1805 | }; |
| 1747 | | 1806 | |
| 1748 | const assert = std.debug.assert; | 1807 | const assert = std.debug.assert; |