elf: do not re-create synthetic sections if already created

This commit is contained in:
Jakub Konka 2024-09-24 10:46:39 +02:00
parent 4ceefca14b
commit 62c282ba46
2 changed files with 107 additions and 83 deletions

View File

@ -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,67 +3037,81 @@ 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),
});
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_STRTAB,
.entsize = 1,
.addralign = 1,
.offset = std.math.maxInt(u64),
});
}
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_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) {
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),
});
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),
});
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),
});
}
}
}

View File

@ -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);