authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-06-15 00:15:18+02:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2021-06-15 00:15:18+02:00
logd2427e6490587c4d9cfb1b2dfb735c20967121db
tree5b444f3bd51c241cb627f4cb864f0df960658fac
parent408d8df86c55decd79020d472855624d98e32b03
parent7001bde84ce687885442a4d5a4f8715f7d573dba
signaturebadge-question-mark Signed by PGP key 4AEE18F83AFDEB23

Merge pull request #9118 from ziglang/zld-eh-frame

zld: handle __gcc_except_tab and __eh_frame, and streamline section mapping

5 files changed, 384 insertions(+), 130 deletions(-)

src/link/MachO/Object.zig+37
......@@ -70,6 +70,43 @@ pub const Section = struct {
7070 allocator.free(relocs);
7171 }
7272 }
73
74 pub fn segname(self: Section) []const u8 {
75 return parseName(&self.inner.segname);
76 }
77
78 pub fn sectname(self: Section) []const u8 {
79 return parseName(&self.inner.sectname);
80 }
81
82 pub fn flags(self: Section) u32 {
83 return self.inner.flags;
84 }
85
86 pub fn sectionType(self: Section) u8 {
87 return @truncate(u8, self.flags() & 0xff);
88 }
89
90 pub fn sectionAttrs(self: Section) u32 {
91 return self.flags() & 0xffffff00;
92 }
93
94 pub fn isCode(self: Section) bool {
95 const attr = self.sectionAttrs();
96 return attr & macho.S_ATTR_PURE_INSTRUCTIONS != 0 and attr & macho.S_ATTR_SOME_INSTRUCTIONS != 0;
97 }
98
99 pub fn isDebug(self: Section) bool {
100 return self.sectionAttrs() & macho.S_ATTR_DEBUG != 0;
101 }
102
103 pub fn dontDeadStrip(self: Section) bool {
104 return self.sectionAttrs() & macho.S_ATTR_NO_DEAD_STRIP != 0;
105 }
106
107 pub fn dontDeadStripIfReferencesLive(self: Section) bool {
108 return self.sectionAttrs() & macho.S_ATTR_LIVE_SUPPORT != 0;
109 }
73110};
74111
75112const DebugInfo = struct {
src/link/MachO/Zld.zig+298-126
......@@ -65,6 +65,9 @@ stub_helper_section_index: ?u16 = null,
6565text_const_section_index: ?u16 = null,
6666cstring_section_index: ?u16 = null,
6767ustring_section_index: ?u16 = null,
68gcc_except_tab_section_index: ?u16 = null,
69unwind_info_section_index: ?u16 = null,
70eh_frame_section_index: ?u16 = null,
6871
6972// __DATA_CONST segment sections
7073got_section_index: ?u16 = null,
......@@ -435,19 +438,17 @@ fn updateMetadata(self: *Zld) !void {
435438 const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
436439
437440 // Create missing metadata
438 for (object_seg.sections.items) |source_sect, sect_id| {
439 if (sect_id == object.text_section_index.?) continue;
440 const segname = parseName(&source_sect.segname);
441 const sectname = parseName(&source_sect.sectname);
442 const flags = source_sect.flags;
441 for (object.sections.items) |sect, sect_id| {
442 const segname = sect.segname();
443 const sectname = sect.sectname();
443444
444 switch (flags) {
445 macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS => {
446 if (self.text_section_index != null) continue;
445 switch (sect.sectionType()) {
446 macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS, macho.S_LITERAL_POINTERS => {
447 if (self.text_const_section_index != null) continue;
447448
448 self.text_section_index = @intCast(u16, text_seg.sections.items.len);
449 self.text_const_section_index = @intCast(u16, text_seg.sections.items.len);
449450 try text_seg.addSection(self.allocator, .{
450 .sectname = makeStaticString("__text"),
451 .sectname = makeStaticString("__const"),
451452 .segname = makeStaticString("__TEXT"),
452453 .addr = 0,
453454 .size = 0,
......@@ -455,70 +456,12 @@ fn updateMetadata(self: *Zld) !void {
455456 .@"align" = 0,
456457 .reloff = 0,
457458 .nreloc = 0,
458 .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
459 .flags = macho.S_REGULAR,
459460 .reserved1 = 0,
460461 .reserved2 = 0,
461462 .reserved3 = 0,
462463 });
463 },
464 macho.S_REGULAR, macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => {
465 if (mem.eql(u8, segname, "__TEXT")) {
466 if (mem.eql(u8, sectname, "__ustring")) {
467 if (self.ustring_section_index != null) continue;
468
469 self.ustring_section_index = @intCast(u16, text_seg.sections.items.len);
470 try text_seg.addSection(self.allocator, .{
471 .sectname = makeStaticString("__ustring"),
472 .segname = makeStaticString("__TEXT"),
473 .addr = 0,
474 .size = 0,
475 .offset = 0,
476 .@"align" = 0,
477 .reloff = 0,
478 .nreloc = 0,
479 .flags = macho.S_REGULAR,
480 .reserved1 = 0,
481 .reserved2 = 0,
482 .reserved3 = 0,
483 });
484 } else {
485 if (self.text_const_section_index != null) continue;
486
487 self.text_const_section_index = @intCast(u16, text_seg.sections.items.len);
488 try text_seg.addSection(self.allocator, .{
489 .sectname = makeStaticString("__const"),
490 .segname = makeStaticString("__TEXT"),
491 .addr = 0,
492 .size = 0,
493 .offset = 0,
494 .@"align" = 0,
495 .reloff = 0,
496 .nreloc = 0,
497 .flags = macho.S_REGULAR,
498 .reserved1 = 0,
499 .reserved2 = 0,
500 .reserved3 = 0,
501 });
502 }
503 } else if (mem.eql(u8, segname, "__DATA") or mem.eql(u8, segname, "__DATA_CONST")) {
504 if (self.data_const_section_index != null) continue;
505
506 self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);
507 try data_const_seg.addSection(self.allocator, .{
508 .sectname = makeStaticString("__const"),
509 .segname = makeStaticString("__DATA_CONST"),
510 .addr = 0,
511 .size = 0,
512 .offset = 0,
513 .@"align" = 0,
514 .reloff = 0,
515 .nreloc = 0,
516 .flags = macho.S_REGULAR,
517 .reserved1 = 0,
518 .reserved2 = 0,
519 .reserved3 = 0,
520 });
521 }
464 continue;
522465 },
523466 macho.S_CSTRING_LITERALS => {
524467 if (self.cstring_section_index != null) continue;
......@@ -538,6 +481,7 @@ fn updateMetadata(self: *Zld) !void {
538481 .reserved2 = 0,
539482 .reserved3 = 0,
540483 });
484 continue;
541485 },
542486 macho.S_MOD_INIT_FUNC_POINTERS => {
543487 if (self.mod_init_func_section_index != null) continue;
......@@ -557,6 +501,7 @@ fn updateMetadata(self: *Zld) !void {
557501 .reserved2 = 0,
558502 .reserved3 = 0,
559503 });
504 continue;
560505 },
561506 macho.S_MOD_TERM_FUNC_POINTERS => {
562507 if (self.mod_term_func_section_index != null) continue;
......@@ -576,6 +521,7 @@ fn updateMetadata(self: *Zld) !void {
576521 .reserved2 = 0,
577522 .reserved3 = 0,
578523 });
524 continue;
579525 },
580526 macho.S_ZEROFILL => {
581527 if (mem.eql(u8, sectname, "__common")) {
......@@ -615,6 +561,7 @@ fn updateMetadata(self: *Zld) !void {
615561 .reserved3 = 0,
616562 });
617563 }
564 continue;
618565 },
619566 macho.S_THREAD_LOCAL_VARIABLES => {
620567 if (self.tlv_section_index != null) continue;
......@@ -634,6 +581,7 @@ fn updateMetadata(self: *Zld) !void {
634581 .reserved2 = 0,
635582 .reserved3 = 0,
636583 });
584 continue;
637585 },
638586 macho.S_THREAD_LOCAL_REGULAR => {
639587 if (self.tlv_data_section_index != null) continue;
......@@ -653,6 +601,7 @@ fn updateMetadata(self: *Zld) !void {
653601 .reserved2 = 0,
654602 .reserved3 = 0,
655603 });
604 continue;
656605 },
657606 macho.S_THREAD_LOCAL_ZEROFILL => {
658607 if (self.tlv_bss_section_index != null) continue;
......@@ -672,58 +621,240 @@ fn updateMetadata(self: *Zld) !void {
672621 .reserved2 = 0,
673622 .reserved3 = 0,
674623 });
675 },
676 macho.S_COALESCED |
677 macho.S_ATTR_NO_TOC |
678 macho.S_ATTR_STRIP_STATIC_SYMS |
679 macho.S_ATTR_LIVE_SUPPORT => {
680 log.debug("TODO __eh_frame section: type 0x{x}, name '{s},{s}'", .{
681 flags, segname, sectname,
682 });
683624 continue;
684625 },
685 macho.S_REGULAR | macho.S_ATTR_DEBUG => {
686 if (mem.eql(u8, "__LD", segname) and mem.eql(u8, "__compact_unwind", sectname)) {
687 log.debug("TODO compact unwind section: type 0x{x}, name '{s},{s}'", .{
688 flags, segname, sectname,
626 macho.S_COALESCED => {
627 if (mem.eql(u8, "__TEXT", segname) and mem.eql(u8, "__eh_frame", sectname)) {
628 // TODO I believe __eh_frame is currently part of __unwind_info section
629 // in the latest ld64 output.
630 if (self.eh_frame_section_index != null) continue;
631
632 self.eh_frame_section_index = @intCast(u16, text_seg.sections.items.len);
633 try text_seg.addSection(self.allocator, .{
634 .sectname = makeStaticString("__eh_frame"),
635 .segname = makeStaticString("__TEXT"),
636 .addr = 0,
637 .size = 0,
638 .offset = 0,
639 .@"align" = 0,
640 .reloff = 0,
641 .nreloc = 0,
642 .flags = macho.S_REGULAR,
643 .reserved1 = 0,
644 .reserved2 = 0,
645 .reserved3 = 0,
689646 });
647 continue;
690648 }
649
650 // TODO audit this: is this the right mapping?
651 if (self.data_const_section_index != null) continue;
652
653 self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);
654 try data_const_seg.addSection(self.allocator, .{
655 .sectname = makeStaticString("__const"),
656 .segname = makeStaticString("__DATA_CONST"),
657 .addr = 0,
658 .size = 0,
659 .offset = 0,
660 .@"align" = 0,
661 .reloff = 0,
662 .nreloc = 0,
663 .flags = macho.S_REGULAR,
664 .reserved1 = 0,
665 .reserved2 = 0,
666 .reserved3 = 0,
667 });
691668 continue;
692669 },
693 else => {
670 macho.S_REGULAR => {
671 if (sect.isCode()) {
672 if (self.text_section_index != null) continue;
673
674 self.text_section_index = @intCast(u16, text_seg.sections.items.len);
675 try text_seg.addSection(self.allocator, .{
676 .sectname = makeStaticString("__text"),
677 .segname = makeStaticString("__TEXT"),
678 .addr = 0,
679 .size = 0,
680 .offset = 0,
681 .@"align" = 0,
682 .reloff = 0,
683 .nreloc = 0,
684 .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
685 .reserved1 = 0,
686 .reserved2 = 0,
687 .reserved3 = 0,
688 });
689 continue;
690 }
691
692 if (sect.isDebug()) {
693 if (mem.eql(u8, "__LD", segname) and mem.eql(u8, "__compact_unwind", sectname)) {
694 log.debug("TODO compact unwind section: type 0x{x}, name '{s},{s}'", .{
695 sect.flags(), segname, sectname,
696 });
697 }
698 continue;
699 }
700
701 if (mem.eql(u8, segname, "__TEXT")) {
702 if (mem.eql(u8, sectname, "__ustring")) {
703 if (self.ustring_section_index != null) continue;
704
705 self.ustring_section_index = @intCast(u16, text_seg.sections.items.len);
706 try text_seg.addSection(self.allocator, .{
707 .sectname = makeStaticString("__ustring"),
708 .segname = makeStaticString("__TEXT"),
709 .addr = 0,
710 .size = 0,
711 .offset = 0,
712 .@"align" = 0,
713 .reloff = 0,
714 .nreloc = 0,
715 .flags = macho.S_REGULAR,
716 .reserved1 = 0,
717 .reserved2 = 0,
718 .reserved3 = 0,
719 });
720 } else if (mem.eql(u8, sectname, "__gcc_except_tab")) {
721 if (self.gcc_except_tab_section_index != null) continue;
722
723 self.gcc_except_tab_section_index = @intCast(u16, text_seg.sections.items.len);
724 try text_seg.addSection(self.allocator, .{
725 .sectname = makeStaticString("__gcc_except_tab"),
726 .segname = makeStaticString("__TEXT"),
727 .addr = 0,
728 .size = 0,
729 .offset = 0,
730 .@"align" = 0,
731 .reloff = 0,
732 .nreloc = 0,
733 .flags = macho.S_REGULAR,
734 .reserved1 = 0,
735 .reserved2 = 0,
736 .reserved3 = 0,
737 });
738 } else {
739 if (self.text_const_section_index != null) continue;
740
741 self.text_const_section_index = @intCast(u16, text_seg.sections.items.len);
742 try text_seg.addSection(self.allocator, .{
743 .sectname = makeStaticString("__const"),
744 .segname = makeStaticString("__TEXT"),
745 .addr = 0,
746 .size = 0,
747 .offset = 0,
748 .@"align" = 0,
749 .reloff = 0,
750 .nreloc = 0,
751 .flags = macho.S_REGULAR,
752 .reserved1 = 0,
753 .reserved2 = 0,
754 .reserved3 = 0,
755 });
756 }
757 continue;
758 }
759
760 if (mem.eql(u8, segname, "__DATA_CONST")) {
761 if (self.data_const_section_index != null) continue;
762
763 self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);
764 try data_const_seg.addSection(self.allocator, .{
765 .sectname = makeStaticString("__const"),
766 .segname = makeStaticString("__DATA_CONST"),
767 .addr = 0,
768 .size = 0,
769 .offset = 0,
770 .@"align" = 0,
771 .reloff = 0,
772 .nreloc = 0,
773 .flags = macho.S_REGULAR,
774 .reserved1 = 0,
775 .reserved2 = 0,
776 .reserved3 = 0,
777 });
778 continue;
779 }
780
781 if (mem.eql(u8, segname, "__DATA")) {
782 if (mem.eql(u8, sectname, "__const")) {
783 if (self.data_const_section_index != null) continue;
784
785 self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);
786 try data_const_seg.addSection(self.allocator, .{
787 .sectname = makeStaticString("__const"),
788 .segname = makeStaticString("__DATA_CONST"),
789 .addr = 0,
790 .size = 0,
791 .offset = 0,
792 .@"align" = 0,
793 .reloff = 0,
794 .nreloc = 0,
795 .flags = macho.S_REGULAR,
796 .reserved1 = 0,
797 .reserved2 = 0,
798 .reserved3 = 0,
799 });
800 } else {
801 if (self.data_section_index != null) continue;
802
803 self.data_section_index = @intCast(u16, data_seg.sections.items.len);
804 try data_seg.addSection(self.allocator, .{
805 .sectname = makeStaticString("__data"),
806 .segname = makeStaticString("__DATA"),
807 .addr = 0,
808 .size = 0,
809 .offset = 0,
810 .@"align" = 0,
811 .reloff = 0,
812 .nreloc = 0,
813 .flags = macho.S_REGULAR,
814 .reserved1 = 0,
815 .reserved2 = 0,
816 .reserved3 = 0,
817 });
818 }
819
820 continue;
821 }
822
694823 if (mem.eql(u8, "__LLVM", segname) and mem.eql(u8, "__asm", sectname)) {
695 log.debug("TODO LLVM bitcode section: type 0x{x}, name '{s},{s}'", .{
696 flags, segname, sectname,
824 log.debug("TODO LLVM asm section: type 0x{x}, name '{s},{s}'", .{
825 sect.flags(), segname, sectname,
697826 });
698827 continue;
699828 }
700 log.err("unhandled section type 0x{x} for '{s},{s}'", .{ flags, segname, sectname });
701 return error.UnhandledSection;
702829 },
830 else => {},
703831 }
832
833 log.err("{s}: unhandled section type 0x{x} for '{s},{s}'", .{
834 object.name.?,
835 sect.flags(),
836 segname,
837 sectname,
838 });
839 return error.UnhandledSection;
704840 }
705841
706842 // Find ideal section alignment.
707 for (object_seg.sections.items) |source_sect| {
708 if (self.getMatchingSection(source_sect)) |res| {
843 for (object.sections.items) |sect| {
844 if (self.getMatchingSection(sect)) |res| {
709845 const target_seg = &self.load_commands.items[res.seg].Segment;
710846 const target_sect = &target_seg.sections.items[res.sect];
711 target_sect.@"align" = math.max(target_sect.@"align", source_sect.@"align");
847 target_sect.@"align" = math.max(target_sect.@"align", sect.inner.@"align");
712848 }
713849 }
714850
715851 // Update section mappings
716 for (object_seg.sections.items) |source_sect, sect_id| {
717 const source_sect_id = @intCast(u16, sect_id);
718 if (self.getMatchingSection(source_sect)) |res| {
719 try self.mapAndUpdateSections(object, source_sect_id, res.seg, res.sect);
852 for (object.sections.items) |sect, sect_id| {
853 if (self.getMatchingSection(sect)) |res| {
854 try self.mapAndUpdateSections(object, @intCast(u16, sect_id), res.seg, res.sect);
720855 continue;
721856 }
722
723 log.debug("section '{s},{s}' will be unmapped", .{
724 parseName(&source_sect.segname),
725 parseName(&source_sect.sectname),
726 });
857 log.debug("section '{s},{s}' will be unmapped", .{ sect.segname(), sect.sectname() });
727858 }
728859 }
729860
......@@ -819,13 +950,13 @@ const MatchingSection = struct {
819950 sect: u16,
820951};
821952
822fn getMatchingSection(self: *Zld, section: macho.section_64) ?MatchingSection {
823 const segname = parseName(&section.segname);
824 const sectname = parseName(&section.sectname);
953fn getMatchingSection(self: *Zld, sect: Object.Section) ?MatchingSection {
954 const segname = sect.segname();
955 const sectname = sect.sectname();
825956
826957 const res: ?MatchingSection = blk: {
827 switch (section.flags) {
828 macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => {
958 switch (sect.sectionType()) {
959 macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS, macho.S_LITERAL_POINTERS => {
829960 break :blk .{
830961 .seg = self.text_segment_cmd_index.?,
831962 .sect = self.text_const_section_index.?,
......@@ -855,11 +986,12 @@ fn getMatchingSection(self: *Zld, section: macho.section_64) ?MatchingSection {
855986 .seg = self.data_segment_cmd_index.?,
856987 .sect = self.common_section_index.?,
857988 };
989 } else {
990 break :blk .{
991 .seg = self.data_segment_cmd_index.?,
992 .sect = self.bss_section_index.?,
993 };
858994 }
859 break :blk .{
860 .seg = self.data_segment_cmd_index.?,
861 .sect = self.bss_section_index.?,
862 };
863995 },
864996 macho.S_THREAD_LOCAL_VARIABLES => {
865997 break :blk .{
......@@ -879,31 +1011,57 @@ fn getMatchingSection(self: *Zld, section: macho.section_64) ?MatchingSection {
8791011 .sect = self.tlv_bss_section_index.?,
8801012 };
8811013 },
882 macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS => {
1014 macho.S_COALESCED => {
1015 if (mem.eql(u8, "__TEXT", segname) and mem.eql(u8, "__eh_frame", sectname)) {
1016 break :blk .{
1017 .seg = self.text_segment_cmd_index.?,
1018 .sect = self.eh_frame_section_index.?,
1019 };
1020 }
1021
8831022 break :blk .{
884 .seg = self.text_segment_cmd_index.?,
885 .sect = self.text_section_index.?,
1023 .seg = self.data_const_segment_cmd_index.?,
1024 .sect = self.data_const_section_index.?,
8861025 };
8871026 },
8881027 macho.S_REGULAR => {
1028 if (sect.isCode()) {
1029 break :blk .{
1030 .seg = self.text_segment_cmd_index.?,
1031 .sect = self.text_section_index.?,
1032 };
1033 }
1034 if (sect.isDebug()) {
1035 // TODO debug attributes
1036 break :blk null;
1037 }
1038
8891039 if (mem.eql(u8, segname, "__TEXT")) {
8901040 if (mem.eql(u8, sectname, "__ustring")) {
8911041 break :blk .{
8921042 .seg = self.text_segment_cmd_index.?,
8931043 .sect = self.ustring_section_index.?,
8941044 };
1045 } else if (mem.eql(u8, sectname, "__gcc_except_tab")) {
1046 break :blk .{
1047 .seg = self.text_segment_cmd_index.?,
1048 .sect = self.gcc_except_tab_section_index.?,
1049 };
1050 } else {
1051 break :blk .{
1052 .seg = self.text_segment_cmd_index.?,
1053 .sect = self.text_const_section_index.?,
1054 };
8951055 }
896 break :blk .{
897 .seg = self.text_segment_cmd_index.?,
898 .sect = self.text_const_section_index.?,
899 };
9001056 }
1057
9011058 if (mem.eql(u8, segname, "__DATA_CONST")) {
9021059 break :blk .{
9031060 .seg = self.data_const_segment_cmd_index.?,
9041061 .sect = self.data_const_section_index.?,
9051062 };
9061063 }
1064
9071065 if (mem.eql(u8, segname, "__DATA")) {
9081066 if (mem.eql(u8, sectname, "__const")) {
9091067 break :blk .{
......@@ -916,11 +1074,10 @@ fn getMatchingSection(self: *Zld, section: macho.section_64) ?MatchingSection {
9161074 .sect = self.data_section_index.?,
9171075 };
9181076 }
1077
9191078 break :blk null;
9201079 },
921 else => {
922 break :blk null;
923 },
1080 else => break :blk null,
9241081 }
9251082 };
9261083
......@@ -946,9 +1103,11 @@ fn sortSections(self: *Zld) !void {
9461103 &self.text_section_index,
9471104 &self.stubs_section_index,
9481105 &self.stub_helper_section_index,
949 &self.text_const_section_index,
1106 &self.gcc_except_tab_section_index,
9501107 &self.cstring_section_index,
9511108 &self.ustring_section_index,
1109 &self.text_const_section_index,
1110 &self.eh_frame_section_index,
9521111 };
9531112 for (indices) |maybe_index| {
9541113 const new_index: u16 = if (maybe_index.*) |index| blk: {
......@@ -1733,7 +1892,7 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {
17331892 for (relocs) |rel| {
17341893 switch (rel.@"type") {
17351894 .unsigned => continue,
1736 .got_page, .got_page_off, .got_load, .got => {
1895 .got_page, .got_page_off, .got_load, .got, .pointer_to_got => {
17371896 const sym = rel.target.symbol.getTopmostAlias();
17381897 if (sym.got_index != null) continue;
17391898
......@@ -1751,9 +1910,6 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {
17511910
17521911 if (sym.stubs_index != null) continue;
17531912 if (sym.@"type" != .proxy) continue;
1754 // if (sym.cast(Symbol.Regular)) |reg| {
1755 // if (!reg.weak_ref) continue;
1756 // }
17571913
17581914 const index = @intCast(u32, self.stubs.items.len);
17591915 sym.stubs_index = index;
......@@ -1864,11 +2020,19 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
18642020 });
18652021 }
18662022 },
1867 .got_page, .got_page_off, .got_load, .got => {
2023 .got_page, .got_page_off, .got_load, .got, .pointer_to_got => {
18682024 const dc_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
18692025 const got = dc_seg.sections.items[self.got_section_index.?];
18702026 const final = rel.target.symbol.getTopmostAlias();
1871 args.target_addr = got.addr + final.got_index.? * @sizeOf(u64);
2027 const got_index = final.got_index orelse {
2028 // TODO remove this when we can link against TAPI files.
2029 log.err("undefined reference to symbol '{s}'", .{final.name});
2030 log.err(" | referenced in {s}", .{
2031 rel.target.symbol.cast(Symbol.Unresolved).?.file.name.?,
2032 });
2033 return error.UndefinedSymbolReference;
2034 };
2035 args.target_addr = got.addr + got_index * @sizeOf(u64);
18722036 },
18732037 else => |tt| {
18742038 if (tt == .signed and rel.target == .section) {
......@@ -1934,7 +2098,15 @@ fn relocTargetAddr(self: *Zld, object: *const Object, target: reloc.Relocation.T
19342098 log.debug(" | symbol stub '{s}'", .{sym.name});
19352099 const segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
19362100 const stubs = segment.sections.items[self.stubs_section_index.?];
1937 break :blk stubs.addr + proxy.base.stubs_index.? * stubs.reserved2;
2101 const stubs_index = proxy.base.stubs_index orelse {
2102 // TODO remove this when we can link against TAPI files.
2103 log.err("undefined reference to symbol '{s}'", .{final.name});
2104 log.err(" | referenced in {s}", .{
2105 sym.cast(Symbol.Unresolved).?.file.name.?,
2106 });
2107 return error.UndefinedSymbolReference;
2108 };
2109 break :blk stubs.addr + stubs_index * stubs.reserved2;
19382110 } else {
19392111 log.err("failed to resolve symbol '{s}' as a relocation target", .{sym.name});
19402112 return error.FailedToResolveRelocationTarget;
src/link/MachO/reloc.zig+2
......@@ -52,6 +52,7 @@ pub const Relocation = struct {
5252 .page_off => @fieldParentPtr(aarch64.PageOff, "base", base).resolve(args),
5353 .got_page => @fieldParentPtr(aarch64.GotPage, "base", base).resolve(args),
5454 .got_page_off => @fieldParentPtr(aarch64.GotPageOff, "base", base).resolve(args),
55 .pointer_to_got => @fieldParentPtr(aarch64.PointerToGot, "base", base).resolve(args),
5556 .tlvp_page => @fieldParentPtr(aarch64.TlvpPage, "base", base).resolve(args),
5657 .tlvp_page_off => @fieldParentPtr(aarch64.TlvpPageOff, "base", base).resolve(args),
5758 .branch_x86_64 => @fieldParentPtr(x86_64.Branch, "base", base).resolve(args),
......@@ -70,6 +71,7 @@ pub const Relocation = struct {
7071 got_page,
7172 got_page_off,
7273 tlvp_page,
74 pointer_to_got,
7375 tlvp_page_off,
7476 branch_x86_64,
7577 signed,
src/link/MachO/reloc/aarch64.zig+40-3
......@@ -141,6 +141,20 @@ pub const GotPageOff = struct {
141141 }
142142};
143143
144pub const PointerToGot = struct {
145 base: Relocation,
146
147 pub const base_type: Relocation.Type = .pointer_to_got;
148
149 pub fn resolve(ptr_to_got: PointerToGot, args: Relocation.ResolveArgs) !void {
150 const result = try math.cast(i32, @intCast(i64, args.target_addr) - @intCast(i64, args.source_addr));
151
152 log.debug(" | calculated value 0x{x}", .{result});
153
154 mem.writeIntLittle(u32, ptr_to_got.base.code[0..4], @bitCast(u32, result));
155 }
156};
157
144158pub const TlvpPage = struct {
145159 base: Relocation,
146160 /// Always .PCRelativeAddress
......@@ -228,9 +242,7 @@ pub const Parser = struct {
228242 try parser.parseTlvpLoadPageOff(rel);
229243 },
230244 .ARM64_RELOC_POINTER_TO_GOT => {
231 // TODO Handle pointer to GOT. This reloc seems to appear in
232 // __LD,__compact_unwind section which we currently don't handle.
233 log.debug("Unhandled relocation ARM64_RELOC_POINTER_TO_GOT", .{});
245 try parser.parsePointerToGot(rel);
234246 },
235247 }
236248 }
......@@ -583,6 +595,31 @@ pub const Parser = struct {
583595 log.debug(" | emitting {}", .{unsigned});
584596 try parser.parsed.append(&unsigned.base);
585597 }
598
599 fn parsePointerToGot(parser: *Parser, rel: macho.relocation_info) !void {
600 const rel_type = @intToEnum(macho.reloc_type_arm64, rel.r_type);
601 assert(rel_type == .ARM64_RELOC_POINTER_TO_GOT);
602 assert(rel.r_pcrel == 1);
603 assert(rel.r_length == 2);
604
605 var ptr_to_got = try parser.allocator.create(PointerToGot);
606 errdefer parser.allocator.destroy(ptr_to_got);
607
608 const target = Relocation.Target.from_reloc(rel, parser.symbols);
609 const offset = @intCast(u32, rel.r_address);
610
611 ptr_to_got.* = .{
612 .base = .{
613 .@"type" = .pointer_to_got,
614 .code = parser.code[offset..][0..4],
615 .offset = offset,
616 .target = target,
617 },
618 };
619
620 log.debug(" | emitting {}", .{ptr_to_got});
621 try parser.parsed.append(&ptr_to_got.base);
622 }
586623};
587624
588625inline fn isArithmeticOp(inst: *const [4]u8) bool {
src/link/MachO/reloc/x86_64.zig+7-1
......@@ -66,11 +66,15 @@ pub const GotLoad = struct {
6666
6767pub const Got = struct {
6868 base: Relocation,
69 addend: i32,
6970
7071 pub const base_type: Relocation.Type = .got;
7172
7273 pub fn resolve(got: Got, args: Relocation.ResolveArgs) !void {
73 const displacement = try math.cast(i32, @intCast(i64, args.target_addr) - @intCast(i64, args.source_addr) - 4);
74 const displacement = try math.cast(
75 i32,
76 @intCast(i64, args.target_addr) - @intCast(i64, args.source_addr) - 4 + got.addend,
77 );
7478 log.debug(" | displacement 0x{x}", .{displacement});
7579 mem.writeIntLittle(u32, got.base.code[0..4], @bitCast(u32, displacement));
7680 }
......@@ -237,6 +241,7 @@ pub const Parser = struct {
237241 const offset = @intCast(u32, rel.r_address);
238242 const inst = parser.code[offset..][0..4];
239243 const target = Relocation.Target.from_reloc(rel, parser.symbols);
244 const addend = mem.readIntLittle(i32, inst);
240245
241246 var got = try parser.allocator.create(Got);
242247 errdefer parser.allocator.destroy(got);
......@@ -248,6 +253,7 @@ pub const Parser = struct {
248253 .offset = offset,
249254 .target = target,
250255 },
256 .addend = addend,
251257 };
252258
253259 log.debug(" | emitting {}", .{got});