diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2024-02-02 20:26:50 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2024-02-03 09:28:19 +0100 |
| commit | dc222c9ba5865176fde9607d10dd5dca69654894 (patch) | |
| tree | 3c5dbf70a9d27020e8608865092ec540a7f5762e /src | |
| parent | c5155170b2f91ba4cba2ac356ffa749c1f30f621 (diff) | |
| download | zig-dc222c9ba5865176fde9607d10dd5dca69654894.tar.gz zig-dc222c9ba5865176fde9607d10dd5dca69654894.zip | |
macho: use findFreeSpace for all sections
Diffstat (limited to 'src')
| -rw-r--r-- | src/link/MachO.zig | 44 | ||||
| -rw-r--r-- | src/link/MachO/relocatable.zig | 52 |
2 files changed, 48 insertions, 48 deletions
diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 2b2487a70f..a78ebee8cb 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -3275,6 +3275,34 @@ fn detectAllocCollision(self: *MachO, start: u64, size: u64) ?u64 { return null; } +fn detectAllocCollisionVirtual(self: *MachO, start: u64, size: u64) ?u64 { + // Conservatively commit one page size as reserved space for the headers as we + // expect it to grow and everything else be moved in flush anyhow. + const header_size = self.getPageSize(); + if (start < header_size) + return header_size; + + const end = start + padToIdeal(size); + + for (self.sections.items(.header)) |header| { + const increased_size = padToIdeal(header.size); + const test_end = header.addr + increased_size; + if (end > header.addr and start < test_end) { + return test_end; + } + } + + for (self.segments.items) |seg| { + const increased_size = padToIdeal(seg.vmsize); + const test_end = seg.vmaddr +| increased_size; + if (end > seg.vmaddr and start < test_end) { + return test_end; + } + } + + return null; +} + fn allocatedSize(self: *MachO, start: u64) u64 { if (start == 0) return 0; var min_pos: u64 = std.math.maxInt(u64); @@ -3307,6 +3335,14 @@ pub fn findFreeSpace(self: *MachO, object_size: u64, min_alignment: u32) u64 { return start; } +pub fn findFreeSpaceVirtual(self: *MachO, object_size: u64, min_alignment: u32) u64 { + var start: u64 = 0; + while (self.detectAllocCollisionVirtual(start, object_size)) |item_end| { + start = mem.alignForward(u64, item_end, min_alignment); + } + return start; +} + pub fn copyRangeAll(self: *MachO, old_offset: u64, new_offset: u64, size: u64) !void { const file = self.base.file.?; const amt = try file.copyRangeAll(old_offset, file, new_offset, size); @@ -3411,7 +3447,11 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void { fn allocSect(macho_file: *MachO, sect_id: u8, size: u64) !void { const sect = &macho_file.sections.items(.header)[sect_id]; const alignment = try math.powi(u32, 2, sect.@"align"); - sect.offset = @intCast(macho_file.findFreeSpace(size, alignment)); + if (!sect.isZerofill()) { + sect.offset = math.cast(u32, macho_file.findFreeSpace(size, alignment)) orelse + return error.Overflow; + } + sect.addr = macho_file.findFreeSpaceVirtual(size, alignment); sect.size = size; } }.allocSect; @@ -3462,7 +3502,7 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void { .flags = macho.S_ZEROFILL, }); if (self.base.isRelocatable()) { - self.sections.items(.header)[self.zig_bss_sect_index.?].size = 1024; + try allocSect(self, self.zig_bss_sect_index.?, 1024); } else { appendSect(self, self.zig_bss_sect_index.?, self.zig_bss_seg_index.?); } diff --git a/src/link/MachO/relocatable.zig b/src/link/MachO/relocatable.zig index 3751326f4c..474d039829 100644 --- a/src/link/MachO/relocatable.zig +++ b/src/link/MachO/relocatable.zig @@ -59,8 +59,7 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u try calcSectionSizes(macho_file); try createSegment(macho_file); - try allocateSectionsVM(macho_file); - try allocateSectionsFile(macho_file); + try allocateSections(macho_file); allocateSegment(macho_file); macho_file.allocateAtoms(); @@ -224,58 +223,20 @@ fn calcCompactUnwindSize(macho_file: *MachO, sect_index: u8) void { sect.@"align" = 3; } -fn allocateSectionsVM(macho_file: *MachO) !void { - var vmaddr: u64 = 0; - const slice = macho_file.sections.slice(); - - for (slice.items(.header)) |*header| { - const alignment = try math.powi(u32, 2, header.@"align"); - vmaddr = mem.alignForward(u64, vmaddr, alignment); - header.addr = vmaddr; - vmaddr += header.size; - } -} - -fn allocateSectionsFile(macho_file: *MachO) !void { - var fileoff = load_commands.calcLoadCommandsSizeObject(macho_file) + @sizeOf(macho.mach_header_64); +fn allocateSections(macho_file: *MachO) !void { const slice = macho_file.sections.slice(); const last_index = for (slice.items(.header), 0..) |header, i| { if (mem.indexOf(u8, header.segName(), "ZIG")) |_| break i; } else slice.items(.header).len; - // TODO: I actually think for relocatable we can just use findFreeSpace - // all the way since there is a single segment involved anyhow. for (slice.items(.header)[0..last_index]) |*header| { - if (header.isZerofill()) continue; const alignment = try math.powi(u32, 2, header.@"align"); - fileoff = mem.alignForward(u32, fileoff, alignment); - header.offset = fileoff; - fileoff += @intCast(header.size); - } - - for (slice.items(.header)[last_index..]) |*header| { - if (header.isZerofill()) continue; - if (header.offset < fileoff) { - const existing_size = header.size; - header.size = 0; - - // Must move the entire section. - const alignment = try math.powi(u32, 2, header.@"align"); - const new_offset = macho_file.findFreeSpace(existing_size, alignment); - - log.debug("new '{s},{s}' file offset 0x{x} to 0x{x}", .{ - header.segName(), - header.sectName(), - new_offset, - new_offset + existing_size, - }); - - try macho_file.copyRangeAll(header.offset, new_offset, existing_size); - - header.offset = @intCast(new_offset); - header.size = existing_size; + if (!header.isZerofill()) { + header.offset = math.cast(u32, macho_file.findFreeSpace(header.size, alignment)) orelse + return error.Overflow; } + header.addr = macho_file.findFreeSpaceVirtual(header.size, alignment); } } @@ -308,7 +269,6 @@ fn allocateSegment(macho_file: *MachO) void { if (!header.isZerofill()) { fileoff = @max(fileoff, header.offset + header.size); } - std.debug.print("fileoff={x},vmaddr={x}\n", .{ fileoff, vmaddr }); } seg.vmsize = vmaddr - seg.vmaddr; |
