Commit ccb2afacc0

Jakub Konka <kubkon@jakubkonka.com>
2023-11-02 12:46:37
elf: postpone creation of .got.zig entry until code emit
1 parent 5affd29
Changed files (5)
src/arch/x86_64/CodeGen.zig
@@ -10235,7 +10235,7 @@ fn genCall(self: *Self, info: union(enum) {
                     if (self.bin_file.cast(link.File.Elf)) |elf_file| {
                         const sym_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, func.owner_decl);
                         const sym = elf_file.symbol(sym_index);
-                        try sym.createZigGotEntry(sym_index, elf_file);
+                        sym.flags.needs_zig_got = true;
                         if (self.bin_file.options.pic) {
                             const callee_reg: Register = switch (resolved_cc) {
                                 .SysV => callee: {
@@ -13103,8 +13103,7 @@ fn genLazySymbolRef(
         const sym_index = elf_file.zigObjectPtr().?.getOrCreateMetadataForLazySymbol(elf_file, lazy_sym) catch |err|
             return self.fail("{s} creating lazy symbol", .{@errorName(err)});
         const sym = elf_file.symbol(sym_index);
-        try sym.createZigGotEntry(sym_index, elf_file);
-
+        sym.flags.needs_zig_got = true;
         if (self.bin_file.options.pic) {
             switch (tag) {
                 .lea, .call => try self.genSetReg(reg, Type.usize, .{
src/arch/x86_64/Emit.zig
@@ -86,9 +86,13 @@ pub fn emitMir(emit: *Emit) Error!void {
                 }),
                 .linker_reloc => |data| if (emit.lower.bin_file.cast(link.File.Elf)) |elf_file| {
                     const atom = elf_file.symbol(data.atom_index).atom(elf_file).?;
-                    const sym = elf_file.symbol(elf_file.zigObjectPtr().?.symbol(data.sym_index));
+                    const sym_index = elf_file.zigObjectPtr().?.symbol(data.sym_index);
+                    const sym = elf_file.symbol(sym_index);
+                    if (sym.flags.needs_zig_got and emit.lower.bin_file.options.effectiveOutputMode() != .Obj) {
+                        _ = try sym.getOrCreateZigGotEntry(sym_index, elf_file);
+                    }
                     if (emit.lower.bin_file.options.pic) {
-                        const r_type: u32 = if (sym.flags.has_zig_got)
+                        const r_type: u32 = if (sym.flags.needs_zig_got)
                             link.File.Elf.R_X86_64_ZIG_GOTPCREL
                         else if (sym.flags.needs_got)
                             std.elf.R_X86_64_GOTPCREL
@@ -100,7 +104,7 @@ pub fn emitMir(emit: *Emit) Error!void {
                             .r_addend = -4,
                         });
                     } else {
-                        const r_type: u32 = if (sym.flags.has_zig_got)
+                        const r_type: u32 = if (sym.flags.needs_zig_got)
                             link.File.Elf.R_X86_64_ZIG_GOT32
                         else if (sym.flags.needs_got)
                             std.elf.R_X86_64_GOT32
src/link/Elf/Symbol.zig
@@ -169,16 +169,12 @@ const GetOrCreateZigGotEntryResult = struct {
 
 pub fn getOrCreateZigGotEntry(symbol: *Symbol, symbol_index: Index, elf_file: *Elf) !GetOrCreateZigGotEntryResult {
     assert(!elf_file.isObject());
+    assert(symbol.flags.needs_zig_got);
     if (symbol.flags.has_zig_got) return .{ .found_existing = true, .index = symbol.extra(elf_file).?.zig_got };
     const index = try elf_file.zig_got.addSymbol(symbol_index, elf_file);
     return .{ .found_existing = false, .index = index };
 }
 
-pub fn createZigGotEntry(symbol: *Symbol, symbol_index: Index, elf_file: *Elf) !void {
-    if (elf_file.isObject()) return;
-    _ = try symbol.getOrCreateZigGotEntry(symbol_index, elf_file);
-}
-
 pub fn zigGotAddress(symbol: Symbol, elf_file: *Elf) u64 {
     if (!symbol.flags.has_zig_got) return 0;
     const extras = symbol.extra(elf_file).?;
@@ -385,6 +381,7 @@ pub const Flags = packed struct {
     has_tlsdesc: bool = false,
 
     /// Whether the symbol contains .zig.got indirection.
+    needs_zig_got: bool = false,
     has_zig_got: bool = false,
 };
 
src/link/Elf/ZigObject.zig
@@ -901,6 +901,7 @@ fn updateDeclCode(
         errdefer self.freeDeclMetadata(elf_file, sym_index);
 
         sym.value = atom_ptr.value;
+        sym.flags.needs_zig_got = true;
         esym.st_value = atom_ptr.value;
 
         if (!elf_file.isObject()) {
@@ -1156,6 +1157,7 @@ fn updateLazySymbol(
     errdefer self.freeDeclMetadata(elf_file, symbol_index);
 
     local_sym.value = atom_ptr.value;
+    local_sym.flags.needs_zig_got = true;
     local_esym.st_value = atom_ptr.value;
 
     if (!elf_file.isObject()) {
src/codegen.zig
@@ -909,7 +909,7 @@ fn genDeclRef(
         }
         const sym_index = try elf_file.zigObjectPtr().?.getOrCreateMetadataForDecl(elf_file, decl_index);
         const sym = elf_file.symbol(sym_index);
-        try sym.createZigGotEntry(sym_index, elf_file);
+        sym.flags.needs_zig_got = true;
         return GenResult.mcv(.{ .load_symbol = sym.esym_index });
     } else if (bin_file.cast(link.File.MachO)) |macho_file| {
         if (is_extern) {