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 {...@@ -70,6 +70,43 @@ pub const Section = struct {
70 allocator.free(relocs);70 allocator.free(relocs);
71 }71 }
72 }72 }
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 }
73};110};
74111
75const DebugInfo = struct {112const DebugInfo = struct {
src/link/MachO/Zld.zig+298-126
...@@ -65,6 +65,9 @@ stub_helper_section_index: ?u16 = null,...@@ -65,6 +65,9 @@ stub_helper_section_index: ?u16 = null,
65text_const_section_index: ?u16 = null,65text_const_section_index: ?u16 = null,
66cstring_section_index: ?u16 = null,66cstring_section_index: ?u16 = null,
67ustring_section_index: ?u16 = null,67ustring_section_index: ?u16 = null,
68gcc_except_tab_section_index: ?u16 = null,
69unwind_info_section_index: ?u16 = null,
70eh_frame_section_index: ?u16 = null,
6871
69// __DATA_CONST segment sections72// __DATA_CONST segment sections
70got_section_index: ?u16 = null,73got_section_index: ?u16 = null,
...@@ -435,19 +438,17 @@ fn updateMetadata(self: *Zld) !void {...@@ -435,19 +438,17 @@ fn updateMetadata(self: *Zld) !void {
435 const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;438 const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
436439
437 // Create missing metadata440 // Create missing metadata
438 for (object_seg.sections.items) |source_sect, sect_id| {441 for (object.sections.items) |sect, sect_id| {
439 if (sect_id == object.text_section_index.?) continue;442 const segname = sect.segname();
440 const segname = parseName(&source_sect.segname);443 const sectname = sect.sectname();
441 const sectname = parseName(&source_sect.sectname);
442 const flags = source_sect.flags;
443444
444 switch (flags) {445 switch (sect.sectionType()) {
445 macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS => {446 macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS, macho.S_LITERAL_POINTERS => {
446 if (self.text_section_index != null) continue;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);
449 try text_seg.addSection(self.allocator, .{450 try text_seg.addSection(self.allocator, .{
450 .sectname = makeStaticString("__text"),451 .sectname = makeStaticString("__const"),
451 .segname = makeStaticString("__TEXT"),452 .segname = makeStaticString("__TEXT"),
452 .addr = 0,453 .addr = 0,
453 .size = 0,454 .size = 0,
...@@ -455,70 +456,12 @@ fn updateMetadata(self: *Zld) !void {...@@ -455,70 +456,12 @@ fn updateMetadata(self: *Zld) !void {
455 .@"align" = 0,456 .@"align" = 0,
456 .reloff = 0,457 .reloff = 0,
457 .nreloc = 0,458 .nreloc = 0,
458 .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,459 .flags = macho.S_REGULAR,
459 .reserved1 = 0,460 .reserved1 = 0,
460 .reserved2 = 0,461 .reserved2 = 0,
461 .reserved3 = 0,462 .reserved3 = 0,
462 });463 });
463 },464 continue;
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 }
522 },465 },
523 macho.S_CSTRING_LITERALS => {466 macho.S_CSTRING_LITERALS => {
524 if (self.cstring_section_index != null) continue;467 if (self.cstring_section_index != null) continue;
...@@ -538,6 +481,7 @@ fn updateMetadata(self: *Zld) !void {...@@ -538,6 +481,7 @@ fn updateMetadata(self: *Zld) !void {
538 .reserved2 = 0,481 .reserved2 = 0,
539 .reserved3 = 0,482 .reserved3 = 0,
540 });483 });
484 continue;
541 },485 },
542 macho.S_MOD_INIT_FUNC_POINTERS => {486 macho.S_MOD_INIT_FUNC_POINTERS => {
543 if (self.mod_init_func_section_index != null) continue;487 if (self.mod_init_func_section_index != null) continue;
...@@ -557,6 +501,7 @@ fn updateMetadata(self: *Zld) !void {...@@ -557,6 +501,7 @@ fn updateMetadata(self: *Zld) !void {
557 .reserved2 = 0,501 .reserved2 = 0,
558 .reserved3 = 0,502 .reserved3 = 0,
559 });503 });
504 continue;
560 },505 },
561 macho.S_MOD_TERM_FUNC_POINTERS => {506 macho.S_MOD_TERM_FUNC_POINTERS => {
562 if (self.mod_term_func_section_index != null) continue;507 if (self.mod_term_func_section_index != null) continue;
...@@ -576,6 +521,7 @@ fn updateMetadata(self: *Zld) !void {...@@ -576,6 +521,7 @@ fn updateMetadata(self: *Zld) !void {
576 .reserved2 = 0,521 .reserved2 = 0,
577 .reserved3 = 0,522 .reserved3 = 0,
578 });523 });
524 continue;
579 },525 },
580 macho.S_ZEROFILL => {526 macho.S_ZEROFILL => {
581 if (mem.eql(u8, sectname, "__common")) {527 if (mem.eql(u8, sectname, "__common")) {
...@@ -615,6 +561,7 @@ fn updateMetadata(self: *Zld) !void {...@@ -615,6 +561,7 @@ fn updateMetadata(self: *Zld) !void {
615 .reserved3 = 0,561 .reserved3 = 0,
616 });562 });
617 }563 }
564 continue;
618 },565 },
619 macho.S_THREAD_LOCAL_VARIABLES => {566 macho.S_THREAD_LOCAL_VARIABLES => {
620 if (self.tlv_section_index != null) continue;567 if (self.tlv_section_index != null) continue;
...@@ -634,6 +581,7 @@ fn updateMetadata(self: *Zld) !void {...@@ -634,6 +581,7 @@ fn updateMetadata(self: *Zld) !void {
634 .reserved2 = 0,581 .reserved2 = 0,
635 .reserved3 = 0,582 .reserved3 = 0,
636 });583 });
584 continue;
637 },585 },
638 macho.S_THREAD_LOCAL_REGULAR => {586 macho.S_THREAD_LOCAL_REGULAR => {
639 if (self.tlv_data_section_index != null) continue;587 if (self.tlv_data_section_index != null) continue;
...@@ -653,6 +601,7 @@ fn updateMetadata(self: *Zld) !void {...@@ -653,6 +601,7 @@ fn updateMetadata(self: *Zld) !void {
653 .reserved2 = 0,601 .reserved2 = 0,
654 .reserved3 = 0,602 .reserved3 = 0,
655 });603 });
604 continue;
656 },605 },
657 macho.S_THREAD_LOCAL_ZEROFILL => {606 macho.S_THREAD_LOCAL_ZEROFILL => {
658 if (self.tlv_bss_section_index != null) continue;607 if (self.tlv_bss_section_index != null) continue;
...@@ -672,58 +621,240 @@ fn updateMetadata(self: *Zld) !void {...@@ -672,58 +621,240 @@ fn updateMetadata(self: *Zld) !void {
672 .reserved2 = 0,621 .reserved2 = 0,
673 .reserved3 = 0,622 .reserved3 = 0,
674 });623 });
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 });
683 continue;624 continue;
684 },625 },
685 macho.S_REGULAR | macho.S_ATTR_DEBUG => {626 macho.S_COALESCED => {
686 if (mem.eql(u8, "__LD", segname) and mem.eql(u8, "__compact_unwind", sectname)) {627 if (mem.eql(u8, "__TEXT", segname) and mem.eql(u8, "__eh_frame", sectname)) {
687 log.debug("TODO compact unwind section: type 0x{x}, name '{s},{s}'", .{628 // TODO I believe __eh_frame is currently part of __unwind_info section
688 flags, segname, sectname,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,
689 });646 });
647 continue;
690 }648 }
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 });
691 continue;668 continue;
692 },669 },
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
694 if (mem.eql(u8, "__LLVM", segname) and mem.eql(u8, "__asm", sectname)) {823 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}'", .{824 log.debug("TODO LLVM asm section: type 0x{x}, name '{s},{s}'", .{
696 flags, segname, sectname,825 sect.flags(), segname, sectname,
697 });826 });
698 continue;827 continue;
699 }828 }
700 log.err("unhandled section type 0x{x} for '{s},{s}'", .{ flags, segname, sectname });
701 return error.UnhandledSection;
702 },829 },
830 else => {},
703 }831 }
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;
704 }840 }
705841
706 // Find ideal section alignment.842 // Find ideal section alignment.
707 for (object_seg.sections.items) |source_sect| {843 for (object.sections.items) |sect| {
708 if (self.getMatchingSection(source_sect)) |res| {844 if (self.getMatchingSection(sect)) |res| {
709 const target_seg = &self.load_commands.items[res.seg].Segment;845 const target_seg = &self.load_commands.items[res.seg].Segment;
710 const target_sect = &target_seg.sections.items[res.sect];846 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");
712 }848 }
713 }849 }
714850
715 // Update section mappings851 // Update section mappings
716 for (object_seg.sections.items) |source_sect, sect_id| {852 for (object.sections.items) |sect, sect_id| {
717 const source_sect_id = @intCast(u16, sect_id);853 if (self.getMatchingSection(sect)) |res| {
718 if (self.getMatchingSection(source_sect)) |res| {854 try self.mapAndUpdateSections(object, @intCast(u16, sect_id), res.seg, res.sect);
719 try self.mapAndUpdateSections(object, source_sect_id, res.seg, res.sect);
720 continue;855 continue;
721 }856 }
722857 log.debug("section '{s},{s}' will be unmapped", .{ sect.segname(), sect.sectname() });
723 log.debug("section '{s},{s}' will be unmapped", .{
724 parseName(&source_sect.segname),
725 parseName(&source_sect.sectname),
726 });
727 }858 }
728 }859 }
729860
...@@ -819,13 +950,13 @@ const MatchingSection = struct {...@@ -819,13 +950,13 @@ const MatchingSection = struct {
819 sect: u16,950 sect: u16,
820};951};
821952
822fn getMatchingSection(self: *Zld, section: macho.section_64) ?MatchingSection {953fn getMatchingSection(self: *Zld, sect: Object.Section) ?MatchingSection {
823 const segname = parseName(&section.segname);954 const segname = sect.segname();
824 const sectname = parseName(&section.sectname);955 const sectname = sect.sectname();
825956
826 const res: ?MatchingSection = blk: {957 const res: ?MatchingSection = blk: {
827 switch (section.flags) {958 switch (sect.sectionType()) {
828 macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => {959 macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS, macho.S_LITERAL_POINTERS => {
829 break :blk .{960 break :blk .{
830 .seg = self.text_segment_cmd_index.?,961 .seg = self.text_segment_cmd_index.?,
831 .sect = self.text_const_section_index.?,962 .sect = self.text_const_section_index.?,
...@@ -855,11 +986,12 @@ fn getMatchingSection(self: *Zld, section: macho.section_64) ?MatchingSection {...@@ -855,11 +986,12 @@ fn getMatchingSection(self: *Zld, section: macho.section_64) ?MatchingSection {
855 .seg = self.data_segment_cmd_index.?,986 .seg = self.data_segment_cmd_index.?,
856 .sect = self.common_section_index.?,987 .sect = self.common_section_index.?,
857 };988 };
989 } else {
990 break :blk .{
991 .seg = self.data_segment_cmd_index.?,
992 .sect = self.bss_section_index.?,
993 };
858 }994 }
859 break :blk .{
860 .seg = self.data_segment_cmd_index.?,
861 .sect = self.bss_section_index.?,
862 };
863 },995 },
864 macho.S_THREAD_LOCAL_VARIABLES => {996 macho.S_THREAD_LOCAL_VARIABLES => {
865 break :blk .{997 break :blk .{
...@@ -879,31 +1011,57 @@ fn getMatchingSection(self: *Zld, section: macho.section_64) ?MatchingSection {...@@ -879,31 +1011,57 @@ fn getMatchingSection(self: *Zld, section: macho.section_64) ?MatchingSection {
879 .sect = self.tlv_bss_section_index.?,1011 .sect = self.tlv_bss_section_index.?,
880 };1012 };
881 },1013 },
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
883 break :blk .{1022 break :blk .{
884 .seg = self.text_segment_cmd_index.?,1023 .seg = self.data_const_segment_cmd_index.?,
885 .sect = self.text_section_index.?,1024 .sect = self.data_const_section_index.?,
886 };1025 };
887 },1026 },
888 macho.S_REGULAR => {1027 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
889 if (mem.eql(u8, segname, "__TEXT")) {1039 if (mem.eql(u8, segname, "__TEXT")) {
890 if (mem.eql(u8, sectname, "__ustring")) {1040 if (mem.eql(u8, sectname, "__ustring")) {
891 break :blk .{1041 break :blk .{
892 .seg = self.text_segment_cmd_index.?,1042 .seg = self.text_segment_cmd_index.?,
893 .sect = self.ustring_section_index.?,1043 .sect = self.ustring_section_index.?,
894 };1044 };
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 };
895 }1055 }
896 break :blk .{
897 .seg = self.text_segment_cmd_index.?,
898 .sect = self.text_const_section_index.?,
899 };
900 }1056 }
1057
901 if (mem.eql(u8, segname, "__DATA_CONST")) {1058 if (mem.eql(u8, segname, "__DATA_CONST")) {
902 break :blk .{1059 break :blk .{
903 .seg = self.data_const_segment_cmd_index.?,1060 .seg = self.data_const_segment_cmd_index.?,
904 .sect = self.data_const_section_index.?,1061 .sect = self.data_const_section_index.?,
905 };1062 };
906 }1063 }
1064
907 if (mem.eql(u8, segname, "__DATA")) {1065 if (mem.eql(u8, segname, "__DATA")) {
908 if (mem.eql(u8, sectname, "__const")) {1066 if (mem.eql(u8, sectname, "__const")) {
909 break :blk .{1067 break :blk .{
...@@ -916,11 +1074,10 @@ fn getMatchingSection(self: *Zld, section: macho.section_64) ?MatchingSection {...@@ -916,11 +1074,10 @@ fn getMatchingSection(self: *Zld, section: macho.section_64) ?MatchingSection {
916 .sect = self.data_section_index.?,1074 .sect = self.data_section_index.?,
917 };1075 };
918 }1076 }
1077
919 break :blk null;1078 break :blk null;
920 },1079 },
921 else => {1080 else => break :blk null,
922 break :blk null;
923 },
924 }1081 }
925 };1082 };
9261083
...@@ -946,9 +1103,11 @@ fn sortSections(self: *Zld) !void {...@@ -946,9 +1103,11 @@ fn sortSections(self: *Zld) !void {
946 &self.text_section_index,1103 &self.text_section_index,
947 &self.stubs_section_index,1104 &self.stubs_section_index,
948 &self.stub_helper_section_index,1105 &self.stub_helper_section_index,
949 &self.text_const_section_index,1106 &self.gcc_except_tab_section_index,
950 &self.cstring_section_index,1107 &self.cstring_section_index,
951 &self.ustring_section_index,1108 &self.ustring_section_index,
1109 &self.text_const_section_index,
1110 &self.eh_frame_section_index,
952 };1111 };
953 for (indices) |maybe_index| {1112 for (indices) |maybe_index| {
954 const new_index: u16 = if (maybe_index.*) |index| blk: {1113 const new_index: u16 = if (maybe_index.*) |index| blk: {
...@@ -1733,7 +1892,7 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {...@@ -1733,7 +1892,7 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {
1733 for (relocs) |rel| {1892 for (relocs) |rel| {
1734 switch (rel.@"type") {1893 switch (rel.@"type") {
1735 .unsigned => continue,1894 .unsigned => continue,
1736 .got_page, .got_page_off, .got_load, .got => {1895 .got_page, .got_page_off, .got_load, .got, .pointer_to_got => {
1737 const sym = rel.target.symbol.getTopmostAlias();1896 const sym = rel.target.symbol.getTopmostAlias();
1738 if (sym.got_index != null) continue;1897 if (sym.got_index != null) continue;
17391898
...@@ -1751,9 +1910,6 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {...@@ -1751,9 +1910,6 @@ fn resolveStubsAndGotEntries(self: *Zld) !void {
17511910
1752 if (sym.stubs_index != null) continue;1911 if (sym.stubs_index != null) continue;
1753 if (sym.@"type" != .proxy) continue;1912 if (sym.@"type" != .proxy) continue;
1754 // if (sym.cast(Symbol.Regular)) |reg| {
1755 // if (!reg.weak_ref) continue;
1756 // }
17571913
1758 const index = @intCast(u32, self.stubs.items.len);1914 const index = @intCast(u32, self.stubs.items.len);
1759 sym.stubs_index = index;1915 sym.stubs_index = index;
...@@ -1864,11 +2020,19 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {...@@ -1864,11 +2020,19 @@ fn resolveRelocsAndWriteSections(self: *Zld) !void {
1864 });2020 });
1865 }2021 }
1866 },2022 },
1867 .got_page, .got_page_off, .got_load, .got => {2023 .got_page, .got_page_off, .got_load, .got, .pointer_to_got => {
1868 const dc_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;2024 const dc_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
1869 const got = dc_seg.sections.items[self.got_section_index.?];2025 const got = dc_seg.sections.items[self.got_section_index.?];
1870 const final = rel.target.symbol.getTopmostAlias();2026 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);
1872 },2036 },
1873 else => |tt| {2037 else => |tt| {
1874 if (tt == .signed and rel.target == .section) {2038 if (tt == .signed and rel.target == .section) {
...@@ -1934,7 +2098,15 @@ fn relocTargetAddr(self: *Zld, object: *const Object, target: reloc.Relocation.T...@@ -1934,7 +2098,15 @@ fn relocTargetAddr(self: *Zld, object: *const Object, target: reloc.Relocation.T
1934 log.debug(" | symbol stub '{s}'", .{sym.name});2098 log.debug(" | symbol stub '{s}'", .{sym.name});
1935 const segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;2099 const segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
1936 const stubs = segment.sections.items[self.stubs_section_index.?];2100 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;
1938 } else {2110 } else {
1939 log.err("failed to resolve symbol '{s}' as a relocation target", .{sym.name});2111 log.err("failed to resolve symbol '{s}' as a relocation target", .{sym.name});
1940 return error.FailedToResolveRelocationTarget;2112 return error.FailedToResolveRelocationTarget;
src/link/MachO/reloc.zig+2
...@@ -52,6 +52,7 @@ pub const Relocation = struct {...@@ -52,6 +52,7 @@ pub const Relocation = struct {
52 .page_off => @fieldParentPtr(aarch64.PageOff, "base", base).resolve(args),52 .page_off => @fieldParentPtr(aarch64.PageOff, "base", base).resolve(args),
53 .got_page => @fieldParentPtr(aarch64.GotPage, "base", base).resolve(args),53 .got_page => @fieldParentPtr(aarch64.GotPage, "base", base).resolve(args),
54 .got_page_off => @fieldParentPtr(aarch64.GotPageOff, "base", base).resolve(args),54 .got_page_off => @fieldParentPtr(aarch64.GotPageOff, "base", base).resolve(args),
55 .pointer_to_got => @fieldParentPtr(aarch64.PointerToGot, "base", base).resolve(args),
55 .tlvp_page => @fieldParentPtr(aarch64.TlvpPage, "base", base).resolve(args),56 .tlvp_page => @fieldParentPtr(aarch64.TlvpPage, "base", base).resolve(args),
56 .tlvp_page_off => @fieldParentPtr(aarch64.TlvpPageOff, "base", base).resolve(args),57 .tlvp_page_off => @fieldParentPtr(aarch64.TlvpPageOff, "base", base).resolve(args),
57 .branch_x86_64 => @fieldParentPtr(x86_64.Branch, "base", base).resolve(args),58 .branch_x86_64 => @fieldParentPtr(x86_64.Branch, "base", base).resolve(args),
...@@ -70,6 +71,7 @@ pub const Relocation = struct {...@@ -70,6 +71,7 @@ pub const Relocation = struct {
70 got_page,71 got_page,
71 got_page_off,72 got_page_off,
72 tlvp_page,73 tlvp_page,
74 pointer_to_got,
73 tlvp_page_off,75 tlvp_page_off,
74 branch_x86_64,76 branch_x86_64,
75 signed,77 signed,
src/link/MachO/reloc/aarch64.zig+40-3
...@@ -141,6 +141,20 @@ pub const GotPageOff = struct {...@@ -141,6 +141,20 @@ pub const GotPageOff = struct {
141 }141 }
142};142};
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
144pub const TlvpPage = struct {158pub const TlvpPage = struct {
145 base: Relocation,159 base: Relocation,
146 /// Always .PCRelativeAddress160 /// Always .PCRelativeAddress
...@@ -228,9 +242,7 @@ pub const Parser = struct {...@@ -228,9 +242,7 @@ pub const Parser = struct {
228 try parser.parseTlvpLoadPageOff(rel);242 try parser.parseTlvpLoadPageOff(rel);
229 },243 },
230 .ARM64_RELOC_POINTER_TO_GOT => {244 .ARM64_RELOC_POINTER_TO_GOT => {
231 // TODO Handle pointer to GOT. This reloc seems to appear in245 try parser.parsePointerToGot(rel);
232 // __LD,__compact_unwind section which we currently don't handle.
233 log.debug("Unhandled relocation ARM64_RELOC_POINTER_TO_GOT", .{});
234 },246 },
235 }247 }
236 }248 }
...@@ -583,6 +595,31 @@ pub const Parser = struct {...@@ -583,6 +595,31 @@ pub const Parser = struct {
583 log.debug(" | emitting {}", .{unsigned});595 log.debug(" | emitting {}", .{unsigned});
584 try parser.parsed.append(&unsigned.base);596 try parser.parsed.append(&unsigned.base);
585 }597 }
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 }
586};623};
587624
588inline fn isArithmeticOp(inst: *const [4]u8) bool {625inline fn isArithmeticOp(inst: *const [4]u8) bool {
src/link/MachO/reloc/x86_64.zig+7-1
...@@ -66,11 +66,15 @@ pub const GotLoad = struct {...@@ -66,11 +66,15 @@ pub const GotLoad = struct {
6666
67pub const Got = struct {67pub const Got = struct {
68 base: Relocation,68 base: Relocation,
69 addend: i32,
6970
70 pub const base_type: Relocation.Type = .got;71 pub const base_type: Relocation.Type = .got;
7172
72 pub fn resolve(got: Got, args: Relocation.ResolveArgs) !void {73 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 );
74 log.debug(" | displacement 0x{x}", .{displacement});78 log.debug(" | displacement 0x{x}", .{displacement});
75 mem.writeIntLittle(u32, got.base.code[0..4], @bitCast(u32, displacement));79 mem.writeIntLittle(u32, got.base.code[0..4], @bitCast(u32, displacement));
76 }80 }
...@@ -237,6 +241,7 @@ pub const Parser = struct {...@@ -237,6 +241,7 @@ pub const Parser = struct {
237 const offset = @intCast(u32, rel.r_address);241 const offset = @intCast(u32, rel.r_address);
238 const inst = parser.code[offset..][0..4];242 const inst = parser.code[offset..][0..4];
239 const target = Relocation.Target.from_reloc(rel, parser.symbols);243 const target = Relocation.Target.from_reloc(rel, parser.symbols);
244 const addend = mem.readIntLittle(i32, inst);
240245
241 var got = try parser.allocator.create(Got);246 var got = try parser.allocator.create(Got);
242 errdefer parser.allocator.destroy(got);247 errdefer parser.allocator.destroy(got);
...@@ -248,6 +253,7 @@ pub const Parser = struct {...@@ -248,6 +253,7 @@ pub const Parser = struct {
248 .offset = offset,253 .offset = offset,
249 .target = target,254 .target = target,
250 },255 },
256 .addend = addend,
251 };257 };
252258
253 log.debug(" | emitting {}", .{got});259 log.debug(" | emitting {}", .{got});