diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2024-09-24 10:46:39 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2024-09-25 17:54:50 +0200 |
| commit | 62c282ba4699bd00d0cb74b3253bac7a925eae68 (patch) | |
| tree | d7f76b3cee61f29ef503c8fa8b81014933a66d8d /src | |
| parent | 4ceefca14be313e91a248fdc532e37edf4a02a51 (diff) | |
| download | zig-62c282ba4699bd00d0cb74b3253bac7a925eae68.tar.gz zig-62c282ba4699bd00d0cb74b3253bac7a925eae68.zip | |
elf: do not re-create synthetic sections if already created
Diffstat (limited to 'src')
| -rw-r--r-- | src/link/Elf.zig | 189 | ||||
| -rw-r--r-- | src/link/Elf/LinkerDefined.zig | 1 |
2 files changed, 107 insertions, 83 deletions
diff --git a/src/link/Elf.zig b/src/link/Elf.zig index ba3abcf330..8e09c7832d 100644 --- a/src/link/Elf.zig +++ b/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(); diff --git a/src/link/Elf/LinkerDefined.zig b/src/link/Elf/LinkerDefined.zig index 60f9482efb..9515dfcd43 100644 --- a/src/link/Elf/LinkerDefined.zig +++ b/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); |
