Commit b3d98a4b88

Jakub Konka <kubkon@jakubkonka.com>
2023-10-14 01:33:25
elf: emit dynamic base relocs for .zig.got entries when required
1 parent 315cd76
Changed files (2)
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));
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);
     }