diff options
| author | Jakub Konka <kubkon@jakubkonka.com> | 2024-01-20 17:09:56 +0100 |
|---|---|---|
| committer | Jakub Konka <kubkon@jakubkonka.com> | 2024-01-24 12:34:42 +0100 |
| commit | aef2c91d9f91c89a883c95331fa382692ab5e7c3 (patch) | |
| tree | 7b6bd68189d129fb540796cd2714cf9b80ec04f7 /src | |
| parent | a531ecf9dc104895741c46901989d400ad4e3043 (diff) | |
| download | zig-aef2c91d9f91c89a883c95331fa382692ab5e7c3.tar.gz zig-aef2c91d9f91c89a883c95331fa382692ab5e7c3.zip | |
macho: move incr Zig sections in file if overlap nonincr sections
Diffstat (limited to 'src')
| -rw-r--r-- | src/link/MachO.zig | 66 |
1 files changed, 47 insertions, 19 deletions
diff --git a/src/link/MachO.zig b/src/link/MachO.zig index 9fed435a41..861ca6e206 100644 --- a/src/link/MachO.zig +++ b/src/link/MachO.zig @@ -1923,12 +1923,13 @@ fn getSegmentProt(segname: []const u8) macho.vm_prot_t { return macho.PROT.READ | macho.PROT.WRITE; } -fn getSegmentRank(segname: []const u8) u4 { +fn getSegmentRank(segname: []const u8) u8 { if (mem.eql(u8, segname, "__PAGEZERO")) return 0x0; if (mem.eql(u8, segname, "__TEXT")) return 0x1; if (mem.eql(u8, segname, "__DATA_CONST")) return 0x2; if (mem.eql(u8, segname, "__DATA")) return 0x3; - if (mem.eql(u8, segname, "__LINKEDIT")) return 0x5; + if (mem.indexOf(u8, segname, "ZIG")) |_| return 0xe; + if (mem.eql(u8, segname, "__LINKEDIT")) return 0xf; return 0x4; } @@ -2282,28 +2283,55 @@ fn allocateSections(self: *MachO) !void { var next_seg_id: u8 = if (self.pagezero_seg_index) |index| index + 1 else 0; for (slice.items(.header), slice.items(.segment_id)) |*header, seg_id| { - if (mem.indexOf(u8, header.segName(), "ZIG")) |_| { - vmaddr = header.addr + header.size; - } else { - if (seg_id != next_seg_id) { - vmaddr = mem.alignForward(u64, vmaddr, page_size); - fileoff = mem.alignForward(u32, fileoff, page_size); - } + defer next_seg_id = seg_id; - const alignment = try math.powi(u32, 2, header.@"align"); + if (mem.indexOf(u8, header.segName(), "ZIG")) |_| continue; + if (seg_id != next_seg_id) { + vmaddr = mem.alignForward(u64, vmaddr, page_size); + fileoff = mem.alignForward(u32, fileoff, page_size); + } - vmaddr = mem.alignForward(u64, vmaddr, alignment); - header.addr = vmaddr; - vmaddr += header.size; + const alignment = try math.powi(u32, 2, header.@"align"); - if (!header.isZerofill()) { - fileoff = mem.alignForward(u32, fileoff, alignment); - header.offset = fileoff; - fileoff += @intCast(header.size); - } + vmaddr = mem.alignForward(u64, vmaddr, alignment); + header.addr = vmaddr; + vmaddr += header.size; + + if (!header.isZerofill()) { + fileoff = mem.alignForward(u32, fileoff, alignment); + header.offset = fileoff; + fileoff += @intCast(header.size); } + } - next_seg_id = seg_id; + // TODO iterate over sections again, but consider only zig sections + // and move them if they are allocated in file below page-aligned fileoff + fileoff = mem.alignForward(u32, fileoff, page_size); + for (slice.items(.header), slice.items(.segment_id)) |*header, seg_id| { + if (mem.indexOf(u8, header.segName(), "ZIG") == null) continue; + if (header.isZerofill()) continue; + if (header.offset < fileoff) { + const existing_size = header.size; + header.size = 0; + + // Must move the entire section. + const new_offset = self.findFreeSpace(existing_size, page_size); + + log.debug("new '{s},{s}' file offset 0x{x} to 0x{x}", .{ + header.segName(), + header.sectName(), + new_offset, + new_offset + existing_size, + }); + + const amt = try self.base.file.?.copyRangeAll(header.offset, self.base.file.?, new_offset, existing_size); + // TODO figure out what to about this error condition - how to communicate it up. + if (amt != existing_size) return error.InputOutput; + + header.offset = @intCast(new_offset); + header.size = existing_size; + self.segments.items[seg_id].fileoff = new_offset; + } } } |
