authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-10-01 07:31:13+02:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2024-10-09 12:38:11-07:00
log887f9a29f35ca32521ac6786ba6aab6fd240421f
treee285d18e56b872b5b79f068483942db5af3d15ed
parent0aa24ac2e3c122ad16d54d640c11f2de6eb2299a

elf: combine growAllocSection and growNonAllocSection into growSection


2 files changed, 28 insertions(+), 77 deletions(-)

src/link/Dwarf.zig+8-7
...@@ -390,14 +390,15 @@ pub const Section = struct {...@@ -390,14 +390,15 @@ pub const Section = struct {
390 const zo = elf_file.zigObjectPtr().?;390 const zo = elf_file.zigObjectPtr().?;
391 const atom = zo.symbol(sec.index).atom(elf_file).?;391 const atom = zo.symbol(sec.index).atom(elf_file).?;
392 const shndx = atom.output_section_index;392 const shndx = atom.output_section_index;
393 if (sec == &dwarf.debug_frame.section)393 const needed_size = len;
394 try elf_file.growAllocSection(shndx, len, sec.alignment.toByteUnits().?)394 const min_alignment = sec.alignment.toByteUnits().?;
395 else395 try elf_file.growSection(shndx, needed_size, min_alignment);
396 try elf_file.growNonAllocSection(shndx, len, sec.alignment.toByteUnits().?, true);396 const shdr = &elf_file.sections.items(.shdr)[shndx];
397 const shdr = elf_file.sections.items(.shdr)[shndx];397 shdr.sh_size = needed_size;
398 atom.size = shdr.sh_size;398 elf_file.markDirty(shndx);
399 atom.size = needed_size;
399 atom.alignment = InternPool.Alignment.fromNonzeroByteUnits(shdr.sh_addralign);400 atom.alignment = InternPool.Alignment.fromNonzeroByteUnits(shdr.sh_addralign);
400 sec.len = shdr.sh_size;401 sec.len = len;
401 } else if (dwarf.bin_file.cast(.macho)) |macho_file| {402 } else if (dwarf.bin_file.cast(.macho)) |macho_file| {
402 const header = if (macho_file.d_sym) |*d_sym| header: {403 const header = if (macho_file.d_sym) |*d_sym| header: {
403 try d_sym.growSection(@intCast(sec.index), len, true, macho_file);404 try d_sym.growSection(@intCast(sec.index), len, true, macho_file);
src/link/Elf.zig+20-70
...@@ -548,16 +548,6 @@ pub fn allocatedSize(self: *Elf, start: u64) u64 {...@@ -548,16 +548,6 @@ pub fn allocatedSize(self: *Elf, start: u64) u64 {
548 return min_pos - start;548 return min_pos - start;
549}549}
550550
551fn allocatedVirtualSize(self: *Elf, start: u64) u64 {
552 if (start == 0) return 0;
553 var min_pos: u64 = std.math.maxInt(u64);
554 for (self.phdrs.items) |phdr| {
555 if (phdr.p_vaddr <= start) continue;
556 if (phdr.p_vaddr < min_pos) min_pos = phdr.p_vaddr;
557 }
558 return min_pos - start;
559}
560
561pub fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u64) !u64 {551pub fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u64) !u64 {
562 var start: u64 = 0;552 var start: u64 = 0;
563 while (try self.detectAllocCollision(start, object_size)) |item_end| {553 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 {...@@ -566,59 +556,21 @@ pub fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u64) !u64 {
566 return start;556 return start;
567}557}
568558
569pub fn growAllocSection(self: *Elf, shdr_index: u32, needed_size: u64, min_alignment: u64) !void {559pub fn growSection(self: *Elf, shdr_index: u32, needed_size: u64, min_alignment: u64) !void {
570 const slice = self.sections.slice();560 const shdr = &self.sections.items(.shdr)[shdr_index];
571 const shdr = &slice.items(.shdr)[shdr_index];561 assert(shdr.sh_type != elf.SHT_NOBITS);
572 assert(shdr.sh_flags & elf.SHF_ALLOC != 0);
573562
574 log.debug("allocated size {x} of {s}, needed size {x}", .{563 const allocated_size = self.allocatedSize(shdr.sh_offset);
575 self.allocatedSize(shdr.sh_offset),564 log.debug("allocated size {x} of '{s}', needed size {x}", .{
565 allocated_size,
576 self.getShString(shdr.sh_name),566 self.getShString(shdr.sh_name),
577 needed_size,567 needed_size,
578 });568 });
579569
580 if (shdr.sh_type != elf.SHT_NOBITS) {
581 const allocated_size = self.allocatedSize(shdr.sh_offset);
582 if (needed_size > allocated_size) {
583 const existing_size = shdr.sh_size;
584 shdr.sh_size = 0;
585 // Must move the entire section.
586 const new_offset = try self.findFreeSpace(needed_size, min_alignment);
587
588 log.debug("new '{s}' file offset 0x{x} to 0x{x}", .{
589 self.getShString(shdr.sh_name),
590 new_offset,
591 new_offset + existing_size,
592 });
593
594 const amt = try self.base.file.?.copyRangeAll(shdr.sh_offset, self.base.file.?, new_offset, existing_size);
595 // TODO figure out what to about this error condition - how to communicate it up.
596 if (amt != existing_size) return error.InputOutput;
597
598 shdr.sh_offset = new_offset;
599 } else if (shdr.sh_offset + allocated_size == std.math.maxInt(u64)) {
600 try self.base.file.?.setEndPos(shdr.sh_offset + needed_size);
601 }
602 }
603 shdr.sh_size = needed_size;
604 self.markDirty(shdr_index);
605}
606
607pub fn growNonAllocSection(
608 self: *Elf,
609 shdr_index: u32,
610 needed_size: u64,
611 min_alignment: u64,
612 requires_file_copy: bool,
613) !void {
614 const shdr = &self.sections.items(.shdr)[shdr_index];
615 assert(shdr.sh_flags & elf.SHF_ALLOC == 0);
616
617 const allocated_size = self.allocatedSize(shdr.sh_offset);
618 if (needed_size > allocated_size) {570 if (needed_size > allocated_size) {
619 const existing_size = shdr.sh_size;571 const existing_size = shdr.sh_size;
620 shdr.sh_size = 0;572 shdr.sh_size = 0;
621 // Move all the symbols to a new file location.573 // Must move the entire section.
622 const new_offset = try self.findFreeSpace(needed_size, min_alignment);574 const new_offset = try self.findFreeSpace(needed_size, min_alignment);
623575
624 log.debug("new '{s}' file offset 0x{x} to 0x{x}", .{576 log.debug("new '{s}' file offset 0x{x} to 0x{x}", .{
...@@ -627,22 +579,19 @@ pub fn growNonAllocSection(...@@ -627,22 +579,19 @@ pub fn growNonAllocSection(
627 new_offset + existing_size,579 new_offset + existing_size,
628 });580 });
629581
630 if (requires_file_copy) {582 const amt = try self.base.file.?.copyRangeAll(
631 const amt = try self.base.file.?.copyRangeAll(583 shdr.sh_offset,
632 shdr.sh_offset,584 self.base.file.?,
633 self.base.file.?,585 new_offset,
634 new_offset,586 existing_size,
635 existing_size,587 );
636 );588 // TODO figure out what to about this error condition - how to communicate it up.
637 if (amt != existing_size) return error.InputOutput;589 if (amt != existing_size) return error.InputOutput;
638 }
639590
640 shdr.sh_offset = new_offset;591 shdr.sh_offset = new_offset;
641 } else if (shdr.sh_offset + allocated_size == std.math.maxInt(u64)) {592 } else if (shdr.sh_offset + allocated_size == std.math.maxInt(u64)) {
642 try self.base.file.?.setEndPos(shdr.sh_offset + needed_size);593 try self.base.file.?.setEndPos(shdr.sh_offset + needed_size);
643 }594 }
644 shdr.sh_size = needed_size;
645 self.markDirty(shdr_index);
646}595}
647596
648pub fn markDirty(self: *Elf, shdr_index: u32) void {597pub fn markDirty(self: *Elf, shdr_index: u32) void {
...@@ -751,10 +700,11 @@ pub fn allocateChunk(self: *Elf, args: struct {...@@ -751,10 +700,11 @@ pub fn allocateChunk(self: *Elf, args: struct {
751 true;700 true;
752 if (expand_section) {701 if (expand_section) {
753 const needed_size = res.value + args.size;702 const needed_size = res.value + args.size;
754 if (shdr.sh_flags & elf.SHF_ALLOC != 0)703 if (shdr.sh_type != elf.SHT_NOBITS) {
755 try self.growAllocSection(args.shndx, needed_size, args.alignment.toByteUnits().?)704 try self.growSection(args.shndx, needed_size, args.alignment.toByteUnits().?);
756 else705 }
757 try self.growNonAllocSection(args.shndx, needed_size, args.alignment.toByteUnits().?, true);706 shdr.sh_size = needed_size;
707 self.markDirty(args.shndx);
758 }708 }
759709
760 return res;710 return res;