Commit 03c3a85ea3

Jakub Konka <kubkon@jakubkonka.com>
2023-11-09 18:29:58
elf: write out COMDAT groups to file
1 parent acd7cbf
Changed files (2)
src/link/Elf/synthetic_sections.zig
@@ -1503,24 +1503,48 @@ pub const ComdatGroupSection = struct {
     shndx: u32,
     cg_index: u32,
 
-    // pub fn size(cg: ComdatGroupSection) usize {
-    //     return cg.members.items.len + 1;
-    // }
-
-    // pub fn write(cg: ComdatGroupSection, elf_file: *Elf, writer: anytype) !void {
-    //     try writeInt(@as(u32, elf.GRP_COMDAT), elf_file, writer);
-    //     for (cg.members.items) |atom_index| {
-    //         const atom = elf_file.atom(atom_index);
-    //         const input_shdr = atom.inputShdr(elf_file);
-    //         switch (input_shdr.sh_type) {
-    //             elf.SHT_RELA => {
-
-    //         },
-    //             else => {},
-    //         }
-    //     }
-    //     try writer.writeAll(mem.sliceAsBytes(cg.members.items));
-    // }
+    fn file(cgs: ComdatGroupSection, elf_file: *Elf) ?File {
+        const cg = elf_file.comdatGroup(cgs.cg_index);
+        const cg_owner = elf_file.comdatGroupOwner(cg.owner);
+        return elf_file.file(cg_owner.file);
+    }
+
+    pub fn symbol(cgs: ComdatGroupSection, elf_file: *Elf) Symbol.Index {
+        const cg = elf_file.comdatGroup(cgs.cg_index);
+        const object = cgs.file(elf_file).?.object;
+        const shdr = object.shdrs.items[cg.shndx];
+        return object.symbols.items[shdr.sh_info];
+    }
+
+    pub fn size(cgs: ComdatGroupSection, elf_file: *Elf) usize {
+        const cg = elf_file.comdatGroup(cgs.cg_index);
+        const object = cgs.file(elf_file).?.object;
+        const members = object.comdatGroupMembers(cg.shndx);
+        return (members.len + 1) * @sizeOf(u32);
+    }
+
+    pub fn write(cgs: ComdatGroupSection, elf_file: *Elf, writer: anytype) !void {
+        const cg = elf_file.comdatGroup(cgs.cg_index);
+        const object = cgs.file(elf_file).?.object;
+        const members = object.comdatGroupMembers(cg.shndx);
+        try writeInt(@as(u32, elf.GRP_COMDAT), elf_file, writer);
+        for (members) |shndx| {
+            const shdr = object.shdrs.items[shndx];
+            switch (shdr.sh_type) {
+                elf.SHT_RELA => {
+                    const atom_index = object.atoms.items[shdr.sh_info];
+                    const atom = elf_file.atom(atom_index).?;
+                    const rela = elf_file.output_rela_sections.get(atom.outputShndx().?).?;
+                    try writeInt(rela.shndx, elf_file, writer);
+                },
+                else => {
+                    const atom_index = object.atoms.items[shndx];
+                    const atom = elf_file.atom(atom_index).?;
+                    try writeInt(atom.outputShndx().?, elf_file, writer);
+                },
+            }
+        }
+    }
 };
 
 fn writeInt(value: anytype, elf_file: *Elf, writer: anytype) !void {
src/link/Elf.zig
@@ -3611,6 +3611,8 @@ fn initComdatGroups(self: *Elf) !void {
                     .name = ".group",
                     .type = elf.SHT_GROUP,
                     .entsize = @sizeOf(u32),
+                    .addralign = @alignOf(u32),
+                    .offset = std.math.maxInt(u64),
                 }),
                 .cg_index = cg_index,
             };
@@ -4293,13 +4295,22 @@ fn updateSectionSizesObject(self: *Elf) !void {
         shdr.sh_size = eh_frame.calcEhFrameRelocs(self) * shdr.sh_entsize;
     }
 
-    self.updateComdatGroupsSizes();
     try self.updateSymtabSize();
+    self.updateComdatGroupsSizes();
     self.updateShStrtabSize();
 }
 
 fn updateComdatGroupsSizes(self: *Elf) void {
-    _ = self;
+    for (self.comdat_group_sections.items) |cg| {
+        const shdr = &self.shdrs.items[cg.shndx];
+        shdr.sh_size = cg.size(self);
+        shdr.sh_link = self.symtab_section_index.?;
+
+        const sym = self.symbol(cg.symbol(self));
+        std.debug.print("{s}\n", .{sym.name(self)});
+        shdr.sh_info = sym.outputSymtabIndex(self) orelse
+            self.sectionSymbolOutputSymtabIndex(sym.outputShndx().?);
+    }
 }
 
 fn updateShStrtabSize(self: *Elf) void {
@@ -5068,10 +5079,23 @@ fn writeSyntheticSectionsObject(self: *Elf) !void {
         try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
     }
 
+    try self.writeComdatGroups();
     try self.writeSymtab();
     try self.writeShStrtab();
 }
 
+fn writeComdatGroups(self: *Elf) !void {
+    const gpa = self.base.allocator;
+    for (self.comdat_group_sections.items) |cgs| {
+        const shdr = self.shdrs.items[cgs.shndx];
+        const sh_size = math.cast(usize, shdr.sh_size) orelse return error.Overflow;
+        var buffer = try std.ArrayList(u8).initCapacity(gpa, sh_size);
+        defer buffer.deinit();
+        try cgs.write(self, buffer.writer());
+        try self.base.file.?.pwriteAll(buffer.items, shdr.sh_offset);
+    }
+}
+
 fn writeShStrtab(self: *Elf) !void {
     if (self.shstrtab_section_index) |index| {
         const shdr = self.shdrs.items[index];