| author | |
| committer | |
| log | c575e3daa4cdb39e38cc0b32fc8fe4a917947d34 |
| tree | d0e01d739543c5783d57e046e301c9179ea5692c |
| parent | fa09276510b03292ace9b8cc72064341530a1940 |
7 files changed, 138 insertions(+), 125 deletions(-)
src/link/Elf.zig+27-92| ... | @@ -215,11 +215,8 @@ merge_subsections: std.ArrayListUnmanaged(MergeSubsection) = .{}, | ... | @@ -215,11 +215,8 @@ merge_subsections: std.ArrayListUnmanaged(MergeSubsection) = .{}, |
| 215 | /// Table of last atom index in a section and matching atom free list if any. | 215 | /// Table of last atom index in a section and matching atom free list if any. |
| 216 | last_atom_and_free_list_table: LastAtomAndFreeListTable = .{}, | 216 | last_atom_and_free_list_table: LastAtomAndFreeListTable = .{}, |
| 217 | 217 | ||
| 218 | comdat_groups_owners: std.ArrayListUnmanaged(ComdatGroupOwner) = .{}, | ||
| 219 | comdat_groups_table: std.ArrayHashMapUnmanaged(ComdatGroupKey, ComdatGroupOwner.Index, ComdatGroupContext, false) = .{}, | ||
| 220 | |||
| 221 | /// Global string table used to provide quick access to global symbol resolvers | 218 | /// Global string table used to provide quick access to global symbol resolvers |
| 222 | /// such as `resolver` and `comdat_groups_table`. | 219 | /// such as `resolver`. |
| 223 | strings: StringTable = .{}, | 220 | strings: StringTable = .{}, |
| 224 | 221 | ||
| 225 | first_eflags: ?elf.Elf64_Word = null, | 222 | first_eflags: ?elf.Elf64_Word = null, |
| ... | @@ -506,8 +503,6 @@ pub fn deinit(self: *Elf) void { | ... | @@ -506,8 +503,6 @@ pub fn deinit(self: *Elf) void { |
| 506 | } | 503 | } |
| 507 | self.last_atom_and_free_list_table.deinit(gpa); | 504 | self.last_atom_and_free_list_table.deinit(gpa); |
| 508 | 505 | ||
| 509 | self.comdat_groups_owners.deinit(gpa); | ||
| 510 | self.comdat_groups_table.deinit(gpa); | ||
| 511 | self.strings.deinit(gpa); | 506 | self.strings.deinit(gpa); |
| 512 | 507 | ||
| 513 | self.got.deinit(gpa); | 508 | self.got.deinit(gpa); |
| ... | @@ -1305,7 +1300,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod | ... | @@ -1305,7 +1300,7 @@ pub fn flushModule(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_nod |
| 1305 | // input Object files. | 1300 | // input Object files. |
| 1306 | // Any qualifing unresolved symbol will be upgraded to an absolute, weak | 1301 | // Any qualifing unresolved symbol will be upgraded to an absolute, weak |
| 1307 | // symbol for potential resolution at load-time. | 1302 | // symbol for potential resolution at load-time. |
| 1308 | self.resolveSymbols(); | 1303 | try self.resolveSymbols(); |
| 1309 | self.markEhFrameAtomsDead(); | 1304 | self.markEhFrameAtomsDead(); |
| 1310 | try self.resolveMergeSections(); | 1305 | try self.resolveMergeSections(); |
| 1311 | 1306 | ||
| ... | @@ -1955,7 +1950,7 @@ fn accessLibPath( | ... | @@ -1955,7 +1950,7 @@ fn accessLibPath( |
| 1955 | /// 4. Reset state of all resolved globals since we will redo this bit on the pruned set. | 1950 | /// 4. Reset state of all resolved globals since we will redo this bit on the pruned set. |
| 1956 | /// 5. Remove references to dead objects/shared objects | 1951 | /// 5. Remove references to dead objects/shared objects |
| 1957 | /// 6. Re-run symbol resolution on pruned objects and shared objects sets. | 1952 | /// 6. Re-run symbol resolution on pruned objects and shared objects sets. |
| 1958 | pub fn resolveSymbols(self: *Elf) void { | 1953 | pub fn resolveSymbols(self: *Elf) !void { |
| 1959 | // Resolve symbols in the ZigObject. For now, we assume that it's always live. | 1954 | // Resolve symbols in the ZigObject. For now, we assume that it's always live. |
| 1960 | if (self.zigObjectPtr()) |zig_object| zig_object.asFile().resolveSymbols(self); | 1955 | if (self.zigObjectPtr()) |zig_object| zig_object.asFile().resolveSymbols(self); |
| 1961 | // Resolve symbols on the set of all objects and shared objects (even if some are unneeded). | 1956 | // Resolve symbols on the set of all objects and shared objects (even if some are unneeded). |
| ... | @@ -1986,32 +1981,17 @@ pub fn resolveSymbols(self: *Elf) void { | ... | @@ -1986,32 +1981,17 @@ pub fn resolveSymbols(self: *Elf) void { |
| 1986 | } else i += 1; | 1981 | } else i += 1; |
| 1987 | } | 1982 | } |
| 1988 | 1983 | ||
| 1989 | // Dedup comdat groups. | 1984 | { |
| 1990 | for (self.objects.items) |index| { | 1985 | // Dedup comdat groups. |
| 1991 | const object = self.file(index).?.object; | 1986 | var table = std.StringHashMap(Ref).init(self.base.comp.gpa); |
| 1992 | for (object.comdat_groups.items) |cg| { | 1987 | defer table.deinit(); |
| 1993 | const cg_owner = self.comdatGroupOwner(cg.owner); | 1988 | |
| 1994 | const owner_file_index = if (self.file(cg_owner.file)) |file_ptr| | 1989 | for (self.objects.items) |index| { |
| 1995 | file_ptr.object.index | 1990 | try self.file(index).?.object.resolveComdatGroups(self, &table); |
| 1996 | else | ||
| 1997 | std.math.maxInt(File.Index); | ||
| 1998 | cg_owner.file = @min(owner_file_index, index); | ||
| 1999 | } | 1991 | } |
| 2000 | } | ||
| 2001 | 1992 | ||
| 2002 | for (self.objects.items) |index| { | 1993 | for (self.objects.items) |index| { |
| 2003 | const object = self.file(index).?.object; | 1994 | self.file(index).?.object.markComdatGroupsDead(self); |
| 2004 | for (object.comdat_groups.items) |cg| { | ||
| 2005 | const cg_owner = self.comdatGroupOwner(cg.owner); | ||
| 2006 | if (cg_owner.file != index) { | ||
| 2007 | for (cg.comdatGroupMembers(self)) |shndx| { | ||
| 2008 | const atom_index = object.atoms_indexes.items[shndx]; | ||
| 2009 | if (object.atom(atom_index)) |atom_ptr| { | ||
| 2010 | atom_ptr.flags.alive = false; | ||
| 2011 | atom_ptr.markFdesDead(self); | ||
| 2012 | } | ||
| 2013 | } | ||
| 2014 | } | ||
| 2015 | } | 1995 | } |
| 2016 | } | 1996 | } |
| 2017 | 1997 | ||
| ... | @@ -5632,6 +5612,10 @@ pub fn atom(self: *Elf, ref: Ref) ?*Atom { | ... | @@ -5632,6 +5612,10 @@ pub fn atom(self: *Elf, ref: Ref) ?*Atom { |
| 5632 | return file_ptr.atom(ref.index); | 5612 | return file_ptr.atom(ref.index); |
| 5633 | } | 5613 | } |
| 5634 | 5614 | ||
| 5615 | pub fn comdatGroup(self: *Elf, ref: Ref) *ComdatGroup { | ||
| 5616 | return self.file(ref.file).?.comdatGroup(ref.index); | ||
| 5617 | } | ||
| 5618 | |||
| 5635 | /// Returns pointer-to-symbol described at sym_index. | 5619 | /// Returns pointer-to-symbol described at sym_index. |
| 5636 | pub fn symbol(self: *Elf, sym_index: Symbol.Index) *Symbol { | 5620 | pub fn symbol(self: *Elf, sym_index: Symbol.Index) *Symbol { |
| 5637 | return &self.symbols.items[sym_index]; | 5621 | return &self.symbols.items[sym_index]; |
| ... | @@ -5737,31 +5721,6 @@ pub fn zigObjectPtr(self: *Elf) ?*ZigObject { | ... | @@ -5737,31 +5721,6 @@ pub fn zigObjectPtr(self: *Elf) ?*ZigObject { |
| 5737 | return self.file(index).?.zig_object; | 5721 | return self.file(index).?.zig_object; |
| 5738 | } | 5722 | } |
| 5739 | 5723 | ||
| 5740 | const GetOrCreateComdatGroupOwnerResult = struct { | ||
| 5741 | found_existing: bool, | ||
| 5742 | index: ComdatGroupOwner.Index, | ||
| 5743 | }; | ||
| 5744 | |||
| 5745 | pub fn getOrCreateComdatGroupOwner(self: *Elf, key: ComdatGroupKey) !GetOrCreateComdatGroupOwnerResult { | ||
| 5746 | const gpa = self.base.comp.gpa; | ||
| 5747 | const gop = try self.comdat_groups_table.getOrPutContext(gpa, key, .{ .elf_file = self }); | ||
| 5748 | if (!gop.found_existing) { | ||
| 5749 | const index: ComdatGroupOwner.Index = @intCast(self.comdat_groups_owners.items.len); | ||
| 5750 | const owner = try self.comdat_groups_owners.addOne(gpa); | ||
| 5751 | owner.* = .{}; | ||
| 5752 | gop.value_ptr.* = index; | ||
| 5753 | } | ||
| 5754 | return .{ | ||
| 5755 | .found_existing = gop.found_existing, | ||
| 5756 | .index = gop.value_ptr.*, | ||
| 5757 | }; | ||
| 5758 | } | ||
| 5759 | |||
| 5760 | pub fn comdatGroupOwner(self: *Elf, index: ComdatGroupOwner.Index) *ComdatGroupOwner { | ||
| 5761 | assert(index < self.comdat_groups_owners.items.len); | ||
| 5762 | return &self.comdat_groups_owners.items[index]; | ||
| 5763 | } | ||
| 5764 | |||
| 5765 | pub fn addMergeSubsection(self: *Elf) !MergeSubsection.Index { | 5724 | pub fn addMergeSubsection(self: *Elf) !MergeSubsection.Index { |
| 5766 | const index: MergeSubsection.Index = @intCast(self.merge_subsections.items.len); | 5725 | const index: MergeSubsection.Index = @intCast(self.merge_subsections.items.len); |
| 5767 | const msec = try self.merge_subsections.addOne(self.base.comp.gpa); | 5726 | const msec = try self.merge_subsections.addOne(self.base.comp.gpa); |
| ... | @@ -6243,48 +6202,24 @@ const default_entry_addr = 0x8000000; | ... | @@ -6243,48 +6202,24 @@ const default_entry_addr = 0x8000000; |
| 6243 | 6202 | ||
| 6244 | pub const base_tag: link.File.Tag = .elf; | 6203 | pub const base_tag: link.File.Tag = .elf; |
| 6245 | 6204 | ||
| 6246 | const ComdatGroupKey = struct { | 6205 | pub const ComdatGroup = struct { |
| 6247 | /// String table offset. | 6206 | signature_off: u32, |
| 6248 | off: u32, | ||
| 6249 | |||
| 6250 | /// File index. | ||
| 6251 | file_index: File.Index, | 6207 | file_index: File.Index, |
| 6208 | shndx: u32, | ||
| 6209 | members_start: u32, | ||
| 6210 | members_len: u32, | ||
| 6211 | alive: bool = true, | ||
| 6252 | 6212 | ||
| 6253 | pub fn get(key: ComdatGroupKey, elf_file: *Elf) [:0]const u8 { | 6213 | pub fn file(cg: ComdatGroup, elf_file: *Elf) File { |
| 6254 | const file_ptr = elf_file.file(key.file_index).?; | 6214 | return elf_file.file(cg.file_index).?; |
| 6255 | return file_ptr.getString(key.off); | ||
| 6256 | } | ||
| 6257 | }; | ||
| 6258 | |||
| 6259 | const ComdatGroupContext = struct { | ||
| 6260 | elf_file: *Elf, | ||
| 6261 | |||
| 6262 | pub fn eql(ctx: ComdatGroupContext, a: ComdatGroupKey, b: ComdatGroupKey, b_index: usize) bool { | ||
| 6263 | _ = b_index; | ||
| 6264 | const elf_file = ctx.elf_file; | ||
| 6265 | return mem.eql(u8, a.get(elf_file), b.get(elf_file)); | ||
| 6266 | } | 6215 | } |
| 6267 | 6216 | ||
| 6268 | pub fn hash(ctx: ComdatGroupContext, a: ComdatGroupKey) u32 { | 6217 | pub fn signature(cg: ComdatGroup, elf_file: *Elf) [:0]const u8 { |
| 6269 | return std.array_hash_map.hashString(a.get(ctx.elf_file)); | 6218 | return cg.file(elf_file).object.getString(cg.signature_off); |
| 6270 | } | 6219 | } |
| 6271 | }; | ||
| 6272 | |||
| 6273 | const ComdatGroupOwner = struct { | ||
| 6274 | file: File.Index = 0, | ||
| 6275 | |||
| 6276 | const Index = u32; | ||
| 6277 | }; | ||
| 6278 | |||
| 6279 | pub const ComdatGroup = struct { | ||
| 6280 | owner: ComdatGroupOwner.Index, | ||
| 6281 | file: File.Index, | ||
| 6282 | shndx: u32, | ||
| 6283 | members_start: u32, | ||
| 6284 | members_len: u32, | ||
| 6285 | 6220 | ||
| 6286 | pub fn comdatGroupMembers(cg: ComdatGroup, elf_file: *Elf) []const u32 { | 6221 | pub fn comdatGroupMembers(cg: ComdatGroup, elf_file: *Elf) []const u32 { |
| 6287 | const object = elf_file.file(cg.file).?.object; | 6222 | const object = cg.file(elf_file).object; |
| 6288 | return object.comdat_group_data.items[cg.members_start..][0..cg.members_len]; | 6223 | return object.comdat_group_data.items[cg.members_start..][0..cg.members_len]; |
| 6289 | } | 6224 | } |
| 6290 | 6225 |
src/link/Elf/Atom.zig+4-1| ... | @@ -346,7 +346,10 @@ pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.El | ... | @@ -346,7 +346,10 @@ pub fn writeRelocs(self: Atom, elf_file: *Elf, out_relocs: *std.ArrayList(elf.El |
| 346 | r_sym = elf_file.sectionSymbolOutputSymtabIndex(msub.mergeSection(elf_file).output_section_index); | 346 | r_sym = elf_file.sectionSymbolOutputSymtabIndex(msub.mergeSection(elf_file).output_section_index); |
| 347 | } else { | 347 | } else { |
| 348 | r_addend += @intCast(target.address(.{}, elf_file)); | 348 | r_addend += @intCast(target.address(.{}, elf_file)); |
| 349 | r_sym = elf_file.sectionSymbolOutputSymtabIndex(target.outputShndx().?); | 349 | r_sym = if (target.outputShndx()) |osec| |
| 350 | elf_file.sectionSymbolOutputSymtabIndex(osec) | ||
| 351 | else | ||
| 352 | 0; | ||
| 350 | }, | 353 | }, |
| 351 | else => { | 354 | else => { |
| 352 | r_sym = target.outputSymtabIndex(elf_file) orelse 0; | 355 | r_sym = target.outputSymtabIndex(elf_file) orelse 0; |
src/link/Elf/Object.zig+58-13| ... | @@ -216,27 +216,41 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file: | ... | @@ -216,27 +216,41 @@ fn initAtoms(self: *Object, allocator: Allocator, handle: std.fs.File, elf_file: |
| 216 | const shndx = @as(u32, @intCast(i)); | 216 | const shndx = @as(u32, @intCast(i)); |
| 217 | const group_raw_data = try self.preadShdrContentsAlloc(allocator, handle, shndx); | 217 | const group_raw_data = try self.preadShdrContentsAlloc(allocator, handle, shndx); |
| 218 | defer allocator.free(group_raw_data); | 218 | defer allocator.free(group_raw_data); |
| 219 | const group_nmembers = @divExact(group_raw_data.len, @sizeOf(u32)); | 219 | const group_nmembers = math.divExact(usize, group_raw_data.len, @sizeOf(u32)) catch { |
| 220 | try elf_file.reportParseError2( | ||
| 221 | self.index, | ||
| 222 | "corrupt section group: not evenly divisible ", | ||
| 223 | .{}, | ||
| 224 | ); | ||
| 225 | return error.MalformedObject; | ||
| 226 | }; | ||
| 227 | if (group_nmembers == 0) { | ||
| 228 | try elf_file.reportParseError2( | ||
| 229 | self.index, | ||
| 230 | "corrupt section group: empty section", | ||
| 231 | .{}, | ||
| 232 | ); | ||
| 233 | return error.MalformedObject; | ||
| 234 | } | ||
| 220 | const group_members = @as([*]align(1) const u32, @ptrCast(group_raw_data.ptr))[0..group_nmembers]; | 235 | const group_members = @as([*]align(1) const u32, @ptrCast(group_raw_data.ptr))[0..group_nmembers]; |
| 221 | 236 | ||
| 222 | if (group_members[0] != elf.GRP_COMDAT) { | 237 | if (group_members[0] != elf.GRP_COMDAT) { |
| 223 | // TODO convert into an error | 238 | try elf_file.reportParseError2( |
| 224 | log.debug("{}: unknown SHT_GROUP format", .{self.fmtPath()}); | 239 | self.index, |
| 225 | continue; | 240 | "corrupt section group: unknown SHT_GROUP format", |
| 241 | .{}, | ||
| 242 | ); | ||
| 243 | return error.MalformedObject; | ||
| 226 | } | 244 | } |
| 227 | 245 | ||
| 228 | const group_start = @as(u32, @intCast(self.comdat_group_data.items.len)); | 246 | const group_start = @as(u32, @intCast(self.comdat_group_data.items.len)); |
| 229 | try self.comdat_group_data.appendUnalignedSlice(allocator, group_members[1..]); | 247 | try self.comdat_group_data.appendUnalignedSlice(allocator, group_members[1..]); |
| 230 | 248 | ||
| 231 | const gop = try elf_file.getOrCreateComdatGroupOwner(.{ | ||
| 232 | .off = group_signature, | ||
| 233 | .file_index = self.index, | ||
| 234 | }); | ||
| 235 | const comdat_group_index = try self.addComdatGroup(allocator); | 249 | const comdat_group_index = try self.addComdatGroup(allocator); |
| 236 | const comdat_group = self.comdatGroup(comdat_group_index); | 250 | const comdat_group = self.comdatGroup(comdat_group_index); |
| 237 | comdat_group.* = .{ | 251 | comdat_group.* = .{ |
| 238 | .owner = gop.index, | 252 | .signature_off = group_signature, |
| 239 | .file = self.index, | 253 | .file_index = self.index, |
| 240 | .shndx = shndx, | 254 | .shndx = shndx, |
| 241 | .members_start = group_start, | 255 | .members_start = group_start, |
| 242 | .members_len = @intCast(group_nmembers - 1), | 256 | .members_len = @intCast(group_nmembers - 1), |
| ... | @@ -912,6 +926,37 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void { | ... | @@ -912,6 +926,37 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void { |
| 912 | } | 926 | } |
| 913 | } | 927 | } |
| 914 | 928 | ||
| 929 | pub fn resolveComdatGroups(self: *Object, elf_file: *Elf, table: anytype) !void { | ||
| 930 | for (self.comdat_groups.items, 0..) |*cg, cgi| { | ||
| 931 | const signature = cg.signature(elf_file); | ||
| 932 | const gop = try table.getOrPut(signature); | ||
| 933 | if (!gop.found_existing) { | ||
| 934 | gop.value_ptr.* = .{ .index = @intCast(cgi), .file = self.index }; | ||
| 935 | continue; | ||
| 936 | } | ||
| 937 | const current = elf_file.comdatGroup(gop.value_ptr.*); | ||
| 938 | cg.alive = false; | ||
| 939 | if (self.index < current.file_index) { | ||
| 940 | current.alive = false; | ||
| 941 | cg.alive = true; | ||
| 942 | gop.value_ptr.* = .{ .index = @intCast(cgi), .file = self.index }; | ||
| 943 | } | ||
| 944 | } | ||
| 945 | } | ||
| 946 | |||
| 947 | pub fn markComdatGroupsDead(self: *Object, elf_file: *Elf) void { | ||
| 948 | for (self.comdat_groups.items) |cg| { | ||
| 949 | if (cg.alive) continue; | ||
| 950 | for (cg.comdatGroupMembers(elf_file)) |shndx| { | ||
| 951 | const atom_index = self.atoms_indexes.items[shndx]; | ||
| 952 | if (self.atom(atom_index)) |atom_ptr| { | ||
| 953 | atom_ptr.flags.alive = false; | ||
| 954 | atom_ptr.markFdesDead(elf_file); | ||
| 955 | } | ||
| 956 | } | ||
| 957 | } | ||
| 958 | } | ||
| 959 | |||
| 915 | pub fn initOutputSections(self: *Object, elf_file: *Elf) !void { | 960 | pub fn initOutputSections(self: *Object, elf_file: *Elf) !void { |
| 916 | for (self.atoms_indexes.items) |atom_index| { | 961 | for (self.atoms_indexes.items) |atom_index| { |
| 917 | const atom_ptr = self.atom(atom_index) orelse continue; | 962 | const atom_ptr = self.atom(atom_index) orelse continue; |
| ... | @@ -1428,9 +1473,9 @@ fn formatComdatGroups( | ... | @@ -1428,9 +1473,9 @@ fn formatComdatGroups( |
| 1428 | const elf_file = ctx.elf_file; | 1473 | const elf_file = ctx.elf_file; |
| 1429 | try writer.writeAll(" COMDAT groups\n"); | 1474 | try writer.writeAll(" COMDAT groups\n"); |
| 1430 | for (object.comdat_groups.items, 0..) |cg, cg_index| { | 1475 | for (object.comdat_groups.items, 0..) |cg, cg_index| { |
| 1431 | const cg_owner = elf_file.comdatGroupOwner(cg.owner); | 1476 | try writer.print(" COMDAT({d})", .{cg_index}); |
| 1432 | if (cg_owner.file != object.index) continue; | 1477 | if (!cg.alive) try writer.writeAll(" : [*]"); |
| 1433 | try writer.print(" COMDAT({d})\n", .{cg_index}); | 1478 | try writer.writeByte('\n'); |
| 1434 | const cg_members = cg.comdatGroupMembers(elf_file); | 1479 | const cg_members = cg.comdatGroupMembers(elf_file); |
| 1435 | for (cg_members) |shndx| { | 1480 | for (cg_members) |shndx| { |
| 1436 | const atom_index = object.atoms_indexes.items[shndx]; | 1481 | const atom_index = object.atoms_indexes.items[shndx]; |
src/link/Elf/file.zig+7| ... | @@ -137,6 +137,13 @@ pub const File = union(enum) { | ... | @@ -137,6 +137,13 @@ pub const File = union(enum) { |
| 137 | }; | 137 | }; |
| 138 | } | 138 | } |
| 139 | 139 | ||
| 140 | pub fn comdatGroup(file: File, ind: Elf.ComdatGroup.Index) *Elf.ComdatGroup { | ||
| 141 | return switch (file) { | ||
| 142 | .linker_defined, .shared_object, .zig_object => unreachable, | ||
| 143 | .object => |x| x.comdatGroup(ind), | ||
| 144 | }; | ||
| 145 | } | ||
| 146 | |||
| 140 | pub fn symbol(file: File, ind: Symbol.Index) Symbol.Index { | 147 | pub fn symbol(file: File, ind: Symbol.Index) Symbol.Index { |
| 141 | return switch (file) { | 148 | return switch (file) { |
| 142 | .zig_object => |x| x.symbol(ind), | 149 | .zig_object => |x| x.symbol(ind), |
src/link/Elf/relocatable.zig+2-5| ... | @@ -190,7 +190,7 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const | ... | @@ -190,7 +190,7 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation, module_obj_path: ?[]const |
| 190 | // Now, we are ready to resolve the symbols across all input files. | 190 | // Now, we are ready to resolve the symbols across all input files. |
| 191 | // We will first resolve the files in the ZigObject, next in the parsed | 191 | // We will first resolve the files in the ZigObject, next in the parsed |
| 192 | // input Object files. | 192 | // input Object files. |
| 193 | elf_file.resolveSymbols(); | 193 | try elf_file.resolveSymbols(); |
| 194 | elf_file.markEhFrameAtomsDead(); | 194 | elf_file.markEhFrameAtomsDead(); |
| 195 | try elf_file.resolveMergeSections(); | 195 | try elf_file.resolveMergeSections(); |
| 196 | try elf_file.addCommentString(); | 196 | try elf_file.addCommentString(); |
| ... | @@ -318,11 +318,8 @@ fn initComdatGroups(elf_file: *Elf) !void { | ... | @@ -318,11 +318,8 @@ fn initComdatGroups(elf_file: *Elf) !void { |
| 318 | 318 | ||
| 319 | for (elf_file.objects.items) |index| { | 319 | for (elf_file.objects.items) |index| { |
| 320 | const object = elf_file.file(index).?.object; | 320 | const object = elf_file.file(index).?.object; |
| 321 | |||
| 322 | for (object.comdat_groups.items, 0..) |cg, cg_index| { | 321 | for (object.comdat_groups.items, 0..) |cg, cg_index| { |
| 323 | const cg_owner = elf_file.comdatGroupOwner(cg.owner); | 322 | if (!cg.alive) continue; |
| 324 | if (cg_owner.file != index) continue; | ||
| 325 | |||
| 326 | const cg_sec = try elf_file.comdat_group_sections.addOne(gpa); | 323 | const cg_sec = try elf_file.comdat_group_sections.addOne(gpa); |
| 327 | cg_sec.* = .{ | 324 | cg_sec.* = .{ |
| 328 | .shndx = try elf_file.addSection(.{ | 325 | .shndx = try elf_file.addSection(.{ |
src/link/Elf/synthetic_sections.zig+2-8| ... | @@ -1672,12 +1672,6 @@ pub const ComdatGroupSection = struct { | ... | @@ -1672,12 +1672,6 @@ pub const ComdatGroupSection = struct { |
| 1672 | shndx: u32, | 1672 | shndx: u32, |
| 1673 | cg_ref: Elf.Ref, | 1673 | cg_ref: Elf.Ref, |
| 1674 | 1674 | ||
| 1675 | fn ownerFile(cgs: ComdatGroupSection, elf_file: *Elf) ?File { | ||
| 1676 | const cg = cgs.comdatGroup(elf_file); | ||
| 1677 | const cg_owner = elf_file.comdatGroupOwner(cg.owner); | ||
| 1678 | return elf_file.file(cg_owner.file); | ||
| 1679 | } | ||
| 1680 | |||
| 1681 | fn comdatGroup(cgs: ComdatGroupSection, elf_file: *Elf) *Elf.ComdatGroup { | 1675 | fn comdatGroup(cgs: ComdatGroupSection, elf_file: *Elf) *Elf.ComdatGroup { |
| 1682 | const cg_file = elf_file.file(cgs.cg_ref.file).?; | 1676 | const cg_file = elf_file.file(cgs.cg_ref.file).?; |
| 1683 | return cg_file.object.comdatGroup(cgs.cg_ref.index); | 1677 | return cg_file.object.comdatGroup(cgs.cg_ref.index); |
| ... | @@ -1685,7 +1679,7 @@ pub const ComdatGroupSection = struct { | ... | @@ -1685,7 +1679,7 @@ pub const ComdatGroupSection = struct { |
| 1685 | 1679 | ||
| 1686 | pub fn symbol(cgs: ComdatGroupSection, elf_file: *Elf) Symbol.Index { | 1680 | pub fn symbol(cgs: ComdatGroupSection, elf_file: *Elf) Symbol.Index { |
| 1687 | const cg = cgs.comdatGroup(elf_file); | 1681 | const cg = cgs.comdatGroup(elf_file); |
| 1688 | const object = cgs.ownerFile(elf_file).?.object; | 1682 | const object = cg.file(elf_file).object; |
| 1689 | const shdr = object.shdrs.items[cg.shndx]; | 1683 | const shdr = object.shdrs.items[cg.shndx]; |
| 1690 | return object.symbols.items[shdr.sh_info]; | 1684 | return object.symbols.items[shdr.sh_info]; |
| 1691 | } | 1685 | } |
| ... | @@ -1698,7 +1692,7 @@ pub const ComdatGroupSection = struct { | ... | @@ -1698,7 +1692,7 @@ pub const ComdatGroupSection = struct { |
| 1698 | 1692 | ||
| 1699 | pub fn write(cgs: ComdatGroupSection, elf_file: *Elf, writer: anytype) !void { | 1693 | pub fn write(cgs: ComdatGroupSection, elf_file: *Elf, writer: anytype) !void { |
| 1700 | const cg = cgs.comdatGroup(elf_file); | 1694 | const cg = cgs.comdatGroup(elf_file); |
| 1701 | const object = cgs.ownerFile(elf_file).?.object; | 1695 | const object = cg.file(elf_file).object; |
| 1702 | const members = cg.comdatGroupMembers(elf_file); | 1696 | const members = cg.comdatGroupMembers(elf_file); |
| 1703 | try writer.writeInt(u32, elf.GRP_COMDAT, .little); | 1697 | try writer.writeInt(u32, elf.GRP_COMDAT, .little); |
| 1704 | for (members) |shndx| { | 1698 | for (members) |shndx| { |
test/link/elf.zig+38-6| ... | @@ -404,9 +404,7 @@ fn testComdatElimination(b: *Build, opts: Options) *Step { | ... | @@ -404,9 +404,7 @@ fn testComdatElimination(b: *Build, opts: Options) *Step { |
| 404 | main_o.linkLibCpp(); | 404 | main_o.linkLibCpp(); |
| 405 | 405 | ||
| 406 | { | 406 | { |
| 407 | const exe = addExecutable(b, opts, .{ | 407 | const exe = addExecutable(b, opts, .{ .name = "main1" }); |
| 408 | .name = "main1", | ||
| 409 | }); | ||
| 410 | exe.addObject(a_o); | 408 | exe.addObject(a_o); |
| 411 | exe.addObject(main_o); | 409 | exe.addObject(main_o); |
| 412 | exe.linkLibCpp(); | 410 | exe.linkLibCpp(); |
| ... | @@ -431,9 +429,7 @@ fn testComdatElimination(b: *Build, opts: Options) *Step { | ... | @@ -431,9 +429,7 @@ fn testComdatElimination(b: *Build, opts: Options) *Step { |
| 431 | } | 429 | } |
| 432 | 430 | ||
| 433 | { | 431 | { |
| 434 | const exe = addExecutable(b, opts, .{ | 432 | const exe = addExecutable(b, opts, .{ .name = "main2" }); |
| 435 | .name = "main2", | ||
| 436 | }); | ||
| 437 | exe.addObject(main_o); | 433 | exe.addObject(main_o); |
| 438 | exe.addObject(a_o); | 434 | exe.addObject(a_o); |
| 439 | exe.linkLibCpp(); | 435 | exe.linkLibCpp(); |
| ... | @@ -457,6 +453,42 @@ fn testComdatElimination(b: *Build, opts: Options) *Step { | ... | @@ -457,6 +453,42 @@ fn testComdatElimination(b: *Build, opts: Options) *Step { |
| 457 | test_step.dependOn(&check.step); | 453 | test_step.dependOn(&check.step); |
| 458 | } | 454 | } |
| 459 | 455 | ||
| 456 | { | ||
| 457 | const c_o = addObject(b, opts, .{ .name = "c" }); | ||
| 458 | c_o.addObject(main_o); | ||
| 459 | c_o.addObject(a_o); | ||
| 460 | |||
| 461 | const exe = addExecutable(b, opts, .{ .name = "main3" }); | ||
| 462 | exe.addObject(c_o); | ||
| 463 | exe.linkLibCpp(); | ||
| 464 | |||
| 465 | const run = addRunArtifact(exe); | ||
| 466 | run.expectStdOutEqual( | ||
| 467 | \\calling foo in main | ||
| 468 | \\calling foo in main | ||
| 469 | \\ | ||
| 470 | ); | ||
| 471 | test_step.dependOn(&run.step); | ||
| 472 | } | ||
| 473 | |||
| 474 | { | ||
| 475 | const d_o = addObject(b, opts, .{ .name = "d" }); | ||
| 476 | d_o.addObject(a_o); | ||
| 477 | d_o.addObject(main_o); | ||
| 478 | |||
| 479 | const exe = addExecutable(b, opts, .{ .name = "main4" }); | ||
| 480 | exe.addObject(d_o); | ||
| 481 | exe.linkLibCpp(); | ||
| 482 | |||
| 483 | const run = addRunArtifact(exe); | ||
| 484 | run.expectStdOutEqual( | ||
| 485 | \\calling foo in a | ||
| 486 | \\calling foo in a | ||
| 487 | \\ | ||
| 488 | ); | ||
| 489 | test_step.dependOn(&run.step); | ||
| 490 | } | ||
| 491 | |||
| 460 | return test_step; | 492 | return test_step; |
| 461 | } | 493 | } |
| 462 | 494 |