diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2023-11-09 18:29:58 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2023-11-09 18:29:58 +0100 |
| commit | 03c3a85ea36d8d6a18437b8d9c8a5fc714e4a81e (patch) | |
| tree | a6714287704e5905243cad2483a3f21dfa0d3052 | |
| parent | acd7cbf0b51dbc8039387de285e2b391a78f59ae (diff) | |
| download | zig-03c3a85ea36d8d6a18437b8d9c8a5fc714e4a81e.tar.gz zig-03c3a85ea36d8d6a18437b8d9c8a5fc714e4a81e.zip | |
elf: write out COMDAT groups to file
| -rw-r--r-- | src/link/Elf.zig | 28 | ||||
| -rw-r--r-- | src/link/Elf/synthetic_sections.zig | 60 |
2 files changed, 68 insertions, 20 deletions
diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 678844aa81..ce7f2fc40e 100644 --- a/src/link/Elf.zig +++ b/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]; diff --git a/src/link/Elf/synthetic_sections.zig b/src/link/Elf/synthetic_sections.zig index 7fbc75d80a..67acba9dd2 100644 --- a/src/link/Elf/synthetic_sections.zig +++ b/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 { |
