From f4c4ca4b4c6f1d0c61ce85d1fd9677ff01cb3072 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Mon, 23 Sep 2024 06:56:33 +0200 Subject: [PATCH 1/4] elf: fix condition for skipping symbols if atom is dead Skipping the symbols too early when resolving would end up in the linker not deduping CIEs fully. --- src/link/Elf/Object.zig | 11 +++++------ src/link/Elf/ZigObject.zig | 11 +++++------ 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/link/Elf/Object.zig b/src/link/Elf/Object.zig index a7091b7394..de6903504b 100644 --- a/src/link/Elf/Object.zig +++ b/src/link/Elf/Object.zig @@ -524,12 +524,6 @@ pub fn resolveSymbols(self: *Object, elf_file: *Elf) !void { const first_global = self.first_global orelse return; for (self.globals(), first_global..) |_, i| { const esym = self.symtab.items[i]; - if (esym.st_shndx != elf.SHN_ABS and esym.st_shndx != elf.SHN_COMMON and esym.st_shndx != elf.SHN_UNDEF) { - const atom_index = self.atoms_indexes.items[esym.st_shndx]; - const atom_ptr = self.atom(atom_index) orelse continue; - if (!atom_ptr.alive) continue; - } - const resolv = &self.symbols_resolver.items[i - first_global]; const gop = try elf_file.resolver.getOrPut(gpa, .{ .index = @intCast(i), @@ -541,6 +535,11 @@ pub fn resolveSymbols(self: *Object, elf_file: *Elf) !void { resolv.* = gop.index; if (esym.st_shndx == elf.SHN_UNDEF) continue; + if (esym.st_shndx != elf.SHN_ABS and esym.st_shndx != elf.SHN_COMMON) { + const atom_index = self.atoms_indexes.items[esym.st_shndx]; + const atom_ptr = self.atom(atom_index) orelse continue; + if (!atom_ptr.alive) continue; + } if (elf_file.symbol(gop.ref.*) == null) { gop.ref.* = .{ .index = @intCast(i), .file = self.index }; continue; diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig index 671049919d..de70462b07 100644 --- a/src/link/Elf/ZigObject.zig +++ b/src/link/Elf/ZigObject.zig @@ -603,12 +603,6 @@ pub fn resolveSymbols(self: *ZigObject, elf_file: *Elf) !void { const global = &self.symbols.items[index]; const esym = global.elfSym(elf_file); const shndx = self.symtab.items(.shndx)[global.esym_index]; - if (esym.st_shndx != elf.SHN_ABS and esym.st_shndx != elf.SHN_COMMON and esym.st_shndx != elf.SHN_UNDEF) { - assert(esym.st_shndx == SHN_ATOM); - const atom_ptr = self.atom(shndx) orelse continue; - if (!atom_ptr.alive) continue; - } - const resolv = &self.symbols_resolver.items[i]; const gop = try elf_file.resolver.getOrPut(gpa, .{ .index = @intCast(i | global_symbol_bit), @@ -620,6 +614,11 @@ pub fn resolveSymbols(self: *ZigObject, elf_file: *Elf) !void { resolv.* = gop.index; if (esym.st_shndx == elf.SHN_UNDEF) continue; + if (esym.st_shndx != elf.SHN_ABS and esym.st_shndx != elf.SHN_COMMON) { + assert(esym.st_shndx == SHN_ATOM); + const atom_ptr = self.atom(shndx) orelse continue; + if (!atom_ptr.alive) continue; + } if (elf_file.symbol(gop.ref.*) == null) { gop.ref.* = .{ .index = @intCast(i | global_symbol_bit), .file = self.index }; continue; From 6929a5f44026cec8162fe713668b02e0e02bdfcc Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Mon, 23 Sep 2024 06:59:03 +0200 Subject: [PATCH 2/4] elf: remove dead code --- src/link/Elf/Symbol.zig | 1 - 1 file changed, 1 deletion(-) diff --git a/src/link/Elf/Symbol.zig b/src/link/Elf/Symbol.zig index 821f9e0bb9..cdf1b6f40a 100644 --- a/src/link/Elf/Symbol.zig +++ b/src/link/Elf/Symbol.zig @@ -471,7 +471,6 @@ pub const Extra = struct { tlsgd: u32 = 0, gottp: u32 = 0, tlsdesc: u32 = 0, - merge_section: u32 = 0, trampoline: u32 = 0, }; From 7c2abff1e13f6172771c3fe36aa580cdaa56b11e Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Mon, 23 Sep 2024 07:01:30 +0200 Subject: [PATCH 3/4] elf: only allocate __dso_handle symbol if not found in any object --- src/link/Elf/LinkerDefined.zig | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/link/Elf/LinkerDefined.zig b/src/link/Elf/LinkerDefined.zig index 59aea19efa..c01dff49b8 100644 --- a/src/link/Elf/LinkerDefined.zig +++ b/src/link/Elf/LinkerDefined.zig @@ -47,7 +47,7 @@ fn newSymbolAssumeCapacity(self: *LinkerDefined, name_off: u32, elf_file: *Elf) const esym = self.symtab.addOneAssumeCapacity(); esym.* = .{ .st_name = name_off, - .st_info = elf.STB_GLOBAL << 4, + .st_info = elf.STB_WEAK << 4, .st_other = @intFromEnum(elf.STV.HIDDEN), .st_shndx = elf.SHN_ABS, .st_value = 0, @@ -255,8 +255,10 @@ pub fn allocateSymbols(self: *LinkerDefined, elf_file: *Elf) void { // __dso_handle if (self.dso_handle_index) |index| { - const shdr = shdrs[1]; - allocSymbol(self, index, shdr.sh_addr, 0, elf_file); + if (self.resolveSymbol(index, elf_file).file == self.index) { + const shdr = shdrs[1]; + allocSymbol(self, index, shdr.sh_addr, 0, elf_file); + } } // __GNU_EH_FRAME_HDR From e0acf432482efba4c92029a7dd18037f1607fc27 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Mon, 23 Sep 2024 07:02:21 +0200 Subject: [PATCH 4/4] elf: always override existing __start/__stop symbols --- src/link/Elf/LinkerDefined.zig | 1 - 1 file changed, 1 deletion(-) diff --git a/src/link/Elf/LinkerDefined.zig b/src/link/Elf/LinkerDefined.zig index c01dff49b8..60f9482efb 100644 --- a/src/link/Elf/LinkerDefined.zig +++ b/src/link/Elf/LinkerDefined.zig @@ -158,7 +158,6 @@ pub fn initStartStopSymbols(self: *LinkerDefined, elf_file: *Elf) !void { .index = index, .file = self.index, }, elf_file); - assert(!gop.found_existing); gop.ref.* = .{ .index = index, .file = self.index }; self.symbols_resolver.appendAssumeCapacity(gop.index); }