zig

fork of https://codeberg.org/ziglang/zig
Log | Files | Refs | README | LICENSE

commit 0aa24ac2e3c122ad16d54d640c11f2de6eb2299a (tree)
parent 9a15c3e1a1dc01d04c976ffbdec46b206455634e
Author: Jakub Konka <kubkon@jakubkonka.com>
Date:   Mon, 30 Sep 2024 22:09:44 +0200

elf: move sections in segments that need moving only

Diffstat:
Msrc/link/Elf.zig | 97+++++++++++++++++++++++++++++++++++++++++++------------------------------------
Msrc/link/Elf/ZigObject.zig | 38--------------------------------------
2 files changed, 53 insertions(+), 82 deletions(-)

diff --git a/src/link/Elf.zig b/src/link/Elf.zig @@ -570,8 +570,6 @@ pub fn growAllocSection(self: *Elf, shdr_index: u32, needed_size: u64, min_align const slice = self.sections.slice(); const shdr = &slice.items(.shdr)[shdr_index]; assert(shdr.sh_flags & elf.SHF_ALLOC != 0); - const phndx = slice.items(.phndx)[shdr_index]; - const maybe_phdr = if (phndx) |ndx| &self.phdrs.items[ndx] else null; log.debug("allocated size {x} of {s}, needed size {x}", .{ self.allocatedSize(shdr.sh_offset), @@ -598,11 +596,9 @@ pub fn growAllocSection(self: *Elf, shdr_index: u32, needed_size: u64, min_align if (amt != existing_size) return error.InputOutput; shdr.sh_offset = new_offset; - if (maybe_phdr) |phdr| phdr.p_offset = new_offset; } else if (shdr.sh_offset + allocated_size == std.math.maxInt(u64)) { try self.base.file.?.setEndPos(shdr.sh_offset + needed_size); } - if (maybe_phdr) |phdr| phdr.p_filesz = needed_size; } shdr.sh_size = needed_size; self.markDirty(shdr_index); @@ -3890,57 +3886,70 @@ pub fn allocateAllocSections(self: *Elf) !void { } const first = slice.items(.shdr)[cover.items[0]]; - var new_offset = try self.findFreeSpace(filesz, @"align"); const phndx = self.getPhdr(.{ .type = elf.PT_LOAD, .flags = shdrToPhdrFlags(first.sh_flags) }).?; const phdr = &self.phdrs.items[phndx]; - phdr.p_offset = new_offset; - phdr.p_vaddr = first.sh_addr; - phdr.p_paddr = first.sh_addr; - phdr.p_memsz = memsz; - phdr.p_filesz = filesz; - phdr.p_align = @"align"; - - for (cover.items) |shndx| { - const shdr = &slice.items(.shdr)[shndx]; - slice.items(.phndx)[shndx] = phndx; - if (shdr.sh_type == elf.SHT_NOBITS) { - shdr.sh_offset = 0; - continue; - } - new_offset = alignment.@"align"(shndx, shdr.sh_addralign, new_offset); + const allocated_size = self.allocatedSize(phdr.p_offset); + if (filesz > allocated_size) { + const old_offset = phdr.p_offset; + phdr.p_offset = 0; + var new_offset = try self.findFreeSpace(filesz, @"align"); + phdr.p_offset = new_offset; + + log.debug("moving phdr({d}) from 0x{x} to 0x{x}", .{ phndx, old_offset, new_offset }); + + for (cover.items) |shndx| { + const shdr = &slice.items(.shdr)[shndx]; + slice.items(.phndx)[shndx] = phndx; + if (shdr.sh_type == elf.SHT_NOBITS) { + shdr.sh_offset = 0; + continue; + } + new_offset = alignment.@"align"(shndx, shdr.sh_addralign, new_offset); - if (self.zigObjectPtr()) |zo| blk: { - const existing_size = for ([_]?Symbol.Index{ - zo.text_index, - zo.rodata_index, - zo.data_relro_index, - zo.data_index, - zo.tdata_index, - zo.eh_frame_index, - }) |maybe_sym_index| { - const sect_sym_index = maybe_sym_index orelse continue; - const sect_atom_ptr = zo.symbol(sect_sym_index).atom(self).?; - if (sect_atom_ptr.output_section_index != shndx) continue; - break sect_atom_ptr.size; - } else break :blk; log.debug("moving {s} from 0x{x} to 0x{x}", .{ self.getShString(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; - } - shdr.sh_offset = new_offset; - new_offset += shdr.sh_size; + if (shdr.sh_offset > 0) { + // Get size actually commited to the output file. + const existing_size = if (self.zigObjectPtr()) |zo| for ([_]?Symbol.Index{ + zo.text_index, + zo.rodata_index, + zo.data_relro_index, + zo.data_index, + zo.tdata_index, + zo.eh_frame_index, + }) |maybe_sym_index| { + const sect_sym_index = maybe_sym_index orelse continue; + const sect_atom_ptr = zo.symbol(sect_sym_index).atom(self).?; + if (sect_atom_ptr.output_section_index != shndx) continue; + break sect_atom_ptr.size; + } else 0 else 0 + if (!slice.items(.atom_list_2)[shndx].dirty) + slice.items(.atom_list_2)[shndx].size + else + 0; + 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; + new_offset += shdr.sh_size; + } } + phdr.p_vaddr = first.sh_addr; + phdr.p_paddr = first.sh_addr; + phdr.p_memsz = memsz; + phdr.p_filesz = filesz; + phdr.p_align = @"align"; + addr = mem.alignForward(u64, addr, self.page_size); } } diff --git a/src/link/Elf/ZigObject.zig b/src/link/Elf/ZigObject.zig @@ -336,8 +336,6 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi const atom_ptr = self.atom(sym.ref.index).?; if (!atom_ptr.alive) continue; - log.debug("parsing relocs in {s}", .{sym.name(elf_file)}); - const relocs = &self.relocs.items[atom_ptr.relocsShndx().?]; for (sect.units.items) |*unit| { try relocs.ensureUnusedCapacity(gpa, unit.cross_unit_relocs.items.len + @@ -350,12 +348,6 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi else 0)); const r_type = relocation.dwarf.crossSectionRelocType(dwarf.format, cpu_arch); - log.debug(" {s} <- r_off={x}, r_add={x}, r_type={}", .{ - self.symbol(sym_index).name(elf_file), - r_offset, - r_addend, - relocation.fmtRelocType(r_type, cpu_arch), - }); atom_ptr.addRelocAssumeCapacity(.{ .r_offset = r_offset, .r_addend = r_addend, @@ -384,12 +376,6 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi else 0)); const r_type = relocation.dwarf.crossSectionRelocType(dwarf.format, cpu_arch); - log.debug(" {s} <- r_off={x}, r_add={x}, r_type={}", .{ - self.symbol(target_sym_index).name(elf_file), - r_offset, - r_addend, - relocation.fmtRelocType(r_type, cpu_arch), - }); atom_ptr.addRelocAssumeCapacity(.{ .r_offset = r_offset, .r_addend = r_addend, @@ -410,12 +396,6 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi else 0)); const r_type = relocation.dwarf.crossSectionRelocType(dwarf.format, cpu_arch); - log.debug(" {s} <- r_off={x}, r_add={x}, r_type={}", .{ - self.symbol(sym_index).name(elf_file), - r_offset, - r_addend, - relocation.fmtRelocType(r_type, cpu_arch), - }); atom_ptr.addRelocAssumeCapacity(.{ .r_offset = r_offset, .r_addend = r_addend, @@ -430,12 +410,6 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi else 0)); const r_type = relocation.dwarf.crossSectionRelocType(dwarf.format, cpu_arch); - log.debug(" {s} <- r_off={x}, r_add={x}, r_type={}", .{ - self.symbol(sym_index).name(elf_file), - r_offset, - r_addend, - relocation.fmtRelocType(r_type, cpu_arch), - }); atom_ptr.addRelocAssumeCapacity(.{ .r_offset = r_offset, .r_addend = r_addend, @@ -464,12 +438,6 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi else 0)); const r_type = relocation.dwarf.crossSectionRelocType(dwarf.format, cpu_arch); - log.debug(" {s} <- r_off={x}, r_add={x}, r_type={}", .{ - self.symbol(target_sym_index).name(elf_file), - r_offset, - r_addend, - relocation.fmtRelocType(r_type, cpu_arch), - }); atom_ptr.addRelocAssumeCapacity(.{ .r_offset = r_offset, .r_addend = r_addend, @@ -481,12 +449,6 @@ pub fn flushModule(self: *ZigObject, elf_file: *Elf, tid: Zcu.PerThread.Id) !voi const r_offset = entry_off + reloc.source_off; const r_addend: i64 = @intCast(reloc.target_off); const r_type = relocation.dwarf.externalRelocType(target_sym.*, sect_index, dwarf.address_size, cpu_arch); - log.debug(" {s} <- r_off={x}, r_add={x}, r_type={}", .{ - target_sym.name(elf_file), - r_offset, - r_addend, - relocation.fmtRelocType(r_type, cpu_arch), - }); atom_ptr.addRelocAssumeCapacity(.{ .r_offset = r_offset, .r_addend = r_addend,