| ... | @@ -613,7 +613,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node | ... | @@ -613,7 +613,7 @@ pub fn flushModule(self: *MachO, arena: Allocator, prog_node: *std.Progress.Node |
| 613 | if (!atom.flags.alive) continue; | 613 | if (!atom.flags.alive) continue; |
| 614 | const sect = &self.sections.items(.header)[atom.out_n_sect]; | 614 | const sect = &self.sections.items(.header)[atom.out_n_sect]; |
| 615 | if (sect.isZerofill()) continue; | 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 | if (atom.getRelocs(self).len == 0) continue; | 617 | if (atom.getRelocs(self).len == 0) continue; |
| 618 | // TODO: we will resolve and write ZigObject's TLS data twice: | 618 | // TODO: we will resolve and write ZigObject's TLS data twice: |
| 619 | // once here, and once in writeAtoms | 619 | // once here, and once in writeAtoms |
| ... | @@ -2231,11 +2231,11 @@ fn initSegments(self: *MachO) !void { | ... | @@ -2231,11 +2231,11 @@ fn initSegments(self: *MachO) !void { |
| 2231 | log.warn("requested __PAGEZERO size (0x{x}) is not page aligned", .{pagezero_size}); | 2231 | log.warn("requested __PAGEZERO size (0x{x}) is not page aligned", .{pagezero_size}); |
| 2232 | log.warn(" rounding down to 0x{x}", .{aligned_pagezero_size}); | 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 | // __TEXT segment is non-optional | 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 | // Next, create segments required by sections | 2240 | // Next, create segments required by sections |
| 2241 | for (slice.items(.header)) |header| { | 2241 | for (slice.items(.header)) |header| { |
| ... | @@ -2247,15 +2247,57 @@ fn initSegments(self: *MachO) !void { | ... | @@ -2247,15 +2247,57 @@ fn initSegments(self: *MachO) !void { |
| 2247 | } | 2247 | } |
| 2248 | | 2248 | |
| 2249 | // Add __LINKEDIT | 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 | // Sort segments | 2252 | // Sort segments |
| 2253 | const sortFn = struct { | 2253 | const Entry = struct { |
| 2254 | fn sortFn(ctx: void, lhs: macho.segment_command_64, rhs: macho.segment_command_64) bool { | 2254 | index: u8, |
| 2255 | return segmentLessThan(ctx, lhs.segName(), rhs.segName()); | 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; | 2263 | }; |
| 2258 | mem.sort(macho.segment_command_64, self.segments.items, {}, sortFn); | 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 | // Attach sections to segments | 2302 | // Attach sections to segments |
| 2261 | for (slice.items(.header), slice.items(.segment_id)) |header, *seg_id| { | 2303 | for (slice.items(.header), slice.items(.segment_id)) |header, *seg_id| { |
| ... | @@ -2276,15 +2318,6 @@ fn initSegments(self: *MachO) !void { | ... | @@ -2276,15 +2318,6 @@ fn initSegments(self: *MachO) !void { |
| 2276 | segment.nsects += 1; | 2318 | segment.nsects += 1; |
| 2277 | seg_id.* = segment_id; | 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 | fn allocateSections(self: *MachO) !void { | 2323 | fn allocateSections(self: *MachO) !void { |
| ... | @@ -2299,8 +2332,8 @@ fn allocateSections(self: *MachO) !void { | ... | @@ -2299,8 +2332,8 @@ fn allocateSections(self: *MachO) !void { |
| 2299 | | 2332 | |
| 2300 | const page_size = self.getPageSize(); | 2333 | const page_size = self.getPageSize(); |
| 2301 | const slice = self.sections.slice(); | 2334 | const slice = self.sections.slice(); |
| 2302 | const last_index = for (slice.items(.header), 0..) |header, i| { | 2335 | const last_index = for (0..slice.items(.header).len) |i| { |
| 2303 | if (mem.indexOf(u8, header.segName(), "ZIG")) |_| break i; | 2336 | if (self.isZigSection(@intCast(i))) break i; |
| 2304 | } else slice.items(.header).len; | 2337 | } else slice.items(.header).len; |
| 2305 | | 2338 | |
| 2306 | for (slice.items(.header)[0..last_index], slice.items(.segment_id)[0..last_index]) |*header, curr_seg_id| { | 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,8 +2386,8 @@ fn allocateSections(self: *MachO) !void { |
| 2353 | /// We allocate segments in a separate step to also consider segments that have no sections. | 2386 | /// We allocate segments in a separate step to also consider segments that have no sections. |
| 2354 | fn allocateSegments(self: *MachO) void { | 2387 | fn allocateSegments(self: *MachO) void { |
| 2355 | const first_index = if (self.pagezero_seg_index) |index| index + 1 else 0; | 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| { | 2389 | const last_index = for (0..self.segments.items.len) |i| { |
| 2357 | if (mem.indexOf(u8, seg.segName(), "ZIG")) |_| break i; | 2390 | if (self.isZigSegment(@intCast(i))) break i; |
| 2358 | } else self.segments.items.len; | 2391 | } else self.segments.items.len; |
| 2359 | | 2392 | |
| 2360 | var vmaddr: u64 = if (self.pagezero_seg_index) |index| | 2393 | var vmaddr: u64 = if (self.pagezero_seg_index) |index| |
| ... | @@ -3622,6 +3655,36 @@ inline fn requiresThunks(self: MachO) bool { | ... | @@ -3622,6 +3655,36 @@ inline fn requiresThunks(self: MachO) bool { |
| 3622 | return self.getTarget().cpu.arch == .aarch64; | 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 | pub fn addSegment(self: *MachO, name: []const u8, opts: struct { | 3688 | pub fn addSegment(self: *MachO, name: []const u8, opts: struct { |
| 3626 | vmaddr: u64 = 0, | 3689 | vmaddr: u64 = 0, |
| 3627 | vmsize: u64 = 0, | 3690 | vmsize: u64 = 0, |