authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-02-08 13:22:48+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-02-08 13:22:48+01:00
logdcb7f5791a206d7713bea153a8d94f22dfb155a9
treee4b0e3196d2d1a50ed990d6b05c75bd6e8909342
parent102846315c1be4518ce7783717dc1ceb133b66cf

macho: alloc improvement for relocatable


2 files changed, 60 insertions(+), 46 deletions(-)

src/link/MachO.zig+49-37
......@@ -3202,20 +3202,22 @@ fn detectAllocCollision(self: *MachO, start: u64, size: u64) ?u64 {
32023202
32033203 const end = start + padToIdeal(size);
32043204
3205 for (self.sections.items(.header)) |header| {
3206 if (header.isZerofill()) continue;
3207 const increased_size = padToIdeal(header.size);
3208 const test_end = header.offset +| increased_size;
3209 if (end > header.offset and start < test_end) {
3210 return test_end;
3205 if (self.base.isRelocatable()) {
3206 for (self.sections.items(.header)) |header| {
3207 if (header.isZerofill()) continue;
3208 const increased_size = padToIdeal(header.size);
3209 const test_end = header.offset +| increased_size;
3210 if (end > header.offset and start < test_end) {
3211 return test_end;
3212 }
32113213 }
3212 }
3213
3214 for (self.segments.items) |seg| {
3215 const increased_size = padToIdeal(seg.filesize);
3216 const test_end = seg.fileoff +| increased_size;
3217 if (end > seg.fileoff and start < test_end) {
3218 return test_end;
3214 } else {
3215 for (self.segments.items) |seg| {
3216 const increased_size = padToIdeal(seg.filesize);
3217 const test_end = seg.fileoff +| increased_size;
3218 if (end > seg.fileoff and start < test_end) {
3219 return test_end;
3220 }
32193221 }
32203222 }
32213223
......@@ -3223,27 +3225,29 @@ fn detectAllocCollision(self: *MachO, start: u64, size: u64) ?u64 {
32233225}
32243226
32253227fn detectAllocCollisionVirtual(self: *MachO, start: u64, size: u64) ?u64 {
3226 // Conservatively commit one page size as reserved space for the headers as we
3227 // expect it to grow and everything else be moved in flush anyhow.
3228 const header_size = self.getPageSize();
3229 if (start < header_size)
3230 return header_size;
3231
32323228 const end = start + padToIdeal(size);
32333229
3234 for (self.sections.items(.header)) |header| {
3235 const increased_size = padToIdeal(header.size);
3236 const test_end = header.addr +| increased_size;
3237 if (end > header.addr and start < test_end) {
3238 return test_end;
3230 if (self.base.isRelocatable()) {
3231 for (self.sections.items(.header)) |header| {
3232 const increased_size = padToIdeal(header.size);
3233 const test_end = header.addr +| increased_size;
3234 if (end > header.addr and start < test_end) {
3235 return test_end;
3236 }
32393237 }
3240 }
3238 } else {
3239 // Conservatively commit one page size as reserved space for the headers as we
3240 // expect it to grow and everything else be moved in flush anyhow.
3241 const header_size = self.getPageSize();
3242 if (start < header_size)
3243 return header_size;
32413244
3242 for (self.segments.items) |seg| {
3243 const increased_size = padToIdeal(seg.vmsize);
3244 const test_end = seg.vmaddr +| increased_size;
3245 if (end > seg.vmaddr and start < test_end) {
3246 return test_end;
3245 for (self.segments.items) |seg| {
3246 const increased_size = padToIdeal(seg.vmsize);
3247 const test_end = seg.vmaddr +| increased_size;
3248 if (end > seg.vmaddr and start < test_end) {
3249 return test_end;
3250 }
32473251 }
32483252 }
32493253
......@@ -3252,21 +3256,29 @@ fn detectAllocCollisionVirtual(self: *MachO, start: u64, size: u64) ?u64 {
32523256
32533257pub fn allocatedSize(self: *MachO, start: u64) u64 {
32543258 if (start == 0) return 0;
3259
32553260 var min_pos: u64 = std.math.maxInt(u64);
3256 for (self.sections.items(.header)) |header| {
3257 if (header.offset <= start) continue;
3258 if (header.offset < min_pos) min_pos = header.offset;
3259 }
3260 for (self.segments.items) |seg| {
3261 if (seg.fileoff <= start) continue;
3262 if (seg.fileoff < min_pos) min_pos = seg.fileoff;
3261
3262 if (self.base.isRelocatable()) {
3263 for (self.sections.items(.header)) |header| {
3264 if (header.offset <= start) continue;
3265 if (header.offset < min_pos) min_pos = header.offset;
3266 }
3267 } else {
3268 for (self.segments.items) |seg| {
3269 if (seg.fileoff <= start) continue;
3270 if (seg.fileoff < min_pos) min_pos = seg.fileoff;
3271 }
32633272 }
3273
32643274 return min_pos - start;
32653275}
32663276
32673277pub fn allocatedSizeVirtual(self: *MachO, start: u64) u64 {
32683278 if (start == 0) return 0;
3279
32693280 var min_pos: u64 = std.math.maxInt(u64);
3281
32703282 if (self.base.isRelocatable()) {
32713283 for (self.sections.items(.header)) |header| {
32723284 if (header.addr <= start) continue;
src/link/MachO/relocatable.zig+11-9
......@@ -437,18 +437,20 @@ fn calcCompactUnwindSize(macho_file: *MachO, sect_index: u8) void {
437437
438438fn allocateSections(macho_file: *MachO) !void {
439439 const slice = macho_file.sections.slice();
440
441 const last_index = for (0..slice.items(.header).len) |i| {
442 if (macho_file.isZigSection(@intCast(i))) break i;
443 } else slice.items(.header).len;
444
445 for (slice.items(.header)[0..last_index]) |*header| {
440 for (slice.items(.header)) |*header| {
441 const needed_size = header.size;
442 header.size = 0;
446443 const alignment = try math.powi(u32, 2, header.@"align");
447444 if (!header.isZerofill()) {
448 header.offset = math.cast(u32, macho_file.findFreeSpace(header.size, alignment)) orelse
449 return error.Overflow;
445 if (needed_size > macho_file.allocatedSize(header.offset)) {
446 header.offset = math.cast(u32, macho_file.findFreeSpace(needed_size, alignment)) orelse
447 return error.Overflow;
448 }
449 }
450 if (needed_size > macho_file.allocatedSizeVirtual(header.addr)) {
451 header.addr = macho_file.findFreeSpaceVirtual(needed_size, alignment);
450452 }
451 header.addr = macho_file.findFreeSpaceVirtual(header.size, alignment);
453 header.size = needed_size;
452454 }
453455}
454456