| ... | @@ -164,11 +164,13 @@ tentatives: std.AutoArrayHashMapUnmanaged(u32, void) = .{}, | ... | @@ -164,11 +164,13 @@ tentatives: std.AutoArrayHashMapUnmanaged(u32, void) = .{}, |
| 164 | locals_free_list: std.ArrayListUnmanaged(u32) = .{}, | 164 | locals_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| 165 | globals_free_list: std.ArrayListUnmanaged(u32) = .{}, | 165 | globals_free_list: std.ArrayListUnmanaged(u32) = .{}, |
| 166 | | 166 | |
| 167 | mh_execute_header_index: ?u32 = null, | | |
| 168 | dyld_stub_binder_index: ?u32 = null, | 167 | dyld_stub_binder_index: ?u32 = null, |
| 169 | dyld_private_atom: ?*Atom = null, | 168 | dyld_private_atom: ?*Atom = null, |
| 170 | stub_helper_preamble_atom: ?*Atom = null, | 169 | stub_helper_preamble_atom: ?*Atom = null, |
| 171 | | 170 | |
| | 171 | mh_execute_header_sym_index: ?u32 = null, |
| | 172 | dso_handle_sym_index: ?u32 = null, |
| | 173 | |
| 172 | strtab: std.ArrayListUnmanaged(u8) = .{}, | 174 | strtab: std.ArrayListUnmanaged(u8) = .{}, |
| 173 | strtab_dir: std.HashMapUnmanaged(u32, void, StringIndexContext, std.hash_map.default_max_load_percentage) = .{}, | 175 | strtab_dir: std.HashMapUnmanaged(u32, void, StringIndexContext, std.hash_map.default_max_load_percentage) = .{}, |
| 174 | | 176 | |
| ... | @@ -856,7 +858,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No | ... | @@ -856,7 +858,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No |
| 856 | // re-exports every single symbol definition. | 858 | // re-exports every single symbol definition. |
| 857 | for (lib_dirs.items) |dir| { | 859 | for (lib_dirs.items) |dir| { |
| 858 | if (try resolveLib(arena, dir, "System", ".tbd")) |full_path| { | 860 | if (try resolveLib(arena, dir, "System", ".tbd")) |full_path| { |
| 859 | try libs.put(full_path, .{ .needed = false }); | 861 | try libs.put(full_path, .{ .needed = true }); |
| 860 | libsystem_available = true; | 862 | libsystem_available = true; |
| 861 | break :blk; | 863 | break :blk; |
| 862 | } | 864 | } |
| ... | @@ -866,8 +868,8 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No | ... | @@ -866,8 +868,8 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No |
| 866 | for (lib_dirs.items) |dir| { | 868 | for (lib_dirs.items) |dir| { |
| 867 | if (try resolveLib(arena, dir, "System", ".dylib")) |libsystem_path| { | 869 | if (try resolveLib(arena, dir, "System", ".dylib")) |libsystem_path| { |
| 868 | if (try resolveLib(arena, dir, "c", ".dylib")) |libc_path| { | 870 | if (try resolveLib(arena, dir, "c", ".dylib")) |libc_path| { |
| 869 | try libs.put(libsystem_path, .{ .needed = false }); | 871 | try libs.put(libsystem_path, .{ .needed = true }); |
| 870 | try libs.put(libc_path, .{ .needed = false }); | 872 | try libs.put(libc_path, .{ .needed = true }); |
| 871 | libsystem_available = true; | 873 | libsystem_available = true; |
| 872 | break :blk; | 874 | break :blk; |
| 873 | } | 875 | } |
| ... | @@ -881,7 +883,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No | ... | @@ -881,7 +883,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No |
| 881 | const full_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ | 883 | const full_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ |
| 882 | "libc", "darwin", libsystem_name, | 884 | "libc", "darwin", libsystem_name, |
| 883 | }); | 885 | }); |
| 884 | try libs.put(full_path, .{ .needed = false }); | 886 | try libs.put(full_path, .{ .needed = true }); |
| 885 | } | 887 | } |
| 886 | | 888 | |
| 887 | // frameworks | 889 | // frameworks |
| ... | @@ -1090,7 +1092,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No | ... | @@ -1090,7 +1092,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No |
| 1090 | try self.parseDependentLibs(self.base.options.sysroot, &dependent_libs); | 1092 | try self.parseDependentLibs(self.base.options.sysroot, &dependent_libs); |
| 1091 | } | 1093 | } |
| 1092 | | 1094 | |
| 1093 | try self.createMhExecuteHeaderAtom(); | 1095 | try self.createMhExecuteHeaderSymbol(); |
| 1094 | for (self.objects.items) |*object, object_id| { | 1096 | for (self.objects.items) |*object, object_id| { |
| 1095 | if (object.analyzed) continue; | 1097 | if (object.analyzed) continue; |
| 1096 | try self.resolveSymbolsInObject(@intCast(u16, object_id)); | 1098 | try self.resolveSymbolsInObject(@intCast(u16, object_id)); |
| ... | @@ -1101,7 +1103,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No | ... | @@ -1101,7 +1103,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No |
| 1101 | try self.createDyldPrivateAtom(); | 1103 | try self.createDyldPrivateAtom(); |
| 1102 | try self.createStubHelperPreambleAtom(); | 1104 | try self.createStubHelperPreambleAtom(); |
| 1103 | try self.resolveSymbolsInDylibs(); | 1105 | try self.resolveSymbolsInDylibs(); |
| 1104 | try self.createDsoHandleAtom(); | 1106 | try self.createDsoHandleSymbol(); |
| 1105 | try self.addCodeSignatureLC(); | 1107 | try self.addCodeSignatureLC(); |
| 1106 | | 1108 | |
| 1107 | { | 1109 | { |
| ... | @@ -1156,14 +1158,12 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No | ... | @@ -1156,14 +1158,12 @@ pub fn flushModule(self: *MachO, comp: *Compilation, prog_node: *std.Progress.No |
| 1156 | | 1158 | |
| 1157 | const use_llvm = build_options.have_llvm and self.base.options.use_llvm; | 1159 | const use_llvm = build_options.have_llvm and self.base.options.use_llvm; |
| 1158 | if (use_llvm or use_stage1) { | 1160 | if (use_llvm or use_stage1) { |
| 1159 | try self.sortSections(); | 1161 | try self.pruneAndSortSections(); |
| 1160 | try self.allocateTextSegment(); | 1162 | try self.allocateSegments(); |
| 1161 | try self.allocateDataConstSegment(); | | |
| 1162 | try self.allocateDataSegment(); | | |
| 1163 | self.allocateLinkeditSegment(); | | |
| 1164 | try self.allocateLocals(); | 1163 | try self.allocateLocals(); |
| 1165 | } | 1164 | } |
| 1166 | | 1165 | |
| | 1166 | try self.allocateSpecialSymbols(); |
| 1167 | try self.allocateGlobals(); | 1167 | try self.allocateGlobals(); |
| 1168 | | 1168 | |
| 1169 | if (build_options.enable_logging) { | 1169 | if (build_options.enable_logging) { |
| ... | @@ -2261,6 +2261,27 @@ fn shiftLocalsByOffset(self: *MachO, match: MatchingSection, offset: i64) !void | ... | @@ -2261,6 +2261,27 @@ fn shiftLocalsByOffset(self: *MachO, match: MatchingSection, offset: i64) !void |
| 2261 | } | 2261 | } |
| 2262 | } | 2262 | } |
| 2263 | | 2263 | |
| | 2264 | fn allocateSpecialSymbols(self: *MachO) !void { |
| | 2265 | for (&[_]?u32{ |
| | 2266 | self.mh_execute_header_sym_index, |
| | 2267 | self.dso_handle_sym_index, |
| | 2268 | }) |maybe_sym_index| { |
| | 2269 | const sym_index = maybe_sym_index orelse continue; |
| | 2270 | const sym = &self.locals.items[sym_index]; |
| | 2271 | const seg = self.load_commands.items[self.text_segment_cmd_index.?].segment; |
| | 2272 | sym.n_sect = @intCast(u8, self.section_ordinals.getIndex(.{ |
| | 2273 | .seg = self.text_segment_cmd_index.?, |
| | 2274 | .sect = 0, |
| | 2275 | }).? + 1); |
| | 2276 | sym.n_value = seg.inner.vmaddr; |
| | 2277 | |
| | 2278 | log.debug("allocating {s} at the start of {s}", .{ |
| | 2279 | self.getString(sym.n_strx), |
| | 2280 | seg.inner.segName(), |
| | 2281 | }); |
| | 2282 | } |
| | 2283 | } |
| | 2284 | |
| 2264 | fn allocateGlobals(self: *MachO) !void { | 2285 | fn allocateGlobals(self: *MachO) !void { |
| 2265 | log.debug("allocating global symbols", .{}); | 2286 | log.debug("allocating global symbols", .{}); |
| 2266 | | 2287 | |
| ... | @@ -2442,7 +2463,9 @@ pub fn createTlvPtrAtom(self: *MachO, target: Atom.Relocation.Target) !*Atom { | ... | @@ -2442,7 +2463,9 @@ pub fn createTlvPtrAtom(self: *MachO, target: Atom.Relocation.Target) !*Atom { |
| 2442 | } | 2463 | } |
| 2443 | | 2464 | |
| 2444 | fn createDyldPrivateAtom(self: *MachO) !void { | 2465 | fn createDyldPrivateAtom(self: *MachO) !void { |
| | 2466 | if (self.dyld_stub_binder_index == null) return; |
| 2445 | if (self.dyld_private_atom != null) return; | 2467 | if (self.dyld_private_atom != null) return; |
| | 2468 | |
| 2446 | const local_sym_index = @intCast(u32, self.locals.items.len); | 2469 | const local_sym_index = @intCast(u32, self.locals.items.len); |
| 2447 | const sym = try self.locals.addOne(self.base.allocator); | 2470 | const sym = try self.locals.addOne(self.base.allocator); |
| 2448 | sym.* = .{ | 2471 | sym.* = .{ |
| ... | @@ -2468,7 +2491,9 @@ fn createDyldPrivateAtom(self: *MachO) !void { | ... | @@ -2468,7 +2491,9 @@ fn createDyldPrivateAtom(self: *MachO) !void { |
| 2468 | } | 2491 | } |
| 2469 | | 2492 | |
| 2470 | fn createStubHelperPreambleAtom(self: *MachO) !void { | 2493 | fn createStubHelperPreambleAtom(self: *MachO) !void { |
| | 2494 | if (self.dyld_stub_binder_index == null) return; |
| 2471 | if (self.stub_helper_preamble_atom != null) return; | 2495 | if (self.stub_helper_preamble_atom != null) return; |
| | 2496 | |
| 2472 | const arch = self.base.options.target.cpu.arch; | 2497 | const arch = self.base.options.target.cpu.arch; |
| 2473 | const size: u64 = switch (arch) { | 2498 | const size: u64 = switch (arch) { |
| 2474 | .x86_64 => 15, | 2499 | .x86_64 => 15, |
| ... | @@ -2816,57 +2841,46 @@ fn createTentativeDefAtoms(self: *MachO) !void { | ... | @@ -2816,57 +2841,46 @@ fn createTentativeDefAtoms(self: *MachO) !void { |
| 2816 | } | 2841 | } |
| 2817 | } | 2842 | } |
| 2818 | | 2843 | |
| 2819 | fn createDsoHandleAtom(self: *MachO) !void { | 2844 | fn createDsoHandleSymbol(self: *MachO) !void { |
| 2820 | if (self.strtab_dir.getKeyAdapted(@as([]const u8, "___dso_handle"), StringIndexAdapter{ | 2845 | if (self.dso_handle_sym_index != null) return; |
| | 2846 | |
| | 2847 | const n_strx = self.strtab_dir.getKeyAdapted(@as([]const u8, "___dso_handle"), StringIndexAdapter{ |
| 2821 | .bytes = &self.strtab, | 2848 | .bytes = &self.strtab, |
| 2822 | })) |n_strx| blk: { | 2849 | }) orelse return; |
| 2823 | const resolv = self.symbol_resolver.getPtr(n_strx) orelse break :blk; | | |
| 2824 | if (resolv.where != .undef) break :blk; | | |
| 2825 | | 2850 | |
| 2826 | const undef = &self.undefs.items[resolv.where_index]; | 2851 | const resolv = self.symbol_resolver.getPtr(n_strx) orelse return; |
| 2827 | const match: MatchingSection = .{ | 2852 | if (resolv.where != .undef) return; |
| 2828 | .seg = self.text_segment_cmd_index.?, | | |
| 2829 | .sect = self.text_section_index.?, | | |
| 2830 | }; | | |
| 2831 | const local_sym_index = @intCast(u32, self.locals.items.len); | | |
| 2832 | var nlist = macho.nlist_64{ | | |
| 2833 | .n_strx = undef.n_strx, | | |
| 2834 | .n_type = macho.N_SECT, | | |
| 2835 | .n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1), | | |
| 2836 | .n_desc = 0, | | |
| 2837 | .n_value = 0, | | |
| 2838 | }; | | |
| 2839 | try self.locals.append(self.base.allocator, nlist); | | |
| 2840 | const global_sym_index = @intCast(u32, self.globals.items.len); | | |
| 2841 | nlist.n_type |= macho.N_EXT; | | |
| 2842 | nlist.n_desc = macho.N_WEAK_DEF; | | |
| 2843 | try self.globals.append(self.base.allocator, nlist); | | |
| 2844 | | 2853 | |
| 2845 | assert(self.unresolved.swapRemove(resolv.where_index)); | 2854 | const undef = &self.undefs.items[resolv.where_index]; |
| | 2855 | const local_sym_index = @intCast(u32, self.locals.items.len); |
| | 2856 | var nlist = macho.nlist_64{ |
| | 2857 | .n_strx = undef.n_strx, |
| | 2858 | .n_type = macho.N_SECT, |
| | 2859 | .n_sect = 0, |
| | 2860 | .n_desc = 0, |
| | 2861 | .n_value = 0, |
| | 2862 | }; |
| | 2863 | try self.locals.append(self.base.allocator, nlist); |
| | 2864 | const global_sym_index = @intCast(u32, self.globals.items.len); |
| | 2865 | nlist.n_type |= macho.N_EXT; |
| | 2866 | nlist.n_desc = macho.N_WEAK_DEF; |
| | 2867 | try self.globals.append(self.base.allocator, nlist); |
| | 2868 | self.dso_handle_sym_index = local_sym_index; |
| 2846 | | 2869 | |
| 2847 | undef.* = .{ | 2870 | assert(self.unresolved.swapRemove(resolv.where_index)); |
| 2848 | .n_strx = 0, | | |
| 2849 | .n_type = macho.N_UNDF, | | |
| 2850 | .n_sect = 0, | | |
| 2851 | .n_desc = 0, | | |
| 2852 | .n_value = 0, | | |
| 2853 | }; | | |
| 2854 | resolv.* = .{ | | |
| 2855 | .where = .global, | | |
| 2856 | .where_index = global_sym_index, | | |
| 2857 | .local_sym_index = local_sym_index, | | |
| 2858 | }; | | |
| 2859 | | 2871 | |
| 2860 | // We create an empty atom for this symbol. | 2872 | undef.* = .{ |
| 2861 | // TODO perhaps we should special-case special symbols? Create a separate | 2873 | .n_strx = 0, |
| 2862 | // linked list of atoms? | 2874 | .n_type = macho.N_UNDF, |
| 2863 | const atom = try self.createEmptyAtom(local_sym_index, 0, 0); | 2875 | .n_sect = 0, |
| 2864 | if (self.needs_prealloc) { | 2876 | .n_desc = 0, |
| 2865 | const sym = &self.locals.items[local_sym_index]; | 2877 | .n_value = 0, |
| 2866 | const vaddr = try self.allocateAtom(atom, 0, 1, match); | 2878 | }; |
| 2867 | sym.n_value = vaddr; | 2879 | resolv.* = .{ |
| 2868 | } else try self.addAtomToSection(atom, match); | 2880 | .where = .global, |
| 2869 | } | 2881 | .where_index = global_sym_index, |
| | 2882 | .local_sym_index = local_sym_index, |
| | 2883 | }; |
| 2870 | } | 2884 | } |
| 2871 | | 2885 | |
| 2872 | fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { | 2886 | fn resolveSymbolsInObject(self: *MachO, object_id: u16) !void { |
| ... | @@ -3183,27 +3197,21 @@ fn resolveSymbolsInDylibs(self: *MachO) !void { | ... | @@ -3183,27 +3197,21 @@ fn resolveSymbolsInDylibs(self: *MachO) !void { |
| 3183 | } | 3197 | } |
| 3184 | } | 3198 | } |
| 3185 | | 3199 | |
| 3186 | fn createMhExecuteHeaderAtom(self: *MachO) !void { | 3200 | fn createMhExecuteHeaderSymbol(self: *MachO) !void { |
| 3187 | if (self.mh_execute_header_index != null) return; | 3201 | if (self.base.options.output_mode != .Exe) return; |
| 3188 | | 3202 | if (self.mh_execute_header_sym_index != null) return; |
| 3189 | const match: MatchingSection = .{ | | |
| 3190 | .seg = self.text_segment_cmd_index.?, | | |
| 3191 | .sect = self.text_section_index.?, | | |
| 3192 | }; | | |
| 3193 | const seg = self.load_commands.items[match.seg].segment; | | |
| 3194 | const sect = seg.sections.items[match.sect]; | | |
| 3195 | | 3203 | |
| 3196 | const n_strx = try self.makeString("__mh_execute_header"); | 3204 | const n_strx = try self.makeString("__mh_execute_header"); |
| 3197 | const local_sym_index = @intCast(u32, self.locals.items.len); | 3205 | const local_sym_index = @intCast(u32, self.locals.items.len); |
| 3198 | var nlist = macho.nlist_64{ | 3206 | var nlist = macho.nlist_64{ |
| 3199 | .n_strx = n_strx, | 3207 | .n_strx = n_strx, |
| 3200 | .n_type = macho.N_SECT, | 3208 | .n_type = macho.N_SECT, |
| 3201 | .n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1), | 3209 | .n_sect = 0, |
| 3202 | .n_desc = 0, | 3210 | .n_desc = 0, |
| 3203 | .n_value = sect.addr, | 3211 | .n_value = 0, |
| 3204 | }; | 3212 | }; |
| 3205 | try self.locals.append(self.base.allocator, nlist); | 3213 | try self.locals.append(self.base.allocator, nlist); |
| 3206 | self.mh_execute_header_index = local_sym_index; | 3214 | self.mh_execute_header_sym_index = local_sym_index; |
| 3207 | | 3215 | |
| 3208 | if (self.symbol_resolver.getPtr(n_strx)) |resolv| { | 3216 | if (self.symbol_resolver.getPtr(n_strx)) |resolv| { |
| 3209 | const global = &self.globals.items[resolv.where_index]; | 3217 | const global = &self.globals.items[resolv.where_index]; |
| ... | @@ -3223,23 +3231,11 @@ fn createMhExecuteHeaderAtom(self: *MachO) !void { | ... | @@ -3223,23 +3231,11 @@ fn createMhExecuteHeaderAtom(self: *MachO) !void { |
| 3223 | .file = null, | 3231 | .file = null, |
| 3224 | }); | 3232 | }); |
| 3225 | } | 3233 | } |
| 3226 | | | |
| 3227 | // We always set the __mh_execute_header to point to the beginning of the __TEXT,__text section | | |
| 3228 | const atom = try self.createEmptyAtom(local_sym_index, 0, 0); | | |
| 3229 | if (self.atoms.get(match)) |last| { | | |
| 3230 | var first = last; | | |
| 3231 | while (first.prev) |prev| { | | |
| 3232 | first = prev; | | |
| 3233 | } | | |
| 3234 | atom.next = first; | | |
| 3235 | first.prev = atom; | | |
| 3236 | } else { | | |
| 3237 | try self.atoms.putNoClobber(self.base.allocator, match, atom); | | |
| 3238 | } | | |
| 3239 | } | 3234 | } |
| 3240 | | 3235 | |
| 3241 | fn resolveDyldStubBinder(self: *MachO) !void { | 3236 | fn resolveDyldStubBinder(self: *MachO) !void { |
| 3242 | if (self.dyld_stub_binder_index != null) return; | 3237 | if (self.dyld_stub_binder_index != null) return; |
| | 3238 | if (self.unresolved.count() == 0) return; // no need for a stub binder if we don't have any imports |
| 3243 | | 3239 | |
| 3244 | const n_strx = try self.makeString("dyld_stub_binder"); | 3240 | const n_strx = try self.makeString("dyld_stub_binder"); |
| 3245 | const sym_index = @intCast(u32, self.undefs.items.len); | 3241 | const sym_index = @intCast(u32, self.undefs.items.len); |
| ... | @@ -3295,7 +3291,12 @@ fn resolveDyldStubBinder(self: *MachO) !void { | ... | @@ -3295,7 +3291,12 @@ fn resolveDyldStubBinder(self: *MachO) !void { |
| 3295 | const vaddr = try self.allocateAtom(atom, @sizeOf(u64), 8, match); | 3291 | const vaddr = try self.allocateAtom(atom, @sizeOf(u64), 8, match); |
| 3296 | log.debug("allocated {s} atom at 0x{x}", .{ self.getString(sym.n_strx), vaddr }); | 3292 | log.debug("allocated {s} atom at 0x{x}", .{ self.getString(sym.n_strx), vaddr }); |
| 3297 | atom_sym.n_value = vaddr; | 3293 | atom_sym.n_value = vaddr; |
| 3298 | } else try self.addAtomToSection(atom, match); | 3294 | } else { |
| | 3295 | const seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].segment; |
| | 3296 | const sect = &seg.sections.items[self.got_section_index.?]; |
| | 3297 | sect.size += atom.size; |
| | 3298 | try self.addAtomToSection(atom, match); |
| | 3299 | } |
| 3299 | | 3300 | |
| 3300 | atom_sym.n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1); | 3301 | atom_sym.n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1); |
| 3301 | } | 3302 | } |
| ... | @@ -4512,6 +4513,7 @@ fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -4512,6 +4513,7 @@ fn populateMissingMetadata(self: *MachO) !void { |
| 4512 | const aligned_pagezero_vmsize = mem.alignBackwardGeneric(u64, pagezero_vmsize, self.page_size); | 4513 | const aligned_pagezero_vmsize = mem.alignBackwardGeneric(u64, pagezero_vmsize, self.page_size); |
| 4513 | | 4514 | |
| 4514 | if (self.pagezero_segment_cmd_index == null) blk: { | 4515 | if (self.pagezero_segment_cmd_index == null) blk: { |
| | 4516 | if (self.base.options.output_mode == .Lib) break :blk; |
| 4515 | if (aligned_pagezero_vmsize == 0) break :blk; | 4517 | if (aligned_pagezero_vmsize == 0) break :blk; |
| 4516 | if (aligned_pagezero_vmsize != pagezero_vmsize) { | 4518 | if (aligned_pagezero_vmsize != pagezero_vmsize) { |
| 4517 | log.warn("requested __PAGEZERO size (0x{x}) is not page aligned", .{pagezero_vmsize}); | 4519 | log.warn("requested __PAGEZERO size (0x{x}) is not page aligned", .{pagezero_vmsize}); |
| ... | @@ -4636,9 +4638,9 @@ fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -4636,9 +4638,9 @@ fn populateMissingMetadata(self: *MachO) !void { |
| 4636 | var fileoff: u64 = 0; | 4638 | var fileoff: u64 = 0; |
| 4637 | var needed_size: u64 = 0; | 4639 | var needed_size: u64 = 0; |
| 4638 | if (self.needs_prealloc) { | 4640 | if (self.needs_prealloc) { |
| 4639 | const address_and_offset = self.nextSegmentAddressAndOffset(); | 4641 | const base = self.getSegmentAllocBase(&.{self.text_segment_cmd_index.?}); |
| 4640 | vmaddr = address_and_offset.address; | 4642 | vmaddr = base.vmaddr; |
| 4641 | fileoff = address_and_offset.offset; | 4643 | fileoff = base.fileoff; |
| 4642 | const ideal_size = @sizeOf(u64) * self.base.options.symbol_count_hint; | 4644 | const ideal_size = @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 4643 | needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size); | 4645 | needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size); |
| 4644 | log.debug("found __DATA_CONST segment free space 0x{x} to 0x{x}", .{ | 4646 | log.debug("found __DATA_CONST segment free space 0x{x} to 0x{x}", .{ |
| ... | @@ -4686,9 +4688,9 @@ fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -4686,9 +4688,9 @@ fn populateMissingMetadata(self: *MachO) !void { |
| 4686 | var fileoff: u64 = 0; | 4688 | var fileoff: u64 = 0; |
| 4687 | var needed_size: u64 = 0; | 4689 | var needed_size: u64 = 0; |
| 4688 | if (self.needs_prealloc) { | 4690 | if (self.needs_prealloc) { |
| 4689 | const address_and_offset = self.nextSegmentAddressAndOffset(); | 4691 | const base = self.getSegmentAllocBase(&.{self.data_const_segment_cmd_index.?}); |
| 4690 | vmaddr = address_and_offset.address; | 4692 | vmaddr = base.vmaddr; |
| 4691 | fileoff = address_and_offset.offset; | 4693 | fileoff = base.fileoff; |
| 4692 | const ideal_size = 2 * @sizeOf(u64) * self.base.options.symbol_count_hint; | 4694 | const ideal_size = 2 * @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 4693 | needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size); | 4695 | needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size); |
| 4694 | log.debug("found __DATA segment free space 0x{x} to 0x{x}", .{ | 4696 | log.debug("found __DATA segment free space 0x{x} to 0x{x}", .{ |
| ... | @@ -4803,9 +4805,9 @@ fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -4803,9 +4805,9 @@ fn populateMissingMetadata(self: *MachO) !void { |
| 4803 | var vmaddr: u64 = 0; | 4805 | var vmaddr: u64 = 0; |
| 4804 | var fileoff: u64 = 0; | 4806 | var fileoff: u64 = 0; |
| 4805 | if (self.needs_prealloc) { | 4807 | if (self.needs_prealloc) { |
| 4806 | const address_and_offset = self.nextSegmentAddressAndOffset(); | 4808 | const base = self.getSegmentAllocBase(&.{self.data_segment_cmd_index.?}); |
| 4807 | vmaddr = address_and_offset.address; | 4809 | vmaddr = base.vmaddr; |
| 4808 | fileoff = address_and_offset.offset; | 4810 | fileoff = base.fileoff; |
| 4809 | log.debug("found __LINKEDIT segment free space at 0x{x}", .{fileoff}); | 4811 | log.debug("found __LINKEDIT segment free space at 0x{x}", .{fileoff}); |
| 4810 | } | 4812 | } |
| 4811 | try self.load_commands.append(self.base.allocator, .{ | 4813 | try self.load_commands.append(self.base.allocator, .{ |
| ... | @@ -5030,17 +5032,10 @@ fn populateMissingMetadata(self: *MachO) !void { | ... | @@ -5030,17 +5032,10 @@ fn populateMissingMetadata(self: *MachO) !void { |
| 5030 | self.cold_start = true; | 5032 | self.cold_start = true; |
| 5031 | } | 5033 | } |
| 5032 | | 5034 | |
| 5033 | fn allocateTextSegment(self: *MachO) !void { | 5035 | fn calcMinHeaderpad(self: *MachO) u64 { |
| 5034 | const seg = &self.load_commands.items[self.text_segment_cmd_index.?].segment; | | |
| 5035 | const base_vmaddr = if (self.pagezero_segment_cmd_index) |index| | | |
| 5036 | self.load_commands.items[index].segment.inner.vmsize | | |
| 5037 | else | | |
| 5038 | 0; | | |
| 5039 | seg.inner.fileoff = 0; | | |
| 5040 | seg.inner.vmaddr = base_vmaddr; | | |
| 5041 | | | |
| 5042 | var sizeofcmds: u32 = 0; | 5036 | var sizeofcmds: u32 = 0; |
| 5043 | for (self.load_commands.items) |lc| { | 5037 | for (self.load_commands.items) |lc| { |
| | 5038 | if (lc.cmd() == .NONE) continue; |
| 5044 | sizeofcmds += lc.cmdsize(); | 5039 | sizeofcmds += lc.cmdsize(); |
| 5045 | } | 5040 | } |
| 5046 | | 5041 | |
| ... | @@ -5067,60 +5062,74 @@ fn allocateTextSegment(self: *MachO) !void { | ... | @@ -5067,60 +5062,74 @@ fn allocateTextSegment(self: *MachO) !void { |
| 5067 | } | 5062 | } |
| 5068 | const offset = @sizeOf(macho.mach_header_64) + padding; | 5063 | const offset = @sizeOf(macho.mach_header_64) + padding; |
| 5069 | log.debug("actual headerpad size 0x{x}", .{offset}); | 5064 | log.debug("actual headerpad size 0x{x}", .{offset}); |
| 5070 | try self.allocateSegment(self.text_segment_cmd_index.?, offset); | | |
| 5071 | | 5065 | |
| 5072 | // Shift all sections to the back to minimize jump size between __TEXT and __DATA segments. | 5066 | return offset; |
| 5073 | var min_alignment: u32 = 0; | 5067 | } |
| 5074 | for (seg.sections.items) |sect| { | | |
| 5075 | const alignment = try math.powi(u32, 2, sect.@"align"); | | |
| 5076 | min_alignment = math.max(min_alignment, alignment); | | |
| 5077 | } | | |
| 5078 | | 5068 | |
| 5079 | assert(min_alignment > 0); | 5069 | fn allocateSegments(self: *MachO) !void { |
| 5080 | const last_sect_idx = seg.sections.items.len - 1; | 5070 | try self.allocateSegment(self.text_segment_cmd_index, &.{ |
| 5081 | const last_sect = seg.sections.items[last_sect_idx]; | 5071 | self.pagezero_segment_cmd_index, |
| 5082 | const shift: u32 = blk: { | 5072 | }, self.calcMinHeaderpad()); |
| 5083 | const diff = seg.inner.filesize - last_sect.offset - last_sect.size; | 5073 | |
| 5084 | const factor = @divTrunc(diff, min_alignment); | 5074 | if (self.text_segment_cmd_index) |index| blk: { |
| 5085 | break :blk @intCast(u32, factor * min_alignment); | 5075 | const seg = &self.load_commands.items[index].segment; |
| 5086 | }; | 5076 | if (seg.sections.items.len == 0) break :blk; |
| 5087 | | 5077 | |
| 5088 | if (shift > 0) { | 5078 | // Shift all sections to the back to minimize jump size between __TEXT and __DATA segments. |
| 5089 | for (seg.sections.items) |*sect| { | 5079 | var min_alignment: u32 = 0; |
| 5090 | sect.offset += shift; | 5080 | for (seg.sections.items) |sect| { |
| 5091 | sect.addr += shift; | 5081 | const alignment = try math.powi(u32, 2, sect.@"align"); |
| | 5082 | min_alignment = math.max(min_alignment, alignment); |
| | 5083 | } |
| | 5084 | |
| | 5085 | assert(min_alignment > 0); |
| | 5086 | const last_sect_idx = seg.sections.items.len - 1; |
| | 5087 | const last_sect = seg.sections.items[last_sect_idx]; |
| | 5088 | const shift: u32 = shift: { |
| | 5089 | const diff = seg.inner.filesize - last_sect.offset - last_sect.size; |
| | 5090 | const factor = @divTrunc(diff, min_alignment); |
| | 5091 | break :shift @intCast(u32, factor * min_alignment); |
| | 5092 | }; |
| | 5093 | |
| | 5094 | if (shift > 0) { |
| | 5095 | for (seg.sections.items) |*sect| { |
| | 5096 | sect.offset += shift; |
| | 5097 | sect.addr += shift; |
| | 5098 | } |
| 5092 | } | 5099 | } |
| 5093 | } | 5100 | } |
| 5094 | } | | |
| 5095 | | 5101 | |
| 5096 | fn allocateDataConstSegment(self: *MachO) !void { | 5102 | try self.allocateSegment(self.data_const_segment_cmd_index, &.{ |
| 5097 | const seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].segment; | 5103 | self.text_segment_cmd_index, |
| 5098 | const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].segment; | 5104 | self.pagezero_segment_cmd_index, |
| 5099 | seg.inner.fileoff = text_seg.inner.fileoff + text_seg.inner.filesize; | 5105 | }, 0); |
| 5100 | seg.inner.vmaddr = text_seg.inner.vmaddr + text_seg.inner.vmsize; | | |
| 5101 | try self.allocateSegment(self.data_const_segment_cmd_index.?, 0); | | |
| 5102 | } | | |
| 5103 | | 5106 | |
| 5104 | fn allocateDataSegment(self: *MachO) !void { | 5107 | try self.allocateSegment(self.data_segment_cmd_index, &.{ |
| 5105 | const seg = &self.load_commands.items[self.data_segment_cmd_index.?].segment; | 5108 | self.data_const_segment_cmd_index, |
| 5106 | const data_const_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].segment; | 5109 | self.text_segment_cmd_index, |
| 5107 | seg.inner.fileoff = data_const_seg.inner.fileoff + data_const_seg.inner.filesize; | 5110 | self.pagezero_segment_cmd_index, |
| 5108 | seg.inner.vmaddr = data_const_seg.inner.vmaddr + data_const_seg.inner.vmsize; | 5111 | }, 0); |
| 5109 | try self.allocateSegment(self.data_segment_cmd_index.?, 0); | | |
| 5110 | } | | |
| 5111 | | 5112 | |
| 5112 | fn allocateLinkeditSegment(self: *MachO) void { | 5113 | try self.allocateSegment(self.linkedit_segment_cmd_index, &.{ |
| 5113 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].segment; | 5114 | self.data_segment_cmd_index, |
| 5114 | const data_seg = self.load_commands.items[self.data_segment_cmd_index.?].segment; | 5115 | self.data_const_segment_cmd_index, |
| 5115 | seg.inner.fileoff = data_seg.inner.fileoff + data_seg.inner.filesize; | 5116 | self.text_segment_cmd_index, |
| 5116 | seg.inner.vmaddr = data_seg.inner.vmaddr + data_seg.inner.vmsize; | 5117 | self.pagezero_segment_cmd_index, |
| | 5118 | }, 0); |
| 5117 | } | 5119 | } |
| 5118 | | 5120 | |
| 5119 | fn allocateSegment(self: *MachO, index: u16, offset: u64) !void { | 5121 | fn allocateSegment(self: *MachO, maybe_index: ?u16, indices: []const ?u16, init_size: u64) !void { |
| | 5122 | const index = maybe_index orelse return; |
| 5120 | const seg = &self.load_commands.items[index].segment; | 5123 | const seg = &self.load_commands.items[index].segment; |
| 5121 | | 5124 | |
| | 5125 | const base = self.getSegmentAllocBase(indices); |
| | 5126 | seg.inner.vmaddr = base.vmaddr; |
| | 5127 | seg.inner.fileoff = base.fileoff; |
| | 5128 | seg.inner.filesize = init_size; |
| | 5129 | seg.inner.vmsize = init_size; |
| | 5130 | |
| 5122 | // Allocate the sections according to their alignment at the beginning of the segment. | 5131 | // Allocate the sections according to their alignment at the beginning of the segment. |
| 5123 | var start: u64 = offset; | 5132 | var start = init_size; |
| 5124 | for (seg.sections.items) |*sect, sect_id| { | 5133 | for (seg.sections.items) |*sect, sect_id| { |
| 5125 | const is_zerofill = sect.flags == macho.S_ZEROFILL or sect.flags == macho.S_THREAD_LOCAL_ZEROFILL; | 5134 | const is_zerofill = sect.flags == macho.S_ZEROFILL or sect.flags == macho.S_THREAD_LOCAL_ZEROFILL; |
| 5126 | const use_llvm = build_options.have_llvm and self.base.options.use_llvm; | 5135 | const use_llvm = build_options.have_llvm and self.base.options.use_llvm; |
| ... | @@ -5524,6 +5533,9 @@ fn addAtomToSection(self: *MachO, atom: *Atom, match: MatchingSection) !void { | ... | @@ -5524,6 +5533,9 @@ fn addAtomToSection(self: *MachO, atom: *Atom, match: MatchingSection) !void { |
| 5524 | } else { | 5533 | } else { |
| 5525 | try self.atoms.putNoClobber(self.base.allocator, match, atom); | 5534 | try self.atoms.putNoClobber(self.base.allocator, match, atom); |
| 5526 | } | 5535 | } |
| | 5536 | const seg = &self.load_commands.items[match.seg].segment; |
| | 5537 | const sect = &seg.sections.items[match.sect]; |
| | 5538 | sect.size += atom.size; |
| 5527 | } | 5539 | } |
| 5528 | | 5540 | |
| 5529 | pub fn getGlobalSymbol(self: *MachO, name: []const u8) !u32 { | 5541 | pub fn getGlobalSymbol(self: *MachO, name: []const u8) !u32 { |
| ... | @@ -5551,180 +5563,145 @@ pub fn getGlobalSymbol(self: *MachO, name: []const u8) !u32 { | ... | @@ -5551,180 +5563,145 @@ pub fn getGlobalSymbol(self: *MachO, name: []const u8) !u32 { |
| 5551 | return n_strx; | 5563 | return n_strx; |
| 5552 | } | 5564 | } |
| 5553 | | 5565 | |
| 5554 | const NextSegmentAddressAndOffset = struct { | 5566 | fn getSegmentAllocBase(self: MachO, indices: []const ?u16) struct { vmaddr: u64, fileoff: u64 } { |
| 5555 | address: u64, | 5567 | for (indices) |maybe_prev_id| { |
| 5556 | offset: u64, | 5568 | const prev_id = maybe_prev_id orelse continue; |
| 5557 | }; | 5569 | const prev = self.load_commands.items[prev_id].segment; |
| 5558 | | 5570 | return .{ |
| 5559 | fn nextSegmentAddressAndOffset(self: *MachO) NextSegmentAddressAndOffset { | 5571 | .vmaddr = prev.inner.vmaddr + prev.inner.vmsize, |
| 5560 | var prev_segment_idx: ?usize = null; // We use optional here for safety. | 5572 | .fileoff = prev.inner.fileoff + prev.inner.filesize, |
| 5561 | for (self.load_commands.items) |cmd, i| { | 5573 | }; |
| 5562 | if (cmd == .segment) { | | |
| 5563 | prev_segment_idx = i; | | |
| 5564 | } | | |
| 5565 | } | 5574 | } |
| 5566 | const prev_segment = self.load_commands.items[prev_segment_idx.?].segment; | 5575 | return .{ .vmaddr = 0, .fileoff = 0 }; |
| 5567 | const address = prev_segment.inner.vmaddr + prev_segment.inner.vmsize; | | |
| 5568 | const offset = prev_segment.inner.fileoff + prev_segment.inner.filesize; | | |
| 5569 | return .{ | | |
| 5570 | .address = address, | | |
| 5571 | .offset = offset, | | |
| 5572 | }; | | |
| 5573 | } | 5576 | } |
| 5574 | | 5577 | |
| 5575 | fn sortSections(self: *MachO) !void { | 5578 | fn pruneAndSortSectionsInSegment(self: *MachO, maybe_seg_id: *?u16, indices: []*?u16) !void { |
| 5576 | var text_index_mapping = std.AutoHashMap(u16, u16).init(self.base.allocator); | 5579 | const seg_id = maybe_seg_id.* orelse return; |
| 5577 | defer text_index_mapping.deinit(); | | |
| 5578 | var data_const_index_mapping = std.AutoHashMap(u16, u16).init(self.base.allocator); | | |
| 5579 | defer data_const_index_mapping.deinit(); | | |
| 5580 | var data_index_mapping = std.AutoHashMap(u16, u16).init(self.base.allocator); | | |
| 5581 | defer data_index_mapping.deinit(); | | |
| 5582 | | 5580 | |
| 5583 | { | 5581 | var mapping = std.AutoArrayHashMap(u16, ?u16).init(self.base.allocator); |
| 5584 | // __TEXT segment | 5582 | defer mapping.deinit(); |
| 5585 | const seg = &self.load_commands.items[self.text_segment_cmd_index.?].segment; | 5583 | |
| 5586 | var sections = seg.sections.toOwnedSlice(self.base.allocator); | 5584 | const seg = &self.load_commands.items[seg_id].segment; |
| 5587 | defer self.base.allocator.free(sections); | 5585 | var sections = seg.sections.toOwnedSlice(self.base.allocator); |
| 5588 | try seg.sections.ensureTotalCapacity(self.base.allocator, sections.len); | 5586 | defer self.base.allocator.free(sections); |
| 5589 | | 5587 | try seg.sections.ensureTotalCapacity(self.base.allocator, sections.len); |
| 5590 | const indices = &[_]*?u16{ | 5588 | |
| 5591 | &self.text_section_index, | 5589 | for (indices) |maybe_index| { |
| 5592 | &self.stubs_section_index, | 5590 | const old_idx = maybe_index.* orelse continue; |
| 5593 | &self.stub_helper_section_index, | 5591 | const sect = sections[old_idx]; |
| 5594 | &self.gcc_except_tab_section_index, | 5592 | if (sect.size == 0) { |
| 5595 | &self.cstring_section_index, | 5593 | log.debug("pruning section {s},{s}", .{ sect.segName(), sect.sectName() }); |
| 5596 | &self.ustring_section_index, | 5594 | maybe_index.* = null; |
| 5597 | &self.text_const_section_index, | 5595 | seg.inner.cmdsize -= @sizeOf(macho.section_64); |
| 5598 | &self.objc_methlist_section_index, | 5596 | seg.inner.nsects -= 1; |
| 5599 | &self.objc_methname_section_index, | 5597 | } else { |
| 5600 | &self.objc_methtype_section_index, | 5598 | maybe_index.* = @intCast(u16, seg.sections.items.len); |
| 5601 | &self.objc_classname_section_index, | 5599 | seg.sections.appendAssumeCapacity(sect); |
| 5602 | &self.eh_frame_section_index, | | |
| 5603 | }; | | |
| 5604 | for (indices) |maybe_index| { | | |
| 5605 | const new_index: u16 = if (maybe_index.*) |index| blk: { | | |
| 5606 | const idx = @intCast(u16, seg.sections.items.len); | | |
| 5607 | seg.sections.appendAssumeCapacity(sections[index]); | | |
| 5608 | try text_index_mapping.putNoClobber(index, idx); | | |
| 5609 | break :blk idx; | | |
| 5610 | } else continue; | | |
| 5611 | maybe_index.* = new_index; | | |
| 5612 | } | 5600 | } |
| | 5601 | try mapping.putNoClobber(old_idx, maybe_index.*); |
| 5613 | } | 5602 | } |
| 5614 | | 5603 | |
| 5615 | { | 5604 | var atoms = std.ArrayList(struct { match: MatchingSection, atom: *Atom }).init(self.base.allocator); |
| 5616 | // __DATA_CONST segment | 5605 | defer atoms.deinit(); |
| 5617 | const seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].segment; | 5606 | try atoms.ensureTotalCapacity(mapping.count()); |
| 5618 | var sections = seg.sections.toOwnedSlice(self.base.allocator); | 5607 | |
| 5619 | defer self.base.allocator.free(sections); | 5608 | for (mapping.keys()) |old_sect| { |
| 5620 | try seg.sections.ensureTotalCapacity(self.base.allocator, sections.len); | 5609 | const new_sect = mapping.get(old_sect).? orelse { |
| 5621 | | 5610 | _ = self.atoms.remove(.{ .seg = seg_id, .sect = old_sect }); |
| 5622 | const indices = &[_]*?u16{ | 5611 | continue; |
| 5623 | &self.got_section_index, | | |
| 5624 | &self.mod_init_func_section_index, | | |
| 5625 | &self.mod_term_func_section_index, | | |
| 5626 | &self.data_const_section_index, | | |
| 5627 | &self.objc_cfstring_section_index, | | |
| 5628 | &self.objc_classlist_section_index, | | |
| 5629 | &self.objc_imageinfo_section_index, | | |
| 5630 | }; | 5612 | }; |
| 5631 | for (indices) |maybe_index| { | 5613 | const kv = self.atoms.fetchRemove(.{ .seg = seg_id, .sect = old_sect }).?; |
| 5632 | const new_index: u16 = if (maybe_index.*) |index| blk: { | 5614 | atoms.appendAssumeCapacity(.{ |
| 5633 | const idx = @intCast(u16, seg.sections.items.len); | 5615 | .match = .{ .seg = seg_id, .sect = new_sect }, |
| 5634 | seg.sections.appendAssumeCapacity(sections[index]); | 5616 | .atom = kv.value, |
| 5635 | try data_const_index_mapping.putNoClobber(index, idx); | 5617 | }); |
| 5636 | break :blk idx; | | |
| 5637 | } else continue; | | |
| 5638 | maybe_index.* = new_index; | | |
| 5639 | } | | |
| 5640 | } | 5618 | } |
| 5641 | | 5619 | |
| 5642 | { | 5620 | while (atoms.popOrNull()) |next| { |
| 5643 | // __DATA segment | 5621 | try self.atoms.putNoClobber(self.base.allocator, next.match, next.atom); |
| 5644 | const seg = &self.load_commands.items[self.data_segment_cmd_index.?].segment; | | |
| 5645 | var sections = seg.sections.toOwnedSlice(self.base.allocator); | | |
| 5646 | defer self.base.allocator.free(sections); | | |
| 5647 | try seg.sections.ensureTotalCapacity(self.base.allocator, sections.len); | | |
| 5648 | | | |
| 5649 | // __DATA segment | | |
| 5650 | const indices = &[_]*?u16{ | | |
| 5651 | &self.rustc_section_index, | | |
| 5652 | &self.la_symbol_ptr_section_index, | | |
| 5653 | &self.objc_const_section_index, | | |
| 5654 | &self.objc_selrefs_section_index, | | |
| 5655 | &self.objc_classrefs_section_index, | | |
| 5656 | &self.objc_data_section_index, | | |
| 5657 | &self.data_section_index, | | |
| 5658 | &self.tlv_section_index, | | |
| 5659 | &self.tlv_ptrs_section_index, | | |
| 5660 | &self.tlv_data_section_index, | | |
| 5661 | &self.tlv_bss_section_index, | | |
| 5662 | &self.bss_section_index, | | |
| 5663 | }; | | |
| 5664 | for (indices) |maybe_index| { | | |
| 5665 | const new_index: u16 = if (maybe_index.*) |index| blk: { | | |
| 5666 | const idx = @intCast(u16, seg.sections.items.len); | | |
| 5667 | seg.sections.appendAssumeCapacity(sections[index]); | | |
| 5668 | try data_index_mapping.putNoClobber(index, idx); | | |
| 5669 | break :blk idx; | | |
| 5670 | } else continue; | | |
| 5671 | maybe_index.* = new_index; | | |
| 5672 | } | | |
| 5673 | } | 5622 | } |
| 5674 | | 5623 | |
| 5675 | { | 5624 | if (seg.inner.nsects == 0 and !mem.eql(u8, "__TEXT", seg.inner.segName())) { |
| 5676 | var transient: std.AutoHashMapUnmanaged(MatchingSection, *Atom) = .{}; | 5625 | // Segment has now become empty, so mark it as such |
| 5677 | try transient.ensureTotalCapacity(self.base.allocator, self.atoms.count()); | 5626 | log.debug("marking segment {s} as dead", .{seg.inner.segName()}); |
| | 5627 | seg.inner.cmd = @intToEnum(macho.LC, 0); |
| | 5628 | maybe_seg_id.* = null; |
| | 5629 | } |
| | 5630 | } |
| 5678 | | 5631 | |
| 5679 | var it = self.atoms.iterator(); | 5632 | fn pruneAndSortSections(self: *MachO) !void { |
| 5680 | while (it.next()) |entry| { | 5633 | try self.pruneAndSortSectionsInSegment(&self.text_segment_cmd_index, &.{ |
| 5681 | const old = entry.key_ptr.*; | 5634 | &self.text_section_index, |
| 5682 | const sect = if (old.seg == self.text_segment_cmd_index.?) | 5635 | &self.stubs_section_index, |
| 5683 | text_index_mapping.get(old.sect).? | 5636 | &self.stub_helper_section_index, |
| 5684 | else if (old.seg == self.data_const_segment_cmd_index.?) | 5637 | &self.gcc_except_tab_section_index, |
| 5685 | data_const_index_mapping.get(old.sect).? | 5638 | &self.cstring_section_index, |
| 5686 | else | 5639 | &self.ustring_section_index, |
| 5687 | data_index_mapping.get(old.sect).?; | 5640 | &self.text_const_section_index, |
| 5688 | transient.putAssumeCapacityNoClobber(.{ | 5641 | &self.objc_methlist_section_index, |
| 5689 | .seg = old.seg, | 5642 | &self.objc_methname_section_index, |
| 5690 | .sect = sect, | 5643 | &self.objc_methtype_section_index, |
| 5691 | }, entry.value_ptr.*); | 5644 | &self.objc_classname_section_index, |
| 5692 | } | 5645 | &self.eh_frame_section_index, |
| | 5646 | }); |
| 5693 | | 5647 | |
| 5694 | self.atoms.clearAndFree(self.base.allocator); | 5648 | try self.pruneAndSortSectionsInSegment(&self.data_const_segment_cmd_index, &.{ |
| 5695 | self.atoms.deinit(self.base.allocator); | 5649 | &self.got_section_index, |
| 5696 | self.atoms = transient; | 5650 | &self.mod_init_func_section_index, |
| 5697 | } | 5651 | &self.mod_term_func_section_index, |
| | 5652 | &self.data_const_section_index, |
| | 5653 | &self.objc_cfstring_section_index, |
| | 5654 | &self.objc_classlist_section_index, |
| | 5655 | &self.objc_imageinfo_section_index, |
| | 5656 | }); |
| 5698 | | 5657 | |
| 5699 | { | 5658 | try self.pruneAndSortSectionsInSegment(&self.data_segment_cmd_index, &.{ |
| 5700 | // Create new section ordinals. | 5659 | &self.rustc_section_index, |
| 5701 | self.section_ordinals.clearRetainingCapacity(); | 5660 | &self.la_symbol_ptr_section_index, |
| 5702 | const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].segment; | 5661 | &self.objc_const_section_index, |
| 5703 | for (text_seg.sections.items) |_, sect_id| { | 5662 | &self.objc_selrefs_section_index, |
| | 5663 | &self.objc_classrefs_section_index, |
| | 5664 | &self.objc_data_section_index, |
| | 5665 | &self.data_section_index, |
| | 5666 | &self.tlv_section_index, |
| | 5667 | &self.tlv_ptrs_section_index, |
| | 5668 | &self.tlv_data_section_index, |
| | 5669 | &self.tlv_bss_section_index, |
| | 5670 | &self.bss_section_index, |
| | 5671 | }); |
| | 5672 | |
| | 5673 | // Create new section ordinals. |
| | 5674 | self.section_ordinals.clearRetainingCapacity(); |
| | 5675 | if (self.text_segment_cmd_index) |seg_id| { |
| | 5676 | const seg = self.load_commands.items[seg_id].segment; |
| | 5677 | for (seg.sections.items) |_, sect_id| { |
| 5704 | const res = self.section_ordinals.getOrPutAssumeCapacity(.{ | 5678 | const res = self.section_ordinals.getOrPutAssumeCapacity(.{ |
| 5705 | .seg = self.text_segment_cmd_index.?, | 5679 | .seg = seg_id, |
| 5706 | .sect = @intCast(u16, sect_id), | 5680 | .sect = @intCast(u16, sect_id), |
| 5707 | }); | 5681 | }); |
| 5708 | assert(!res.found_existing); | 5682 | assert(!res.found_existing); |
| 5709 | } | 5683 | } |
| 5710 | const data_const_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].segment; | 5684 | } |
| 5711 | for (data_const_seg.sections.items) |_, sect_id| { | 5685 | if (self.data_const_segment_cmd_index) |seg_id| { |
| | 5686 | const seg = self.load_commands.items[seg_id].segment; |
| | 5687 | for (seg.sections.items) |_, sect_id| { |
| 5712 | const res = self.section_ordinals.getOrPutAssumeCapacity(.{ | 5688 | const res = self.section_ordinals.getOrPutAssumeCapacity(.{ |
| 5713 | .seg = self.data_const_segment_cmd_index.?, | 5689 | .seg = seg_id, |
| 5714 | .sect = @intCast(u16, sect_id), | 5690 | .sect = @intCast(u16, sect_id), |
| 5715 | }); | 5691 | }); |
| 5716 | assert(!res.found_existing); | 5692 | assert(!res.found_existing); |
| 5717 | } | 5693 | } |
| 5718 | const data_seg = self.load_commands.items[self.data_segment_cmd_index.?].segment; | 5694 | } |
| 5719 | for (data_seg.sections.items) |_, sect_id| { | 5695 | if (self.data_segment_cmd_index) |seg_id| { |
| | 5696 | const seg = self.load_commands.items[seg_id].segment; |
| | 5697 | for (seg.sections.items) |_, sect_id| { |
| 5720 | const res = self.section_ordinals.getOrPutAssumeCapacity(.{ | 5698 | const res = self.section_ordinals.getOrPutAssumeCapacity(.{ |
| 5721 | .seg = self.data_segment_cmd_index.?, | 5699 | .seg = seg_id, |
| 5722 | .sect = @intCast(u16, sect_id), | 5700 | .sect = @intCast(u16, sect_id), |
| 5723 | }); | 5701 | }); |
| 5724 | assert(!res.found_existing); | 5702 | assert(!res.found_existing); |
| 5725 | } | 5703 | } |
| 5726 | } | 5704 | } |
| 5727 | | | |
| 5728 | self.sections_order_dirty = false; | 5705 | self.sections_order_dirty = false; |
| 5729 | } | 5706 | } |
| 5730 | | 5707 | |
| ... | @@ -5739,12 +5716,16 @@ fn updateSectionOrdinals(self: *MachO) !void { | ... | @@ -5739,12 +5716,16 @@ fn updateSectionOrdinals(self: *MachO) !void { |
| 5739 | var ordinals: std.AutoArrayHashMapUnmanaged(MatchingSection, void) = .{}; | 5716 | var ordinals: std.AutoArrayHashMapUnmanaged(MatchingSection, void) = .{}; |
| 5740 | | 5717 | |
| 5741 | var new_ordinal: u8 = 0; | 5718 | var new_ordinal: u8 = 0; |
| 5742 | for (self.load_commands.items) |lc, lc_id| { | 5719 | for (&[_]?u16{ |
| 5743 | if (lc != .segment) break; | 5720 | self.text_segment_cmd_index, |
| 5744 | | 5721 | self.data_const_segment_cmd_index, |
| 5745 | for (lc.segment.sections.items) |_, sect_id| { | 5722 | self.data_segment_cmd_index, |
| | 5723 | }) |maybe_index| { |
| | 5724 | const index = maybe_index orelse continue; |
| | 5725 | const seg = self.load_commands.items[index].segment; |
| | 5726 | for (seg.sections.items) |_, sect_id| { |
| 5746 | const match = MatchingSection{ | 5727 | const match = MatchingSection{ |
| 5747 | .seg = @intCast(u16, lc_id), | 5728 | .seg = @intCast(u16, index), |
| 5748 | .sect = @intCast(u16, sect_id), | 5729 | .sect = @intCast(u16, sect_id), |
| 5749 | }; | 5730 | }; |
| 5750 | const old_ordinal = @intCast(u8, self.section_ordinals.getIndex(match).? + 1); | 5731 | const old_ordinal = @intCast(u8, self.section_ordinals.getIndex(match).? + 1); |
| ... | @@ -5783,7 +5764,9 @@ fn writeDyldInfoData(self: *MachO) !void { | ... | @@ -5783,7 +5764,9 @@ fn writeDyldInfoData(self: *MachO) !void { |
| 5783 | const match = entry.key_ptr.*; | 5764 | const match = entry.key_ptr.*; |
| 5784 | var atom: *Atom = entry.value_ptr.*; | 5765 | var atom: *Atom = entry.value_ptr.*; |
| 5785 | | 5766 | |
| 5786 | if (match.seg == self.text_segment_cmd_index.?) continue; // __TEXT is non-writable | 5767 | if (self.text_segment_cmd_index) |seg| { |
| | 5768 | if (match.seg == seg) continue; // __TEXT is non-writable |
| | 5769 | } |
| 5787 | | 5770 | |
| 5788 | const seg = self.load_commands.items[match.seg].segment; | 5771 | const seg = self.load_commands.items[match.seg].segment; |
| 5789 | | 5772 | |
| ... | @@ -5865,6 +5848,7 @@ fn writeDyldInfoData(self: *MachO) !void { | ... | @@ -5865,6 +5848,7 @@ fn writeDyldInfoData(self: *MachO) !void { |
| 5865 | { | 5848 | { |
| 5866 | // TODO handle macho.EXPORT_SYMBOL_FLAGS_REEXPORT and macho.EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER. | 5849 | // TODO handle macho.EXPORT_SYMBOL_FLAGS_REEXPORT and macho.EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER. |
| 5867 | log.debug("generating export trie", .{}); | 5850 | log.debug("generating export trie", .{}); |
| | 5851 | |
| 5868 | const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].segment; | 5852 | const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].segment; |
| 5869 | const base_address = text_segment.inner.vmaddr; | 5853 | const base_address = text_segment.inner.vmaddr; |
| 5870 | | 5854 | |
| ... | @@ -5957,10 +5941,13 @@ fn writeDyldInfoData(self: *MachO) !void { | ... | @@ -5957,10 +5941,13 @@ fn writeDyldInfoData(self: *MachO) !void { |
| 5957 | } | 5941 | } |
| 5958 | | 5942 | |
| 5959 | fn populateLazyBindOffsetsInStubHelper(self: *MachO, buffer: []const u8) !void { | 5943 | fn populateLazyBindOffsetsInStubHelper(self: *MachO, buffer: []const u8) !void { |
| | 5944 | const text_segment_cmd_index = self.text_segment_cmd_index orelse return; |
| | 5945 | const stub_helper_section_index = self.stub_helper_section_index orelse return; |
| 5960 | const last_atom = self.atoms.get(.{ | 5946 | const last_atom = self.atoms.get(.{ |
| 5961 | .seg = self.text_segment_cmd_index.?, | 5947 | .seg = text_segment_cmd_index, |
| 5962 | .sect = self.stub_helper_section_index.?, | 5948 | .sect = stub_helper_section_index, |
| 5963 | }) orelse return; | 5949 | }) orelse return; |
| | 5950 | if (self.stub_helper_preamble_atom == null) return; |
| 5964 | if (last_atom == self.stub_helper_preamble_atom.?) return; | 5951 | if (last_atom == self.stub_helper_preamble_atom.?) return; |
| 5965 | | 5952 | |
| 5966 | var table = std.AutoHashMap(i64, *Atom).init(self.base.allocator); | 5953 | var table = std.AutoHashMap(i64, *Atom).init(self.base.allocator); |
| ... | @@ -6036,8 +6023,8 @@ fn populateLazyBindOffsetsInStubHelper(self: *MachO, buffer: []const u8) !void { | ... | @@ -6036,8 +6023,8 @@ fn populateLazyBindOffsetsInStubHelper(self: *MachO, buffer: []const u8) !void { |
| 6036 | } | 6023 | } |
| 6037 | | 6024 | |
| 6038 | const sect = blk: { | 6025 | const sect = blk: { |
| 6039 | const seg = self.load_commands.items[self.text_segment_cmd_index.?].segment; | 6026 | const seg = self.load_commands.items[text_segment_cmd_index].segment; |
| 6040 | break :blk seg.sections.items[self.stub_helper_section_index.?]; | 6027 | break :blk seg.sections.items[stub_helper_section_index]; |
| 6041 | }; | 6028 | }; |
| 6042 | const stub_offset: u4 = switch (self.base.options.target.cpu.arch) { | 6029 | const stub_offset: u4 = switch (self.base.options.target.cpu.arch) { |
| 6043 | .x86_64 => 1, | 6030 | .x86_64 => 1, |
| ... | @@ -6326,15 +6313,8 @@ fn writeSymbolTable(self: *MachO) !void { | ... | @@ -6326,15 +6313,8 @@ fn writeSymbolTable(self: *MachO) !void { |
| 6326 | dysymtab.iundefsym = dysymtab.nlocalsym + dysymtab.nextdefsym; | 6313 | dysymtab.iundefsym = dysymtab.nlocalsym + dysymtab.nextdefsym; |
| 6327 | dysymtab.nundefsym = @intCast(u32, nundefs); | 6314 | dysymtab.nundefsym = @intCast(u32, nundefs); |
| 6328 | | 6315 | |
| 6329 | const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].segment; | 6316 | const nstubs = @intCast(u32, self.stubs_table.count()); |
| 6330 | const stubs = &text_segment.sections.items[self.stubs_section_index.?]; | 6317 | const ngot_entries = @intCast(u32, self.got_entries_table.count()); |
| 6331 | const data_const_segment = &self.load_commands.items[self.data_const_segment_cmd_index.?].segment; | | |
| 6332 | const got = &data_const_segment.sections.items[self.got_section_index.?]; | | |
| 6333 | const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].segment; | | |
| 6334 | const la_symbol_ptr = &data_segment.sections.items[self.la_symbol_ptr_section_index.?]; | | |
| 6335 | | | |
| 6336 | const nstubs = @intCast(u32, self.stubs_table.keys().len); | | |
| 6337 | const ngot_entries = @intCast(u32, self.got_entries_table.keys().len); | | |
| 6338 | | 6318 | |
| 6339 | const indirectsymoff = mem.alignForwardGeneric(u64, seg.inner.fileoff + seg.inner.filesize, @alignOf(u64)); | 6319 | const indirectsymoff = mem.alignForwardGeneric(u64, seg.inner.fileoff + seg.inner.filesize, @alignOf(u64)); |
| 6340 | dysymtab.indirectsymoff = @intCast(u32, indirectsymoff); | 6320 | dysymtab.indirectsymoff = @intCast(u32, indirectsymoff); |
| ... | @@ -6352,35 +6332,50 @@ fn writeSymbolTable(self: *MachO) !void { | ... | @@ -6352,35 +6332,50 @@ fn writeSymbolTable(self: *MachO) !void { |
| 6352 | try buf.ensureTotalCapacity(dysymtab.nindirectsyms * @sizeOf(u32)); | 6332 | try buf.ensureTotalCapacity(dysymtab.nindirectsyms * @sizeOf(u32)); |
| 6353 | const writer = buf.writer(); | 6333 | const writer = buf.writer(); |
| 6354 | | 6334 | |
| 6355 | stubs.reserved1 = 0; | 6335 | if (self.text_segment_cmd_index) |text_segment_cmd_index| blk: { |
| 6356 | for (self.stubs_table.keys()) |key| { | 6336 | const stubs_section_index = self.stubs_section_index orelse break :blk; |
| 6357 | const resolv = self.symbol_resolver.get(key).?; | 6337 | const text_segment = &self.load_commands.items[text_segment_cmd_index].segment; |
| 6358 | switch (resolv.where) { | 6338 | const stubs = &text_segment.sections.items[stubs_section_index]; |
| 6359 | .global => try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL), | 6339 | stubs.reserved1 = 0; |
| 6360 | .undef => try writer.writeIntLittle(u32, dysymtab.iundefsym + undefs_table.get(resolv.where_index).?), | 6340 | for (self.stubs_table.keys()) |key| { |
| | 6341 | const resolv = self.symbol_resolver.get(key).?; |
| | 6342 | switch (resolv.where) { |
| | 6343 | .global => try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL), |
| | 6344 | .undef => try writer.writeIntLittle(u32, dysymtab.iundefsym + undefs_table.get(resolv.where_index).?), |
| | 6345 | } |
| 6361 | } | 6346 | } |
| 6362 | } | 6347 | } |
| 6363 | | 6348 | |
| 6364 | got.reserved1 = nstubs; | 6349 | if (self.data_const_segment_cmd_index) |data_const_segment_cmd_index| blk: { |
| 6365 | for (self.got_entries_table.keys()) |key| { | 6350 | const got_section_index = self.got_section_index orelse break :blk; |
| 6366 | switch (key) { | 6351 | const data_const_segment = &self.load_commands.items[data_const_segment_cmd_index].segment; |
| 6367 | .local => try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL), | 6352 | const got = &data_const_segment.sections.items[got_section_index]; |
| 6368 | .global => |n_strx| { | 6353 | got.reserved1 = nstubs; |
| 6369 | const resolv = self.symbol_resolver.get(n_strx).?; | 6354 | for (self.got_entries_table.keys()) |key| { |
| 6370 | switch (resolv.where) { | 6355 | switch (key) { |
| 6371 | .global => try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL), | 6356 | .local => try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL), |
| 6372 | .undef => try writer.writeIntLittle(u32, dysymtab.iundefsym + undefs_table.get(resolv.where_index).?), | 6357 | .global => |n_strx| { |
| 6373 | } | 6358 | const resolv = self.symbol_resolver.get(n_strx).?; |
| 6374 | }, | 6359 | switch (resolv.where) { |
| | 6360 | .global => try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL), |
| | 6361 | .undef => try writer.writeIntLittle(u32, dysymtab.iundefsym + undefs_table.get(resolv.where_index).?), |
| | 6362 | } |
| | 6363 | }, |
| | 6364 | } |
| 6375 | } | 6365 | } |
| 6376 | } | 6366 | } |
| 6377 | | 6367 | |
| 6378 | la_symbol_ptr.reserved1 = got.reserved1 + ngot_entries; | 6368 | if (self.data_segment_cmd_index) |data_segment_cmd_index| blk: { |
| 6379 | for (self.stubs_table.keys()) |key| { | 6369 | const la_symbol_ptr_section_index = self.la_symbol_ptr_section_index orelse break :blk; |
| 6380 | const resolv = self.symbol_resolver.get(key).?; | 6370 | const data_segment = &self.load_commands.items[data_segment_cmd_index].segment; |
| 6381 | switch (resolv.where) { | 6371 | const la_symbol_ptr = &data_segment.sections.items[la_symbol_ptr_section_index]; |
| 6382 | .global => try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL), | 6372 | la_symbol_ptr.reserved1 = nstubs + ngot_entries; |
| 6383 | .undef => try writer.writeIntLittle(u32, dysymtab.iundefsym + undefs_table.get(resolv.where_index).?), | 6373 | for (self.stubs_table.keys()) |key| { |
| | 6374 | const resolv = self.symbol_resolver.get(key).?; |
| | 6375 | switch (resolv.where) { |
| | 6376 | .global => try writer.writeIntLittle(u32, macho.INDIRECT_SYMBOL_LOCAL), |
| | 6377 | .undef => try writer.writeIntLittle(u32, dysymtab.iundefsym + undefs_table.get(resolv.where_index).?), |
| | 6378 | } |
| 6384 | } | 6379 | } |
| 6385 | } | 6380 | } |
| 6386 | | 6381 | |
| ... | @@ -6452,15 +6447,16 @@ fn writeCodeSignature(self: *MachO, code_sig: *CodeSignature) !void { | ... | @@ -6452,15 +6447,16 @@ fn writeCodeSignature(self: *MachO, code_sig: *CodeSignature) !void { |
| 6452 | const tracy = trace(@src()); | 6447 | const tracy = trace(@src()); |
| 6453 | defer tracy.end(); | 6448 | defer tracy.end(); |
| 6454 | | 6449 | |
| 6455 | const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].segment; | | |
| 6456 | const code_sig_cmd = self.load_commands.items[self.code_signature_cmd_index.?].linkedit_data; | 6450 | const code_sig_cmd = self.load_commands.items[self.code_signature_cmd_index.?].linkedit_data; |
| | 6451 | const seg = self.load_commands.items[self.text_segment_cmd_index.?].segment; |
| 6457 | | 6452 | |
| 6458 | var buffer = std.ArrayList(u8).init(self.base.allocator); | 6453 | var buffer = std.ArrayList(u8).init(self.base.allocator); |
| 6459 | defer buffer.deinit(); | 6454 | defer buffer.deinit(); |
| 6460 | try buffer.ensureTotalCapacityPrecise(code_sig.size()); | 6455 | try buffer.ensureTotalCapacityPrecise(code_sig.size()); |
| 6461 | try code_sig.writeAdhocSignature(self.base.allocator, .{ | 6456 | try code_sig.writeAdhocSignature(self.base.allocator, .{ |
| 6462 | .file = self.base.file.?, | 6457 | .file = self.base.file.?, |
| 6463 | .text_segment = text_segment.inner, | 6458 | .exec_seg_base = seg.inner.fileoff, |
| | 6459 | .exec_seg_limit = seg.inner.filesize, |
| 6464 | .code_sig_cmd = code_sig_cmd, | 6460 | .code_sig_cmd = code_sig_cmd, |
| 6465 | .output_mode = self.base.options.output_mode, | 6461 | .output_mode = self.base.options.output_mode, |
| 6466 | }, buffer.writer()); | 6462 | }, buffer.writer()); |
| ... | @@ -6480,6 +6476,7 @@ fn writeLoadCommands(self: *MachO) !void { | ... | @@ -6480,6 +6476,7 @@ fn writeLoadCommands(self: *MachO) !void { |
| 6480 | | 6476 | |
| 6481 | var sizeofcmds: u32 = 0; | 6477 | var sizeofcmds: u32 = 0; |
| 6482 | for (self.load_commands.items) |lc| { | 6478 | for (self.load_commands.items) |lc| { |
| | 6479 | if (lc.cmd() == .NONE) continue; |
| 6483 | sizeofcmds += lc.cmdsize(); | 6480 | sizeofcmds += lc.cmdsize(); |
| 6484 | } | 6481 | } |
| 6485 | | 6482 | |
| ... | @@ -6488,12 +6485,13 @@ fn writeLoadCommands(self: *MachO) !void { | ... | @@ -6488,12 +6485,13 @@ fn writeLoadCommands(self: *MachO) !void { |
| 6488 | var fib = std.io.fixedBufferStream(buffer); | 6485 | var fib = std.io.fixedBufferStream(buffer); |
| 6489 | const writer = fib.writer(); | 6486 | const writer = fib.writer(); |
| 6490 | for (self.load_commands.items) |lc| { | 6487 | for (self.load_commands.items) |lc| { |
| | 6488 | if (lc.cmd() == .NONE) continue; |
| 6491 | try lc.write(writer); | 6489 | try lc.write(writer); |
| 6492 | } | 6490 | } |
| 6493 | | 6491 | |
| 6494 | const off = @sizeOf(macho.mach_header_64); | 6492 | const off = @sizeOf(macho.mach_header_64); |
| 6495 | | 6493 | |
| 6496 | log.debug("writing {} load commands from 0x{x} to 0x{x}", .{ self.load_commands.items.len, off, off + sizeofcmds }); | 6494 | log.debug("writing load commands from 0x{x} to 0x{x}", .{ off, off + sizeofcmds }); |
| 6497 | | 6495 | |
| 6498 | try self.base.file.?.pwriteAll(buffer, off); | 6496 | try self.base.file.?.pwriteAll(buffer, off); |
| 6499 | self.load_commands_dirty = false; | 6497 | self.load_commands_dirty = false; |
| ... | @@ -6532,11 +6530,13 @@ fn writeHeader(self: *MachO) !void { | ... | @@ -6532,11 +6530,13 @@ fn writeHeader(self: *MachO) !void { |
| 6532 | header.flags |= macho.MH_HAS_TLV_DESCRIPTORS; | 6530 | header.flags |= macho.MH_HAS_TLV_DESCRIPTORS; |
| 6533 | } | 6531 | } |
| 6534 | | 6532 | |
| 6535 | header.ncmds = @intCast(u32, self.load_commands.items.len); | 6533 | header.ncmds = 0; |
| 6536 | header.sizeofcmds = 0; | 6534 | header.sizeofcmds = 0; |
| 6537 | | 6535 | |
| 6538 | for (self.load_commands.items) |cmd| { | 6536 | for (self.load_commands.items) |cmd| { |
| | 6537 | if (cmd.cmd() == .NONE) continue; |
| 6539 | header.sizeofcmds += cmd.cmdsize(); | 6538 | header.sizeofcmds += cmd.cmdsize(); |
| | 6539 | header.ncmds += 1; |
| 6540 | } | 6540 | } |
| 6541 | | 6541 | |
| 6542 | log.debug("writing Mach-O header {}", .{header}); | 6542 | log.debug("writing Mach-O header {}", .{header}); |