authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-06-21 13:21:34+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-06-24 18:55:43+02:00
log5f9b4cba6da9540d5a2fd03d9b379d0b7eb5937d
tree9a3151e1ae7e9539cae3e262b27694e83647a6fb
parent852e1ed23cb5cfdb687a52c39fa9c60be3159730

zld: clean up logic for matching and mapping sections


1 files changed, 150 insertions(+), 214 deletions(-)

src/link/MachO/Zld.zig+150-214
......@@ -503,217 +503,22 @@ fn mapAndUpdateSections(
503503
504504fn updateMetadata(self: *Zld) !void {
505505 for (self.objects.items) |object| {
506 const text_seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
507 const data_const_seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
508 const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
509
510 // Create missing metadata
511 for (object.sections.items) |sect| {
512 const segname = sect.segname();
513 const sectname = sect.sectname();
514
515 switch (sect.sectionType()) {
516 macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS, macho.S_LITERAL_POINTERS => {
517 if (self.text_const_section_index != null) continue;
518
519 self.text_const_section_index = @intCast(u16, text_seg.sections.items.len);
520 try text_seg.addSection(self.allocator, "__const", "__TEXT", .{});
521 continue;
522 },
523 macho.S_CSTRING_LITERALS => {
524 if (self.cstring_section_index != null) continue;
525
526 self.cstring_section_index = @intCast(u16, text_seg.sections.items.len);
527 try text_seg.addSection(self.allocator, "__cstring", "__TEXT", .{
528 .flags = macho.S_CSTRING_LITERALS,
529 });
530 continue;
531 },
532 macho.S_MOD_INIT_FUNC_POINTERS => {
533 if (self.mod_init_func_section_index != null) continue;
534
535 self.mod_init_func_section_index = @intCast(u16, data_const_seg.sections.items.len);
536 try data_const_seg.addSection(self.allocator, "__mod_init_func", "__DATA_CONST", .{
537 .flags = macho.S_MOD_INIT_FUNC_POINTERS,
538 });
539 continue;
540 },
541 macho.S_MOD_TERM_FUNC_POINTERS => {
542 if (self.mod_term_func_section_index != null) continue;
543
544 self.mod_term_func_section_index = @intCast(u16, data_const_seg.sections.items.len);
545 try data_const_seg.addSection(self.allocator, "__mod_term_func", "__DATA_CONST", .{
546 .flags = macho.S_MOD_TERM_FUNC_POINTERS,
547 });
548 continue;
549 },
550 macho.S_ZEROFILL => {
551 if (mem.eql(u8, sectname, "__common")) {
552 if (self.common_section_index != null) continue;
553
554 self.common_section_index = @intCast(u16, data_seg.sections.items.len);
555 try data_seg.addSection(self.allocator, "__common", "__DATA", .{
556 .flags = macho.S_ZEROFILL,
557 });
558 } else {
559 if (self.bss_section_index != null) continue;
560
561 self.bss_section_index = @intCast(u16, data_seg.sections.items.len);
562 try data_seg.addSection(self.allocator, "__bss", "__DATA", .{
563 .flags = macho.S_ZEROFILL,
564 });
565 }
566 continue;
567 },
568 macho.S_THREAD_LOCAL_VARIABLES => {
569 if (self.tlv_section_index != null) continue;
570
571 self.tlv_section_index = @intCast(u16, data_seg.sections.items.len);
572 try data_seg.addSection(self.allocator, "__thread_vars", "__DATA", .{
573 .flags = macho.S_THREAD_LOCAL_VARIABLES,
574 });
575 continue;
576 },
577 macho.S_THREAD_LOCAL_REGULAR => {
578 if (self.tlv_data_section_index != null) continue;
579
580 self.tlv_data_section_index = @intCast(u16, data_seg.sections.items.len);
581 try data_seg.addSection(self.allocator, "__thread_data", "__DATA", .{
582 .flags = macho.S_THREAD_LOCAL_REGULAR,
583 });
584 continue;
585 },
586 macho.S_THREAD_LOCAL_ZEROFILL => {
587 if (self.tlv_bss_section_index != null) continue;
588
589 self.tlv_bss_section_index = @intCast(u16, data_seg.sections.items.len);
590 try data_seg.addSection(self.allocator, "__thread_bss", "__DATA", .{
591 .flags = macho.S_THREAD_LOCAL_ZEROFILL,
592 });
593 continue;
594 },
595 macho.S_COALESCED => {
596 if (mem.eql(u8, "__TEXT", segname) and mem.eql(u8, "__eh_frame", sectname)) {
597 // TODO I believe __eh_frame is currently part of __unwind_info section
598 // in the latest ld64 output.
599 if (self.eh_frame_section_index != null) continue;
600
601 self.eh_frame_section_index = @intCast(u16, text_seg.sections.items.len);
602 try text_seg.addSection(self.allocator, "__eh_frame", "__TEXT", .{});
603 continue;
604 }
605
606 // TODO audit this: is this the right mapping?
607 if (self.data_const_section_index != null) continue;
608
609 self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);
610 try data_const_seg.addSection(self.allocator, "__const", "__DATA_CONST", .{});
611 continue;
612 },
613 macho.S_REGULAR => {
614 if (sect.isCode()) {
615 if (self.text_section_index != null) continue;
616
617 self.text_section_index = @intCast(u16, text_seg.sections.items.len);
618 try text_seg.addSection(self.allocator, "__text", "__TEXT", .{
619 .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
620 });
621 continue;
622 }
623
624 if (sect.isDebug()) {
625 if (mem.eql(u8, "__LD", segname) and mem.eql(u8, "__compact_unwind", sectname)) {
626 log.debug("TODO compact unwind section: type 0x{x}, name '{s},{s}'", .{
627 sect.flags(), segname, sectname,
628 });
629 }
630 continue;
631 }
632
633 if (mem.eql(u8, segname, "__TEXT")) {
634 if (mem.eql(u8, sectname, "__ustring")) {
635 if (self.ustring_section_index != null) continue;
636
637 self.ustring_section_index = @intCast(u16, text_seg.sections.items.len);
638 try text_seg.addSection(self.allocator, "__ustring", "__TEXT", .{});
639 } else if (mem.eql(u8, sectname, "__gcc_except_tab")) {
640 if (self.gcc_except_tab_section_index != null) continue;
641
642 self.gcc_except_tab_section_index = @intCast(u16, text_seg.sections.items.len);
643 try text_seg.addSection(self.allocator, "__gcc_except_tab", "__TEXT", .{});
644 } else {
645 if (self.text_const_section_index != null) continue;
646
647 self.text_const_section_index = @intCast(u16, text_seg.sections.items.len);
648 try text_seg.addSection(self.allocator, "__const", "__TEXT", .{});
649 }
650 continue;
651 }
652
653 if (mem.eql(u8, segname, "__DATA_CONST")) {
654 if (self.data_const_section_index != null) continue;
655
656 self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);
657 try data_const_seg.addSection(self.allocator, "__const", "__DATA_CONST", .{});
658 continue;
659 }
660
661 if (mem.eql(u8, segname, "__DATA")) {
662 if (mem.eql(u8, sectname, "__const")) {
663 if (self.data_const_section_index != null) continue;
664
665 self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);
666 try data_const_seg.addSection(self.allocator, "__const", "__DATA_CONST", .{});
667 } else if (mem.eql(u8, sectname, "__cfstring")) {
668 if (self.objc_cfstring_section_index != null) continue;
669
670 self.objc_cfstring_section_index = @intCast(u16, data_const_seg.sections.items.len);
671 try data_const_seg.addSection(self.allocator, "__cfstring", "__DATA_CONST", .{});
672 } else {
673 if (self.data_section_index != null) continue;
674
675 self.data_section_index = @intCast(u16, data_seg.sections.items.len);
676 try data_seg.addSection(self.allocator, "__data", "__DATA", .{});
677 }
678
679 continue;
680 }
681
682 if (mem.eql(u8, "__LLVM", segname) and mem.eql(u8, "__asm", sectname)) {
683 log.debug("TODO LLVM asm section: type 0x{x}, name '{s},{s}'", .{
684 sect.flags(), segname, sectname,
685 });
686 continue;
687 }
688 },
689 else => {},
690 }
691
692 log.err("{s}: unhandled section type 0x{x} for '{s},{s}'", .{
693 object.name.?,
694 sect.flags(),
695 segname,
696 sectname,
697 });
698 return error.UnhandledSection;
699 }
700
701 // Find ideal section alignment.
702 for (object.sections.items) |sect| {
703 if (self.getMatchingSection(sect)) |res| {
704 const target_seg = &self.load_commands.items[res.seg].Segment;
705 const target_sect = &target_seg.sections.items[res.sect];
706 target_sect.@"align" = math.max(target_sect.@"align", sect.inner.@"align");
707 }
708 }
709
710 // Update section mappings
506 // Find ideal section alignment and update section mappings
711507 for (object.sections.items) |sect, sect_id| {
712 if (self.getMatchingSection(sect)) |res| {
713 try self.mapAndUpdateSections(object, @intCast(u16, sect_id), res.seg, res.sect);
508 const match = (try self.getMatchingSection(sect)) orelse {
509 log.debug("{s}: unhandled section type 0x{x} for '{s},{s}'", .{
510 object.name.?,
511 sect.flags(),
512 sect.segname(),
513 sect.sectname(),
514 });
714515 continue;
715 }
716 log.debug("section '{s},{s}' will be unmapped", .{ sect.segname(), sect.sectname() });
516 };
517 const target_seg = &self.load_commands.items[match.seg].Segment;
518 const target_sect = &target_seg.sections.items[match.sect];
519 target_sect.@"align" = math.max(target_sect.@"align", sect.inner.@"align");
520
521 try self.mapAndUpdateSections(object, @intCast(u16, sect_id), match.seg, match.sect);
717522 }
718523 }
719524
......@@ -798,31 +603,60 @@ const MatchingSection = struct {
798603 sect: u16,
799604};
800605
801fn getMatchingSection(self: *Zld, sect: Object.Section) ?MatchingSection {
606fn getMatchingSection(self: *Zld, sect: Object.Section) !?MatchingSection {
607 const text_seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
608 const data_const_seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment;
609 const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
802610 const segname = sect.segname();
803611 const sectname = sect.sectname();
804612
805613 const res: ?MatchingSection = blk: {
806614 switch (sect.sectionType()) {
807615 macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS, macho.S_LITERAL_POINTERS => {
616 if (self.text_const_section_index == null) {
617 self.text_const_section_index = @intCast(u16, text_seg.sections.items.len);
618 try text_seg.addSection(self.allocator, "__const", "__TEXT", .{});
619 }
620
808621 break :blk .{
809622 .seg = self.text_segment_cmd_index.?,
810623 .sect = self.text_const_section_index.?,
811624 };
812625 },
813626 macho.S_CSTRING_LITERALS => {
627 if (self.cstring_section_index == null) {
628 self.cstring_section_index = @intCast(u16, text_seg.sections.items.len);
629 try text_seg.addSection(self.allocator, "__cstring", "__TEXT", .{
630 .flags = macho.S_CSTRING_LITERALS,
631 });
632 }
633
814634 break :blk .{
815635 .seg = self.text_segment_cmd_index.?,
816636 .sect = self.cstring_section_index.?,
817637 };
818638 },
819639 macho.S_MOD_INIT_FUNC_POINTERS => {
640 if (self.mod_init_func_section_index == null) {
641 self.mod_init_func_section_index = @intCast(u16, data_const_seg.sections.items.len);
642 try data_const_seg.addSection(self.allocator, "__mod_init_func", "__DATA_CONST", .{
643 .flags = macho.S_MOD_INIT_FUNC_POINTERS,
644 });
645 }
646
820647 break :blk .{
821648 .seg = self.data_const_segment_cmd_index.?,
822649 .sect = self.mod_init_func_section_index.?,
823650 };
824651 },
825652 macho.S_MOD_TERM_FUNC_POINTERS => {
653 if (self.mod_term_func_section_index == null) {
654 self.mod_term_func_section_index = @intCast(u16, data_const_seg.sections.items.len);
655 try data_const_seg.addSection(self.allocator, "__mod_term_func", "__DATA_CONST", .{
656 .flags = macho.S_MOD_TERM_FUNC_POINTERS,
657 });
658 }
659
826660 break :blk .{
827661 .seg = self.data_const_segment_cmd_index.?,
828662 .sect = self.mod_term_func_section_index.?,
......@@ -830,11 +664,25 @@ fn getMatchingSection(self: *Zld, sect: Object.Section) ?MatchingSection {
830664 },
831665 macho.S_ZEROFILL => {
832666 if (mem.eql(u8, sectname, "__common")) {
667 if (self.common_section_index == null) {
668 self.common_section_index = @intCast(u16, data_seg.sections.items.len);
669 try data_seg.addSection(self.allocator, "__common", "__DATA", .{
670 .flags = macho.S_ZEROFILL,
671 });
672 }
673
833674 break :blk .{
834675 .seg = self.data_segment_cmd_index.?,
835676 .sect = self.common_section_index.?,
836677 };
837678 } else {
679 if (self.bss_section_index == null) {
680 self.bss_section_index = @intCast(u16, data_seg.sections.items.len);
681 try data_seg.addSection(self.allocator, "__bss", "__DATA", .{
682 .flags = macho.S_ZEROFILL,
683 });
684 }
685
838686 break :blk .{
839687 .seg = self.data_segment_cmd_index.?,
840688 .sect = self.bss_section_index.?,
......@@ -842,18 +690,39 @@ fn getMatchingSection(self: *Zld, sect: Object.Section) ?MatchingSection {
842690 }
843691 },
844692 macho.S_THREAD_LOCAL_VARIABLES => {
693 if (self.tlv_section_index == null) {
694 self.tlv_section_index = @intCast(u16, data_seg.sections.items.len);
695 try data_seg.addSection(self.allocator, "__thread_vars", "__DATA", .{
696 .flags = macho.S_THREAD_LOCAL_VARIABLES,
697 });
698 }
699
845700 break :blk .{
846701 .seg = self.data_segment_cmd_index.?,
847702 .sect = self.tlv_section_index.?,
848703 };
849704 },
850705 macho.S_THREAD_LOCAL_REGULAR => {
706 if (self.tlv_data_section_index == null) {
707 self.tlv_data_section_index = @intCast(u16, data_seg.sections.items.len);
708 try data_seg.addSection(self.allocator, "__thread_data", "__DATA", .{
709 .flags = macho.S_THREAD_LOCAL_REGULAR,
710 });
711 }
712
851713 break :blk .{
852714 .seg = self.data_segment_cmd_index.?,
853715 .sect = self.tlv_data_section_index.?,
854716 };
855717 },
856718 macho.S_THREAD_LOCAL_ZEROFILL => {
719 if (self.tlv_bss_section_index == null) {
720 self.tlv_bss_section_index = @intCast(u16, data_seg.sections.items.len);
721 try data_seg.addSection(self.allocator, "__thread_bss", "__DATA", .{
722 .flags = macho.S_THREAD_LOCAL_ZEROFILL,
723 });
724 }
725
857726 break :blk .{
858727 .seg = self.data_segment_cmd_index.?,
859728 .sect = self.tlv_bss_section_index.?,
......@@ -861,12 +730,25 @@ fn getMatchingSection(self: *Zld, sect: Object.Section) ?MatchingSection {
861730 },
862731 macho.S_COALESCED => {
863732 if (mem.eql(u8, "__TEXT", segname) and mem.eql(u8, "__eh_frame", sectname)) {
733 // TODO I believe __eh_frame is currently part of __unwind_info section
734 // in the latest ld64 output.
735 if (self.eh_frame_section_index == null) {
736 self.eh_frame_section_index = @intCast(u16, text_seg.sections.items.len);
737 try text_seg.addSection(self.allocator, "__eh_frame", "__TEXT", .{});
738 }
739
864740 break :blk .{
865741 .seg = self.text_segment_cmd_index.?,
866742 .sect = self.eh_frame_section_index.?,
867743 };
868744 }
869745
746 // TODO audit this: is this the right mapping?
747 if (self.data_const_section_index == null) {
748 self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);
749 try data_const_seg.addSection(self.allocator, "__const", "__DATA_CONST", .{});
750 }
751
870752 break :blk .{
871753 .seg = self.data_const_segment_cmd_index.?,
872754 .sect = self.data_const_section_index.?,
......@@ -874,6 +756,13 @@ fn getMatchingSection(self: *Zld, sect: Object.Section) ?MatchingSection {
874756 },
875757 macho.S_REGULAR => {
876758 if (sect.isCode()) {
759 if (self.text_section_index == null) {
760 self.text_section_index = @intCast(u16, text_seg.sections.items.len);
761 try text_seg.addSection(self.allocator, "__text", "__TEXT", .{
762 .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
763 });
764 }
765
877766 break :blk .{
878767 .seg = self.text_segment_cmd_index.?,
879768 .sect = self.text_section_index.?,
......@@ -881,21 +770,41 @@ fn getMatchingSection(self: *Zld, sect: Object.Section) ?MatchingSection {
881770 }
882771 if (sect.isDebug()) {
883772 // TODO debug attributes
773 if (mem.eql(u8, "__LD", segname) and mem.eql(u8, "__compact_unwind", sectname)) {
774 log.debug("TODO compact unwind section: type 0x{x}, name '{s},{s}'", .{
775 sect.flags(), segname, sectname,
776 });
777 }
884778 break :blk null;
885779 }
886780
887781 if (mem.eql(u8, segname, "__TEXT")) {
888782 if (mem.eql(u8, sectname, "__ustring")) {
783 if (self.ustring_section_index == null) {
784 self.ustring_section_index = @intCast(u16, text_seg.sections.items.len);
785 try text_seg.addSection(self.allocator, "__ustring", "__TEXT", .{});
786 }
787
889788 break :blk .{
890789 .seg = self.text_segment_cmd_index.?,
891790 .sect = self.ustring_section_index.?,
892791 };
893792 } else if (mem.eql(u8, sectname, "__gcc_except_tab")) {
793 if (self.gcc_except_tab_section_index == null) {
794 self.gcc_except_tab_section_index = @intCast(u16, text_seg.sections.items.len);
795 try text_seg.addSection(self.allocator, "__gcc_except_tab", "__TEXT", .{});
796 }
797
894798 break :blk .{
895799 .seg = self.text_segment_cmd_index.?,
896800 .sect = self.gcc_except_tab_section_index.?,
897801 };
898802 } else {
803 if (self.text_const_section_index == null) {
804 self.text_const_section_index = @intCast(u16, text_seg.sections.items.len);
805 try text_seg.addSection(self.allocator, "__const", "__TEXT", .{});
806 }
807
899808 break :blk .{
900809 .seg = self.text_segment_cmd_index.?,
901810 .sect = self.text_const_section_index.?,
......@@ -904,6 +813,11 @@ fn getMatchingSection(self: *Zld, sect: Object.Section) ?MatchingSection {
904813 }
905814
906815 if (mem.eql(u8, segname, "__DATA_CONST")) {
816 if (self.data_const_section_index == null) {
817 self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);
818 try data_const_seg.addSection(self.allocator, "__const", "__DATA_CONST", .{});
819 }
820
907821 break :blk .{
908822 .seg = self.data_const_segment_cmd_index.?,
909823 .sect = self.data_const_section_index.?,
......@@ -912,20 +826,42 @@ fn getMatchingSection(self: *Zld, sect: Object.Section) ?MatchingSection {
912826
913827 if (mem.eql(u8, segname, "__DATA")) {
914828 if (mem.eql(u8, sectname, "__const")) {
829 if (self.data_const_section_index == null) {
830 self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);
831 try data_const_seg.addSection(self.allocator, "__const", "__DATA_CONST", .{});
832 }
833
915834 break :blk .{
916835 .seg = self.data_const_segment_cmd_index.?,
917836 .sect = self.data_const_section_index.?,
918837 };
919838 } else if (mem.eql(u8, sectname, "__cfstring")) {
839 if (self.objc_cfstring_section_index == null) {
840 self.objc_cfstring_section_index = @intCast(u16, data_const_seg.sections.items.len);
841 try data_const_seg.addSection(self.allocator, "__cfstring", "__DATA_CONST", .{});
842 }
843
920844 break :blk .{
921845 .seg = self.data_const_segment_cmd_index.?,
922846 .sect = self.objc_cfstring_section_index.?,
923847 };
848 } else {
849 if (self.data_section_index == null) {
850 self.data_section_index = @intCast(u16, data_seg.sections.items.len);
851 try data_seg.addSection(self.allocator, "__data", "__DATA", .{});
852 }
853
854 break :blk .{
855 .seg = self.data_segment_cmd_index.?,
856 .sect = self.data_section_index.?,
857 };
924858 }
925 break :blk .{
926 .seg = self.data_segment_cmd_index.?,
927 .sect = self.data_section_index.?,
928 };
859 }
860
861 if (mem.eql(u8, "__LLVM", segname) and mem.eql(u8, "__asm", sectname)) {
862 log.debug("TODO LLVM asm section: type 0x{x}, name '{s},{s}'", .{
863 sect.flags(), segname, sectname,
864 });
929865 }
930866
931867 break :blk null;