authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-01-20 17:09:56+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2024-01-24 12:34:42+01:00
logaef2c91d9f91c89a883c95331fa382692ab5e7c3
tree7b6bd68189d129fb540796cd2714cf9b80ec04f7
parenta531ecf9dc104895741c46901989d400ad4e3043

macho: move incr Zig sections in file if overlap nonincr sections


1 files changed, 47 insertions(+), 19 deletions(-)

src/link/MachO.zig+47-19
...@@ -1923,12 +1923,13 @@ fn getSegmentProt(segname: []const u8) macho.vm_prot_t {...@@ -1923,12 +1923,13 @@ fn getSegmentProt(segname: []const u8) macho.vm_prot_t {
1923 return macho.PROT.READ | macho.PROT.WRITE;1923 return macho.PROT.READ | macho.PROT.WRITE;
1924}1924}
19251925
1926fn getSegmentRank(segname: []const u8) u4 {1926fn getSegmentRank(segname: []const u8) u8 {
1927 if (mem.eql(u8, segname, "__PAGEZERO")) return 0x0;1927 if (mem.eql(u8, segname, "__PAGEZERO")) return 0x0;
1928 if (mem.eql(u8, segname, "__TEXT")) return 0x1;1928 if (mem.eql(u8, segname, "__TEXT")) return 0x1;
1929 if (mem.eql(u8, segname, "__DATA_CONST")) return 0x2;1929 if (mem.eql(u8, segname, "__DATA_CONST")) return 0x2;
1930 if (mem.eql(u8, segname, "__DATA")) return 0x3;1930 if (mem.eql(u8, segname, "__DATA")) return 0x3;
1931 if (mem.eql(u8, segname, "__LINKEDIT")) return 0x5;1931 if (mem.indexOf(u8, segname, "ZIG")) |_| return 0xe;
1932 if (mem.eql(u8, segname, "__LINKEDIT")) return 0xf;
1932 return 0x4;1933 return 0x4;
1933}1934}
19341935
...@@ -2282,28 +2283,55 @@ fn allocateSections(self: *MachO) !void {...@@ -2282,28 +2283,55 @@ fn allocateSections(self: *MachO) !void {
22822283
2283 var next_seg_id: u8 = if (self.pagezero_seg_index) |index| index + 1 else 0;2284 var next_seg_id: u8 = if (self.pagezero_seg_index) |index| index + 1 else 0;
2284 for (slice.items(.header), slice.items(.segment_id)) |*header, seg_id| {2285 for (slice.items(.header), slice.items(.segment_id)) |*header, seg_id| {
2285 if (mem.indexOf(u8, header.segName(), "ZIG")) |_| {2286 defer next_seg_id = seg_id;
2286 vmaddr = header.addr + header.size;
2287 } else {
2288 if (seg_id != next_seg_id) {
2289 vmaddr = mem.alignForward(u64, vmaddr, page_size);
2290 fileoff = mem.alignForward(u32, fileoff, page_size);
2291 }
22922287
2293 const alignment = try math.powi(u32, 2, header.@"align");2288 if (mem.indexOf(u8, header.segName(), "ZIG")) |_| continue;
2289 if (seg_id != next_seg_id) {
2290 vmaddr = mem.alignForward(u64, vmaddr, page_size);
2291 fileoff = mem.alignForward(u32, fileoff, page_size);
2292 }
22942293
2295 vmaddr = mem.alignForward(u64, vmaddr, alignment);2294 const alignment = try math.powi(u32, 2, header.@"align");
2296 header.addr = vmaddr;
2297 vmaddr += header.size;
22982295
2299 if (!header.isZerofill()) {2296 vmaddr = mem.alignForward(u64, vmaddr, alignment);
2300 fileoff = mem.alignForward(u32, fileoff, alignment);2297 header.addr = vmaddr;
2301 header.offset = fileoff;2298 vmaddr += header.size;
2302 fileoff += @intCast(header.size);2299
2303 }2300 if (!header.isZerofill()) {
2301 fileoff = mem.alignForward(u32, fileoff, alignment);
2302 header.offset = fileoff;
2303 fileoff += @intCast(header.size);
2304 }2304 }
2305 }
23052306
2306 next_seg_id = seg_id;2307 // TODO iterate over sections again, but consider only zig sections
2308 // and move them if they are allocated in file below page-aligned fileoff
2309 fileoff = mem.alignForward(u32, fileoff, page_size);
2310 for (slice.items(.header), slice.items(.segment_id)) |*header, seg_id| {
2311 if (mem.indexOf(u8, header.segName(), "ZIG") == null) continue;
2312 if (header.isZerofill()) continue;
2313 if (header.offset < fileoff) {
2314 const existing_size = header.size;
2315 header.size = 0;
2316
2317 // Must move the entire section.
2318 const new_offset = self.findFreeSpace(existing_size, page_size);
2319
2320 log.debug("new '{s},{s}' file offset 0x{x} to 0x{x}", .{
2321 header.segName(),
2322 header.sectName(),
2323 new_offset,
2324 new_offset + existing_size,
2325 });
2326
2327 const amt = try self.base.file.?.copyRangeAll(header.offset, self.base.file.?, new_offset, existing_size);
2328 // TODO figure out what to about this error condition - how to communicate it up.
2329 if (amt != existing_size) return error.InputOutput;
2330
2331 header.offset = @intCast(new_offset);
2332 header.size = existing_size;
2333 self.segments.items[seg_id].fileoff = new_offset;
2334 }
2307 }2335 }
2308}2336}
23092337