From c92c72d08cfb102206594d723e29dd0616290d31 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Fri, 4 Oct 2024 10:38:43 +0200 Subject: [PATCH] elf: do not create atoms for section symbols that do not require it --- src/link/Elf.zig | 7 +- src/link/Elf/Atom.zig | 3 +- src/link/Elf/ZigObject.zig | 191 +++++++++++++++++++++++-------------- 3 files changed, 123 insertions(+), 78 deletions(-) diff --git a/src/link/Elf.zig b/src/link/Elf.zig index c8faaa33b6..c4cbb107bc 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -3472,12 +3472,7 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u32) void { } } - if (self.zigObjectPtr()) |zo| { - for (zo.atoms_indexes.items) |atom_index| { - const atom_ptr = zo.atom(atom_index) orelse continue; - atom_ptr.output_section_index = backlinks[atom_ptr.output_section_index]; - } - } + if (self.zigObjectPtr()) |zo| zo.resetShdrIndexes(backlinks); for (self.comdat_group_sections.items) |*cg| { cg.shndx = backlinks[cg.shndx]; diff --git a/src/link/Elf/Atom.zig b/src/link/Elf/Atom.zig index 854fb72afb..ab87d4f38e 100644 --- a/src/link/Elf/Atom.zig +++ b/src/link/Elf/Atom.zig @@ -935,9 +935,10 @@ fn format2( _ = unused_fmt_string; const atom = ctx.atom; const elf_file = ctx.elf_file; - try writer.print("atom({d}) : {s} : @{x} : shdr({d}) : align({x}) : size({x})", .{ + try writer.print("atom({d}) : {s} : @{x} : shdr({d}) : align({x}) : size({x}) : prev({}) : next({})", .{ atom.atom_index, atom.name(elf_file), atom.address(elf_file), atom.output_section_index, atom.alignment.toByteUnits() orelse 0, atom.size, + atom.prev_atom_ref, atom.next_atom_ref, }); if (atom.fdes(elf_file).len > 0) { try writer.writeAll(" : fdes{ "); diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index b27474fcab..957418f65e 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -101,6 +101,28 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { .dwarf => |v| { var dwarf = Dwarf.init(&elf_file.base, v); + const addSectionSymbolWithAtom = struct { + fn addSectionSymbolWithAtom( + zo: *ZigObject, + allocator: Allocator, + name: [:0]const u8, + alignment: Atom.Alignment, + shndx: u32, + ) !Symbol.Index { + const name_off = try zo.addString(allocator, name); + const sym_index = try zo.addSectionSymbol(allocator, name_off, shndx); + const sym = zo.symbol(sym_index); + const atom_index = try zo.newAtom(allocator, name_off); + const atom_ptr = zo.atom(atom_index).?; + atom_ptr.alignment = alignment; + atom_ptr.output_section_index = shndx; + sym.ref = .{ .index = atom_index, .file = zo.index }; + zo.symtab.items(.shndx)[sym.esym_index] = atom_index; + zo.symtab.items(.elf_sym)[sym.esym_index].st_shndx = SHN_ATOM; + return sym_index; + } + }.addSectionSymbolWithAtom; + if (self.debug_str_index == null) { const osec = try elf_file.addSection(.{ .name = try elf_file.insertShString(".debug_str"), @@ -110,7 +132,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { .addralign = 1, }); self.debug_str_section_dirty = true; - self.debug_str_index = try self.addSectionSymbol(gpa, ".debug_str", .@"1", osec); + self.debug_str_index = try addSectionSymbolWithAtom(self, gpa, ".debug_str", .@"1", osec); elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_str_index.?).ref; } @@ -121,7 +143,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { .addralign = 1, }); self.debug_info_section_dirty = true; - self.debug_info_index = try self.addSectionSymbol(gpa, ".debug_info", .@"1", osec); + self.debug_info_index = try addSectionSymbolWithAtom(self, gpa, ".debug_info", .@"1", osec); elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_info_index.?).ref; } @@ -132,7 +154,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { .addralign = 1, }); self.debug_abbrev_section_dirty = true; - self.debug_abbrev_index = try self.addSectionSymbol(gpa, ".debug_abbrev", .@"1", osec); + self.debug_abbrev_index = try addSectionSymbolWithAtom(self, gpa, ".debug_abbrev", .@"1", osec); elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_abbrev_index.?).ref; } @@ -143,7 +165,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { .addralign = 16, }); self.debug_aranges_section_dirty = true; - self.debug_aranges_index = try self.addSectionSymbol(gpa, ".debug_aranges", .@"16", osec); + self.debug_aranges_index = try addSectionSymbolWithAtom(self, gpa, ".debug_aranges", .@"16", osec); elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_aranges_index.?).ref; } @@ -154,7 +176,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { .addralign = 1, }); self.debug_line_section_dirty = true; - self.debug_line_index = try self.addSectionSymbol(gpa, ".debug_line", .@"1", osec); + self.debug_line_index = try addSectionSymbolWithAtom(self, gpa, ".debug_line", .@"1", osec); elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_line_index.?).ref; } @@ -167,7 +189,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { .addralign = 1, }); self.debug_line_str_section_dirty = true; - self.debug_line_str_index = try self.addSectionSymbol(gpa, ".debug_line_str", .@"1", osec); + self.debug_line_str_index = try addSectionSymbolWithAtom(self, gpa, ".debug_line_str", .@"1", osec); elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_line_str_index.?).ref; } @@ -178,7 +200,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { .addralign = 1, }); self.debug_loclists_section_dirty = true; - self.debug_loclists_index = try self.addSectionSymbol(gpa, ".debug_loclists", .@"1", osec); + self.debug_loclists_index = try addSectionSymbolWithAtom(self, gpa, ".debug_loclists", .@"1", osec); elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_loclists_index.?).ref; } @@ -189,7 +211,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { .addralign = 1, }); self.debug_rnglists_section_dirty = true; - self.debug_rnglists_index = try self.addSectionSymbol(gpa, ".debug_rnglists", .@"1", osec); + self.debug_rnglists_index = try addSectionSymbolWithAtom(self, gpa, ".debug_rnglists", .@"1", osec); elf_file.sections.items(.last_atom)[osec] = self.symbol(self.debug_rnglists_index.?).ref; } @@ -204,7 +226,7 @@ pub fn init(self: *ZigObject, elf_file: *Elf, options: InitOptions) !void { .addralign = ptr_size, }); self.eh_frame_section_dirty = true; - self.eh_frame_index = try self.addSectionSymbol(gpa, ".eh_frame", Atom.Alignment.fromNonzeroByteUnits(ptr_size), osec); + self.eh_frame_index = try addSectionSymbolWithAtom(self, gpa, ".eh_frame", Atom.Alignment.fromNonzeroByteUnits(ptr_size), osec); elf_file.sections.items(.last_atom)[osec] = self.symbol(self.eh_frame_index.?).ref; } @@ -997,7 +1019,7 @@ pub fn lowerUav( } const osec = if (self.data_relro_index) |sym_index| - self.symbol(sym_index).atom(elf_file).?.output_section_index + self.symbol(sym_index).outputShndx(elf_file).? else osec: { const osec = try elf_file.addSection(.{ .name = try elf_file.insertShString(".data.rel.ro"), @@ -1006,7 +1028,7 @@ pub fn lowerUav( .flags = elf.SHF_ALLOC | elf.SHF_WRITE, .offset = std.math.maxInt(u64), }); - self.data_relro_index = try self.addSectionSymbol(gpa, ".data.rel.ro", .@"1", osec); + self.data_relro_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".data.rel.ro"), osec); break :osec osec; }; @@ -1112,24 +1134,14 @@ pub fn getOrCreateMetadataForNav( return gop.value_ptr.symbol_index; } -// FIXME: we always create an atom to basically store size and alignment, however, this is only true for -// sections that have a single atom like the debug sections. It would be a better solution to decouple this -// concept from the atom, maybe. -fn addSectionSymbol( - self: *ZigObject, - allocator: Allocator, - name: [:0]const u8, - alignment: Atom.Alignment, - shndx: u32, -) !Symbol.Index { - const name_off = try self.addString(allocator, name); - const index = try self.newSymbolWithAtom(allocator, name_off); +fn addSectionSymbol(self: *ZigObject, allocator: Allocator, name_off: u32, shndx: u32) !Symbol.Index { + const index = try self.newLocalSymbol(allocator, name_off); const sym = self.symbol(index); const esym = &self.symtab.items(.elf_sym)[sym.esym_index]; esym.st_info |= elf.STT_SECTION; - const atom_ptr = self.atom(sym.ref.index).?; - atom_ptr.alignment = alignment; - atom_ptr.output_section_index = shndx; + // TODO create fake shdrs? + // esym.st_shndx = shndx; + sym.output_section_index = shndx; return index; } @@ -1148,7 +1160,7 @@ fn getNavShdrIndex( const nav_val = zcu.navValue(nav_index); if (ip.isFunctionType(nav_val.typeOf(zcu).toIntern())) { if (self.text_index) |symbol_index| - return self.symbol(symbol_index).atom(elf_file).?.output_section_index; + return self.symbol(symbol_index).outputShndx(elf_file).?; const osec = try elf_file.addSection(.{ .type = elf.SHT_PROGBITS, .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR, @@ -1156,7 +1168,7 @@ fn getNavShdrIndex( .addralign = 1, .offset = std.math.maxInt(u64), }); - self.text_index = try self.addSectionSymbol(gpa, ".text", .@"1", osec); + self.text_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".text"), osec); return osec; } const is_const, const is_threadlocal, const nav_init = switch (ip.indexToKey(nav_val.toIntern())) { @@ -1171,18 +1183,18 @@ fn getNavShdrIndex( } else true; if (is_bss) { if (self.tbss_index) |symbol_index| - return self.symbol(symbol_index).atom(elf_file).?.output_section_index; + return self.symbol(symbol_index).outputShndx(elf_file).?; const osec = try elf_file.addSection(.{ .name = try elf_file.insertShString(".tbss"), .flags = elf.SHF_ALLOC | elf.SHF_WRITE | elf.SHF_TLS, .type = elf.SHT_NOBITS, .addralign = 1, }); - self.tbss_index = try self.addSectionSymbol(gpa, ".tbss", .@"1", osec); + self.tbss_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".tbss"), osec); return osec; } if (self.tdata_index) |symbol_index| - return self.symbol(symbol_index).atom(elf_file).?.output_section_index; + return self.symbol(symbol_index).outputShndx(elf_file).?; const osec = try elf_file.addSection(.{ .type = elf.SHT_PROGBITS, .flags = elf.SHF_ALLOC | elf.SHF_WRITE | elf.SHF_TLS, @@ -1190,12 +1202,12 @@ fn getNavShdrIndex( .addralign = 1, .offset = std.math.maxInt(u64), }); - self.tdata_index = try self.addSectionSymbol(gpa, ".tdata", .@"1", osec); + self.tdata_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".tdata"), osec); return osec; } if (is_const) { if (self.data_relro_index) |symbol_index| - return self.symbol(symbol_index).atom(elf_file).?.output_section_index; + return self.symbol(symbol_index).outputShndx(elf_file).?; const osec = try elf_file.addSection(.{ .name = try elf_file.insertShString(".data.rel.ro"), .type = elf.SHT_PROGBITS, @@ -1203,14 +1215,14 @@ fn getNavShdrIndex( .flags = elf.SHF_ALLOC | elf.SHF_WRITE, .offset = std.math.maxInt(u64), }); - self.data_relro_index = try self.addSectionSymbol(gpa, ".data.rel.ro", .@"1", osec); + self.data_relro_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".data.rel.ro"), osec); return osec; } if (nav_init != .none and Value.fromInterned(nav_init).isUndefDeep(zcu)) return switch (zcu.navFileScope(nav_index).mod.optimize_mode) { .Debug, .ReleaseSafe => { if (self.data_index) |symbol_index| - return self.symbol(symbol_index).atom(elf_file).?.output_section_index; + return self.symbol(symbol_index).outputShndx(elf_file).?; const osec = try elf_file.addSection(.{ .name = try elf_file.insertShString(".data"), .type = elf.SHT_PROGBITS, @@ -1218,24 +1230,19 @@ fn getNavShdrIndex( .flags = elf.SHF_ALLOC | elf.SHF_WRITE, .offset = std.math.maxInt(u64), }); - self.data_index = try self.addSectionSymbol( - gpa, - ".data", - Atom.Alignment.fromNonzeroByteUnits(ptr_size), - osec, - ); + self.data_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".data"), osec); return osec; }, .ReleaseFast, .ReleaseSmall => { if (self.bss_index) |symbol_index| - return self.symbol(symbol_index).atom(elf_file).?.output_section_index; + return self.symbol(symbol_index).outputShndx(elf_file).?; const osec = try elf_file.addSection(.{ .type = elf.SHT_NOBITS, .flags = elf.SHF_ALLOC | elf.SHF_WRITE, .name = try elf_file.insertShString(".bss"), .addralign = 1, }); - self.bss_index = try self.addSectionSymbol(gpa, ".bss", .@"1", osec); + self.bss_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".bss"), osec); return osec; }, }; @@ -1244,18 +1251,18 @@ fn getNavShdrIndex( } else true; if (is_bss) { if (self.bss_index) |symbol_index| - return self.symbol(symbol_index).atom(elf_file).?.output_section_index; + return self.symbol(symbol_index).outputShndx(elf_file).?; const osec = try elf_file.addSection(.{ .type = elf.SHT_NOBITS, .flags = elf.SHF_ALLOC | elf.SHF_WRITE, .name = try elf_file.insertShString(".bss"), .addralign = 1, }); - self.bss_index = try self.addSectionSymbol(gpa, ".bss", .@"1", osec); + self.bss_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".bss"), osec); return osec; } if (self.data_index) |symbol_index| - return self.symbol(symbol_index).atom(elf_file).?.output_section_index; + return self.symbol(symbol_index).outputShndx(elf_file).?; const osec = try elf_file.addSection(.{ .name = try elf_file.insertShString(".data"), .type = elf.SHT_PROGBITS, @@ -1263,12 +1270,7 @@ fn getNavShdrIndex( .flags = elf.SHF_ALLOC | elf.SHF_WRITE, .offset = std.math.maxInt(u64), }); - self.data_index = try self.addSectionSymbol( - gpa, - ".data", - Atom.Alignment.fromNonzeroByteUnits(ptr_size), - osec, - ); + self.data_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".data"), osec); return osec; } @@ -1521,7 +1523,7 @@ pub fn updateFunc( .addralign = 1, .offset = std.math.maxInt(u64), }); - self.text_index = try self.addSectionSymbol(gpa, ".text", .@"1", osec); + self.text_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".text"), osec); break :osec osec; }; const name_off = try self.addString(gpa, name); @@ -1688,7 +1690,7 @@ fn updateLazySymbol( const output_section_index = switch (sym.kind) { .code => if (self.text_index) |sym_index| - self.symbol(sym_index).atom(elf_file).?.output_section_index + self.symbol(sym_index).outputShndx(elf_file).? else osec: { const osec = try elf_file.addSection(.{ .name = try elf_file.insertShString(".text"), @@ -1697,11 +1699,11 @@ fn updateLazySymbol( .flags = elf.SHF_ALLOC | elf.SHF_EXECINSTR, .offset = std.math.maxInt(u64), }); - self.text_index = try self.addSectionSymbol(gpa, ".text", .@"1", osec); + self.text_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".text"), osec); break :osec osec; }, .const_data => if (self.rodata_index) |sym_index| - self.symbol(sym_index).atom(elf_file).?.output_section_index + self.symbol(sym_index).outputShndx(elf_file).? else osec: { const osec = try elf_file.addSection(.{ .name = try elf_file.insertShString(".rodata"), @@ -1710,7 +1712,7 @@ fn updateLazySymbol( .flags = elf.SHF_ALLOC, .offset = std.math.maxInt(u64), }); - self.rodata_index = try self.addSectionSymbol(gpa, ".rodata", .@"1", osec); + self.rodata_index = try self.addSectionSymbol(gpa, try self.addString(gpa, ".rodata"), osec); break :osec osec; }, }; @@ -2011,20 +2013,10 @@ fn allocateAtom(self: *ZigObject, atom_ptr: *Atom, elf_file: *Elf) !void { } shdr.sh_addralign = @max(shdr.sh_addralign, atom_ptr.alignment.toByteUnits().?); - const sect_atom_ptr = for ([_]?Symbol.Index{ - self.text_index, - self.rodata_index, - self.data_relro_index, - self.data_index, - self.tdata_index, - }) |maybe_sym_index| { - const sect_sym_index = maybe_sym_index orelse continue; - const sect_atom_ptr = self.symbol(sect_sym_index).atom(elf_file).?; - if (sect_atom_ptr.output_section_index == atom_ptr.output_section_index) break sect_atom_ptr; - } else null; - if (sect_atom_ptr) |sap| { - sap.size = shdr.sh_size; - sap.alignment = Atom.Alignment.fromNonzeroByteUnits(shdr.sh_addralign); + if (self.sectionSymbol(atom_ptr.output_section_index, elf_file)) |sym| { + assert(sym.atom(elf_file) == null and sym.mergeSubsection(elf_file) == null); + const esym = &self.symtab.items(.elf_sym)[sym.esym_index]; + esym.st_size += atom_ptr.size + Elf.padToIdeal(atom_ptr.size); } // This function can also reallocate an atom. @@ -2053,10 +2045,67 @@ fn growAtom(self: *ZigObject, atom_ptr: *Atom, elf_file: *Elf) !void { } } +pub fn resetShdrIndexes(self: *ZigObject, backlinks: anytype) void { + for (self.atoms_indexes.items) |atom_index| { + const atom_ptr = self.atom(atom_index) orelse continue; + atom_ptr.output_section_index = backlinks[atom_ptr.output_section_index]; + } + inline for ([_]?Symbol.Index{ + self.text_index, + self.rodata_index, + self.data_relro_index, + self.data_index, + self.bss_index, + self.tdata_index, + self.tbss_index, + self.eh_frame_index, + self.debug_info_index, + self.debug_abbrev_index, + self.debug_aranges_index, + self.debug_str_index, + self.debug_line_index, + self.debug_line_str_index, + self.debug_loclists_index, + self.debug_rnglists_index, + }) |maybe_sym_index| { + if (maybe_sym_index) |sym_index| { + const sym = self.symbol(sym_index); + sym.output_section_index = backlinks[sym.output_section_index]; + } + } +} + pub fn asFile(self: *ZigObject) File { return .{ .zig_object = self }; } +pub fn sectionSymbol(self: *ZigObject, shndx: u32, elf_file: *Elf) ?*Symbol { + inline for ([_]?Symbol.Index{ + self.text_index, + self.rodata_index, + self.data_relro_index, + self.data_index, + self.bss_index, + self.tdata_index, + self.tbss_index, + self.eh_frame_index, + self.debug_info_index, + self.debug_abbrev_index, + self.debug_aranges_index, + self.debug_str_index, + self.debug_line_index, + self.debug_line_str_index, + self.debug_loclists_index, + self.debug_rnglists_index, + }) |maybe_sym_index| { + if (maybe_sym_index) |sym_index| { + const sym = self.symbol(sym_index); + if (sym.outputShndx(elf_file) == shndx) return sym; + } + } + return null; +} + pub fn addString(self: *ZigObject, allocator: Allocator, string: []const u8) !u32 { return self.strtab.insert(allocator, string); }