authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-08-31 23:05:01+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-08-31 23:05:01+02:00
log50db993119d9b1031700be94b757eaf100f35857
treeb13b39d4942b5129aaa0ff37f6df36d740996d5d
parent2831d6e9b8b29c21bc7417c5e370674e3130f6ae

macho: fix allocating sections within segment when parsing objects


4 files changed, 551 insertions(+), 603 deletions(-)

lib/std/macho.zig+20-20
......@@ -601,35 +601,35 @@ pub const segment_command = extern struct {
601601/// command and their size is reflected in cmdsize.
602602pub const segment_command_64 = extern struct {
603603 /// LC_SEGMENT_64
604 cmd: u32,
604 cmd: u32 = LC_SEGMENT_64,
605605
606606 /// includes sizeof section_64 structs
607 cmdsize: u32,
607 cmdsize: u32 = @sizeOf(segment_command_64),
608608
609609 /// segment name
610610 segname: [16]u8,
611611
612612 /// memory address of this segment
613 vmaddr: u64,
613 vmaddr: u64 = 0,
614614
615615 /// memory size of this segment
616 vmsize: u64,
616 vmsize: u64 = 0,
617617
618618 /// file offset of this segment
619 fileoff: u64,
619 fileoff: u64 = 0,
620620
621621 /// amount to map from the file
622 filesize: u64,
622 filesize: u64 = 0,
623623
624624 /// maximum VM protection
625 maxprot: vm_prot_t,
625 maxprot: vm_prot_t = VM_PROT_NONE,
626626
627627 /// initial VM protection
628 initprot: vm_prot_t,
628 initprot: vm_prot_t = VM_PROT_NONE,
629629
630630 /// number of sections in segment
631 nsects: u32,
632 flags: u32,
631 nsects: u32 = 0,
632 flags: u32 = 0,
633633};
634634
635635/// A segment is made up of zero or more sections. Non-MH_OBJECT files have
......@@ -700,34 +700,34 @@ pub const section_64 = extern struct {
700700 segname: [16]u8,
701701
702702 /// memory address of this section
703 addr: u64,
703 addr: u64 = 0,
704704
705705 /// size in bytes of this section
706 size: u64,
706 size: u64 = 0,
707707
708708 /// file offset of this section
709 offset: u32,
709 offset: u32 = 0,
710710
711711 /// section alignment (power of 2)
712 @"align": u32,
712 @"align": u32 = 0,
713713
714714 /// file offset of relocation entries
715 reloff: u32,
715 reloff: u32 = 0,
716716
717717 /// number of relocation entries
718 nreloc: u32,
718 nreloc: u32 = 0,
719719
720720 /// flags (section type and attributes
721 flags: u32,
721 flags: u32 = S_REGULAR,
722722
723723 /// reserved (for offset or index)
724 reserved1: u32,
724 reserved1: u32 = 0,
725725
726726 /// reserved (for count or sizeof)
727 reserved2: u32,
727 reserved2: u32 = 0,
728728
729729 /// reserved
730 reserved3: u32,
730 reserved3: u32 = 0,
731731};
732732
733733pub const nlist = extern struct {
src/link/MachO.zig+449-403
......@@ -1133,20 +1133,19 @@ pub const MatchingSection = struct {
11331133};
11341134
11351135pub 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;
11391136 const segname = commands.segmentName(sect);
11401137 const sectname = commands.sectionName(sect);
1141
1142 var needs_allocation = false;
11431138 const res: ?MatchingSection = blk: {
11441139 switch (commands.sectionType(sect)) {
11451140 macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => {
11461141 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 );
11501149 }
11511150
11521151 break :blk .{
......@@ -1159,11 +1158,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
11591158 // TODO it seems the common values within the sections in objects are deduplicated/merged
11601159 // on merging the sections' contents.
11611160 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 );
11671168 }
11681169
11691170 break :blk .{
......@@ -1172,11 +1173,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
11721173 };
11731174 } else if (mem.eql(u8, sectname, "__objc_methtype")) {
11741175 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 );
11801183 }
11811184
11821185 break :blk .{
......@@ -1185,9 +1188,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
11851188 };
11861189 } else if (mem.eql(u8, sectname, "__objc_classname")) {
11871190 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 );
11911198 }
11921199
11931200 break :blk .{
......@@ -1197,11 +1204,15 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
11971204 }
11981205
11991206 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 );
12051216 }
12061217
12071218 break :blk .{
......@@ -1212,29 +1223,37 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
12121223 macho.S_LITERAL_POINTERS => {
12131224 if (mem.eql(u8, segname, "__DATA") and mem.eql(u8, sectname, "__objc_selrefs")) {
12141225 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 );
12201235 }
12211236
12221237 break :blk .{
12231238 .seg = self.data_segment_cmd_index.?,
12241239 .sect = self.objc_selrefs_section_index.?,
12251240 };
1241 } else {
1242 // TODO investigate
1243 break :blk null;
12261244 }
1227
1228 // TODO investigate
1229 break :blk null;
12301245 },
12311246 macho.S_MOD_INIT_FUNC_POINTERS => {
12321247 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 );
12381257 }
12391258
12401259 break :blk .{
......@@ -1244,11 +1263,15 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
12441263 },
12451264 macho.S_MOD_TERM_FUNC_POINTERS => {
12461265 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 );
12521275 }
12531276
12541277 break :blk .{
......@@ -1258,11 +1281,15 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
12581281 },
12591282 macho.S_ZEROFILL => {
12601283 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 );
12661293 }
12671294
12681295 break :blk .{
......@@ -1272,11 +1299,15 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
12721299 },
12731300 macho.S_THREAD_LOCAL_VARIABLES => {
12741301 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 );
12801311 }
12811312
12821313 break :blk .{
......@@ -1286,11 +1317,15 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
12861317 },
12871318 macho.S_THREAD_LOCAL_REGULAR => {
12881319 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 );
12941329 }
12951330
12961331 break :blk .{
......@@ -1300,11 +1335,15 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
13001335 },
13011336 macho.S_THREAD_LOCAL_ZEROFILL => {
13021337 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 );
13081347 }
13091348
13101349 break :blk .{
......@@ -1317,9 +1356,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
13171356 // TODO I believe __eh_frame is currently part of __unwind_info section
13181357 // in the latest ld64 output.
13191358 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 );
13231366 }
13241367
13251368 break :blk .{
......@@ -1330,9 +1373,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
13301373
13311374 // TODO audit this: is this the right mapping?
13321375 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 );
13361383 }
13371384
13381385 break :blk .{
......@@ -1343,11 +1390,17 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
13431390 macho.S_REGULAR => {
13441391 if (commands.sectionIsCode(sect)) {
13451392 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 );
13511404 }
13521405
13531406 break :blk .{
......@@ -1368,9 +1421,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
13681421 if (mem.eql(u8, segname, "__TEXT")) {
13691422 if (mem.eql(u8, sectname, "__ustring")) {
13701423 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 );
13741431 }
13751432
13761433 break :blk .{
......@@ -1379,9 +1436,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
13791436 };
13801437 } else if (mem.eql(u8, sectname, "__gcc_except_tab")) {
13811438 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 );
13851446 }
13861447
13871448 break :blk .{
......@@ -1390,9 +1451,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
13901451 };
13911452 } else if (mem.eql(u8, sectname, "__objc_methlist")) {
13921453 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 );
13961461 }
13971462
13981463 break :blk .{
......@@ -1406,9 +1471,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
14061471 mem.eql(u8, sectname, "__gopclntab"))
14071472 {
14081473 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 );
14121481 }
14131482
14141483 break :blk .{
......@@ -1417,9 +1486,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
14171486 };
14181487 } else {
14191488 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 );
14231496 }
14241497
14251498 break :blk .{
......@@ -1431,9 +1504,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
14311504
14321505 if (mem.eql(u8, segname, "__DATA_CONST")) {
14331506 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 );
14371514 }
14381515
14391516 break :blk .{
......@@ -1445,9 +1522,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
14451522 if (mem.eql(u8, segname, "__DATA")) {
14461523 if (mem.eql(u8, sectname, "__const")) {
14471524 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 );
14511532 }
14521533
14531534 break :blk .{
......@@ -1456,9 +1537,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
14561537 };
14571538 } else if (mem.eql(u8, sectname, "__cfstring")) {
14581539 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 );
14621547 }
14631548
14641549 break :blk .{
......@@ -1467,9 +1552,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
14671552 };
14681553 } else if (mem.eql(u8, sectname, "__objc_classlist")) {
14691554 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 );
14731562 }
14741563
14751564 break :blk .{
......@@ -1478,9 +1567,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
14781567 };
14791568 } else if (mem.eql(u8, sectname, "__objc_imageinfo")) {
14801569 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 );
14841577 }
14851578
14861579 break :blk .{
......@@ -1489,9 +1582,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
14891582 };
14901583 } else if (mem.eql(u8, sectname, "__objc_const")) {
14911584 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 );
14951592 }
14961593
14971594 break :blk .{
......@@ -1500,9 +1597,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
15001597 };
15011598 } else if (mem.eql(u8, sectname, "__objc_classrefs")) {
15021599 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 );
15061607 }
15071608
15081609 break :blk .{
......@@ -1511,9 +1612,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
15111612 };
15121613 } else if (mem.eql(u8, sectname, "__objc_data")) {
15131614 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 );
15171622 }
15181623
15191624 break :blk .{
......@@ -1522,9 +1627,13 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
15221627 };
15231628 } else {
15241629 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 );
15281637 }
15291638
15301639 break :blk .{
......@@ -1545,42 +1654,6 @@ pub fn getMatchingSection(self: *MachO, sect: macho.section_64) !?MatchingSectio
15451654 else => break :blk null,
15461655 }
15471656 };
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
15841657 return res;
15851658}
15861659
......@@ -3878,9 +3951,12 @@ pub fn populateMissingMetadata(self: *MachO) !void {
38783951 if (self.pagezero_segment_cmd_index == null) {
38793952 self.pagezero_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
38803953 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 },
38843960 });
38853961 self.load_commands_dirty = true;
38863962 }
......@@ -3895,51 +3971,39 @@ pub fn populateMissingMetadata(self: *MachO) !void {
38953971 log.debug("found __TEXT segment free space 0x{x} to 0x{x}", .{ 0, needed_size });
38963972
38973973 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 },
39053984 });
39063985 self.load_commands_dirty = true;
39073986 }
39083987
39093988 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
39133989 const alignment: u2 = switch (self.base.options.target.cpu.arch) {
39143990 .x86_64 => 0,
39153991 .aarch64 => 2,
39163992 else => unreachable, // unhandled architecture type
39173993 };
39183994 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 );
39374004 }
39384005
39394006 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
39434007 const alignment: u2 = switch (self.base.options.target.cpu.arch) {
39444008 .x86_64 => 0,
39454009 .aarch64 => 2,
......@@ -3951,32 +4015,19 @@ pub fn populateMissingMetadata(self: *MachO) !void {
39514015 else => unreachable, // unhandled architecture type
39524016 };
39534017 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 );
39744028 }
39754029
39764030 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
39804031 const alignment: u2 = switch (self.base.options.target.cpu.arch) {
39814032 .x86_64 => 0,
39824033 .aarch64 => 2,
......@@ -3993,25 +4044,15 @@ pub fn populateMissingMetadata(self: *MachO) !void {
39934044 else => unreachable,
39944045 };
39954046 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 );
40154056 }
40164057
40174058 if (self.data_const_segment_cmd_index == null) {
......@@ -4020,45 +4061,39 @@ pub fn populateMissingMetadata(self: *MachO) !void {
40204061 const ideal_size = @sizeOf(u64) * self.base.options.symbol_count_hint;
40214062 const needed_size = mem.alignForwardGeneric(u64, padToIdeal(ideal_size), self.page_size);
40224063
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 });
40244068
40254069 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 },
40344081 });
40354082 self.load_commands_dirty = true;
40364083 }
40374084
40384085 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
40424086 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 );
40624097 }
40634098
40644099 if (self.data_segment_cmd_index == null) {
......@@ -4070,175 +4105,115 @@ pub fn populateMissingMetadata(self: *MachO) !void {
40704105 log.debug("found __DATA segment free space 0x{x} to 0x{x}", .{ address_and_offset.offset, address_and_offset.offset + needed_size });
40714106
40724107 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 },
40814119 });
40824120 self.load_commands_dirty = true;
40834121 }
40844122
40854123 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
40894124 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 );
41094135 }
41104136
41114137 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
41154138 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 );
41344147 }
41354148
41364149 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
41404150 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 );
41604161 }
41614162
41624163 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
41664164 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 );
41864175 }
41874176
41884177 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
41924178 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 );
41974189
41984190 // We keep offset to the section in a separate variable as the actual section is usually pointing at the
41994191 // 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;
42144196 }
42154197
42164198 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
42204199 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 );
42254210
42264211 // We keep offset to the section in a separate variable as the actual section is usually pointing at the
42274212 // 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;
42424217 }
42434218
42444219 if (self.linkedit_segment_cmd_index == null) {
......@@ -4248,12 +4223,15 @@ pub fn populateMissingMetadata(self: *MachO) !void {
42484223 log.debug("found __LINKEDIT segment free space at 0x{x}", .{address_and_offset.offset});
42494224
42504225 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 },
42574235 });
42584236 self.load_commands_dirty = true;
42594237 }
......@@ -4485,6 +4463,67 @@ pub fn populateMissingMetadata(self: *MachO) !void {
44854463 }
44864464}
44874465
4466const AllocateSectionOpts = struct {
4467 flags: u32 = macho.S_REGULAR,
4468 reserved1: u32 = 0,
4469 reserved2: u32 = 0,
4470};
4471
4472fn 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
44884527fn allocateTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 {
44894528 const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
44904529 const text_section = &text_segment.sections.items[self.text_section_index.?];
......@@ -5513,6 +5552,13 @@ pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) {
55135552 std.math.maxInt(@TypeOf(actual_size));
55145553}
55155554
5555pub 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
55165562pub fn makeString(self: *MachO, string: []const u8) !u32 {
55175563 if (self.strtab_dir.getAdapted(@as([]const u8, string), StringSliceAdapter{ .strtab = &self.strtab })) |off| {
55185564 log.debug("reusing string '{s}' at offset 0x{x}", .{ string, off });
src/link/MachO/DebugSymbols.zig+77-92
......@@ -5,23 +5,26 @@ const assert = std.debug.assert;
55const fs = std.fs;
66const log = std.log.scoped(.dsym);
77const macho = std.macho;
8const math = std.math;
89const mem = std.mem;
910const DW = std.dwarf;
1011const leb = std.leb;
1112const Allocator = mem.Allocator;
1213
1314const build_options = @import("build_options");
15const commands = @import("commands.zig");
1416const trace = @import("../../tracy.zig").trace;
17const LoadCommand = commands.LoadCommand;
1518const Module = @import("../../Module.zig");
1619const Type = @import("../../type.zig").Type;
1720const link = @import("../../link.zig");
1821const MachO = @import("../MachO.zig");
19const SrcFn = MachO.SrcFn;
2022const TextBlock = MachO.TextBlock;
23const SegmentCommand = commands.SegmentCommand;
24const SrcFn = MachO.SrcFn;
25const makeStaticString = MachO.makeStaticString;
2126const padToIdeal = MachO.padToIdeal;
2227
23usingnamespace @import("commands.zig");
24
2528const page_size: u16 = 0x1000;
2629
2730base: *MachO,
......@@ -185,105 +188,84 @@ pub fn populateMissingMetadata(self: *DebugSymbols, allocator: *Allocator) !void
185188 log.debug("found __DWARF segment free space 0x{x} to 0x{x}", .{ off, off + needed_size });
186189
187190 try self.load_commands.append(allocator, .{
188 .Segment = SegmentCommand.empty("__DWARF", .{
189 .vmaddr = vmaddr,
190 .vmsize = needed_size,
191 .fileoff = off,
192 .filesize = needed_size,
193 }),
191 .Segment = .{
192 .inner = .{
193 .segname = makeStaticString("__DWARF"),
194 .vmaddr = vmaddr,
195 .vmsize = needed_size,
196 .fileoff = off,
197 .filesize = needed_size,
198 },
199 },
194200 });
195201 self.load_commands_dirty = true;
196202 }
197203 if (self.debug_str_section_index == null) {
198 const dwarf_segment = &self.load_commands.items[self.dwarf_segment_cmd_index.?].Segment;
199 self.debug_str_section_index = @intCast(u16, dwarf_segment.sections.items.len);
200204 assert(self.debug_string_table.items.len == 0);
201
202 try dwarf_segment.addSection(allocator, "__debug_str", .{
203 .addr = dwarf_segment.inner.vmaddr,
204 .size = @intCast(u32, self.debug_string_table.items.len),
205 .offset = @intCast(u32, dwarf_segment.inner.fileoff),
206 .@"align" = 1,
207 });
208 self.load_commands_dirty = true;
205 self.debug_str_section_index = try self.allocateSection(
206 "__debug_str",
207 @intCast(u32, self.debug_string_table.items.len),
208 0,
209 );
209210 self.debug_string_table_dirty = true;
210211 }
211212 if (self.debug_info_section_index == null) {
212 const dwarf_segment = &self.load_commands.items[self.dwarf_segment_cmd_index.?].Segment;
213 self.debug_info_section_index = @intCast(u16, dwarf_segment.sections.items.len);
214
215 const file_size_hint = 200;
216 const p_align = 1;
217 const off = dwarf_segment.findFreeSpace(file_size_hint, p_align, null);
218
219 log.debug("found __debug_info free space 0x{x} to 0x{x}", .{ off, off + file_size_hint });
220
221 try dwarf_segment.addSection(allocator, "__debug_info", .{
222 .addr = dwarf_segment.inner.vmaddr + off - dwarf_segment.inner.fileoff,
223 .size = file_size_hint,
224 .offset = @intCast(u32, off),
225 .@"align" = p_align,
226 });
227 self.load_commands_dirty = true;
213 self.debug_info_section_index = try self.allocateSection("__debug_info", 200, 0);
228214 self.debug_info_header_dirty = true;
229215 }
230216 if (self.debug_abbrev_section_index == null) {
231 const dwarf_segment = &self.load_commands.items[self.dwarf_segment_cmd_index.?].Segment;
232 self.debug_abbrev_section_index = @intCast(u16, dwarf_segment.sections.items.len);
233
234 const file_size_hint = 128;
235 const p_align = 1;
236 const off = dwarf_segment.findFreeSpace(file_size_hint, p_align, null);
237
238 log.debug("found __debug_abbrev free space 0x{x} to 0x{x}", .{ off, off + file_size_hint });
239
240 try dwarf_segment.addSection(allocator, "__debug_abbrev", .{
241 .addr = dwarf_segment.inner.vmaddr + off - dwarf_segment.inner.fileoff,
242 .size = file_size_hint,
243 .offset = @intCast(u32, off),
244 .@"align" = p_align,
245 });
246 self.load_commands_dirty = true;
217 self.debug_abbrev_section_index = try self.allocateSection("__debug_abbrev", 128, 0);
247218 self.debug_abbrev_section_dirty = true;
248219 }
249220 if (self.debug_aranges_section_index == null) {
250 const dwarf_segment = &self.load_commands.items[self.dwarf_segment_cmd_index.?].Segment;
251 self.debug_aranges_section_index = @intCast(u16, dwarf_segment.sections.items.len);
252
253 const file_size_hint = 160;
254 const p_align = 16;
255 const off = dwarf_segment.findFreeSpace(file_size_hint, p_align, null);
256
257 log.debug("found __debug_aranges free space 0x{x} to 0x{x}", .{ off, off + file_size_hint });
258
259 try dwarf_segment.addSection(allocator, "__debug_aranges", .{
260 .addr = dwarf_segment.inner.vmaddr + off - dwarf_segment.inner.fileoff,
261 .size = file_size_hint,
262 .offset = @intCast(u32, off),
263 .@"align" = p_align,
264 });
265 self.load_commands_dirty = true;
221 self.debug_aranges_section_index = try self.allocateSection("__debug_aranges", 160, 4);
266222 self.debug_aranges_section_dirty = true;
267223 }
268224 if (self.debug_line_section_index == null) {
269 const dwarf_segment = &self.load_commands.items[self.dwarf_segment_cmd_index.?].Segment;
270 self.debug_line_section_index = @intCast(u16, dwarf_segment.sections.items.len);
225 self.debug_line_section_index = try self.allocateSection("__debug_line", 250, 0);
226 self.debug_line_header_dirty = true;
227 }
228}
271229
272 const file_size_hint = 250;
273 const p_align = 1;
274 const off = dwarf_segment.findFreeSpace(file_size_hint, p_align, null);
230fn allocateSection(self: *DebugSymbols, sectname: []const u8, size: u64, alignment: u16) !u16 {
231 const seg = &self.load_commands.items[self.dwarf_segment_cmd_index.?].Segment;
232 var sect = macho.section_64{
233 .sectname = makeStaticString(sectname),
234 .segname = seg.inner.segname,
235 .size = @intCast(u32, size),
236 .@"align" = alignment,
237 };
238 const alignment_pow_2 = try math.powi(u32, 2, alignment);
239 const off = seg.findFreeSpace(size, alignment_pow_2, null);
275240
276 log.debug("found __debug_line free space 0x{x} to 0x{x}", .{ off, off + file_size_hint });
241 assert(off + size <= seg.inner.fileoff + seg.inner.filesize); // TODO expand
277242
278 try dwarf_segment.addSection(allocator, "__debug_line", .{
279 .addr = dwarf_segment.inner.vmaddr + off - dwarf_segment.inner.fileoff,
280 .size = file_size_hint,
281 .offset = @intCast(u32, off),
282 .@"align" = p_align,
283 });
284 self.load_commands_dirty = true;
285 self.debug_line_header_dirty = true;
286 }
243 log.debug("found {s},{s} section free space 0x{x} to 0x{x}", .{
244 commands.segmentName(sect),
245 commands.sectionName(sect),
246 off,
247 off + size,
248 });
249
250 sect.addr = seg.inner.vmaddr + off - seg.inner.fileoff;
251 sect.offset = @intCast(u32, off);
252
253 const index = @intCast(u16, seg.sections.items.len);
254 try seg.sections.append(self.base.base.allocator, sect);
255 seg.inner.cmdsize += @sizeOf(macho.section_64);
256 seg.inner.nsects += 1;
257
258 // TODO
259 // const match = MatchingSection{
260 // .seg = segment_id,
261 // .sect = index,
262 // };
263 // _ = try self.section_ordinals.getOrPut(self.base.allocator, match);
264 // try self.block_free_lists.putNoClobber(self.base.allocator, match, .{});
265
266 self.load_commands_dirty = true;
267
268 return index;
287269}
288270
289271pub fn flushModule(self: *DebugSymbols, allocator: *Allocator, options: link.Options) !void {
......@@ -611,15 +593,18 @@ pub fn deinit(self: *DebugSymbols, allocator: *Allocator) void {
611593}
612594
613595fn copySegmentCommand(self: *DebugSymbols, allocator: *Allocator, base_cmd: SegmentCommand) !SegmentCommand {
614 var cmd = SegmentCommand.empty("", .{
615 .cmdsize = base_cmd.inner.cmdsize,
616 .vmaddr = base_cmd.inner.vmaddr,
617 .vmsize = base_cmd.inner.vmsize,
618 .maxprot = base_cmd.inner.maxprot,
619 .initprot = base_cmd.inner.initprot,
620 .nsects = base_cmd.inner.nsects,
621 .flags = base_cmd.inner.flags,
622 });
596 var cmd = SegmentCommand{
597 .inner = .{
598 .segname = undefined,
599 .cmdsize = base_cmd.inner.cmdsize,
600 .vmaddr = base_cmd.inner.vmaddr,
601 .vmsize = base_cmd.inner.vmsize,
602 .maxprot = base_cmd.inner.maxprot,
603 .initprot = base_cmd.inner.initprot,
604 .nsects = base_cmd.inner.nsects,
605 .flags = base_cmd.inner.flags,
606 },
607 };
623608 mem.copy(u8, &cmd.inner.segname, &base_cmd.inner.segname);
624609
625610 try cmd.sections.ensureCapacity(allocator, cmd.inner.nsects);
......@@ -689,7 +674,7 @@ fn writeLoadCommands(self: *DebugSymbols, allocator: *Allocator) !void {
689674}
690675
691676fn writeHeader(self: *DebugSymbols) !void {
692 var header = emptyHeader(.{
677 var header = commands.emptyHeader(.{
693678 .filetype = macho.MH_DSYM,
694679 });
695680
src/link/MachO/commands.zig+5-88
......@@ -9,6 +9,7 @@ const assert = std.debug.assert;
99
1010const Allocator = std.mem.Allocator;
1111const MachO = @import("../MachO.zig");
12const makeStaticString = MachO.makeStaticString;
1213const padToIdeal = MachO.padToIdeal;
1314
1415pub const HeaderArgs = struct {
......@@ -217,75 +218,6 @@ pub const SegmentCommand = struct {
217218 inner: macho.segment_command_64,
218219 sections: std.ArrayListUnmanaged(macho.section_64) = .{},
219220
220 const SegmentOptions = struct {
221 cmdsize: u32 = @sizeOf(macho.segment_command_64),
222 vmaddr: u64 = 0,
223 vmsize: u64 = 0,
224 fileoff: u64 = 0,
225 filesize: u64 = 0,
226 maxprot: macho.vm_prot_t = macho.VM_PROT_NONE,
227 initprot: macho.vm_prot_t = macho.VM_PROT_NONE,
228 nsects: u32 = 0,
229 flags: u32 = 0,
230 };
231
232 pub fn empty(comptime segname: []const u8, opts: SegmentOptions) SegmentCommand {
233 return .{
234 .inner = .{
235 .cmd = macho.LC_SEGMENT_64,
236 .cmdsize = opts.cmdsize,
237 .segname = makeStaticString(segname),
238 .vmaddr = opts.vmaddr,
239 .vmsize = opts.vmsize,
240 .fileoff = opts.fileoff,
241 .filesize = opts.filesize,
242 .maxprot = opts.maxprot,
243 .initprot = opts.initprot,
244 .nsects = opts.nsects,
245 .flags = opts.flags,
246 },
247 };
248 }
249
250 const SectionOptions = struct {
251 addr: u64 = 0,
252 size: u64 = 0,
253 offset: u32 = 0,
254 @"align": u32 = 0,
255 reloff: u32 = 0,
256 nreloc: u32 = 0,
257 flags: u32 = macho.S_REGULAR,
258 reserved1: u32 = 0,
259 reserved2: u32 = 0,
260 reserved3: u32 = 0,
261 };
262
263 pub fn addSection(
264 self: *SegmentCommand,
265 alloc: *Allocator,
266 comptime sectname: []const u8,
267 opts: SectionOptions,
268 ) !void {
269 var section = macho.section_64{
270 .sectname = makeStaticString(sectname),
271 .segname = undefined,
272 .addr = opts.addr,
273 .size = opts.size,
274 .offset = opts.offset,
275 .@"align" = opts.@"align",
276 .reloff = opts.reloff,
277 .nreloc = opts.nreloc,
278 .flags = opts.flags,
279 .reserved1 = opts.reserved1,
280 .reserved2 = opts.reserved2,
281 .reserved3 = opts.reserved3,
282 };
283 mem.copy(u8, &section.segname, &self.inner.segname);
284 try self.sections.append(alloc, section);
285 self.inner.cmdsize += @sizeOf(macho.section_64);
286 self.inner.nsects += 1;
287 }
288
289221 pub fn read(alloc: *Allocator, reader: anytype) !SegmentCommand {
290222 const inner = try reader.readStruct(macho.segment_command_64);
291223 var segment = SegmentCommand{
......@@ -427,13 +359,6 @@ pub fn createLoadDylibCommand(
427359 return dylib_cmd;
428360}
429361
430fn makeStaticString(bytes: []const u8) [16]u8 {
431 var buf = [_]u8{0} ** 16;
432 assert(bytes.len <= buf.len);
433 mem.copy(u8, &buf, bytes);
434 return buf;
435}
436
437362fn parseName(name: *const [16]u8) []const u8 {
438363 const len = mem.indexOfScalar(u8, name, @as(u8, 0)) orelse name.len;
439364 return name[0..len];
......@@ -513,34 +438,26 @@ test "read-write segment command" {
513438 0x00, 0x00, 0x00, 0x00, // reserved3
514439 };
515440 var cmd = SegmentCommand{
516 .inner = .{
517 .cmd = macho.LC_SEGMENT_64,
441 .inner = macho.segment_command_64.new(.{
518442 .cmdsize = 152,
519443 .segname = makeStaticString("__TEXT"),
520444 .vmaddr = 4294967296,
521445 .vmsize = 294912,
522 .fileoff = 0,
523446 .filesize = 294912,
524447 .maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE | macho.VM_PROT_EXECUTE,
525448 .initprot = macho.VM_PROT_EXECUTE | macho.VM_PROT_READ,
526449 .nsects = 1,
527 .flags = 0,
528 },
450 }),
529451 };
530 try cmd.sections.append(gpa, .{
452 try cmd.sections.append(gpa, macho.section_64.new(.{
531453 .sectname = makeStaticString("__text"),
532454 .segname = makeStaticString("__TEXT"),
533455 .addr = 4294983680,
534456 .size = 448,
535457 .offset = 16384,
536458 .@"align" = 2,
537 .reloff = 0,
538 .nreloc = 0,
539459 .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
540 .reserved1 = 0,
541 .reserved2 = 0,
542 .reserved3 = 0,
543 });
460 }));
544461 defer cmd.deinit(gpa);
545462 try testRead(gpa, in_buffer, LoadCommand{ .Segment = cmd });
546463