authorgravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-06-06 00:45:00-04:00
committergravatar for jacobly@ziglang.orgJacob Young <jacobly@ziglang.org> 2025-06-06 00:45:37-04:00
logbcf387f0b9e3911ade500313dc1624b67a011619
tree5b130f0bdcf7aaa0defca7293bc050e687328281
parent25da0f83727e8d04a520474799ee4006e7818508

Elf: support non-comdat groups

I haven't actually found any documentation about these, but apparently groups aren't always comdats.

5 files changed, 92 insertions(+), 91 deletions(-)

src/link/Elf.zig+20-19
...@@ -99,7 +99,7 @@ copy_rel: CopyRelSection = .{},...@@ -99,7 +99,7 @@ copy_rel: CopyRelSection = .{},
99rela_plt: std.ArrayListUnmanaged(elf.Elf64_Rela) = .empty,99rela_plt: std.ArrayListUnmanaged(elf.Elf64_Rela) = .empty,
100/// SHT_GROUP sections100/// SHT_GROUP sections
101/// Applies only to a relocatable.101/// Applies only to a relocatable.
102comdat_group_sections: std.ArrayListUnmanaged(ComdatGroupSection) = .empty,102group_sections: std.ArrayListUnmanaged(GroupSection) = .empty,
103103
104resolver: SymbolResolver = .{},104resolver: SymbolResolver = .{},
105105
...@@ -510,7 +510,7 @@ pub fn deinit(self: *Elf) void {...@@ -510,7 +510,7 @@ pub fn deinit(self: *Elf) void {
510 self.copy_rel.deinit(gpa);510 self.copy_rel.deinit(gpa);
511 self.rela_dyn.deinit(gpa);511 self.rela_dyn.deinit(gpa);
512 self.rela_plt.deinit(gpa);512 self.rela_plt.deinit(gpa);
513 self.comdat_group_sections.deinit(gpa);513 self.group_sections.deinit(gpa);
514 self.dump_argv_list.deinit(gpa);514 self.dump_argv_list.deinit(gpa);
515}515}
516516
...@@ -919,7 +919,7 @@ fn flushModuleInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {...@@ -919,7 +919,7 @@ fn flushModuleInner(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id) !void {
919 &self.sections,919 &self.sections,
920 self.shstrtab.items,920 self.shstrtab.items,
921 self.merge_sections.items,921 self.merge_sections.items,
922 self.comdat_group_sections.items,922 self.group_sections.items,
923 self.zigObjectPtr(),923 self.zigObjectPtr(),
924 self.files,924 self.files,
925 );925 );
...@@ -1315,16 +1315,16 @@ pub fn resolveSymbols(self: *Elf) !void {...@@ -1315,16 +1315,16 @@ pub fn resolveSymbols(self: *Elf) !void {
1315 }1315 }
13161316
1317 {1317 {
1318 // Dedup comdat groups.1318 // Dedup groups.
1319 var table = std.StringHashMap(Ref).init(self.base.comp.gpa);1319 var table = std.StringHashMap(Ref).init(self.base.comp.gpa);
1320 defer table.deinit();1320 defer table.deinit();
13211321
1322 for (self.objects.items) |index| {1322 for (self.objects.items) |index| {
1323 try self.file(index).?.object.resolveComdatGroups(self, &table);1323 try self.file(index).?.object.resolveGroups(self, &table);
1324 }1324 }
13251325
1326 for (self.objects.items) |index| {1326 for (self.objects.items) |index| {
1327 self.file(index).?.object.markComdatGroupsDead(self);1327 self.file(index).?.object.markGroupsDead(self);
1328 }1328 }
1329 }1329 }
13301330
...@@ -3125,7 +3125,7 @@ pub fn sortShdrs(...@@ -3125,7 +3125,7 @@ pub fn sortShdrs(
3125 sections: *std.MultiArrayList(Section),3125 sections: *std.MultiArrayList(Section),
3126 shstrtab: []const u8,3126 shstrtab: []const u8,
3127 merge_sections: []Merge.Section,3127 merge_sections: []Merge.Section,
3128 comdat_group_sections: []ComdatGroupSection,3128 comdat_group_sections: []GroupSection,
3129 zig_object_ptr: ?*ZigObject,3129 zig_object_ptr: ?*ZigObject,
3130 files: std.MultiArrayList(File.Entry),3130 files: std.MultiArrayList(File.Entry),
3131) !void {3131) !void {
...@@ -4446,8 +4446,8 @@ pub fn atom(self: *Elf, ref: Ref) ?*Atom {...@@ -4446,8 +4446,8 @@ pub fn atom(self: *Elf, ref: Ref) ?*Atom {
4446 return file_ptr.atom(ref.index);4446 return file_ptr.atom(ref.index);
4447}4447}
44484448
4449pub fn comdatGroup(self: *Elf, ref: Ref) *ComdatGroup {4449pub fn group(self: *Elf, ref: Ref) *Group {
4450 return self.file(ref.file).?.comdatGroup(ref.index);4450 return self.file(ref.file).?.group(ref.index);
4451}4451}
44524452
4453pub fn symbol(self: *Elf, ref: Ref) ?*Symbol {4453pub fn symbol(self: *Elf, ref: Ref) ?*Symbol {
...@@ -4814,7 +4814,7 @@ fn fmtDumpState(...@@ -4814,7 +4814,7 @@ fn fmtDumpState(
4814 object.fmtCies(self),4814 object.fmtCies(self),
4815 object.fmtFdes(self),4815 object.fmtFdes(self),
4816 object.fmtSymtab(self),4816 object.fmtSymtab(self),
4817 object.fmtComdatGroups(self),4817 object.fmtGroups(self),
4818 });4818 });
4819 }4819 }
48204820
...@@ -4852,9 +4852,9 @@ fn fmtDumpState(...@@ -4852,9 +4852,9 @@ fn fmtDumpState(
4852 try writer.print("{}\n", .{self.got.fmt(self)});4852 try writer.print("{}\n", .{self.got.fmt(self)});
4853 try writer.print("{}\n", .{self.plt.fmt(self)});4853 try writer.print("{}\n", .{self.plt.fmt(self)});
48544854
4855 try writer.writeAll("Output COMDAT groups\n");4855 try writer.writeAll("Output groups\n");
4856 for (self.comdat_group_sections.items) |cg| {4856 for (self.group_sections.items) |cg| {
4857 try writer.print(" shdr({d}) : COMDAT({})\n", .{ cg.shndx, cg.cg_ref });4857 try writer.print(" shdr({d}) : GROUP({})\n", .{ cg.shndx, cg.cg_ref });
4858 }4858 }
48594859
4860 try writer.writeAll("\nOutput merge sections\n");4860 try writer.writeAll("\nOutput merge sections\n");
...@@ -4934,25 +4934,26 @@ const default_entry_addr = 0x8000000;...@@ -4934,25 +4934,26 @@ const default_entry_addr = 0x8000000;
49344934
4935pub const base_tag: link.File.Tag = .elf;4935pub const base_tag: link.File.Tag = .elf;
49364936
4937pub const ComdatGroup = struct {4937pub const Group = struct {
4938 signature_off: u32,4938 signature_off: u32,
4939 file_index: File.Index,4939 file_index: File.Index,
4940 shndx: u32,4940 shndx: u32,
4941 members_start: u32,4941 members_start: u32,
4942 members_len: u32,4942 members_len: u32,
4943 is_comdat: bool,
4943 alive: bool = true,4944 alive: bool = true,
49444945
4945 pub fn file(cg: ComdatGroup, elf_file: *Elf) File {4946 pub fn file(cg: Group, elf_file: *Elf) File {
4946 return elf_file.file(cg.file_index).?;4947 return elf_file.file(cg.file_index).?;
4947 }4948 }
49484949
4949 pub fn signature(cg: ComdatGroup, elf_file: *Elf) [:0]const u8 {4950 pub fn signature(cg: Group, elf_file: *Elf) [:0]const u8 {
4950 return cg.file(elf_file).object.getString(cg.signature_off);4951 return cg.file(elf_file).object.getString(cg.signature_off);
4951 }4952 }
49524953
4953 pub fn comdatGroupMembers(cg: ComdatGroup, elf_file: *Elf) []const u32 {4954 pub fn members(cg: Group, elf_file: *Elf) []const u32 {
4954 const object = cg.file(elf_file).object;4955 const object = cg.file(elf_file).object;
4955 return object.comdat_group_data.items[cg.members_start..][0..cg.members_len];4956 return object.group_data.items[cg.members_start..][0..cg.members_len];
4956 }4957 }
49574958
4958 pub const Index = u32;4959 pub const Index = u32;
...@@ -5310,7 +5311,7 @@ const Air = @import("../Air.zig");...@@ -5310,7 +5311,7 @@ const Air = @import("../Air.zig");
5310const Archive = @import("Elf/Archive.zig");5311const Archive = @import("Elf/Archive.zig");
5311const AtomList = @import("Elf/AtomList.zig");5312const AtomList = @import("Elf/AtomList.zig");
5312const Compilation = @import("../Compilation.zig");5313const Compilation = @import("../Compilation.zig");
5313const ComdatGroupSection = synthetic_sections.ComdatGroupSection;5314const GroupSection = synthetic_sections.GroupSection;
5314const CopyRelSection = synthetic_sections.CopyRelSection;5315const CopyRelSection = synthetic_sections.CopyRelSection;
5315const Diags = @import("../link.zig").Diags;5316const Diags = @import("../link.zig").Diags;
5316const DynamicSection = synthetic_sections.DynamicSection;5317const DynamicSection = synthetic_sections.DynamicSection;
src/link/Elf/Object.zig+45-45
...@@ -20,8 +20,8 @@ atoms: std.ArrayListUnmanaged(Atom) = .empty,...@@ -20,8 +20,8 @@ atoms: std.ArrayListUnmanaged(Atom) = .empty,
20atoms_indexes: std.ArrayListUnmanaged(Atom.Index) = .empty,20atoms_indexes: std.ArrayListUnmanaged(Atom.Index) = .empty,
21atoms_extra: std.ArrayListUnmanaged(u32) = .empty,21atoms_extra: std.ArrayListUnmanaged(u32) = .empty,
2222
23comdat_groups: std.ArrayListUnmanaged(Elf.ComdatGroup) = .empty,23groups: std.ArrayListUnmanaged(Elf.Group) = .empty,
24comdat_group_data: std.ArrayListUnmanaged(u32) = .empty,24group_data: std.ArrayListUnmanaged(u32) = .empty,
2525
26input_merge_sections: std.ArrayListUnmanaged(Merge.InputSection) = .empty,26input_merge_sections: std.ArrayListUnmanaged(Merge.InputSection) = .empty,
27input_merge_sections_indexes: std.ArrayListUnmanaged(Merge.InputSection.Index) = .empty,27input_merge_sections_indexes: std.ArrayListUnmanaged(Merge.InputSection.Index) = .empty,
...@@ -49,8 +49,8 @@ pub fn deinit(self: *Object, gpa: Allocator) void {...@@ -49,8 +49,8 @@ pub fn deinit(self: *Object, gpa: Allocator) void {
49 self.atoms.deinit(gpa);49 self.atoms.deinit(gpa);
50 self.atoms_indexes.deinit(gpa);50 self.atoms_indexes.deinit(gpa);
51 self.atoms_extra.deinit(gpa);51 self.atoms_extra.deinit(gpa);
52 self.comdat_groups.deinit(gpa);52 self.groups.deinit(gpa);
53 self.comdat_group_data.deinit(gpa);53 self.group_data.deinit(gpa);
54 self.relocs.deinit(gpa);54 self.relocs.deinit(gpa);
55 self.fdes.deinit(gpa);55 self.fdes.deinit(gpa);
56 self.cies.deinit(gpa);56 self.cies.deinit(gpa);
...@@ -304,22 +304,22 @@ fn initAtoms(...@@ -304,22 +304,22 @@ fn initAtoms(
304 }304 }
305 const group_members = @as([*]align(1) const u32, @ptrCast(group_raw_data.ptr))[0..group_nmembers];305 const group_members = @as([*]align(1) const u32, @ptrCast(group_raw_data.ptr))[0..group_nmembers];
306306
307 if (group_members[0] != elf.GRP_COMDAT) {307 switch (group_members[0]) {
308 return diags.failParse(path, "corrupt section group: unknown SHT_GROUP format", .{});308 0, elf.GRP_COMDAT => {
309 const group_start: u32 = @intCast(self.group_data.items.len);
310 try self.group_data.appendUnalignedSlice(gpa, group_members[1..]);
311
312 self.group(try self.addGroup(gpa)).* = .{
313 .signature_off = group_signature,
314 .file_index = self.index,
315 .shndx = shndx,
316 .members_start = group_start,
317 .members_len = @intCast(group_nmembers - 1),
318 .is_comdat = group_members[0] == elf.GRP_COMDAT,
319 };
320 },
321 else => return diags.failParse(path, "corrupt section group: unknown SHT_GROUP format", .{}),
309 }322 }
310
311 const group_start: u32 = @intCast(self.comdat_group_data.items.len);
312 try self.comdat_group_data.appendUnalignedSlice(gpa, group_members[1..]);
313
314 const comdat_group_index = try self.addComdatGroup(gpa);
315 const comdat_group = self.comdatGroup(comdat_group_index);
316 comdat_group.* = .{
317 .signature_off = group_signature,
318 .file_index = self.index,
319 .shndx = shndx,
320 .members_start = group_start,
321 .members_len = @intCast(group_nmembers - 1),
322 };
323 },323 },
324324
325 elf.SHT_SYMTAB_SHNDX => @panic("TODO SHT_SYMTAB_SHNDX"),325 elf.SHT_SYMTAB_SHNDX => @panic("TODO SHT_SYMTAB_SHNDX"),
...@@ -986,28 +986,28 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void {...@@ -986,28 +986,28 @@ pub fn convertCommonSymbols(self: *Object, elf_file: *Elf) !void {
986 }986 }
987}987}
988988
989pub fn resolveComdatGroups(self: *Object, elf_file: *Elf, table: anytype) !void {989pub fn resolveGroups(self: *Object, elf_file: *Elf, table: anytype) !void {
990 for (self.comdat_groups.items, 0..) |*cg, cgi| {990 for (self.groups.items, 0..) |*g, gi| {
991 const signature = cg.signature(elf_file);991 const signature = g.signature(elf_file);
992 const gop = try table.getOrPut(signature);992 const gop = try table.getOrPut(signature);
993 if (!gop.found_existing) {993 if (!gop.found_existing) {
994 gop.value_ptr.* = .{ .index = @intCast(cgi), .file = self.index };994 gop.value_ptr.* = .{ .index = @intCast(gi), .file = self.index };
995 continue;995 continue;
996 }996 }
997 const current = elf_file.comdatGroup(gop.value_ptr.*);997 const current = elf_file.group(gop.value_ptr.*);
998 cg.alive = false;998 g.alive = false;
999 if (self.index < current.file_index) {999 if (self.index < current.file_index) {
1000 current.alive = false;1000 current.alive = false;
1001 cg.alive = true;1001 g.alive = true;
1002 gop.value_ptr.* = .{ .index = @intCast(cgi), .file = self.index };1002 gop.value_ptr.* = .{ .index = @intCast(gi), .file = self.index };
1003 }1003 }
1004 }1004 }
1005}1005}
10061006
1007pub fn markComdatGroupsDead(self: *Object, elf_file: *Elf) void {1007pub fn markGroupsDead(self: *Object, elf_file: *Elf) void {
1008 for (self.comdat_groups.items) |cg| {1008 for (self.groups.items) |g| {
1009 if (cg.alive) continue;1009 if (g.alive) continue;
1010 for (cg.comdatGroupMembers(elf_file)) |shndx| {1010 for (g.members(elf_file)) |shndx| {
1011 const atom_index = self.atoms_indexes.items[shndx];1011 const atom_index = self.atoms_indexes.items[shndx];
1012 if (self.atom(atom_index)) |atom_ptr| {1012 if (self.atom(atom_index)) |atom_ptr| {
1013 atom_ptr.alive = false;1013 atom_ptr.alive = false;
...@@ -1421,15 +1421,15 @@ fn inputMergeSection(self: *Object, index: Merge.InputSection.Index) ?*Merge.Inp...@@ -1421,15 +1421,15 @@ fn inputMergeSection(self: *Object, index: Merge.InputSection.Index) ?*Merge.Inp
1421 return &self.input_merge_sections.items[index];1421 return &self.input_merge_sections.items[index];
1422}1422}
14231423
1424fn addComdatGroup(self: *Object, gpa: Allocator) !Elf.ComdatGroup.Index {1424fn addGroup(self: *Object, gpa: Allocator) !Elf.Group.Index {
1425 const index = @as(Elf.ComdatGroup.Index, @intCast(self.comdat_groups.items.len));1425 const index: Elf.Group.Index = @intCast(self.groups.items.len);
1426 _ = try self.comdat_groups.addOne(gpa);1426 _ = try self.groups.addOne(gpa);
1427 return index;1427 return index;
1428}1428}
14291429
1430pub fn comdatGroup(self: *Object, index: Elf.ComdatGroup.Index) *Elf.ComdatGroup {1430pub fn group(self: *Object, index: Elf.Group.Index) *Elf.Group {
1431 assert(index < self.comdat_groups.items.len);1431 assert(index < self.groups.items.len);
1432 return &self.comdat_groups.items[index];1432 return &self.groups.items[index];
1433}1433}
14341434
1435pub fn format(1435pub fn format(
...@@ -1550,14 +1550,14 @@ fn formatFdes(...@@ -1550,14 +1550,14 @@ fn formatFdes(
1550 }1550 }
1551}1551}
15521552
1553pub fn fmtComdatGroups(self: *Object, elf_file: *Elf) std.fmt.Formatter(formatComdatGroups) {1553pub fn fmtGroups(self: *Object, elf_file: *Elf) std.fmt.Formatter(formatGroups) {
1554 return .{ .data = .{1554 return .{ .data = .{
1555 .object = self,1555 .object = self,
1556 .elf_file = elf_file,1556 .elf_file = elf_file,
1557 } };1557 } };
1558}1558}
15591559
1560fn formatComdatGroups(1560fn formatGroups(
1561 ctx: FormatContext,1561 ctx: FormatContext,
1562 comptime unused_fmt_string: []const u8,1562 comptime unused_fmt_string: []const u8,
1563 options: std.fmt.FormatOptions,1563 options: std.fmt.FormatOptions,
...@@ -1567,13 +1567,13 @@ fn formatComdatGroups(...@@ -1567,13 +1567,13 @@ fn formatComdatGroups(
1567 _ = options;1567 _ = options;
1568 const object = ctx.object;1568 const object = ctx.object;
1569 const elf_file = ctx.elf_file;1569 const elf_file = ctx.elf_file;
1570 try writer.writeAll(" COMDAT groups\n");1570 try writer.writeAll(" groups\n");
1571 for (object.comdat_groups.items, 0..) |cg, cg_index| {1571 for (object.groups.items, 0..) |g, g_index| {
1572 try writer.print(" COMDAT({d})", .{cg_index});1572 try writer.print(" {s}({d})", .{ if (g.is_comdat) "COMDAT" else "GROUP", g_index });
1573 if (!cg.alive) try writer.writeAll(" : [*]");1573 if (!g.alive) try writer.writeAll(" : [*]");
1574 try writer.writeByte('\n');1574 try writer.writeByte('\n');
1575 const cg_members = cg.comdatGroupMembers(elf_file);1575 const g_members = g.members(elf_file);
1576 for (cg_members) |shndx| {1576 for (g_members) |shndx| {
1577 const atom_index = object.atoms_indexes.items[shndx];1577 const atom_index = object.atoms_indexes.items[shndx];
1578 const atom_ptr = object.atom(atom_index) orelse continue;1578 const atom_ptr = object.atom(atom_index) orelse continue;
1579 try writer.print(" atom({d}) : {s}\n", .{ atom_index, atom_ptr.name(elf_file) });1579 try writer.print(" atom({d}) : {s}\n", .{ atom_index, atom_ptr.name(elf_file) });
src/link/Elf/file.zig+2-2
...@@ -198,10 +198,10 @@ pub const File = union(enum) {...@@ -198,10 +198,10 @@ pub const File = union(enum) {
198 };198 };
199 }199 }
200200
201 pub fn comdatGroup(file: File, ind: Elf.ComdatGroup.Index) *Elf.ComdatGroup {201 pub fn group(file: File, ind: Elf.Group.Index) *Elf.Group {
202 return switch (file) {202 return switch (file) {
203 .linker_defined, .shared_object, .zig_object => unreachable,203 .linker_defined, .shared_object, .zig_object => unreachable,
204 .object => |x| x.comdatGroup(ind),204 .object => |x| x.group(ind),
205 };205 };
206 }206 }
207207
src/link/Elf/relocatable.zig+13-13
...@@ -19,7 +19,7 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void {...@@ -19,7 +19,7 @@ pub fn flushStaticLib(elf_file: *Elf, comp: *Compilation) !void {
19 &elf_file.sections,19 &elf_file.sections,
20 elf_file.shstrtab.items,20 elf_file.shstrtab.items,
21 elf_file.merge_sections.items,21 elf_file.merge_sections.items,
22 elf_file.comdat_group_sections.items,22 elf_file.group_sections.items,
23 elf_file.zigObjectPtr(),23 elf_file.zigObjectPtr(),
24 elf_file.files,24 elf_file.files,
25 );25 );
...@@ -152,7 +152,7 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation) !void {...@@ -152,7 +152,7 @@ pub fn flushObject(elf_file: *Elf, comp: *Compilation) !void {
152 &elf_file.sections,152 &elf_file.sections,
153 elf_file.shstrtab.items,153 elf_file.shstrtab.items,
154 elf_file.merge_sections.items,154 elf_file.merge_sections.items,
155 elf_file.comdat_group_sections.items,155 elf_file.group_sections.items,
156 elf_file.zigObjectPtr(),156 elf_file.zigObjectPtr(),
157 elf_file.files,157 elf_file.files,
158 );158 );
...@@ -233,19 +233,19 @@ fn initSections(elf_file: *Elf) !void {...@@ -233,19 +233,19 @@ fn initSections(elf_file: *Elf) !void {
233 );233 );
234 }234 }
235235
236 try initComdatGroups(elf_file);236 try initGroups(elf_file);
237 try elf_file.initSymtab();237 try elf_file.initSymtab();
238 try elf_file.initShStrtab();238 try elf_file.initShStrtab();
239}239}
240240
241fn initComdatGroups(elf_file: *Elf) !void {241fn initGroups(elf_file: *Elf) !void {
242 const gpa = elf_file.base.comp.gpa;242 const gpa = elf_file.base.comp.gpa;
243243
244 for (elf_file.objects.items) |index| {244 for (elf_file.objects.items) |index| {
245 const object = elf_file.file(index).?.object;245 const object = elf_file.file(index).?.object;
246 for (object.comdat_groups.items, 0..) |cg, cg_index| {246 for (object.groups.items, 0..) |cg, cg_index| {
247 if (!cg.alive) continue;247 if (!cg.alive) continue;
248 const cg_sec = try elf_file.comdat_group_sections.addOne(gpa);248 const cg_sec = try elf_file.group_sections.addOne(gpa);
249 cg_sec.* = .{249 cg_sec.* = .{
250 .shndx = try elf_file.addSection(.{250 .shndx = try elf_file.addSection(.{
251 .name = try elf_file.insertShString(".group"),251 .name = try elf_file.insertShString(".group"),
...@@ -292,12 +292,12 @@ fn updateSectionSizes(elf_file: *Elf) !void {...@@ -292,12 +292,12 @@ fn updateSectionSizes(elf_file: *Elf) !void {
292 }292 }
293293
294 try elf_file.updateSymtabSize();294 try elf_file.updateSymtabSize();
295 updateComdatGroupsSizes(elf_file);295 updateGroupsSizes(elf_file);
296 elf_file.updateShStrtabSize();296 elf_file.updateShStrtabSize();
297}297}
298298
299fn updateComdatGroupsSizes(elf_file: *Elf) void {299fn updateGroupsSizes(elf_file: *Elf) void {
300 for (elf_file.comdat_group_sections.items) |cg| {300 for (elf_file.group_sections.items) |cg| {
301 const shdr = &elf_file.sections.items(.shdr)[cg.shndx];301 const shdr = &elf_file.sections.items(.shdr)[cg.shndx];
302 shdr.sh_size = cg.size(elf_file);302 shdr.sh_size = cg.size(elf_file);
303 shdr.sh_link = elf_file.section_indexes.symtab.?;303 shdr.sh_link = elf_file.section_indexes.symtab.?;
...@@ -436,21 +436,21 @@ fn writeSyntheticSections(elf_file: *Elf) !void {...@@ -436,21 +436,21 @@ fn writeSyntheticSections(elf_file: *Elf) !void {
436 try elf_file.base.file.?.pwriteAll(mem.sliceAsBytes(relocs.items), shdr.sh_offset);436 try elf_file.base.file.?.pwriteAll(mem.sliceAsBytes(relocs.items), shdr.sh_offset);
437 }437 }
438438
439 try writeComdatGroups(elf_file);439 try writeGroups(elf_file);
440 try elf_file.writeSymtab();440 try elf_file.writeSymtab();
441 try elf_file.writeShStrtab();441 try elf_file.writeShStrtab();
442}442}
443443
444fn writeComdatGroups(elf_file: *Elf) !void {444fn writeGroups(elf_file: *Elf) !void {
445 const gpa = elf_file.base.comp.gpa;445 const gpa = elf_file.base.comp.gpa;
446 for (elf_file.comdat_group_sections.items) |cgs| {446 for (elf_file.group_sections.items) |cgs| {
447 const shdr = elf_file.sections.items(.shdr)[cgs.shndx];447 const shdr = elf_file.sections.items(.shdr)[cgs.shndx];
448 const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;448 const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;
449 var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);449 var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);
450 defer buffer.deinit();450 defer buffer.deinit();
451 try cgs.write(elf_file, buffer.writer());451 try cgs.write(elf_file, buffer.writer());
452 assert(buffer.items.len == sh_size);452 assert(buffer.items.len == sh_size);
453 log.debug("writing COMDAT group from 0x{x} to 0x{x}", .{453 log.debug("writing group from 0x{x} to 0x{x}", .{
454 shdr.sh_offset,454 shdr.sh_offset,
455 shdr.sh_offset + shdr.sh_size,455 shdr.sh_offset + shdr.sh_size,
456 });456 });
src/link/Elf/synthetic_sections.zig+12-12
...@@ -1484,33 +1484,33 @@ pub const VerneedSection = struct {...@@ -1484,33 +1484,33 @@ pub const VerneedSection = struct {
1484 }1484 }
1485};1485};
14861486
1487pub const ComdatGroupSection = struct {1487pub const GroupSection = struct {
1488 shndx: u32,1488 shndx: u32,
1489 cg_ref: Elf.Ref,1489 cg_ref: Elf.Ref,
14901490
1491 fn comdatGroup(cgs: ComdatGroupSection, elf_file: *Elf) *Elf.ComdatGroup {1491 fn group(cgs: GroupSection, elf_file: *Elf) *Elf.Group {
1492 const cg_file = elf_file.file(cgs.cg_ref.file).?;1492 const cg_file = elf_file.file(cgs.cg_ref.file).?;
1493 return cg_file.object.comdatGroup(cgs.cg_ref.index);1493 return cg_file.object.group(cgs.cg_ref.index);
1494 }1494 }
14951495
1496 pub fn symbol(cgs: ComdatGroupSection, elf_file: *Elf) *Symbol {1496 pub fn symbol(cgs: GroupSection, elf_file: *Elf) *Symbol {
1497 const cg = cgs.comdatGroup(elf_file);1497 const cg = cgs.group(elf_file);
1498 const object = cg.file(elf_file).object;1498 const object = cg.file(elf_file).object;
1499 const shdr = object.shdrs.items[cg.shndx];1499 const shdr = object.shdrs.items[cg.shndx];
1500 return &object.symbols.items[shdr.sh_info];1500 return &object.symbols.items[shdr.sh_info];
1501 }1501 }
15021502
1503 pub fn size(cgs: ComdatGroupSection, elf_file: *Elf) usize {1503 pub fn size(cgs: GroupSection, elf_file: *Elf) usize {
1504 const cg = cgs.comdatGroup(elf_file);1504 const cg = cgs.group(elf_file);
1505 const members = cg.comdatGroupMembers(elf_file);1505 const members = cg.members(elf_file);
1506 return (members.len + 1) * @sizeOf(u32);1506 return (members.len + 1) * @sizeOf(u32);
1507 }1507 }
15081508
1509 pub fn write(cgs: ComdatGroupSection, elf_file: *Elf, writer: anytype) !void {1509 pub fn write(cgs: GroupSection, elf_file: *Elf, writer: anytype) !void {
1510 const cg = cgs.comdatGroup(elf_file);1510 const cg = cgs.group(elf_file);
1511 const object = cg.file(elf_file).object;1511 const object = cg.file(elf_file).object;
1512 const members = cg.comdatGroupMembers(elf_file);1512 const members = cg.members(elf_file);
1513 try writer.writeInt(u32, elf.GRP_COMDAT, .little);1513 try writer.writeInt(u32, if (cg.is_comdat) elf.GRP_COMDAT else 0, .little);
1514 for (members) |shndx| {1514 for (members) |shndx| {
1515 const shdr = object.shdrs.items[shndx];1515 const shdr = object.shdrs.items[shndx];
1516 switch (shdr.sh_type) {1516 switch (shdr.sh_type) {