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