macho: use findFreeSpace for all sections
This commit is contained in:
@@ -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.?);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user