authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-08-08 08:30:56+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-08-13 13:30:23+02:00
log67e703dc71a30989f9caaa3fa13e141d1e9584c3
tree5f43d93c9e34e1bbc4fcbdc8fe6c9fbffa9f5fe4
parent27e1e636710ca72fb4508e2ea731dcb39cedbc95

elf: allocate new offset table via Atom.allocate mechanism


3 files changed, 75 insertions(+), 11 deletions(-)

src/link/Elf.zig+1-1
...@@ -5661,7 +5661,7 @@ fn fmtDumpState(...@@ -5661,7 +5661,7 @@ fn fmtDumpState(
5661 zig_object.fmtAtoms(self),5661 zig_object.fmtAtoms(self),
5662 zig_object.fmtSymtab(self),5662 zig_object.fmtSymtab(self),
5663 });5663 });
5664 if (zig_object.func_offset_table) |ot| {5664 if (zig_object.offset_table) |ot| {
5665 try writer.print("{}", .{ot.fmt(zig_object, self)});5665 try writer.print("{}", .{ot.fmt(zig_object, self)});
5666 }5666 }
5667 try writer.writeByte('\n');5667 try writer.writeByte('\n');
src/link/Elf/Symbol.zig+5
...@@ -260,6 +260,7 @@ const AddExtraOpts = struct {...@@ -260,6 +260,7 @@ const AddExtraOpts = struct {
260 gottp: ?u32 = null,260 gottp: ?u32 = null,
261 tlsdesc: ?u32 = null,261 tlsdesc: ?u32 = null,
262 zig_got: ?u32 = null,262 zig_got: ?u32 = null,
263 zig_offset_table: ?u32 = null,
263};264};
264265
265pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, elf_file: *Elf) void {266pub fn addExtra(symbol: *Symbol, opts: AddExtraOpts, elf_file: *Elf) void {
...@@ -467,6 +468,9 @@ pub const Flags = packed struct {...@@ -467,6 +468,9 @@ pub const Flags = packed struct {
467468
468 /// Whether the symbol is a merge subsection.469 /// Whether the symbol is a merge subsection.
469 merge_subsection: bool = false,470 merge_subsection: bool = false,
471
472 /// Whether the symbol has __zig_offset_table indirection.
473 zig_offset_table: bool = false,
470};474};
471475
472pub const Extra = struct {476pub const Extra = struct {
...@@ -481,6 +485,7 @@ pub const Extra = struct {...@@ -481,6 +485,7 @@ pub const Extra = struct {
481 tlsdesc: u32 = 0,485 tlsdesc: u32 = 0,
482 zig_got: u32 = 0,486 zig_got: u32 = 0,
483 merge_section: u32 = 0,487 merge_section: u32 = 0,
488 zig_offset_table: u32 = 0,
484};489};
485490
486pub const Index = u32;491pub const Index = u32;
src/link/Elf/ZigObject.zig+69-10
...@@ -55,7 +55,10 @@ debug_str_section_zig_size: u64 = 0,...@@ -55,7 +55,10 @@ debug_str_section_zig_size: u64 = 0,
55debug_aranges_section_zig_size: u64 = 0,55debug_aranges_section_zig_size: u64 = 0,
56debug_line_section_zig_size: u64 = 0,56debug_line_section_zig_size: u64 = 0,
5757
58func_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.
61offset_table: ?OffsetTable = null,
5962
60pub const global_symbol_bit: u32 = 0x80000000;63pub const global_symbol_bit: u32 = 0x80000000;
61pub const symbol_mask: u32 = 0x7fffffff;64pub 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 }
133136
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);
10431047
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 });
10451049
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);
10481052
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();
10511066
...@@ -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}
14481463
1464fn offsetTablePtr(self: *ZigObject) ?*OffsetTable {
1465 return if (self.offset_table) |*ot| ot else null;
1466}
1467
1468fn 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
1449pub fn asFile(self: *ZigObject) File {1485pub 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
1694const TlsTable = std.AutoArrayHashMapUnmanaged(Atom.Index, TlsVariable);1730const TlsTable = std.AutoArrayHashMapUnmanaged(Atom.Index, TlsVariable);
16951731
1696pub const OffsetTable = struct {1732pub 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) = .{},
16991735
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 }
17031739
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 }
17101767
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};
17471806
1748const assert = std.debug.assert;1807const assert = std.debug.assert;