diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2022-04-14 15:16:51 +0200 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2022-04-14 15:16:55 +0200 |
| commit | 4d77ef25f948cac32e4d5fd3f9df019e728fcb45 (patch) | |
| tree | 919aef64f0588c0ab864ac07b51b27612948dd0e | |
| parent | 7a0022725342be8d3ea555a635da51f0e8c47b25 (diff) | |
| download | zig-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.zig | 16 |
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) { |
