| ... | @@ -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; |
| 306 | | 306 | |
| 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; | | |
| 313 | | 308 | |
| | 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 | } |
| 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 | 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 | } |
| 1051 | | 1054 | |
| 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 | } |
| 1078 | | 1076 | |
| 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") or | 1128 | 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") or | 1139 | 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) orelse | 1142 | 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 | } |
| 1202 | | 1166 | |
| 1203 | pub fn createEmptyAtom(gpa: Allocator, sym_index: u32, size: u64, alignment: u32) !*Atom { | 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,12 +1363,17 @@ pub fn createTlvPtrAtom(self: *MachO, target: SymbolWithLoc) !*Atom { |
| 1399 | | 1363 | |
| 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; |
| 1408 | | 1377 | |
| 1409 | try self.allocateAtomCommon(atom); | 1378 | try self.allocateAtomCommon(atom); |
| 1410 | | 1379 | |
| ... | @@ -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 | } |
| 1762 | | 1735 | |
| 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 function | 2861 | // 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 | } |
| 2904 | | 2880 | |
| 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 | } |
| 2913 | | 2891 | |
| 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 | } |
| 3256 | | 3239 | |
| 3257 | pub fn populateMissingMetadata(self: *MachO) !void { | 3240 | pub 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 | |
| 3262 | | 3247 | 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 | } |
| 3277 | | 3257 | |
| 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 type | 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; | 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 | } |
| 3317 | | 3291 | |
| 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 type | 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; | 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 | } |
| 3341 | | 3310 | |
| 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_size | 3328 | self.stub_helper_section_index = try self.initSection("__TEXT", "__stub_helper", .{ |
| 3360 | else | 3329 | .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 | } |
| 3372 | | 3333 | |
| 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 | } |
| 3400 | | 3358 | |
| 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 | } |
| 3417 | | 3367 | |
| 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 | } |
| 3445 | | 3392 | |
| 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 | } |
| 3462 | | 3401 | |
| 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 | } |
| 3477 | | 3408 | |
| 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 | } |
| 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 | pub fn calcMinHeaderPad(self: *MachO) !u64 { | 3530 | pub 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 | } |
| 3605 | | 3546 | |
| 3606 | const InitSectionOpts = struct { | 3547 | fn 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 | | | |
| 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).?; | | |
| 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); |
| 3631 | | 3559 | } 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; |
| 3636 | | 3564 | 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); | | |
| 3658 | | 3566 | |
| 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; |
| 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 | fn getSectionPrecedence(header: macho.section_64) u4 { | 3585 | fn 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 | } |
| 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 | fn insertSection(self: *MachO, segment_index: u8, header: macho.section_64) !u8 { | 3633 | fn 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); |