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 {...@@ -3493,6 +3493,14 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void {
3493}3493}
34943494
3495pub fn growSection(self: *MachO, sect_index: u8, needed_size: u64) !void {3495pub 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 {
3496 const sect = &self.sections.items(.header)[sect_index];3504 const sect = &self.sections.items(.header)[sect_index];
34973505
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;
35013509
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 });
35073520
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 });
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);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);
35243527
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 });
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);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 }
35373546
3538 sect.size = needed_size;3547 seg.vmsize = needed_size;
3548}
35393549
3540 if (!self.base.isRelocatable()) {3550fn 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;
35443552
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;
35483556
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);
35593572
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}
35633579
3564pub fn getTarget(self: MachO) std.Target {3580pub 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...@@ -26,11 +26,6 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u
26 return;26 return;
27 }27 }
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
34 for (positionals.items) |obj| {29 for (positionals.items) |obj| {
35 macho_file.parsePositional(obj.path, obj.must_link) catch |err| switch (err) {30 macho_file.parsePositional(obj.path, obj.must_link) catch |err| switch (err) {
36 error.MalformedObject,31 error.MalformedObject,