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 {
304304 errdefer file.close();
305305 self.base.file = file;
306306
307 if (!options.strip and options.module != null) blk: {
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;
307 if (self.mode == .one_shot) return self;
313308
309 if (!options.strip and options.module != null) {
314310 // Create dSYM bundle.
315311 const dir = options.module.?.zig_cache_artifact_directory;
316312 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:
10381034 }
10391035}
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 {
10421043 const segname = sect.segName();
10431044 const sectname = sect.sectName();
1044 const res: ?u8 = blk: {
1045
1046 var found_existing: bool = true;
1047 const sect_id: u8 = blk: {
10451048 if (mem.eql(u8, "__LLVM", segname)) {
10461049 log.debug("TODO LLVM section: type 0x{x}, name '{s},{s}'", .{
10471050 sect.flags, segname, sectname,
10481051 });
1049 break :blk null;
1052 return null;
10501053 }
10511054
10521055 if (sect.isCode()) {
10531056 if (self.text_section_index == null) {
1054 self.text_section_index = try self.initSection(
1055 "__TEXT",
1056 "__text",
1057 sect.size,
1058 sect.@"align",
1059 .{
1060 .flags = macho.S_REGULAR |
1061 macho.S_ATTR_PURE_INSTRUCTIONS |
1062 macho.S_ATTR_SOME_INSTRUCTIONS,
1063 },
1064 );
1057 self.text_section_index = try self.initSection("__TEXT", "__text", .{
1058 .flags = macho.S_REGULAR |
1059 macho.S_ATTR_PURE_INSTRUCTIONS |
1060 macho.S_ATTR_SOME_INSTRUCTIONS,
1061 });
1062 found_existing = false;
10651063 }
10661064 break :blk self.text_section_index.?;
10671065 }
......@@ -1073,7 +1071,7 @@ pub fn getOutputSection(self: *MachO, sect: macho.section_64) !?u8 {
10731071 sect.flags, segname, sectname,
10741072 });
10751073 }
1076 break :blk null;
1074 return null;
10771075 }
10781076
10791077 switch (sect.@"type"()) {
......@@ -1081,42 +1079,30 @@ pub fn getOutputSection(self: *MachO, sect: macho.section_64) !?u8 {
10811079 macho.S_8BYTE_LITERALS,
10821080 macho.S_16BYTE_LITERALS,
10831081 => {
1084 break :blk self.getSectionByName("__TEXT", "__const") orelse try self.initSection(
1085 "__TEXT",
1086 "__const",
1087 sect.size,
1088 sect.@"align",
1089 .{},
1090 );
1082 if (self.getSectionByName("__TEXT", "__const")) |sect_id| break :blk sect_id;
1083 found_existing = false;
1084 break :blk try self.initSection("__TEXT", "__const", .{});
10911085 },
10921086 macho.S_CSTRING_LITERALS => {
10931087 if (mem.startsWith(u8, sectname, "__objc")) {
1094 break :blk self.getSectionByName(segname, sectname) orelse try self.initSection(
1095 segname,
1096 sectname,
1097 sect.size,
1098 sect.@"align",
1099 .{},
1100 );
1088 if (self.getSectionByName(segname, sectname)) |sect_id| break :blk sect_id;
1089 found_existing = false;
1090 break :blk try self.initSection(segname, sectname, .{});
11011091 }
1102 break :blk self.getSectionByName("__TEXT", "__cstring") orelse try self.initSection(
1103 "__TEXT",
1104 "__cstring",
1105 sect.size,
1106 sect.@"align",
1107 .{ .flags = macho.S_CSTRING_LITERALS },
1108 );
1092 if (self.getSectionByName("__TEXT", "__cstring")) |sect_id| break :blk sect_id;
1093 found_existing = false;
1094 break :blk try self.initSection("__TEXT", "__cstring", .{
1095 .flags = macho.S_CSTRING_LITERALS,
1096 });
11091097 },
11101098 macho.S_MOD_INIT_FUNC_POINTERS,
11111099 macho.S_MOD_TERM_FUNC_POINTERS,
11121100 => {
1113 break :blk self.getSectionByName("__DATA_CONST", sectname) orelse try self.initSection(
1114 "__DATA_CONST",
1115 sectname,
1116 sect.size,
1117 sect.@"align",
1118 .{ .flags = sect.flags },
1119 );
1101 if (self.getSectionByName("__DATA_CONST", sectname)) |sect_id| break :blk sect_id;
1102 found_existing = false;
1103 break :blk try self.initSection("__DATA_CONST", sectname, .{
1104 .flags = sect.flags,
1105 });
11201106 },
11211107 macho.S_LITERAL_POINTERS,
11221108 macho.S_ZEROFILL,
......@@ -1125,22 +1111,14 @@ pub fn getOutputSection(self: *MachO, sect: macho.section_64) !?u8 {
11251111 macho.S_THREAD_LOCAL_REGULAR,
11261112 macho.S_THREAD_LOCAL_ZEROFILL,
11271113 => {
1128 break :blk self.getSectionByName(segname, sectname) orelse try self.initSection(
1129 segname,
1130 sectname,
1131 sect.size,
1132 sect.@"align",
1133 .{ .flags = sect.flags },
1134 );
1114 if (self.getSectionByName(segname, sectname)) |sect_id| break :blk sect_id;
1115 found_existing = false;
1116 break :blk try self.initSection(segname, sectname, .{ .flags = sect.flags });
11351117 },
11361118 macho.S_COALESCED => {
1137 break :blk self.getSectionByName(segname, sectname) orelse try self.initSection(
1138 segname,
1139 sectname,
1140 sect.size,
1141 sect.@"align",
1142 .{},
1143 );
1119 if (self.getSectionByName(segname, sectname)) |sect_id| break :blk sect_id;
1120 found_existing = false;
1121 break :blk try self.initSection(segname, sectname, .{});
11441122 },
11451123 macho.S_REGULAR => {
11461124 if (mem.eql(u8, segname, "__TEXT")) {
......@@ -1150,13 +1128,9 @@ pub fn getOutputSection(self: *MachO, sect: macho.section_64) !?u8 {
11501128 mem.eql(u8, sectname, "__gosymtab") or
11511129 mem.eql(u8, sectname, "__gopclntab"))
11521130 {
1153 break :blk self.getSectionByName("__DATA_CONST", "__const") orelse try self.initSection(
1154 "__DATA_CONST",
1155 "__const",
1156 sect.size,
1157 sect.@"align",
1158 .{},
1159 );
1131 if (self.getSectionByName("__DATA_CONST", "__const")) |sect_id| break :blk sect_id;
1132 found_existing = false;
1133 break :blk try self.initSection("__DATA_CONST", "__const", .{});
11601134 }
11611135 }
11621136 if (mem.eql(u8, segname, "__DATA")) {
......@@ -1165,39 +1139,29 @@ pub fn getOutputSection(self: *MachO, sect: macho.section_64) !?u8 {
11651139 mem.eql(u8, sectname, "__objc_classlist") or
11661140 mem.eql(u8, sectname, "__objc_imageinfo"))
11671141 {
1168 break :blk self.getSectionByName("__DATA_CONST", sectname) orelse
1169 try self.initSection(
1170 "__DATA_CONST",
1171 sectname,
1172 sect.size,
1173 sect.@"align",
1174 .{},
1175 );
1142 if (self.getSectionByName("__DATA_CONST", sectname)) |sect_id| break :blk sect_id;
1143 found_existing = false;
1144 break :blk try self.initSection("__DATA_CONST", sectname, .{});
11761145 } else if (mem.eql(u8, sectname, "__data")) {
11771146 if (self.data_section_index == null) {
1178 self.data_section_index = try self.initSection(
1179 segname,
1180 sectname,
1181 sect.size,
1182 sect.@"align",
1183 .{},
1184 );
1147 self.data_section_index = try self.initSection(segname, sectname, .{});
1148 found_existing = false;
11851149 }
11861150 break :blk self.data_section_index.?;
11871151 }
11881152 }
1189 break :blk self.getSectionByName(segname, sectname) orelse try self.initSection(
1190 segname,
1191 sectname,
1192 sect.size,
1193 sect.@"align",
1194 .{},
1195 );
1153 if (self.getSectionByName(segname, sectname)) |sect_id| break :blk sect_id;
1154 found_existing = false;
1155 break :blk try self.initSection(segname, sectname, .{});
11961156 },
1197 else => break :blk null,
1157 else => return null,
11981158 }
11991159 };
1200 return res;
1160
1161 return GetOutputSectionResult{
1162 .found_existing = found_existing,
1163 .sect_id = sect_id,
1164 };
12011165}
12021166
12031167pub fn createEmptyAtom(gpa: Allocator, sym_index: u32, size: u64, alignment: u32) !*Atom {
......@@ -1399,12 +1363,17 @@ pub fn createTlvPtrAtom(self: *MachO, target: SymbolWithLoc) !*Atom {
13991363
14001364 const sym = atom.getSymbolPtr(self);
14011365 sym.n_type = macho.N_SECT;
1402 const sect_id = (try self.getOutputSection(.{
1366 const gop = (try self.getOutputSection(.{
14031367 .segname = makeStaticString("__DATA"),
14041368 .sectname = makeStaticString("__thread_ptrs"),
14051369 .flags = macho.S_THREAD_LOCAL_VARIABLE_POINTERS,
14061370 })).?;
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
14091378 try self.allocateAtomCommon(atom);
14101379
......@@ -1754,16 +1723,20 @@ pub fn createTentativeDefAtoms(self: *MachO) !void {
17541723 // text blocks for each tentative definition.
17551724 const size = sym.n_value;
17561725 const alignment = (sym.n_desc >> 8) & 0x0f;
1757 const n_sect = (try self.getOutputSection(.{
1726 const gop = (try self.getOutputSection(.{
17581727 .segname = makeStaticString("__DATA"),
17591728 .sectname = makeStaticString("__bss"),
17601729 .flags = macho.S_ZEROFILL,
17611730 })).?;
1731 if (self.mode == .incremental and !gop.found_existing) {
1732 // TODO allocate section
1733 try self.allocateSection(gop.sect_id, size, alignment);
1734 }
17621735
17631736 sym.* = .{
17641737 .n_strx = sym.n_strx,
17651738 .n_type = macho.N_SECT | macho.N_EXT,
1766 .n_sect = n_sect,
1739 .n_sect = gop.sect_id,
17671740 .n_desc = 0,
17681741 .n_value = 0,
17691742 };
......@@ -2883,16 +2856,19 @@ fn getOutputSectionAtom(
28832856 const align_log_2 = math.log2(alignment);
28842857 const zig_ty = ty.zigTypeTag();
28852858 const mode = self.base.options.optimize_mode;
2859
28862860 const sect_id: u8 = blk: {
28872861 // TODO finish and audit this function
28882862 if (val.isUndefDeep()) {
28892863 if (mode == .ReleaseFast or mode == .ReleaseSmall) {
2890 break :blk (try self.getOutputSection(.{
2864 const gop = (try self.getOutputSection(.{
28912865 .segname = makeStaticString("__DATA"),
28922866 .sectname = makeStaticString("__bss"),
2893 .size = code.len,
2894 .@"align" = align_log_2,
28952867 })).?;
2868 if (!gop.found_existing) {
2869 try self.allocateSection(gop.sect_id, code.len, align_log_2);
2870 }
2871 break :blk gop.sect_id;
28962872 } else {
28972873 break :blk self.data_section_index.?;
28982874 }
......@@ -2903,12 +2879,14 @@ fn getOutputSectionAtom(
29032879 }
29042880
29052881 if (needsPointerRebase(ty, val, mod)) {
2906 break :blk (try self.getOutputSection(.{
2882 const gop = (try self.getOutputSection(.{
29072883 .segname = makeStaticString("__DATA_CONST"),
29082884 .sectname = makeStaticString("__const"),
2909 .size = code.len,
2910 .@"align" = align_log_2,
29112885 })).?;
2886 if (!gop.found_existing) {
2887 try self.allocateSection(gop.sect_id, code.len, align_log_2);
2888 }
2889 break :blk gop.sect_id;
29122890 }
29132891
29142892 switch (zig_ty) {
......@@ -2922,13 +2900,15 @@ fn getOutputSectionAtom(
29222900 .const_slice_u8_sentinel_0,
29232901 .manyptr_const_u8_sentinel_0,
29242902 => {
2925 break :blk (try self.getOutputSection(.{
2903 const gop = (try self.getOutputSection(.{
29262904 .segname = makeStaticString("__TEXT"),
29272905 .sectname = makeStaticString("__cstring"),
29282906 .flags = macho.S_CSTRING_LITERALS,
2929 .size = code.len,
2930 .@"align" = align_log_2,
29312907 })).?;
2908 if (!gop.found_existing) {
2909 try self.allocateSection(gop.sect_id, code.len, align_log_2);
2910 }
2911 break :blk gop.sect_id;
29322912 },
29332913 else => {},
29342914 }
......@@ -2936,13 +2916,16 @@ fn getOutputSectionAtom(
29362916 },
29372917 else => {},
29382918 }
2939 break :blk (try self.getOutputSection(.{
2919 const gop = (try self.getOutputSection(.{
29402920 .segname = makeStaticString("__TEXT"),
29412921 .sectname = makeStaticString("__const"),
2942 .size = code.len,
2943 .@"align" = align_log_2,
29442922 })).?;
2923 if (!gop.found_existing) {
2924 try self.allocateSection(gop.sect_id, code.len, align_log_2);
2925 }
2926 break :blk gop.sect_id;
29452927 };
2928
29462929 const header = self.sections.items(.header)[sect_id];
29472930 log.debug(" allocating atom '{s}' in '{s},{s}', ord({d})", .{
29482931 name,
......@@ -3255,40 +3238,36 @@ pub fn getDeclVAddr(self: *MachO, decl_index: Module.Decl.Index, reloc_info: Fil
32553238}
32563239
32573240pub fn populateMissingMetadata(self: *MachO) !void {
3241 assert(self.mode == .incremental);
3242
32583243 const gpa = self.base.allocator;
32593244 const cpu_arch = self.base.options.target.cpu.arch;
3260 const pagezero_vmsize = self.base.options.pagezero_size orelse default_pagezero_vmsize;
3261 const aligned_pagezero_vmsize = mem.alignBackwardGeneric(u64, pagezero_vmsize, self.page_size);
3262
3263 if (self.pagezero_segment_cmd_index == null) blk: {
3264 if (self.base.options.output_mode == .Lib) break :blk;
3265 if (aligned_pagezero_vmsize == 0) break :blk;
3266 if (aligned_pagezero_vmsize != pagezero_vmsize) {
3267 log.warn("requested __PAGEZERO size (0x{x}) is not page aligned", .{pagezero_vmsize});
3268 log.warn(" rounding down to 0x{x}", .{aligned_pagezero_vmsize});
3245 const pagezero_vmsize = self.calcPagezeroSize();
3246
3247 if (self.pagezero_segment_cmd_index == null) {
3248 if (pagezero_vmsize > 0) {
3249 self.pagezero_segment_cmd_index = @intCast(u8, self.segments.items.len);
3250 try self.segments.append(gpa, .{
3251 .segname = makeStaticString("__PAGEZERO"),
3252 .vmsize = pagezero_vmsize,
3253 .cmdsize = @sizeOf(macho.segment_command_64),
3254 });
32693255 }
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 });
32763256 }
32773257
32783258 if (self.text_segment_cmd_index == null) {
32793259 self.text_segment_cmd_index = @intCast(u8, self.segments.items.len);
3280 const needed_size = if (self.mode == .incremental) blk: {
3281 const headerpad_size = @maximum(self.base.options.headerpad_size orelse 0, default_headerpad_size);
3282 const program_code_size_hint = self.base.options.program_code_size_hint;
3283 const got_size_hint = @sizeOf(u64) * self.base.options.symbol_count_hint;
3284 const ideal_size = headerpad_size + program_code_size_hint + got_size_hint;
3285 const needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size);
3286 log.debug("found __TEXT segment free space 0x{x} to 0x{x}", .{ 0, needed_size });
3287 break :blk needed_size;
3288 } else 0;
3260 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;
3262 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;
3264 const needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size);
3265
3266 log.debug("found __TEXT segment free space 0x{x} to 0x{x}", .{ 0, needed_size });
3267
32893268 try self.segments.append(gpa, .{
32903269 .segname = makeStaticString("__TEXT"),
3291 .vmaddr = aligned_pagezero_vmsize,
3270 .vmaddr = pagezero_vmsize,
32923271 .vmsize = needed_size,
32933272 .filesize = needed_size,
32943273 .maxprot = macho.PROT.READ | macho.PROT.EXEC,
......@@ -3303,16 +3282,11 @@ pub fn populateMissingMetadata(self: *MachO) !void {
33033282 .aarch64 => 2,
33043283 else => unreachable, // unhandled architecture type
33053284 };
3306 const needed_size = if (self.mode == .incremental) self.base.options.program_code_size_hint else 0;
3307 self.text_section_index = try self.initSection(
3308 "__TEXT",
3309 "__text",
3310 needed_size,
3311 alignment,
3312 .{
3313 .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
3314 },
3315 );
3285 const needed_size = self.base.options.program_code_size_hint;
3286 self.text_section_index = try self.initSection("__TEXT", "__text", .{
3287 .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
3288 });
3289 try self.allocateSection(self.text_section_index.?, needed_size, alignment);
33163290 }
33173291
33183292 if (self.stubs_section_index == null) {
......@@ -3326,17 +3300,12 @@ pub fn populateMissingMetadata(self: *MachO) !void {
33263300 .aarch64 => 3 * @sizeOf(u32),
33273301 else => unreachable, // unhandled architecture type
33283302 };
3329 const needed_size = if (self.mode == .incremental) stub_size * self.base.options.symbol_count_hint else 0;
3330 self.stubs_section_index = try self.initSection(
3331 "__TEXT",
3332 "__stubs",
3333 needed_size,
3334 alignment,
3335 .{
3336 .flags = macho.S_SYMBOL_STUBS | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
3337 .reserved2 = stub_size,
3338 },
3339 );
3303 const needed_size = stub_size * self.base.options.symbol_count_hint;
3304 self.stubs_section_index = try self.initSection("__TEXT", "__stubs", .{
3305 .flags = macho.S_SYMBOL_STUBS | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
3306 .reserved2 = stub_size,
3307 });
3308 try self.allocateSection(self.stubs_section_index.?, needed_size, alignment);
33403309 }
33413310
33423311 if (self.stub_helper_section_index == null) {
......@@ -3355,37 +3324,26 @@ pub fn populateMissingMetadata(self: *MachO) !void {
33553324 .aarch64 => 3 * @sizeOf(u32),
33563325 else => unreachable,
33573326 };
3358 const needed_size = if (self.mode == .incremental)
3359 stub_size * self.base.options.symbol_count_hint + preamble_size
3360 else
3361 0;
3362 self.stub_helper_section_index = try self.initSection(
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 );
3327 const needed_size = stub_size * self.base.options.symbol_count_hint + preamble_size;
3328 self.stub_helper_section_index = try self.initSection("__TEXT", "__stub_helper", .{
3329 .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
3330 });
3331 try self.allocateSection(self.stub_helper_section_index.?, needed_size, alignment);
33713332 }
33723333
33733334 if (self.data_const_segment_cmd_index == null) {
33743335 self.data_const_segment_cmd_index = @intCast(u8, self.segments.items.len);
3375 var vmaddr: u64 = 0;
3376 var fileoff: u64 = 0;
3377 var needed_size: u64 = 0;
3378 if (self.mode == .incremental) {
3379 const base = self.getSegmentAllocBase(&.{self.text_segment_cmd_index.?});
3380 vmaddr = base.vmaddr;
3381 fileoff = base.fileoff;
3382 const ideal_size = @sizeOf(u64) * self.base.options.symbol_count_hint;
3383 needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size);
3384 log.debug("found __DATA_CONST segment free space 0x{x} to 0x{x}", .{
3385 fileoff,
3386 fileoff + needed_size,
3387 });
3388 }
3336 const base = self.getSegmentAllocBase(&.{self.text_segment_cmd_index.?});
3337 const vmaddr = base.vmaddr;
3338 const fileoff = base.fileoff;
3339 const ideal_size = @sizeOf(u64) * self.base.options.symbol_count_hint;
3340 const needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size);
3341
3342 log.debug("found __DATA_CONST segment free space 0x{x} to 0x{x}", .{
3343 fileoff,
3344 fileoff + needed_size,
3345 });
3346
33893347 try self.segments.append(gpa, .{
33903348 .segname = makeStaticString("__DATA_CONST"),
33913349 .vmaddr = vmaddr,
......@@ -3399,38 +3357,27 @@ pub fn populateMissingMetadata(self: *MachO) !void {
33993357 }
34003358
34013359 if (self.got_section_index == null) {
3402 const needed_size = if (self.mode == .incremental)
3403 @sizeOf(u64) * self.base.options.symbol_count_hint
3404 else
3405 0;
3360 const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint;
34063361 const alignment: u16 = 3; // 2^3 = @sizeOf(u64)
3407 self.got_section_index = try self.initSection(
3408 "__DATA_CONST",
3409 "__got",
3410 needed_size,
3411 alignment,
3412 .{
3413 .flags = macho.S_NON_LAZY_SYMBOL_POINTERS,
3414 },
3415 );
3362 self.got_section_index = try self.initSection("__DATA_CONST", "__got", .{
3363 .flags = macho.S_NON_LAZY_SYMBOL_POINTERS,
3364 });
3365 try self.allocateSection(self.got_section_index.?, needed_size, alignment);
34163366 }
34173367
34183368 if (self.data_segment_cmd_index == null) {
34193369 self.data_segment_cmd_index = @intCast(u8, self.segments.items.len);
3420 var vmaddr: u64 = 0;
3421 var fileoff: u64 = 0;
3422 var needed_size: u64 = 0;
3423 if (self.mode == .incremental) {
3424 const base = self.getSegmentAllocBase(&.{self.data_const_segment_cmd_index.?});
3425 vmaddr = base.vmaddr;
3426 fileoff = base.fileoff;
3427 const ideal_size = 2 * @sizeOf(u64) * self.base.options.symbol_count_hint;
3428 needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size);
3429 log.debug("found __DATA segment free space 0x{x} to 0x{x}", .{
3430 fileoff,
3431 fileoff + needed_size,
3432 });
3433 }
3370 const base = self.getSegmentAllocBase(&.{self.data_const_segment_cmd_index.?});
3371 const vmaddr = base.vmaddr;
3372 const fileoff = base.fileoff;
3373 const ideal_size = 2 * @sizeOf(u64) * self.base.options.symbol_count_hint;
3374 const needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size);
3375
3376 log.debug("found __DATA segment free space 0x{x} to 0x{x}", .{
3377 fileoff,
3378 fileoff + needed_size,
3379 });
3380
34343381 try self.segments.append(gpa, .{
34353382 .segname = makeStaticString("__DATA"),
34363383 .vmaddr = vmaddr,
......@@ -3444,47 +3391,29 @@ pub fn populateMissingMetadata(self: *MachO) !void {
34443391 }
34453392
34463393 if (self.la_symbol_ptr_section_index == null) {
3447 const needed_size = if (self.mode == .incremental)
3448 @sizeOf(u64) * self.base.options.symbol_count_hint
3449 else
3450 0;
3394 const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint;
34513395 const alignment: u16 = 3; // 2^3 = @sizeOf(u64)
3452 self.la_symbol_ptr_section_index = try self.initSection(
3453 "__DATA",
3454 "__la_symbol_ptr",
3455 needed_size,
3456 alignment,
3457 .{
3458 .flags = macho.S_LAZY_SYMBOL_POINTERS,
3459 },
3460 );
3396 self.la_symbol_ptr_section_index = try self.initSection("__DATA", "__la_symbol_ptr", .{
3397 .flags = macho.S_LAZY_SYMBOL_POINTERS,
3398 });
3399 try self.allocateSection(self.la_symbol_ptr_section_index.?, needed_size, alignment);
34613400 }
34623401
34633402 if (self.data_section_index == null) {
3464 const needed_size = if (self.mode == .incremental)
3465 @sizeOf(u64) * self.base.options.symbol_count_hint
3466 else
3467 0;
3403 const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint;
34683404 const alignment: u16 = 3; // 2^3 = @sizeOf(u64)
3469 self.data_section_index = try self.initSection(
3470 "__DATA",
3471 "__data",
3472 needed_size,
3473 alignment,
3474 .{},
3475 );
3405 self.data_section_index = try self.initSection("__DATA", "__data", .{});
3406 try self.allocateSection(self.data_section_index.?, needed_size, alignment);
34763407 }
34773408
34783409 if (self.linkedit_segment_cmd_index == null) {
34793410 self.linkedit_segment_cmd_index = @intCast(u8, self.segments.items.len);
3480 var vmaddr: u64 = 0;
3481 var fileoff: u64 = 0;
3482 if (self.mode == .incremental) {
3483 const base = self.getSegmentAllocBase(&.{self.data_segment_cmd_index.?});
3484 vmaddr = base.vmaddr;
3485 fileoff = base.fileoff;
3486 log.debug("found __LINKEDIT segment free space at 0x{x}", .{fileoff});
3487 }
3411 const base = self.getSegmentAllocBase(&.{self.data_segment_cmd_index.?});
3412 const vmaddr = base.vmaddr;
3413 const fileoff = base.fileoff;
3414
3415 log.debug("found __LINKEDIT segment free space at 0x{x}", .{fileoff});
3416
34883417 try self.segments.append(gpa, .{
34893418 .segname = makeStaticString("__LINKEDIT"),
34903419 .vmaddr = vmaddr,
......@@ -3586,6 +3515,18 @@ fn calcLCsSize(self: *MachO, assume_max_path_len: bool) !u32 {
35863515 return @intCast(u32, sizeofcmds);
35873516}
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
35893530pub fn calcMinHeaderPad(self: *MachO) !u64 {
35903531 var padding: u32 = (try self.calcLCsSize(false)) + (self.base.options.headerpad_size orelse 0);
35913532 log.debug("minimum requested headerpad size 0x{x}", .{padding + @sizeOf(macho.mach_header_64)});
......@@ -3603,69 +3544,42 @@ pub fn calcMinHeaderPad(self: *MachO) !u64 {
36033544 return offset;
36043545}
36053546
3606const InitSectionOpts = struct {
3607 flags: u32 = macho.S_REGULAR,
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).?;
3547fn allocateSection(self: *MachO, sect_id: u8, size: u64, alignment: u32) !void {
3548 const segment_id = self.sections.items(.segment_index)[sect_id];
36213549 const seg = &self.segments.items[segment_id];
3622 const index = try self.insertSection(segment_id, .{
3623 .sectname = makeStaticString(sectname),
3624 .segname = seg.segname,
3625 .flags = opts.flags,
3626 .reserved1 = opts.reserved1,
3627 .reserved2 = opts.reserved2,
3628 });
3629 seg.cmdsize += @sizeOf(macho.section_64);
3630 seg.nsects += 1;
3631
3632 if (self.mode == .incremental) {
3633 const header = &self.sections.items(.header)[index];
3634 header.size = size;
3635 header.@"align" = alignment;
3636
3637 const prev_end_off = if (index > 0) blk: {
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);
3550 const header = &self.sections.items(.header)[sect_id];
3551 header.size = size;
3552 header.@"align" = alignment;
3553
3554 const prev_end_off = if (sect_id > 0) blk: {
3555 const prev_section = self.sections.get(sect_id - 1);
3556 if (prev_section.segment_index == segment_id) {
3557 const prev_header = prev_section.header;
3558 break :blk prev_header.offset + padToIdeal(prev_header.size);
3559 } else break :blk seg.fileoff;
3560 } else 0;
3561 const alignment_pow_2 = try math.powi(u32, 2, alignment);
3562 // TODO better prealloc for __text section
3563 // const padding: u64 = if (sect_id == 0) try self.calcMinHeaderPad() else 0;
3564 const padding: u64 = if (sect_id == 0) 0x1000 else 0;
3565 const off = mem.alignForwardGeneric(u64, padding + prev_end_off, alignment_pow_2);
36583566
3659 if (size > max_size) {
3660 try self.growSection(index, @intCast(u32, size));
3661 }
3567 if (!header.isZerofill()) {
3568 header.offset = @intCast(u32, off);
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));
36663578 }
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);
36693583}
36703584
36713585fn getSectionPrecedence(header: macho.section_64) u4 {
......@@ -3690,6 +3604,32 @@ fn getSectionPrecedence(header: macho.section_64) u4 {
36903604 }
36913605}
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
36933633fn insertSection(self: *MachO, segment_index: u8, header: macho.section_64) !u8 {
36943634 const precedence = getSectionPrecedence(header);
36953635 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,
314314 const sect_id = @intCast(u16, rel.r_symbolnum - 1);
315315 const sym_index = object.sections_as_symbols.get(sect_id) orelse blk: {
316316 const sect = object.getSourceSection(sect_id);
317 const out_sect_id = (try context.macho_file.getOutputSection(sect)) orelse
317 const gop = (try context.macho_file.getOutputSection(sect)) orelse
318318 unreachable;
319 const out_sect_id = gop.sect_id;
319320 const sym_index = @intCast(u32, object.symtab.items.len);
320321 try object.symtab.append(gpa, .{
321322 .n_strx = 0,
src/link/MachO/Object.zig+5-4
......@@ -220,15 +220,15 @@ fn filterRelocs(
220220
221221pub fn scanInputSections(self: Object, macho_file: *MachO) !void {
222222 for (self.sections.items) |sect| {
223 const sect_id = (try macho_file.getOutputSection(sect)) orelse {
223 const gop = (try macho_file.getOutputSection(sect)) orelse {
224224 log.debug(" unhandled section", .{});
225225 continue;
226226 };
227 const output = macho_file.sections.items(.header)[sect_id];
227 const output = macho_file.sections.items(.header)[gop.sect_id];
228228 log.debug("mapping '{s},{s}' into output sect({d}, '{s},{s}')", .{
229229 sect.segName(),
230230 sect.sectName(),
231 sect_id + 1,
231 gop.sect_id + 1,
232232 output.segName(),
233233 output.sectName(),
234234 });
......@@ -335,10 +335,11 @@ pub fn splitIntoAtoms(self: *Object, macho_file: *MachO, object_id: u32) !void {
335335 log.debug("splitting section '{s},{s}' into atoms", .{ sect.segName(), sect.sectName() });
336336
337337 // 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 {
339339 log.debug(" unhandled section", .{});
340340 continue;
341341 };
342 const out_sect_id = gop.sect_id;
342343
343344 log.debug(" output sect({d}, '{s},{s}')", .{
344345 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
198198 .n_value = 0,
199199 });
200200 try macho_file.strtab.buffer.append(gpa, 0);
201 try macho_file.populateMissingMetadata();
201 try initSections(macho_file);
202202
203203 var lib_not_found = false;
204204 var framework_not_found = false;
......@@ -646,6 +646,116 @@ pub fn linkWithZld(macho_file: *MachO, comp: *Compilation, prog_node: *std.Progr
646646 }
647647}
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
649759fn writeAtoms(macho_file: *MachO) !void {
650760 assert(macho_file.mode == .one_shot);
651761