elf: clearly separate updating and writing symtab from only ZigObject

This commit is contained in:
Jakub Konka 2023-11-06 14:26:35 +01:00
parent 281dabaa88
commit 1b69b0c621
2 changed files with 73 additions and 6 deletions

View File

@ -1539,14 +1539,14 @@ pub fn flushStaticLib(self: *Elf, comp: *Compilation) link.File.FlushError!void
try self.initShStrtab();
try self.sortShdrs();
zig_object.updateRelaSectionSizes(self);
try self.updateSymtabSize();
self.updateSymtabSizeObject(zig_object);
self.updateShStrtabSize();
try self.allocateNonAllocSections();
try self.writeShdrTable();
try zig_object.writeRelaSections(self);
try self.writeSymtab();
try self.writeSymtabObject(zig_object);
try self.writeShStrtab();
try self.writeElfHeader();
}
@ -4060,7 +4060,7 @@ fn updateSectionSizes(self: *Elf) !void {
self.shdrs.items[index].sh_size = self.verneed.size();
}
try self.updateSymtabSize();
self.updateSymtabSize();
self.updateShStrtabSize();
}
@ -4483,7 +4483,7 @@ fn writeAtoms(self: *Elf) !void {
try self.reportUndefined(&undefs);
}
fn updateSymtabSize(self: *Elf) !void {
fn updateSymtabSize(self: *Elf) void {
var sizes = SymtabSize{};
if (self.zigObjectPtr()) |zig_object| {
@ -4544,6 +4544,25 @@ fn updateSymtabSize(self: *Elf) !void {
strtab.sh_size = sizes.strsize + 1;
}
fn updateSymtabSizeObject(self: *Elf, zig_object: *ZigObject) void {
zig_object.asFile().updateSymtabSize(self);
const sizes = zig_object.output_symtab_size;
const symtab_shdr = &self.shdrs.items[self.symtab_section_index.?];
symtab_shdr.sh_info = sizes.nlocals + 1;
symtab_shdr.sh_link = self.strtab_section_index.?;
const sym_size: u64 = switch (self.ptr_width) {
.p32 => @sizeOf(elf.Elf32_Sym),
.p64 => @sizeOf(elf.Elf64_Sym),
};
const needed_size = (sizes.nlocals + sizes.nglobals + 1) * sym_size;
symtab_shdr.sh_size = needed_size;
const strtab = &self.shdrs.items[self.strtab_section_index.?];
strtab.sh_size = sizes.strsize + 1;
}
fn writeSyntheticSections(self: *Elf) !void {
const gpa = self.base.allocator;
@ -4788,6 +4807,54 @@ fn writeSymtab(self: *Elf) !void {
try self.base.file.?.pwriteAll(self.strtab.items, strtab_shdr.sh_offset);
}
fn writeSymtabObject(self: *Elf, zig_object: *ZigObject) !void {
const gpa = self.base.allocator;
const symtab_shdr = self.shdrs.items[self.symtab_section_index.?];
const strtab_shdr = self.shdrs.items[self.strtab_section_index.?];
const sym_size: u64 = switch (self.ptr_width) {
.p32 => @sizeOf(elf.Elf32_Sym),
.p64 => @sizeOf(elf.Elf64_Sym),
};
const nsyms = math.cast(usize, @divExact(symtab_shdr.sh_size, sym_size)) orelse return error.Overflow;
log.debug("writing {d} symbols at 0x{x}", .{ nsyms, symtab_shdr.sh_offset });
try self.symtab.resize(gpa, nsyms);
const needed_strtab_size = math.cast(usize, strtab_shdr.sh_size - 1) orelse return error.Overflow;
try self.strtab.ensureUnusedCapacity(gpa, needed_strtab_size);
zig_object.asFile().writeSymtab(self, .{ .ilocal = 1, .iglobal = symtab_shdr.sh_info });
const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian();
switch (self.ptr_width) {
.p32 => {
const buf = try gpa.alloc(elf.Elf32_Sym, self.symtab.items.len);
defer gpa.free(buf);
for (buf, self.symtab.items) |*out, sym| {
out.* = .{
.st_name = sym.st_name,
.st_info = sym.st_info,
.st_other = sym.st_other,
.st_shndx = sym.st_shndx,
.st_value = @as(u32, @intCast(sym.st_value)),
.st_size = @as(u32, @intCast(sym.st_size)),
};
if (foreign_endian) mem.byteSwapAllFields(elf.Elf32_Sym, out);
}
try self.base.file.?.pwriteAll(mem.sliceAsBytes(buf), symtab_shdr.sh_offset);
},
.p64 => {
if (foreign_endian) {
for (self.symtab.items) |*sym| mem.byteSwapAllFields(elf.Elf64_Sym, sym);
}
try self.base.file.?.pwriteAll(mem.sliceAsBytes(self.symtab.items), symtab_shdr.sh_offset);
},
}
try self.base.file.?.pwriteAll(self.strtab.items, strtab_shdr.sh_offset);
}
/// Always 4 or 8 depending on whether this is 32-bit ELF or 64-bit ELF.
fn ptrWidthBytes(self: Elf) u8 {
return switch (self.ptr_width) {

View File

@ -161,7 +161,7 @@ pub const File = union(enum) {
}
pub fn writeSymtab(file: File, elf_file: *Elf, ctx: anytype) void {
var ilocal = ctx.ilocal;
var ilocal: usize = ctx.ilocal;
for (file.locals()) |local_index| {
const local = elf_file.symbol(local_index);
if (!local.flags.output_symtab) continue;
@ -173,7 +173,7 @@ pub const File = union(enum) {
ilocal += 1;
}
var iglobal = ctx.iglobal;
var iglobal: usize = ctx.iglobal;
for (file.globals()) |global_index| {
const global = elf_file.symbol(global_index);
const file_ptr = global.file(elf_file) orelse continue;