authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-09-10 20:41:30+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2022-09-18 10:00:04+02:00
log34f9360ea20228b895df10b3950c72f40efb6843
tree0dfb9df04eedb71ea15d425a968da523598fb4ef
parente5da251635bb24d418dbec4385aa2319c7f75247

macho: do not call populateMissingMetadata in full link mode


4 files changed, 357 insertions(+), 305 deletions(-)

src/link/MachO.zig+239-299
...@@ -304,13 +304,9 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {...@@ -304,13 +304,9 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO {
304 errdefer file.close();304 errdefer file.close();
305 self.base.file = file;305 self.base.file = file;
306306
307 if (!options.strip and options.module != null) blk: {307 if (self.mode == .one_shot) return self;
308 // TODO once I add support for converting (and relocating) DWARF info from relocatable
309 // object files, this check becomes unnecessary.
310 // For now, for LLVM backend we fallback to the old-fashioned stabs approach used by
311 // stage1.
312 if (build_options.have_llvm and options.use_llvm) break :blk;
313308
309 if (!options.strip and options.module != null) {
314 // Create dSYM bundle.310 // Create dSYM bundle.
315 const dir = options.module.?.zig_cache_artifact_directory;311 const dir = options.module.?.zig_cache_artifact_directory;
316 log.debug("creating {s}.dSYM bundle in {?s}", .{ emit.sub_path, dir.path });312 log.debug("creating {s}.dSYM bundle in {?s}", .{ emit.sub_path, dir.path });
...@@ -1038,30 +1034,32 @@ pub fn parseDependentLibs(self: *MachO, syslibroot: ?[]const u8, dependent_libs:...@@ -1038,30 +1034,32 @@ pub fn parseDependentLibs(self: *MachO, syslibroot: ?[]const u8, dependent_libs:
1038 }1034 }
1039}1035}
10401036
1041pub fn getOutputSection(self: *MachO, sect: macho.section_64) !?u8 {1037const GetOutputSectionResult = struct {
1038 found_existing: bool,
1039 sect_id: u8,
1040};
1041
1042pub fn getOutputSection(self: *MachO, sect: macho.section_64) !?GetOutputSectionResult {
1042 const segname = sect.segName();1043 const segname = sect.segName();
1043 const sectname = sect.sectName();1044 const sectname = sect.sectName();
1044 const res: ?u8 = blk: {1045
1046 var found_existing: bool = true;
1047 const sect_id: u8 = blk: {
1045 if (mem.eql(u8, "__LLVM", segname)) {1048 if (mem.eql(u8, "__LLVM", segname)) {
1046 log.debug("TODO LLVM section: type 0x{x}, name '{s},{s}'", .{1049 log.debug("TODO LLVM section: type 0x{x}, name '{s},{s}'", .{
1047 sect.flags, segname, sectname,1050 sect.flags, segname, sectname,
1048 });1051 });
1049 break :blk null;1052 return null;
1050 }1053 }
10511054
1052 if (sect.isCode()) {1055 if (sect.isCode()) {
1053 if (self.text_section_index == null) {1056 if (self.text_section_index == null) {
1054 self.text_section_index = try self.initSection(1057 self.text_section_index = try self.initSection("__TEXT", "__text", .{
1055 "__TEXT",1058 .flags = macho.S_REGULAR |
1056 "__text",1059 macho.S_ATTR_PURE_INSTRUCTIONS |
1057 sect.size,1060 macho.S_ATTR_SOME_INSTRUCTIONS,
1058 sect.@"align",1061 });
1059 .{1062 found_existing = false;
1060 .flags = macho.S_REGULAR |
1061 macho.S_ATTR_PURE_INSTRUCTIONS |
1062 macho.S_ATTR_SOME_INSTRUCTIONS,
1063 },
1064 );
1065 }1063 }
1066 break :blk self.text_section_index.?;1064 break :blk self.text_section_index.?;
1067 }1065 }
...@@ -1073,7 +1071,7 @@ pub fn getOutputSection(self: *MachO, sect: macho.section_64) !?u8 {...@@ -1073,7 +1071,7 @@ pub fn getOutputSection(self: *MachO, sect: macho.section_64) !?u8 {
1073 sect.flags, segname, sectname,1071 sect.flags, segname, sectname,
1074 });1072 });
1075 }1073 }
1076 break :blk null;1074 return null;
1077 }1075 }
10781076
1079 switch (sect.@"type"()) {1077 switch (sect.@"type"()) {
...@@ -1081,42 +1079,30 @@ pub fn getOutputSection(self: *MachO, sect: macho.section_64) !?u8 {...@@ -1081,42 +1079,30 @@ pub fn getOutputSection(self: *MachO, sect: macho.section_64) !?u8 {
1081 macho.S_8BYTE_LITERALS,1079 macho.S_8BYTE_LITERALS,
1082 macho.S_16BYTE_LITERALS,1080 macho.S_16BYTE_LITERALS,
1083 => {1081 => {
1084 break :blk self.getSectionByName("__TEXT", "__const") orelse try self.initSection(1082 if (self.getSectionByName("__TEXT", "__const")) |sect_id| break :blk sect_id;
1085 "__TEXT",1083 found_existing = false;
1086 "__const",1084 break :blk try self.initSection("__TEXT", "__const", .{});
1087 sect.size,
1088 sect.@"align",
1089 .{},
1090 );
1091 },1085 },
1092 macho.S_CSTRING_LITERALS => {1086 macho.S_CSTRING_LITERALS => {
1093 if (mem.startsWith(u8, sectname, "__objc")) {1087 if (mem.startsWith(u8, sectname, "__objc")) {
1094 break :blk self.getSectionByName(segname, sectname) orelse try self.initSection(1088 if (self.getSectionByName(segname, sectname)) |sect_id| break :blk sect_id;
1095 segname,1089 found_existing = false;
1096 sectname,1090 break :blk try self.initSection(segname, sectname, .{});
1097 sect.size,
1098 sect.@"align",
1099 .{},
1100 );
1101 }1091 }
1102 break :blk self.getSectionByName("__TEXT", "__cstring") orelse try self.initSection(1092 if (self.getSectionByName("__TEXT", "__cstring")) |sect_id| break :blk sect_id;
1103 "__TEXT",1093 found_existing = false;
1104 "__cstring",1094 break :blk try self.initSection("__TEXT", "__cstring", .{
1105 sect.size,1095 .flags = macho.S_CSTRING_LITERALS,
1106 sect.@"align",1096 });
1107 .{ .flags = macho.S_CSTRING_LITERALS },
1108 );
1109 },1097 },
1110 macho.S_MOD_INIT_FUNC_POINTERS,1098 macho.S_MOD_INIT_FUNC_POINTERS,
1111 macho.S_MOD_TERM_FUNC_POINTERS,1099 macho.S_MOD_TERM_FUNC_POINTERS,
1112 => {1100 => {
1113 break :blk self.getSectionByName("__DATA_CONST", sectname) orelse try self.initSection(1101 if (self.getSectionByName("__DATA_CONST", sectname)) |sect_id| break :blk sect_id;
1114 "__DATA_CONST",1102 found_existing = false;
1115 sectname,1103 break :blk try self.initSection("__DATA_CONST", sectname, .{
1116 sect.size,1104 .flags = sect.flags,
1117 sect.@"align",1105 });
1118 .{ .flags = sect.flags },
1119 );
1120 },1106 },
1121 macho.S_LITERAL_POINTERS,1107 macho.S_LITERAL_POINTERS,
1122 macho.S_ZEROFILL,1108 macho.S_ZEROFILL,
...@@ -1125,22 +1111,14 @@ pub fn getOutputSection(self: *MachO, sect: macho.section_64) !?u8 {...@@ -1125,22 +1111,14 @@ pub fn getOutputSection(self: *MachO, sect: macho.section_64) !?u8 {
1125 macho.S_THREAD_LOCAL_REGULAR,1111 macho.S_THREAD_LOCAL_REGULAR,
1126 macho.S_THREAD_LOCAL_ZEROFILL,1112 macho.S_THREAD_LOCAL_ZEROFILL,
1127 => {1113 => {
1128 break :blk self.getSectionByName(segname, sectname) orelse try self.initSection(1114 if (self.getSectionByName(segname, sectname)) |sect_id| break :blk sect_id;
1129 segname,1115 found_existing = false;
1130 sectname,1116 break :blk try self.initSection(segname, sectname, .{ .flags = sect.flags });
1131 sect.size,
1132 sect.@"align",
1133 .{ .flags = sect.flags },
1134 );
1135 },1117 },
1136 macho.S_COALESCED => {1118 macho.S_COALESCED => {
1137 break :blk self.getSectionByName(segname, sectname) orelse try self.initSection(1119 if (self.getSectionByName(segname, sectname)) |sect_id| break :blk sect_id;
1138 segname,1120 found_existing = false;
1139 sectname,1121 break :blk try self.initSection(segname, sectname, .{});
1140 sect.size,
1141 sect.@"align",
1142 .{},
1143 );
1144 },1122 },
1145 macho.S_REGULAR => {1123 macho.S_REGULAR => {
1146 if (mem.eql(u8, segname, "__TEXT")) {1124 if (mem.eql(u8, segname, "__TEXT")) {
...@@ -1150,13 +1128,9 @@ pub fn getOutputSection(self: *MachO, sect: macho.section_64) !?u8 {...@@ -1150,13 +1128,9 @@ pub fn getOutputSection(self: *MachO, sect: macho.section_64) !?u8 {
1150 mem.eql(u8, sectname, "__gosymtab") or1128 mem.eql(u8, sectname, "__gosymtab") or
1151 mem.eql(u8, sectname, "__gopclntab"))1129 mem.eql(u8, sectname, "__gopclntab"))
1152 {1130 {
1153 break :blk self.getSectionByName("__DATA_CONST", "__const") orelse try self.initSection(1131 if (self.getSectionByName("__DATA_CONST", "__const")) |sect_id| break :blk sect_id;
1154 "__DATA_CONST",1132 found_existing = false;
1155 "__const",1133 break :blk try self.initSection("__DATA_CONST", "__const", .{});
1156 sect.size,
1157 sect.@"align",
1158 .{},
1159 );
1160 }1134 }
1161 }1135 }
1162 if (mem.eql(u8, segname, "__DATA")) {1136 if (mem.eql(u8, segname, "__DATA")) {
...@@ -1165,39 +1139,29 @@ pub fn getOutputSection(self: *MachO, sect: macho.section_64) !?u8 {...@@ -1165,39 +1139,29 @@ pub fn getOutputSection(self: *MachO, sect: macho.section_64) !?u8 {
1165 mem.eql(u8, sectname, "__objc_classlist") or1139 mem.eql(u8, sectname, "__objc_classlist") or
1166 mem.eql(u8, sectname, "__objc_imageinfo"))1140 mem.eql(u8, sectname, "__objc_imageinfo"))
1167 {1141 {
1168 break :blk self.getSectionByName("__DATA_CONST", sectname) orelse1142 if (self.getSectionByName("__DATA_CONST", sectname)) |sect_id| break :blk sect_id;
1169 try self.initSection(1143 found_existing = false;
1170 "__DATA_CONST",1144 break :blk try self.initSection("__DATA_CONST", sectname, .{});
1171 sectname,
1172 sect.size,
1173 sect.@"align",
1174 .{},
1175 );
1176 } else if (mem.eql(u8, sectname, "__data")) {1145 } else if (mem.eql(u8, sectname, "__data")) {
1177 if (self.data_section_index == null) {1146 if (self.data_section_index == null) {
1178 self.data_section_index = try self.initSection(1147 self.data_section_index = try self.initSection(segname, sectname, .{});
1179 segname,1148 found_existing = false;
1180 sectname,
1181 sect.size,
1182 sect.@"align",
1183 .{},
1184 );
1185 }1149 }
1186 break :blk self.data_section_index.?;1150 break :blk self.data_section_index.?;
1187 }1151 }
1188 }1152 }
1189 break :blk self.getSectionByName(segname, sectname) orelse try self.initSection(1153 if (self.getSectionByName(segname, sectname)) |sect_id| break :blk sect_id;
1190 segname,1154 found_existing = false;
1191 sectname,1155 break :blk try self.initSection(segname, sectname, .{});
1192 sect.size,
1193 sect.@"align",
1194 .{},
1195 );
1196 },1156 },
1197 else => break :blk null,1157 else => return null,
1198 }1158 }
1199 };1159 };
1200 return res;1160
1161 return GetOutputSectionResult{
1162 .found_existing = found_existing,
1163 .sect_id = sect_id,
1164 };
1201}1165}
12021166
1203pub fn createEmptyAtom(gpa: Allocator, sym_index: u32, size: u64, alignment: u32) !*Atom {1167pub fn createEmptyAtom(gpa: Allocator, sym_index: u32, size: u64, alignment: u32) !*Atom {
...@@ -1399,12 +1363,17 @@ pub fn createTlvPtrAtom(self: *MachO, target: SymbolWithLoc) !*Atom {...@@ -1399,12 +1363,17 @@ pub fn createTlvPtrAtom(self: *MachO, target: SymbolWithLoc) !*Atom {
13991363
1400 const sym = atom.getSymbolPtr(self);1364 const sym = atom.getSymbolPtr(self);
1401 sym.n_type = macho.N_SECT;1365 sym.n_type = macho.N_SECT;
1402 const sect_id = (try self.getOutputSection(.{1366 const gop = (try self.getOutputSection(.{
1403 .segname = makeStaticString("__DATA"),1367 .segname = makeStaticString("__DATA"),
1404 .sectname = makeStaticString("__thread_ptrs"),1368 .sectname = makeStaticString("__thread_ptrs"),
1405 .flags = macho.S_THREAD_LOCAL_VARIABLE_POINTERS,1369 .flags = macho.S_THREAD_LOCAL_VARIABLE_POINTERS,
1406 })).?;1370 })).?;
1407 sym.n_sect = sect_id + 1;1371 if (self.mode == .incremental and !gop.found_existing) {
1372 // TODO allocate section
1373 const needed_size: u64 = self.page_size;
1374 try self.allocateSection(gop.sect_id, needed_size, @alignOf(u64));
1375 }
1376 sym.n_sect = gop.sect_id + 1;
14081377
1409 try self.allocateAtomCommon(atom);1378 try self.allocateAtomCommon(atom);
14101379
...@@ -1754,16 +1723,20 @@ pub fn createTentativeDefAtoms(self: *MachO) !void {...@@ -1754,16 +1723,20 @@ pub fn createTentativeDefAtoms(self: *MachO) !void {
1754 // text blocks for each tentative definition.1723 // text blocks for each tentative definition.
1755 const size = sym.n_value;1724 const size = sym.n_value;
1756 const alignment = (sym.n_desc >> 8) & 0x0f;1725 const alignment = (sym.n_desc >> 8) & 0x0f;
1757 const n_sect = (try self.getOutputSection(.{1726 const gop = (try self.getOutputSection(.{
1758 .segname = makeStaticString("__DATA"),1727 .segname = makeStaticString("__DATA"),
1759 .sectname = makeStaticString("__bss"),1728 .sectname = makeStaticString("__bss"),
1760 .flags = macho.S_ZEROFILL,1729 .flags = macho.S_ZEROFILL,
1761 })).?;1730 })).?;
1731 if (self.mode == .incremental and !gop.found_existing) {
1732 // TODO allocate section
1733 try self.allocateSection(gop.sect_id, size, alignment);
1734 }
17621735
1763 sym.* = .{1736 sym.* = .{
1764 .n_strx = sym.n_strx,1737 .n_strx = sym.n_strx,
1765 .n_type = macho.N_SECT | macho.N_EXT,1738 .n_type = macho.N_SECT | macho.N_EXT,
1766 .n_sect = n_sect,1739 .n_sect = gop.sect_id,
1767 .n_desc = 0,1740 .n_desc = 0,
1768 .n_value = 0,1741 .n_value = 0,
1769 };1742 };
...@@ -2883,16 +2856,19 @@ fn getOutputSectionAtom(...@@ -2883,16 +2856,19 @@ fn getOutputSectionAtom(
2883 const align_log_2 = math.log2(alignment);2856 const align_log_2 = math.log2(alignment);
2884 const zig_ty = ty.zigTypeTag();2857 const zig_ty = ty.zigTypeTag();
2885 const mode = self.base.options.optimize_mode;2858 const mode = self.base.options.optimize_mode;
2859
2886 const sect_id: u8 = blk: {2860 const sect_id: u8 = blk: {
2887 // TODO finish and audit this function2861 // TODO finish and audit this function
2888 if (val.isUndefDeep()) {2862 if (val.isUndefDeep()) {
2889 if (mode == .ReleaseFast or mode == .ReleaseSmall) {2863 if (mode == .ReleaseFast or mode == .ReleaseSmall) {
2890 break :blk (try self.getOutputSection(.{2864 const gop = (try self.getOutputSection(.{
2891 .segname = makeStaticString("__DATA"),2865 .segname = makeStaticString("__DATA"),
2892 .sectname = makeStaticString("__bss"),2866 .sectname = makeStaticString("__bss"),
2893 .size = code.len,
2894 .@"align" = align_log_2,
2895 })).?;2867 })).?;
2868 if (!gop.found_existing) {
2869 try self.allocateSection(gop.sect_id, code.len, align_log_2);
2870 }
2871 break :blk gop.sect_id;
2896 } else {2872 } else {
2897 break :blk self.data_section_index.?;2873 break :blk self.data_section_index.?;
2898 }2874 }
...@@ -2903,12 +2879,14 @@ fn getOutputSectionAtom(...@@ -2903,12 +2879,14 @@ fn getOutputSectionAtom(
2903 }2879 }
29042880
2905 if (needsPointerRebase(ty, val, mod)) {2881 if (needsPointerRebase(ty, val, mod)) {
2906 break :blk (try self.getOutputSection(.{2882 const gop = (try self.getOutputSection(.{
2907 .segname = makeStaticString("__DATA_CONST"),2883 .segname = makeStaticString("__DATA_CONST"),
2908 .sectname = makeStaticString("__const"),2884 .sectname = makeStaticString("__const"),
2909 .size = code.len,
2910 .@"align" = align_log_2,
2911 })).?;2885 })).?;
2886 if (!gop.found_existing) {
2887 try self.allocateSection(gop.sect_id, code.len, align_log_2);
2888 }
2889 break :blk gop.sect_id;
2912 }2890 }
29132891
2914 switch (zig_ty) {2892 switch (zig_ty) {
...@@ -2922,13 +2900,15 @@ fn getOutputSectionAtom(...@@ -2922,13 +2900,15 @@ fn getOutputSectionAtom(
2922 .const_slice_u8_sentinel_0,2900 .const_slice_u8_sentinel_0,
2923 .manyptr_const_u8_sentinel_0,2901 .manyptr_const_u8_sentinel_0,
2924 => {2902 => {
2925 break :blk (try self.getOutputSection(.{2903 const gop = (try self.getOutputSection(.{
2926 .segname = makeStaticString("__TEXT"),2904 .segname = makeStaticString("__TEXT"),
2927 .sectname = makeStaticString("__cstring"),2905 .sectname = makeStaticString("__cstring"),
2928 .flags = macho.S_CSTRING_LITERALS,2906 .flags = macho.S_CSTRING_LITERALS,
2929 .size = code.len,
2930 .@"align" = align_log_2,
2931 })).?;2907 })).?;
2908 if (!gop.found_existing) {
2909 try self.allocateSection(gop.sect_id, code.len, align_log_2);
2910 }
2911 break :blk gop.sect_id;
2932 },2912 },
2933 else => {},2913 else => {},
2934 }2914 }
...@@ -2936,13 +2916,16 @@ fn getOutputSectionAtom(...@@ -2936,13 +2916,16 @@ fn getOutputSectionAtom(
2936 },2916 },
2937 else => {},2917 else => {},
2938 }2918 }
2939 break :blk (try self.getOutputSection(.{2919 const gop = (try self.getOutputSection(.{
2940 .segname = makeStaticString("__TEXT"),2920 .segname = makeStaticString("__TEXT"),
2941 .sectname = makeStaticString("__const"),2921 .sectname = makeStaticString("__const"),
2942 .size = code.len,
2943 .@"align" = align_log_2,
2944 })).?;2922 })).?;
2923 if (!gop.found_existing) {
2924 try self.allocateSection(gop.sect_id, code.len, align_log_2);
2925 }
2926 break :blk gop.sect_id;
2945 };2927 };
2928
2946 const header = self.sections.items(.header)[sect_id];2929 const header = self.sections.items(.header)[sect_id];
2947 log.debug(" allocating atom '{s}' in '{s},{s}', ord({d})", .{2930 log.debug(" allocating atom '{s}' in '{s},{s}', ord({d})", .{
2948 name,2931 name,
...@@ -3255,40 +3238,36 @@ pub fn getDeclVAddr(self: *MachO, decl_index: Module.Decl.Index, reloc_info: Fil...@@ -3255,40 +3238,36 @@ pub fn getDeclVAddr(self: *MachO, decl_index: Module.Decl.Index, reloc_info: Fil
3255}3238}
32563239
3257pub fn populateMissingMetadata(self: *MachO) !void {3240pub fn populateMissingMetadata(self: *MachO) !void {
3241 assert(self.mode == .incremental);
3242
3258 const gpa = self.base.allocator;3243 const gpa = self.base.allocator;
3259 const cpu_arch = self.base.options.target.cpu.arch;3244 const cpu_arch = self.base.options.target.cpu.arch;
3260 const pagezero_vmsize = self.base.options.pagezero_size orelse default_pagezero_vmsize;3245 const pagezero_vmsize = self.calcPagezeroSize();
3261 const aligned_pagezero_vmsize = mem.alignBackwardGeneric(u64, pagezero_vmsize, self.page_size);3246
32623247 if (self.pagezero_segment_cmd_index == null) {
3263 if (self.pagezero_segment_cmd_index == null) blk: {3248 if (pagezero_vmsize > 0) {
3264 if (self.base.options.output_mode == .Lib) break :blk;3249 self.pagezero_segment_cmd_index = @intCast(u8, self.segments.items.len);
3265 if (aligned_pagezero_vmsize == 0) break :blk;3250 try self.segments.append(gpa, .{
3266 if (aligned_pagezero_vmsize != pagezero_vmsize) {3251 .segname = makeStaticString("__PAGEZERO"),
3267 log.warn("requested __PAGEZERO size (0x{x}) is not page aligned", .{pagezero_vmsize});3252 .vmsize = pagezero_vmsize,
3268 log.warn(" rounding down to 0x{x}", .{aligned_pagezero_vmsize});3253 .cmdsize = @sizeOf(macho.segment_command_64),
3254 });
3269 }3255 }
3270 self.pagezero_segment_cmd_index = @intCast(u8, self.segments.items.len);
3271 try self.segments.append(gpa, .{
3272 .segname = makeStaticString("__PAGEZERO"),
3273 .vmsize = aligned_pagezero_vmsize,
3274 .cmdsize = @sizeOf(macho.segment_command_64),
3275 });
3276 }3256 }
32773257
3278 if (self.text_segment_cmd_index == null) {3258 if (self.text_segment_cmd_index == null) {
3279 self.text_segment_cmd_index = @intCast(u8, self.segments.items.len);3259 self.text_segment_cmd_index = @intCast(u8, self.segments.items.len);
3280 const needed_size = if (self.mode == .incremental) blk: {3260 const headerpad_size = @maximum(self.base.options.headerpad_size orelse 0, default_headerpad_size);
3281 const headerpad_size = @maximum(self.base.options.headerpad_size orelse 0, default_headerpad_size);3261 const program_code_size_hint = self.base.options.program_code_size_hint;
3282 const program_code_size_hint = self.base.options.program_code_size_hint;3262 const got_size_hint = @sizeOf(u64) * self.base.options.symbol_count_hint;
3283 const got_size_hint = @sizeOf(u64) * self.base.options.symbol_count_hint;3263 const ideal_size = headerpad_size + program_code_size_hint + got_size_hint;
3284 const ideal_size = headerpad_size + program_code_size_hint + got_size_hint;3264 const needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size);
3285 const needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size);3265
3286 log.debug("found __TEXT segment free space 0x{x} to 0x{x}", .{ 0, needed_size });3266 log.debug("found __TEXT segment free space 0x{x} to 0x{x}", .{ 0, needed_size });
3287 break :blk needed_size;3267
3288 } else 0;
3289 try self.segments.append(gpa, .{3268 try self.segments.append(gpa, .{
3290 .segname = makeStaticString("__TEXT"),3269 .segname = makeStaticString("__TEXT"),
3291 .vmaddr = aligned_pagezero_vmsize,3270 .vmaddr = pagezero_vmsize,
3292 .vmsize = needed_size,3271 .vmsize = needed_size,
3293 .filesize = needed_size,3272 .filesize = needed_size,
3294 .maxprot = macho.PROT.READ | macho.PROT.EXEC,3273 .maxprot = macho.PROT.READ | macho.PROT.EXEC,
...@@ -3303,16 +3282,11 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -3303,16 +3282,11 @@ pub fn populateMissingMetadata(self: *MachO) !void {
3303 .aarch64 => 2,3282 .aarch64 => 2,
3304 else => unreachable, // unhandled architecture type3283 else => unreachable, // unhandled architecture type
3305 };3284 };
3306 const needed_size = if (self.mode == .incremental) self.base.options.program_code_size_hint else 0;3285 const needed_size = self.base.options.program_code_size_hint;
3307 self.text_section_index = try self.initSection(3286 self.text_section_index = try self.initSection("__TEXT", "__text", .{
3308 "__TEXT",3287 .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
3309 "__text",3288 });
3310 needed_size,3289 try self.allocateSection(self.text_section_index.?, needed_size, alignment);
3311 alignment,
3312 .{
3313 .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
3314 },
3315 );
3316 }3290 }
33173291
3318 if (self.stubs_section_index == null) {3292 if (self.stubs_section_index == null) {
...@@ -3326,17 +3300,12 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -3326,17 +3300,12 @@ pub fn populateMissingMetadata(self: *MachO) !void {
3326 .aarch64 => 3 * @sizeOf(u32),3300 .aarch64 => 3 * @sizeOf(u32),
3327 else => unreachable, // unhandled architecture type3301 else => unreachable, // unhandled architecture type
3328 };3302 };
3329 const needed_size = if (self.mode == .incremental) stub_size * self.base.options.symbol_count_hint else 0;3303 const needed_size = stub_size * self.base.options.symbol_count_hint;
3330 self.stubs_section_index = try self.initSection(3304 self.stubs_section_index = try self.initSection("__TEXT", "__stubs", .{
3331 "__TEXT",3305 .flags = macho.S_SYMBOL_STUBS | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
3332 "__stubs",3306 .reserved2 = stub_size,
3333 needed_size,3307 });
3334 alignment,3308 try self.allocateSection(self.stubs_section_index.?, needed_size, alignment);
3335 .{
3336 .flags = macho.S_SYMBOL_STUBS | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
3337 .reserved2 = stub_size,
3338 },
3339 );
3340 }3309 }
33413310
3342 if (self.stub_helper_section_index == null) {3311 if (self.stub_helper_section_index == null) {
...@@ -3355,37 +3324,26 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -3355,37 +3324,26 @@ pub fn populateMissingMetadata(self: *MachO) !void {
3355 .aarch64 => 3 * @sizeOf(u32),3324 .aarch64 => 3 * @sizeOf(u32),
3356 else => unreachable,3325 else => unreachable,
3357 };3326 };
3358 const needed_size = if (self.mode == .incremental)3327 const needed_size = stub_size * self.base.options.symbol_count_hint + preamble_size;
3359 stub_size * self.base.options.symbol_count_hint + preamble_size3328 self.stub_helper_section_index = try self.initSection("__TEXT", "__stub_helper", .{
3360 else3329 .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
3361 0;3330 });
3362 self.stub_helper_section_index = try self.initSection(3331 try self.allocateSection(self.stub_helper_section_index.?, needed_size, alignment);
3363 "__TEXT",
3364 "__stub_helper",
3365 needed_size,
3366 alignment,
3367 .{
3368 .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
3369 },
3370 );
3371 }3332 }
33723333
3373 if (self.data_const_segment_cmd_index == null) {3334 if (self.data_const_segment_cmd_index == null) {
3374 self.data_const_segment_cmd_index = @intCast(u8, self.segments.items.len);3335 self.data_const_segment_cmd_index = @intCast(u8, self.segments.items.len);
3375 var vmaddr: u64 = 0;3336 const base = self.getSegmentAllocBase(&.{self.text_segment_cmd_index.?});
3376 var fileoff: u64 = 0;3337 const vmaddr = base.vmaddr;
3377 var needed_size: u64 = 0;3338 const fileoff = base.fileoff;
3378 if (self.mode == .incremental) {3339 const ideal_size = @sizeOf(u64) * self.base.options.symbol_count_hint;
3379 const base = self.getSegmentAllocBase(&.{self.text_segment_cmd_index.?});3340 const needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size);
3380 vmaddr = base.vmaddr;3341
3381 fileoff = base.fileoff;3342 log.debug("found __DATA_CONST segment free space 0x{x} to 0x{x}", .{
3382 const ideal_size = @sizeOf(u64) * self.base.options.symbol_count_hint;3343 fileoff,
3383 needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size);3344 fileoff + needed_size,
3384 log.debug("found __DATA_CONST segment free space 0x{x} to 0x{x}", .{3345 });
3385 fileoff,3346
3386 fileoff + needed_size,
3387 });
3388 }
3389 try self.segments.append(gpa, .{3347 try self.segments.append(gpa, .{
3390 .segname = makeStaticString("__DATA_CONST"),3348 .segname = makeStaticString("__DATA_CONST"),
3391 .vmaddr = vmaddr,3349 .vmaddr = vmaddr,
...@@ -3399,38 +3357,27 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -3399,38 +3357,27 @@ pub fn populateMissingMetadata(self: *MachO) !void {
3399 }3357 }
34003358
3401 if (self.got_section_index == null) {3359 if (self.got_section_index == null) {
3402 const needed_size = if (self.mode == .incremental)3360 const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint;
3403 @sizeOf(u64) * self.base.options.symbol_count_hint
3404 else
3405 0;
3406 const alignment: u16 = 3; // 2^3 = @sizeOf(u64)3361 const alignment: u16 = 3; // 2^3 = @sizeOf(u64)
3407 self.got_section_index = try self.initSection(3362 self.got_section_index = try self.initSection("__DATA_CONST", "__got", .{
3408 "__DATA_CONST",3363 .flags = macho.S_NON_LAZY_SYMBOL_POINTERS,
3409 "__got",3364 });
3410 needed_size,3365 try self.allocateSection(self.got_section_index.?, needed_size, alignment);
3411 alignment,
3412 .{
3413 .flags = macho.S_NON_LAZY_SYMBOL_POINTERS,
3414 },
3415 );
3416 }3366 }
34173367
3418 if (self.data_segment_cmd_index == null) {3368 if (self.data_segment_cmd_index == null) {
3419 self.data_segment_cmd_index = @intCast(u8, self.segments.items.len);3369 self.data_segment_cmd_index = @intCast(u8, self.segments.items.len);
3420 var vmaddr: u64 = 0;3370 const base = self.getSegmentAllocBase(&.{self.data_const_segment_cmd_index.?});
3421 var fileoff: u64 = 0;3371 const vmaddr = base.vmaddr;
3422 var needed_size: u64 = 0;3372 const fileoff = base.fileoff;
3423 if (self.mode == .incremental) {3373 const ideal_size = 2 * @sizeOf(u64) * self.base.options.symbol_count_hint;
3424 const base = self.getSegmentAllocBase(&.{self.data_const_segment_cmd_index.?});3374 const needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size);
3425 vmaddr = base.vmaddr;3375
3426 fileoff = base.fileoff;3376 log.debug("found __DATA segment free space 0x{x} to 0x{x}", .{
3427 const ideal_size = 2 * @sizeOf(u64) * self.base.options.symbol_count_hint;3377 fileoff,
3428 needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size);3378 fileoff + needed_size,
3429 log.debug("found __DATA segment free space 0x{x} to 0x{x}", .{3379 });
3430 fileoff,3380
3431 fileoff + needed_size,
3432 });
3433 }
3434 try self.segments.append(gpa, .{3381 try self.segments.append(gpa, .{
3435 .segname = makeStaticString("__DATA"),3382 .segname = makeStaticString("__DATA"),
3436 .vmaddr = vmaddr,3383 .vmaddr = vmaddr,
...@@ -3444,47 +3391,29 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -3444,47 +3391,29 @@ pub fn populateMissingMetadata(self: *MachO) !void {
3444 }3391 }
34453392
3446 if (self.la_symbol_ptr_section_index == null) {3393 if (self.la_symbol_ptr_section_index == null) {
3447 const needed_size = if (self.mode == .incremental)3394 const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint;
3448 @sizeOf(u64) * self.base.options.symbol_count_hint
3449 else
3450 0;
3451 const alignment: u16 = 3; // 2^3 = @sizeOf(u64)3395 const alignment: u16 = 3; // 2^3 = @sizeOf(u64)
3452 self.la_symbol_ptr_section_index = try self.initSection(3396 self.la_symbol_ptr_section_index = try self.initSection("__DATA", "__la_symbol_ptr", .{
3453 "__DATA",3397 .flags = macho.S_LAZY_SYMBOL_POINTERS,
3454 "__la_symbol_ptr",3398 });
3455 needed_size,3399 try self.allocateSection(self.la_symbol_ptr_section_index.?, needed_size, alignment);
3456 alignment,
3457 .{
3458 .flags = macho.S_LAZY_SYMBOL_POINTERS,
3459 },
3460 );
3461 }3400 }
34623401
3463 if (self.data_section_index == null) {3402 if (self.data_section_index == null) {
3464 const needed_size = if (self.mode == .incremental)3403 const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint;
3465 @sizeOf(u64) * self.base.options.symbol_count_hint
3466 else
3467 0;
3468 const alignment: u16 = 3; // 2^3 = @sizeOf(u64)3404 const alignment: u16 = 3; // 2^3 = @sizeOf(u64)
3469 self.data_section_index = try self.initSection(3405 self.data_section_index = try self.initSection("__DATA", "__data", .{});
3470 "__DATA",3406 try self.allocateSection(self.data_section_index.?, needed_size, alignment);
3471 "__data",
3472 needed_size,
3473 alignment,
3474 .{},
3475 );
3476 }3407 }
34773408
3478 if (self.linkedit_segment_cmd_index == null) {3409 if (self.linkedit_segment_cmd_index == null) {
3479 self.linkedit_segment_cmd_index = @intCast(u8, self.segments.items.len);3410 self.linkedit_segment_cmd_index = @intCast(u8, self.segments.items.len);
3480 var vmaddr: u64 = 0;3411 const base = self.getSegmentAllocBase(&.{self.data_segment_cmd_index.?});
3481 var fileoff: u64 = 0;3412 const vmaddr = base.vmaddr;
3482 if (self.mode == .incremental) {3413 const fileoff = base.fileoff;
3483 const base = self.getSegmentAllocBase(&.{self.data_segment_cmd_index.?});3414
3484 vmaddr = base.vmaddr;3415 log.debug("found __LINKEDIT segment free space at 0x{x}", .{fileoff});
3485 fileoff = base.fileoff;3416
3486 log.debug("found __LINKEDIT segment free space at 0x{x}", .{fileoff});
3487 }
3488 try self.segments.append(gpa, .{3417 try self.segments.append(gpa, .{
3489 .segname = makeStaticString("__LINKEDIT"),3418 .segname = makeStaticString("__LINKEDIT"),
3490 .vmaddr = vmaddr,3419 .vmaddr = vmaddr,
...@@ -3586,6 +3515,18 @@ fn calcLCsSize(self: *MachO, assume_max_path_len: bool) !u32 {...@@ -3586,6 +3515,18 @@ fn calcLCsSize(self: *MachO, assume_max_path_len: bool) !u32 {
3586 return @intCast(u32, sizeofcmds);3515 return @intCast(u32, sizeofcmds);
3587}3516}
35883517
3518pub fn calcPagezeroSize(self: *MachO) u64 {
3519 const pagezero_vmsize = self.base.options.pagezero_size orelse default_pagezero_vmsize;
3520 const aligned_pagezero_vmsize = mem.alignBackwardGeneric(u64, pagezero_vmsize, self.page_size);
3521 if (self.base.options.output_mode == .Lib) return 0;
3522 if (aligned_pagezero_vmsize == 0) return 0;
3523 if (aligned_pagezero_vmsize != pagezero_vmsize) {
3524 log.warn("requested __PAGEZERO size (0x{x}) is not page aligned", .{pagezero_vmsize});
3525 log.warn(" rounding down to 0x{x}", .{aligned_pagezero_vmsize});
3526 }
3527 return aligned_pagezero_vmsize;
3528}
3529
3589pub fn calcMinHeaderPad(self: *MachO) !u64 {3530pub fn calcMinHeaderPad(self: *MachO) !u64 {
3590 var padding: u32 = (try self.calcLCsSize(false)) + (self.base.options.headerpad_size orelse 0);3531 var padding: u32 = (try self.calcLCsSize(false)) + (self.base.options.headerpad_size orelse 0);
3591 log.debug("minimum requested headerpad size 0x{x}", .{padding + @sizeOf(macho.mach_header_64)});3532 log.debug("minimum requested headerpad size 0x{x}", .{padding + @sizeOf(macho.mach_header_64)});
...@@ -3603,69 +3544,42 @@ pub fn calcMinHeaderPad(self: *MachO) !u64 {...@@ -3603,69 +3544,42 @@ pub fn calcMinHeaderPad(self: *MachO) !u64 {
3603 return offset;3544 return offset;
3604}3545}
36053546
3606const InitSectionOpts = struct {3547fn allocateSection(self: *MachO, sect_id: u8, size: u64, alignment: u32) !void {
3607 flags: u32 = macho.S_REGULAR,3548 const segment_id = self.sections.items(.segment_index)[sect_id];
3608 reserved1: u32 = 0,
3609 reserved2: u32 = 0,
3610};
3611
3612fn initSection(
3613 self: *MachO,
3614 segname: []const u8,
3615 sectname: []const u8,
3616 size: u64,
3617 alignment: u32,
3618 opts: InitSectionOpts,
3619) !u8 {
3620 const segment_id = self.getSegmentByName(segname).?;
3621 const seg = &self.segments.items[segment_id];3549 const seg = &self.segments.items[segment_id];
3622 const index = try self.insertSection(segment_id, .{3550 const header = &self.sections.items(.header)[sect_id];
3623 .sectname = makeStaticString(sectname),3551 header.size = size;
3624 .segname = seg.segname,3552 header.@"align" = alignment;
3625 .flags = opts.flags,3553
3626 .reserved1 = opts.reserved1,3554 const prev_end_off = if (sect_id > 0) blk: {
3627 .reserved2 = opts.reserved2,3555 const prev_section = self.sections.get(sect_id - 1);
3628 });3556 if (prev_section.segment_index == segment_id) {
3629 seg.cmdsize += @sizeOf(macho.section_64);3557 const prev_header = prev_section.header;
3630 seg.nsects += 1;3558 break :blk prev_header.offset + padToIdeal(prev_header.size);
36313559 } else break :blk seg.fileoff;
3632 if (self.mode == .incremental) {3560 } else 0;
3633 const header = &self.sections.items(.header)[index];3561 const alignment_pow_2 = try math.powi(u32, 2, alignment);
3634 header.size = size;3562 // TODO better prealloc for __text section
3635 header.@"align" = alignment;3563 // const padding: u64 = if (sect_id == 0) try self.calcMinHeaderPad() else 0;
36363564 const padding: u64 = if (sect_id == 0) 0x1000 else 0;
3637 const prev_end_off = if (index > 0) blk: {3565 const off = mem.alignForwardGeneric(u64, padding + prev_end_off, alignment_pow_2);
3638 const prev_section = self.sections.get(index - 1);
3639 if (prev_section.segment_index == segment_id) {
3640 const prev_header = prev_section.header;
3641 break :blk prev_header.offset + padToIdeal(prev_header.size);
3642 } else break :blk seg.fileoff;
3643 } else 0;
3644 const alignment_pow_2 = try math.powi(u32, 2, alignment);
3645 // TODO better prealloc for __text section
3646 // const padding: u64 = if (index == 0) try self.calcMinHeaderPad() else 0;
3647 const padding: u64 = if (index == 0) 0x1000 else 0;
3648 const off = mem.alignForwardGeneric(u64, padding + prev_end_off, alignment_pow_2);
3649
3650 if (!header.isZerofill()) {
3651 header.offset = @intCast(u32, off);
3652 }
3653 header.addr = seg.vmaddr + off - seg.fileoff;
3654
3655 // TODO Will this break if we are inserting section that is not the last section
3656 // in a segment?
3657 const max_size = self.allocatedSize(segment_id, off);
36583566
3659 if (size > max_size) {3567 if (!header.isZerofill()) {
3660 try self.growSection(index, @intCast(u32, size));3568 header.offset = @intCast(u32, off);
3661 }3569 }
3570 header.addr = seg.vmaddr + off - seg.fileoff;
36623571
3663 log.debug("allocating {s},{s} section at 0x{x}", .{ header.segName(), header.sectName(), off });3572 // TODO Will this break if we are inserting section that is not the last section
3573 // in a segment?
3574 const max_size = self.allocatedSize(segment_id, off);
36643575
3665 self.updateSectionOrdinals(index + 1);3576 if (size > max_size) {
3577 try self.growSection(sect_id, @intCast(u32, size));
3666 }3578 }
36673579
3668 return index;3580 log.debug("allocating {s},{s} section at 0x{x}", .{ header.segName(), header.sectName(), off });
3581
3582 self.updateSectionOrdinals(sect_id + 1);
3669}3583}
36703584
3671fn getSectionPrecedence(header: macho.section_64) u4 {3585fn getSectionPrecedence(header: macho.section_64) u4 {
...@@ -3690,6 +3604,32 @@ fn getSectionPrecedence(header: macho.section_64) u4 {...@@ -3690,6 +3604,32 @@ fn getSectionPrecedence(header: macho.section_64) u4 {
3690 }3604 }
3691}3605}
36923606
3607const InitSectionOpts = struct {
3608 flags: u32 = macho.S_REGULAR,
3609 reserved1: u32 = 0,
3610 reserved2: u32 = 0,
3611};
3612
3613pub fn initSection(
3614 self: *MachO,
3615 segname: []const u8,
3616 sectname: []const u8,
3617 opts: InitSectionOpts,
3618) !u8 {
3619 const segment_id = self.getSegmentByName(segname).?;
3620 const seg = &self.segments.items[segment_id];
3621 const index = try self.insertSection(segment_id, .{
3622 .sectname = makeStaticString(sectname),
3623 .segname = seg.segname,
3624 .flags = opts.flags,
3625 .reserved1 = opts.reserved1,
3626 .reserved2 = opts.reserved2,
3627 });
3628 seg.cmdsize += @sizeOf(macho.section_64);
3629 seg.nsects += 1;
3630 return index;
3631}
3632
3693fn insertSection(self: *MachO, segment_index: u8, header: macho.section_64) !u8 {3633fn insertSection(self: *MachO, segment_index: u8, header: macho.section_64) !u8 {
3694 const precedence = getSectionPrecedence(header);3634 const precedence = getSectionPrecedence(header);
3695 const indexes = self.getSectionIndexes(segment_index);3635 const indexes = self.getSectionIndexes(segment_index);
src/link/MachO/Atom.zig+2-1
...@@ -314,8 +314,9 @@ pub fn parseRelocs(self: *Atom, relocs: []align(1) const macho.relocation_info,...@@ -314,8 +314,9 @@ pub fn parseRelocs(self: *Atom, relocs: []align(1) const macho.relocation_info,
314 const sect_id = @intCast(u16, rel.r_symbolnum - 1);314 const sect_id = @intCast(u16, rel.r_symbolnum - 1);
315 const sym_index = object.sections_as_symbols.get(sect_id) orelse blk: {315 const sym_index = object.sections_as_symbols.get(sect_id) orelse blk: {
316 const sect = object.getSourceSection(sect_id);316 const sect = object.getSourceSection(sect_id);
317 const out_sect_id = (try context.macho_file.getOutputSection(sect)) orelse317 const gop = (try context.macho_file.getOutputSection(sect)) orelse
318 unreachable;318 unreachable;
319 const out_sect_id = gop.sect_id;
319 const sym_index = @intCast(u32, object.symtab.items.len);320 const sym_index = @intCast(u32, object.symtab.items.len);
320 try object.symtab.append(gpa, .{321 try object.symtab.append(gpa, .{
321 .n_strx = 0,322 .n_strx = 0,
src/link/MachO/Object.zig+5-4
...@@ -220,15 +220,15 @@ fn filterRelocs(...@@ -220,15 +220,15 @@ fn filterRelocs(
220220
221pub fn scanInputSections(self: Object, macho_file: *MachO) !void {221pub fn scanInputSections(self: Object, macho_file: *MachO) !void {
222 for (self.sections.items) |sect| {222 for (self.sections.items) |sect| {
223 const sect_id = (try macho_file.getOutputSection(sect)) orelse {223 const gop = (try macho_file.getOutputSection(sect)) orelse {
224 log.debug(" unhandled section", .{});224 log.debug(" unhandled section", .{});
225 continue;225 continue;
226 };226 };
227 const output = macho_file.sections.items(.header)[sect_id];227 const output = macho_file.sections.items(.header)[gop.sect_id];
228 log.debug("mapping '{s},{s}' into output sect({d}, '{s},{s}')", .{228 log.debug("mapping '{s},{s}' into output sect({d}, '{s},{s}')", .{
229 sect.segName(),229 sect.segName(),
230 sect.sectName(),230 sect.sectName(),
231 sect_id + 1,231 gop.sect_id + 1,
232 output.segName(),232 output.segName(),
233 output.sectName(),233 output.sectName(),
234 });234 });
...@@ -335,10 +335,11 @@ pub fn splitIntoAtoms(self: *Object, macho_file: *MachO, object_id: u32) !void {...@@ -335,10 +335,11 @@ pub fn splitIntoAtoms(self: *Object, macho_file: *MachO, object_id: u32) !void {
335 log.debug("splitting section '{s},{s}' into atoms", .{ sect.segName(), sect.sectName() });335 log.debug("splitting section '{s},{s}' into atoms", .{ sect.segName(), sect.sectName() });
336336
337 // Get matching segment/section in the final artifact.337 // Get matching segment/section in the final artifact.
338 const out_sect_id = (try macho_file.getOutputSection(sect)) orelse {338 const gop = (try macho_file.getOutputSection(sect)) orelse {
339 log.debug(" unhandled section", .{});339 log.debug(" unhandled section", .{});
340 continue;340 continue;
341 };341 };
342 const out_sect_id = gop.sect_id;
342343
343 log.debug(" output sect({d}, '{s},{s}')", .{344 log.debug(" output sect({d}, '{s},{s}')", .{
344 out_sect_id + 1,345 out_sect_id + 1,
src/link/MachO/zld.zig+111-1
...@@ -198,7 +198,7 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr...@@ -198,7 +198,7 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
198 .n_value = 0,198 .n_value = 0,
199 });199 });
200 try macho_file.strtab.buffer.append(gpa, 0);200 try macho_file.strtab.buffer.append(gpa, 0);
201 try macho_file.populateMissingMetadata();201 try initSections(macho_file);
202202
203 var lib_not_found = false;203 var lib_not_found = false;
204 var framework_not_found = false;204 var framework_not_found = false;
...@@ -646,6 +646,116 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr...@@ -646,6 +646,116 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
646 }646 }
647}647}
648648
649fn initSections(macho_file: *MachO) !void {
650 const gpa = macho_file.base.allocator;
651 const cpu_arch = macho_file.base.options.target.cpu.arch;
652 const pagezero_vmsize = macho_file.calcPagezeroSize();
653
654 if (macho_file.pagezero_segment_cmd_index == null) {
655 if (pagezero_vmsize > 0) {
656 macho_file.pagezero_segment_cmd_index = @intCast(u8, macho_file.segments.items.len);
657 try macho_file.segments.append(gpa, .{
658 .segname = MachO.makeStaticString("__PAGEZERO"),
659 .vmsize = pagezero_vmsize,
660 .cmdsize = @sizeOf(macho.segment_command_64),
661 });
662 }
663 }
664
665 if (macho_file.text_segment_cmd_index == null) {
666 macho_file.text_segment_cmd_index = @intCast(u8, macho_file.segments.items.len);
667 try macho_file.segments.append(gpa, .{
668 .segname = MachO.makeStaticString("__TEXT"),
669 .vmaddr = pagezero_vmsize,
670 .vmsize = 0,
671 .filesize = 0,
672 .maxprot = macho.PROT.READ | macho.PROT.EXEC,
673 .initprot = macho.PROT.READ | macho.PROT.EXEC,
674 .cmdsize = @sizeOf(macho.segment_command_64),
675 });
676 }
677
678 if (macho_file.text_section_index == null) {
679 macho_file.text_section_index = try macho_file.initSection("__TEXT", "__text", .{
680 .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
681 });
682 }
683
684 if (macho_file.stubs_section_index == null) {
685 const stub_size: u4 = switch (cpu_arch) {
686 .x86_64 => 6,
687 .aarch64 => 3 * @sizeOf(u32),
688 else => unreachable, // unhandled architecture type
689 };
690 macho_file.stubs_section_index = try macho_file.initSection("__TEXT", "__stubs", .{
691 .flags = macho.S_SYMBOL_STUBS | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
692 .reserved2 = stub_size,
693 });
694 }
695
696 if (macho_file.stub_helper_section_index == null) {
697 macho_file.stub_helper_section_index = try macho_file.initSection("__TEXT", "__stub_helper", .{
698 .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
699 });
700 }
701
702 if (macho_file.data_const_segment_cmd_index == null) {
703 macho_file.data_const_segment_cmd_index = @intCast(u8, macho_file.segments.items.len);
704 try macho_file.segments.append(gpa, .{
705 .segname = MachO.makeStaticString("__DATA_CONST"),
706 .vmaddr = 0,
707 .vmsize = 0,
708 .fileoff = 0,
709 .filesize = 0,
710 .maxprot = macho.PROT.READ | macho.PROT.WRITE,
711 .initprot = macho.PROT.READ | macho.PROT.WRITE,
712 .cmdsize = @sizeOf(macho.segment_command_64),
713 });
714 }
715
716 if (macho_file.got_section_index == null) {
717 macho_file.got_section_index = try macho_file.initSection("__DATA_CONST", "__got", .{
718 .flags = macho.S_NON_LAZY_SYMBOL_POINTERS,
719 });
720 }
721
722 if (macho_file.data_segment_cmd_index == null) {
723 macho_file.data_segment_cmd_index = @intCast(u8, macho_file.segments.items.len);
724 try macho_file.segments.append(gpa, .{
725 .segname = MachO.makeStaticString("__DATA"),
726 .vmaddr = 0,
727 .vmsize = 0,
728 .fileoff = 0,
729 .filesize = 0,
730 .maxprot = macho.PROT.READ | macho.PROT.WRITE,
731 .initprot = macho.PROT.READ | macho.PROT.WRITE,
732 .cmdsize = @sizeOf(macho.segment_command_64),
733 });
734 }
735
736 if (macho_file.la_symbol_ptr_section_index == null) {
737 macho_file.la_symbol_ptr_section_index = try macho_file.initSection("__DATA", "__la_symbol_ptr", .{
738 .flags = macho.S_LAZY_SYMBOL_POINTERS,
739 });
740 }
741
742 if (macho_file.data_section_index == null) {
743 macho_file.data_section_index = try macho_file.initSection("__DATA", "__data", .{});
744 }
745
746 if (macho_file.linkedit_segment_cmd_index == null) {
747 macho_file.linkedit_segment_cmd_index = @intCast(u8, macho_file.segments.items.len);
748 try macho_file.segments.append(gpa, .{
749 .segname = MachO.makeStaticString("__LINKEDIT"),
750 .vmaddr = 0,
751 .fileoff = 0,
752 .maxprot = macho.PROT.READ,
753 .initprot = macho.PROT.READ,
754 .cmdsize = @sizeOf(macho.segment_command_64),
755 });
756 }
757}
758
649fn writeAtoms(macho_file: *MachO) !void {759fn writeAtoms(macho_file: *MachO) !void {
650 assert(macho_file.mode == .one_shot);760 assert(macho_file.mode == .one_shot);
651761