authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-03-08 17:21:25+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-03-17 19:59:13+01:00
log349f878ecf0b6ad5eee6b1cdfdba90014cbcb619
tree20a4616ade9191ad714c0804a12f248ecc5b3ebb
parent62f43fbc068ae63b6492af20a7cfd38b7426cb92

zld: mimick Apple and add __DATA_CONST seg


1 files changed, 176 insertions(+), 153 deletions(-)

src/link/MachO/Zld.zig+176-153
...@@ -37,6 +37,7 @@ load_commands: std.ArrayListUnmanaged(LoadCommand) = .{},...@@ -37,6 +37,7 @@ load_commands: std.ArrayListUnmanaged(LoadCommand) = .{},
3737
38pagezero_segment_cmd_index: ?u16 = null,38pagezero_segment_cmd_index: ?u16 = null,
39text_segment_cmd_index: ?u16 = null,39text_segment_cmd_index: ?u16 = null,
40data_const_segment_cmd_index: ?u16 = null,
40data_segment_cmd_index: ?u16 = null,41data_segment_cmd_index: ?u16 = null,
41linkedit_segment_cmd_index: ?u16 = null,42linkedit_segment_cmd_index: ?u16 = null,
42dyld_info_cmd_index: ?u16 = null,43dyld_info_cmd_index: ?u16 = null,
...@@ -277,6 +278,7 @@ pub fn link(self: *Zld, files: []const []const u8, out_path: []const u8) !void {...@@ -277,6 +278,7 @@ pub fn link(self: *Zld, files: []const []const u8, out_path: []const u8) !void {
277 try self.sortSections();278 try self.sortSections();
278 try self.resolveImports();279 try self.resolveImports();
279 try self.allocateTextSegment();280 try self.allocateTextSegment();
281 try self.allocateDataConstSegment();
280 try self.allocateDataSegment();282 try self.allocateDataSegment();
281 self.allocateLinkeditSegment();283 self.allocateLinkeditSegment();
282 try self.writeStubHelperCommon();284 try self.writeStubHelperCommon();
...@@ -362,6 +364,7 @@ fn updateMetadata(self: *Zld, object_id: u16) !void {...@@ -362,6 +364,7 @@ fn updateMetadata(self: *Zld, object_id: u16) !void {
362 const object = self.objects.items[object_id];364 const object = self.objects.items[object_id];
363 const object_seg = object.load_commands.items[object.segment_cmd_index.?].Segment;365 const object_seg = object.load_commands.items[object.segment_cmd_index.?].Segment;
364 const text_seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;366 const text_seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
367 const data_const_seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
365 const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;368 const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
366369
367 // Create missing metadata370 // Create missing metadata
...@@ -395,10 +398,10 @@ fn updateMetadata(self: *Zld, object_id: u16) !void {...@@ -395,10 +398,10 @@ fn updateMetadata(self: *Zld, object_id: u16) !void {
395 if (!mem.eql(u8, sectname, "__const")) continue;398 if (!mem.eql(u8, sectname, "__const")) continue;
396 if (self.data_const_section_index != null) continue;399 if (self.data_const_section_index != null) continue;
397400
398 self.data_const_section_index = @intCast(u16, data_seg.sections.items.len);401 self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);
399 try data_seg.addSection(self.allocator, .{402 try data_const_seg.addSection(self.allocator, .{
400 .sectname = makeStaticString("__const"),403 .sectname = makeStaticString("__const"),
401 .segname = makeStaticString("__DATA"),404 .segname = makeStaticString("__DATA_CONST"),
402 .addr = 0,405 .addr = 0,
403 .size = 0,406 .size = 0,
404 .offset = 0,407 .offset = 0,
...@@ -611,7 +614,7 @@ fn getMatchingSection(self: *Zld, section: macho.section_64) ?MatchingSection {...@@ -611,7 +614,7 @@ fn getMatchingSection(self: *Zld, section: macho.section_64) ?MatchingSection {
611 };614 };
612 } else if (mem.eql(u8, sectname, "__const")) {615 } else if (mem.eql(u8, sectname, "__const")) {
613 break :blk .{616 break :blk .{
614 .seg = self.data_segment_cmd_index.?,617 .seg = self.data_const_segment_cmd_index.?,
615 .sect = self.data_const_section_index.?,618 .sect = self.data_const_section_index.?,
616 };619 };
617 }620 }
...@@ -627,100 +630,85 @@ fn getMatchingSection(self: *Zld, section: macho.section_64) ?MatchingSection {...@@ -627,100 +630,85 @@ fn getMatchingSection(self: *Zld, section: macho.section_64) ?MatchingSection {
627}630}
628631
629fn sortSections(self: *Zld) !void {632fn sortSections(self: *Zld) !void {
630 const text_seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
631 var text_sections = text_seg.sections.toOwnedSlice(self.allocator);
632 defer self.allocator.free(text_sections);
633 try text_seg.sections.ensureCapacity(self.allocator, text_sections.len);
634
635 const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
636 var data_sections = data_seg.sections.toOwnedSlice(self.allocator);
637 defer self.allocator.free(data_sections);
638 try data_seg.sections.ensureCapacity(self.allocator, data_sections.len);
639
640 var text_index_mapping = std.AutoHashMap(u16, u16).init(self.allocator);633 var text_index_mapping = std.AutoHashMap(u16, u16).init(self.allocator);
641 defer text_index_mapping.deinit();634 defer text_index_mapping.deinit();
642635 var data_const_index_mapping = std.AutoHashMap(u16, u16).init(self.allocator);
636 defer data_const_index_mapping.deinit();
643 var data_index_mapping = std.AutoHashMap(u16, u16).init(self.allocator);637 var data_index_mapping = std.AutoHashMap(u16, u16).init(self.allocator);
644 defer data_index_mapping.deinit();638 defer data_index_mapping.deinit();
645639
646 if (self.text_section_index) |index| {640 {
647 const new_index = @intCast(u16, text_seg.sections.items.len);641 // __TEXT segment
648 self.text_section_index = new_index;642 const seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
649 text_seg.sections.appendAssumeCapacity(text_sections[index]);643 var sections = seg.sections.toOwnedSlice(self.allocator);
650 try text_index_mapping.putNoClobber(index, new_index);644 defer self.allocator.free(sections);
651 }645 try seg.sections.ensureCapacity(self.allocator, sections.len);
652 if (self.stubs_section_index) |index| {646
653 const new_index = @intCast(u16, text_seg.sections.items.len);647 const indices = &[_]*?u16{
654 self.stubs_section_index = new_index;648 &self.text_section_index,
655 text_seg.sections.appendAssumeCapacity(text_sections[index]);649 &self.stubs_section_index,
656 try text_index_mapping.putNoClobber(index, new_index);650 &self.stub_helper_section_index,
657 }651 &self.text_const_section_index,
658 if (self.stub_helper_section_index) |index| {652 &self.cstring_section_index,
659 const new_index = @intCast(u16, text_seg.sections.items.len);653 };
660 self.stub_helper_section_index = new_index;654 for (indices) |maybe_index| {
661 text_seg.sections.appendAssumeCapacity(text_sections[index]);655 const new_index: u16 = if (maybe_index.*) |index| blk: {
662 try text_index_mapping.putNoClobber(index, new_index);656 const idx = @intCast(u16, seg.sections.items.len);
663 }657 seg.sections.appendAssumeCapacity(sections[index]);
664 if (self.text_const_section_index) |index| {658 try text_index_mapping.putNoClobber(index, idx);
665 const new_index = @intCast(u16, text_seg.sections.items.len);659 break :blk idx;
666 self.text_const_section_index = new_index;660 } else continue;
667 text_seg.sections.appendAssumeCapacity(text_sections[index]);661 maybe_index.* = new_index;
668 try text_index_mapping.putNoClobber(index, new_index);662 }
669 }
670 if (self.cstring_section_index) |index| {
671 const new_index = @intCast(u16, text_seg.sections.items.len);
672 self.cstring_section_index = new_index;
673 text_seg.sections.appendAssumeCapacity(text_sections[index]);
674 try text_index_mapping.putNoClobber(index, new_index);
675 }
676
677 if (self.got_section_index) |index| {
678 const new_index = @intCast(u16, data_seg.sections.items.len);
679 self.got_section_index = new_index;
680 data_seg.sections.appendAssumeCapacity(data_sections[index]);
681 try data_index_mapping.putNoClobber(index, new_index);
682 }
683 if (self.data_const_section_index) |index| {
684 const new_index = @intCast(u16, data_seg.sections.items.len);
685 self.data_const_section_index = new_index;
686 data_seg.sections.appendAssumeCapacity(data_sections[index]);
687 try data_index_mapping.putNoClobber(index, new_index);
688 }
689 if (self.la_symbol_ptr_section_index) |index| {
690 const new_index = @intCast(u16, data_seg.sections.items.len);
691 self.la_symbol_ptr_section_index = new_index;
692 data_seg.sections.appendAssumeCapacity(data_sections[index]);
693 try data_index_mapping.putNoClobber(index, new_index);
694 }
695 if (self.tlv_section_index) |index| {
696 const new_index = @intCast(u16, data_seg.sections.items.len);
697 self.tlv_section_index = new_index;
698 data_seg.sections.appendAssumeCapacity(data_sections[index]);
699 try data_index_mapping.putNoClobber(index, new_index);
700 }
701 if (self.data_section_index) |index| {
702 const new_index = @intCast(u16, data_seg.sections.items.len);
703 self.data_section_index = new_index;
704 data_seg.sections.appendAssumeCapacity(data_sections[index]);
705 try data_index_mapping.putNoClobber(index, new_index);
706 }
707 if (self.tlv_data_section_index) |index| {
708 const new_index = @intCast(u16, data_seg.sections.items.len);
709 self.tlv_data_section_index = new_index;
710 data_seg.sections.appendAssumeCapacity(data_sections[index]);
711 try data_index_mapping.putNoClobber(index, new_index);
712 }663 }
713 if (self.tlv_bss_section_index) |index| {664
714 const new_index = @intCast(u16, data_seg.sections.items.len);665 {
715 self.tlv_bss_section_index = new_index;666 // __DATA_CONST segment
716 data_seg.sections.appendAssumeCapacity(data_sections[index]);667 const seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
717 try data_index_mapping.putNoClobber(index, new_index);668 var sections = seg.sections.toOwnedSlice(self.allocator);
669 defer self.allocator.free(sections);
670 try seg.sections.ensureCapacity(self.allocator, sections.len);
671
672 const indices = &[_]*?u16{
673 &self.got_section_index,
674 &self.data_const_section_index,
675 };
676 for (indices) |maybe_index| {
677 const new_index: u16 = if (maybe_index.*) |index| blk: {
678 const idx = @intCast(u16, seg.sections.items.len);
679 seg.sections.appendAssumeCapacity(sections[index]);
680 try data_const_index_mapping.putNoClobber(index, idx);
681 break :blk idx;
682 } else continue;
683 maybe_index.* = new_index;
684 }
718 }685 }
719 if (self.bss_section_index) |index| {686
720 const new_index = @intCast(u16, data_seg.sections.items.len);687 {
721 self.bss_section_index = new_index;688 // __DATA segment
722 data_seg.sections.appendAssumeCapacity(data_sections[index]);689 const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
723 try data_index_mapping.putNoClobber(index, new_index);690 var sections = seg.sections.toOwnedSlice(self.allocator);
691 defer self.allocator.free(sections);
692 try seg.sections.ensureCapacity(self.allocator, sections.len);
693
694 // __DATA segment
695 const indices = &[_]*?u16{
696 &self.la_symbol_ptr_section_index,
697 &self.tlv_section_index,
698 &self.data_section_index,
699 &self.tlv_data_section_index,
700 &self.tlv_bss_section_index,
701 &self.bss_section_index,
702 };
703 for (indices) |maybe_index| {
704 const new_index: u16 = if (maybe_index.*) |index| blk: {
705 const idx = @intCast(u16, seg.sections.items.len);
706 seg.sections.appendAssumeCapacity(sections[index]);
707 try data_index_mapping.putNoClobber(index, idx);
708 break :blk idx;
709 } else continue;
710 maybe_index.* = new_index;
711 }
724 }712 }
725713
726 var it = self.mappings.iterator();714 var it = self.mappings.iterator();
...@@ -729,6 +717,9 @@ fn sortSections(self: *Zld) !void {...@@ -729,6 +717,9 @@ fn sortSections(self: *Zld) !void {
729 if (self.text_segment_cmd_index.? == mapping.target_seg_id) {717 if (self.text_segment_cmd_index.? == mapping.target_seg_id) {
730 const new_index = text_index_mapping.get(mapping.target_sect_id) orelse unreachable;718 const new_index = text_index_mapping.get(mapping.target_sect_id) orelse unreachable;
731 mapping.target_sect_id = new_index;719 mapping.target_sect_id = new_index;
720 } else if (self.data_const_segment_cmd_index.? == mapping.target_seg_id) {
721 const new_index = data_const_index_mapping.get(mapping.target_sect_id) orelse unreachable;
722 mapping.target_sect_id = new_index;
732 } else if (self.data_segment_cmd_index.? == mapping.target_seg_id) {723 } else if (self.data_segment_cmd_index.? == mapping.target_seg_id) {
733 const new_index = data_index_mapping.get(mapping.target_sect_id) orelse unreachable;724 const new_index = data_index_mapping.get(mapping.target_sect_id) orelse unreachable;
734 mapping.target_sect_id = new_index;725 mapping.target_sect_id = new_index;
...@@ -874,10 +865,9 @@ fn allocateTextSegment(self: *Zld) !void {...@@ -874,10 +865,9 @@ fn allocateTextSegment(self: *Zld) !void {
874 }865 }
875}866}
876867
877fn allocateDataSegment(self: *Zld) !void {868fn allocateDataConstSegment(self: *Zld) !void {
878 const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;869 const seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
879 const nonlazy = @intCast(u32, self.nonlazy_imports.items().len);870 const nonlazy = @intCast(u32, self.nonlazy_imports.items().len);
880 const lazy = @intCast(u32, self.lazy_imports.items().len);
881871
882 const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment;872 const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
883 seg.inner.fileoff = text_seg.inner.fileoff + text_seg.inner.filesize;873 seg.inner.fileoff = text_seg.inner.fileoff + text_seg.inner.filesize;
...@@ -887,6 +877,17 @@ fn allocateDataSegment(self: *Zld) !void {...@@ -887,6 +877,17 @@ fn allocateDataSegment(self: *Zld) !void {
887 const got = &seg.sections.items[self.got_section_index.?];877 const got = &seg.sections.items[self.got_section_index.?];
888 got.size += nonlazy * @sizeOf(u64);878 got.size += nonlazy * @sizeOf(u64);
889879
880 try self.allocateSegment(self.data_const_segment_cmd_index.?, 0);
881}
882
883fn allocateDataSegment(self: *Zld) !void {
884 const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
885 const lazy = @intCast(u32, self.lazy_imports.items().len);
886
887 const data_const_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
888 seg.inner.fileoff = data_const_seg.inner.fileoff + data_const_seg.inner.filesize;
889 seg.inner.vmaddr = data_const_seg.inner.vmaddr + data_const_seg.inner.vmsize;
890
890 // Set la_symbol_ptr and data size891 // Set la_symbol_ptr and data size
891 const la_symbol_ptr = &seg.sections.items[self.la_symbol_ptr_section_index.?];892 const la_symbol_ptr = &seg.sections.items[self.la_symbol_ptr_section_index.?];
892 const data = &seg.sections.items[self.data_section_index.?];893 const data = &seg.sections.items[self.data_section_index.?];
...@@ -926,10 +927,11 @@ fn allocateSegment(self: *Zld, index: u16, offset: u64) !void {...@@ -926,10 +927,11 @@ fn allocateSegment(self: *Zld, index: u16, offset: u64) !void {
926fn writeStubHelperCommon(self: *Zld) !void {927fn writeStubHelperCommon(self: *Zld) !void {
927 const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;928 const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
928 const stub_helper = &text_segment.sections.items[self.stub_helper_section_index.?];929 const stub_helper = &text_segment.sections.items[self.stub_helper_section_index.?];
930 const data_const_segment = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
931 const got = &data_const_segment.sections.items[self.got_section_index.?];
929 const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;932 const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
930 const data = &data_segment.sections.items[self.data_section_index.?];933 const data = &data_segment.sections.items[self.data_section_index.?];
931 const la_symbol_ptr = data_segment.sections.items[self.la_symbol_ptr_section_index.?];934 const la_symbol_ptr = data_segment.sections.items[self.la_symbol_ptr_section_index.?];
932 const got = &data_segment.sections.items[self.got_section_index.?];
933935
934 self.stub_helper_stubs_start_off = blk: {936 self.stub_helper_stubs_start_off = blk: {
935 switch (self.arch.?) {937 switch (self.arch.?) {
...@@ -1247,15 +1249,16 @@ fn resolveSymbols(self: *Zld) !void {...@@ -1247,15 +1249,16 @@ fn resolveSymbols(self: *Zld) !void {
12471249
1248 log.debug("resolving '{s}':{} as {s} symbol at 0x{x}", .{ sym_name, sym, tt, n_value });1250 log.debug("resolving '{s}':{} as {s} symbol at 0x{x}", .{ sym_name, sym, tt, n_value });
12491251
1250 // TODO this assumes only two symbol-filled segments. Also, there might be a more1252 // TODO there might be a more generic way of doing this.
1251 // generic way of doing this.1253 var n_sect: u16 = 0;
1252 const n_sect = blk: {1254 for (self.load_commands.items) |cmd, cmd_id| {
1253 if (self.text_segment_cmd_index.? == target_mapping.target_seg_id) {1255 if (cmd != .Segment) break;
1254 break :blk target_mapping.target_sect_id + 1;1256 if (cmd_id == target_mapping.target_seg_id) {
1257 n_sect += target_mapping.target_sect_id + 1;
1258 break;
1255 }1259 }
1256 const prev_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment;1260 n_sect += @intCast(u16, cmd.Segment.sections.items.len);
1257 break :blk @intCast(u16, prev_seg.sections.items.len + target_mapping.target_sect_id + 1);1261 }
1258 };
12591262
1260 const n_strx = try self.makeString(sym_name);1263 const n_strx = try self.makeString(sym_name);
1261 try locs.entry.value.append(self.allocator, .{1264 try locs.entry.value.append(self.allocator, .{
...@@ -1460,23 +1463,24 @@ fn doRelocs(self: *Zld) !void {...@@ -1460,23 +1463,24 @@ fn doRelocs(self: *Zld) !void {
1460 mem.writeIntLittle(u64, inst, @bitCast(u64, result));1463 mem.writeIntLittle(u64, inst, @bitCast(u64, result));
1461 sub = null;1464 sub = null;
14621465
1463 // TODO should handle this better.
1464 outer: {1466 outer: {
1465 var hit: bool = false;1467 var hit: bool = false;
1466 if (self.data_section_index) |index| inner: {1468 if (target_mapping.target_seg_id == self.data_segment_cmd_index.?) {
1467 if (index != target_mapping.target_sect_id) break :inner;1469 if (self.data_section_index) |index| {
1468 hit = true;1470 if (index == target_mapping.target_sect_id) hit = true;
1471 }
1469 }1472 }
1470 if (self.data_const_section_index) |index| inner: {1473 if (target_mapping.target_seg_id == self.data_const_segment_cmd_index.?) {
1471 if (index != target_mapping.target_sect_id) break :inner;1474 if (self.data_const_section_index) |index| {
1472 hit = true;1475 if (index == target_mapping.target_sect_id) hit = true;
1476 }
1473 }1477 }
1478
1474 if (!hit) break :outer;1479 if (!hit) break :outer;
1475 const this_seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;1480
1476 const this_offset = target_sect_addr + off - this_seg.inner.vmaddr;
1477 try self.local_rebases.append(self.allocator, .{1481 try self.local_rebases.append(self.allocator, .{
1478 .offset = this_offset,1482 .offset = this_addr - target_seg.inner.vmaddr,
1479 .segment_id = @intCast(u16, self.data_segment_cmd_index.?),1483 .segment_id = target_mapping.target_seg_id,
1480 });1484 });
1481 }1485 }
1482 },1486 },
...@@ -1642,23 +1646,24 @@ fn doRelocs(self: *Zld) !void {...@@ -1642,23 +1646,24 @@ fn doRelocs(self: *Zld) !void {
1642 mem.writeIntLittle(u64, inst, @bitCast(u64, result));1646 mem.writeIntLittle(u64, inst, @bitCast(u64, result));
1643 sub = null;1647 sub = null;
16441648
1645 // TODO should handle this better.
1646 outer: {1649 outer: {
1647 var hit: bool = false;1650 var hit: bool = false;
1648 if (self.data_section_index) |index| inner: {1651 if (target_mapping.target_seg_id == self.data_segment_cmd_index.?) {
1649 if (index != target_mapping.target_sect_id) break :inner;1652 if (self.data_section_index) |index| {
1650 hit = true;1653 if (index == target_mapping.target_sect_id) hit = true;
1654 }
1651 }1655 }
1652 if (self.data_const_section_index) |index| inner: {1656 if (target_mapping.target_seg_id == self.data_const_segment_cmd_index.?) {
1653 if (index != target_mapping.target_sect_id) break :inner;1657 if (self.data_const_section_index) |index| {
1654 hit = true;1658 if (index == target_mapping.target_sect_id) hit = true;
1659 }
1655 }1660 }
1661
1656 if (!hit) break :outer;1662 if (!hit) break :outer;
1657 const this_seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;1663
1658 const this_offset = target_sect_addr + off - this_seg.inner.vmaddr;
1659 try self.local_rebases.append(self.allocator, .{1664 try self.local_rebases.append(self.allocator, .{
1660 .offset = this_offset,1665 .offset = this_addr - target_seg.inner.vmaddr,
1661 .segment_id = @intCast(u16, self.data_segment_cmd_index.?),1666 .segment_id = target_mapping.target_seg_id,
1662 });1667 });
1663 }1668 }
1664 },1669 },
...@@ -1763,7 +1768,7 @@ fn relocTargetAddr(self: *Zld, object_id: u16, rel: macho.relocation_info) !u64...@@ -1763,7 +1768,7 @@ fn relocTargetAddr(self: *Zld, object_id: u16, rel: macho.relocation_info) !u64
1763 const stubs = segment.sections.items[self.stubs_section_index.?];1768 const stubs = segment.sections.items[self.stubs_section_index.?];
1764 break :blk stubs.addr + ext.index * stubs.reserved2;1769 break :blk stubs.addr + ext.index * stubs.reserved2;
1765 } else if (self.nonlazy_imports.get(sym_name)) |ext| {1770 } else if (self.nonlazy_imports.get(sym_name)) |ext| {
1766 const segment = self.load_commands.items[self.data_segment_cmd_index.?].Segment;1771 const segment = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
1767 const got = segment.sections.items[self.got_section_index.?];1772 const got = segment.sections.items[self.got_section_index.?];
1768 break :blk got.addr + ext.index * @sizeOf(u64);1773 break :blk got.addr + ext.index * @sizeOf(u64);
1769 } else if (self.threadlocal_imports.get(sym_name)) |ext| {1774 } else if (self.threadlocal_imports.get(sym_name)) |ext| {
...@@ -1916,13 +1921,13 @@ fn populateMetadata(self: *Zld) !void {...@@ -1916,13 +1921,13 @@ fn populateMetadata(self: *Zld) !void {
1916 });1921 });
1917 }1922 }
19181923
1919 if (self.data_segment_cmd_index == null) {1924 if (self.data_const_segment_cmd_index == null) {
1920 self.data_segment_cmd_index = @intCast(u16, self.load_commands.items.len);1925 self.data_const_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
1921 try self.load_commands.append(self.allocator, .{1926 try self.load_commands.append(self.allocator, .{
1922 .Segment = SegmentCommand.empty(.{1927 .Segment = SegmentCommand.empty(.{
1923 .cmd = macho.LC_SEGMENT_64,1928 .cmd = macho.LC_SEGMENT_64,
1924 .cmdsize = @sizeOf(macho.segment_command_64),1929 .cmdsize = @sizeOf(macho.segment_command_64),
1925 .segname = makeStaticString("__DATA"),1930 .segname = makeStaticString("__DATA_CONST"),
1926 .vmaddr = 0,1931 .vmaddr = 0,
1927 .vmsize = 0,1932 .vmsize = 0,
1928 .fileoff = 0,1933 .fileoff = 0,
...@@ -1936,11 +1941,11 @@ fn populateMetadata(self: *Zld) !void {...@@ -1936,11 +1941,11 @@ fn populateMetadata(self: *Zld) !void {
1936 }1941 }
19371942
1938 if (self.got_section_index == null) {1943 if (self.got_section_index == null) {
1939 const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;1944 const data_const_seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
1940 self.got_section_index = @intCast(u16, data_seg.sections.items.len);1945 self.got_section_index = @intCast(u16, data_const_seg.sections.items.len);
1941 try data_seg.addSection(self.allocator, .{1946 try data_const_seg.addSection(self.allocator, .{
1942 .sectname = makeStaticString("__got"),1947 .sectname = makeStaticString("__got"),
1943 .segname = makeStaticString("__DATA"),1948 .segname = makeStaticString("__DATA_CONST"),
1944 .addr = 0,1949 .addr = 0,
1945 .size = 0,1950 .size = 0,
1946 .offset = 0,1951 .offset = 0,
...@@ -1954,6 +1959,25 @@ fn populateMetadata(self: *Zld) !void {...@@ -1954,6 +1959,25 @@ fn populateMetadata(self: *Zld) !void {
1954 });1959 });
1955 }1960 }
19561961
1962 if (self.data_segment_cmd_index == null) {
1963 self.data_segment_cmd_index = @intCast(u16, self.load_commands.items.len);
1964 try self.load_commands.append(self.allocator, .{
1965 .Segment = SegmentCommand.empty(.{
1966 .cmd = macho.LC_SEGMENT_64,
1967 .cmdsize = @sizeOf(macho.segment_command_64),
1968 .segname = makeStaticString("__DATA"),
1969 .vmaddr = 0,
1970 .vmsize = 0,
1971 .fileoff = 0,
1972 .filesize = 0,
1973 .maxprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE,
1974 .initprot = macho.VM_PROT_READ | macho.VM_PROT_WRITE,
1975 .nsects = 0,
1976 .flags = 0,
1977 }),
1978 });
1979 }
1980
1957 if (self.la_symbol_ptr_section_index == null) {1981 if (self.la_symbol_ptr_section_index == null) {
1958 const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;1982 const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
1959 self.la_symbol_ptr_section_index = @intCast(u16, data_seg.sections.items.len);1983 self.la_symbol_ptr_section_index = @intCast(u16, data_seg.sections.items.len);
...@@ -2269,15 +2293,17 @@ fn setEntryPoint(self: *Zld) !void {...@@ -2269,15 +2293,17 @@ fn setEntryPoint(self: *Zld) !void {
2269}2293}
22702294
2271fn writeRebaseInfoTable(self: *Zld) !void {2295fn writeRebaseInfoTable(self: *Zld) !void {
2272 const data_seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
2273
2274 var pointers = std.ArrayList(Pointer).init(self.allocator);2296 var pointers = std.ArrayList(Pointer).init(self.allocator);
2275 defer pointers.deinit();2297 defer pointers.deinit();
2276 try pointers.ensureCapacity(self.lazy_imports.items().len);2298
2299 try pointers.ensureCapacity(pointers.items.len + self.local_rebases.items.len);
2300 pointers.appendSliceAssumeCapacity(self.local_rebases.items);
22772301
2278 if (self.la_symbol_ptr_section_index) |idx| {2302 if (self.la_symbol_ptr_section_index) |idx| {
2279 const sect = data_seg.sections.items[idx];2303 try pointers.ensureCapacity(pointers.items.len + self.lazy_imports.items().len);
2280 const base_offset = sect.addr - data_seg.inner.vmaddr;2304 const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
2305 const sect = seg.sections.items[idx];
2306 const base_offset = sect.addr - seg.inner.vmaddr;
2281 const segment_id = @intCast(u16, self.data_segment_cmd_index.?);2307 const segment_id = @intCast(u16, self.data_segment_cmd_index.?);
2282 for (self.lazy_imports.items()) |entry| {2308 for (self.lazy_imports.items()) |entry| {
2283 pointers.appendAssumeCapacity(.{2309 pointers.appendAssumeCapacity(.{
...@@ -2287,9 +2313,6 @@ fn writeRebaseInfoTable(self: *Zld) !void {...@@ -2287,9 +2313,6 @@ fn writeRebaseInfoTable(self: *Zld) !void {
2287 }2313 }
2288 }2314 }
22892315
2290 try pointers.ensureCapacity(pointers.items.len + self.local_rebases.items.len);
2291 pointers.appendSliceAssumeCapacity(self.local_rebases.items);
2292
2293 std.sort.sort(Pointer, pointers.items, {}, pointerCmp);2316 std.sort.sort(Pointer, pointers.items, {}, pointerCmp);
22942317
2295 const size = try rebaseInfoSize(pointers.items);2318 const size = try rebaseInfoSize(pointers.items);
...@@ -2319,16 +2342,15 @@ fn pointerCmp(context: void, a: Pointer, b: Pointer) bool {...@@ -2319,16 +2342,15 @@ fn pointerCmp(context: void, a: Pointer, b: Pointer) bool {
2319}2342}
23202343
2321fn writeBindInfoTable(self: *Zld) !void {2344fn writeBindInfoTable(self: *Zld) !void {
2322 const data_seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
2323
2324 var pointers = std.ArrayList(Pointer).init(self.allocator);2345 var pointers = std.ArrayList(Pointer).init(self.allocator);
2325 defer pointers.deinit();2346 defer pointers.deinit();
2326 try pointers.ensureCapacity(self.nonlazy_imports.items().len + self.threadlocal_imports.items().len);2347 try pointers.ensureCapacity(self.nonlazy_imports.items().len + self.threadlocal_imports.items().len);
23272348
2328 if (self.got_section_index) |idx| {2349 if (self.got_section_index) |idx| {
2329 const sect = data_seg.sections.items[idx];2350 const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
2330 const base_offset = sect.addr - data_seg.inner.vmaddr;2351 const sect = seg.sections.items[idx];
2331 const segment_id = @intCast(u16, self.data_segment_cmd_index.?);2352 const base_offset = sect.addr - seg.inner.vmaddr;
2353 const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?);
2332 for (self.nonlazy_imports.items()) |entry| {2354 for (self.nonlazy_imports.items()) |entry| {
2333 pointers.appendAssumeCapacity(.{2355 pointers.appendAssumeCapacity(.{
2334 .offset = base_offset + entry.value.index * @sizeOf(u64),2356 .offset = base_offset + entry.value.index * @sizeOf(u64),
...@@ -2340,8 +2362,9 @@ fn writeBindInfoTable(self: *Zld) !void {...@@ -2340,8 +2362,9 @@ fn writeBindInfoTable(self: *Zld) !void {
2340 }2362 }
23412363
2342 if (self.tlv_section_index) |idx| {2364 if (self.tlv_section_index) |idx| {
2343 const sect = data_seg.sections.items[idx];2365 const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
2344 const base_offset = sect.addr - data_seg.inner.vmaddr;2366 const sect = seg.sections.items[idx];
2367 const base_offset = sect.addr - seg.inner.vmaddr;
2345 const segment_id = @intCast(u16, self.data_segment_cmd_index.?);2368 const segment_id = @intCast(u16, self.data_segment_cmd_index.?);
2346 for (self.threadlocal_imports.items()) |entry| {2369 for (self.threadlocal_imports.items()) |entry| {
2347 pointers.appendAssumeCapacity(.{2370 pointers.appendAssumeCapacity(.{
...@@ -2372,15 +2395,14 @@ fn writeBindInfoTable(self: *Zld) !void {...@@ -2372,15 +2395,14 @@ fn writeBindInfoTable(self: *Zld) !void {
2372}2395}
23732396
2374fn writeLazyBindInfoTable(self: *Zld) !void {2397fn writeLazyBindInfoTable(self: *Zld) !void {
2375 const data_seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
2376
2377 var pointers = std.ArrayList(Pointer).init(self.allocator);2398 var pointers = std.ArrayList(Pointer).init(self.allocator);
2378 defer pointers.deinit();2399 defer pointers.deinit();
2379 try pointers.ensureCapacity(self.lazy_imports.items().len);2400 try pointers.ensureCapacity(self.lazy_imports.items().len);
23802401
2381 if (self.la_symbol_ptr_section_index) |idx| {2402 if (self.la_symbol_ptr_section_index) |idx| {
2382 const sect = data_seg.sections.items[idx];2403 const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
2383 const base_offset = sect.addr - data_seg.inner.vmaddr;2404 const sect = seg.sections.items[idx];
2405 const base_offset = sect.addr - seg.inner.vmaddr;
2384 const segment_id = @intCast(u16, self.data_segment_cmd_index.?);2406 const segment_id = @intCast(u16, self.data_segment_cmd_index.?);
2385 for (self.lazy_imports.items()) |entry| {2407 for (self.lazy_imports.items()) |entry| {
2386 pointers.appendAssumeCapacity(.{2408 pointers.appendAssumeCapacity(.{
...@@ -2725,8 +2747,9 @@ fn writeDynamicSymbolTable(self: *Zld) !void {...@@ -2725,8 +2747,9 @@ fn writeDynamicSymbolTable(self: *Zld) !void {
2725 const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;2747 const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;
2726 const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;2748 const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
2727 const stubs = &text_segment.sections.items[self.stubs_section_index.?];2749 const stubs = &text_segment.sections.items[self.stubs_section_index.?];
2750 const data_const_segment = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
2751 const got = &data_const_segment.sections.items[self.got_section_index.?];
2728 const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;2752 const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
2729 const got = &data_segment.sections.items[self.got_section_index.?];
2730 const la_symbol_ptr = &data_segment.sections.items[self.la_symbol_ptr_section_index.?];2753 const la_symbol_ptr = &data_segment.sections.items[self.la_symbol_ptr_section_index.?];
2731 const dysymtab = &self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab;2754 const dysymtab = &self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab;
27322755