From b3d98a4b88514b1e8d2cc07ef05c218f50f5f5d8 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Sat, 14 Oct 2023 01:33:25 +0200 Subject: [PATCH] elf: emit dynamic base relocs for .zig.got entries when required --- src/link/Elf.zig | 5 +++-- src/link/Elf/synthetic_sections.zig | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 729d13550c..f89f303c6a 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -3747,7 +3747,7 @@ fn initSections(self: *Elf) !void { const needs_rela_dyn = blk: { if (self.got.flags.needs_rela or self.got.flags.needs_tlsld or - self.copy_rel.symbols.items.len > 0) break :blk true; + self.zig_got.flags.needs_rela or self.copy_rel.symbols.items.len > 0) break :blk true; if (self.zig_module_index) |index| { if (self.file(index).?.zig_module.num_dynrelocs > 0) break :blk true; } @@ -4319,7 +4319,7 @@ fn updateSectionSizes(self: *Elf) !void { } if (self.rela_dyn_section_index) |shndx| { - var num = self.got.numRela(self) + self.copy_rel.numRela(); + var num = self.got.numRela(self) + self.copy_rel.numRela() + self.zig_got.numRela(); if (self.zig_module_index) |index| { num += self.file(index).?.zig_module.num_dynrelocs; } @@ -4901,6 +4901,7 @@ fn writeSyntheticSections(self: *Elf) !void { const shdr = self.shdrs.items[shndx]; try self.got.addRela(self); try self.copy_rel.addRela(self); + try self.zig_got.addRela(self); self.sortRelaDyn(); try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.rela_dyn.items), shdr.sh_offset); } diff --git a/src/link/Elf/synthetic_sections.zig b/src/link/Elf/synthetic_sections.zig index 1d411a6064..3524b981fd 100644 --- a/src/link/Elf/synthetic_sections.zig +++ b/src/link/Elf/synthetic_sections.zig @@ -251,6 +251,9 @@ pub const ZigGotSection = struct { entry.* = sym_index; const symbol = elf_file.symbol(sym_index); symbol.flags.has_zig_got = true; + if (elf_file.base.options.pic) { + zig_got.flags.needs_rela = true; + } if (symbol.extra(elf_file)) |extra| { var new_extra = extra; new_extra.zig_got = index; @@ -338,6 +341,23 @@ pub const ZigGotSection = struct { } } + pub fn numRela(zig_got: ZigGotSection) usize { + return zig_got.entries.items.len; + } + + pub fn addRela(zig_got: ZigGotSection, elf_file: *Elf) !void { + try elf_file.rela_dyn.ensureUnusedCapacity(elf_file.base.allocator, zig_got.numRela()); + for (zig_got.entries.items) |entry| { + const symbol = elf_file.symbol(entry); + const offset = symbol.zigGotAddress(elf_file); + elf_file.addRelaDynAssumeCapacity(.{ + .offset = offset, + .type = elf.R_X86_64_RELATIVE, + .addend = @intCast(symbol.address(.{ .plt = false }, elf_file)), + }); + } + } + pub fn updateSymtabSize(zig_got: *ZigGotSection, elf_file: *Elf) void { _ = elf_file; zig_got.output_symtab_size.nlocals = @as(u32, @intCast(zig_got.entries.items.len));