Commit 906cf48e14

Jakub Konka <kubkon@jakubkonka.com>
2024-10-01 12:00:07
elf: fix creation of synthetic sections
1 parent 887f9a2
Changed files (3)
src/link/Elf/file.zig
@@ -99,18 +99,18 @@ pub const File = union(enum) {
                     log.debug("'{s}' needs GOT", .{sym.name(ef)});
                     _ = try ef.got.addGotSymbol(ref, ef);
                 }
-                if (sym.flags.needs_plt and !sym.flags.has_plt) {
-                    if (sym.flags.is_canonical) {
+                if (sym.flags.needs_plt) {
+                    if (sym.flags.is_canonical and !sym.flags.has_plt) {
                         log.debug("'{s}' needs CPLT", .{sym.name(ef)});
                         sym.flags.@"export" = true;
                         try ef.plt.addSymbol(ref, ef);
-                    } else if (sym.flags.needs_got and !sym.flags.has_got) {
+                    } else if (sym.flags.needs_got and !sym.flags.has_pltgot) {
                         log.debug("'{s}' needs PLTGOT", .{sym.name(ef)});
                         try ef.plt_got.addSymbol(ref, ef);
-                    } else {
+                    } else if (!sym.flags.has_plt) {
                         log.debug("'{s}' needs PLT", .{sym.name(ef)});
                         try ef.plt.addSymbol(ref, ef);
-                    }
+                    } else unreachable;
                 }
                 if (sym.flags.needs_copy_rel and !sym.flags.has_copy_rel) {
                     log.debug("'{s}' needs COPYREL", .{sym.name(ef)});
src/link/Elf/Symbol.zig
@@ -112,13 +112,16 @@ pub fn address(symbol: Symbol, opts: struct { plt: bool = true, trampoline: bool
     if (symbol.flags.has_trampoline and opts.trampoline) {
         return symbol.trampolineAddress(elf_file);
     }
-    if (symbol.flags.has_plt and opts.plt) {
-        if (!symbol.flags.is_canonical and symbol.flags.has_got) {
+    if (opts.plt) {
+        if (symbol.flags.has_pltgot) {
+            assert(!symbol.flags.is_canonical);
             // We have a non-lazy bound function pointer, use that!
             return symbol.pltGotAddress(elf_file);
         }
-        // Lazy-bound function it is!
-        return symbol.pltAddress(elf_file);
+        if (symbol.flags.has_plt) {
+            // Lazy-bound function it is!
+            return symbol.pltAddress(elf_file);
+        }
     }
     if (symbol.atom(elf_file)) |atom_ptr| {
         if (!atom_ptr.alive) {
@@ -171,7 +174,7 @@ pub fn gotAddress(symbol: Symbol, elf_file: *Elf) i64 {
 }
 
 pub fn pltGotAddress(symbol: Symbol, elf_file: *Elf) i64 {
-    if (!(symbol.flags.has_plt and symbol.flags.has_got)) return 0;
+    if (!symbol.flags.has_pltgot) return 0;
     const extras = symbol.extra(elf_file);
     const shdr = elf_file.sections.items(.shdr)[elf_file.plt_got_section_index.?];
     const cpu_arch = elf_file.getTarget().cpu.arch;
@@ -430,6 +433,8 @@ pub const Flags = packed struct {
     has_plt: bool = false,
     /// Whether the PLT entry is canonical.
     is_canonical: bool = false,
+    /// Whether the PLT entry is indirected via GOT.
+    has_pltgot: bool = false,
 
     /// Whether the symbol contains COPYREL directive.
     needs_copy_rel: bool = false,
src/link/Elf/synthetic_sections.zig
@@ -895,8 +895,7 @@ pub const PltGotSection = struct {
         const gpa = comp.gpa;
         const index = @as(u32, @intCast(plt_got.symbols.items.len));
         const symbol = elf_file.symbol(ref).?;
-        symbol.flags.has_plt = true;
-        symbol.flags.has_got = true;
+        symbol.flags.has_pltgot = true;
         symbol.addExtra(.{ .plt_got = index }, elf_file);
         try plt_got.symbols.append(gpa, ref);
     }