| author | |
| committer | |
| log | dc222c9ba5865176fde9607d10dd5dca69654894 |
| tree | 3c5dbf70a9d27020e8608865092ec540a7f5762e |
| parent | c5155170b2f91ba4cba2ac356ffa749c1f30f621 |
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 { | ... | @@ -3275,6 +3275,34 @@ fn detectAllocCollision(self: *MachO, start: u64, size: u64) ?u64 { |
| 3275 | return null; | 3275 | return null; |
| 3276 | } | 3276 | } |
| 3277 | 3277 | ||
| 3278 | fn 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 | |||
| 3278 | fn allocatedSize(self: *MachO, start: u64) u64 { | 3306 | fn allocatedSize(self: *MachO, start: u64) u64 { |
| 3279 | if (start == 0) return 0; | 3307 | if (start == 0) return 0; |
| 3280 | var min_pos: u64 = std.math.maxInt(u64); | 3308 | var min_pos: u64 = std.math.maxInt(u64); |
| ... | @@ -3307,6 +3335,14 @@ pub fn findFreeSpace(self: *MachO, object_size: u64, min_alignment: u32) u64 { | ... | @@ -3307,6 +3335,14 @@ pub fn findFreeSpace(self: *MachO, object_size: u64, min_alignment: u32) u64 { |
| 3307 | return start; | 3335 | return start; |
| 3308 | } | 3336 | } |
| 3309 | 3337 | ||
| 3338 | pub 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 | |||
| 3310 | pub fn copyRangeAll(self: *MachO, old_offset: u64, new_offset: u64, size: u64) !void { | 3346 | pub fn copyRangeAll(self: *MachO, old_offset: u64, new_offset: u64, size: u64) !void { |
| 3311 | const file = self.base.file.?; | 3347 | const file = self.base.file.?; |
| 3312 | const amt = try file.copyRangeAll(old_offset, file, new_offset, size); | 3348 | const amt = try file.copyRangeAll(old_offset, file, new_offset, size); |
| ... | @@ -3411,7 +3447,11 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void { | ... | @@ -3411,7 +3447,11 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void { |
| 3411 | fn allocSect(macho_file: *MachO, sect_id: u8, size: u64) !void { | 3447 | fn allocSect(macho_file: *MachO, sect_id: u8, size: u64) !void { |
| 3412 | const sect = &macho_file.sections.items(.header)[sect_id]; | 3448 | const sect = &macho_file.sections.items(.header)[sect_id]; |
| 3413 | const alignment = try math.powi(u32, 2, sect.@"align"); | 3449 | 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); | ||
| 3415 | sect.size = size; | 3455 | sect.size = size; |
| 3416 | } | 3456 | } |
| 3417 | }.allocSect; | 3457 | }.allocSect; |
| ... | @@ -3462,7 +3502,7 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void { | ... | @@ -3462,7 +3502,7 @@ fn initMetadata(self: *MachO, options: InitMetadataOptions) !void { |
| 3462 | .flags = macho.S_ZEROFILL, | 3502 | .flags = macho.S_ZEROFILL, |
| 3463 | }); | 3503 | }); |
| 3464 | if (self.base.isRelocatable()) { | 3504 | 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); |
| 3466 | } else { | 3506 | } else { |
| 3467 | appendSect(self, self.zig_bss_sect_index.?, self.zig_bss_seg_index.?); | 3507 | appendSect(self, self.zig_bss_sect_index.?, self.zig_bss_seg_index.?); |
| 3468 | } | 3508 | } |
src/link/MachO/relocatable.zig+6-46| ... | @@ -59,8 +59,7 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u | ... | @@ -59,8 +59,7 @@ pub fn flush(macho_file: *MachO, comp: *Compilation, module_obj_path: ?[]const u |
| 59 | try calcSectionSizes(macho_file); | 59 | try calcSectionSizes(macho_file); |
| 60 | 60 | ||
| 61 | try createSegment(macho_file); | 61 | try createSegment(macho_file); |
| 62 | try allocateSectionsVM(macho_file); | 62 | try allocateSections(macho_file); |
| 63 | try allocateSectionsFile(macho_file); | ||
| 64 | allocateSegment(macho_file); | 63 | allocateSegment(macho_file); |
| 65 | macho_file.allocateAtoms(); | 64 | macho_file.allocateAtoms(); |
| 66 | 65 | ||
| ... | @@ -224,58 +223,20 @@ fn calcCompactUnwindSize(macho_file: *MachO, sect_index: u8) void { | ... | @@ -224,58 +223,20 @@ fn calcCompactUnwindSize(macho_file: *MachO, sect_index: u8) void { |
| 224 | sect.@"align" = 3; | 223 | sect.@"align" = 3; |
| 225 | } | 224 | } |
| 226 | 225 | ||
| 227 | fn allocateSectionsVM(macho_file: *MachO) !void { | 226 | fn allocateSections(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 | |||
| 239 | fn allocateSectionsFile(macho_file: *MachO) !void { | ||
| 240 | var fileoff = load_commands.calcLoadCommandsSizeObject(macho_file) + @sizeOf(macho.mach_header_64); | ||
| 241 | const slice = macho_file.sections.slice(); | 227 | const slice = macho_file.sections.slice(); |
| 242 | 228 | ||
| 243 | const last_index = for (slice.items(.header), 0..) |header, i| { | 229 | const last_index = for (slice.items(.header), 0..) |header, i| { |
| 244 | if (mem.indexOf(u8, header.segName(), "ZIG")) |_| break i; | 230 | if (mem.indexOf(u8, header.segName(), "ZIG")) |_| break i; |
| 245 | } else slice.items(.header).len; | 231 | } else slice.items(.header).len; |
| 246 | 232 | ||
| 247 | // TODO: I actually think for relocatable we can just use findFreeSpace | ||
| 248 | // all the way since there is a single segment involved anyhow. | ||
| 249 | for (slice.items(.header)[0..last_index]) |*header| { | 233 | for (slice.items(.header)[0..last_index]) |*header| { |
| 250 | if (header.isZerofill()) continue; | ||
| 251 | const alignment = try math.powi(u32, 2, header.@"align"); | 234 | const alignment = try math.powi(u32, 2, header.@"align"); |
| 252 | fileoff = mem.alignForward(u32, fileoff, alignment); | 235 | if (!header.isZerofill()) { |
| 253 | header.offset = fileoff; | 236 | header.offset = math.cast(u32, macho_file.findFreeSpace(header.size, alignment)) orelse |
| 254 | fileoff += @intCast(header.size); | 237 | return error.Overflow; |
| 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; | ||
| 278 | } | 238 | } |
| 239 | header.addr = macho_file.findFreeSpaceVirtual(header.size, alignment); | ||
| 279 | } | 240 | } |
| 280 | } | 241 | } |
| 281 | 242 | ||
| ... | @@ -308,7 +269,6 @@ fn allocateSegment(macho_file: *MachO) void { | ... | @@ -308,7 +269,6 @@ fn allocateSegment(macho_file: *MachO) void { |
| 308 | if (!header.isZerofill()) { | 269 | if (!header.isZerofill()) { |
| 309 | fileoff = @max(fileoff, header.offset + header.size); | 270 | fileoff = @max(fileoff, header.offset + header.size); |
| 310 | } | 271 | } |
| 311 | std.debug.print("fileoff={x},vmaddr={x}\n", .{ fileoff, vmaddr }); | ||
| 312 | } | 272 | } |
| 313 | 273 | ||
| 314 | seg.vmsize = vmaddr - seg.vmaddr; | 274 | seg.vmsize = vmaddr - seg.vmaddr; |