| ... | ... | @@ -1133,20 +1133,19 @@ pub const MatchingSection = struct { |
| 1133 | 1133 | }; |
| 1134 | 1134 | |
| 1135 | 1135 | pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSection { |
| 1136 | | const text_seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 1137 | | const data_const_seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; |
| 1138 | | const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 1139 | 1136 | const segname = commands.segmentName(sect); |
| 1140 | 1137 | const sectname = commands.sectionName(sect); |
| 1141 | | |
| 1142 | | var needs_allocation = false; |
| 1143 | 1138 | const res: ?MatchingSection = blk: { |
| 1144 | 1139 | switch (commands.sectionType(sect)) { |
| 1145 | 1140 | macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => { |
| 1146 | 1141 | if (self.text_const_section_index == null) { |
| 1147 | | self.text_const_section_index = @intCast(u16, text_seg.sections.items.len); |
| 1148 | | try text_seg.addSection(self.base.allocator, "__const", .{}); |
| 1149 | | needs_allocation = true; |
| 1142 | self.text_const_section_index = try self.allocateSection( |
| 1143 | self.text_segment_cmd_index.?, |
| 1144 | "__const", |
| 1145 | sect.size, |
| 1146 | sect.@"align", |
| 1147 | .{}, |
| 1148 | ); |
| 1150 | 1149 | } |
| 1151 | 1150 | |
| 1152 | 1151 | break :blk .{ |
| ... | ... | @@ -1159,11 +1158,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1159 | 1158 | // TODO it seems the common values within the sections in objects are deduplicated/merged |
| 1160 | 1159 | // on merging the sections' contents. |
| 1161 | 1160 | if (self.objc_methname_section_index == null) { |
| 1162 | | self.objc_methname_section_index = @intCast(u16, text_seg.sections.items.len); |
| 1163 | | try text_seg.addSection(self.base.allocator, "__objc_methname", .{ |
| 1164 | | .flags = macho.S_CSTRING_LITERALS, |
| 1165 | | }); |
| 1166 | | needs_allocation = true; |
| 1161 | self.objc_methname_section_index = try self.allocateSection( |
| 1162 | self.text_segment_cmd_index.?, |
| 1163 | "__objc_methname", |
| 1164 | sect.size, |
| 1165 | sect.@"align", |
| 1166 | .{}, |
| 1167 | ); |
| 1167 | 1168 | } |
| 1168 | 1169 | |
| 1169 | 1170 | break :blk .{ |
| ... | ... | @@ -1172,11 +1173,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1172 | 1173 | }; |
| 1173 | 1174 | } else if (mem.eql(u8, sectname, "__objc_methtype")) { |
| 1174 | 1175 | if (self.objc_methtype_section_index == null) { |
| 1175 | | self.objc_methtype_section_index = @intCast(u16, text_seg.sections.items.len); |
| 1176 | | try text_seg.addSection(self.base.allocator, "__objc_methtype", .{ |
| 1177 | | .flags = macho.S_CSTRING_LITERALS, |
| 1178 | | }); |
| 1179 | | needs_allocation = true; |
| 1176 | self.objc_methtype_section_index = try self.allocateSection( |
| 1177 | self.text_segment_cmd_index.?, |
| 1178 | "__objc_methtype", |
| 1179 | sect.size, |
| 1180 | sect.@"align", |
| 1181 | .{}, |
| 1182 | ); |
| 1180 | 1183 | } |
| 1181 | 1184 | |
| 1182 | 1185 | break :blk .{ |
| ... | ... | @@ -1185,9 +1188,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1185 | 1188 | }; |
| 1186 | 1189 | } else if (mem.eql(u8, sectname, "__objc_classname")) { |
| 1187 | 1190 | if (self.objc_classname_section_index == null) { |
| 1188 | | self.objc_classname_section_index = @intCast(u16, text_seg.sections.items.len); |
| 1189 | | try text_seg.addSection(self.base.allocator, "__objc_classname", .{}); |
| 1190 | | needs_allocation = true; |
| 1191 | self.objc_classname_section_index = try self.allocateSection( |
| 1192 | self.text_segment_cmd_index.?, |
| 1193 | "__objc_classname", |
| 1194 | sect.size, |
| 1195 | sect.@"align", |
| 1196 | .{}, |
| 1197 | ); |
| 1191 | 1198 | } |
| 1192 | 1199 | |
| 1193 | 1200 | break :blk .{ |
| ... | ... | @@ -1197,11 +1204,15 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1197 | 1204 | } |
| 1198 | 1205 | |
| 1199 | 1206 | if (self.cstring_section_index == null) { |
| 1200 | | self.cstring_section_index = @intCast(u16, text_seg.sections.items.len); |
| 1201 | | try text_seg.addSection(self.base.allocator, "__cstring", .{ |
| 1202 | | .flags = macho.S_CSTRING_LITERALS, |
| 1203 | | }); |
| 1204 | | needs_allocation = true; |
| 1207 | self.cstring_section_index = try self.allocateSection( |
| 1208 | self.text_segment_cmd_index.?, |
| 1209 | "__cstring", |
| 1210 | sect.size, |
| 1211 | sect.@"align", |
| 1212 | .{ |
| 1213 | .flags = macho.S_CSTRING_LITERALS, |
| 1214 | }, |
| 1215 | ); |
| 1205 | 1216 | } |
| 1206 | 1217 | |
| 1207 | 1218 | break :blk .{ |
| ... | ... | @@ -1212,29 +1223,37 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1212 | 1223 | macho.S_LITERAL_POINTERS => { |
| 1213 | 1224 | if (mem.eql(u8, segname, "__DATA") and mem.eql(u8, sectname, "__objc_selrefs")) { |
| 1214 | 1225 | if (self.objc_selrefs_section_index == null) { |
| 1215 | | self.objc_selrefs_section_index = @intCast(u16, data_seg.sections.items.len); |
| 1216 | | try data_seg.addSection(self.base.allocator, "__objc_selrefs", .{ |
| 1217 | | .flags = macho.S_LITERAL_POINTERS, |
| 1218 | | }); |
| 1219 | | needs_allocation = true; |
| 1226 | self.objc_selrefs_section_index = try self.allocateSection( |
| 1227 | self.data_segment_cmd_index.?, |
| 1228 | "__objc_selrefs", |
| 1229 | sect.size, |
| 1230 | sect.@"align", |
| 1231 | .{ |
| 1232 | .flags = macho.S_LITERAL_POINTERS, |
| 1233 | }, |
| 1234 | ); |
| 1220 | 1235 | } |
| 1221 | 1236 | |
| 1222 | 1237 | break :blk .{ |
| 1223 | 1238 | .seg = self.data_segment_cmd_index.?, |
| 1224 | 1239 | .sect = self.objc_selrefs_section_index.?, |
| 1225 | 1240 | }; |
| 1241 | } else { |
| 1242 | // TODO investigate |
| 1243 | break :blk null; |
| 1226 | 1244 | } |
| 1227 | | |
| 1228 | | // TODO investigate |
| 1229 | | break :blk null; |
| 1230 | 1245 | }, |
| 1231 | 1246 | macho.S_MOD_INIT_FUNC_POINTERS => { |
| 1232 | 1247 | if (self.mod_init_func_section_index == null) { |
| 1233 | | self.mod_init_func_section_index = @intCast(u16, data_const_seg.sections.items.len); |
| 1234 | | try data_const_seg.addSection(self.base.allocator, "__mod_init_func", .{ |
| 1235 | | .flags = macho.S_MOD_INIT_FUNC_POINTERS, |
| 1236 | | }); |
| 1237 | | needs_allocation = true; |
| 1248 | self.mod_init_func_section_index = try self.allocateSection( |
| 1249 | self.data_const_segment_cmd_index.?, |
| 1250 | "__mod_init_func", |
| 1251 | sect.size, |
| 1252 | sect.@"align", |
| 1253 | .{ |
| 1254 | .flags = macho.S_MOD_INIT_FUNC_POINTERS, |
| 1255 | }, |
| 1256 | ); |
| 1238 | 1257 | } |
| 1239 | 1258 | |
| 1240 | 1259 | break :blk .{ |
| ... | ... | @@ -1244,11 +1263,15 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1244 | 1263 | }, |
| 1245 | 1264 | macho.S_MOD_TERM_FUNC_POINTERS => { |
| 1246 | 1265 | if (self.mod_term_func_section_index == null) { |
| 1247 | | self.mod_term_func_section_index = @intCast(u16, data_const_seg.sections.items.len); |
| 1248 | | try data_const_seg.addSection(self.base.allocator, "__mod_term_func", .{ |
| 1249 | | .flags = macho.S_MOD_TERM_FUNC_POINTERS, |
| 1250 | | }); |
| 1251 | | needs_allocation = true; |
| 1266 | self.mod_term_func_section_index = try self.allocateSection( |
| 1267 | self.data_const_segment_cmd_index.?, |
| 1268 | "__mod_term_func", |
| 1269 | sect.size, |
| 1270 | sect.@"align", |
| 1271 | .{ |
| 1272 | .flags = macho.S_MOD_TERM_FUNC_POINTERS, |
| 1273 | }, |
| 1274 | ); |
| 1252 | 1275 | } |
| 1253 | 1276 | |
| 1254 | 1277 | break :blk .{ |
| ... | ... | @@ -1258,11 +1281,15 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1258 | 1281 | }, |
| 1259 | 1282 | macho.S_ZEROFILL => { |
| 1260 | 1283 | if (self.bss_section_index == null) { |
| 1261 | | self.bss_section_index = @intCast(u16, data_seg.sections.items.len); |
| 1262 | | try data_seg.addSection(self.base.allocator, "__bss", .{ |
| 1263 | | .flags = macho.S_ZEROFILL, |
| 1264 | | }); |
| 1265 | | needs_allocation = true; |
| 1284 | self.bss_section_index = try self.allocateSection( |
| 1285 | self.data_segment_cmd_index.?, |
| 1286 | "__bss", |
| 1287 | sect.size, |
| 1288 | sect.@"align", |
| 1289 | .{ |
| 1290 | .flags = macho.S_ZEROFILL, |
| 1291 | }, |
| 1292 | ); |
| 1266 | 1293 | } |
| 1267 | 1294 | |
| 1268 | 1295 | break :blk .{ |
| ... | ... | @@ -1272,11 +1299,15 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1272 | 1299 | }, |
| 1273 | 1300 | macho.S_THREAD_LOCAL_VARIABLES => { |
| 1274 | 1301 | if (self.tlv_section_index == null) { |
| 1275 | | self.tlv_section_index = @intCast(u16, data_seg.sections.items.len); |
| 1276 | | try data_seg.addSection(self.base.allocator, "__thread_vars", .{ |
| 1277 | | .flags = macho.S_THREAD_LOCAL_VARIABLES, |
| 1278 | | }); |
| 1279 | | needs_allocation = true; |
| 1302 | self.tlv_section_index = try self.allocateSection( |
| 1303 | self.data_segment_cmd_index.?, |
| 1304 | "__thread_vars", |
| 1305 | sect.size, |
| 1306 | sect.@"align", |
| 1307 | .{ |
| 1308 | .flags = macho.S_THREAD_LOCAL_VARIABLES, |
| 1309 | }, |
| 1310 | ); |
| 1280 | 1311 | } |
| 1281 | 1312 | |
| 1282 | 1313 | break :blk .{ |
| ... | ... | @@ -1286,11 +1317,15 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1286 | 1317 | }, |
| 1287 | 1318 | macho.S_THREAD_LOCAL_REGULAR => { |
| 1288 | 1319 | if (self.tlv_data_section_index == null) { |
| 1289 | | self.tlv_data_section_index = @intCast(u16, data_seg.sections.items.len); |
| 1290 | | try data_seg.addSection(self.base.allocator, "__thread_data", .{ |
| 1291 | | .flags = macho.S_THREAD_LOCAL_REGULAR, |
| 1292 | | }); |
| 1293 | | needs_allocation = true; |
| 1320 | self.tlv_data_section_index = try self.allocateSection( |
| 1321 | self.data_segment_cmd_index.?, |
| 1322 | "__thread_data", |
| 1323 | sect.size, |
| 1324 | sect.@"align", |
| 1325 | .{ |
| 1326 | .flags = macho.S_THREAD_LOCAL_REGULAR, |
| 1327 | }, |
| 1328 | ); |
| 1294 | 1329 | } |
| 1295 | 1330 | |
| 1296 | 1331 | break :blk .{ |
| ... | ... | @@ -1300,11 +1335,15 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1300 | 1335 | }, |
| 1301 | 1336 | macho.S_THREAD_LOCAL_ZEROFILL => { |
| 1302 | 1337 | if (self.tlv_bss_section_index == null) { |
| 1303 | | self.tlv_bss_section_index = @intCast(u16, data_seg.sections.items.len); |
| 1304 | | try data_seg.addSection(self.base.allocator, "__thread_bss", .{ |
| 1305 | | .flags = macho.S_THREAD_LOCAL_ZEROFILL, |
| 1306 | | }); |
| 1307 | | needs_allocation = true; |
| 1338 | self.tlv_bss_section_index = try self.allocateSection( |
| 1339 | self.data_segment_cmd_index.?, |
| 1340 | "__thread_bss", |
| 1341 | sect.size, |
| 1342 | sect.@"align", |
| 1343 | .{ |
| 1344 | .flags = macho.S_THREAD_LOCAL_ZEROFILL, |
| 1345 | }, |
| 1346 | ); |
| 1308 | 1347 | } |
| 1309 | 1348 | |
| 1310 | 1349 | break :blk .{ |
| ... | ... | @@ -1317,9 +1356,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1317 | 1356 | // TODO I believe __eh_frame is currently part of __unwind_info section |
| 1318 | 1357 | // in the latest ld64 output. |
| 1319 | 1358 | if (self.eh_frame_section_index == null) { |
| 1320 | | self.eh_frame_section_index = @intCast(u16, text_seg.sections.items.len); |
| 1321 | | try text_seg.addSection(self.base.allocator, "__eh_frame", .{}); |
| 1322 | | needs_allocation = true; |
| 1359 | self.eh_frame_section_index = try self.allocateSection( |
| 1360 | self.text_segment_cmd_index.?, |
| 1361 | "__eh_frame", |
| 1362 | sect.size, |
| 1363 | sect.@"align", |
| 1364 | .{}, |
| 1365 | ); |
| 1323 | 1366 | } |
| 1324 | 1367 | |
| 1325 | 1368 | break :blk .{ |
| ... | ... | @@ -1330,9 +1373,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1330 | 1373 | |
| 1331 | 1374 | // TODO audit this: is this the right mapping? |
| 1332 | 1375 | if (self.data_const_section_index == null) { |
| 1333 | | self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len); |
| 1334 | | try data_const_seg.addSection(self.base.allocator, "__const", .{}); |
| 1335 | | needs_allocation = true; |
| 1376 | self.data_const_section_index = try self.allocateSection( |
| 1377 | self.data_const_segment_cmd_index.?, |
| 1378 | "__const", |
| 1379 | sect.size, |
| 1380 | sect.@"align", |
| 1381 | .{}, |
| 1382 | ); |
| 1336 | 1383 | } |
| 1337 | 1384 | |
| 1338 | 1385 | break :blk .{ |
| ... | ... | @@ -1343,11 +1390,17 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1343 | 1390 | macho.S_REGULAR => { |
| 1344 | 1391 | if (commands.sectionIsCode(sect)) { |
| 1345 | 1392 | if (self.text_section_index == null) { |
| 1346 | | self.text_section_index = @intCast(u16, text_seg.sections.items.len); |
| 1347 | | try text_seg.addSection(self.base.allocator, "__text", .{ |
| 1348 | | .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS, |
| 1349 | | }); |
| 1350 | | needs_allocation = true; |
| 1393 | self.text_section_index = try self.allocateSection( |
| 1394 | self.text_segment_cmd_index.?, |
| 1395 | "__text", |
| 1396 | sect.size, |
| 1397 | sect.@"align", |
| 1398 | .{ |
| 1399 | .flags = macho.S_REGULAR | |
| 1400 | macho.S_ATTR_PURE_INSTRUCTIONS | |
| 1401 | macho.S_ATTR_SOME_INSTRUCTIONS, |
| 1402 | }, |
| 1403 | ); |
| 1351 | 1404 | } |
| 1352 | 1405 | |
| 1353 | 1406 | break :blk .{ |
| ... | ... | @@ -1368,9 +1421,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1368 | 1421 | if (mem.eql(u8, segname, "__TEXT")) { |
| 1369 | 1422 | if (mem.eql(u8, sectname, "__ustring")) { |
| 1370 | 1423 | if (self.ustring_section_index == null) { |
| 1371 | | self.ustring_section_index = @intCast(u16, text_seg.sections.items.len); |
| 1372 | | try text_seg.addSection(self.base.allocator, "__ustring", .{}); |
| 1373 | | needs_allocation = true; |
| 1424 | self.ustring_section_index = try self.allocateSection( |
| 1425 | self.text_segment_cmd_index.?, |
| 1426 | "__ustring", |
| 1427 | sect.size, |
| 1428 | sect.@"align", |
| 1429 | .{}, |
| 1430 | ); |
| 1374 | 1431 | } |
| 1375 | 1432 | |
| 1376 | 1433 | break :blk .{ |
| ... | ... | @@ -1379,9 +1436,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1379 | 1436 | }; |
| 1380 | 1437 | } else if (mem.eql(u8, sectname, "__gcc_except_tab")) { |
| 1381 | 1438 | if (self.gcc_except_tab_section_index == null) { |
| 1382 | | self.gcc_except_tab_section_index = @intCast(u16, text_seg.sections.items.len); |
| 1383 | | try text_seg.addSection(self.base.allocator, "__gcc_except_tab", .{}); |
| 1384 | | needs_allocation = true; |
| 1439 | self.gcc_except_tab_section_index = try self.allocateSection( |
| 1440 | self.text_segment_cmd_index.?, |
| 1441 | "__gcc_except_tab", |
| 1442 | sect.size, |
| 1443 | sect.@"align", |
| 1444 | .{}, |
| 1445 | ); |
| 1385 | 1446 | } |
| 1386 | 1447 | |
| 1387 | 1448 | break :blk .{ |
| ... | ... | @@ -1390,9 +1451,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1390 | 1451 | }; |
| 1391 | 1452 | } else if (mem.eql(u8, sectname, "__objc_methlist")) { |
| 1392 | 1453 | if (self.objc_methlist_section_index == null) { |
| 1393 | | self.objc_methlist_section_index = @intCast(u16, text_seg.sections.items.len); |
| 1394 | | try text_seg.addSection(self.base.allocator, "__objc_methlist", .{}); |
| 1395 | | needs_allocation = true; |
| 1454 | self.objc_methlist_section_index = try self.allocateSection( |
| 1455 | self.text_segment_cmd_index.?, |
| 1456 | "__objc_methlist", |
| 1457 | sect.size, |
| 1458 | sect.@"align", |
| 1459 | .{}, |
| 1460 | ); |
| 1396 | 1461 | } |
| 1397 | 1462 | |
| 1398 | 1463 | break :blk .{ |
| ... | ... | @@ -1406,9 +1471,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1406 | 1471 | mem.eql(u8, sectname, "__gopclntab")) |
| 1407 | 1472 | { |
| 1408 | 1473 | if (self.data_const_section_index == null) { |
| 1409 | | self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len); |
| 1410 | | try data_const_seg.addSection(self.base.allocator, "__const", .{}); |
| 1411 | | needs_allocation = true; |
| 1474 | self.data_const_section_index = try self.allocateSection( |
| 1475 | self.data_const_segment_cmd_index.?, |
| 1476 | "__const", |
| 1477 | sect.size, |
| 1478 | sect.@"align", |
| 1479 | .{}, |
| 1480 | ); |
| 1412 | 1481 | } |
| 1413 | 1482 | |
| 1414 | 1483 | break :blk .{ |
| ... | ... | @@ -1417,9 +1486,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1417 | 1486 | }; |
| 1418 | 1487 | } else { |
| 1419 | 1488 | if (self.text_const_section_index == null) { |
| 1420 | | self.text_const_section_index = @intCast(u16, text_seg.sections.items.len); |
| 1421 | | try text_seg.addSection(self.base.allocator, "__const", .{}); |
| 1422 | | needs_allocation = true; |
| 1489 | self.text_const_section_index = try self.allocateSection( |
| 1490 | self.text_segment_cmd_index.?, |
| 1491 | "__const", |
| 1492 | sect.size, |
| 1493 | sect.@"align", |
| 1494 | .{}, |
| 1495 | ); |
| 1423 | 1496 | } |
| 1424 | 1497 | |
| 1425 | 1498 | break :blk .{ |
| ... | ... | @@ -1431,9 +1504,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1431 | 1504 | |
| 1432 | 1505 | if (mem.eql(u8, segname, "__DATA_CONST")) { |
| 1433 | 1506 | if (self.data_const_section_index == null) { |
| 1434 | | self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len); |
| 1435 | | try data_const_seg.addSection(self.base.allocator, "__const", .{}); |
| 1436 | | needs_allocation = true; |
| 1507 | self.data_const_section_index = try self.allocateSection( |
| 1508 | self.data_const_segment_cmd_index.?, |
| 1509 | "__const", |
| 1510 | sect.size, |
| 1511 | sect.@"align", |
| 1512 | .{}, |
| 1513 | ); |
| 1437 | 1514 | } |
| 1438 | 1515 | |
| 1439 | 1516 | break :blk .{ |
| ... | ... | @@ -1445,9 +1522,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1445 | 1522 | if (mem.eql(u8, segname, "__DATA")) { |
| 1446 | 1523 | if (mem.eql(u8, sectname, "__const")) { |
| 1447 | 1524 | if (self.data_const_section_index == null) { |
| 1448 | | self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len); |
| 1449 | | try data_const_seg.addSection(self.base.allocator, "__const", .{}); |
| 1450 | | needs_allocation = true; |
| 1525 | self.data_const_section_index = try self.allocateSection( |
| 1526 | self.data_const_segment_cmd_index.?, |
| 1527 | "__const", |
| 1528 | sect.size, |
| 1529 | sect.@"align", |
| 1530 | .{}, |
| 1531 | ); |
| 1451 | 1532 | } |
| 1452 | 1533 | |
| 1453 | 1534 | break :blk .{ |
| ... | ... | @@ -1456,9 +1537,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1456 | 1537 | }; |
| 1457 | 1538 | } else if (mem.eql(u8, sectname, "__cfstring")) { |
| 1458 | 1539 | if (self.objc_cfstring_section_index == null) { |
| 1459 | | self.objc_cfstring_section_index = @intCast(u16, data_const_seg.sections.items.len); |
| 1460 | | try data_const_seg.addSection(self.base.allocator, "__cfstring", .{}); |
| 1461 | | needs_allocation = true; |
| 1540 | self.objc_cfstring_section_index = try self.allocateSection( |
| 1541 | self.data_const_segment_cmd_index.?, |
| 1542 | "__cfstring", |
| 1543 | sect.size, |
| 1544 | sect.@"align", |
| 1545 | .{}, |
| 1546 | ); |
| 1462 | 1547 | } |
| 1463 | 1548 | |
| 1464 | 1549 | break :blk .{ |
| ... | ... | @@ -1467,9 +1552,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1467 | 1552 | }; |
| 1468 | 1553 | } else if (mem.eql(u8, sectname, "__objc_classlist")) { |
| 1469 | 1554 | if (self.objc_classlist_section_index == null) { |
| 1470 | | self.objc_classlist_section_index = @intCast(u16, data_const_seg.sections.items.len); |
| 1471 | | try data_const_seg.addSection(self.base.allocator, "__objc_classlist", .{}); |
| 1472 | | needs_allocation = true; |
| 1555 | self.objc_classlist_section_index = try self.allocateSection( |
| 1556 | self.data_const_segment_cmd_index.?, |
| 1557 | "__objc_classlist", |
| 1558 | sect.size, |
| 1559 | sect.@"align", |
| 1560 | .{}, |
| 1561 | ); |
| 1473 | 1562 | } |
| 1474 | 1563 | |
| 1475 | 1564 | break :blk .{ |
| ... | ... | @@ -1478,9 +1567,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1478 | 1567 | }; |
| 1479 | 1568 | } else if (mem.eql(u8, sectname, "__objc_imageinfo")) { |
| 1480 | 1569 | if (self.objc_imageinfo_section_index == null) { |
| 1481 | | self.objc_imageinfo_section_index = @intCast(u16, data_const_seg.sections.items.len); |
| 1482 | | try data_const_seg.addSection(self.base.allocator, "__objc_imageinfo", .{}); |
| 1483 | | needs_allocation = true; |
| 1570 | self.objc_imageinfo_section_index = try self.allocateSection( |
| 1571 | self.data_const_segment_cmd_index.?, |
| 1572 | "__objc_imageinfo", |
| 1573 | sect.size, |
| 1574 | sect.@"align", |
| 1575 | .{}, |
| 1576 | ); |
| 1484 | 1577 | } |
| 1485 | 1578 | |
| 1486 | 1579 | break :blk .{ |
| ... | ... | @@ -1489,9 +1582,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1489 | 1582 | }; |
| 1490 | 1583 | } else if (mem.eql(u8, sectname, "__objc_const")) { |
| 1491 | 1584 | if (self.objc_const_section_index == null) { |
| 1492 | | self.objc_const_section_index = @intCast(u16, data_seg.sections.items.len); |
| 1493 | | try data_seg.addSection(self.base.allocator, "__objc_const", .{}); |
| 1494 | | needs_allocation = true; |
| 1585 | self.objc_const_section_index = try self.allocateSection( |
| 1586 | self.data_segment_cmd_index.?, |
| 1587 | "__objc_const", |
| 1588 | sect.size, |
| 1589 | sect.@"align", |
| 1590 | .{}, |
| 1591 | ); |
| 1495 | 1592 | } |
| 1496 | 1593 | |
| 1497 | 1594 | break :blk .{ |
| ... | ... | @@ -1500,9 +1597,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1500 | 1597 | }; |
| 1501 | 1598 | } else if (mem.eql(u8, sectname, "__objc_classrefs")) { |
| 1502 | 1599 | if (self.objc_classrefs_section_index == null) { |
| 1503 | | self.objc_classrefs_section_index = @intCast(u16, data_seg.sections.items.len); |
| 1504 | | try data_seg.addSection(self.base.allocator, "__objc_classrefs", .{}); |
| 1505 | | needs_allocation = true; |
| 1600 | self.objc_classrefs_section_index = try self.allocateSection( |
| 1601 | self.data_segment_cmd_index.?, |
| 1602 | "__objc_classrefs", |
| 1603 | sect.size, |
| 1604 | sect.@"align", |
| 1605 | .{}, |
| 1606 | ); |
| 1506 | 1607 | } |
| 1507 | 1608 | |
| 1508 | 1609 | break :blk .{ |
| ... | ... | @@ -1511,9 +1612,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1511 | 1612 | }; |
| 1512 | 1613 | } else if (mem.eql(u8, sectname, "__objc_data")) { |
| 1513 | 1614 | if (self.objc_data_section_index == null) { |
| 1514 | | self.objc_data_section_index = @intCast(u16, data_seg.sections.items.len); |
| 1515 | | try data_seg.addSection(self.base.allocator, "__objc_data", .{}); |
| 1516 | | needs_allocation = true; |
| 1615 | self.objc_data_section_index = try self.allocateSection( |
| 1616 | self.data_segment_cmd_index.?, |
| 1617 | "__objc_data", |
| 1618 | sect.size, |
| 1619 | sect.@"align", |
| 1620 | .{}, |
| 1621 | ); |
| 1517 | 1622 | } |
| 1518 | 1623 | |
| 1519 | 1624 | break :blk .{ |
| ... | ... | @@ -1522,9 +1627,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1522 | 1627 | }; |
| 1523 | 1628 | } else { |
| 1524 | 1629 | if (self.data_section_index == null) { |
| 1525 | | self.data_section_index = @intCast(u16, data_seg.sections.items.len); |
| 1526 | | try data_seg.addSection(self.base.allocator, "__data", .{}); |
| 1527 | | needs_allocation = true; |
| 1630 | self.data_section_index = try self.allocateSection( |
| 1631 | self.data_segment_cmd_index.?, |
| 1632 | "__data", |
| 1633 | sect.size, |
| 1634 | sect.@"align", |
| 1635 | .{}, |
| 1636 | ); |
| 1528 | 1637 | } |
| 1529 | 1638 | |
| 1530 | 1639 | break :blk .{ |
| ... | ... | @@ -1545,42 +1654,6 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio |
| 1545 | 1654 | else => break :blk null, |
| 1546 | 1655 | } |
| 1547 | 1656 | }; |
| 1548 | | |
| 1549 | | if (res) |match| { |
| 1550 | | _ = try self.section_ordinals.getOrPut(self.base.allocator, match); |
| 1551 | | _ = try self.block_free_lists.getOrPutValue(self.base.allocator, match, .{}); |
| 1552 | | |
| 1553 | | const use_stage1 = build_options.is_stage1 and self.base.options.use_stage1; |
| 1554 | | if (!use_stage1) { |
| 1555 | | const target_seg = &self.load_commands.items[match.seg].Segment; |
| 1556 | | const target_sect = &target_seg.sections.items[match.sect]; |
| 1557 | | |
| 1558 | | // Update section's alignment |
| 1559 | | // TODO if sect.@"align" > target_sect.@"align", should we move the entire |
| 1560 | | // section to match the required alignment? |
| 1561 | | target_sect.@"align" = math.max(target_sect.@"align", sect.@"align"); |
| 1562 | | |
| 1563 | | if (needs_allocation) { |
| 1564 | | const alignment = try math.powi(u32, 2, target_sect.@"align"); |
| 1565 | | const needed_size = sect.size; |
| 1566 | | const off = target_seg.findFreeSpace(needed_size, alignment, self.header_pad); |
| 1567 | | assert(off + needed_size <= target_seg.inner.fileoff + target_seg.inner.filesize); // TODO expand |
| 1568 | | |
| 1569 | | log.debug("found {s},{s} section free space 0x{x} to 0x{x}", .{ |
| 1570 | | segname, |
| 1571 | | sectname, |
| 1572 | | off, |
| 1573 | | off + needed_size, |
| 1574 | | }); |
| 1575 | | |
| 1576 | | target_sect.addr = target_seg.inner.vmaddr + off; |
| 1577 | | target_sect.size = needed_size; |
| 1578 | | target_sect.offset = @intCast(u32, off); |
| 1579 | | self.load_commands_dirty = true; |
| 1580 | | } |
| 1581 | | } |
| 1582 | | } |
| 1583 | | |
| 1584 | 1657 | return res; |
| 1585 | 1658 | } |
| 1586 | 1659 | |
| ... | ... | @@ -3878,9 +3951,12 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3878 | 3951 | if (self.pagezero_segment_cmd_index == null) { |
| 3879 | 3952 | self.pagezero_segment_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 3880 | 3953 | try self.load_commands.append(self.base.allocator, .{ |
| 3881 | | .Segment = SegmentCommand.empty("__PAGEZERO", .{ |
| 3882 | | .vmsize = 0x100000000, // size always set to 4GB |
| 3883 | | }), |
| 3954 | .Segment = .{ |
| 3955 | .inner = .{ |
| 3956 | .segname = makeStaticString("__PAGEZERO"), |
| 3957 | .vmsize = 0x100000000, // size always set to 4GB |
| 3958 | }, |
| 3959 | }, |
| 3884 | 3960 | }); |
| 3885 | 3961 | self.load_commands_dirty = true; |
| 3886 | 3962 | } |
| ... | ... | @@ -3895,51 +3971,39 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3895 | 3971 | log.debug("found __TEXT segment free space 0x{x} to 0x{x}", .{ 0, needed_size }); |
| 3896 | 3972 | |
| 3897 | 3973 | try self.load_commands.append(self.base.allocator, .{ |
| 3898 | | .Segment = SegmentCommand.empty("__TEXT", .{ |
| 3899 | | .vmaddr = 0x100000000, // always starts at 4GB |
| 3900 | | .vmsize = needed_size, |
| 3901 | | .filesize = needed_size, |
| 3902 | | .maxprot = macho.VM_PROT_READ | macho.VM_PROT_EXECUTE, |
| 3903 | | .initprot = macho.VM_PROT_READ | macho.VM_PROT_EXECUTE, |
| 3904 | | }), |
| 3974 | .Segment = .{ |
| 3975 | .inner = .{ |
| 3976 | .segname = makeStaticString("__TEXT"), |
| 3977 | .vmaddr = 0x100000000, // always starts at 4GB |
| 3978 | .vmsize = needed_size, |
| 3979 | .filesize = needed_size, |
| 3980 | .maxprot = macho.VM_PROT_READ | macho.VM_PROT_EXECUTE, |
| 3981 | .initprot = macho.VM_PROT_READ | macho.VM_PROT_EXECUTE, |
| 3982 | }, |
| 3983 | }, |
| 3905 | 3984 | }); |
| 3906 | 3985 | self.load_commands_dirty = true; |
| 3907 | 3986 | } |
| 3908 | 3987 | |
| 3909 | 3988 | if (self.text_section_index == null) { |
| 3910 | | const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 3911 | | self.text_section_index = @intCast(u16, text_segment.sections.items.len); |
| 3912 | | |
| 3913 | 3989 | const alignment: u2 = switch (self.base.options.target.cpu.arch) { |
| 3914 | 3990 | .x86_64 => 0, |
| 3915 | 3991 | .aarch64 => 2, |
| 3916 | 3992 | else => unreachable, // unhandled architecture type |
| 3917 | 3993 | }; |
| 3918 | 3994 | const needed_size = self.base.options.program_code_size_hint; |
| 3919 | | const off = text_segment.findFreeSpace(needed_size, @as(u16, 1) << alignment, self.header_pad); |
| 3920 | | |
| 3921 | | log.debug("found __text section free space 0x{x} to 0x{x}", .{ off, off + needed_size }); |
| 3922 | | |
| 3923 | | try text_segment.addSection(self.base.allocator, "__text", .{ |
| 3924 | | .addr = text_segment.inner.vmaddr + off, |
| 3925 | | .size = @intCast(u32, needed_size), |
| 3926 | | .offset = @intCast(u32, off), |
| 3927 | | .@"align" = alignment, |
| 3928 | | .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS, |
| 3929 | | }); |
| 3930 | | const match = MatchingSection{ |
| 3931 | | .seg = self.text_segment_cmd_index.?, |
| 3932 | | .sect = self.text_section_index.?, |
| 3933 | | }; |
| 3934 | | _ = try self.section_ordinals.getOrPut(self.base.allocator, match); |
| 3935 | | try self.block_free_lists.putNoClobber(self.base.allocator, match, .{}); |
| 3936 | | self.load_commands_dirty = true; |
| 3995 | self.text_section_index = try self.allocateSection( |
| 3996 | self.text_segment_cmd_index.?, |
| 3997 | "__text", |
| 3998 | needed_size, |
| 3999 | alignment, |
| 4000 | .{ |
| 4001 | .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS, |
| 4002 | }, |
| 4003 | ); |
| 3937 | 4004 | } |
| 3938 | 4005 | |
| 3939 | 4006 | if (self.stubs_section_index == null) { |
| 3940 | | const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 3941 | | self.stubs_section_index = @intCast(u16, text_segment.sections.items.len); |
| 3942 | | |
| 3943 | 4007 | const alignment: u2 = switch (self.base.options.target.cpu.arch) { |
| 3944 | 4008 | .x86_64 => 0, |
| 3945 | 4009 | .aarch64 => 2, |
| ... | ... | @@ -3951,32 +4015,19 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3951 | 4015 | else => unreachable, // unhandled architecture type |
| 3952 | 4016 | }; |
| 3953 | 4017 | const needed_size = stub_size * self.base.options.symbol_count_hint; |
| 3954 | | const off = text_segment.findFreeSpace(needed_size, @alignOf(u64), self.header_pad); |
| 3955 | | assert(off + needed_size <= text_segment.inner.fileoff + text_segment.inner.filesize); // TODO Must expand __TEXT segment. |
| 3956 | | |
| 3957 | | log.debug("found __stubs section free space 0x{x} to 0x{x}", .{ off, off + needed_size }); |
| 3958 | | |
| 3959 | | try text_segment.addSection(self.base.allocator, "__stubs", .{ |
| 3960 | | .addr = text_segment.inner.vmaddr + off, |
| 3961 | | .size = needed_size, |
| 3962 | | .offset = @intCast(u32, off), |
| 3963 | | .@"align" = alignment, |
| 3964 | | .flags = macho.S_SYMBOL_STUBS | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS, |
| 3965 | | .reserved2 = stub_size, |
| 3966 | | }); |
| 3967 | | const match = MatchingSection{ |
| 3968 | | .seg = self.text_segment_cmd_index.?, |
| 3969 | | .sect = self.stubs_section_index.?, |
| 3970 | | }; |
| 3971 | | _ = try self.section_ordinals.getOrPut(self.base.allocator, match); |
| 3972 | | try self.block_free_lists.putNoClobber(self.base.allocator, match, .{}); |
| 3973 | | self.load_commands_dirty = true; |
| 4018 | self.stubs_section_index = try self.allocateSection( |
| 4019 | self.text_segment_cmd_index.?, |
| 4020 | "__stubs", |
| 4021 | needed_size, |
| 4022 | alignment, |
| 4023 | .{ |
| 4024 | .flags = macho.S_SYMBOL_STUBS | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS, |
| 4025 | .reserved2 = stub_size, |
| 4026 | }, |
| 4027 | ); |
| 3974 | 4028 | } |
| 3975 | 4029 | |
| 3976 | 4030 | if (self.stub_helper_section_index == null) { |
| 3977 | | const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 3978 | | self.stub_helper_section_index = @intCast(u16, text_segment.sections.items.len); |
| 3979 | | |
| 3980 | 4031 | const alignment: u2 = switch (self.base.options.target.cpu.arch) { |
| 3981 | 4032 | .x86_64 => 0, |
| 3982 | 4033 | .aarch64 => 2, |
| ... | ... | @@ -3993,25 +4044,15 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 3993 | 4044 | else => unreachable, |
| 3994 | 4045 | }; |
| 3995 | 4046 | const needed_size = stub_size * self.base.options.symbol_count_hint + preamble_size; |
| 3996 | | const off = text_segment.findFreeSpace(needed_size, @alignOf(u64), self.header_pad); |
| 3997 | | assert(off + needed_size <= text_segment.inner.fileoff + text_segment.inner.filesize); // TODO Must expand __TEXT segment. |
| 3998 | | |
| 3999 | | log.debug("found __stub_helper section free space 0x{x} to 0x{x}", .{ off, off + needed_size }); |
| 4000 | | |
| 4001 | | try text_segment.addSection(self.base.allocator, "__stub_helper", .{ |
| 4002 | | .addr = text_segment.inner.vmaddr + off, |
| 4003 | | .size = needed_size, |
| 4004 | | .offset = @intCast(u32, off), |
| 4005 | | .@"align" = alignment, |
| 4006 | | .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS, |
| 4007 | | }); |
| 4008 | | const match = MatchingSection{ |
| 4009 | | .seg = self.text_segment_cmd_index.?, |
| 4010 | | .sect = self.stub_helper_section_index.?, |
| 4011 | | }; |
| 4012 | | _ = try self.section_ordinals.getOrPut(self.base.allocator, match); |
| 4013 | | try self.block_free_lists.putNoClobber(self.base.allocator, match, .{}); |
| 4014 | | self.load_commands_dirty = true; |
| 4047 | self.stub_helper_section_index = try self.allocateSection( |
| 4048 | self.text_segment_cmd_index.?, |
| 4049 | "__stub_helper", |
| 4050 | needed_size, |
| 4051 | alignment, |
| 4052 | .{ |
| 4053 | .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS, |
| 4054 | }, |
| 4055 | ); |
| 4015 | 4056 | } |
| 4016 | 4057 | |
| 4017 | 4058 | if (self.data_const_segment_cmd_index == null) { |
| ... | ... | @@ -4020,45 +4061,39 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 4020 | 4061 | const ideal_size = @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 4021 | 4062 | const needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size); |
| 4022 | 4063 | |
| 4023 | | log.debug("found __DATA_CONST segment free space 0x{x} to 0x{x}", .{ address_and_offset.offset, address_and_offset.offset + needed_size }); |
| 4064 | log.debug("found __DATA_CONST segment free space 0x{x} to 0x{x}", .{ |
| 4065 | address_and_offset.offset, |
| 4066 | address_and_offset.offset + needed_size, |
| 4067 | }); |
| 4024 | 4068 | |
| 4025 | 4069 | try self.load_commands.append(self.base.allocator, .{ |
| 4026 | | .Segment = SegmentCommand.empty("__DATA_CONST", .{ |
| 4027 | | .vmaddr = address_and_offset.address, |
| 4028 | | .vmsize = needed_size, |
| 4029 | | .fileoff = address_and_offset.offset, |
| 4030 | | .filesize = needed_size, |
| 4031 | | .maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE, |
| 4032 | | .initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE, |
| 4033 | | }), |
| 4070 | .Segment = .{ |
| 4071 | .inner = .{ |
| 4072 | .segname = makeStaticString("__DATA_CONST"), |
| 4073 | .vmaddr = address_and_offset.address, |
| 4074 | .vmsize = needed_size, |
| 4075 | .fileoff = address_and_offset.offset, |
| 4076 | .filesize = needed_size, |
| 4077 | .maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE, |
| 4078 | .initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE, |
| 4079 | }, |
| 4080 | }, |
| 4034 | 4081 | }); |
| 4035 | 4082 | self.load_commands_dirty = true; |
| 4036 | 4083 | } |
| 4037 | 4084 | |
| 4038 | 4085 | if (self.got_section_index == null) { |
| 4039 | | const dc_segment = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; |
| 4040 | | self.got_section_index = @intCast(u16, dc_segment.sections.items.len); |
| 4041 | | |
| 4042 | 4086 | const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 4043 | | const off = dc_segment.findFreeSpace(needed_size, @alignOf(u64), null); |
| 4044 | | assert(off + needed_size <= dc_segment.inner.fileoff + dc_segment.inner.filesize); // TODO Must expand __DATA_CONST segment. |
| 4045 | | |
| 4046 | | log.debug("found __got section free space 0x{x} to 0x{x}", .{ off, off + needed_size }); |
| 4047 | | |
| 4048 | | try dc_segment.addSection(self.base.allocator, "__got", .{ |
| 4049 | | .addr = dc_segment.inner.vmaddr + off - dc_segment.inner.fileoff, |
| 4050 | | .size = needed_size, |
| 4051 | | .offset = @intCast(u32, off), |
| 4052 | | .@"align" = 3, // 2^3 = @sizeOf(u64) |
| 4053 | | .flags = macho.S_NON_LAZY_SYMBOL_POINTERS, |
| 4054 | | }); |
| 4055 | | const match = MatchingSection{ |
| 4056 | | .seg = self.data_const_segment_cmd_index.?, |
| 4057 | | .sect = self.got_section_index.?, |
| 4058 | | }; |
| 4059 | | _ = try self.section_ordinals.getOrPut(self.base.allocator, match); |
| 4060 | | try self.block_free_lists.putNoClobber(self.base.allocator, match, .{}); |
| 4061 | | self.load_commands_dirty = true; |
| 4087 | const alignment: u16 = 3; // 2^3 = @sizeOf(u64) |
| 4088 | self.got_section_index = try self.allocateSection( |
| 4089 | self.data_const_segment_cmd_index.?, |
| 4090 | "__got", |
| 4091 | needed_size, |
| 4092 | alignment, |
| 4093 | .{ |
| 4094 | .flags = macho.S_NON_LAZY_SYMBOL_POINTERS, |
| 4095 | }, |
| 4096 | ); |
| 4062 | 4097 | } |
| 4063 | 4098 | |
| 4064 | 4099 | if (self.data_segment_cmd_index == null) { |
| ... | ... | @@ -4070,175 +4105,115 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 4070 | 4105 | log.debug("found __DATA segment free space 0x{x} to 0x{x}", .{ address_and_offset.offset, address_and_offset.offset + needed_size }); |
| 4071 | 4106 | |
| 4072 | 4107 | try self.load_commands.append(self.base.allocator, .{ |
| 4073 | | .Segment = SegmentCommand.empty("__DATA", .{ |
| 4074 | | .vmaddr = address_and_offset.address, |
| 4075 | | .vmsize = needed_size, |
| 4076 | | .fileoff = address_and_offset.offset, |
| 4077 | | .filesize = needed_size, |
| 4078 | | .maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE, |
| 4079 | | .initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE, |
| 4080 | | }), |
| 4108 | .Segment = .{ |
| 4109 | .inner = .{ |
| 4110 | .segname = makeStaticString("__DATA"), |
| 4111 | .vmaddr = address_and_offset.address, |
| 4112 | .vmsize = needed_size, |
| 4113 | .fileoff = address_and_offset.offset, |
| 4114 | .filesize = needed_size, |
| 4115 | .maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE, |
| 4116 | .initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE, |
| 4117 | }, |
| 4118 | }, |
| 4081 | 4119 | }); |
| 4082 | 4120 | self.load_commands_dirty = true; |
| 4083 | 4121 | } |
| 4084 | 4122 | |
| 4085 | 4123 | if (self.la_symbol_ptr_section_index == null) { |
| 4086 | | const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 4087 | | self.la_symbol_ptr_section_index = @intCast(u16, data_segment.sections.items.len); |
| 4088 | | |
| 4089 | 4124 | const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 4090 | | const off = data_segment.findFreeSpace(needed_size, @alignOf(u64), null); |
| 4091 | | assert(off + needed_size <= data_segment.inner.fileoff + data_segment.inner.filesize); // TODO Must expand __DATA segment. |
| 4092 | | |
| 4093 | | log.debug("found __la_symbol_ptr section free space 0x{x} to 0x{x}", .{ off, off + needed_size }); |
| 4094 | | |
| 4095 | | try data_segment.addSection(self.base.allocator, "__la_symbol_ptr", .{ |
| 4096 | | .addr = data_segment.inner.vmaddr + off - data_segment.inner.fileoff, |
| 4097 | | .size = needed_size, |
| 4098 | | .offset = @intCast(u32, off), |
| 4099 | | .@"align" = 3, // 2^3 = @sizeOf(u64) |
| 4100 | | .flags = macho.S_LAZY_SYMBOL_POINTERS, |
| 4101 | | }); |
| 4102 | | const match = MatchingSection{ |
| 4103 | | .seg = self.data_segment_cmd_index.?, |
| 4104 | | .sect = self.la_symbol_ptr_section_index.?, |
| 4105 | | }; |
| 4106 | | _ = try self.section_ordinals.getOrPut(self.base.allocator, match); |
| 4107 | | try self.block_free_lists.putNoClobber(self.base.allocator, match, .{}); |
| 4108 | | self.load_commands_dirty = true; |
| 4125 | const alignment: u16 = 3; // 2^3 = @sizeOf(u64) |
| 4126 | self.la_symbol_ptr_section_index = try self.allocateSection( |
| 4127 | self.data_segment_cmd_index.?, |
| 4128 | "__la_symbol_ptr", |
| 4129 | needed_size, |
| 4130 | alignment, |
| 4131 | .{ |
| 4132 | .flags = macho.S_LAZY_SYMBOL_POINTERS, |
| 4133 | }, |
| 4134 | ); |
| 4109 | 4135 | } |
| 4110 | 4136 | |
| 4111 | 4137 | if (self.data_section_index == null) { |
| 4112 | | const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 4113 | | self.data_section_index = @intCast(u16, data_segment.sections.items.len); |
| 4114 | | |
| 4115 | 4138 | const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 4116 | | const off = data_segment.findFreeSpace(needed_size, @alignOf(u64), null); |
| 4117 | | assert(off + needed_size <= data_segment.inner.fileoff + data_segment.inner.filesize); // TODO Must expand __DATA segment. |
| 4118 | | |
| 4119 | | log.debug("found __data section free space 0x{x} to 0x{x}", .{ off, off + needed_size }); |
| 4120 | | |
| 4121 | | try data_segment.addSection(self.base.allocator, "__data", .{ |
| 4122 | | .addr = data_segment.inner.vmaddr + off - data_segment.inner.fileoff, |
| 4123 | | .size = needed_size, |
| 4124 | | .offset = @intCast(u32, off), |
| 4125 | | .@"align" = 3, // 2^3 = @sizeOf(u64) |
| 4126 | | }); |
| 4127 | | const match = MatchingSection{ |
| 4128 | | .seg = self.data_segment_cmd_index.?, |
| 4129 | | .sect = self.data_section_index.?, |
| 4130 | | }; |
| 4131 | | _ = try self.section_ordinals.getOrPut(self.base.allocator, match); |
| 4132 | | try self.block_free_lists.putNoClobber(self.base.allocator, match, .{}); |
| 4133 | | self.load_commands_dirty = true; |
| 4139 | const alignment: u16 = 3; // 2^3 = @sizeOf(u64) |
| 4140 | self.data_section_index = try self.allocateSection( |
| 4141 | self.data_segment_cmd_index.?, |
| 4142 | "__data", |
| 4143 | needed_size, |
| 4144 | alignment, |
| 4145 | .{}, |
| 4146 | ); |
| 4134 | 4147 | } |
| 4135 | 4148 | |
| 4136 | 4149 | if (self.tlv_section_index == null) { |
| 4137 | | const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 4138 | | self.tlv_section_index = @intCast(u16, data_segment.sections.items.len); |
| 4139 | | |
| 4140 | 4150 | const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 4141 | | const off = data_segment.findFreeSpace(needed_size, @alignOf(u64), null); |
| 4142 | | assert(off + needed_size <= data_segment.inner.fileoff + data_segment.inner.filesize); // TODO Must expand __DATA segment. |
| 4143 | | |
| 4144 | | log.debug("found __thread_vars section free space 0x{x} to 0x{x}", .{ off, off + needed_size }); |
| 4145 | | |
| 4146 | | try data_segment.addSection(self.base.allocator, "__thread_vars", .{ |
| 4147 | | .addr = data_segment.inner.vmaddr + off - data_segment.inner.fileoff, |
| 4148 | | .size = needed_size, |
| 4149 | | .offset = @intCast(u32, off), |
| 4150 | | .@"align" = 3, // 2^3 = @sizeOf(u64) |
| 4151 | | .flags = macho.S_THREAD_LOCAL_VARIABLES, |
| 4152 | | }); |
| 4153 | | const match = MatchingSection{ |
| 4154 | | .seg = self.data_segment_cmd_index.?, |
| 4155 | | .sect = self.tlv_section_index.?, |
| 4156 | | }; |
| 4157 | | _ = try self.section_ordinals.getOrPut(self.base.allocator, match); |
| 4158 | | try self.block_free_lists.putNoClobber(self.base.allocator, match, .{}); |
| 4159 | | self.load_commands_dirty = true; |
| 4151 | const alignment: u16 = 3; // 2^3 = @sizeOf(u64) |
| 4152 | self.tlv_section_index = try self.allocateSection( |
| 4153 | self.data_segment_cmd_index.?, |
| 4154 | "__thread_vars", |
| 4155 | needed_size, |
| 4156 | alignment, |
| 4157 | .{ |
| 4158 | .flags = macho.S_THREAD_LOCAL_VARIABLES, |
| 4159 | }, |
| 4160 | ); |
| 4160 | 4161 | } |
| 4161 | 4162 | |
| 4162 | 4163 | if (self.tlv_data_section_index == null) { |
| 4163 | | const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 4164 | | self.tlv_data_section_index = @intCast(u16, data_segment.sections.items.len); |
| 4165 | | |
| 4166 | 4164 | const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 4167 | | const off = data_segment.findFreeSpace(needed_size, @alignOf(u64), null); |
| 4168 | | assert(off + needed_size <= data_segment.inner.fileoff + data_segment.inner.filesize); // TODO Must expand __DATA segment. |
| 4169 | | |
| 4170 | | log.debug("found __thread_data section free space 0x{x} to 0x{x}", .{ off, off + needed_size }); |
| 4171 | | |
| 4172 | | try data_segment.addSection(self.base.allocator, "__thread_data", .{ |
| 4173 | | .addr = data_segment.inner.vmaddr + off - data_segment.inner.fileoff, |
| 4174 | | .size = needed_size, |
| 4175 | | .offset = @intCast(u32, off), |
| 4176 | | .@"align" = 3, // 2^3 = @sizeOf(u64) |
| 4177 | | .flags = macho.S_THREAD_LOCAL_REGULAR, |
| 4178 | | }); |
| 4179 | | const match = MatchingSection{ |
| 4180 | | .seg = self.data_segment_cmd_index.?, |
| 4181 | | .sect = self.tlv_data_section_index.?, |
| 4182 | | }; |
| 4183 | | _ = try self.section_ordinals.getOrPut(self.base.allocator, match); |
| 4184 | | try self.block_free_lists.putNoClobber(self.base.allocator, match, .{}); |
| 4185 | | self.load_commands_dirty = true; |
| 4165 | const alignment: u16 = 3; // 2^3 = @sizeOf(u64) |
| 4166 | self.tlv_data_section_index = try self.allocateSection( |
| 4167 | self.data_segment_cmd_index.?, |
| 4168 | "__thread_data", |
| 4169 | needed_size, |
| 4170 | alignment, |
| 4171 | .{ |
| 4172 | .flags = macho.S_THREAD_LOCAL_REGULAR, |
| 4173 | }, |
| 4174 | ); |
| 4186 | 4175 | } |
| 4187 | 4176 | |
| 4188 | 4177 | if (self.tlv_bss_section_index == null) { |
| 4189 | | const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 4190 | | self.tlv_bss_section_index = @intCast(u16, data_segment.sections.items.len); |
| 4191 | | |
| 4192 | 4178 | const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 4193 | | const off = data_segment.findFreeSpace(needed_size, @alignOf(u64), null); |
| 4194 | | assert(off + needed_size <= data_segment.inner.fileoff + data_segment.inner.filesize); // TODO Must expand __DATA segment. |
| 4195 | | |
| 4196 | | log.debug("found __thread_bss section free space 0x{x} to 0x{x}", .{ off, off + needed_size }); |
| 4179 | const alignment: u16 = 3; // 2^3 = @sizeOf(u64) |
| 4180 | self.tlv_bss_section_index = try self.allocateSection( |
| 4181 | self.data_segment_cmd_index.?, |
| 4182 | "__thread_bss", |
| 4183 | needed_size, |
| 4184 | alignment, |
| 4185 | .{ |
| 4186 | .flags = macho.S_THREAD_LOCAL_ZEROFILL, |
| 4187 | }, |
| 4188 | ); |
| 4197 | 4189 | |
| 4198 | 4190 | // We keep offset to the section in a separate variable as the actual section is usually pointing at the |
| 4199 | 4191 | // beginning of the file. |
| 4200 | | self.tlv_bss_file_offset = off; |
| 4201 | | try data_segment.addSection(self.base.allocator, "__thread_bss", .{ |
| 4202 | | .addr = data_segment.inner.vmaddr + off - data_segment.inner.fileoff, |
| 4203 | | .size = needed_size, |
| 4204 | | .@"align" = 3, // 2^3 = @sizeOf(u64) |
| 4205 | | .flags = macho.S_THREAD_LOCAL_ZEROFILL, |
| 4206 | | }); |
| 4207 | | const match = MatchingSection{ |
| 4208 | | .seg = self.data_segment_cmd_index.?, |
| 4209 | | .sect = self.tlv_bss_section_index.?, |
| 4210 | | }; |
| 4211 | | _ = try self.section_ordinals.getOrPut(self.base.allocator, match); |
| 4212 | | try self.block_free_lists.putNoClobber(self.base.allocator, match, .{}); |
| 4213 | | self.load_commands_dirty = true; |
| 4192 | const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 4193 | const out_sect = &seg.sections.items[self.tlv_bss_section_index.?]; |
| 4194 | self.tlv_bss_file_offset = out_sect.offset; |
| 4195 | out_sect.offset = 0; |
| 4214 | 4196 | } |
| 4215 | 4197 | |
| 4216 | 4198 | if (self.bss_section_index == null) { |
| 4217 | | const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 4218 | | self.bss_section_index = @intCast(u16, data_segment.sections.items.len); |
| 4219 | | |
| 4220 | 4199 | const needed_size = @sizeOf(u64) * self.base.options.symbol_count_hint; |
| 4221 | | const off = data_segment.findFreeSpace(needed_size, @alignOf(u64), null); |
| 4222 | | assert(off + needed_size <= data_segment.inner.fileoff + data_segment.inner.filesize); // TODO Must expand __DATA segment. |
| 4223 | | |
| 4224 | | log.debug("found __bss section free space 0x{x} to 0x{x}", .{ off, off + needed_size }); |
| 4200 | const alignment: u16 = 3; // 2^3 = @sizeOf(u64) |
| 4201 | self.bss_section_index = try self.allocateSection( |
| 4202 | self.data_segment_cmd_index.?, |
| 4203 | "__bss", |
| 4204 | needed_size, |
| 4205 | alignment, |
| 4206 | .{ |
| 4207 | .flags = macho.S_ZEROFILL, |
| 4208 | }, |
| 4209 | ); |
| 4225 | 4210 | |
| 4226 | 4211 | // We keep offset to the section in a separate variable as the actual section is usually pointing at the |
| 4227 | 4212 | // beginning of the file. |
| 4228 | | self.bss_file_offset = off; |
| 4229 | | try data_segment.addSection(self.base.allocator, "__bss", .{ |
| 4230 | | .addr = data_segment.inner.vmaddr + off - data_segment.inner.fileoff, |
| 4231 | | .size = 0, |
| 4232 | | .@"align" = 3, // 2^3 = @sizeOf(u64) |
| 4233 | | .flags = macho.S_ZEROFILL, |
| 4234 | | }); |
| 4235 | | const match = MatchingSection{ |
| 4236 | | .seg = self.data_segment_cmd_index.?, |
| 4237 | | .sect = self.bss_section_index.?, |
| 4238 | | }; |
| 4239 | | _ = try self.section_ordinals.getOrPut(self.base.allocator, match); |
| 4240 | | try self.block_free_lists.putNoClobber(self.base.allocator, match, .{}); |
| 4241 | | self.load_commands_dirty = true; |
| 4213 | const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 4214 | const out_sect = &seg.sections.items[self.bss_section_index.?]; |
| 4215 | self.bss_file_offset = out_sect.offset; |
| 4216 | out_sect.offset = 0; |
| 4242 | 4217 | } |
| 4243 | 4218 | |
| 4244 | 4219 | if (self.linkedit_segment_cmd_index == null) { |
| ... | ... | @@ -4248,12 +4223,15 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 4248 | 4223 | log.debug("found __LINKEDIT segment free space at 0x{x}", .{address_and_offset.offset}); |
| 4249 | 4224 | |
| 4250 | 4225 | try self.load_commands.append(self.base.allocator, .{ |
| 4251 | | .Segment = SegmentCommand.empty("__LINKEDIT", .{ |
| 4252 | | .vmaddr = address_and_offset.address, |
| 4253 | | .fileoff = address_and_offset.offset, |
| 4254 | | .maxprot = macho.VM_PROT_READ, |
| 4255 | | .initprot = macho.VM_PROT_READ, |
| 4256 | | }), |
| 4226 | .Segment = .{ |
| 4227 | .inner = .{ |
| 4228 | .segname = makeStaticString("__LINKEDIT"), |
| 4229 | .vmaddr = address_and_offset.address, |
| 4230 | .fileoff = address_and_offset.offset, |
| 4231 | .maxprot = macho.VM_PROT_READ, |
| 4232 | .initprot = macho.VM_PROT_READ, |
| 4233 | }, |
| 4234 | }, |
| 4257 | 4235 | }); |
| 4258 | 4236 | self.load_commands_dirty = true; |
| 4259 | 4237 | } |
| ... | ... | @@ -4485,6 +4463,67 @@ pub fn populateMissingMetadata(self: *MachO) !void { |
| 4485 | 4463 | } |
| 4486 | 4464 | } |
| 4487 | 4465 | |
| 4466 | const AllocateSectionOpts = struct { |
| 4467 | flags: u32 = macho.S_REGULAR, |
| 4468 | reserved1: u32 = 0, |
| 4469 | reserved2: u32 = 0, |
| 4470 | }; |
| 4471 | |
| 4472 | fn allocateSection( |
| 4473 | self: *MachO, |
| 4474 | segment_id: u16, |
| 4475 | sectname: []const u8, |
| 4476 | size: u64, |
| 4477 | alignment: u32, |
| 4478 | opts: AllocateSectionOpts, |
| 4479 | ) !u16 { |
| 4480 | const seg = &self.load_commands.items[segment_id].Segment; |
| 4481 | var sect = macho.section_64{ |
| 4482 | .sectname = makeStaticString(sectname), |
| 4483 | .segname = seg.inner.segname, |
| 4484 | .size = @intCast(u32, size), |
| 4485 | .@"align" = alignment, |
| 4486 | .flags = opts.flags, |
| 4487 | .reserved1 = opts.reserved1, |
| 4488 | .reserved2 = opts.reserved2, |
| 4489 | }; |
| 4490 | |
| 4491 | const use_stage1 = build_options.is_stage1 and self.base.options.use_stage1; |
| 4492 | if (!use_stage1) { |
| 4493 | const alignment_pow_2 = try math.powi(u32, 2, alignment); |
| 4494 | const padding: ?u64 = if (segment_id == self.text_segment_cmd_index.?) self.header_pad else null; |
| 4495 | const off = seg.findFreeSpace(size, alignment_pow_2, padding); |
| 4496 | |
| 4497 | assert(off + size <= seg.inner.fileoff + seg.inner.filesize); // TODO expand |
| 4498 | |
| 4499 | log.debug("found {s},{s} section free space 0x{x} to 0x{x}", .{ |
| 4500 | commands.segmentName(sect), |
| 4501 | commands.sectionName(sect), |
| 4502 | off, |
| 4503 | off + size, |
| 4504 | }); |
| 4505 | |
| 4506 | sect.addr = seg.inner.vmaddr + off - seg.inner.fileoff; |
| 4507 | sect.offset = @intCast(u32, off); |
| 4508 | } |
| 4509 | |
| 4510 | const index = @intCast(u16, seg.sections.items.len); |
| 4511 | try seg.sections.append(self.base.allocator, sect); |
| 4512 | seg.inner.cmdsize += @sizeOf(macho.section_64); |
| 4513 | seg.inner.nsects += 1; |
| 4514 | |
| 4515 | const match = MatchingSection{ |
| 4516 | .seg = segment_id, |
| 4517 | .sect = index, |
| 4518 | }; |
| 4519 | _ = try self.section_ordinals.getOrPut(self.base.allocator, match); |
| 4520 | try self.block_free_lists.putNoClobber(self.base.allocator, match, .{}); |
| 4521 | |
| 4522 | self.load_commands_dirty = true; |
| 4523 | |
| 4524 | return index; |
| 4525 | } |
| 4526 | |
| 4488 | 4527 | fn allocateTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 { |
| 4489 | 4528 | const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 4490 | 4529 | const text_section = &text_segment.sections.items[self.text_section_index.?]; |
| ... | ... | @@ -5513,6 +5552,13 @@ pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { |
| 5513 | 5552 | std.math.maxInt(@TypeOf(actual_size)); |
| 5514 | 5553 | } |
| 5515 | 5554 | |
| 5555 | pub fn makeStaticString(bytes: []const u8) [16]u8 { |
| 5556 | var buf = [_]u8{0} ** 16; |
| 5557 | assert(bytes.len <= buf.len); |
| 5558 | mem.copy(u8, &buf, bytes); |
| 5559 | return buf; |
| 5560 | } |
| 5561 | |
| 5516 | 5562 | pub fn makeString(self: *MachO, string: []const u8) !u32 { |
| 5517 | 5563 | if (self.strtab_dir.getAdapted(@as([]const u8, string), StringSliceAdapter{ .strtab = &self.strtab })) |off| { |
| 5518 | 5564 | log.debug("reusing string '{s}' at offset 0x{x}", .{ string, off }); |