aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Konka <kubkon@jakubkonka.com>2022-04-14 15:16:51 +0200
committerJakub Konka <kubkon@jakubkonka.com>2022-04-14 15:16:55 +0200
commit4d77ef25f948cac32e4d5fd3f9df019e728fcb45 (patch)
tree919aef64f0588c0ab864ac07b51b27612948dd0e
parent7a0022725342be8d3ea555a635da51f0e8c47b25 (diff)
downloadzig-4d77ef25f948cac32e4d5fd3f9df019e728fcb45.tar.gz
zig-4d77ef25f948cac32e4d5fd3f9df019e728fcb45.zip
elf: check symtab section headers size when writing globals
Without this, it may happen we write the globals without extending the symtab section header's size. This can potentially lead to clobbering some data in the file, or simply omitting the globals from the symtab when displaying with support tooling such as `readelf`.
-rw-r--r--src/link/Elf.zig16
1 files changed, 16 insertions, 0 deletions
diff --git a/src/link/Elf.zig b/src/link/Elf.zig
index bb13aad3a6..add23113a7 100644
--- a/src/link/Elf.zig
+++ b/src/link/Elf.zig
@@ -2799,6 +2799,22 @@ fn writeAllGlobalSymbols(self: *Elf) !void {
.p32 => @sizeOf(elf.Elf32_Sym),
.p64 => @sizeOf(elf.Elf64_Sym),
};
+ const sym_align: u16 = switch (self.ptr_width) {
+ .p32 => @alignOf(elf.Elf32_Sym),
+ .p64 => @alignOf(elf.Elf64_Sym),
+ };
+ const needed_size = (self.local_symbols.items.len + self.global_symbols.items.len) * sym_size;
+ if (needed_size > self.allocatedSize(syms_sect.sh_offset)) {
+ // Move all the symbols to a new file location.
+ const new_offset = self.findFreeSpace(needed_size, sym_align);
+ const existing_size = @as(u64, syms_sect.sh_info) * sym_size;
+ const amt = try self.base.file.?.copyRangeAll(syms_sect.sh_offset, self.base.file.?, new_offset, existing_size);
+ if (amt != existing_size) return error.InputOutput;
+ syms_sect.sh_offset = new_offset;
+ }
+ syms_sect.sh_size = needed_size; // anticipating adding the global symbols later
+ self.shdr_table_dirty = true; // TODO look into only writing one section
+
const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian();
const global_syms_off = syms_sect.sh_offset + self.local_symbols.items.len * sym_size;
switch (self.ptr_width) {