| ... | ... | @@ -613,7 +613,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node |
| 613 | 613 | if (!atom.flags.alive) continue; |
| 614 | 614 | const sect = &self.sections.items(.header)[atom.out_n_sect]; |
| 615 | 615 | if (sect.isZerofill()) continue; |
| 616 | | if (mem.indexOf(u8, sect.segName(), "ZIG") == null) continue; // Non-Zig sections are handled separately |
| 616 | if (!self.isZigSection(atom.out_n_sect)) continue; // Non-Zig sections are handled separately |
| 617 | 617 | if (atom.getRelocs(self).len == 0) continue; |
| 618 | 618 | // TODO: we will resolve and write ZigObject's TLS data twice: |
| 619 | 619 | // once here, and once in writeAtoms |
| ... | ... | @@ -2231,11 +2231,11 @@ fn initSegments(self: *MachO) !void { |
| 2231 | 2231 | log.warn("requested __PAGEZERO size (0x{x}) is not page aligned", .{pagezero_size}); |
| 2232 | 2232 | log.warn(" rounding down to 0x{x}", .{aligned_pagezero_size}); |
| 2233 | 2233 | } |
| 2234 | | _ = try self.addSegment("__PAGEZERO", .{ .vmsize = aligned_pagezero_size }); |
| 2234 | self.pagezero_seg_index = try self.addSegment("__PAGEZERO", .{ .vmsize = aligned_pagezero_size }); |
| 2235 | 2235 | } |
| 2236 | 2236 | |
| 2237 | 2237 | // __TEXT segment is non-optional |
| 2238 | | _ = try self.addSegment("__TEXT", .{ .prot = getSegmentProt("__TEXT") }); |
| 2238 | self.text_seg_index = try self.addSegment("__TEXT", .{ .prot = getSegmentProt("__TEXT") }); |
| 2239 | 2239 | |
| 2240 | 2240 | // Next, create segments required by sections |
| 2241 | 2241 | for (slice.items(.header)) |header| { |
| ... | ... | @@ -2247,15 +2247,57 @@ fn initSegments(self: *MachO) !void { |
| 2247 | 2247 | } |
| 2248 | 2248 | |
| 2249 | 2249 | // Add __LINKEDIT |
| 2250 | | _ = try self.addSegment("__LINKEDIT", .{ .prot = getSegmentProt("__LINKEDIT") }); |
| 2250 | self.linkedit_seg_index = try self.addSegment("__LINKEDIT", .{ .prot = getSegmentProt("__LINKEDIT") }); |
| 2251 | 2251 | |
| 2252 | 2252 | // Sort segments |
| 2253 | | const sortFn = struct { |
| 2254 | | fn sortFn(ctx: void, lhs: macho.segment_command_64, rhs: macho.segment_command_64) bool { |
| 2255 | | return segmentLessThan(ctx, lhs.segName(), rhs.segName()); |
| 2253 | const Entry = struct { |
| 2254 | index: u8, |
| 2255 | |
| 2256 | pub fn lessThan(macho_file: *MachO, lhs: @This(), rhs: @This()) bool { |
| 2257 | return segmentLessThan( |
| 2258 | {}, |
| 2259 | macho_file.segments.items[lhs.index].segName(), |
| 2260 | macho_file.segments.items[rhs.index].segName(), |
| 2261 | ); |
| 2256 | 2262 | } |
| 2257 | | }.sortFn; |
| 2258 | | mem.sort(macho.segment_command_64, self.segments.items, {}, sortFn); |
| 2263 | }; |
| 2264 | |
| 2265 | var entries = try std.ArrayList(Entry).initCapacity(gpa, self.segments.items.len); |
| 2266 | defer entries.deinit(); |
| 2267 | for (0..self.segments.items.len) |index| { |
| 2268 | entries.appendAssumeCapacity(.{ .index = @intCast(index) }); |
| 2269 | } |
| 2270 | |
| 2271 | mem.sort(Entry, entries.items, self, Entry.lessThan); |
| 2272 | |
| 2273 | const backlinks = try gpa.alloc(u8, entries.items.len); |
| 2274 | defer gpa.free(backlinks); |
| 2275 | for (entries.items, 0..) |entry, i| { |
| 2276 | backlinks[entry.index] = @intCast(i); |
| 2277 | } |
| 2278 | |
| 2279 | const segments = try self.segments.toOwnedSlice(gpa); |
| 2280 | defer gpa.free(segments); |
| 2281 | |
| 2282 | try self.segments.ensureTotalCapacityPrecise(gpa, segments.len); |
| 2283 | for (entries.items) |sorted| { |
| 2284 | self.segments.appendAssumeCapacity(segments[sorted.index]); |
| 2285 | } |
| 2286 | |
| 2287 | for (&[_]*?u8{ |
| 2288 | &self.pagezero_seg_index, |
| 2289 | &self.text_seg_index, |
| 2290 | &self.linkedit_seg_index, |
| 2291 | &self.zig_text_seg_index, |
| 2292 | &self.zig_got_seg_index, |
| 2293 | &self.zig_const_seg_index, |
| 2294 | &self.zig_data_seg_index, |
| 2295 | &self.zig_bss_seg_index, |
| 2296 | }) |maybe_index| { |
| 2297 | if (maybe_index.*) |*index| { |
| 2298 | index.* = backlinks[index.*]; |
| 2299 | } |
| 2300 | } |
| 2259 | 2301 | |
| 2260 | 2302 | // Attach sections to segments |
| 2261 | 2303 | for (slice.items(.header), slice.items(.segment_id)) |header, *seg_id| { |
| ... | ... | @@ -2276,15 +2318,6 @@ fn initSegments(self: *MachO) !void { |
| 2276 | 2318 | segment.nsects += 1; |
| 2277 | 2319 | seg_id.* = segment_id; |
| 2278 | 2320 | } |
| 2279 | | |
| 2280 | | self.pagezero_seg_index = self.getSegmentByName("__PAGEZERO"); |
| 2281 | | self.text_seg_index = self.getSegmentByName("__TEXT").?; |
| 2282 | | self.linkedit_seg_index = self.getSegmentByName("__LINKEDIT").?; |
| 2283 | | self.zig_text_seg_index = self.getSegmentByName("__TEXT_ZIG"); |
| 2284 | | self.zig_got_seg_index = self.getSegmentByName("__GOT_ZIG"); |
| 2285 | | self.zig_const_seg_index = self.getSegmentByName("__CONST_ZIG"); |
| 2286 | | self.zig_data_seg_index = self.getSegmentByName("__DATA_ZIG"); |
| 2287 | | self.zig_bss_seg_index = self.getSegmentByName("__BSS_ZIG"); |
| 2288 | 2321 | } |
| 2289 | 2322 | |
| 2290 | 2323 | fn allocateSections(self: *MachO) !void { |
| ... | ... | @@ -2299,8 +2332,8 @@ fn allocateSections(self: *MachO) !void { |
| 2299 | 2332 | |
| 2300 | 2333 | const page_size = self.getPageSize(); |
| 2301 | 2334 | const slice = self.sections.slice(); |
| 2302 | | const last_index = for (slice.items(.header), 0..) |header, i| { |
| 2303 | | if (mem.indexOf(u8, header.segName(), "ZIG")) |_| break i; |
| 2335 | const last_index = for (0..slice.items(.header).len) |i| { |
| 2336 | if (self.isZigSection(@intCast(i))) break i; |
| 2304 | 2337 | } else slice.items(.header).len; |
| 2305 | 2338 | |
| 2306 | 2339 | for (slice.items(.header)[0..last_index], slice.items(.segment_id)[0..last_index]) |*header, curr_seg_id| { |
| ... | ... | @@ -2353,8 +2386,8 @@ fn allocateSections(self: *MachO) !void { |
| 2353 | 2386 | /// We allocate segments in a separate step to also consider segments that have no sections. |
| 2354 | 2387 | fn allocateSegments(self: *MachO) void { |
| 2355 | 2388 | const first_index = if (self.pagezero_seg_index) |index| index + 1 else 0; |
| 2356 | | const last_index = for (self.segments.items, 0..) |seg, i| { |
| 2357 | | if (mem.indexOf(u8, seg.segName(), "ZIG")) |_| break i; |
| 2389 | const last_index = for (0..self.segments.items.len) |i| { |
| 2390 | if (self.isZigSegment(@intCast(i))) break i; |
| 2358 | 2391 | } else self.segments.items.len; |
| 2359 | 2392 | |
| 2360 | 2393 | var vmaddr: u64 = if (self.pagezero_seg_index) |index| |
| ... | ... | @@ -3622,6 +3655,36 @@ inline fn requiresThunks(self: MachO) bool { |
| 3622 | 3655 | return self.getTarget().cpu.arch == .aarch64; |
| 3623 | 3656 | } |
| 3624 | 3657 | |
| 3658 | pub fn isZigSegment(self: MachO, seg_id: u8) bool { |
| 3659 | inline for (&[_]?u8{ |
| 3660 | self.zig_text_seg_index, |
| 3661 | self.zig_got_seg_index, |
| 3662 | self.zig_const_seg_index, |
| 3663 | self.zig_data_seg_index, |
| 3664 | self.zig_bss_seg_index, |
| 3665 | }) |maybe_index| { |
| 3666 | if (maybe_index) |index| { |
| 3667 | if (index == seg_id) return true; |
| 3668 | } |
| 3669 | } |
| 3670 | return false; |
| 3671 | } |
| 3672 | |
| 3673 | pub fn isZigSection(self: MachO, sect_id: u8) bool { |
| 3674 | inline for (&[_]?u8{ |
| 3675 | self.zig_text_sect_index, |
| 3676 | self.zig_got_sect_index, |
| 3677 | self.zig_const_sect_index, |
| 3678 | self.zig_data_sect_index, |
| 3679 | self.zig_bss_sect_index, |
| 3680 | }) |maybe_index| { |
| 3681 | if (maybe_index) |index| { |
| 3682 | if (index == sect_id) return true; |
| 3683 | } |
| 3684 | } |
| 3685 | return false; |
| 3686 | } |
| 3687 | |
| 3625 | 3688 | pub fn addSegment(self: *MachO, name: []const u8, opts: struct { |
| 3626 | 3689 | vmaddr: u64 = 0, |
| 3627 | 3690 | vmsize: u64 = 0, |