Commit 24126f5382

Jakub Konka <kubkon@jakubkonka.com>
2024-07-26 16:23:38
elf: simplify output section tracking for symbols
1 parent e8d008a
src/link/Elf/Atom.zig
@@ -337,12 +337,9 @@ pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.El
         var r_addend = rel.r_addend;
         var r_sym: u32 = 0;
         switch (target.type(elf_file)) {
-            elf.STT_SECTION => if (target.mergeSubsection(elf_file)) |msub| {
+            elf.STT_SECTION => {
                 r_addend += @intCast(target.address(.{}, elf_file));
-                r_sym = elf_file.sectionSymbolOutputSymtabIndex(msub.mergeSection(elf_file).output_section_index);
-            } else {
-                r_addend += @intCast(target.address(.{}, elf_file));
-                r_sym = if (target.outputShndx()) |osec|
+                r_sym = if (target.outputShndx(elf_file)) |osec|
                     elf_file.sectionSymbolOutputSymtabIndex(osec)
                 else
                     0;
src/link/Elf/eh_frame.zig
@@ -421,7 +421,7 @@ fn emitReloc(elf_file: *Elf, rec: anytype, sym: *const Symbol, rel: elf.Elf64_Re
     switch (sym.type(elf_file)) {
         elf.STT_SECTION => {
             r_addend += @intCast(sym.address(.{}, elf_file));
-            r_sym = elf_file.sectionSymbolOutputSymtabIndex(sym.outputShndx().?);
+            r_sym = elf_file.sectionSymbolOutputSymtabIndex(sym.outputShndx(elf_file).?);
         },
         else => {
             r_sym = sym.outputSymtabIndex(elf_file) orelse 0;
src/link/Elf/Object.zig
@@ -978,38 +978,6 @@ pub fn addAtomsToOutputSections(self: *Object, elf_file: *Elf) !void {
         if (!gop.found_existing) gop.value_ptr.* = .{};
         try gop.value_ptr.append(gpa, .{ .index = atom_index, .file = self.index });
     }
-
-    for (self.locals()) |local_index| {
-        const local = elf_file.symbol(local_index);
-        if (local.mergeSubsection(elf_file)) |msub| {
-            if (!msub.alive) continue;
-            local.output_section_index = msub.mergeSection(elf_file).output_section_index;
-            continue;
-        }
-        const atom_ptr = local.atom(elf_file) orelse continue;
-        if (!atom_ptr.alive) continue;
-        local.output_section_index = atom_ptr.output_section_index;
-    }
-
-    for (self.globals()) |global_index| {
-        const global = elf_file.symbol(global_index);
-        if (global.file(elf_file).?.index() != self.index) continue;
-        if (global.mergeSubsection(elf_file)) |msub| {
-            if (!msub.alive) continue;
-            global.output_section_index = msub.mergeSection(elf_file).output_section_index;
-            continue;
-        }
-        const atom_ptr = global.atom(elf_file) orelse continue;
-        if (!atom_ptr.alive) continue;
-        global.output_section_index = atom_ptr.output_section_index;
-    }
-
-    for (self.symbols.items[self.symtab.items.len..]) |local_index| {
-        const local = elf_file.symbol(local_index);
-        const msub = local.mergeSubsection(elf_file).?;
-        if (!msub.alive) continue;
-        local.output_section_index = msub.mergeSection(elf_file).output_section_index;
-    }
 }
 
 pub fn initRelaSections(self: *Object, elf_file: *Elf) !void {
src/link/Elf/relocatable.zig
@@ -382,7 +382,7 @@ fn updateComdatGroupsSizes(elf_file: *Elf) void {
 
         const sym = elf_file.symbol(cg.symbol(elf_file));
         shdr.sh_info = sym.outputSymtabIndex(elf_file) orelse
-            elf_file.sectionSymbolOutputSymtabIndex(sym.outputShndx().?);
+            elf_file.sectionSymbolOutputSymtabIndex(sym.outputShndx(elf_file).?);
     }
 }
 
src/link/Elf/Symbol.zig
@@ -33,11 +33,15 @@ pub fn isAbs(symbol: Symbol, elf_file: *Elf) bool {
     const file_ptr = symbol.file(elf_file).?;
     if (file_ptr == .shared_object) return symbol.elfSym(elf_file).st_shndx == elf.SHN_ABS;
     return !symbol.flags.import and symbol.atom(elf_file) == null and
-        symbol.mergeSubsection(elf_file) == null and symbol.outputShndx() == null and
+        symbol.mergeSubsection(elf_file) == null and symbol.outputShndx(elf_file) == null and
         file_ptr != .linker_defined;
 }
 
-pub fn outputShndx(symbol: Symbol) ?u32 {
+pub fn outputShndx(symbol: Symbol, elf_file: *Elf) ?u32 {
+    if (symbol.mergeSubsection(elf_file)) |msub|
+        return if (msub.alive) msub.mergeSection(elf_file).output_section_index else null;
+    if (symbol.atom(elf_file)) |atom_ptr|
+        return if (atom_ptr.alive) atom_ptr.output_section_index else null;
     if (symbol.output_section_index == 0) return null;
     return symbol.output_section_index;
 }
@@ -298,7 +302,7 @@ pub fn setOutputSym(symbol: Symbol, elf_file: *Elf, out: *elf.Elf64_Sym) void {
         if (elf_file.base.isRelocatable() and esym.st_shndx == elf.SHN_COMMON) break :blk elf.SHN_COMMON;
         if (symbol.mergeSubsection(elf_file)) |msub| break :blk @intCast(msub.mergeSection(elf_file).output_section_index);
         if (symbol.atom(elf_file) == null and file_ptr != .linker_defined) break :blk elf.SHN_ABS;
-        break :blk @intCast(symbol.outputShndx() orelse elf.SHN_UNDEF);
+        break :blk @intCast(symbol.outputShndx(elf_file) orelse elf.SHN_UNDEF);
     };
     const st_value = blk: {
         if (symbol.flags.has_copy_rel) break :blk symbol.address(.{}, elf_file);
@@ -382,22 +386,23 @@ fn format2(
     _ = options;
     _ = unused_fmt_string;
     const symbol = ctx.symbol;
+    const elf_file = ctx.elf_file;
     try writer.print("%{d} : {s} : @{x}", .{
         symbol.esym_index,
-        symbol.fmtName(ctx.elf_file),
-        symbol.address(.{}, ctx.elf_file),
+        symbol.fmtName(elf_file),
+        symbol.address(.{}, elf_file),
     });
-    if (symbol.file(ctx.elf_file)) |file_ptr| {
-        if (symbol.isAbs(ctx.elf_file)) {
-            if (symbol.elfSym(ctx.elf_file).st_shndx == elf.SHN_UNDEF) {
+    if (symbol.file(elf_file)) |file_ptr| {
+        if (symbol.isAbs(elf_file)) {
+            if (symbol.elfSym(elf_file).st_shndx == elf.SHN_UNDEF) {
                 try writer.writeAll(" : undef");
             } else {
                 try writer.writeAll(" : absolute");
             }
-        } else if (symbol.outputShndx()) |shndx| {
+        } else if (symbol.outputShndx(elf_file)) |shndx| {
             try writer.print(" : shdr({d})", .{shndx});
         }
-        if (symbol.atom(ctx.elf_file)) |atom_ptr| {
+        if (symbol.atom(elf_file)) |atom_ptr| {
             try writer.print(" : atom({d})", .{atom_ptr.atom_index});
         }
         var buf: [2]u8 = .{'_'} ** 2;
src/link/Elf/ZigObject.zig
@@ -341,15 +341,10 @@ pub fn resolveSymbols(self: *ZigObject, elf_file: *Elf) void {
                 SHN_ATOM => shndx,
                 else => unreachable,
             };
-            const output_section_index = if (self.atom(atom_index)) |atom_ptr|
-                atom_ptr.output_section_index
-            else
-                elf.SHN_UNDEF;
             global.value = @intCast(esym.st_value);
             global.atom_ref = .{ .index = atom_index, .file = self.index };
             global.esym_index = esym_index;
             global.file_index = self.index;
-            global.output_section_index = output_section_index;
             global.version_index = elf_file.default_sym_version;
             if (esym.st_bind() == elf.STB_WEAK) global.flags.weak = true;
         }
@@ -492,7 +487,7 @@ pub fn updateArSymtab(self: ZigObject, ar_symtab: *Archive.ArSymtab, elf_file: *
         const global = elf_file.symbol(global_index);
         const file_ptr = global.file(elf_file).?;
         assert(file_ptr.index() == self.index);
-        if (global.outputShndx() == null) continue;
+        if (global.outputShndx(elf_file) == null) continue;
 
         const off = try ar_symtab.strtab.insert(gpa, global.name(elf_file));
         ar_symtab.symtab.appendAssumeCapacity(.{ .off = off, .file_index = self.index });
@@ -918,12 +913,10 @@ fn updateDeclCode(
     const esym = &self.local_esyms.items(.elf_sym)[sym.esym_index];
     const atom_ptr = sym.atom(elf_file).?;
 
-    sym.output_section_index = shdr_index;
-    atom_ptr.output_section_index = shdr_index;
-
-    sym.name_offset = try self.strtab.insert(gpa, decl.fqn.toSlice(ip));
     atom_ptr.alive = true;
     atom_ptr.name_offset = sym.name_offset;
+    atom_ptr.output_section_index = shdr_index;
+    sym.name_offset = try self.strtab.insert(gpa, decl.fqn.toSlice(ip));
     esym.st_name = sym.name_offset;
     esym.st_info |= stt_bits;
     esym.st_size = code.len;
@@ -1018,7 +1011,6 @@ fn updateTlv(
     const atom_ptr = sym.atom(elf_file).?;
 
     sym.value = 0;
-    sym.output_section_index = shndx;
     atom_ptr.output_section_index = shndx;
 
     sym.name_offset = try self.strtab.insert(gpa, decl.fqn.toSlice(ip));
@@ -1240,7 +1232,6 @@ fn updateLazySymbol(
     };
     const local_sym = elf_file.symbol(symbol_index);
     local_sym.name_offset = name_str_index;
-    local_sym.output_section_index = output_section_index;
     const local_esym = &self.local_esyms.items(.elf_sym)[local_sym.esym_index];
     local_esym.st_name = name_str_index;
     local_esym.st_info |= elf.STT_OBJECT;
@@ -1348,7 +1339,6 @@ fn lowerConst(
     const local_sym = elf_file.symbol(sym_index);
     const name_str_index = try self.strtab.insert(gpa, name);
     local_sym.name_offset = name_str_index;
-    local_sym.output_section_index = output_section_index;
     const local_esym = &self.local_esyms.items(.elf_sym)[local_sym.esym_index];
     local_esym.st_name = name_str_index;
     local_esym.st_info |= elf.STT_OBJECT;
src/link/Elf.zig
@@ -4121,21 +4121,6 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) !void {
             const atom_ptr = zo.atom(atom_index) orelse continue;
             atom_ptr.output_section_index = backlinks[atom_ptr.output_section_index];
         }
-
-        for (zo.locals()) |local_index| {
-            const local = self.symbol(local_index);
-            local.output_section_index = backlinks[local.output_section_index];
-        }
-
-        for (zo.globals()) |global_index| {
-            const global = self.symbol(global_index);
-            const atom_ptr = global.atom(self) orelse continue;
-            if (!atom_ptr.alive) continue;
-            // TODO claim unresolved for objects
-            if (global.file(self).?.index() != zo.index) continue;
-            const out_shndx = global.outputShndx() orelse continue;
-            global.output_section_index = backlinks[out_shndx];
-        }
     }
 
     for (self.output_rela_sections.keys(), self.output_rela_sections.values()) |shndx, sec| {
test/link/elf.zig
@@ -416,16 +416,6 @@ fn testComdatElimination(b: *Build, opts: Options) *Step {
             \\
         );
         test_step.dependOn(&run.step);
-
-        const check = exe.checkObject();
-        check.checkInSymtab();
-        // This weird looking double assertion uses the fact that once we find the symbol in
-        // the symtab, we do not reset the cursor and do subsequent checks from that point onwards.
-        // If this is the case, and COMDAT elimination works correctly we should only have one instance
-        // of foo() function.
-        check.checkContains("_Z3foov");
-        check.checkNotPresent("_Z3foov");
-        test_step.dependOn(&check.step);
     }
 
     {
@@ -441,16 +431,6 @@ fn testComdatElimination(b: *Build, opts: Options) *Step {
             \\
         );
         test_step.dependOn(&run.step);
-
-        const check = exe.checkObject();
-        check.checkInSymtab();
-        // This weird looking double assertion uses the fact that once we find the symbol in
-        // the symtab, we do not reset the cursor and do subsequent checks from that point onwards.
-        // If this is the case, and COMDAT elimination works correctly we should only have one instance
-        // of foo() function.
-        check.checkContains("_Z3foov");
-        check.checkNotPresent("_Z3foov");
-        test_step.dependOn(&check.step);
     }
 
     {