authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-02-03 15:55:32+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-02-03 15:55:32+01:00
log1ad545c97bbfed8e29f0312a794731638377705a
tree6df73cd79bfd0e1746556c57ccdef78b86b1b0ad
parent0a0f90f949942b19950455647bc955b369407dd4

macho: refactor growSection logic; remove -r limitation for ZigObject


2 files changed, 62 insertions(+), 51 deletions(-)

src/link/MachO.zig+62-46
......@@ -3493,6 +3493,14 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void {
34933493}
34943494
34953495pub 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
3503fn growSectionNonRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !void {
34963504 const sect = &self.sections.items(.header)[sect_index];
34973505
34983506 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 {
35003508 sect.size = 0;
35013509
35023510 // 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 });
35073520
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);
35163522
3517 try self.copyRangeAll(sect.offset, new_offset, existing_size);
3523 sect.offset = @intCast(new_offset);
3524 }
35183525
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;
35243527
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;
35313531
3532 try self.copyRangeAllZeroOut(sect.offset, new_offset, existing_size);
3532 if (!sect.isZerofill()) {
3533 seg.filesize = needed_size;
3534 }
35333535
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", .{});
35363545 }
35373546
3538 sect.size = needed_size;
3547 seg.vmsize = needed_size;
3548}
35393549
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;
3550fn growSectionRelocatable(self: *MachO, sect_index: u8, needed_size: u64) !void {
3551 const sect = &self.sections.items(.header)[sect_index];
35443552
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;
35483556
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);
35593572
3560 seg.vmsize = needed_size;
3573 sect.offset = @intCast(new_offset);
3574 sect.addr = new_addr;
35613575 }
3576
3577 sect.size = needed_size;
35623578}
35633579
35643580pub fn getTarget(self: MachO) std.Target {
src/link/MachO/relocatable.zig-5
......@@ -26,11 +26,6 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u
2626 return;
2727 }
2828
29 if (macho_file.getZigObject() != null and positionals.items.len > 0) {
30 try macho_file.reportUnexpectedError("TODO: build-obj for ZigObject and input object files", .{});
31 return error.FlushFailure;
32 }
33
3429 for (positionals.items) |obj| {
3530 macho_file.parsePositional(obj.path, obj.must_link) catch |err| switch (err) {
3631 error.MalformedObject,