Commit 62c282ba46

Jakub Konka <kubkon@jakubkonka.com>
2024-09-24 10:46:39
elf: do not re-create synthetic sections if already created
1 parent 4ceefca
Changed files (2)
src/link/Elf/LinkerDefined.zig
@@ -145,6 +145,7 @@ pub fn initStartStopSymbols(self: *LinkerDefined, elf_file: *Elf) !void {
     try self.symbols_resolver.ensureUnusedCapacity(gpa, nsyms);
 
     for (slice.items(.shdr)) |shdr| {
+        // TODO use getOrPut for incremental so that we don't create duplicates
         if (elf_file.getStartStopBasename(shdr)) |name| {
             const start_name = try std.fmt.allocPrintZ(gpa, "__start_{s}", .{name});
             defer gpa.free(start_name);
src/link/Elf.zig
@@ -147,6 +147,7 @@ thunks: std.ArrayListUnmanaged(Thunk) = .empty,
 
 /// List of output merge sections with deduped contents.
 merge_sections: std.ArrayListUnmanaged(MergeSection) = .empty,
+comment_merge_section_index: ?MergeSection.Index = null,
 
 first_eflags: ?elf.Elf64_Word = null,
 
@@ -2790,6 +2791,7 @@ fn checkDuplicates(self: *Elf) !void {
 
 pub fn addCommentString(self: *Elf) !void {
     const gpa = self.base.comp.gpa;
+    if (self.comment_merge_section_index != null) return;
     const msec_index = try self.getOrCreateMergeSection(".comment", elf.SHF_MERGE | elf.SHF_STRINGS, elf.SHT_PROGBITS);
     const msec = self.mergeSection(msec_index);
     const res = try msec.insertZ(gpa, "zig " ++ builtin.zig_version_string);
@@ -2803,6 +2805,7 @@ pub fn addCommentString(self: *Elf) !void {
     msub.entsize = 1;
     msub.alive = true;
     res.sub.* = msub_index;
+    self.comment_merge_section_index = msec_index;
 }
 
 pub fn resolveMergeSections(self: *Elf) !void {
@@ -2920,7 +2923,7 @@ fn initSyntheticSections(self: *Elf) !void {
                 .offset = std.math.maxInt(u64),
             });
         }
-        if (comp.link_eh_frame_hdr) {
+        if (comp.link_eh_frame_hdr and self.eh_frame_hdr_section_index == null) {
             self.eh_frame_hdr_section_index = try self.addSection(.{
                 .name = try self.insertShString(".eh_frame_hdr"),
                 .type = elf.SHT_PROGBITS,
@@ -2931,7 +2934,7 @@ fn initSyntheticSections(self: *Elf) !void {
         }
     }
 
-    if (self.got.entries.items.len > 0) {
+    if (self.got.entries.items.len > 0 and self.got_section_index == null) {
         self.got_section_index = try self.addSection(.{
             .name = try self.insertShString(".got"),
             .type = elf.SHT_PROGBITS,
@@ -2941,13 +2944,15 @@ fn initSyntheticSections(self: *Elf) !void {
         });
     }
 
-    self.got_plt_section_index = try self.addSection(.{
-        .name = try self.insertShString(".got.plt"),
-        .type = elf.SHT_PROGBITS,
-        .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
-        .addralign = @alignOf(u64),
-        .offset = std.math.maxInt(u64),
-    });
+    if (self.got_plt_section_index == null) {
+        self.got_plt_section_index = try self.addSection(.{
+            .name = try self.insertShString(".got.plt"),
+            .type = elf.SHT_PROGBITS,
+            .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
+            .addralign = @alignOf(u64),
+            .offset = std.math.maxInt(u64),
+        });
+    }
 
     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)
@@ -2960,7 +2965,7 @@ fn initSyntheticSections(self: *Elf) !void {
         }
         break :blk false;
     };
-    if (needs_rela_dyn) {
+    if (needs_rela_dyn and self.rela_dyn_section_index == null) {
         self.rela_dyn_section_index = try self.addSection(.{
             .name = try self.insertShString(".rela.dyn"),
             .type = elf.SHT_RELA,
@@ -2972,24 +2977,28 @@ fn initSyntheticSections(self: *Elf) !void {
     }
 
     if (self.plt.symbols.items.len > 0) {
-        self.plt_section_index = try self.addSection(.{
-            .name = try self.insertShString(".plt"),
-            .type = elf.SHT_PROGBITS,
-            .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,
-            .addralign = 16,
-            .offset = std.math.maxInt(u64),
-        });
-        self.rela_plt_section_index = try self.addSection(.{
-            .name = try self.insertShString(".rela.plt"),
-            .type = elf.SHT_RELA,
-            .flags = elf.SHF_ALLOC,
-            .addralign = @alignOf(elf.Elf64_Rela),
-            .entsize = @sizeOf(elf.Elf64_Rela),
-            .offset = std.math.maxInt(u64),
-        });
+        if (self.plt_section_index == null) {
+            self.plt_section_index = try self.addSection(.{
+                .name = try self.insertShString(".plt"),
+                .type = elf.SHT_PROGBITS,
+                .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR,
+                .addralign = 16,
+                .offset = std.math.maxInt(u64),
+            });
+        }
+        if (self.rela_plt_section_index == null) {
+            self.rela_plt_section_index = try self.addSection(.{
+                .name = try self.insertShString(".rela.plt"),
+                .type = elf.SHT_RELA,
+                .flags = elf.SHF_ALLOC,
+                .addralign = @alignOf(elf.Elf64_Rela),
+                .entsize = @sizeOf(elf.Elf64_Rela),
+                .offset = std.math.maxInt(u64),
+            });
+        }
     }
 
-    if (self.plt_got.symbols.items.len > 0) {
+    if (self.plt_got.symbols.items.len > 0 and self.plt_got_section_index == null) {
         self.plt_got_section_index = try self.addSection(.{
             .name = try self.insertShString(".plt.got"),
             .type = elf.SHT_PROGBITS,
@@ -2999,7 +3008,7 @@ fn initSyntheticSections(self: *Elf) !void {
         });
     }
 
-    if (self.copy_rel.symbols.items.len > 0) {
+    if (self.copy_rel.symbols.items.len > 0 and self.copy_rel_section_index == null) {
         self.copy_rel_section_index = try self.addSection(.{
             .name = try self.insertShString(".copyrel"),
             .type = elf.SHT_NOBITS,
@@ -3017,7 +3026,7 @@ fn initSyntheticSections(self: *Elf) !void {
         if (self.base.isStatic() and !comp.config.pie) break :blk false;
         break :blk target.dynamic_linker.get() != null;
     };
-    if (needs_interp) {
+    if (needs_interp and self.interp_section_index == null) {
         self.interp_section_index = try self.addSection(.{
             .name = try self.insertShString(".interp"),
             .type = elf.SHT_PROGBITS,
@@ -3028,68 +3037,82 @@ fn initSyntheticSections(self: *Elf) !void {
     }
 
     if (self.isEffectivelyDynLib() or self.shared_objects.items.len > 0 or comp.config.pie) {
-        self.dynstrtab_section_index = try self.addSection(.{
-            .name = try self.insertShString(".dynstr"),
-            .flags = elf.SHF_ALLOC,
-            .type = elf.SHT_STRTAB,
-            .entsize = 1,
-            .addralign = 1,
-            .offset = std.math.maxInt(u64),
-        });
-        self.dynamic_section_index = try self.addSection(.{
-            .name = try self.insertShString(".dynamic"),
-            .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
-            .type = elf.SHT_DYNAMIC,
-            .entsize = @sizeOf(elf.Elf64_Dyn),
-            .addralign = @alignOf(elf.Elf64_Dyn),
-            .offset = std.math.maxInt(u64),
-        });
-        self.dynsymtab_section_index = try self.addSection(.{
-            .name = try self.insertShString(".dynsym"),
-            .flags = elf.SHF_ALLOC,
-            .type = elf.SHT_DYNSYM,
-            .addralign = @alignOf(elf.Elf64_Sym),
-            .entsize = @sizeOf(elf.Elf64_Sym),
-            .info = 1,
-            .offset = std.math.maxInt(u64),
-        });
-        self.hash_section_index = try self.addSection(.{
-            .name = try self.insertShString(".hash"),
-            .flags = elf.SHF_ALLOC,
-            .type = elf.SHT_HASH,
-            .addralign = 4,
-            .entsize = 4,
-            .offset = std.math.maxInt(u64),
-        });
-        self.gnu_hash_section_index = try self.addSection(.{
-            .name = try self.insertShString(".gnu.hash"),
-            .flags = elf.SHF_ALLOC,
-            .type = elf.SHT_GNU_HASH,
-            .addralign = 8,
-            .offset = std.math.maxInt(u64),
-        });
-
-        const needs_versions = for (self.dynsym.entries.items) |entry| {
-            const sym = self.symbol(entry.ref).?;
-            if (sym.flags.import and sym.version_index & elf.VERSYM_VERSION > elf.VER_NDX_GLOBAL) break true;
-        } else false;
-        if (needs_versions) {
-            self.versym_section_index = try self.addSection(.{
-                .name = try self.insertShString(".gnu.version"),
+        if (self.dynstrtab_section_index == null) {
+            self.dynstrtab_section_index = try self.addSection(.{
+                .name = try self.insertShString(".dynstr"),
                 .flags = elf.SHF_ALLOC,
-                .type = elf.SHT_GNU_VERSYM,
-                .addralign = @alignOf(elf.Elf64_Versym),
-                .entsize = @sizeOf(elf.Elf64_Versym),
+                .type = elf.SHT_STRTAB,
+                .entsize = 1,
+                .addralign = 1,
                 .offset = std.math.maxInt(u64),
             });
-            self.verneed_section_index = try self.addSection(.{
-                .name = try self.insertShString(".gnu.version_r"),
+        }
+        if (self.dynamic_section_index == null) {
+            self.dynamic_section_index = try self.addSection(.{
+                .name = try self.insertShString(".dynamic"),
+                .flags = elf.SHF_ALLOC | elf.SHF_WRITE,
+                .type = elf.SHT_DYNAMIC,
+                .entsize = @sizeOf(elf.Elf64_Dyn),
+                .addralign = @alignOf(elf.Elf64_Dyn),
+                .offset = std.math.maxInt(u64),
+            });
+        }
+        if (self.dynsymtab_section_index == null) {
+            self.dynsymtab_section_index = try self.addSection(.{
+                .name = try self.insertShString(".dynsym"),
                 .flags = elf.SHF_ALLOC,
-                .type = elf.SHT_GNU_VERNEED,
-                .addralign = @alignOf(elf.Elf64_Verneed),
+                .type = elf.SHT_DYNSYM,
+                .addralign = @alignOf(elf.Elf64_Sym),
+                .entsize = @sizeOf(elf.Elf64_Sym),
+                .info = 1,
                 .offset = std.math.maxInt(u64),
             });
         }
+        if (self.hash_section_index == null) {
+            self.hash_section_index = try self.addSection(.{
+                .name = try self.insertShString(".hash"),
+                .flags = elf.SHF_ALLOC,
+                .type = elf.SHT_HASH,
+                .addralign = 4,
+                .entsize = 4,
+                .offset = std.math.maxInt(u64),
+            });
+        }
+        if (self.gnu_hash_section_index == null) {
+            self.gnu_hash_section_index = try self.addSection(.{
+                .name = try self.insertShString(".gnu.hash"),
+                .flags = elf.SHF_ALLOC,
+                .type = elf.SHT_GNU_HASH,
+                .addralign = 8,
+                .offset = std.math.maxInt(u64),
+            });
+        }
+
+        const needs_versions = for (self.dynsym.entries.items) |entry| {
+            const sym = self.symbol(entry.ref).?;
+            if (sym.flags.import and sym.version_index & elf.VERSYM_VERSION > elf.VER_NDX_GLOBAL) break true;
+        } else false;
+        if (needs_versions) {
+            if (self.versym_section_index == null) {
+                self.versym_section_index = try self.addSection(.{
+                    .name = try self.insertShString(".gnu.version"),
+                    .flags = elf.SHF_ALLOC,
+                    .type = elf.SHT_GNU_VERSYM,
+                    .addralign = @alignOf(elf.Elf64_Versym),
+                    .entsize = @sizeOf(elf.Elf64_Versym),
+                    .offset = std.math.maxInt(u64),
+                });
+            }
+            if (self.verneed_section_index == null) {
+                self.verneed_section_index = try self.addSection(.{
+                    .name = try self.insertShString(".gnu.version_r"),
+                    .flags = elf.SHF_ALLOC,
+                    .type = elf.SHT_GNU_VERNEED,
+                    .addralign = @alignOf(elf.Elf64_Verneed),
+                    .offset = std.math.maxInt(u64),
+                });
+            }
+        }
     }
 
     try self.initSymtab();