authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-12-08 14:13:37+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-12-09 09:24:25+01:00
log9ade4f6d8c410eea63ad71569b5cf7813337659d
treed33bd6170d88cce565577b1df3ecfbbf94913246
parentd7e42014caadeb726d19243995365a573b6a9d06

elf: hint linker when file range copy is not necessary


2 files changed, 33 insertions(+), 47 deletions(-)

src/link/Dwarf.zig+5-5
...@@ -1151,7 +1151,7 @@ pub fn commitDeclState(...@@ -1151,7 +1151,7 @@ pub fn commitDeclState(
1151 .elf => {1151 .elf => {
1152 const elf_file = self.bin_file.cast(File.Elf).?;1152 const elf_file = self.bin_file.cast(File.Elf).?;
1153 const shdr_index = elf_file.debug_line_section_index.?;1153 const shdr_index = elf_file.debug_line_section_index.?;
1154 try elf_file.growNonAllocSection(shdr_index, needed_size, 1);1154 try elf_file.growNonAllocSection(shdr_index, needed_size, 1, true);
1155 const debug_line_sect = elf_file.sections.items[shdr_index];1155 const debug_line_sect = elf_file.sections.items[shdr_index];
1156 const file_pos = debug_line_sect.sh_offset + src_fn.off;1156 const file_pos = debug_line_sect.sh_offset + src_fn.off;
1157 try pwriteDbgLineNops(1157 try pwriteDbgLineNops(
...@@ -1398,7 +1398,7 @@ fn writeDeclDebugInfo(self: *Dwarf, atom: *Atom, dbg_info_buf: []const u8) !void...@@ -1398,7 +1398,7 @@ fn writeDeclDebugInfo(self: *Dwarf, atom: *Atom, dbg_info_buf: []const u8) !void
1398 .elf => {1398 .elf => {
1399 const elf_file = self.bin_file.cast(File.Elf).?;1399 const elf_file = self.bin_file.cast(File.Elf).?;
1400 const shdr_index = elf_file.debug_info_section_index.?;1400 const shdr_index = elf_file.debug_info_section_index.?;
1401 try elf_file.growNonAllocSection(shdr_index, needed_size, 1);1401 try elf_file.growNonAllocSection(shdr_index, needed_size, 1, true);
1402 const debug_info_sect = elf_file.sections.items[shdr_index];1402 const debug_info_sect = elf_file.sections.items[shdr_index];
1403 const file_pos = debug_info_sect.sh_offset + atom.off;1403 const file_pos = debug_info_sect.sh_offset + atom.off;
1404 try pwriteDbgInfoNops(1404 try pwriteDbgInfoNops(
...@@ -1689,7 +1689,7 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void {...@@ -1689,7 +1689,7 @@ pub fn writeDbgAbbrev(self: *Dwarf) !void {
1689 .elf => {1689 .elf => {
1690 const elf_file = self.bin_file.cast(File.Elf).?;1690 const elf_file = self.bin_file.cast(File.Elf).?;
1691 const shdr_index = elf_file.debug_abbrev_section_index.?;1691 const shdr_index = elf_file.debug_abbrev_section_index.?;
1692 try elf_file.growNonAllocSection(shdr_index, needed_size, 1);1692 try elf_file.growNonAllocSection(shdr_index, needed_size, 1, false);
1693 const debug_abbrev_sect = elf_file.sections.items[shdr_index];1693 const debug_abbrev_sect = elf_file.sections.items[shdr_index];
1694 const file_pos = debug_abbrev_sect.sh_offset + abbrev_offset;1694 const file_pos = debug_abbrev_sect.sh_offset + abbrev_offset;
1695 try elf_file.base.file.?.pwriteAll(&abbrev_buf, file_pos);1695 try elf_file.base.file.?.pwriteAll(&abbrev_buf, file_pos);
...@@ -2126,7 +2126,7 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void {...@@ -2126,7 +2126,7 @@ pub fn writeDbgAranges(self: *Dwarf, addr: u64, size: u64) !void {
2126 .elf => {2126 .elf => {
2127 const elf_file = self.bin_file.cast(File.Elf).?;2127 const elf_file = self.bin_file.cast(File.Elf).?;
2128 const shdr_index = elf_file.debug_aranges_section_index.?;2128 const shdr_index = elf_file.debug_aranges_section_index.?;
2129 try elf_file.growNonAllocSection(shdr_index, needed_size, 16);2129 try elf_file.growNonAllocSection(shdr_index, needed_size, 16, false);
2130 const debug_aranges_sect = elf_file.sections.items[shdr_index];2130 const debug_aranges_sect = elf_file.sections.items[shdr_index];
2131 const file_pos = debug_aranges_sect.sh_offset;2131 const file_pos = debug_aranges_sect.sh_offset;
2132 try elf_file.base.file.?.pwriteAll(di_buf.items, file_pos);2132 try elf_file.base.file.?.pwriteAll(di_buf.items, file_pos);
...@@ -2289,7 +2289,7 @@ pub fn writeDbgLineHeader(self: *Dwarf, module: *Module) !void {...@@ -2289,7 +2289,7 @@ pub fn writeDbgLineHeader(self: *Dwarf, module: *Module) !void {
2289 const elf_file = self.bin_file.cast(File.Elf).?;2289 const elf_file = self.bin_file.cast(File.Elf).?;
2290 const shdr_index = elf_file.debug_line_section_index.?;2290 const shdr_index = elf_file.debug_line_section_index.?;
2291 const needed_size = elf_file.sections.items[shdr_index].sh_size + delta;2291 const needed_size = elf_file.sections.items[shdr_index].sh_size + delta;
2292 try elf_file.growNonAllocSection(shdr_index, needed_size, 1);2292 try elf_file.growNonAllocSection(shdr_index, needed_size, 1, true);
2293 const file_pos = elf_file.sections.items[shdr_index].sh_offset + src_fn.off;2293 const file_pos = elf_file.sections.items[shdr_index].sh_offset + src_fn.off;
22942294
2295 const amt = try elf_file.base.file.?.preadAll(buffer, file_pos);2295 const amt = try elf_file.base.file.?.preadAll(buffer, file_pos);
src/link/Elf.zig+28-42
...@@ -967,7 +967,13 @@ fn growAllocSection(self: *Elf, shdr_index: u16, phdr_index: u16, needed_size: u...@@ -967,7 +967,13 @@ fn growAllocSection(self: *Elf, shdr_index: u16, phdr_index: u16, needed_size: u
967 self.markDirty(shdr_index, phdr_index);967 self.markDirty(shdr_index, phdr_index);
968}968}
969969
970pub fn growNonAllocSection(self: *Elf, shdr_index: u16, needed_size: u64, min_alignment: u32) !void {970pub fn growNonAllocSection(
971 self: *Elf,
972 shdr_index: u16,
973 needed_size: u64,
974 min_alignment: u32,
975 requires_file_copy: bool,
976) !void {
971 const shdr = &self.sections.items[shdr_index];977 const shdr = &self.sections.items[shdr_index];
972978
973 if (needed_size > self.allocatedSize(shdr.sh_offset)) {979 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...@@ -982,13 +988,17 @@ pub fn growNonAllocSection(self: *Elf, shdr_index: u16, needed_size: u64, min_al
982 // Move all the symbols to a new file location.988 // Move all the symbols to a new file location.
983 const new_offset = self.findFreeSpace(needed_size, min_alignment);989 const new_offset = self.findFreeSpace(needed_size, min_alignment);
984 log.debug("moving '{s}' from 0x{x} to 0x{x}", .{ self.getString(shdr.sh_name), shdr.sh_offset, new_offset });990 log.debug("moving '{s}' from 0x{x} to 0x{x}", .{ self.getString(shdr.sh_name), shdr.sh_offset, new_offset });
985 const amt = try self.base.file.?.copyRangeAll(991
986 shdr.sh_offset,992 if (requires_file_copy) {
987 self.base.file.?,993 const amt = try self.base.file.?.copyRangeAll(
988 new_offset,994 shdr.sh_offset,
989 existing_size,995 self.base.file.?,
990 );996 new_offset,
991 if (amt != existing_size) return error.InputOutput;997 existing_size,
998 );
999 if (amt != existing_size) return error.InputOutput;
1000 }
1001
992 shdr.sh_offset = new_offset;1002 shdr.sh_offset = new_offset;
993 }1003 }
9941004
...@@ -1191,45 +1201,21 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node...@@ -1191,45 +1201,21 @@ pub fn flushModule(self: *Elf, comp: *Compilation, prog_node: *std.Progress.Node
1191 }1201 }
11921202
1193 {1203 {
1194 const shstrtab_sect = &self.sections.items[self.shstrtab_index.?];1204 const shdr_index = self.shstrtab_index.?;
1195 if (self.shstrtab_dirty or self.shstrtab.items.len != shstrtab_sect.sh_size) {1205 if (self.shstrtab_dirty or self.shstrtab.items.len != self.sections.items[shdr_index].sh_size) {
1196 const allocated_size = self.allocatedSize(shstrtab_sect.sh_offset);1206 try self.growNonAllocSection(shdr_index, self.shstrtab.items.len, 1, false);
1197 const needed_size = self.shstrtab.items.len;1207 const shstrtab_sect = self.sections.items[shdr_index];
1198
1199 if (needed_size > allocated_size) {
1200 shstrtab_sect.sh_size = 0; // free the space
1201 shstrtab_sect.sh_offset = self.findFreeSpace(needed_size, 1);
1202 }
1203 shstrtab_sect.sh_size = needed_size;
1204 log.debug("writing shstrtab start=0x{x} end=0x{x}", .{ shstrtab_sect.sh_offset, shstrtab_sect.sh_offset + needed_size });
1205
1206 try self.base.file.?.pwriteAll(self.shstrtab.items, shstrtab_sect.sh_offset);1208 try self.base.file.?.pwriteAll(self.shstrtab.items, shstrtab_sect.sh_offset);
1207 if (!self.shdr_table_dirty) {
1208 // Then it won't get written with the others and we need to do it.
1209 try self.writeSectHeader(self.shstrtab_index.?);
1210 }
1211 self.shstrtab_dirty = false;1209 self.shstrtab_dirty = false;
1212 }1210 }
1213 }1211 }
12141212
1215 if (self.dwarf) |dwarf| {1213 if (self.dwarf) |dwarf| {
1216 const debug_strtab_sect = &self.sections.items[self.debug_str_section_index.?];1214 const shdr_index = self.debug_str_section_index.?;
1217 if (self.debug_strtab_dirty or dwarf.strtab.items.len != debug_strtab_sect.sh_size) {1215 if (self.debug_strtab_dirty or dwarf.strtab.items.len != self.sections.items[shdr_index].sh_size) {
1218 const allocated_size = self.allocatedSize(debug_strtab_sect.sh_offset);1216 try self.growNonAllocSection(shdr_index, dwarf.strtab.items.len, 1, false);
1219 const needed_size = dwarf.strtab.items.len;1217 const debug_strtab_sect = self.sections.items[shdr_index];
1220
1221 if (needed_size > allocated_size) {
1222 debug_strtab_sect.sh_size = 0; // free the space
1223 debug_strtab_sect.sh_offset = self.findFreeSpace(needed_size, 1);
1224 }
1225 debug_strtab_sect.sh_size = needed_size;
1226 log.debug("debug_strtab start=0x{x} end=0x{x}", .{ debug_strtab_sect.sh_offset, debug_strtab_sect.sh_offset + needed_size });
1227
1228 try self.base.file.?.pwriteAll(dwarf.strtab.items, debug_strtab_sect.sh_offset);1218 try self.base.file.?.pwriteAll(dwarf.strtab.items, debug_strtab_sect.sh_offset);
1229 if (!self.shdr_table_dirty) {
1230 // Then it won't get written with the others and we need to do it.
1231 try self.writeSectHeader(self.debug_str_section_index.?);
1232 }
1233 self.debug_strtab_dirty = false;1219 self.debug_strtab_dirty = false;
1234 }1220 }
1235 }1221 }
...@@ -2861,7 +2847,7 @@ fn writeSymbol(self: *Elf, index: usize) !void {...@@ -2861,7 +2847,7 @@ fn writeSymbol(self: *Elf, index: usize) !void {
2861 .p64 => @alignOf(elf.Elf64_Sym),2847 .p64 => @alignOf(elf.Elf64_Sym),
2862 };2848 };
2863 const needed_size = (self.local_symbols.items.len + self.global_symbols.items.len) * sym_size;2849 const needed_size = (self.local_symbols.items.len + self.global_symbols.items.len) * sym_size;
2864 try self.growNonAllocSection(self.symtab_section_index.?, needed_size, sym_align);2850 try self.growNonAllocSection(self.symtab_section_index.?, needed_size, sym_align, true);
2865 syms_sect.sh_info = @intCast(u32, self.local_symbols.items.len);2851 syms_sect.sh_info = @intCast(u32, self.local_symbols.items.len);
2866 }2852 }
2867 const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian();2853 const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian();
...@@ -2910,7 +2896,7 @@ fn writeAllGlobalSymbols(self: *Elf) !void {...@@ -2910,7 +2896,7 @@ fn writeAllGlobalSymbols(self: *Elf) !void {
2910 .p64 => @alignOf(elf.Elf64_Sym),2896 .p64 => @alignOf(elf.Elf64_Sym),
2911 };2897 };
2912 const needed_size = (self.local_symbols.items.len + self.global_symbols.items.len) * sym_size;2898 const needed_size = (self.local_symbols.items.len + self.global_symbols.items.len) * sym_size;
2913 try self.growNonAllocSection(self.symtab_section_index.?, needed_size, sym_align);2899 try self.growNonAllocSection(self.symtab_section_index.?, needed_size, sym_align, true);
29142900
2915 const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian();2901 const foreign_endian = self.base.options.target.cpu.arch.endian() != builtin.cpu.arch.endian();
2916 const global_syms_off = syms_sect.sh_offset + self.local_symbols.items.len * sym_size;2902 const global_syms_off = syms_sect.sh_offset + self.local_symbols.items.len * sym_size;