| ... | @@ -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 | } |
| 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 | pub fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u64) !u64 { | 551 | pub 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 | } |
| 568 | | 558 | |
| 569 | pub fn growAllocSection(self: *Elf, shdr_index: u32, needed_size: u64, min_alignment: u64) !void { | 559 | pub 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); | | |
| 573 | | 562 | |
| 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 | }); |
| 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 | 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); |
| 623 | | 575 | |
| 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 | }); |
| 629 | | 581 | |
| 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 | } | | |
| 639 | | 590 | |
| 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 | } |
| 647 | | 596 | |
| 648 | pub fn markDirty(self: *Elf, shdr_index: u32) void { | 597 | pub 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 | else | 705 | } |
| 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 | } |
| 759 | | 709 | |
| 760 | return res; | 710 | return res; |