| ... | ... | @@ -3493,6 +3493,14 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void { |
| 3493 | 3493 | } |
| 3494 | 3494 | |
| 3495 | 3495 | pub fn growSection(self: *MachO, sect_index: u8, needed_size: u64) !void { |
| 3496 | if (self.base.isRelocatable()) { |
| 3497 | try self.growSectionRelocatable(sect_index, needed_size); |
| 3498 | } else { |
| 3499 | try self.growSectionNonRelocatable(sect_index, needed_size); |
| 3500 | } |
| 3501 | } |
| 3502 | |
| 3503 | fn growSectionNonRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !void { |
| 3496 | 3504 | const sect = &self.sections.items(.header)[sect_index]; |
| 3497 | 3505 | |
| 3498 | 3506 | if (needed_size > self.allocatedSize(sect.offset) and !sect.isZerofill()) { |
| ... | ... | @@ -3500,65 +3508,73 @@ pub fn growSection(self: *MachO, sect_index: u8, needed_size: u64) !void { |
| 3500 | 3508 | sect.size = 0; |
| 3501 | 3509 | |
| 3502 | 3510 | // Must move the entire section. |
| 3503 | | if (self.base.isRelocatable()) { |
| 3504 | | const alignment = try math.powi(u32, 2, sect.@"align"); |
| 3505 | | const new_offset = self.findFreeSpace(needed_size, alignment); |
| 3506 | | const new_addr = self.findFreeSpaceVirtual(needed_size, alignment); |
| 3511 | const alignment = self.getPageSize(); |
| 3512 | const new_offset = self.findFreeSpace(needed_size, alignment); |
| 3513 | |
| 3514 | log.debug("new '{s},{s}' file offset 0x{x} to 0x{x}", .{ |
| 3515 | sect.segName(), |
| 3516 | sect.sectName(), |
| 3517 | new_offset, |
| 3518 | new_offset + existing_size, |
| 3519 | }); |
| 3507 | 3520 | |
| 3508 | | log.debug("new '{s},{s}' file offset 0x{x} to 0x{x} (0x{x} - 0x{x})", .{ |
| 3509 | | sect.segName(), |
| 3510 | | sect.sectName(), |
| 3511 | | new_offset, |
| 3512 | | new_offset + existing_size, |
| 3513 | | new_addr, |
| 3514 | | new_addr + existing_size, |
| 3515 | | }); |
| 3521 | try self.copyRangeAllZeroOut(sect.offset, new_offset, existing_size); |
| 3516 | 3522 | |
| 3517 | | try self.copyRangeAll(sect.offset, new_offset, existing_size); |
| 3523 | sect.offset = @intCast(new_offset); |
| 3524 | } |
| 3518 | 3525 | |
| 3519 | | sect.offset = @intCast(new_offset); |
| 3520 | | sect.addr = new_addr; |
| 3521 | | } else { |
| 3522 | | const alignment = self.getPageSize(); |
| 3523 | | const new_offset = self.findFreeSpace(needed_size, alignment); |
| 3526 | sect.size = needed_size; |
| 3524 | 3527 | |
| 3525 | | log.debug("new '{s},{s}' file offset 0x{x} to 0x{x}", .{ |
| 3526 | | sect.segName(), |
| 3527 | | sect.sectName(), |
| 3528 | | new_offset, |
| 3529 | | new_offset + existing_size, |
| 3530 | | }); |
| 3528 | const seg_id = self.sections.items(.segment_id)[sect_index]; |
| 3529 | const seg = &self.segments.items[seg_id]; |
| 3530 | seg.fileoff = sect.offset; |
| 3531 | 3531 | |
| 3532 | | try self.copyRangeAllZeroOut(sect.offset, new_offset, existing_size); |
| 3532 | if (!sect.isZerofill()) { |
| 3533 | seg.filesize = needed_size; |
| 3534 | } |
| 3533 | 3535 | |
| 3534 | | sect.offset = @intCast(new_offset); |
| 3535 | | } |
| 3536 | const mem_capacity = self.allocatedSizeVirtual(seg.vmaddr); |
| 3537 | if (needed_size > mem_capacity) { |
| 3538 | var err = try self.addErrorWithNotes(2); |
| 3539 | try err.addMsg(self, "fatal linker error: cannot expand segment seg({d})({s}) in virtual memory", .{ |
| 3540 | seg_id, |
| 3541 | seg.segName(), |
| 3542 | }); |
| 3543 | try err.addNote(self, "TODO: emit relocations to memory locations in self-hosted backends", .{}); |
| 3544 | try err.addNote(self, "as a workaround, try increasing pre-allocated virtual memory of each segment", .{}); |
| 3536 | 3545 | } |
| 3537 | 3546 | |
| 3538 | | sect.size = needed_size; |
| 3547 | seg.vmsize = needed_size; |
| 3548 | } |
| 3539 | 3549 | |
| 3540 | | if (!self.base.isRelocatable()) { |
| 3541 | | const seg_id = self.sections.items(.segment_id)[sect_index]; |
| 3542 | | const seg = &self.segments.items[seg_id]; |
| 3543 | | seg.fileoff = sect.offset; |
| 3550 | fn growSectionRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !void { |
| 3551 | const sect = &self.sections.items(.header)[sect_index]; |
| 3544 | 3552 | |
| 3545 | | if (!sect.isZerofill()) { |
| 3546 | | seg.filesize = needed_size; |
| 3547 | | } |
| 3553 | if (needed_size > self.allocatedSize(sect.offset) and !sect.isZerofill()) { |
| 3554 | const existing_size = sect.size; |
| 3555 | sect.size = 0; |
| 3548 | 3556 | |
| 3549 | | const mem_capacity = self.allocatedSizeVirtual(seg.vmaddr); |
| 3550 | | if (needed_size > mem_capacity) { |
| 3551 | | var err = try self.addErrorWithNotes(2); |
| 3552 | | try err.addMsg(self, "fatal linker error: cannot expand segment seg({d})({s}) in virtual memory", .{ |
| 3553 | | seg_id, |
| 3554 | | seg.segName(), |
| 3555 | | }); |
| 3556 | | try err.addNote(self, "TODO: emit relocations to memory locations in self-hosted backends", .{}); |
| 3557 | | try err.addNote(self, "as a workaround, try increasing pre-allocated virtual memory of each segment", .{}); |
| 3558 | | } |
| 3557 | // Must move the entire section. |
| 3558 | const alignment = try math.powi(u32, 2, sect.@"align"); |
| 3559 | const new_offset = self.findFreeSpace(needed_size, alignment); |
| 3560 | const new_addr = self.findFreeSpaceVirtual(needed_size, alignment); |
| 3561 | |
| 3562 | log.debug("new '{s},{s}' file offset 0x{x} to 0x{x} (0x{x} - 0x{x})", .{ |
| 3563 | sect.segName(), |
| 3564 | sect.sectName(), |
| 3565 | new_offset, |
| 3566 | new_offset + existing_size, |
| 3567 | new_addr, |
| 3568 | new_addr + existing_size, |
| 3569 | }); |
| 3570 | |
| 3571 | try self.copyRangeAll(sect.offset, new_offset, existing_size); |
| 3559 | 3572 | |
| 3560 | | seg.vmsize = needed_size; |
| 3573 | sect.offset = @intCast(new_offset); |
| 3574 | sect.addr = new_addr; |
| 3561 | 3575 | } |
| 3576 | |
| 3577 | sect.size = needed_size; |
| 3562 | 3578 | } |
| 3563 | 3579 | |
| 3564 | 3580 | pub fn getTarget(self: MachO) std.Target { |