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...@@ -759,13 +759,14 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi
759 // Address of the dynamic thread pointer.759 // Address of the dynamic thread pointer.
760 const DTP = elf_file.dtpAddress();760 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})", .{
763 relocation.fmtRelocType(rel.r_type(), cpu_arch),763 relocation.fmtRelocType(rel.r_type(), cpu_arch),
764 r_offset,764 r_offset,
765 P,765 P,
766 S + A,766 S + A,
767 G + GOT + A,767 G + GOT + A,
768 ZIG_GOT + A,768 ZIG_GOT + A,
769 target.zigOffsetTableAddress(elf_file) + A,
769 target.name(elf_file),770 target.name(elf_file),
770 });771 });
771772
...@@ -1224,9 +1225,12 @@ const x86_64 = struct {...@@ -1224,9 +1225,12 @@ const x86_64 = struct {
1224 );1225 );
1225 },1226 },
12261227
1227 .PLT32,1228 .PLT32 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little),
1228 .PC32,1229
1229 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little),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
1231 .GOTPCREL => try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little),1235 .GOTPCREL => try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little),
1232 .GOTPC32 => try cwriter.writeInt(i32, @as(i32, @intCast(GOT + A - P)), .little),1236 .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 {...@@ -236,6 +236,14 @@ pub fn zigGotAddress(symbol: Symbol, elf_file: *Elf) i64 {
236 return elf_file.zig_got.entryAddress(extras.zig_got, elf_file);236 return elf_file.zig_got.entryAddress(extras.zig_got, elf_file);
237}237}
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
239pub fn dsoAlignment(symbol: Symbol, elf_file: *Elf) !u64 {247pub fn dsoAlignment(symbol: Symbol, elf_file: *Elf) !u64 {
240 const file_ptr = symbol.file(elf_file) orelse return 0;248 const file_ptr = symbol.file(elf_file) orelse return 0;
241 assert(file_ptr == .shared_object);249 assert(file_ptr == .shared_object);
src/link/Elf/ZigObject.zig+38-18
...@@ -760,7 +760,9 @@ pub fn getOrCreateMetadataForLazySymbol(...@@ -760,7 +760,9 @@ pub fn getOrCreateMetadataForLazySymbol(
760 const gpa = elf_file.base.comp.gpa;760 const gpa = elf_file.base.comp.gpa;
761 const symbol_index = try self.newSymbolWithAtom(gpa, 0);761 const symbol_index = try self.newSymbolWithAtom(gpa, 0);
762 const sym = self.symbol(symbol_index);762 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 }
764 symbol_index_ptr.* = symbol_index;766 symbol_index_ptr.* = symbol_index;
765 },767 },
766 .pending_flush => return symbol_index_ptr.*,768 .pending_flush => return symbol_index_ptr.*,
...@@ -816,7 +818,7 @@ pub fn getOrCreateMetadataForNav(...@@ -816,7 +818,7 @@ pub fn getOrCreateMetadataForNav(
816 sym.flags.is_tls = true;818 sym.flags.is_tls = true;
817 }819 }
818 }820 }
819 if (!sym.flags.is_tls) {821 if (!sym.flags.is_tls and nav_val.typeOf(zcu).zigTypeTag(zcu) != .Fn) {
820 sym.flags.needs_zig_got = true;822 sym.flags.needs_zig_got = true;
821 }823 }
822 gop.value_ptr.* = .{ .symbol_index = symbol_index };824 gop.value_ptr.* = .{ .symbol_index = symbol_index };
...@@ -919,16 +921,19 @@ fn updateNavCode(...@@ -919,16 +921,19 @@ fn updateNavCode(
919 sym.value = 0;921 sym.value = 0;
920 esym.st_value = 0;922 esym.st_value = 0;
921923
922 if (!elf_file.base.isRelocatable()) {924 if (stt_bits != elf.STT_FUNC) {
923 log.debug(" (writing new offset table entry)", .{});925 if (!elf_file.base.isRelocatable()) {
924 assert(sym.flags.has_zig_got);926 log.debug(" (writing new offset table entry)", .{});
925 const extra = sym.extra(elf_file);927 assert(sym.flags.has_zig_got);
926 try elf_file.zig_got.writeOne(elf_file, extra.zig_got);928 const extra = sym.extra(elf_file);
927 if (stt_bits == elf.STT_FUNC) {929 try elf_file.zig_got.writeOne(elf_file, extra.zig_got);
928 const offset_table = self.offsetTablePtr().?;
929 offset_table.entries.items(.dirty)[extra.zig_offset_table] = true;
930 }930 }
931 }931 }
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 }
932 }937 }
933 } else if (code.len < old_size) {938 } else if (code.len < old_size) {
934 atom_ptr.shrink(elf_file);939 atom_ptr.shrink(elf_file);
...@@ -938,12 +943,13 @@ fn updateNavCode(...@@ -938,12 +943,13 @@ fn updateNavCode(
938 errdefer self.freeNavMetadata(elf_file, sym_index);943 errdefer self.freeNavMetadata(elf_file, sym_index);
939944
940 sym.value = 0;945 sym.value = 0;
941 sym.flags.needs_zig_got = true;
942 esym.st_value = 0;946 esym.st_value = 0;
943947 if (stt_bits != elf.STT_FUNC) {
944 if (!elf_file.base.isRelocatable()) {948 sym.flags.needs_zig_got = true;
945 const gop = try sym.getOrCreateZigGotEntry(sym_index, elf_file);949 if (!elf_file.base.isRelocatable()) {
946 try elf_file.zig_got.writeOne(elf_file, gop.index);950 const gop = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
951 try elf_file.zig_got.writeOne(elf_file, gop.index);
952 }
947 }953 }
948 }954 }
949955
...@@ -1061,7 +1067,12 @@ pub fn updateFunc(...@@ -1061,7 +1067,12 @@ pub fn updateFunc(
1061 sym.flags.zig_offset_table = true;1067 sym.flags.zig_offset_table = true;
1062 sym.addExtra(.{ .zig_offset_table = index }, elf_file);1068 sym.addExtra(.{ .zig_offset_table = index }, elf_file);
1063 try offset_table.updateSize(self, elf_file);1069 try offset_table.updateSize(self, elf_file);
1070 const old_vaddr = offset_table.address(self, elf_file);
1064 try self.symbol(offset_table.sym_index).atom(elf_file).?.allocate(elf_file);1071 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 }
1065 }1076 }
1066 }1077 }
10671078
...@@ -1106,7 +1117,13 @@ pub fn updateFunc(...@@ -1106,7 +1117,13 @@ pub fn updateFunc(
11061117
1107 // Exports will be updated by `Zcu.processExports` after the update.1118 // 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 {
1110 const sym = self.symbol(sym_index);1127 const sym = self.symbol(sym_index);
1111 const ot_index = sym.extra(elf_file).zig_offset_table;1128 const ot_index = sym.extra(elf_file).zig_offset_table;
1112 var ot_entry = offset_table.entries.get(ot_index);1129 var ot_entry = offset_table.entries.get(ot_index);
...@@ -1261,7 +1278,9 @@ fn updateLazySymbol(...@@ -1261,7 +1278,9 @@ fn updateLazySymbol(
1261 errdefer self.freeNavMetadata(elf_file, symbol_index);1278 errdefer self.freeNavMetadata(elf_file, symbol_index);
12621279
1263 local_sym.value = 0;1280 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 }
1265 local_esym.st_value = 0;1284 local_esym.st_value = 0;
12661285
1267 if (!elf_file.base.isRelocatable()) {1286 if (!elf_file.base.isRelocatable()) {
...@@ -1476,7 +1495,7 @@ pub fn getGlobalSymbol(self: *ZigObject, elf_file: *Elf, name: []const u8, lib_n...@@ -1476,7 +1495,7 @@ pub fn getGlobalSymbol(self: *ZigObject, elf_file: *Elf, name: []const u8, lib_n
1476 return lookup_gop.value_ptr.*;1495 return lookup_gop.value_ptr.*;
1477}1496}
14781497
1479fn offsetTablePtr(self: *ZigObject) ?*OffsetTable {1498pub fn offsetTablePtr(self: *ZigObject) ?*OffsetTable {
1480 return if (self.offset_table) |*ot| ot else null;1499 return if (self.offset_table) |*ot| ot else null;
1481}1500}
14821501
...@@ -1747,6 +1766,7 @@ const TlsTable = std.AutoArrayHashMapUnmanaged(Atom.Index, TlsVariable);...@@ -1747,6 +1766,7 @@ const TlsTable = std.AutoArrayHashMapUnmanaged(Atom.Index, TlsVariable);
1747pub const OffsetTable = struct {1766pub const OffsetTable = struct {
1748 sym_index: Symbol.Index,1767 sym_index: Symbol.Index,
1749 entries: std.MultiArrayList(Entry) = .{},1768 entries: std.MultiArrayList(Entry) = .{},
1769 dirty: bool = false,
17501770
1751 pub fn deinit(ot: *OffsetTable, allocator: Allocator) void {1771 pub fn deinit(ot: *OffsetTable, allocator: Allocator) void {
1752 ot.entries.deinit(allocator);1772 ot.entries.deinit(allocator);