authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-08-30 15:43:20+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-08-30 15:43:20+02:00
log2831d6e9b8b29c21bc7417c5e370674e3130f6ae
tree81a3f7bc619b03efb15aee12c88ad1aa50c59c3c
parenta14e98fcaceed92be8b1859d7ae331176d4e4d84

macho: add first pass at allocating parsed atoms in objects

This commit makes it possible to combine self-hosted with a pre-compiled C object file, e.g.: ``` zig-out/bin/zig build-exe hello.zig add.o ``` where `add.o` is a pre-compiled C object file.

4 files changed, 164 insertions(+), 46 deletions(-)

src/link/MachO.zig+140-31
...@@ -789,6 +789,31 @@ pub fn flush(self: *MachO, comp: *Compilation) !void {...@@ -789,6 +789,31 @@ pub fn flush(self: *MachO, comp: *Compilation) !void {
789 try self.allocateTextBlocks();789 try self.allocateTextBlocks();
790 try self.flushZld();790 try self.flushZld();
791 } else {791 } else {
792 try self.parseTextBlocks();
793 try self.allocateGlobalSymbols();
794 {
795 log.debug("locals:", .{});
796 for (self.locals.items) |sym| {
797 log.debug(" {s}: {}", .{ self.getString(sym.n_strx), sym });
798 }
799 log.debug("globals:", .{});
800 for (self.globals.items) |sym| {
801 log.debug(" {s}: {}", .{ self.getString(sym.n_strx), sym });
802 }
803 log.debug("undefs:", .{});
804 for (self.undefs.items) |sym| {
805 log.debug(" {s}: {}", .{ self.getString(sym.n_strx), sym });
806 }
807 log.debug("unresolved:", .{});
808 for (self.unresolved.keys()) |key| {
809 log.debug(" {d} => {s}", .{ key, self.unresolved.get(key).? });
810 }
811 log.debug("resolved:", .{});
812 var it = self.symbol_resolver.iterator();
813 while (it.next()) |entry| {
814 log.debug(" {s} => {}", .{ self.getString(entry.key_ptr.*), entry.value_ptr.* });
815 }
816 }
792 try self.writeAtoms();817 try self.writeAtoms();
793 try self.flushModule(comp);818 try self.flushModule(comp);
794 }819 }
...@@ -1114,12 +1139,14 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1114,12 +1139,14 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1114 const segname = commands.segmentName(sect);1139 const segname = commands.segmentName(sect);
1115 const sectname = commands.sectionName(sect);1140 const sectname = commands.sectionName(sect);
11161141
1142 var needs_allocation = false;
1117 const res: ?MatchingSection = blk: {1143 const res: ?MatchingSection = blk: {
1118 switch (commands.sectionType(sect)) {1144 switch (commands.sectionType(sect)) {
1119 macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => {1145 macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => {
1120 if (self.text_const_section_index == null) {1146 if (self.text_const_section_index == null) {
1121 self.text_const_section_index = @intCast(u16, text_seg.sections.items.len);1147 self.text_const_section_index = @intCast(u16, text_seg.sections.items.len);
1122 try text_seg.addSection(self.base.allocator, "__const", .{});1148 try text_seg.addSection(self.base.allocator, "__const", .{});
1149 needs_allocation = true;
1123 }1150 }
11241151
1125 break :blk .{1152 break :blk .{
...@@ -1136,6 +1163,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1136,6 +1163,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1136 try text_seg.addSection(self.base.allocator, "__objc_methname", .{1163 try text_seg.addSection(self.base.allocator, "__objc_methname", .{
1137 .flags = macho.S_CSTRING_LITERALS,1164 .flags = macho.S_CSTRING_LITERALS,
1138 });1165 });
1166 needs_allocation = true;
1139 }1167 }
11401168
1141 break :blk .{1169 break :blk .{
...@@ -1148,6 +1176,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1148,6 +1176,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1148 try text_seg.addSection(self.base.allocator, "__objc_methtype", .{1176 try text_seg.addSection(self.base.allocator, "__objc_methtype", .{
1149 .flags = macho.S_CSTRING_LITERALS,1177 .flags = macho.S_CSTRING_LITERALS,
1150 });1178 });
1179 needs_allocation = true;
1151 }1180 }
11521181
1153 break :blk .{1182 break :blk .{
...@@ -1158,6 +1187,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1158,6 +1187,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1158 if (self.objc_classname_section_index == null) {1187 if (self.objc_classname_section_index == null) {
1159 self.objc_classname_section_index = @intCast(u16, text_seg.sections.items.len);1188 self.objc_classname_section_index = @intCast(u16, text_seg.sections.items.len);
1160 try text_seg.addSection(self.base.allocator, "__objc_classname", .{});1189 try text_seg.addSection(self.base.allocator, "__objc_classname", .{});
1190 needs_allocation = true;
1161 }1191 }
11621192
1163 break :blk .{1193 break :blk .{
...@@ -1171,6 +1201,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1171,6 +1201,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1171 try text_seg.addSection(self.base.allocator, "__cstring", .{1201 try text_seg.addSection(self.base.allocator, "__cstring", .{
1172 .flags = macho.S_CSTRING_LITERALS,1202 .flags = macho.S_CSTRING_LITERALS,
1173 });1203 });
1204 needs_allocation = true;
1174 }1205 }
11751206
1176 break :blk .{1207 break :blk .{
...@@ -1185,6 +1216,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1185,6 +1216,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1185 try data_seg.addSection(self.base.allocator, "__objc_selrefs", .{1216 try data_seg.addSection(self.base.allocator, "__objc_selrefs", .{
1186 .flags = macho.S_LITERAL_POINTERS,1217 .flags = macho.S_LITERAL_POINTERS,
1187 });1218 });
1219 needs_allocation = true;
1188 }1220 }
11891221
1190 break :blk .{1222 break :blk .{
...@@ -1202,6 +1234,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1202,6 +1234,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1202 try data_const_seg.addSection(self.base.allocator, "__mod_init_func", .{1234 try data_const_seg.addSection(self.base.allocator, "__mod_init_func", .{
1203 .flags = macho.S_MOD_INIT_FUNC_POINTERS,1235 .flags = macho.S_MOD_INIT_FUNC_POINTERS,
1204 });1236 });
1237 needs_allocation = true;
1205 }1238 }
12061239
1207 break :blk .{1240 break :blk .{
...@@ -1215,6 +1248,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1215,6 +1248,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1215 try data_const_seg.addSection(self.base.allocator, "__mod_term_func", .{1248 try data_const_seg.addSection(self.base.allocator, "__mod_term_func", .{
1216 .flags = macho.S_MOD_TERM_FUNC_POINTERS,1249 .flags = macho.S_MOD_TERM_FUNC_POINTERS,
1217 });1250 });
1251 needs_allocation = true;
1218 }1252 }
12191253
1220 break :blk .{1254 break :blk .{
...@@ -1228,6 +1262,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1228,6 +1262,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1228 try data_seg.addSection(self.base.allocator, "__bss", .{1262 try data_seg.addSection(self.base.allocator, "__bss", .{
1229 .flags = macho.S_ZEROFILL,1263 .flags = macho.S_ZEROFILL,
1230 });1264 });
1265 needs_allocation = true;
1231 }1266 }
12321267
1233 break :blk .{1268 break :blk .{
...@@ -1241,6 +1276,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1241,6 +1276,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1241 try data_seg.addSection(self.base.allocator, "__thread_vars", .{1276 try data_seg.addSection(self.base.allocator, "__thread_vars", .{
1242 .flags = macho.S_THREAD_LOCAL_VARIABLES,1277 .flags = macho.S_THREAD_LOCAL_VARIABLES,
1243 });1278 });
1279 needs_allocation = true;
1244 }1280 }
12451281
1246 break :blk .{1282 break :blk .{
...@@ -1254,6 +1290,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1254,6 +1290,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1254 try data_seg.addSection(self.base.allocator, "__thread_data", .{1290 try data_seg.addSection(self.base.allocator, "__thread_data", .{
1255 .flags = macho.S_THREAD_LOCAL_REGULAR,1291 .flags = macho.S_THREAD_LOCAL_REGULAR,
1256 });1292 });
1293 needs_allocation = true;
1257 }1294 }
12581295
1259 break :blk .{1296 break :blk .{
...@@ -1267,6 +1304,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1267,6 +1304,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1267 try data_seg.addSection(self.base.allocator, "__thread_bss", .{1304 try data_seg.addSection(self.base.allocator, "__thread_bss", .{
1268 .flags = macho.S_THREAD_LOCAL_ZEROFILL,1305 .flags = macho.S_THREAD_LOCAL_ZEROFILL,
1269 });1306 });
1307 needs_allocation = true;
1270 }1308 }
12711309
1272 break :blk .{1310 break :blk .{
...@@ -1281,6 +1319,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1281,6 +1319,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1281 if (self.eh_frame_section_index == null) {1319 if (self.eh_frame_section_index == null) {
1282 self.eh_frame_section_index = @intCast(u16, text_seg.sections.items.len);1320 self.eh_frame_section_index = @intCast(u16, text_seg.sections.items.len);
1283 try text_seg.addSection(self.base.allocator, "__eh_frame", .{});1321 try text_seg.addSection(self.base.allocator, "__eh_frame", .{});
1322 needs_allocation = true;
1284 }1323 }
12851324
1286 break :blk .{1325 break :blk .{
...@@ -1293,6 +1332,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1293,6 +1332,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1293 if (self.data_const_section_index == null) {1332 if (self.data_const_section_index == null) {
1294 self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);1333 self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);
1295 try data_const_seg.addSection(self.base.allocator, "__const", .{});1334 try data_const_seg.addSection(self.base.allocator, "__const", .{});
1335 needs_allocation = true;
1296 }1336 }
12971337
1298 break :blk .{1338 break :blk .{
...@@ -1307,6 +1347,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1307,6 +1347,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1307 try text_seg.addSection(self.base.allocator, "__text", .{1347 try text_seg.addSection(self.base.allocator, "__text", .{
1308 .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,1348 .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
1309 });1349 });
1350 needs_allocation = true;
1310 }1351 }
13111352
1312 break :blk .{1353 break :blk .{
...@@ -1329,6 +1370,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1329,6 +1370,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1329 if (self.ustring_section_index == null) {1370 if (self.ustring_section_index == null) {
1330 self.ustring_section_index = @intCast(u16, text_seg.sections.items.len);1371 self.ustring_section_index = @intCast(u16, text_seg.sections.items.len);
1331 try text_seg.addSection(self.base.allocator, "__ustring", .{});1372 try text_seg.addSection(self.base.allocator, "__ustring", .{});
1373 needs_allocation = true;
1332 }1374 }
13331375
1334 break :blk .{1376 break :blk .{
...@@ -1339,6 +1381,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1339,6 +1381,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1339 if (self.gcc_except_tab_section_index == null) {1381 if (self.gcc_except_tab_section_index == null) {
1340 self.gcc_except_tab_section_index = @intCast(u16, text_seg.sections.items.len);1382 self.gcc_except_tab_section_index = @intCast(u16, text_seg.sections.items.len);
1341 try text_seg.addSection(self.base.allocator, "__gcc_except_tab", .{});1383 try text_seg.addSection(self.base.allocator, "__gcc_except_tab", .{});
1384 needs_allocation = true;
1342 }1385 }
13431386
1344 break :blk .{1387 break :blk .{
...@@ -1349,6 +1392,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1349,6 +1392,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1349 if (self.objc_methlist_section_index == null) {1392 if (self.objc_methlist_section_index == null) {
1350 self.objc_methlist_section_index = @intCast(u16, text_seg.sections.items.len);1393 self.objc_methlist_section_index = @intCast(u16, text_seg.sections.items.len);
1351 try text_seg.addSection(self.base.allocator, "__objc_methlist", .{});1394 try text_seg.addSection(self.base.allocator, "__objc_methlist", .{});
1395 needs_allocation = true;
1352 }1396 }
13531397
1354 break :blk .{1398 break :blk .{
...@@ -1364,6 +1408,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1364,6 +1408,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1364 if (self.data_const_section_index == null) {1408 if (self.data_const_section_index == null) {
1365 self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);1409 self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);
1366 try data_const_seg.addSection(self.base.allocator, "__const", .{});1410 try data_const_seg.addSection(self.base.allocator, "__const", .{});
1411 needs_allocation = true;
1367 }1412 }
13681413
1369 break :blk .{1414 break :blk .{
...@@ -1374,6 +1419,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1374,6 +1419,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1374 if (self.text_const_section_index == null) {1419 if (self.text_const_section_index == null) {
1375 self.text_const_section_index = @intCast(u16, text_seg.sections.items.len);1420 self.text_const_section_index = @intCast(u16, text_seg.sections.items.len);
1376 try text_seg.addSection(self.base.allocator, "__const", .{});1421 try text_seg.addSection(self.base.allocator, "__const", .{});
1422 needs_allocation = true;
1377 }1423 }
13781424
1379 break :blk .{1425 break :blk .{
...@@ -1387,6 +1433,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1387,6 +1433,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1387 if (self.data_const_section_index == null) {1433 if (self.data_const_section_index == null) {
1388 self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);1434 self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);
1389 try data_const_seg.addSection(self.base.allocator, "__const", .{});1435 try data_const_seg.addSection(self.base.allocator, "__const", .{});
1436 needs_allocation = true;
1390 }1437 }
13911438
1392 break :blk .{1439 break :blk .{
...@@ -1400,6 +1447,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1400,6 +1447,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1400 if (self.data_const_section_index == null) {1447 if (self.data_const_section_index == null) {
1401 self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);1448 self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);
1402 try data_const_seg.addSection(self.base.allocator, "__const", .{});1449 try data_const_seg.addSection(self.base.allocator, "__const", .{});
1450 needs_allocation = true;
1403 }1451 }
14041452
1405 break :blk .{1453 break :blk .{
...@@ -1410,6 +1458,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1410,6 +1458,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1410 if (self.objc_cfstring_section_index == null) {1458 if (self.objc_cfstring_section_index == null) {
1411 self.objc_cfstring_section_index = @intCast(u16, data_const_seg.sections.items.len);1459 self.objc_cfstring_section_index = @intCast(u16, data_const_seg.sections.items.len);
1412 try data_const_seg.addSection(self.base.allocator, "__cfstring", .{});1460 try data_const_seg.addSection(self.base.allocator, "__cfstring", .{});
1461 needs_allocation = true;
1413 }1462 }
14141463
1415 break :blk .{1464 break :blk .{
...@@ -1420,6 +1469,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1420,6 +1469,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1420 if (self.objc_classlist_section_index == null) {1469 if (self.objc_classlist_section_index == null) {
1421 self.objc_classlist_section_index = @intCast(u16, data_const_seg.sections.items.len);1470 self.objc_classlist_section_index = @intCast(u16, data_const_seg.sections.items.len);
1422 try data_const_seg.addSection(self.base.allocator, "__objc_classlist", .{});1471 try data_const_seg.addSection(self.base.allocator, "__objc_classlist", .{});
1472 needs_allocation = true;
1423 }1473 }
14241474
1425 break :blk .{1475 break :blk .{
...@@ -1430,6 +1480,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1430,6 +1480,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1430 if (self.objc_imageinfo_section_index == null) {1480 if (self.objc_imageinfo_section_index == null) {
1431 self.objc_imageinfo_section_index = @intCast(u16, data_const_seg.sections.items.len);1481 self.objc_imageinfo_section_index = @intCast(u16, data_const_seg.sections.items.len);
1432 try data_const_seg.addSection(self.base.allocator, "__objc_imageinfo", .{});1482 try data_const_seg.addSection(self.base.allocator, "__objc_imageinfo", .{});
1483 needs_allocation = true;
1433 }1484 }
14341485
1435 break :blk .{1486 break :blk .{
...@@ -1440,6 +1491,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1440,6 +1491,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1440 if (self.objc_const_section_index == null) {1491 if (self.objc_const_section_index == null) {
1441 self.objc_const_section_index = @intCast(u16, data_seg.sections.items.len);1492 self.objc_const_section_index = @intCast(u16, data_seg.sections.items.len);
1442 try data_seg.addSection(self.base.allocator, "__objc_const", .{});1493 try data_seg.addSection(self.base.allocator, "__objc_const", .{});
1494 needs_allocation = true;
1443 }1495 }
14441496
1445 break :blk .{1497 break :blk .{
...@@ -1450,6 +1502,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1450,6 +1502,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1450 if (self.objc_classrefs_section_index == null) {1502 if (self.objc_classrefs_section_index == null) {
1451 self.objc_classrefs_section_index = @intCast(u16, data_seg.sections.items.len);1503 self.objc_classrefs_section_index = @intCast(u16, data_seg.sections.items.len);
1452 try data_seg.addSection(self.base.allocator, "__objc_classrefs", .{});1504 try data_seg.addSection(self.base.allocator, "__objc_classrefs", .{});
1505 needs_allocation = true;
1453 }1506 }
14541507
1455 break :blk .{1508 break :blk .{
...@@ -1460,6 +1513,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1460,6 +1513,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1460 if (self.objc_data_section_index == null) {1513 if (self.objc_data_section_index == null) {
1461 self.objc_data_section_index = @intCast(u16, data_seg.sections.items.len);1514 self.objc_data_section_index = @intCast(u16, data_seg.sections.items.len);
1462 try data_seg.addSection(self.base.allocator, "__objc_data", .{});1515 try data_seg.addSection(self.base.allocator, "__objc_data", .{});
1516 needs_allocation = true;
1463 }1517 }
14641518
1465 break :blk .{1519 break :blk .{
...@@ -1470,6 +1524,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1470,6 +1524,7 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1470 if (self.data_section_index == null) {1524 if (self.data_section_index == null) {
1471 self.data_section_index = @intCast(u16, data_seg.sections.items.len);1525 self.data_section_index = @intCast(u16, data_seg.sections.items.len);
1472 try data_seg.addSection(self.base.allocator, "__data", .{});1526 try data_seg.addSection(self.base.allocator, "__data", .{});
1527 needs_allocation = true;
1473 }1528 }
14741529
1475 break :blk .{1530 break :blk .{
...@@ -1494,6 +1549,36 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio...@@ -1494,6 +1549,36 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
1494 if (res) |match| {1549 if (res) |match| {
1495 _ = try self.section_ordinals.getOrPut(self.base.allocator, match);1550 _ = try self.section_ordinals.getOrPut(self.base.allocator, match);
1496 _ = try self.block_free_lists.getOrPutValue(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 }
1497 }1582 }
14981583
1499 return res;1584 return res;
...@@ -1759,23 +1844,41 @@ pub fn createEmptyAtom(self: *MachO, local_sym_index: u32, size: u64, alignment:...@@ -1759,23 +1844,41 @@ pub fn createEmptyAtom(self: *MachO, local_sym_index: u32, size: u64, alignment:
1759}1844}
17601845
1761pub fn allocateAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !u64 {1846pub fn allocateAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !u64 {
1762 // TODO converge with `allocateTextBlock`1847 const seg = &self.load_commands.items[match.seg].Segment;
1763 const seg = self.load_commands.items[match.seg].Segment;1848 const sect = &seg.sections.items[match.sect];
1764 const sect = seg.sections.items[match.sect];
1765 const sym = &self.locals.items[atom.local_sym_index];1849 const sym = &self.locals.items[atom.local_sym_index];
1766 const base_addr = if (self.blocks.get(match)) |last| blk: {1850
1851 var atom_placement: ?*TextBlock = null;
1852
1853 // TODO converge with `allocateTextBlock` and handle free list
1854 const vaddr = if (self.blocks.get(match)) |last| blk: {
1767 const last_atom_sym = self.locals.items[last.local_sym_index];1855 const last_atom_sym = self.locals.items[last.local_sym_index];
1768 break :blk last_atom_sym.n_value + last.size;1856 const ideal_capacity = padToIdeal(last.size);
1857 const ideal_capacity_end_vaddr = last_atom_sym.n_value + ideal_capacity;
1858 const last_atom_alignment = try math.powi(u32, 2, atom.alignment);
1859 const new_start_vaddr = mem.alignForwardGeneric(u64, ideal_capacity_end_vaddr, last_atom_alignment);
1860 atom_placement = last;
1861 break :blk new_start_vaddr;
1769 } else sect.addr;1862 } else sect.addr;
1770 const atom_alignment = try math.powi(u32, 2, atom.alignment);1863
1771 const vaddr = mem.alignForwardGeneric(u64, base_addr, atom_alignment);
1772 log.debug("allocating atom for symbol {s} at address 0x{x}", .{ self.getString(sym.n_strx), vaddr });1864 log.debug("allocating atom for symbol {s} at address 0x{x}", .{ self.getString(sym.n_strx), vaddr });
17731865
1774 const expand_section = true;1866 const expand_section = atom_placement == null or atom_placement.?.next == null;
1775 if (expand_section) {1867 if (expand_section) {
1776 // Expand the section, possibly shifting all the atoms for the sections following it.1868 const needed_size = (vaddr + atom.size) - sect.addr;
1777 // It might also be needed to shift entire segments too if there is not enough1869 const end_addr = blk: {
1778 // padding left.1870 const next_ordinal = self.section_ordinals.getIndex(match).?; // Ordinals are +1 to begin with.
1871 const end_addr = if (self.section_ordinals.keys().len > next_ordinal) inner: {
1872 const next_match = self.section_ordinals.keys()[next_ordinal];
1873 const next_seg = self.load_commands.items[next_match.seg].Segment;
1874 const next_sect = next_seg.sections.items[next_match.sect];
1875 break :inner next_sect.addr;
1876 } else seg.inner.filesize;
1877 break :blk end_addr;
1878 };
1879 assert(needed_size <= end_addr); // TODO must expand the section
1880 sect.size = needed_size;
1881 self.load_commands_dirty = true;
1779 }1882 }
1780 const n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1);1883 const n_sect = @intCast(u8, self.section_ordinals.getIndex(match).? + 1);
1781 sym.n_value = vaddr;1884 sym.n_value = vaddr;
...@@ -1828,6 +1931,21 @@ pub fn writeAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !void {...@@ -1828,6 +1931,21 @@ pub fn writeAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !void {
1828 try self.writeLocalSymbol(atom.local_sym_index);1931 try self.writeLocalSymbol(atom.local_sym_index);
1829}1932}
18301933
1934fn allocateGlobalSymbols(self: *MachO) !void {
1935 // TODO should we do this in `allocateAtom` (or similar)? Then, we would need to
1936 // store the link atom -> globals somewhere.
1937 var sym_it = self.symbol_resolver.valueIterator();
1938 while (sym_it.next()) |resolv| {
1939 if (resolv.where != .global) continue;
1940
1941 assert(resolv.local_sym_index != 0);
1942 const local_sym = self.locals.items[resolv.local_sym_index];
1943 const sym = &self.globals.items[resolv.where_index];
1944 sym.n_value = local_sym.n_value;
1945 sym.n_sect = local_sym.n_sect;
1946 }
1947}
1948
1831pub fn allocateAtomStage1(self: *MachO, atom: *TextBlock, match: MatchingSection) !void {1949pub fn allocateAtomStage1(self: *MachO, atom: *TextBlock, match: MatchingSection) !void {
1832 // Update target section's metadata1950 // Update target section's metadata
1833 // TODO should we update segment's size here too?1951 // TODO should we update segment's size here too?
...@@ -2313,14 +2431,14 @@ fn resolveSymbolsInObject(...@@ -2313,14 +2431,14 @@ fn resolveSymbolsInObject(
2313 continue;2431 continue;
2314 },2432 },
2315 .undef => {2433 .undef => {
2316 const undef = &self.undefs.items[resolv.where_index];2434 // const undef = &self.undefs.items[resolv.where_index];
2317 undef.* = .{2435 // undef.* = .{
2318 .n_strx = 0,2436 // .n_strx = 0,
2319 .n_type = macho.N_UNDF,2437 // .n_type = macho.N_UNDF,
2320 .n_sect = 0,2438 // .n_sect = 0,
2321 .n_desc = 0,2439 // .n_desc = 0,
2322 .n_value = 0,2440 // .n_value = 0,
2323 };2441 // };
2324 _ = self.unresolved.fetchSwapRemove(resolv.where_index);2442 _ = self.unresolved.fetchSwapRemove(resolv.where_index);
2325 },2443 },
2326 }2444 }
...@@ -2457,18 +2575,9 @@ fn resolveSymbols(self: *MachO) !void {...@@ -2457,18 +2575,9 @@ fn resolveSymbols(self: *MachO) !void {
2457 // text blocks for each tentative defintion.2575 // text blocks for each tentative defintion.
2458 while (tentatives.popOrNull()) |entry| {2576 while (tentatives.popOrNull()) |entry| {
2459 const sym = &self.globals.items[entry.key];2577 const sym = &self.globals.items[entry.key];
2460 const match: MatchingSection = blk: {2578 const match = MatchingSection{
2461 if (self.bss_section_index == null) {2579 .seg = self.data_segment_cmd_index.?,
2462 const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;2580 .sect = self.bss_section_index.?,
2463 self.bss_section_index = @intCast(u16, data_seg.sections.items.len);
2464 try data_seg.addSection(self.base.allocator, "__bss", .{
2465 .flags = macho.S_ZEROFILL,
2466 });
2467 }
2468 break :blk .{
2469 .seg = self.data_segment_cmd_index.?,
2470 .sect = self.bss_section_index.?,
2471 };
2472 };2581 };
2473 _ = try self.section_ordinals.getOrPut(self.base.allocator, match);2582 _ = try self.section_ordinals.getOrPut(self.base.allocator, match);
24742583
src/link/MachO/Object.zig+10-14
...@@ -504,7 +504,6 @@ pub fn parseTextBlocks(...@@ -504,7 +504,6 @@ pub fn parseTextBlocks(
504 log.debug("unhandled section", .{});504 log.debug("unhandled section", .{});
505 continue;505 continue;
506 };506 };
507 // TODO allocate section here.
508507
509 // Read section's code508 // Read section's code
510 var code = try allocator.alloc(u8, @intCast(usize, sect.size));509 var code = try allocator.alloc(u8, @intCast(usize, sect.size));
...@@ -569,12 +568,6 @@ pub fn parseTextBlocks(...@@ -569,12 +568,6 @@ pub fn parseTextBlocks(
569 const block_size = block_code.len;568 const block_size = block_code.len;
570 const block = try macho_file.createEmptyAtom(block_local_sym_index, block_size, sect.@"align");569 const block = try macho_file.createEmptyAtom(block_local_sym_index, block_size, sect.@"align");
571570
572 if (use_stage1) {
573 try macho_file.allocateAtomStage1(block, match);
574 } else {
575 _ = try macho_file.allocateAtom(block, match);
576 }
577
578 mem.copy(u8, block.code.items, block_code);571 mem.copy(u8, block.code.items, block_code);
579572
580 try block.parseRelocs(relocs, .{573 try block.parseRelocs(relocs, .{
...@@ -597,6 +590,11 @@ pub fn parseTextBlocks(...@@ -597,6 +590,11 @@ pub fn parseTextBlocks(
597 }590 }
598 }591 }
599592
593 if (use_stage1) {
594 try macho_file.allocateAtomStage1(block, match);
595 } else {
596 _ = try macho_file.allocateAtom(block, match);
597 }
600 try self.text_blocks.append(allocator, block);598 try self.text_blocks.append(allocator, block);
601 }599 }
602600
...@@ -648,7 +646,6 @@ pub fn parseTextBlocks(...@@ -648,7 +646,6 @@ pub fn parseTextBlocks(
648 } else {646 } else {
649 _ = try macho_file.allocateAtom(block, match);647 _ = try macho_file.allocateAtom(block, match);
650 }648 }
651
652 try self.text_blocks.append(allocator, block);649 try self.text_blocks.append(allocator, block);
653 }650 }
654651
...@@ -679,12 +676,6 @@ pub fn parseTextBlocks(...@@ -679,12 +676,6 @@ pub fn parseTextBlocks(
679 };676 };
680 const block = try macho_file.createEmptyAtom(block_local_sym_index, sect.size, sect.@"align");677 const block = try macho_file.createEmptyAtom(block_local_sym_index, sect.size, sect.@"align");
681678
682 if (use_stage1) {
683 try macho_file.allocateAtomStage1(block, match);
684 } else {
685 _ = try macho_file.allocateAtom(block, match);
686 }
687
688 mem.copy(u8, block.code.items, code);679 mem.copy(u8, block.code.items, code);
689680
690 try block.parseRelocs(relocs, .{681 try block.parseRelocs(relocs, .{
...@@ -743,6 +734,11 @@ pub fn parseTextBlocks(...@@ -743,6 +734,11 @@ pub fn parseTextBlocks(
743 });734 });
744 }735 }
745736
737 if (use_stage1) {
738 try macho_file.allocateAtomStage1(block, match);
739 } else {
740 _ = try macho_file.allocateAtom(block, match);
741 }
746 try self.text_blocks.append(allocator, block);742 try self.text_blocks.append(allocator, block);
747 }743 }
748 }744 }
src/link/MachO/TextBlock.zig+13
...@@ -1183,9 +1183,22 @@ pub fn resolveRelocs(self: *TextBlock, macho_file: *MachO) !void {...@@ -1183,9 +1183,22 @@ pub fn resolveRelocs(self: *TextBlock, macho_file: *MachO) !void {
1183 },1183 },
1184 .undef => {1184 .undef => {
1185 const atom = macho_file.stubs_map.get(rel.where_index) orelse {1185 const atom = macho_file.stubs_map.get(rel.where_index) orelse {
1186 // TODO this is required for incremental when we don't have every symbol
1187 // resolved when creating relocations. In this case, we will insert a branch
1188 // reloc to an undef symbol which may happen to be defined within the binary.
1189 // Then, the undef we point at will be a null symbol (free symbol) which we
1190 // should remove/repurpose. To circumvent this (for now), we check if the symbol
1191 // we point to is garbage, and if so we fall back to symbol resolver to find by name.
1192 const n_strx = macho_file.undefs.items[rel.where_index].n_strx;
1193 if (macho_file.symbol_resolver.get(n_strx)) |resolv| inner: {
1194 if (resolv.where != .global) break :inner;
1195 break :blk macho_file.globals.items[resolv.where_index].n_value;
1196 }
1197
1186 // TODO verify in TextBlock that the symbol is indeed dynamically bound.1198 // TODO verify in TextBlock that the symbol is indeed dynamically bound.
1187 break :blk 0; // Dynamically bound by dyld.1199 break :blk 0; // Dynamically bound by dyld.
1188 };1200 };
1201
1189 break :blk macho_file.locals.items[atom.local_sym_index].n_value;1202 break :blk macho_file.locals.items[atom.local_sym_index].n_value;
1190 },1203 },
1191 }1204 }
src/link/MachO/commands.zig+1-1
...@@ -337,7 +337,7 @@ pub const SegmentCommand = struct {...@@ -337,7 +337,7 @@ pub const SegmentCommand = struct {
337 return null;337 return null;
338 }338 }
339339
340 pub fn findFreeSpace(self: SegmentCommand, object_size: u64, min_alignment: u16, start: ?u64) u64 {340 pub fn findFreeSpace(self: SegmentCommand, object_size: u64, min_alignment: u32, start: ?u64) u64 {
341 var st: u64 = if (start) |v| v else self.inner.fileoff;341 var st: u64 = if (start) |v| v else self.inner.fileoff;
342 while (self.detectAllocCollision(st, object_size)) |item_end| {342 while (self.detectAllocCollision(st, object_size)) |item_end| {
343 st = mem.alignForwardGeneric(u64, item_end, min_alignment);343 st = mem.alignForwardGeneric(u64, item_end, min_alignment);