elf: write out COMDAT groups to file

This commit is contained in:
Jakub Konka 2023-11-09 18:29:58 +01:00
parent acd7cbf0b5
commit 03c3a85ea3
2 changed files with 66 additions and 18 deletions

View File

@ -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];

View File

@ -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;
// }
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 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 => {
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];
}
// },
// else => {},
// }
// }
// try writer.writeAll(mem.sliceAsBytes(cg.members.items));
// }
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 {