elf: init output COMDAT group sections

This commit is contained in:
Jakub Konka 2023-11-09 17:41:14 +01:00
parent 031d9faf02
commit acd7cbf0b5
4 changed files with 76 additions and 5 deletions

View File

@ -1664,6 +1664,8 @@ pub const EM = enum(u16) {
}
};
pub const GRP_COMDAT = 1;
/// Section data should be writable during execution.
pub const SHF_WRITE = 0x1;

View File

@ -102,6 +102,9 @@ copy_rel: CopyRelSection = .{},
rela_plt: std.ArrayListUnmanaged(elf.Elf64_Rela) = .{},
/// .got.zig section
zig_got: ZigGotSection = .{},
/// SHT_GROUP sections
/// Applies only to a relocatable.
comdat_group_sections: std.ArrayListUnmanaged(ComdatGroupSection) = .{},
/// Tracked section headers with incremental updates to Zig object.
/// .rela.* sections are only used when emitting a relocatable object file.
@ -394,6 +397,7 @@ pub fn deinit(self: *Elf) void {
self.rela_dyn.deinit(gpa);
self.rela_plt.deinit(gpa);
self.zig_got.deinit(gpa);
self.comdat_group_sections.deinit(gpa);
}
pub fn getDeclVAddr(self: *Elf, decl_index: Module.Decl.Index, reloc_info: link.File.RelocInfo) !u64 {
@ -3585,10 +3589,35 @@ fn initSectionsObject(self: *Elf) !void {
self.eh_frame_rela_section_index = try self.addRelaShdr(".rela.eh_frame", self.eh_frame_section_index.?);
}
try self.initComdatGroups();
try self.initSymtab();
try self.initShStrtab();
}
fn initComdatGroups(self: *Elf) !void {
const gpa = self.base.allocator;
for (self.objects.items) |index| {
const object = self.file(index).?.object;
for (object.comdat_groups.items) |cg_index| {
const cg = self.comdatGroup(cg_index);
const cg_owner = self.comdatGroupOwner(cg.owner);
if (cg_owner.file != index) continue;
const cg_sec = try self.comdat_group_sections.addOne(gpa);
cg_sec.* = .{
.shndx = try self.addSection(.{
.name = ".group",
.type = elf.SHT_GROUP,
.entsize = @sizeOf(u32),
}),
.cg_index = cg_index,
};
}
}
}
fn initSymtab(self: *Elf) !void {
const small_ptr = switch (self.ptr_width) {
.p32 => true,
@ -3892,7 +3921,7 @@ fn shdrRank(self: *Elf, shndx: u16) u8 {
elf.SHT_DYNAMIC => return 0xf3,
elf.SHT_RELA => return 0xf,
elf.SHT_RELA, elf.SHT_GROUP => return 0xf,
elf.SHT_PROGBITS => if (flags & elf.SHF_ALLOC != 0) {
if (flags & elf.SHF_EXECINSTR != 0) {
@ -4131,6 +4160,10 @@ fn resetShdrIndexes(self: *Elf, backlinks: []const u16) !void {
shdr.sh_link = self.symtab_section_index.?;
shdr.sh_info = shndx;
}
for (self.comdat_group_sections.items) |*cg| {
cg.shndx = backlinks[cg.shndx];
}
}
fn updateSectionSizes(self: *Elf) !void {
@ -4260,10 +4293,15 @@ fn updateSectionSizesObject(self: *Elf) !void {
shdr.sh_size = eh_frame.calcEhFrameRelocs(self) * shdr.sh_entsize;
}
self.updateComdatGroupsSizes();
try self.updateSymtabSize();
self.updateShStrtabSize();
}
fn updateComdatGroupsSizes(self: *Elf) void {
_ = self;
}
fn updateShStrtabSize(self: *Elf) void {
if (self.shstrtab_section_index) |index| {
self.shdrs.items[index].sh_size = self.shstrtab.items.len;
@ -6168,7 +6206,12 @@ fn fmtDumpState(
try writer.print("{}\n", .{self.got.fmt(self)});
try writer.print("{}\n", .{self.zig_got.fmt(self)});
try writer.writeAll("Output shdrs\n");
try writer.writeAll("Output COMDAT groups\n");
for (self.comdat_group_sections.items) |cg| {
try writer.print("shdr({d}) : COMDAT({d})\n", .{ cg.shndx, cg.cg_index });
}
try writer.writeAll("\nOutput shdrs\n");
for (self.shdrs.items, 0..) |shdr, shndx| {
try writer.print("shdr({d}) : phdr({?d}) : {}\n", .{
shndx,
@ -6332,6 +6375,7 @@ const Archive = @import("Elf/Archive.zig");
pub const Atom = @import("Elf/Atom.zig");
const Cache = std.Build.Cache;
const Compilation = @import("../Compilation.zig");
const ComdatGroupSection = synthetic_sections.ComdatGroupSection;
const CopyRelSection = synthetic_sections.CopyRelSection;
const DynamicSection = synthetic_sections.DynamicSection;
const DynsymSection = synthetic_sections.DynsymSection;

View File

@ -142,7 +142,7 @@ fn initAtoms(self: *Object, elf_file: *Elf) !void {
const group_nmembers = @divExact(group_raw_data.len, @sizeOf(u32));
const group_members = @as([*]align(1) const u32, @ptrCast(group_raw_data.ptr))[0..group_nmembers];
if (group_members[0] != 0x1) { // GRP_COMDAT
if (group_members[0] != elf.GRP_COMDAT) {
// TODO convert into an error
log.debug("{}: unknown SHT_GROUP format", .{self.fmtPath()});
continue;
@ -939,16 +939,17 @@ fn formatComdatGroups(
_ = options;
const object = ctx.object;
const elf_file = ctx.elf_file;
try writer.writeAll(" comdat groups\n");
try writer.writeAll(" COMDAT groups\n");
for (object.comdat_groups.items) |cg_index| {
const cg = elf_file.comdatGroup(cg_index);
const cg_owner = elf_file.comdatGroupOwner(cg.owner);
if (cg_owner.file != object.index) continue;
try writer.print(" COMDAT({d})\n", .{cg_index});
const cg_members = object.comdatGroupMembers(cg.shndx);
for (cg_members) |shndx| {
const atom_index = object.atoms.items[shndx];
const atom = elf_file.atom(atom_index) orelse continue;
try writer.print(" atom({d}) : {s}\n", .{ atom_index, atom.name(elf_file) });
try writer.print(" atom({d}) : {s}\n", .{ atom_index, atom.name(elf_file) });
}
}
}

View File

@ -1499,6 +1499,30 @@ pub const VerneedSection = struct {
}
};
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 writeInt(value: anytype, elf_file: *Elf, writer: anytype) !void {
const entry_size = elf_file.archPtrWidthBytes();
const endian = elf_file.base.options.target.cpu.arch.endian();