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