diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2024-08-08 23:21:52 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2024-08-13 13:30:24 +0200 |
| commit | 7556b32840eabb027945d9a30b57bb9cb46cf0bb (patch) | |
| tree | 96c7208dc11e035119841bd1fc9e276a51c351db /src | |
| parent | 97a65ea0d5275602fac39bb08ab23f2908f8845e (diff) | |
| download | zig-7556b32840eabb027945d9a30b57bb9cb46cf0bb.tar.gz zig-7556b32840eabb027945d9a30b57bb9cb46cf0bb.zip | |
elf: indirect via offset table in the linker away from backend
Diffstat (limited to 'src')
| -rw-r--r-- | src/link/Elf/Atom.zig | 12 | ||||
| -rw-r--r-- | src/link/Elf/Symbol.zig | 8 | ||||
| -rw-r--r-- | src/link/Elf/ZigObject.zig | 56 |
3 files changed, 54 insertions, 22 deletions
diff --git a/src/link/Elf/Atom.zig b/src/link/Elf/Atom.zig index f2757f570b..6fa5d700ef 100644 --- a/src/link/Elf/Atom.zig +++ b/src/link/Elf/Atom.zig @@ -759,13 +759,14 @@ pub fn resolveRelocsAlloc(self: Atom, elf_file: *Elf, code: []u8) RelocError!voi // Address of the dynamic thread pointer. const DTP = elf_file.dtpAddress(); - relocs_log.debug(" {s}: {x}: [{x} => {x}] G({x}) ZG({x}) ({s})", .{ + relocs_log.debug(" {s}: {x}: [{x} => {x}] G({x}) ZG({x}) ZG2({x}) ({s})", .{ relocation.fmtRelocType(rel.r_type(), cpu_arch), r_offset, P, S + A, G + GOT + A, ZIG_GOT + A, + target.zigOffsetTableAddress(elf_file) + A, target.name(elf_file), }); @@ -1224,9 +1225,12 @@ const x86_64 = struct { ); }, - .PLT32, - .PC32, - => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little), + .PLT32 => try cwriter.writeInt(i32, @as(i32, @intCast(S + A - P)), .little), + + .PC32 => { + const S_ = if (target.flags.zig_offset_table) target.zigOffsetTableAddress(elf_file) else S; + try cwriter.writeInt(i32, @as(i32, @intCast(S_ + A - P)), .little); + }, .GOTPCREL => try cwriter.writeInt(i32, @as(i32, @intCast(G + GOT + A - P)), .little), .GOTPC32 => try cwriter.writeInt(i32, @as(i32, @intCast(GOT + A - P)), .little), diff --git a/src/link/Elf/Symbol.zig b/src/link/Elf/Symbol.zig index f023ad5d91..cf285b12d0 100644 --- a/src/link/Elf/Symbol.zig +++ b/src/link/Elf/Symbol.zig @@ -236,6 +236,14 @@ pub fn zigGotAddress(symbol: Symbol, elf_file: *Elf) i64 { return elf_file.zig_got.entryAddress(extras.zig_got, elf_file); } +pub fn zigOffsetTableAddress(symbol: Symbol, elf_file: *Elf) i64 { + if (!symbol.flags.zig_offset_table) return 0; + const zo = elf_file.zigObjectPtr().?; + const offset_table = zo.offsetTablePtr().?; + const ot_index = symbol.extra(elf_file).zig_offset_table; + return offset_table.entryAddress(ot_index, zo, elf_file); +} + pub fn dsoAlignment(symbol: Symbol, elf_file: *Elf) !u64 { const file_ptr = symbol.file(elf_file) orelse return 0; assert(file_ptr == .shared_object); diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index 75a0fd2cbe..f426e43c0a 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -760,7 +760,9 @@ pub fn getOrCreateMetadataForLazySymbol( const gpa = elf_file.base.comp.gpa; const symbol_index = try self.newSymbolWithAtom(gpa, 0); const sym = self.symbol(symbol_index); - sym.flags.needs_zig_got = true; + if (lazy_sym.kind != .code) { + sym.flags.needs_zig_got = true; + } symbol_index_ptr.* = symbol_index; }, .pending_flush => return symbol_index_ptr.*, @@ -816,7 +818,7 @@ pub fn getOrCreateMetadataForNav( sym.flags.is_tls = true; } } - if (!sym.flags.is_tls) { + if (!sym.flags.is_tls and nav_val.typeOf(zcu).zigTypeTag(zcu) != .Fn) { sym.flags.needs_zig_got = true; } gop.value_ptr.* = .{ .symbol_index = symbol_index }; @@ -919,16 +921,19 @@ fn updateNavCode( sym.value = 0; esym.st_value = 0; - if (!elf_file.base.isRelocatable()) { - log.debug(" (writing new offset table entry)", .{}); - assert(sym.flags.has_zig_got); - const extra = sym.extra(elf_file); - try elf_file.zig_got.writeOne(elf_file, extra.zig_got); - if (stt_bits == elf.STT_FUNC) { - const offset_table = self.offsetTablePtr().?; - offset_table.entries.items(.dirty)[extra.zig_offset_table] = true; + if (stt_bits != elf.STT_FUNC) { + if (!elf_file.base.isRelocatable()) { + log.debug(" (writing new offset table entry)", .{}); + assert(sym.flags.has_zig_got); + const extra = sym.extra(elf_file); + try elf_file.zig_got.writeOne(elf_file, extra.zig_got); } } + if (stt_bits == elf.STT_FUNC) { + const extra = sym.extra(elf_file); + const offset_table = self.offsetTablePtr().?; + offset_table.entries.items(.dirty)[extra.zig_offset_table] = true; + } } } else if (code.len < old_size) { atom_ptr.shrink(elf_file); @@ -938,12 +943,13 @@ fn updateNavCode( errdefer self.freeNavMetadata(elf_file, sym_index); sym.value = 0; - sym.flags.needs_zig_got = true; esym.st_value = 0; - - if (!elf_file.base.isRelocatable()) { - const gop = try sym.getOrCreateZigGotEntry(sym_index, elf_file); - try elf_file.zig_got.writeOne(elf_file, gop.index); + if (stt_bits != elf.STT_FUNC) { + sym.flags.needs_zig_got = true; + if (!elf_file.base.isRelocatable()) { + const gop = try sym.getOrCreateZigGotEntry(sym_index, elf_file); + try elf_file.zig_got.writeOne(elf_file, gop.index); + } } } @@ -1061,7 +1067,12 @@ pub fn updateFunc( sym.flags.zig_offset_table = true; sym.addExtra(.{ .zig_offset_table = index }, elf_file); try offset_table.updateSize(self, elf_file); + const old_vaddr = offset_table.address(self, elf_file); try self.symbol(offset_table.sym_index).atom(elf_file).?.allocate(elf_file); + const new_vaddr = offset_table.address(self, elf_file); + if (old_vaddr != new_vaddr) { + offset_table.dirty = true; + } } } @@ -1106,7 +1117,13 @@ pub fn updateFunc( // Exports will be updated by `Zcu.processExports` after the update. - { + if (offset_table.dirty) { + // TODO write in bulk + for (offset_table.entries.items(.dirty), 0..) |*dirty, i| { + try offset_table.writeEntry(@intCast(i), self, elf_file); + dirty.* = false; + } + } else { const sym = self.symbol(sym_index); const ot_index = sym.extra(elf_file).zig_offset_table; var ot_entry = offset_table.entries.get(ot_index); @@ -1261,7 +1278,9 @@ fn updateLazySymbol( errdefer self.freeNavMetadata(elf_file, symbol_index); local_sym.value = 0; - local_sym.flags.needs_zig_got = true; + if (sym.kind != .code) { + local_sym.flags.needs_zig_got = true; + } local_esym.st_value = 0; if (!elf_file.base.isRelocatable()) { @@ -1476,7 +1495,7 @@ pub fn getGlobalSymbol(self: *ZigObject, elf_file: *Elf, name: []const u8, lib_n return lookup_gop.value_ptr.*; } -fn offsetTablePtr(self: *ZigObject) ?*OffsetTable { +pub fn offsetTablePtr(self: *ZigObject) ?*OffsetTable { return if (self.offset_table) |*ot| ot else null; } @@ -1747,6 +1766,7 @@ const TlsTable = std.AutoArrayHashMapUnmanaged(Atom.Index, TlsVariable); pub const OffsetTable = struct { sym_index: Symbol.Index, entries: std.MultiArrayList(Entry) = .{}, + dirty: bool = false, pub fn deinit(ot: *OffsetTable, allocator: Allocator) void { ot.entries.deinit(allocator); |
