| ... | ... | @@ -659,12 +659,17 @@ const AllocateChunkResult = struct { |
| 659 | 659 | placement: Ref, |
| 660 | 660 | }; |
| 661 | 661 | |
| 662 | | pub fn allocateChunk(self: *Elf, shndx: u32, size: u64, alignment: Atom.Alignment) !AllocateChunkResult { |
| 662 | pub fn allocateChunk(self: *Elf, args: struct { |
| 663 | size: u64, |
| 664 | shndx: u32, |
| 665 | alignment: Atom.Alignment, |
| 666 | requires_padding: bool = true, |
| 667 | }) !AllocateChunkResult { |
| 663 | 668 | const slice = self.sections.slice(); |
| 664 | | const shdr = &slice.items(.shdr)[shndx]; |
| 665 | | const free_list = &slice.items(.free_list)[shndx]; |
| 666 | | const last_atom_ref = &slice.items(.last_atom)[shndx]; |
| 667 | | const new_atom_ideal_capacity = padToIdeal(size); |
| 669 | const shdr = &slice.items(.shdr)[args.shndx]; |
| 670 | const free_list = &slice.items(.free_list)[args.shndx]; |
| 671 | const last_atom_ref = &slice.items(.last_atom)[args.shndx]; |
| 672 | const new_atom_ideal_capacity = if (args.requires_padding) padToIdeal(args.size) else args.size; |
| 668 | 673 | |
| 669 | 674 | // First we look for an appropriately sized free list node. |
| 670 | 675 | // The list is unordered. We'll just take the first thing that works. |
| ... | ... | @@ -676,11 +681,11 @@ pub fn allocateChunk(self: *Elf, shndx: u32, size: u64, alignment: Atom.Alignmen |
| 676 | 681 | // We now have a pointer to a live atom that has too much capacity. |
| 677 | 682 | // Is it enough that we could fit this new atom? |
| 678 | 683 | const cap = big_atom.capacity(self); |
| 679 | | const ideal_capacity = padToIdeal(cap); |
| 684 | const ideal_capacity = if (args.requires_padding) padToIdeal(cap) else cap; |
| 680 | 685 | const ideal_capacity_end_vaddr = std.math.add(u64, @intCast(big_atom.value), ideal_capacity) catch ideal_capacity; |
| 681 | 686 | const capacity_end_vaddr = @as(u64, @intCast(big_atom.value)) + cap; |
| 682 | 687 | const new_start_vaddr_unaligned = capacity_end_vaddr - new_atom_ideal_capacity; |
| 683 | | const new_start_vaddr = alignment.backward(new_start_vaddr_unaligned); |
| 688 | const new_start_vaddr = args.alignment.backward(new_start_vaddr_unaligned); |
| 684 | 689 | if (new_start_vaddr < ideal_capacity_end_vaddr) { |
| 685 | 690 | // Additional bookkeeping here to notice if this free list node |
| 686 | 691 | // should be deleted because the block that it points to has grown to take up |
| ... | ... | @@ -703,9 +708,9 @@ pub fn allocateChunk(self: *Elf, shndx: u32, size: u64, alignment: Atom.Alignmen |
| 703 | 708 | } |
| 704 | 709 | break :blk .{ .value = new_start_vaddr, .placement = big_atom_ref }; |
| 705 | 710 | } else if (self.atom(last_atom_ref.*)) |last_atom| { |
| 706 | | const ideal_capacity = padToIdeal(last_atom.size); |
| 711 | const ideal_capacity = if (args.requires_padding) padToIdeal(last_atom.size) else last_atom.size; |
| 707 | 712 | const ideal_capacity_end_vaddr = @as(u64, @intCast(last_atom.value)) + ideal_capacity; |
| 708 | | const new_start_vaddr = alignment.forward(ideal_capacity_end_vaddr); |
| 713 | const new_start_vaddr = args.alignment.forward(ideal_capacity_end_vaddr); |
| 709 | 714 | break :blk .{ .value = new_start_vaddr, .placement = last_atom.ref() }; |
| 710 | 715 | } else { |
| 711 | 716 | break :blk .{ .value = 0, .placement = .{} }; |
| ... | ... | @@ -713,8 +718,8 @@ pub fn allocateChunk(self: *Elf, shndx: u32, size: u64, alignment: Atom.Alignmen |
| 713 | 718 | }; |
| 714 | 719 | |
| 715 | 720 | log.debug("allocated chunk (size({x}),align({x})) at 0x{x} (file(0x{x}))", .{ |
| 716 | | size, |
| 717 | | alignment.toByteUnits().?, |
| 721 | args.size, |
| 722 | args.alignment.toByteUnits().?, |
| 718 | 723 | shdr.sh_addr + res.value, |
| 719 | 724 | shdr.sh_offset + res.value, |
| 720 | 725 | }); |
| ... | ... | @@ -724,11 +729,11 @@ pub fn allocateChunk(self: *Elf, shndx: u32, size: u64, alignment: Atom.Alignmen |
| 724 | 729 | else |
| 725 | 730 | true; |
| 726 | 731 | if (expand_section) { |
| 727 | | const needed_size = res.value + size; |
| 732 | const needed_size = res.value + args.size; |
| 728 | 733 | if (shdr.sh_flags & elf.SHF_ALLOC != 0) |
| 729 | | try self.growAllocSection(shndx, needed_size, alignment.toByteUnits().?) |
| 734 | try self.growAllocSection(args.shndx, needed_size, args.alignment.toByteUnits().?) |
| 730 | 735 | else |
| 731 | | try self.growNonAllocSection(shndx, needed_size, alignment.toByteUnits().?, true); |
| 736 | try self.growNonAllocSection(args.shndx, needed_size, args.alignment.toByteUnits().?, true); |
| 732 | 737 | } |
| 733 | 738 | |
| 734 | 739 | return res; |