Commit 7556b32840
Changed files (3)
src
link
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),
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);
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);