diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2022-12-08 14:13:37 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2022-12-09 09:24:25 +0100 |
| commit | 9ade4f6d8c410eea63ad71569b5cf7813337659d (patch) | |
| tree | d33bd6170d88cce565577b1df3ecfbbf94913246 | |
| parent | d7e42014caadeb726d19243995365a573b6a9d06 (diff) | |
| download | zig-9ade4f6d8c410eea63ad71569b5cf7813337659d.tar.gz zig-9ade4f6d8c410eea63ad71569b5cf7813337659d.zip | |
elf: hint linker when file range copy is not necessary
| -rw-r--r-- | src/link/Dwarf.zig | 10 | ||||
| -rw-r--r-- | src/link/Elf.zig | 70 |
2 files changed, 33 insertions, 47 deletions
diff --git a/src/link/Dwarf.zig b/src/link/Dwarf.zig index 569daf577e..e804871c67 100644 --- a/src/link/Dwarf.zig +++ b/src/link/Dwarf.zig @@ -1151,7 +1151,7 @@ pub fn commitDeclState( .elf => { const elf_file = self.bin_file.cast(File.Elf).?; const shdr_index = elf_file.debug_line_section_index.?; - try elf_file.growNonAllocSection(shdr_index, needed_size, 1); + try elf_file.growNonAllocSection(shdr_index, needed_size, 1, true); const debug_line_sect = elf_file.sections.items[shdr_index]; const file_pos = debug_line_sect.sh_offset + src_fn.off; try pwriteDbgLineNops( @@ -1398,7 +1398,7 @@ fn writeDeclDebugInfo(self: *Dwarf, atom: *Atom, dbg_info_buf: []const u8) !void .elf => { const elf_file = self.bin_file.cast(File.Elf).?; const shdr_index = elf_file.debug_info_section_index.?; - try elf_file.growNonAllocSection(shdr_index, needed_size, 1); + try elf_file.growNonAllocSection(shdr_index, needed_size, 1, true); const debug_info_sect = elf_file.sections.items[shdr_index]; const file_pos = debug_info_sect.sh_offset + atom.off; try pwriteDbgInfoNops( @@ -1689,7 +1689,7 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void { .elf => { const elf_file = self.bin_file.cast(File.Elf).?; const shdr_index = elf_file.debug_abbrev_section_index.?; - try elf_file.growNonAllocSection(shdr_index, needed_size, 1); + try elf_file.growNonAllocSection(shdr_index, needed_size, 1, false); const debug_abbrev_sect = elf_file.sections.items[shdr_index]; const file_pos = debug_abbrev_sect.sh_offset + abbrev_offset; try elf_file.base.file.?.pwriteAll(&abbrev_buf, file_pos); @@ -2126,7 +2126,7 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void { .elf => { const elf_file = self.bin_file.cast(File.Elf).?; const shdr_index = elf_file.debug_aranges_section_index.?; - try elf_file.growNonAllocSection(shdr_index, needed_size, 16); + try elf_file.growNonAllocSection(shdr_index, needed_size, 16, false); const debug_aranges_sect = elf_file.sections.items[shdr_index]; const file_pos = debug_aranges_sect.sh_offset; try elf_file.base.file.?.pwriteAll(di_buf.items, file_pos); @@ -2289,7 +2289,7 @@ pub fn writeDbgLineHeader(self: *Dwarf, module: *Module) !void { const elf_file = self.bin_file.cast(File.Elf).?; const shdr_index = elf_file.debug_line_section_index.?; const needed_size = elf_file.sections.items[shdr_index].sh_size + delta; - try elf_file.growNonAllocSection(shdr_index, needed_size, 1); + try elf_file.growNonAllocSection(shdr_index, needed_size, 1, true); const file_pos = elf_file.sections.items[shdr_index].sh_offset + src_fn.off; const amt = try elf_file.base.file.?.preadAll(buffer, file_pos); diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 0662a558e3..601b1a3e93 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -967,7 +967,13 @@ fn growAllocSection(self: *Elf, shdr_index: u16, phdr_index: u16, needed_size: u self.markDirty(shdr_index, phdr_index); } -pub fn growNonAllocSection(self: *Elf, shdr_index: u16, needed_size: u64, min_alignment: u32) !void { +pub fn growNonAllocSection( + self: *Elf, + shdr_index: u16, + needed_size: u64, + min_alignment: u32, + requires_file_copy: bool, +) !void { const shdr = &self.sections.items[shdr_index]; if (needed_size > self.allocatedSize(shdr.sh_offset)) { @@ -982,13 +988,17 @@ pub fn growNonAllocSection(self: *Elf, shdr_index: u16, needed_size: u64, min_al // Move all the symbols to a new file location. const new_offset = self.findFreeSpace(needed_size, min_alignment); log.debug("moving '{s}' from 0x{x} to 0x{x}", .{ self.getString(shdr.sh_name), shdr.sh_offset, new_offset }); - const amt = try self.base.file.?.copyRangeAll( - shdr.sh_offset, - self.base.file.?, - new_offset, - existing_size, - ); - if (amt != existing_size) return error.InputOutput; + + if (requires_file_copy) { + const amt = try self.base.file.?.copyRangeAll( + shdr.sh_offset, + self.base.file.?, + new_offset, + existing_size, + ); + if (amt != existing_size) return error.InputOutput; + } + shdr.sh_offset = new_offset; } @@ -1191,45 +1201,21 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node } { - const shstrtab_sect = &self.sections.items[self.shstrtab_index.?]; - if (self.shstrtab_dirty or self.shstrtab.items.len != shstrtab_sect.sh_size) { - const allocated_size = self.allocatedSize(shstrtab_sect.sh_offset); - const needed_size = self.shstrtab.items.len; - - if (needed_size > allocated_size) { - shstrtab_sect.sh_size = 0; // free the space - shstrtab_sect.sh_offset = self.findFreeSpace(needed_size, 1); - } - shstrtab_sect.sh_size = needed_size; - log.debug("writing shstrtab start=0x{x} end=0x{x}", .{ shstrtab_sect.sh_offset, shstrtab_sect.sh_offset + needed_size }); - + const shdr_index = self.shstrtab_index.?; + if (self.shstrtab_dirty or self.shstrtab.items.len != self.sections.items[shdr_index].sh_size) { + try self.growNonAllocSection(shdr_index, self.shstrtab.items.len, 1, false); + const shstrtab_sect = self.sections.items[shdr_index]; try self.base.file.?.pwriteAll(self.shstrtab.items, shstrtab_sect.sh_offset); - if (!self.shdr_table_dirty) { - // Then it won't get written with the others and we need to do it. - try self.writeSectHeader(self.shstrtab_index.?); - } self.shstrtab_dirty = false; } } if (self.dwarf) |dwarf| { - const debug_strtab_sect = &self.sections.items[self.debug_str_section_index.?]; - if (self.debug_strtab_dirty or dwarf.strtab.items.len != debug_strtab_sect.sh_size) { - const allocated_size = self.allocatedSize(debug_strtab_sect.sh_offset); - const needed_size = dwarf.strtab.items.len; - - if (needed_size > allocated_size) { - debug_strtab_sect.sh_size = 0; // free the space - debug_strtab_sect.sh_offset = self.findFreeSpace(needed_size, 1); - } - debug_strtab_sect.sh_size = needed_size; - log.debug("debug_strtab start=0x{x} end=0x{x}", .{ debug_strtab_sect.sh_offset, debug_strtab_sect.sh_offset + needed_size }); - + const shdr_index = self.debug_str_section_index.?; + if (self.debug_strtab_dirty or dwarf.strtab.items.len != self.sections.items[shdr_index].sh_size) { + try self.growNonAllocSection(shdr_index, dwarf.strtab.items.len, 1, false); + const debug_strtab_sect = self.sections.items[shdr_index]; try self.base.file.?.pwriteAll(dwarf.strtab.items, debug_strtab_sect.sh_offset); - if (!self.shdr_table_dirty) { - // Then it won't get written with the others and we need to do it. - try self.writeSectHeader(self.debug_str_section_index.?); - } self.debug_strtab_dirty = false; } } @@ -2861,7 +2847,7 @@ fn writeSymbol(self: *Elf, index: usize) !void { .p64 => @alignOf(elf.Elf64_Sym), }; const needed_size = (self.local_symbols.items.len + self.global_symbols.items.len) * sym_size; - try self.growNonAllocSection(self.symtab_section_index.?, needed_size, sym_align); + try self.growNonAllocSection(self.symtab_section_index.?, needed_size, sym_align, true); syms_sect.sh_info = @intCast(u32, self.local_symbols.items.len); } const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian(); @@ -2910,7 +2896,7 @@ fn writeAllGlobalSymbols(self: *Elf) !void { .p64 => @alignOf(elf.Elf64_Sym), }; const needed_size = (self.local_symbols.items.len + self.global_symbols.items.len) * sym_size; - try self.growNonAllocSection(self.symtab_section_index.?, needed_size, sym_align); + try self.growNonAllocSection(self.symtab_section_index.?, needed_size, sym_align, true); 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; |
