authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-11-09 17:41:14+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2023-11-09 17:41:14+01:00
logacd7cbf0b51dbc8039387de285e2b391a78f59ae
treeff25ff13f548d88379c42ed7d645b159713c4dc3
parent031d9faf022eb58c688033148f5a1fa145c6d84c

elf: init output COMDAT group sections


4 files changed, 76 insertions(+), 5 deletions(-)

lib/std/elf.zig+2
...@@ -1664,6 +1664,8 @@ pub const EM = enum(u16) {...@@ -1664,6 +1664,8 @@ pub const EM = enum(u16) {
1664 }1664 }
1665};1665};
16661666
1667pub const GRP_COMDAT = 1;
1668
1667/// Section data should be writable during execution.1669/// Section data should be writable during execution.
1668pub const SHF_WRITE = 0x1;1670pub const SHF_WRITE = 0x1;
16691671
src/link/Elf.zig+46-2
...@@ -102,6 +102,9 @@ copy_rel: CopyRelSection = .{},...@@ -102,6 +102,9 @@ copy_rel: CopyRelSection = .{},
102rela_plt: std.ArrayListUnmanaged(elf.Elf64_Rela) = .{},102rela_plt: std.ArrayListUnmanaged(elf.Elf64_Rela) = .{},
103/// .got.zig section103/// .got.zig section
104zig_got: ZigGotSection = .{},104zig_got: ZigGotSection = .{},
105/// SHT_GROUP sections
106/// Applies only to a relocatable.
107comdat_group_sections: std.ArrayListUnmanaged(ComdatGroupSection) = .{},
105108
106/// Tracked section headers with incremental updates to Zig object.109/// Tracked section headers with incremental updates to Zig object.
107/// .rela.* sections are only used when emitting a relocatable object file.110/// .rela.* sections are only used when emitting a relocatable object file.
...@@ -394,6 +397,7 @@ pub fn deinit(self: *Elf) void {...@@ -394,6 +397,7 @@ pub fn deinit(self: *Elf) void {
394 self.rela_dyn.deinit(gpa);397 self.rela_dyn.deinit(gpa);
395 self.rela_plt.deinit(gpa);398 self.rela_plt.deinit(gpa);
396 self.zig_got.deinit(gpa);399 self.zig_got.deinit(gpa);
400 self.comdat_group_sections.deinit(gpa);
397}401}
398402
399pub fn getDeclVAddr(self: *Elf, decl_index: Module.Decl.Index, reloc_info: link.File.RelocInfo) !u64 {403pub fn getDeclVAddr(self: *Elf, decl_index: Module.Decl.Index, reloc_info: link.File.RelocInfo) !u64 {
...@@ -3585,10 +3589,35 @@ fn initSectionsObject(self: *Elf) !void {...@@ -3585,10 +3589,35 @@ fn initSectionsObject(self: *Elf) !void {
3585 self.eh_frame_rela_section_index = try self.addRelaShdr(".rela.eh_frame", self.eh_frame_section_index.?);3589 self.eh_frame_rela_section_index = try self.addRelaShdr(".rela.eh_frame", self.eh_frame_section_index.?);
3586 }3590 }
35873591
3592 try self.initComdatGroups();
3588 try self.initSymtab();3593 try self.initSymtab();
3589 try self.initShStrtab();3594 try self.initShStrtab();
3590}3595}
35913596
3597fn initComdatGroups(self: *Elf) !void {
3598 const gpa = self.base.allocator;
3599
3600 for (self.objects.items) |index| {
3601 const object = self.file(index).?.object;
3602
3603 for (object.comdat_groups.items) |cg_index| {
3604 const cg = self.comdatGroup(cg_index);
3605 const cg_owner = self.comdatGroupOwner(cg.owner);
3606 if (cg_owner.file != index) continue;
3607
3608 const cg_sec = try self.comdat_group_sections.addOne(gpa);
3609 cg_sec.* = .{
3610 .shndx = try self.addSection(.{
3611 .name = ".group",
3612 .type = elf.SHT_GROUP,
3613 .entsize = @sizeOf(u32),
3614 }),
3615 .cg_index = cg_index,
3616 };
3617 }
3618 }
3619}
3620
3592fn initSymtab(self: *Elf) !void {3621fn initSymtab(self: *Elf) !void {
3593 const small_ptr = switch (self.ptr_width) {3622 const small_ptr = switch (self.ptr_width) {
3594 .p32 => true,3623 .p32 => true,
...@@ -3892,7 +3921,7 @@ fn shdrRank(self: *Elf, shndx: u16) u8 {...@@ -3892,7 +3921,7 @@ fn shdrRank(self: *Elf, shndx: u16) u8 {
38923921
3893 elf.SHT_DYNAMIC => return 0xf3,3922 elf.SHT_DYNAMIC => return 0xf3,
38943923
3895 elf.SHT_RELA => return 0xf,3924 elf.SHT_RELA, elf.SHT_GROUP => return 0xf,
38963925
3897 elf.SHT_PROGBITS => if (flags & elf.SHF_ALLOC != 0) {3926 elf.SHT_PROGBITS => if (flags & elf.SHF_ALLOC != 0) {
3898 if (flags & elf.SHF_EXECINSTR != 0) {3927 if (flags & elf.SHF_EXECINSTR != 0) {
...@@ -4131,6 +4160,10 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u16) !void {...@@ -4131,6 +4160,10 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u16) !void {
4131 shdr.sh_link = self.symtab_section_index.?;4160 shdr.sh_link = self.symtab_section_index.?;
4132 shdr.sh_info = shndx;4161 shdr.sh_info = shndx;
4133 }4162 }
4163
4164 for (self.comdat_group_sections.items) |*cg| {
4165 cg.shndx = backlinks[cg.shndx];
4166 }
4134}4167}
41354168
4136fn updateSectionSizes(self: *Elf) !void {4169fn updateSectionSizes(self: *Elf) !void {
...@@ -4260,10 +4293,15 @@ fn updateSectionSizesObject(self: *Elf) !void {...@@ -4260,10 +4293,15 @@ fn updateSectionSizesObject(self: *Elf) !void {
4260 shdr.sh_size = eh_frame.calcEhFrameRelocs(self) * shdr.sh_entsize;4293 shdr.sh_size = eh_frame.calcEhFrameRelocs(self) * shdr.sh_entsize;
4261 }4294 }
42624295
4296 self.updateComdatGroupsSizes();
4263 try self.updateSymtabSize();4297 try self.updateSymtabSize();
4264 self.updateShStrtabSize();4298 self.updateShStrtabSize();
4265}4299}
42664300
4301fn updateComdatGroupsSizes(self: *Elf) void {
4302 _ = self;
4303}
4304
4267fn updateShStrtabSize(self: *Elf) void {4305fn updateShStrtabSize(self: *Elf) void {
4268 if (self.shstrtab_section_index) |index| {4306 if (self.shstrtab_section_index) |index| {
4269 self.shdrs.items[index].sh_size = self.shstrtab.items.len;4307 self.shdrs.items[index].sh_size = self.shstrtab.items.len;
...@@ -6168,7 +6206,12 @@ fn fmtDumpState(...@@ -6168,7 +6206,12 @@ fn fmtDumpState(
6168 try writer.print("{}\n", .{self.got.fmt(self)});6206 try writer.print("{}\n", .{self.got.fmt(self)});
6169 try writer.print("{}\n", .{self.zig_got.fmt(self)});6207 try writer.print("{}\n", .{self.zig_got.fmt(self)});
61706208
6171 try writer.writeAll("Output shdrs\n");6209 try writer.writeAll("Output COMDAT groups\n");
6210 for (self.comdat_group_sections.items) |cg| {
6211 try writer.print("shdr({d}) : COMDAT({d})\n", .{ cg.shndx, cg.cg_index });
6212 }
6213
6214 try writer.writeAll("\nOutput shdrs\n");
6172 for (self.shdrs.items, 0..) |shdr, shndx| {6215 for (self.shdrs.items, 0..) |shdr, shndx| {
6173 try writer.print("shdr({d}) : phdr({?d}) : {}\n", .{6216 try writer.print("shdr({d}) : phdr({?d}) : {}\n", .{
6174 shndx,6217 shndx,
...@@ -6332,6 +6375,7 @@ const Archive = @import("Elf/Archive.zig");...@@ -6332,6 +6375,7 @@ const Archive = @import("Elf/Archive.zig");
6332pub const Atom = @import("Elf/Atom.zig");6375pub const Atom = @import("Elf/Atom.zig");
6333const Cache = std.Build.Cache;6376const Cache = std.Build.Cache;
6334const Compilation = @import("../Compilation.zig");6377const Compilation = @import("../Compilation.zig");
6378const ComdatGroupSection = synthetic_sections.ComdatGroupSection;
6335const CopyRelSection = synthetic_sections.CopyRelSection;6379const CopyRelSection = synthetic_sections.CopyRelSection;
6336const DynamicSection = synthetic_sections.DynamicSection;6380const DynamicSection = synthetic_sections.DynamicSection;
6337const DynsymSection = synthetic_sections.DynsymSection;6381const DynsymSection = synthetic_sections.DynsymSection;
src/link/Elf/Object.zig+4-3
...@@ -142,7 +142,7 @@ fn initAtoms(self: *Object, elf_file: *Elf) !void {...@@ -142,7 +142,7 @@ fn initAtoms(self: *Object, elf_file: *Elf) !void {
142 const group_nmembers = @divExact(group_raw_data.len, @sizeOf(u32));142 const group_nmembers = @divExact(group_raw_data.len, @sizeOf(u32));
143 const group_members = @as([*]align(1) const u32, @ptrCast(group_raw_data.ptr))[0..group_nmembers];143 const group_members = @as([*]align(1) const u32, @ptrCast(group_raw_data.ptr))[0..group_nmembers];
144144
145 if (group_members[0] != 0x1) { // GRP_COMDAT145 if (group_members[0] != elf.GRP_COMDAT) {
146 // TODO convert into an error146 // TODO convert into an error
147 log.debug("{}: unknown SHT_GROUP format", .{self.fmtPath()});147 log.debug("{}: unknown SHT_GROUP format", .{self.fmtPath()});
148 continue;148 continue;
...@@ -939,16 +939,17 @@ fn formatComdatGroups(...@@ -939,16 +939,17 @@ fn formatComdatGroups(
939 _ = options;939 _ = options;
940 const object = ctx.object;940 const object = ctx.object;
941 const elf_file = ctx.elf_file;941 const elf_file = ctx.elf_file;
942 try writer.writeAll(" comdat groups\n");942 try writer.writeAll(" COMDAT groups\n");
943 for (object.comdat_groups.items) |cg_index| {943 for (object.comdat_groups.items) |cg_index| {
944 const cg = elf_file.comdatGroup(cg_index);944 const cg = elf_file.comdatGroup(cg_index);
945 const cg_owner = elf_file.comdatGroupOwner(cg.owner);945 const cg_owner = elf_file.comdatGroupOwner(cg.owner);
946 if (cg_owner.file != object.index) continue;946 if (cg_owner.file != object.index) continue;
947 try writer.print(" COMDAT({d})\n", .{cg_index});
947 const cg_members = object.comdatGroupMembers(cg.shndx);948 const cg_members = object.comdatGroupMembers(cg.shndx);
948 for (cg_members) |shndx| {949 for (cg_members) |shndx| {
949 const atom_index = object.atoms.items[shndx];950 const atom_index = object.atoms.items[shndx];
950 const atom = elf_file.atom(atom_index) orelse continue;951 const atom = elf_file.atom(atom_index) orelse continue;
951 try writer.print(" atom({d}) : {s}\n", .{ atom_index, atom.name(elf_file) });952 try writer.print(" atom({d}) : {s}\n", .{ atom_index, atom.name(elf_file) });
952 }953 }
953 }954 }
954}955}
src/link/Elf/synthetic_sections.zig+24
...@@ -1499,6 +1499,30 @@ pub const VerneedSection = struct {...@@ -1499,6 +1499,30 @@ pub const VerneedSection = struct {
1499 }1499 }
1500};1500};
15011501
1502pub const ComdatGroupSection = struct {
1503 shndx: u32,
1504 cg_index: u32,
1505
1506 // pub fn size(cg: ComdatGroupSection) usize {
1507 // return cg.members.items.len + 1;
1508 // }
1509
1510 // pub fn write(cg: ComdatGroupSection, elf_file: *Elf, writer: anytype) !void {
1511 // try writeInt(@as(u32, elf.GRP_COMDAT), elf_file, writer);
1512 // for (cg.members.items) |atom_index| {
1513 // const atom = elf_file.atom(atom_index);
1514 // const input_shdr = atom.inputShdr(elf_file);
1515 // switch (input_shdr.sh_type) {
1516 // elf.SHT_RELA => {
1517
1518 // },
1519 // else => {},
1520 // }
1521 // }
1522 // try writer.writeAll(mem.sliceAsBytes(cg.members.items));
1523 // }
1524};
1525
1502fn writeInt(value: anytype, elf_file: *Elf, writer: anytype) !void {1526fn writeInt(value: anytype, elf_file: *Elf, writer: anytype) !void {
1503 const entry_size = elf_file.archPtrWidthBytes();1527 const entry_size = elf_file.archPtrWidthBytes();
1504 const endian = elf_file.base.options.target.cpu.arch.endian();1528 const endian = elf_file.base.options.target.cpu.arch.endian();