Commit 8055f68765

Jakub Konka <kubkon@jakubkonka.com>
2023-11-02 00:20:56
elf: make sure we never emit .got.zig relocs when linking object files
1 parent e8f5221
Changed files (4)
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.getOrCreateZigGotEntry(sym_index, elf_file);
+                        try sym.createZigGotEntry(sym_index, elf_file);
                         if (self.bin_file.options.pic) {
                             const callee_reg: Register = switch (resolved_cc) {
                                 .SysV => callee: {
@@ -13103,7 +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.getOrCreateZigGotEntry(sym_index, elf_file);
+        try sym.createZigGotEntry(sym_index, elf_file);
 
         if (self.bin_file.options.pic) {
             switch (tag) {
src/link/Elf/Symbol.zig
@@ -168,11 +168,17 @@ const GetOrCreateZigGotEntryResult = struct {
 };
 
 pub fn getOrCreateZigGotEntry(symbol: *Symbol, symbol_index: Index, elf_file: *Elf) !GetOrCreateZigGotEntryResult {
+    assert(!elf_file.isObject());
     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).?;
src/link/Elf/ZigObject.zig
@@ -433,7 +433,6 @@ pub fn updateRelaSectionSizes(self: ZigObject, elf_file: *Elf) void {
 }
 
 pub fn writeRelaSections(self: ZigObject, elf_file: *Elf) !void {
-    _ = self;
     const gpa = elf_file.base.allocator;
 
     for (&[_]?u16{
@@ -454,18 +453,18 @@ pub fn writeRelaSections(self: ZigObject, elf_file: *Elf) !void {
 
         while (true) {
             for (atom.relocs(elf_file)) |rel| {
-                relocs.appendAssumeCapacity(switch (rel.r_type()) {
-                    Elf.R_X86_64_ZIG_GOT32 => .{
-                        .r_offset = rel.r_offset,
-                        .r_addend = rel.r_addend,
-                        .r_info = (@as(u64, @intCast(rel.r_sym())) << 32) | elf.R_X86_64_32,
-                    },
-                    Elf.R_X86_64_ZIG_GOTPCREL => .{
-                        .r_offset = rel.r_offset,
-                        .r_addend = rel.r_addend,
-                        .r_info = (@as(u64, @intCast(rel.r_sym())) << 32) | elf.R_X86_64_PC32,
-                    },
-                    else => rel,
+                var r_sym = rel.r_sym() & symbol_mask;
+                if (self.isGlobal(rel.r_sym())) r_sym += @intCast(self.local_esyms.slice().len + 1);
+                const r_type = switch (rel.r_type()) {
+                    Elf.R_X86_64_ZIG_GOT32,
+                    Elf.R_X86_64_ZIG_GOTPCREL,
+                    => unreachable, // Sanity check if we accidentally emitted those.
+                    else => |r_type| r_type,
+                };
+                relocs.appendAssumeCapacity(.{
+                    .r_offset = rel.r_offset,
+                    .r_addend = rel.r_addend,
+                    .r_info = (@as(u64, @intCast(r_sym)) << 32) | r_type,
                 });
             }
             if (elf_file.atom(atom.prev_index)) |prev| {
@@ -486,17 +485,20 @@ pub fn writeRelaSections(self: ZigObject, elf_file: *Elf) !void {
     }
 }
 
+pub fn isGlobal(self: ZigObject, index: Symbol.Index) bool {
+    _ = self;
+    return index & global_symbol_bit != 0;
+}
+
 pub fn symbol(self: *ZigObject, index: Symbol.Index) Symbol.Index {
-    const is_global = index & global_symbol_bit != 0;
     const actual_index = index & symbol_mask;
-    if (is_global) return self.global_symbols.items[actual_index];
+    if (self.isGlobal(index)) return self.global_symbols.items[actual_index];
     return self.local_symbols.items[actual_index];
 }
 
 pub fn elfSym(self: *ZigObject, index: Symbol.Index) *elf.Elf64_Sym {
-    const is_global = index & global_symbol_bit != 0;
     const actual_index = index & symbol_mask;
-    if (is_global) return &self.global_esyms.items(.elf_sym)[actual_index];
+    if (self.isGlobal(index)) return &self.global_esyms.items(.elf_sym)[actual_index];
     return &self.local_esyms.items(.elf_sym)[actual_index];
 }
 
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.getOrCreateZigGotEntry(sym_index, elf_file);
+        try sym.createZigGotEntry(sym_index, elf_file);
         return GenResult.mcv(.{ .load_symbol = sym.esym_index });
     } else if (bin_file.cast(link.File.MachO)) |macho_file| {
         if (is_extern) {