authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-08-08 23:21:52+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-08-13 13:30:24+02:00
log7556b32840eabb027945d9a30b57bb9cb46cf0bb
tree96c7208dc11e035119841bd1fc9e276a51c351db
parent97a65ea0d5275602fac39bb08ab23f2908f8845e

elf: indirect via offset table in the linker away from backend


3 files changed, 54 insertions(+), 22 deletions(-)

src/link/Elf/Atom.zig+8-4
......@@ -759,13 +759,14 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi
759759 // Address of the dynamic thread pointer.
760760 const DTP = elf_file.dtpAddress();
761761
762 relocs_log.debug(" {s}: {x}: [{x} => {x}] G({x}) ZG({x}) ({s})", .{
762 relocs_log.debug(" {s}: {x}: [{x} => {x}] G({x}) ZG({x}) ZG2({x}) ({s})", .{
763763 relocation.fmtRelocType(rel.r_type(), cpu_arch),
764764 r_offset,
765765 P,
766766 S + A,
767767 G + GOT + A,
768768 ZIG_GOT + A,
769 target.zigOffsetTableAddress(elf_file) + A,
769770 target.name(elf_file),
770771 });
771772
......@@ -1224,9 +1225,12 @@ const x86_64 = struct {
12241225 );
12251226 },
12261227
1227 .PLT32,
1228 .PC32,
1229 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little),
1228 .PLT32 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little),
1229
1230 .PC32 => {
1231 const S_ = if (target.flags.zig_offset_table) target.zigOffsetTableAddress(elf_file) else S;
1232 try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little);
1233 },
12301234
12311235 .GOTPCREL => try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little),
12321236 .GOTPC32 => try cwriter.writeInt(i32, @as(i32, @intCast(GOT + A - P)), .little),
src/link/Elf/Symbol.zig+8
......@@ -236,6 +236,14 @@ pub fn zigGotAddress(symbol: Symbol, elf_file: *Elf) i64 {
236236 return elf_file.zig_got.entryAddress(extras.zig_got, elf_file);
237237}
238238
239pub fn zigOffsetTableAddress(symbol: Symbol, elf_file: *Elf) i64 {
240 if (!symbol.flags.zig_offset_table) return 0;
241 const zo = elf_file.zigObjectPtr().?;
242 const offset_table = zo.offsetTablePtr().?;
243 const ot_index = symbol.extra(elf_file).zig_offset_table;
244 return offset_table.entryAddress(ot_index, zo, elf_file);
245}
246
239247pub fn dsoAlignment(symbol: Symbol, elf_file: *Elf) !u64 {
240248 const file_ptr = symbol.file(elf_file) orelse return 0;
241249 assert(file_ptr == .shared_object);
src/link/Elf/ZigObject.zig+38-18
......@@ -760,7 +760,9 @@ pub fn getOrCreateMetadataForLazySymbol(
760760 const gpa = elf_file.base.comp.gpa;
761761 const symbol_index = try self.newSymbolWithAtom(gpa, 0);
762762 const sym = self.symbol(symbol_index);
763 sym.flags.needs_zig_got = true;
763 if (lazy_sym.kind != .code) {
764 sym.flags.needs_zig_got = true;
765 }
764766 symbol_index_ptr.* = symbol_index;
765767 },
766768 .pending_flush => return symbol_index_ptr.*,
......@@ -816,7 +818,7 @@ pub fn getOrCreateMetadataForNav(
816818 sym.flags.is_tls = true;
817819 }
818820 }
819 if (!sym.flags.is_tls) {
821 if (!sym.flags.is_tls and nav_val.typeOf(zcu).zigTypeTag(zcu) != .Fn) {
820822 sym.flags.needs_zig_got = true;
821823 }
822824 gop.value_ptr.* = .{ .symbol_index = symbol_index };
......@@ -919,16 +921,19 @@ fn updateNavCode(
919921 sym.value = 0;
920922 esym.st_value = 0;
921923
922 if (!elf_file.base.isRelocatable()) {
923 log.debug(" (writing new offset table entry)", .{});
924 assert(sym.flags.has_zig_got);
925 const extra = sym.extra(elf_file);
926 try elf_file.zig_got.writeOne(elf_file, extra.zig_got);
927 if (stt_bits == elf.STT_FUNC) {
928 const offset_table = self.offsetTablePtr().?;
929 offset_table.entries.items(.dirty)[extra.zig_offset_table] = true;
924 if (stt_bits != elf.STT_FUNC) {
925 if (!elf_file.base.isRelocatable()) {
926 log.debug(" (writing new offset table entry)", .{});
927 assert(sym.flags.has_zig_got);
928 const extra = sym.extra(elf_file);
929 try elf_file.zig_got.writeOne(elf_file, extra.zig_got);
930930 }
931931 }
932 if (stt_bits == elf.STT_FUNC) {
933 const extra = sym.extra(elf_file);
934 const offset_table = self.offsetTablePtr().?;
935 offset_table.entries.items(.dirty)[extra.zig_offset_table] = true;
936 }
932937 }
933938 } else if (code.len < old_size) {
934939 atom_ptr.shrink(elf_file);
......@@ -938,12 +943,13 @@ fn updateNavCode(
938943 errdefer self.freeNavMetadata(elf_file, sym_index);
939944
940945 sym.value = 0;
941 sym.flags.needs_zig_got = true;
942946 esym.st_value = 0;
943
944 if (!elf_file.base.isRelocatable()) {
945 const gop = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
946 try elf_file.zig_got.writeOne(elf_file, gop.index);
947 if (stt_bits != elf.STT_FUNC) {
948 sym.flags.needs_zig_got = true;
949 if (!elf_file.base.isRelocatable()) {
950 const gop = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
951 try elf_file.zig_got.writeOne(elf_file, gop.index);
952 }
947953 }
948954 }
949955
......@@ -1061,7 +1067,12 @@ pub fn updateFunc(
10611067 sym.flags.zig_offset_table = true;
10621068 sym.addExtra(.{ .zig_offset_table = index }, elf_file);
10631069 try offset_table.updateSize(self, elf_file);
1070 const old_vaddr = offset_table.address(self, elf_file);
10641071 try self.symbol(offset_table.sym_index).atom(elf_file).?.allocate(elf_file);
1072 const new_vaddr = offset_table.address(self, elf_file);
1073 if (old_vaddr != new_vaddr) {
1074 offset_table.dirty = true;
1075 }
10651076 }
10661077 }
10671078
......@@ -1106,7 +1117,13 @@ pub fn updateFunc(
11061117
11071118 // Exports will be updated by `Zcu.processExports` after the update.
11081119
1109 {
1120 if (offset_table.dirty) {
1121 // TODO write in bulk
1122 for (offset_table.entries.items(.dirty), 0..) |*dirty, i| {
1123 try offset_table.writeEntry(@intCast(i), self, elf_file);
1124 dirty.* = false;
1125 }
1126 } else {
11101127 const sym = self.symbol(sym_index);
11111128 const ot_index = sym.extra(elf_file).zig_offset_table;
11121129 var ot_entry = offset_table.entries.get(ot_index);
......@@ -1261,7 +1278,9 @@ fn updateLazySymbol(
12611278 errdefer self.freeNavMetadata(elf_file, symbol_index);
12621279
12631280 local_sym.value = 0;
1264 local_sym.flags.needs_zig_got = true;
1281 if (sym.kind != .code) {
1282 local_sym.flags.needs_zig_got = true;
1283 }
12651284 local_esym.st_value = 0;
12661285
12671286 if (!elf_file.base.isRelocatable()) {
......@@ -1476,7 +1495,7 @@ pub fn getGlobalSymbol(self: *ZigObject, elf_file: *Elf, name: []const u8, lib_n
14761495 return lookup_gop.value_ptr.*;
14771496}
14781497
1479fn offsetTablePtr(self: *ZigObject) ?*OffsetTable {
1498pub fn offsetTablePtr(self: *ZigObject) ?*OffsetTable {
14801499 return if (self.offset_table) |*ot| ot else null;
14811500}
14821501
......@@ -1747,6 +1766,7 @@ const TlsTable = std.AutoArrayHashMapUnmanaged(Atom.Index, TlsVariable);
17471766pub const OffsetTable = struct {
17481767 sym_index: Symbol.Index,
17491768 entries: std.MultiArrayList(Entry) = .{},
1769 dirty: bool = false,
17501770
17511771 pub fn deinit(ot: *OffsetTable, allocator: Allocator) void {
17521772 ot.entries.deinit(allocator);