authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-02-02 20:26:50+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-02-03 09:28:19+01:00
logdc222c9ba5865176fde9607d10dd5dca69654894
tree3c5dbf70a9d27020e8608865092ec540a7f5762e
parentc5155170b2f91ba4cba2ac356ffa749c1f30f621

macho: use findFreeSpace for all sections


2 files changed, 48 insertions(+), 48 deletions(-)

src/link/MachO.zig+42-2
......@@ -3275,6 +3275,34 @@ fn detectAllocCollision(self: *MachO, start: u64, size: u64) ?u64 {
32753275 return null;
32763276}
32773277
3278fn detectAllocCollisionVirtual(self: *MachO, start: u64, size: u64) ?u64 {
3279 // Conservatively commit one page size as reserved space for the headers as we
3280 // expect it to grow and everything else be moved in flush anyhow.
3281 const header_size = self.getPageSize();
3282 if (start < header_size)
3283 return header_size;
3284
3285 const end = start + padToIdeal(size);
3286
3287 for (self.sections.items(.header)) |header| {
3288 const increased_size = padToIdeal(header.size);
3289 const test_end = header.addr + increased_size;
3290 if (end > header.addr and start < test_end) {
3291 return test_end;
3292 }
3293 }
3294
3295 for (self.segments.items) |seg| {
3296 const increased_size = padToIdeal(seg.vmsize);
3297 const test_end = seg.vmaddr +| increased_size;
3298 if (end > seg.vmaddr and start < test_end) {
3299 return test_end;
3300 }
3301 }
3302
3303 return null;
3304}
3305
32783306fn allocatedSize(self: *MachO, start: u64) u64 {
32793307 if (start == 0) return 0;
32803308 var min_pos: u64 = std.math.maxInt(u64);
......@@ -3307,6 +3335,14 @@ pub fn findFreeSpace(self: *MachO, object_size: u64, min_alignment: u32) u64 {
33073335 return start;
33083336}
33093337
3338pub fn findFreeSpaceVirtual(self: *MachO, object_size: u64, min_alignment: u32) u64 {
3339 var start: u64 = 0;
3340 while (self.detectAllocCollisionVirtual(start, object_size)) |item_end| {
3341 start = mem.alignForward(u64, item_end, min_alignment);
3342 }
3343 return start;
3344}
3345
33103346pub fn copyRangeAll(self: *MachO, old_offset: u64, new_offset: u64, size: u64) !void {
33113347 const file = self.base.file.?;
33123348 const amt = try file.copyRangeAll(old_offset, file, new_offset, size);
......@@ -3411,7 +3447,11 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void {
34113447 fn allocSect(macho_file: *MachO, sect_id: u8, size: u64) !void {
34123448 const sect = &macho_file.sections.items(.header)[sect_id];
34133449 const alignment = try math.powi(u32, 2, sect.@"align");
3414 sect.offset = @intCast(macho_file.findFreeSpace(size, alignment));
3450 if (!sect.isZerofill()) {
3451 sect.offset = math.cast(u32, macho_file.findFreeSpace(size, alignment)) orelse
3452 return error.Overflow;
3453 }
3454 sect.addr = macho_file.findFreeSpaceVirtual(size, alignment);
34153455 sect.size = size;
34163456 }
34173457 }.allocSect;
......@@ -3462,7 +3502,7 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void {
34623502 .flags = macho.S_ZEROFILL,
34633503 });
34643504 if (self.base.isRelocatable()) {
3465 self.sections.items(.header)[self.zig_bss_sect_index.?].size = 1024;
3505 try allocSect(self, self.zig_bss_sect_index.?, 1024);
34663506 } else {
34673507 appendSect(self, self.zig_bss_sect_index.?, self.zig_bss_seg_index.?);
34683508 }
src/link/MachO/relocatable.zig+6-46
......@@ -59,8 +59,7 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u
5959 try calcSectionSizes(macho_file);
6060
6161 try createSegment(macho_file);
62 try allocateSectionsVM(macho_file);
63 try allocateSectionsFile(macho_file);
62 try allocateSections(macho_file);
6463 allocateSegment(macho_file);
6564 macho_file.allocateAtoms();
6665
......@@ -224,58 +223,20 @@ fn calcCompactUnwindSize(macho_file: *MachO, sect_index: u8) void {
224223 sect.@"align" = 3;
225224}
226225
227fn allocateSectionsVM(macho_file: *MachO) !void {
228 var vmaddr: u64 = 0;
229 const slice = macho_file.sections.slice();
230
231 for (slice.items(.header)) |*header| {
232 const alignment = try math.powi(u32, 2, header.@"align");
233 vmaddr = mem.alignForward(u64, vmaddr, alignment);
234 header.addr = vmaddr;
235 vmaddr += header.size;
236 }
237}
238
239fn allocateSectionsFile(macho_file: *MachO) !void {
240 var fileoff = load_commands.calcLoadCommandsSizeObject(macho_file) + @sizeOf(macho.mach_header_64);
226fn allocateSections(macho_file: *MachO) !void {
241227 const slice = macho_file.sections.slice();
242228
243229 const last_index = for (slice.items(.header), 0..) |header, i| {
244230 if (mem.indexOf(u8, header.segName(), "ZIG")) |_| break i;
245231 } else slice.items(.header).len;
246232
247 // TODO: I actually think for relocatable we can just use findFreeSpace
248 // all the way since there is a single segment involved anyhow.
249233 for (slice.items(.header)[0..last_index]) |*header| {
250 if (header.isZerofill()) continue;
251234 const alignment = try math.powi(u32, 2, header.@"align");
252 fileoff = mem.alignForward(u32, fileoff, alignment);
253 header.offset = fileoff;
254 fileoff += @intCast(header.size);
255 }
256
257 for (slice.items(.header)[last_index..]) |*header| {
258 if (header.isZerofill()) continue;
259 if (header.offset < fileoff) {
260 const existing_size = header.size;
261 header.size = 0;
262
263 // Must move the entire section.
264 const alignment = try math.powi(u32, 2, header.@"align");
265 const new_offset = macho_file.findFreeSpace(existing_size, alignment);
266
267 log.debug("new '{s},{s}' file offset 0x{x} to 0x{x}", .{
268 header.segName(),
269 header.sectName(),
270 new_offset,
271 new_offset + existing_size,
272 });
273
274 try macho_file.copyRangeAll(header.offset, new_offset, existing_size);
275
276 header.offset = @intCast(new_offset);
277 header.size = existing_size;
235 if (!header.isZerofill()) {
236 header.offset = math.cast(u32, macho_file.findFreeSpace(header.size, alignment)) orelse
237 return error.Overflow;
278238 }
239 header.addr = macho_file.findFreeSpaceVirtual(header.size, alignment);
279240 }
280241}
281242
......@@ -308,7 +269,6 @@ fn allocateSegment(macho_file: *MachO) void {
308269 if (!header.isZerofill()) {
309270 fileoff = @max(fileoff, header.offset + header.size);
310271 }
311 std.debug.print("fileoff={x},vmaddr={x}\n", .{ fileoff, vmaddr });
312272 }
313273
314274 seg.vmsize = vmaddr - seg.vmaddr;