| ... | ... | @@ -558,43 +558,47 @@ pub fn findFreeSpace(self: *Elf, object_size: u64, min_alignment: u64) !u64 { |
| 558 | 558 | |
| 559 | 559 | pub fn growSection(self: *Elf, shdr_index: u32, needed_size: u64, min_alignment: u64) !void { |
| 560 | 560 | const shdr = &self.sections.items(.shdr)[shdr_index]; |
| 561 | | assert(shdr.sh_type != elf.SHT_NOBITS); |
| 562 | 561 | |
| 563 | | const allocated_size = self.allocatedSize(shdr.sh_offset); |
| 564 | | log.debug("allocated size {x} of '{s}', needed size {x}", .{ |
| 565 | | allocated_size, |
| 566 | | self.getShString(shdr.sh_name), |
| 567 | | needed_size, |
| 568 | | }); |
| 569 | | |
| 570 | | if (needed_size > allocated_size) { |
| 571 | | const existing_size = shdr.sh_size; |
| 572 | | shdr.sh_size = 0; |
| 573 | | // Must move the entire section. |
| 574 | | const new_offset = try self.findFreeSpace(needed_size, min_alignment); |
| 575 | | |
| 576 | | log.debug("new '{s}' file offset 0x{x} to 0x{x}", .{ |
| 562 | if (shdr.sh_type != elf.SHT_NOBITS) { |
| 563 | const allocated_size = self.allocatedSize(shdr.sh_offset); |
| 564 | log.debug("allocated size {x} of '{s}', needed size {x}", .{ |
| 565 | allocated_size, |
| 577 | 566 | self.getShString(shdr.sh_name), |
| 578 | | new_offset, |
| 579 | | new_offset + existing_size, |
| 567 | needed_size, |
| 580 | 568 | }); |
| 581 | 569 | |
| 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; |
| 570 | if (needed_size > allocated_size) { |
| 571 | const existing_size = shdr.sh_size; |
| 572 | shdr.sh_size = 0; |
| 573 | // Must move the entire section. |
| 574 | const new_offset = try self.findFreeSpace(needed_size, min_alignment); |
| 575 | |
| 576 | log.debug("new '{s}' file offset 0x{x} to 0x{x}", .{ |
| 577 | self.getShString(shdr.sh_name), |
| 578 | new_offset, |
| 579 | new_offset + existing_size, |
| 580 | }); |
| 581 | |
| 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; |
| 590 | 590 | |
| 591 | | shdr.sh_offset = new_offset; |
| 592 | | } else if (shdr.sh_offset + allocated_size == std.math.maxInt(u64)) { |
| 593 | | try self.base.file.?.setEndPos(shdr.sh_offset + needed_size); |
| 591 | shdr.sh_offset = new_offset; |
| 592 | } else if (shdr.sh_offset + allocated_size == std.math.maxInt(u64)) { |
| 593 | try self.base.file.?.setEndPos(shdr.sh_offset + needed_size); |
| 594 | } |
| 594 | 595 | } |
| 596 | |
| 597 | shdr.sh_size = needed_size; |
| 598 | self.markDirty(shdr_index); |
| 595 | 599 | } |
| 596 | 600 | |
| 597 | | pub fn markDirty(self: *Elf, shdr_index: u32) void { |
| 601 | fn markDirty(self: *Elf, shdr_index: u32) void { |
| 598 | 602 | if (self.zigObjectPtr()) |zo| { |
| 599 | 603 | for ([_]?Symbol.Index{ |
| 600 | 604 | zo.debug_info_index, |
| ... | ... | @@ -700,11 +704,7 @@ pub fn allocateChunk(self: *Elf, args: struct { |
| 700 | 704 | true; |
| 701 | 705 | if (expand_section) { |
| 702 | 706 | const needed_size = res.value + args.size; |
| 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); |
| 707 | try self.growSection(args.shndx, needed_size, args.alignment.toByteUnits().?); |
| 708 | 708 | } |
| 709 | 709 | |
| 710 | 710 | return res; |