| ... | ... | @@ -304,13 +304,9 @@ pub fn openPath(allocator: Allocator, options: link.Options) !*MachO { |
| 304 | 304 | errdefer file.close(); |
| 305 | 305 | self.base.file = file; |
| 306 | 306 | |
| 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; |
| 313 | 308 | |
| 309 | if (!options.strip and options.module != null) { |
| 314 | 310 | // Create dSYM bundle. |
| 315 | 311 | const dir = options.module.?.zig_cache_artifact_directory; |
| 316 | 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 | 1034 | } |
| 1039 | 1035 | } |
| 1040 | 1036 | |
| 1041 | | pub fn getOutputSection(self: *MachO, sect: macho.section_64) !?u8 { |
| 1037 | const GetOutputSectionResult = struct { |
| 1038 | found_existing: bool, |
| 1039 | sect_id: u8, |
| 1040 | }; |
| 1041 | |
| 1042 | pub fn getOutputSection(self: *MachO, sect: macho.section_64) !?GetOutputSectionResult { |
| 1042 | 1043 | const segname = sect.segName(); |
| 1043 | 1044 | const sectname = sect.sectName(); |
| 1044 | | const res: ?u8 = blk: { |
| 1045 | |
| 1046 | var found_existing: bool = true; |
| 1047 | const sect_id: u8 = blk: { |
| 1045 | 1048 | if (mem.eql(u8, "__LLVM", segname)) { |
| 1046 | 1049 | log.debug("TODO LLVM section: type 0x{x}, name '{s},{s}'", .{ |
| 1047 | 1050 | sect.flags, segname, sectname, |
| 1048 | 1051 | }); |
| 1049 | | break :blk null; |
| 1052 | return null; |
| 1050 | 1053 | } |
| 1051 | 1054 | |
| 1052 | 1055 | if (sect.isCode()) { |
| 1053 | 1056 | 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; |
| 1065 | 1063 | } |
| 1066 | 1064 | break :blk self.text_section_index.?; |
| 1067 | 1065 | } |
| ... | ... | @@ -1073,7 +1071,7 @@ pub fn getOutputSection(self: *MachO, sect: macho.section_64) !?u8 { |
| 1073 | 1071 | sect.flags, segname, sectname, |
| 1074 | 1072 | }); |
| 1075 | 1073 | } |
| 1076 | | break :blk null; |
| 1074 | return null; |
| 1077 | 1075 | } |
| 1078 | 1076 | |
| 1079 | 1077 | switch (sect.@"type"()) { |
| ... | ... | @@ -1081,42 +1079,30 @@ pub fn getOutputSection(self: *MachO, sect: macho.section_64) !?u8 { |
| 1081 | 1079 | macho.S_8BYTE_LITERALS, |
| 1082 | 1080 | macho.S_16BYTE_LITERALS, |
| 1083 | 1081 | => { |
| 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", .{}); |
| 1091 | 1085 | }, |
| 1092 | 1086 | macho.S_CSTRING_LITERALS => { |
| 1093 | 1087 | 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, .{}); |
| 1101 | 1091 | } |
| 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 | }); |
| 1109 | 1097 | }, |
| 1110 | 1098 | macho.S_MOD_INIT_FUNC_POINTERS, |
| 1111 | 1099 | macho.S_MOD_TERM_FUNC_POINTERS, |
| 1112 | 1100 | => { |
| 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 | }); |
| 1120 | 1106 | }, |
| 1121 | 1107 | macho.S_LITERAL_POINTERS, |
| 1122 | 1108 | macho.S_ZEROFILL, |
| ... | ... | @@ -1125,22 +1111,14 @@ pub fn getOutputSection(self: *MachO, sect: macho.section_64) !?u8 { |
| 1125 | 1111 | macho.S_THREAD_LOCAL_REGULAR, |
| 1126 | 1112 | macho.S_THREAD_LOCAL_ZEROFILL, |
| 1127 | 1113 | => { |
| 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 }); |
| 1135 | 1117 | }, |
| 1136 | 1118 | 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, .{}); |
| 1144 | 1122 | }, |
| 1145 | 1123 | macho.S_REGULAR => { |
| 1146 | 1124 | if (mem.eql(u8, segname, "__TEXT")) { |
| ... | ... | @@ -1150,13 +1128,9 @@ pub fn getOutputSection(self: *MachO, sect: macho.section_64) !?u8 { |
| 1150 | 1128 | mem.eql(u8, sectname, "__gosymtab") or |
| 1151 | 1129 | mem.eql(u8, sectname, "__gopclntab")) |
| 1152 | 1130 | { |
| 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", .{}); |
| 1160 | 1134 | } |
| 1161 | 1135 | } |
| 1162 | 1136 | if (mem.eql(u8, segname, "__DATA")) { |
| ... | ... | @@ -1165,39 +1139,29 @@ pub fn getOutputSection(self: *MachO, sect: macho.section_64) !?u8 { |
| 1165 | 1139 | mem.eql(u8, sectname, "__objc_classlist") or |
| 1166 | 1140 | mem.eql(u8, sectname, "__objc_imageinfo")) |
| 1167 | 1141 | { |
| 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, .{}); |
| 1176 | 1145 | } else if (mem.eql(u8, sectname, "__data")) { |
| 1177 | 1146 | 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; |
| 1185 | 1149 | } |
| 1186 | 1150 | break :blk self.data_section_index.?; |
| 1187 | 1151 | } |
| 1188 | 1152 | } |
| 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, .{}); |
| 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 | } |
| 1202 | 1166 | |
| 1203 | 1167 | pub 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 | 1363 | |
| 1400 | 1364 | const sym = atom.getSymbolPtr(self); |
| 1401 | 1365 | sym.n_type = macho.N_SECT; |
| 1402 | | const sect_id = (try self.getOutputSection(.{ |
| 1366 | const gop = (try self.getOutputSection(.{ |
| 1403 | 1367 | .segname = makeStaticString("__DATA"), |
| 1404 | 1368 | .sectname = makeStaticString("__thread_ptrs"), |
| 1405 | 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; |
| 1408 | 1377 | |
| 1409 | 1378 | try self.allocateAtomCommon(atom); |
| 1410 | 1379 | |
| ... | ... | @@ -1754,16 +1723,20 @@ pub fn createTentativeDefAtoms(self: *MachO) !void { |
| 1754 | 1723 | // text blocks for each tentative definition. |
| 1755 | 1724 | const size = sym.n_value; |
| 1756 | 1725 | const alignment = (sym.n_desc >> 8) & 0x0f; |
| 1757 | | const n_sect = (try self.getOutputSection(.{ |
| 1726 | const gop = (try self.getOutputSection(.{ |
| 1758 | 1727 | .segname = makeStaticString("__DATA"), |
| 1759 | 1728 | .sectname = makeStaticString("__bss"), |
| 1760 | 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 | } |
| 1762 | 1735 | |
| 1763 | 1736 | sym.* = .{ |
| 1764 | 1737 | .n_strx = sym.n_strx, |
| 1765 | 1738 | .n_type = macho.N_SECT | macho.N_EXT, |
| 1766 | | .n_sect = n_sect, |
| 1739 | .n_sect = gop.sect_id, |
| 1767 | 1740 | .n_desc = 0, |
| 1768 | 1741 | .n_value = 0, |
| 1769 | 1742 | }; |
| ... | ... | @@ -2883,16 +2856,19 @@ fn getOutputSectionAtom( |
| 2883 | 2856 | const align_log_2 = math.log2(alignment); |
| 2884 | 2857 | const zig_ty = ty.zigTypeTag(); |
| 2885 | 2858 | const mode = self.base.options.optimize_mode; |
| 2859 | |
| 2886 | 2860 | const sect_id: u8 = blk: { |
| 2887 | 2861 | // TODO finish and audit this function |
| 2888 | 2862 | if (val.isUndefDeep()) { |
| 2889 | 2863 | if (mode == .ReleaseFast or mode == .ReleaseSmall) { |
| 2890 | | break :blk (try self.getOutputSection(.{ |
| 2864 | const gop = (try self.getOutputSection(.{ |
| 2891 | 2865 | .segname = makeStaticString("__DATA"), |
| 2892 | 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 | 2872 | } else { |
| 2897 | 2873 | break :blk self.data_section_index.?; |
| 2898 | 2874 | } |
| ... | ... | @@ -2903,12 +2879,14 @@ fn getOutputSectionAtom( |
| 2903 | 2879 | } |
| 2904 | 2880 | |
| 2905 | 2881 | if (needsPointerRebase(ty, val, mod)) { |
| 2906 | | break :blk (try self.getOutputSection(.{ |
| 2882 | const gop = (try self.getOutputSection(.{ |
| 2907 | 2883 | .segname = makeStaticString("__DATA_CONST"), |
| 2908 | 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 | } |
| 2913 | 2891 | |
| 2914 | 2892 | switch (zig_ty) { |
| ... | ... | @@ -2922,13 +2900,15 @@ fn getOutputSectionAtom( |
| 2922 | 2900 | .const_slice_u8_sentinel_0, |
| 2923 | 2901 | .manyptr_const_u8_sentinel_0, |
| 2924 | 2902 | => { |
| 2925 | | break :blk (try self.getOutputSection(.{ |
| 2903 | const gop = (try self.getOutputSection(.{ |
| 2926 | 2904 | .segname = makeStaticString("__TEXT"), |
| 2927 | 2905 | .sectname = makeStaticString("__cstring"), |
| 2928 | 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 | 2913 | else => {}, |
| 2934 | 2914 | } |
| ... | ... | @@ -2936,13 +2916,16 @@ fn getOutputSectionAtom( |
| 2936 | 2916 | }, |
| 2937 | 2917 | else => {}, |
| 2938 | 2918 | } |
| 2939 | | break :blk (try self.getOutputSection(.{ |
| 2919 | const gop = (try self.getOutputSection(.{ |
| 2940 | 2920 | .segname = makeStaticString("__TEXT"), |
| 2941 | 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 | 2929 | const header = self.sections.items(.header)[sect_id]; |
| 2947 | 2930 | log.debug(" allocating atom '{s}' in '{s},{s}', ord({d})", .{ |
| 2948 | 2931 | name, |
| ... | ... | @@ -3255,40 +3238,36 @@ pub fn getDeclVAddr(self: *MachO, decl_index: Module.Decl.Index, reloc_info: Fil |
| 3255 | 3238 | } |
| 3256 | 3239 | |
| 3257 | 3240 | pub fn populateMissingMetadata(self: *MachO) !void { |
| 3241 | assert(self.mode == .incremental); |
| 3242 | |
| 3258 | 3243 | const gpa = self.base.allocator; |
| 3259 | 3244 | 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 | }); |
| 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 | } |
| 3277 | 3257 | |
| 3278 | 3258 | if (self.text_segment_cmd_index == null) { |
| 3279 | 3259 | 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 | |
| 3289 | 3268 | try self.segments.append(gpa, .{ |
| 3290 | 3269 | .segname = makeStaticString("__TEXT"), |
| 3291 | | .vmaddr = aligned_pagezero_vmsize, |
| 3270 | .vmaddr = pagezero_vmsize, |
| 3292 | 3271 | .vmsize = needed_size, |
| 3293 | 3272 | .filesize = needed_size, |
| 3294 | 3273 | .maxprot = macho.PROT.READ | macho.PROT.EXEC, |
| ... | ... | @@ -3303,16 +3282,11 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3303 | 3282 | .aarch64 => 2, |
| 3304 | 3283 | else => unreachable, // unhandled architecture type |
| 3305 | 3284 | }; |
| 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); |
| 3316 | 3290 | } |
| 3317 | 3291 | |
| 3318 | 3292 | if (self.stubs_section_index == null) { |
| ... | ... | @@ -3326,17 +3300,12 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3326 | 3300 | .aarch64 => 3 * @sizeOf(u32), |
| 3327 | 3301 | 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; |
| 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); |
| 3340 | 3309 | } |
| 3341 | 3310 | |
| 3342 | 3311 | if (self.stub_helper_section_index == null) { |
| ... | ... | @@ -3355,37 +3324,26 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3355 | 3324 | .aarch64 => 3 * @sizeOf(u32), |
| 3356 | 3325 | else => unreachable, |
| 3357 | 3326 | }; |
| 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); |
| 3371 | 3332 | } |
| 3372 | 3333 | |
| 3373 | 3334 | if (self.data_const_segment_cmd_index == null) { |
| 3374 | 3335 | 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 | |
| 3389 | 3347 | try self.segments.append(gpa, .{ |
| 3390 | 3348 | .segname = makeStaticString("__DATA_CONST"), |
| 3391 | 3349 | .vmaddr = vmaddr, |
| ... | ... | @@ -3399,38 +3357,27 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3399 | 3357 | } |
| 3400 | 3358 | |
| 3401 | 3359 | 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; |
| 3406 | 3361 | 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); |
| 3416 | 3366 | } |
| 3417 | 3367 | |
| 3418 | 3368 | if (self.data_segment_cmd_index == null) { |
| 3419 | 3369 | 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 | |
| 3434 | 3381 | try self.segments.append(gpa, .{ |
| 3435 | 3382 | .segname = makeStaticString("__DATA"), |
| 3436 | 3383 | .vmaddr = vmaddr, |
| ... | ... | @@ -3444,47 +3391,29 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3444 | 3391 | } |
| 3445 | 3392 | |
| 3446 | 3393 | 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; |
| 3451 | 3395 | 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); |
| 3461 | 3400 | } |
| 3462 | 3401 | |
| 3463 | 3402 | 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; |
| 3468 | 3404 | 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); |
| 3476 | 3407 | } |
| 3477 | 3408 | |
| 3478 | 3409 | if (self.linkedit_segment_cmd_index == null) { |
| 3479 | 3410 | 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 | |
| 3488 | 3417 | try self.segments.append(gpa, .{ |
| 3489 | 3418 | .segname = makeStaticString("__LINKEDIT"), |
| 3490 | 3419 | .vmaddr = vmaddr, |
| ... | ... | @@ -3586,6 +3515,18 @@ fn calcLCsSize(self: *MachO, assume_max_path_len: bool) !u32 { |
| 3586 | 3515 | return @intCast(u32, sizeofcmds); |
| 3587 | 3516 | } |
| 3588 | 3517 | |
| 3518 | pub 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 | |
| 3589 | 3530 | pub fn calcMinHeaderPad(self: *MachO) !u64 { |
| 3590 | 3531 | var padding: u32 = (try self.calcLCsSize(false)) + (self.base.options.headerpad_size orelse 0); |
| 3591 | 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 | 3544 | return offset; |
| 3604 | 3545 | } |
| 3605 | 3546 | |
| 3606 | | const InitSectionOpts = struct { |
| 3607 | | flags: u32 = macho.S_REGULAR, |
| 3608 | | reserved1: u32 = 0, |
| 3609 | | reserved2: u32 = 0, |
| 3610 | | }; |
| 3611 | | |
| 3612 | | fn 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).?; |
| 3547 | fn allocateSection(self: *MachO, sect_id: u8, size: u64, alignment: u32) !void { |
| 3548 | const segment_id = self.sections.items(.segment_index)[sect_id]; |
| 3621 | 3549 | 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); |
| 3658 | 3566 | |
| 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; |
| 3662 | 3571 | |
| 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); |
| 3664 | 3575 | |
| 3665 | | self.updateSectionOrdinals(index + 1); |
| 3576 | if (size > max_size) { |
| 3577 | try self.growSection(sect_id, @intCast(u32, size)); |
| 3666 | 3578 | } |
| 3667 | 3579 | |
| 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 | } |
| 3670 | 3584 | |
| 3671 | 3585 | fn getSectionPrecedence(header: macho.section_64) u4 { |
| ... | ... | @@ -3690,6 +3604,32 @@ fn getSectionPrecedence(header: macho.section_64) u4 { |
| 3690 | 3604 | } |
| 3691 | 3605 | } |
| 3692 | 3606 | |
| 3607 | const InitSectionOpts = struct { |
| 3608 | flags: u32 = macho.S_REGULAR, |
| 3609 | reserved1: u32 = 0, |
| 3610 | reserved2: u32 = 0, |
| 3611 | }; |
| 3612 | |
| 3613 | pub 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 | |
| 3693 | 3633 | fn insertSection(self: *MachO, segment_index: u8, header: macho.section_64) !u8 { |
| 3694 | 3634 | const precedence = getSectionPrecedence(header); |
| 3695 | 3635 | const indexes = self.getSectionIndexes(segment_index); |