| ... | ... | @@ -548,16 +548,6 @@ pub fn allocatedSize(self: *Elf, start: u64) u64 { |
| 548 | 548 | return min_pos - start; |
| 549 | 549 | } |
| 550 | 550 | |
| 551 | | fn 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 | | |
| 561 | 551 | pub fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u64) !u64 { |
| 562 | 552 | var start: u64 = 0; |
| 563 | 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 | 556 | return start; |
| 567 | 557 | } |
| 568 | 558 | |
| 569 | | pub fn growAllocSection(self: *Elf, shdr_index: u32, needed_size: u64, min_alignment: u64) !void { |
| 570 | | const slice = self.sections.slice(); |
| 571 | | const shdr = &slice.items(.shdr)[shdr_index]; |
| 572 | | assert(shdr.sh_flags & elf.SHF_ALLOC != 0); |
| 559 | pub fn growSection(self: *Elf, shdr_index: u32, needed_size: u64, min_alignment: u64) !void { |
| 560 | const shdr = &self.sections.items(.shdr)[shdr_index]; |
| 561 | assert(shdr.sh_type != elf.SHT_NOBITS); |
| 573 | 562 | |
| 574 | | log.debug("allocated size {x} of {s}, needed size {x}", .{ |
| 575 | | self.allocatedSize(shdr.sh_offset), |
| 563 | const allocated_size = self.allocatedSize(shdr.sh_offset); |
| 564 | log.debug("allocated size {x} of '{s}', needed size {x}", .{ |
| 565 | allocated_size, |
| 576 | 566 | self.getShString(shdr.sh_name), |
| 577 | 567 | needed_size, |
| 578 | 568 | }); |
| 579 | 569 | |
| 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 | | |
| 607 | | pub 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 | 570 | if (needed_size > allocated_size) { |
| 619 | 571 | const existing_size = shdr.sh_size; |
| 620 | 572 | shdr.sh_size = 0; |
| 621 | | // Move all the symbols to a new file location. |
| 573 | // Must move the entire section. |
| 622 | 574 | const new_offset = try self.findFreeSpace(needed_size, min_alignment); |
| 623 | 575 | |
| 624 | 576 | log.debug("new '{s}' file offset 0x{x} to 0x{x}", .{ |
| ... | ... | @@ -627,22 +579,19 @@ pub fn growNonAllocSection( |
| 627 | 579 | new_offset + existing_size, |
| 628 | 580 | }); |
| 629 | 581 | |
| 630 | | if (requires_file_copy) { |
| 631 | | const amt = try self.base.file.?.copyRangeAll( |
| 632 | | shdr.sh_offset, |
| 633 | | self.base.file.?, |
| 634 | | new_offset, |
| 635 | | existing_size, |
| 636 | | ); |
| 637 | | if (amt != existing_size) return error.InputOutput; |
| 638 | | } |
| 582 | const amt = try self.base.file.?.copyRangeAll( |
| 583 | shdr.sh_offset, |
| 584 | self.base.file.?, |
| 585 | new_offset, |
| 586 | existing_size, |
| 587 | ); |
| 588 | // TODO figure out what to about this error condition - how to communicate it up. |
| 589 | if (amt != existing_size) return error.InputOutput; |
| 639 | 590 | |
| 640 | 591 | shdr.sh_offset = new_offset; |
| 641 | 592 | } else if (shdr.sh_offset + allocated_size == std.math.maxInt(u64)) { |
| 642 | 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 | } |
| 647 | 596 | |
| 648 | 597 | pub fn markDirty(self: *Elf, shdr_index: u32) void { |
| ... | ... | @@ -751,10 +700,11 @@ pub fn allocateChunk(self: *Elf, args: struct { |
| 751 | 700 | true; |
| 752 | 701 | if (expand_section) { |
| 753 | 702 | const needed_size = res.value + args.size; |
| 754 | | if (shdr.sh_flags & elf.SHF_ALLOC != 0) |
| 755 | | try self.growAllocSection(args.shndx, needed_size, args.alignment.toByteUnits().?) |
| 756 | | else |
| 757 | | try self.growNonAllocSection(args.shndx, needed_size, args.alignment.toByteUnits().?, true); |
| 703 | if (shdr.sh_type != elf.SHT_NOBITS) { |
| 704 | try self.growSection(args.shndx, needed_size, args.alignment.toByteUnits().?); |
| 705 | } |
| 706 | shdr.sh_size = needed_size; |
| 707 | self.markDirty(args.shndx); |
| 758 | 708 | } |
| 759 | 709 | |
| 760 | 710 | return res; |