elf: hint linker when file range copy is not necessary
This commit is contained in:
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user