elf: combine growAllocSection and growNonAllocSection into growSection

This commit is contained in:
Jakub Konka 2024-10-01 07:31:13 +02:00 committed by Andrew Kelley
parent 0aa24ac2e3
commit 887f9a29f3
2 changed files with 28 additions and 77 deletions

View File

@ -390,14 +390,15 @@ pub const Section = struct {
const zo = elf_file.zigObjectPtr().?;
const atom = zo.symbol(sec.index).atom(elf_file).?;
const shndx = atom.output_section_index;
if (sec == &dwarf.debug_frame.section)
try elf_file.growAllocSection(shndx, len, sec.alignment.toByteUnits().?)
else
try elf_file.growNonAllocSection(shndx, len, sec.alignment.toByteUnits().?, true);
const shdr = elf_file.sections.items(.shdr)[shndx];
atom.size = shdr.sh_size;
const needed_size = len;
const min_alignment = sec.alignment.toByteUnits().?;
try elf_file.growSection(shndx, needed_size, min_alignment);
const shdr = &elf_file.sections.items(.shdr)[shndx];
shdr.sh_size = needed_size;
elf_file.markDirty(shndx);
atom.size = needed_size;
atom.alignment = InternPool.Alignment.fromNonzeroByteUnits(shdr.sh_addralign);
sec.len = shdr.sh_size;
sec.len = len;
} else if (dwarf.bin_file.cast(.macho)) |macho_file| {
const header = if (macho_file.d_sym) |*d_sym| header: {
try d_sym.growSection(@intCast(sec.index), len, true, macho_file);

View File

@ -548,16 +548,6 @@ pub fn allocatedSize(self: *Elf, start: u64) u64 {
return min_pos - start;
}
fn allocatedVirtualSize(self: *Elf, start: u64) u64 {
if (start == 0) return 0;
var min_pos: u64 = std.math.maxInt(u64);
for (self.phdrs.items) |phdr| {
if (phdr.p_vaddr <= start) continue;
if (phdr.p_vaddr < min_pos) min_pos = phdr.p_vaddr;
}
return min_pos - start;
}
pub fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u64) !u64 {
var start: u64 = 0;
while (try self.detectAllocCollision(start, object_size)) |item_end| {
@ -566,59 +556,21 @@ pub fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u64) !u64 {
return start;
}
pub fn growAllocSection(self: *Elf, shdr_index: u32, needed_size: u64, min_alignment: u64) !void {
const slice = self.sections.slice();
const shdr = &slice.items(.shdr)[shdr_index];
assert(shdr.sh_flags & elf.SHF_ALLOC != 0);
pub fn growSection(self: *Elf, shdr_index: u32, needed_size: u64, min_alignment: u64) !void {
const shdr = &self.sections.items(.shdr)[shdr_index];
assert(shdr.sh_type != elf.SHT_NOBITS);
log.debug("allocated size {x} of {s}, needed size {x}", .{
self.allocatedSize(shdr.sh_offset),
const allocated_size = self.allocatedSize(shdr.sh_offset);
log.debug("allocated size {x} of '{s}', needed size {x}", .{
allocated_size,
self.getShString(shdr.sh_name),
needed_size,
});
if (shdr.sh_type != elf.SHT_NOBITS) {
const allocated_size = self.allocatedSize(shdr.sh_offset);
if (needed_size > allocated_size) {
const existing_size = shdr.sh_size;
shdr.sh_size = 0;
// Must move the entire section.
const new_offset = try self.findFreeSpace(needed_size, min_alignment);
log.debug("new '{s}' file offset 0x{x} to 0x{x}", .{
self.getShString(shdr.sh_name),
new_offset,
new_offset + existing_size,
});
const amt = try self.base.file.?.copyRangeAll(shdr.sh_offset, self.base.file.?, new_offset, existing_size);
// TODO figure out what to about this error condition - how to communicate it up.
if (amt != existing_size) return error.InputOutput;
shdr.sh_offset = new_offset;
} else if (shdr.sh_offset + allocated_size == std.math.maxInt(u64)) {
try self.base.file.?.setEndPos(shdr.sh_offset + needed_size);
}
}
shdr.sh_size = needed_size;
self.markDirty(shdr_index);
}
pub fn growNonAllocSection(
self: *Elf,
shdr_index: u32,
needed_size: u64,
min_alignment: u64,
requires_file_copy: bool,
) !void {
const shdr = &self.sections.items(.shdr)[shdr_index];
assert(shdr.sh_flags & elf.SHF_ALLOC == 0);
const allocated_size = self.allocatedSize(shdr.sh_offset);
if (needed_size > allocated_size) {
const existing_size = shdr.sh_size;
shdr.sh_size = 0;
// Move all the symbols to a new file location.
// Must move the entire section.
const new_offset = try self.findFreeSpace(needed_size, min_alignment);
log.debug("new '{s}' file offset 0x{x} to 0x{x}", .{
@ -627,22 +579,19 @@ pub fn growNonAllocSection(
new_offset + existing_size,
});
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;
}
const amt = try self.base.file.?.copyRangeAll(
shdr.sh_offset,
self.base.file.?,
new_offset,
existing_size,
);
// TODO figure out what to about this error condition - how to communicate it up.
if (amt != existing_size) return error.InputOutput;
shdr.sh_offset = new_offset;
} else if (shdr.sh_offset + allocated_size == std.math.maxInt(u64)) {
try self.base.file.?.setEndPos(shdr.sh_offset + needed_size);
}
shdr.sh_size = needed_size;
self.markDirty(shdr_index);
}
pub fn markDirty(self: *Elf, shdr_index: u32) void {
@ -751,10 +700,11 @@ pub fn allocateChunk(self: *Elf, args: struct {
true;
if (expand_section) {
const needed_size = res.value + args.size;
if (shdr.sh_flags & elf.SHF_ALLOC != 0)
try self.growAllocSection(args.shndx, needed_size, args.alignment.toByteUnits().?)
else
try self.growNonAllocSection(args.shndx, needed_size, args.alignment.toByteUnits().?, true);
if (shdr.sh_type != elf.SHT_NOBITS) {
try self.growSection(args.shndx, needed_size, args.alignment.toByteUnits().?);
}
shdr.sh_size = needed_size;
self.markDirty(args.shndx);
}
return res;