| ... | ... | @@ -37,6 +37,7 @@ load_commands: std.ArrayListUnmanaged(LoadCommand) = .{}, |
| 37 | 37 | |
| 38 | 38 | pagezero_segment_cmd_index: ?u16 = null, |
| 39 | 39 | text_segment_cmd_index: ?u16 = null, |
| 40 | data_const_segment_cmd_index: ?u16 = null, |
| 40 | 41 | data_segment_cmd_index: ?u16 = null, |
| 41 | 42 | linkedit_segment_cmd_index: ?u16 = null, |
| 42 | 43 | dyld_info_cmd_index: ?u16 = null, |
| ... | ... | @@ -277,6 +278,7 @@ pub fn link(self: *Zld, files: []const []const u8, out_path: []const u8) !void { |
| 277 | 278 | try self.sortSections(); |
| 278 | 279 | try self.resolveImports(); |
| 279 | 280 | try self.allocateTextSegment(); |
| 281 | try self.allocateDataConstSegment(); |
| 280 | 282 | try self.allocateDataSegment(); |
| 281 | 283 | self.allocateLinkeditSegment(); |
| 282 | 284 | try self.writeStubHelperCommon(); |
| ... | ... | @@ -362,6 +364,7 @@ fn updateMetadata(self: *Zld, object_id: u16) !void { |
| 362 | 364 | const object = self.objects.items[object_id]; |
| 363 | 365 | const object_seg = object.load_commands.items[object.segment_cmd_index.?].Segment; |
| 364 | 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 | 368 | const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 366 | 369 | |
| 367 | 370 | // Create missing metadata |
| ... | ... | @@ -395,10 +398,10 @@ fn updateMetadata(self: *Zld, object_id: u16) !void { |
| 395 | 398 | if (!mem.eql(u8, sectname, "__const")) continue; |
| 396 | 399 | if (self.data_const_section_index != null) continue; |
| 397 | 400 | |
| 398 | | self.data_const_section_index = @intCast(u16, data_seg.sections.items.len); |
| 399 | | try data_seg.addSection(self.allocator, .{ |
| 401 | self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len); |
| 402 | try data_const_seg.addSection(self.allocator, .{ |
| 400 | 403 | .sectname = makeStaticString("__const"), |
| 401 | | .segname = makeStaticString("__DATA"), |
| 404 | .segname = makeStaticString("__DATA_CONST"), |
| 402 | 405 | .addr = 0, |
| 403 | 406 | .size = 0, |
| 404 | 407 | .offset = 0, |
| ... | ... | @@ -611,7 +614,7 @@ fn getMatchingSection(self: *Zld, section: macho.section_64) ?MatchingSection { |
| 611 | 614 | }; |
| 612 | 615 | } else if (mem.eql(u8, sectname, "__const")) { |
| 613 | 616 | break :blk .{ |
| 614 | | .seg = self.data_segment_cmd_index.?, |
| 617 | .seg = self.data_const_segment_cmd_index.?, |
| 615 | 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 | 630 | } |
| 628 | 631 | |
| 629 | 632 | fn 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 | 633 | var text_index_mapping = std.AutoHashMap(u16, u16).init(self.allocator); |
| 641 | 634 | defer text_index_mapping.deinit(); |
| 642 | | |
| 635 | var data_const_index_mapping = std.AutoHashMap(u16, u16).init(self.allocator); |
| 636 | defer data_const_index_mapping.deinit(); |
| 643 | 637 | var data_index_mapping = std.AutoHashMap(u16, u16).init(self.allocator); |
| 644 | 638 | defer data_index_mapping.deinit(); |
| 645 | 639 | |
| 646 | | if (self.text_section_index) |index| { |
| 647 | | const new_index = @intCast(u16, text_seg.sections.items.len); |
| 648 | | self.text_section_index = new_index; |
| 649 | | text_seg.sections.appendAssumeCapacity(text_sections[index]); |
| 650 | | try text_index_mapping.putNoClobber(index, new_index); |
| 651 | | } |
| 652 | | if (self.stubs_section_index) |index| { |
| 653 | | const new_index = @intCast(u16, text_seg.sections.items.len); |
| 654 | | self.stubs_section_index = new_index; |
| 655 | | text_seg.sections.appendAssumeCapacity(text_sections[index]); |
| 656 | | try text_index_mapping.putNoClobber(index, new_index); |
| 657 | | } |
| 658 | | if (self.stub_helper_section_index) |index| { |
| 659 | | const new_index = @intCast(u16, text_seg.sections.items.len); |
| 660 | | self.stub_helper_section_index = new_index; |
| 661 | | text_seg.sections.appendAssumeCapacity(text_sections[index]); |
| 662 | | try text_index_mapping.putNoClobber(index, new_index); |
| 663 | | } |
| 664 | | if (self.text_const_section_index) |index| { |
| 665 | | const new_index = @intCast(u16, text_seg.sections.items.len); |
| 666 | | self.text_const_section_index = new_index; |
| 667 | | text_seg.sections.appendAssumeCapacity(text_sections[index]); |
| 668 | | try text_index_mapping.putNoClobber(index, new_index); |
| 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); |
| 640 | { |
| 641 | // __TEXT segment |
| 642 | const seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 643 | var sections = seg.sections.toOwnedSlice(self.allocator); |
| 644 | defer self.allocator.free(sections); |
| 645 | try seg.sections.ensureCapacity(self.allocator, sections.len); |
| 646 | |
| 647 | const indices = &[_]*?u16{ |
| 648 | &self.text_section_index, |
| 649 | &self.stubs_section_index, |
| 650 | &self.stub_helper_section_index, |
| 651 | &self.text_const_section_index, |
| 652 | &self.cstring_section_index, |
| 653 | }; |
| 654 | for (indices) |maybe_index| { |
| 655 | const new_index: u16 = if (maybe_index.*) |index| blk: { |
| 656 | const idx = @intCast(u16, seg.sections.items.len); |
| 657 | seg.sections.appendAssumeCapacity(sections[index]); |
| 658 | try text_index_mapping.putNoClobber(index, idx); |
| 659 | break :blk idx; |
| 660 | } else continue; |
| 661 | maybe_index.* = new_index; |
| 662 | } |
| 712 | 663 | } |
| 713 | | if (self.tlv_bss_section_index) |index| { |
| 714 | | const new_index = @intCast(u16, data_seg.sections.items.len); |
| 715 | | self.tlv_bss_section_index = new_index; |
| 716 | | data_seg.sections.appendAssumeCapacity(data_sections[index]); |
| 717 | | try data_index_mapping.putNoClobber(index, new_index); |
| 664 | |
| 665 | { |
| 666 | // __DATA_CONST segment |
| 667 | const seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; |
| 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| { |
| 720 | | const new_index = @intCast(u16, data_seg.sections.items.len); |
| 721 | | self.bss_section_index = new_index; |
| 722 | | data_seg.sections.appendAssumeCapacity(data_sections[index]); |
| 723 | | try data_index_mapping.putNoClobber(index, new_index); |
| 686 | |
| 687 | { |
| 688 | // __DATA segment |
| 689 | const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 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 | } |
| 725 | 713 | |
| 726 | 714 | var it = self.mappings.iterator(); |
| ... | ... | @@ -729,6 +717,9 @@ fn sortSections(self: *Zld) !void { |
| 729 | 717 | if (self.text_segment_cmd_index.? == mapping.target_seg_id) { |
| 730 | 718 | const new_index = text_index_mapping.get(mapping.target_sect_id) orelse unreachable; |
| 731 | 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 | 723 | } else if (self.data_segment_cmd_index.? == mapping.target_seg_id) { |
| 733 | 724 | const new_index = data_index_mapping.get(mapping.target_sect_id) orelse unreachable; |
| 734 | 725 | mapping.target_sect_id = new_index; |
| ... | ... | @@ -874,10 +865,9 @@ fn allocateTextSegment(self: *Zld) !void { |
| 874 | 865 | } |
| 875 | 866 | } |
| 876 | 867 | |
| 877 | | fn allocateDataSegment(self: *Zld) !void { |
| 878 | | const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 868 | fn allocateDataConstSegment(self: *Zld) !void { |
| 869 | const seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; |
| 879 | 870 | const nonlazy = @intCast(u32, self.nonlazy_imports.items().len); |
| 880 | | const lazy = @intCast(u32, self.lazy_imports.items().len); |
| 881 | 871 | |
| 882 | 872 | const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 883 | 873 | seg.inner.fileoff = text_seg.inner.fileoff + text_seg.inner.filesize; |
| ... | ... | @@ -887,6 +877,17 @@ fn allocateDataSegment(self: *Zld) !void { |
| 887 | 877 | const got = &seg.sections.items[self.got_section_index.?]; |
| 888 | 878 | got.size += nonlazy * @sizeOf(u64); |
| 889 | 879 | |
| 880 | try self.allocateSegment(self.data_const_segment_cmd_index.?, 0); |
| 881 | } |
| 882 | |
| 883 | fn 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 | 891 | // Set la_symbol_ptr and data size |
| 891 | 892 | const la_symbol_ptr = &seg.sections.items[self.la_symbol_ptr_section_index.?]; |
| 892 | 893 | const data = &seg.sections.items[self.data_section_index.?]; |
| ... | ... | @@ -926,10 +927,11 @@ fn allocateSegment(self: *Zld, index: u16, offset: u64) !void { |
| 926 | 927 | fn writeStubHelperCommon(self: *Zld) !void { |
| 927 | 928 | const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 928 | 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 | 932 | const data_segment = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 930 | 933 | const data = &data_segment.sections.items[self.data_section_index.?]; |
| 931 | 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.?]; |
| 933 | 935 | |
| 934 | 936 | self.stub_helper_stubs_start_off = blk: { |
| 935 | 937 | switch (self.arch.?) { |
| ... | ... | @@ -1247,15 +1249,16 @@ fn resolveSymbols(self: *Zld) !void { |
| 1247 | 1249 | |
| 1248 | 1250 | log.debug("resolving '{s}':{} as {s} symbol at 0x{x}", .{ sym_name, sym, tt, n_value }); |
| 1249 | 1251 | |
| 1250 | | // TODO this assumes only two symbol-filled segments. Also, there might be a more |
| 1251 | | // generic way of doing this. |
| 1252 | | const n_sect = blk: { |
| 1253 | | if (self.text_segment_cmd_index.? == target_mapping.target_seg_id) { |
| 1254 | | break :blk target_mapping.target_sect_id + 1; |
| 1252 | // TODO there might be a more generic way of doing this. |
| 1253 | var n_sect: u16 = 0; |
| 1254 | for (self.load_commands.items) |cmd, cmd_id| { |
| 1255 | if (cmd != .Segment) break; |
| 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; |
| 1257 | | break :blk @intCast(u16, prev_seg.sections.items.len + target_mapping.target_sect_id + 1); |
| 1258 | | }; |
| 1260 | n_sect += @intCast(u16, cmd.Segment.sections.items.len); |
| 1261 | } |
| 1259 | 1262 | |
| 1260 | 1263 | const n_strx = try self.makeString(sym_name); |
| 1261 | 1264 | try locs.entry.value.append(self.allocator, .{ |
| ... | ... | @@ -1460,23 +1463,24 @@ fn doRelocs(self: *Zld) !void { |
| 1460 | 1463 | mem.writeIntLittle(u64, inst, @bitCast(u64, result)); |
| 1461 | 1464 | sub = null; |
| 1462 | 1465 | |
| 1463 | | // TODO should handle this better. |
| 1464 | 1466 | outer: { |
| 1465 | 1467 | var hit: bool = false; |
| 1466 | | if (self.data_section_index) |index| inner: { |
| 1467 | | if (index != target_mapping.target_sect_id) break :inner; |
| 1468 | | hit = true; |
| 1468 | if (target_mapping.target_seg_id == self.data_segment_cmd_index.?) { |
| 1469 | if (self.data_section_index) |index| { |
| 1470 | if (index == target_mapping.target_sect_id) hit = true; |
| 1471 | } |
| 1469 | 1472 | } |
| 1470 | | if (self.data_const_section_index) |index| inner: { |
| 1471 | | if (index != target_mapping.target_sect_id) break :inner; |
| 1472 | | hit = true; |
| 1473 | if (target_mapping.target_seg_id == self.data_const_segment_cmd_index.?) { |
| 1474 | if (self.data_const_section_index) |index| { |
| 1475 | if (index == target_mapping.target_sect_id) hit = true; |
| 1476 | } |
| 1473 | 1477 | } |
| 1478 | |
| 1474 | 1479 | if (!hit) break :outer; |
| 1475 | | const this_seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 1476 | | const this_offset = target_sect_addr + off - this_seg.inner.vmaddr; |
| 1480 | |
| 1477 | 1481 | try self.local_rebases.append(self.allocator, .{ |
| 1478 | | .offset = this_offset, |
| 1479 | | .segment_id = @intCast(u16, self.data_segment_cmd_index.?), |
| 1482 | .offset = this_addr - target_seg.inner.vmaddr, |
| 1483 | .segment_id = target_mapping.target_seg_id, |
| 1480 | 1484 | }); |
| 1481 | 1485 | } |
| 1482 | 1486 | }, |
| ... | ... | @@ -1642,23 +1646,24 @@ fn doRelocs(self: *Zld) !void { |
| 1642 | 1646 | mem.writeIntLittle(u64, inst, @bitCast(u64, result)); |
| 1643 | 1647 | sub = null; |
| 1644 | 1648 | |
| 1645 | | // TODO should handle this better. |
| 1646 | 1649 | outer: { |
| 1647 | 1650 | var hit: bool = false; |
| 1648 | | if (self.data_section_index) |index| inner: { |
| 1649 | | if (index != target_mapping.target_sect_id) break :inner; |
| 1650 | | hit = true; |
| 1651 | if (target_mapping.target_seg_id == self.data_segment_cmd_index.?) { |
| 1652 | if (self.data_section_index) |index| { |
| 1653 | if (index == target_mapping.target_sect_id) hit = true; |
| 1654 | } |
| 1651 | 1655 | } |
| 1652 | | if (self.data_const_section_index) |index| inner: { |
| 1653 | | if (index != target_mapping.target_sect_id) break :inner; |
| 1654 | | hit = true; |
| 1656 | if (target_mapping.target_seg_id == self.data_const_segment_cmd_index.?) { |
| 1657 | if (self.data_const_section_index) |index| { |
| 1658 | if (index == target_mapping.target_sect_id) hit = true; |
| 1659 | } |
| 1655 | 1660 | } |
| 1661 | |
| 1656 | 1662 | if (!hit) break :outer; |
| 1657 | | const this_seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 1658 | | const this_offset = target_sect_addr + off - this_seg.inner.vmaddr; |
| 1663 | |
| 1659 | 1664 | try self.local_rebases.append(self.allocator, .{ |
| 1660 | | .offset = this_offset, |
| 1661 | | .segment_id = @intCast(u16, self.data_segment_cmd_index.?), |
| 1665 | .offset = this_addr - target_seg.inner.vmaddr, |
| 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 | 1768 | const stubs = segment.sections.items[self.stubs_section_index.?]; |
| 1764 | 1769 | break :blk stubs.addr + ext.index * stubs.reserved2; |
| 1765 | 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 | 1772 | const got = segment.sections.items[self.got_section_index.?]; |
| 1768 | 1773 | break :blk got.addr + ext.index * @sizeOf(u64); |
| 1769 | 1774 | } else if (self.threadlocal_imports.get(sym_name)) |ext| { |
| ... | ... | @@ -1916,13 +1921,13 @@ fn populateMetadata(self: *Zld) !void { |
| 1916 | 1921 | }); |
| 1917 | 1922 | } |
| 1918 | 1923 | |
| 1919 | | if (self.data_segment_cmd_index == null) { |
| 1920 | | self.data_segment_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 1924 | if (self.data_const_segment_cmd_index == null) { |
| 1925 | self.data_const_segment_cmd_index = @intCast(u16, self.load_commands.items.len); |
| 1921 | 1926 | try self.load_commands.append(self.allocator, .{ |
| 1922 | 1927 | .Segment = SegmentCommand.empty(.{ |
| 1923 | 1928 | .cmd = macho.LC_SEGMENT_64, |
| 1924 | 1929 | .cmdsize = @sizeOf(macho.segment_command_64), |
| 1925 | | .segname = makeStaticString("__DATA"), |
| 1930 | .segname = makeStaticString("__DATA_CONST"), |
| 1926 | 1931 | .vmaddr = 0, |
| 1927 | 1932 | .vmsize = 0, |
| 1928 | 1933 | .fileoff = 0, |
| ... | ... | @@ -1936,11 +1941,11 @@ fn populateMetadata(self: *Zld) !void { |
| 1936 | 1941 | } |
| 1937 | 1942 | |
| 1938 | 1943 | if (self.got_section_index == null) { |
| 1939 | | const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 1940 | | self.got_section_index = @intCast(u16, data_seg.sections.items.len); |
| 1941 | | try data_seg.addSection(self.allocator, .{ |
| 1944 | const data_const_seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; |
| 1945 | self.got_section_index = @intCast(u16, data_const_seg.sections.items.len); |
| 1946 | try data_const_seg.addSection(self.allocator, .{ |
| 1942 | 1947 | .sectname = makeStaticString("__got"), |
| 1943 | | .segname = makeStaticString("__DATA"), |
| 1948 | .segname = makeStaticString("__DATA_CONST"), |
| 1944 | 1949 | .addr = 0, |
| 1945 | 1950 | .size = 0, |
| 1946 | 1951 | .offset = 0, |
| ... | ... | @@ -1954,6 +1959,25 @@ fn populateMetadata(self: *Zld) !void { |
| 1954 | 1959 | }); |
| 1955 | 1960 | } |
| 1956 | 1961 | |
| 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 | 1981 | if (self.la_symbol_ptr_section_index == null) { |
| 1958 | 1982 | const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 1959 | 1983 | self.la_symbol_ptr_section_index = @intCast(u16, data_seg.sections.items.len); |
| ... | ... | @@ -2269,15 +2293,17 @@ fn setEntryPoint(self: *Zld) !void { |
| 2269 | 2293 | } |
| 2270 | 2294 | |
| 2271 | 2295 | fn writeRebaseInfoTable(self: *Zld) !void { |
| 2272 | | const data_seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 2273 | | |
| 2274 | 2296 | var pointers = std.ArrayList(Pointer).init(self.allocator); |
| 2275 | 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); |
| 2277 | 2301 | |
| 2278 | 2302 | if (self.la_symbol_ptr_section_index) |idx| { |
| 2279 | | const sect = data_seg.sections.items[idx]; |
| 2280 | | const base_offset = sect.addr - data_seg.inner.vmaddr; |
| 2303 | try pointers.ensureCapacity(pointers.items.len + self.lazy_imports.items().len); |
| 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 | 2307 | const segment_id = @intCast(u16, self.data_segment_cmd_index.?); |
| 2282 | 2308 | for (self.lazy_imports.items()) |entry| { |
| 2283 | 2309 | pointers.appendAssumeCapacity(.{ |
| ... | ... | @@ -2287,9 +2313,6 @@ fn writeRebaseInfoTable(self: *Zld) !void { |
| 2287 | 2313 | } |
| 2288 | 2314 | } |
| 2289 | 2315 | |
| 2290 | | try pointers.ensureCapacity(pointers.items.len + self.local_rebases.items.len); |
| 2291 | | pointers.appendSliceAssumeCapacity(self.local_rebases.items); |
| 2292 | | |
| 2293 | 2316 | std.sort.sort(Pointer, pointers.items, {}, pointerCmp); |
| 2294 | 2317 | |
| 2295 | 2318 | const size = try rebaseInfoSize(pointers.items); |
| ... | ... | @@ -2319,16 +2342,15 @@ fn pointerCmp(context: void, a: Pointer, b: Pointer) bool { |
| 2319 | 2342 | } |
| 2320 | 2343 | |
| 2321 | 2344 | fn writeBindInfoTable(self: *Zld) !void { |
| 2322 | | const data_seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 2323 | | |
| 2324 | 2345 | var pointers = std.ArrayList(Pointer).init(self.allocator); |
| 2325 | 2346 | defer pointers.deinit(); |
| 2326 | 2347 | try pointers.ensureCapacity(self.nonlazy_imports.items().len + self.threadlocal_imports.items().len); |
| 2327 | 2348 | |
| 2328 | 2349 | if (self.got_section_index) |idx| { |
| 2329 | | const sect = data_seg.sections.items[idx]; |
| 2330 | | const base_offset = sect.addr - data_seg.inner.vmaddr; |
| 2331 | | const segment_id = @intCast(u16, self.data_segment_cmd_index.?); |
| 2350 | const seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; |
| 2351 | const sect = seg.sections.items[idx]; |
| 2352 | const base_offset = sect.addr - seg.inner.vmaddr; |
| 2353 | const segment_id = @intCast(u16, self.data_const_segment_cmd_index.?); |
| 2332 | 2354 | for (self.nonlazy_imports.items()) |entry| { |
| 2333 | 2355 | pointers.appendAssumeCapacity(.{ |
| 2334 | 2356 | .offset = base_offset + entry.value.index * @sizeOf(u64), |
| ... | ... | @@ -2340,8 +2362,9 @@ fn writeBindInfoTable(self: *Zld) !void { |
| 2340 | 2362 | } |
| 2341 | 2363 | |
| 2342 | 2364 | if (self.tlv_section_index) |idx| { |
| 2343 | | const sect = data_seg.sections.items[idx]; |
| 2344 | | const base_offset = sect.addr - data_seg.inner.vmaddr; |
| 2365 | const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 2366 | const sect = seg.sections.items[idx]; |
| 2367 | const base_offset = sect.addr - seg.inner.vmaddr; |
| 2345 | 2368 | const segment_id = @intCast(u16, self.data_segment_cmd_index.?); |
| 2346 | 2369 | for (self.threadlocal_imports.items()) |entry| { |
| 2347 | 2370 | pointers.appendAssumeCapacity(.{ |
| ... | ... | @@ -2372,15 +2395,14 @@ fn writeBindInfoTable(self: *Zld) !void { |
| 2372 | 2395 | } |
| 2373 | 2396 | |
| 2374 | 2397 | fn writeLazyBindInfoTable(self: *Zld) !void { |
| 2375 | | const data_seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 2376 | | |
| 2377 | 2398 | var pointers = std.ArrayList(Pointer).init(self.allocator); |
| 2378 | 2399 | defer pointers.deinit(); |
| 2379 | 2400 | try pointers.ensureCapacity(self.lazy_imports.items().len); |
| 2380 | 2401 | |
| 2381 | 2402 | if (self.la_symbol_ptr_section_index) |idx| { |
| 2382 | | const sect = data_seg.sections.items[idx]; |
| 2383 | | const base_offset = sect.addr - data_seg.inner.vmaddr; |
| 2403 | const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| 2404 | const sect = seg.sections.items[idx]; |
| 2405 | const base_offset = sect.addr - seg.inner.vmaddr; |
| 2384 | 2406 | const segment_id = @intCast(u16, self.data_segment_cmd_index.?); |
| 2385 | 2407 | for (self.lazy_imports.items()) |entry| { |
| 2386 | 2408 | pointers.appendAssumeCapacity(.{ |
| ... | ... | @@ -2725,8 +2747,9 @@ fn writeDynamicSymbolTable(self: *Zld) !void { |
| 2725 | 2747 | const seg = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment; |
| 2726 | 2748 | const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| 2727 | 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 | 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 | 2753 | const la_symbol_ptr = &data_segment.sections.items[self.la_symbol_ptr_section_index.?]; |
| 2731 | 2754 | const dysymtab = &self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab; |
| 2732 | 2755 | |