authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-06-14 12:56:53+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-06-15 12:14:03+02:00
log96d3c4f54fb4d80a44d9319c0054b45f4b856cad
tree640f659313dfeefbafa9bf7424a313ed02cb28d0
parent6fad1d48e4c95295a3f0e7b613306efef666e084

zld: clean up parsing section by type and attrs


2 files changed, 244 insertions(+), 122 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+207-122
......@@ -409,7 +409,7 @@ fn mapAndUpdateSections(
409409 const offset = mem.alignForwardGeneric(u64, target_sect.size, alignment);
410410 const size = mem.alignForwardGeneric(u64, source_sect.inner.size, alignment);
411411
412 log.debug("{s}: '{s},{s}' mapped to '{s},{s}' from 0x{x} to 0x{x}", .{
412 log.warn("{s}: '{s},{s}' mapped to '{s},{s}' from 0x{x} to 0x{x}", .{
413413 object.name.?,
414414 parseName(&source_sect.inner.segname),
415415 parseName(&source_sect.inner.sectname),
......@@ -435,19 +435,17 @@ fn updateMetadata(self: *Zld) !void {
435435 const data_seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
436436
437437 // 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;
438 for (object.sections.items) |sect, sect_id| {
439 const segname = sect.segname();
440 const sectname = sect.sectname();
443441
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;
442 switch (sect.sectionType()) {
443 macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS, macho.S_LITERAL_POINTERS => {
444 if (self.text_const_section_index != null) continue;
447445
448 self.text_section_index = @intCast(u16, text_seg.sections.items.len);
446 self.text_const_section_index = @intCast(u16, text_seg.sections.items.len);
449447 try text_seg.addSection(self.allocator, .{
450 .sectname = makeStaticString("__text"),
448 .sectname = makeStaticString("__const"),
451449 .segname = makeStaticString("__TEXT"),
452450 .addr = 0,
453451 .size = 0,
......@@ -455,70 +453,12 @@ fn updateMetadata(self: *Zld) !void {
455453 .@"align" = 0,
456454 .reloff = 0,
457455 .nreloc = 0,
458 .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
456 .flags = macho.S_REGULAR,
459457 .reserved1 = 0,
460458 .reserved2 = 0,
461459 .reserved3 = 0,
462460 });
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 }
461 continue;
522462 },
523463 macho.S_CSTRING_LITERALS => {
524464 if (self.cstring_section_index != null) continue;
......@@ -538,6 +478,7 @@ fn updateMetadata(self: *Zld) !void {
538478 .reserved2 = 0,
539479 .reserved3 = 0,
540480 });
481 continue;
541482 },
542483 macho.S_MOD_INIT_FUNC_POINTERS => {
543484 if (self.mod_init_func_section_index != null) continue;
......@@ -557,6 +498,7 @@ fn updateMetadata(self: *Zld) !void {
557498 .reserved2 = 0,
558499 .reserved3 = 0,
559500 });
501 continue;
560502 },
561503 macho.S_MOD_TERM_FUNC_POINTERS => {
562504 if (self.mod_term_func_section_index != null) continue;
......@@ -576,6 +518,7 @@ fn updateMetadata(self: *Zld) !void {
576518 .reserved2 = 0,
577519 .reserved3 = 0,
578520 });
521 continue;
579522 },
580523 macho.S_ZEROFILL => {
581524 if (mem.eql(u8, sectname, "__common")) {
......@@ -615,6 +558,7 @@ fn updateMetadata(self: *Zld) !void {
615558 .reserved3 = 0,
616559 });
617560 }
561 continue;
618562 },
619563 macho.S_THREAD_LOCAL_VARIABLES => {
620564 if (self.tlv_section_index != null) continue;
......@@ -634,6 +578,7 @@ fn updateMetadata(self: *Zld) !void {
634578 .reserved2 = 0,
635579 .reserved3 = 0,
636580 });
581 continue;
637582 },
638583 macho.S_THREAD_LOCAL_REGULAR => {
639584 if (self.tlv_data_section_index != null) continue;
......@@ -653,6 +598,7 @@ fn updateMetadata(self: *Zld) !void {
653598 .reserved2 = 0,
654599 .reserved3 = 0,
655600 });
601 continue;
656602 },
657603 macho.S_THREAD_LOCAL_ZEROFILL => {
658604 if (self.tlv_bss_section_index != null) continue;
......@@ -672,58 +618,185 @@ fn updateMetadata(self: *Zld) !void {
672618 .reserved2 = 0,
673619 .reserved3 = 0,
674620 });
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 });
683621 continue;
684622 },
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,
623 macho.S_COALESCED => {
624 if (mem.eql(u8, "__TEXT", segname) and mem.eql(u8, "__eh_frame", sectname)) {
625 log.debug("TODO __eh_frame section: type 0x{x}, name '{s},{s}'", .{
626 sect.flags(), segname, sectname,
689627 });
628 continue;
690629 }
691 continue;
692630 },
693 else => {
631 macho.S_REGULAR => {
632 if (sect.isCode()) {
633 if (self.text_section_index != null) continue;
634
635 self.text_section_index = @intCast(u16, text_seg.sections.items.len);
636 try text_seg.addSection(self.allocator, .{
637 .sectname = makeStaticString("__text"),
638 .segname = makeStaticString("__TEXT"),
639 .addr = 0,
640 .size = 0,
641 .offset = 0,
642 .@"align" = 0,
643 .reloff = 0,
644 .nreloc = 0,
645 .flags = macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS,
646 .reserved1 = 0,
647 .reserved2 = 0,
648 .reserved3 = 0,
649 });
650 continue;
651 }
652 if (sect.isDebug()) {
653 if (mem.eql(u8, "__LD", segname) and mem.eql(u8, "__compact_unwind", sectname)) {
654 log.debug("TODO compact unwind section: type 0x{x}, name '{s},{s}'", .{
655 sect.flags(), segname, sectname,
656 });
657 }
658 continue;
659 }
660
661 if (mem.eql(u8, segname, "__TEXT")) {
662 if (mem.eql(u8, sectname, "__ustring")) {
663 if (self.ustring_section_index != null) continue;
664
665 self.ustring_section_index = @intCast(u16, text_seg.sections.items.len);
666 try text_seg.addSection(self.allocator, .{
667 .sectname = makeStaticString("__ustring"),
668 .segname = makeStaticString("__TEXT"),
669 .addr = 0,
670 .size = 0,
671 .offset = 0,
672 .@"align" = 0,
673 .reloff = 0,
674 .nreloc = 0,
675 .flags = macho.S_REGULAR,
676 .reserved1 = 0,
677 .reserved2 = 0,
678 .reserved3 = 0,
679 });
680 } else {
681 if (self.text_const_section_index != null) continue;
682
683 self.text_const_section_index = @intCast(u16, text_seg.sections.items.len);
684 try text_seg.addSection(self.allocator, .{
685 .sectname = makeStaticString("__const"),
686 .segname = makeStaticString("__TEXT"),
687 .addr = 0,
688 .size = 0,
689 .offset = 0,
690 .@"align" = 0,
691 .reloff = 0,
692 .nreloc = 0,
693 .flags = macho.S_REGULAR,
694 .reserved1 = 0,
695 .reserved2 = 0,
696 .reserved3 = 0,
697 });
698 }
699 continue;
700 }
701
702 if (mem.eql(u8, segname, "__DATA_CONST")) {
703 if (self.data_const_section_index != null) continue;
704
705 self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);
706 try data_const_seg.addSection(self.allocator, .{
707 .sectname = makeStaticString("__const"),
708 .segname = makeStaticString("__DATA_CONST"),
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 continue;
721 }
722
723 if (mem.eql(u8, segname, "__DATA")) {
724 if (mem.eql(u8, sectname, "__const")) {
725 if (self.data_const_section_index != null) continue;
726
727 self.data_const_section_index = @intCast(u16, data_const_seg.sections.items.len);
728 try data_const_seg.addSection(self.allocator, .{
729 .sectname = makeStaticString("__const"),
730 .segname = makeStaticString("__DATA_CONST"),
731 .addr = 0,
732 .size = 0,
733 .offset = 0,
734 .@"align" = 0,
735 .reloff = 0,
736 .nreloc = 0,
737 .flags = macho.S_REGULAR,
738 .reserved1 = 0,
739 .reserved2 = 0,
740 .reserved3 = 0,
741 });
742 } else {
743 if (self.data_section_index != null) continue;
744
745 self.data_section_index = @intCast(u16, data_seg.sections.items.len);
746 try data_seg.addSection(self.allocator, .{
747 .sectname = makeStaticString("__data"),
748 .segname = makeStaticString("__DATA"),
749 .addr = 0,
750 .size = 0,
751 .offset = 0,
752 .@"align" = 0,
753 .reloff = 0,
754 .nreloc = 0,
755 .flags = macho.S_REGULAR,
756 .reserved1 = 0,
757 .reserved2 = 0,
758 .reserved3 = 0,
759 });
760 }
761
762 continue;
763 }
764
694765 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,
766 log.debug("TODO LLVM asm section: type 0x{x}, name '{s},{s}'", .{
767 sect.flags(), segname, sectname,
697768 });
698769 continue;
699770 }
700 log.err("unhandled section type 0x{x} for '{s},{s}'", .{ flags, segname, sectname });
701 return error.UnhandledSection;
702771 },
772 else => {},
703773 }
774
775 log.err("{s}: unhandled section type 0x{x} for '{s},{s}'", .{
776 object.name.?,
777 sect.flags(),
778 segname,
779 sectname,
780 });
781 return error.UnhandledSection;
704782 }
705783
706784 // Find ideal section alignment.
707 for (object_seg.sections.items) |source_sect| {
708 if (self.getMatchingSection(source_sect)) |res| {
785 for (object.sections.items) |sect| {
786 if (self.getMatchingSection(sect)) |res| {
709787 const target_seg = &self.load_commands.items[res.seg].Segment;
710788 const target_sect = &target_seg.sections.items[res.sect];
711 target_sect.@"align" = math.max(target_sect.@"align", source_sect.@"align");
789 target_sect.@"align" = math.max(target_sect.@"align", sect.inner.@"align");
712790 }
713791 }
714792
715793 // 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);
794 for (object.sections.items) |sect, sect_id| {
795 if (self.getMatchingSection(sect)) |res| {
796 try self.mapAndUpdateSections(object, @intCast(u16, sect_id), res.seg, res.sect);
720797 continue;
721798 }
722
723 log.debug("section '{s},{s}' will be unmapped", .{
724 parseName(&source_sect.segname),
725 parseName(&source_sect.sectname),
726 });
799 log.warn("section '{s},{s}' will be unmapped", .{ sect.segname(), sect.sectname() });
727800 }
728801 }
729802
......@@ -819,13 +892,13 @@ const MatchingSection = struct {
819892 sect: u16,
820893};
821894
822fn getMatchingSection(self: *Zld, section: macho.section_64) ?MatchingSection {
823 const segname = parseName(&section.segname);
824 const sectname = parseName(&section.sectname);
895fn getMatchingSection(self: *Zld, sect: Object.Section) ?MatchingSection {
896 const segname = sect.segname();
897 const sectname = sect.sectname();
825898
826899 const res: ?MatchingSection = blk: {
827 switch (section.flags) {
828 macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS => {
900 switch (sect.sectionType()) {
901 macho.S_4BYTE_LITERALS, macho.S_8BYTE_LITERALS, macho.S_16BYTE_LITERALS, macho.S_LITERAL_POINTERS => {
829902 break :blk .{
830903 .seg = self.text_segment_cmd_index.?,
831904 .sect = self.text_const_section_index.?,
......@@ -855,11 +928,12 @@ fn getMatchingSection(self: *Zld, section: macho.section_64) ?MatchingSection {
855928 .seg = self.data_segment_cmd_index.?,
856929 .sect = self.common_section_index.?,
857930 };
931 } else {
932 break :blk .{
933 .seg = self.data_segment_cmd_index.?,
934 .sect = self.bss_section_index.?,
935 };
858936 }
859 break :blk .{
860 .seg = self.data_segment_cmd_index.?,
861 .sect = self.bss_section_index.?,
862 };
863937 },
864938 macho.S_THREAD_LOCAL_VARIABLES => {
865939 break :blk .{
......@@ -879,31 +953,43 @@ fn getMatchingSection(self: *Zld, section: macho.section_64) ?MatchingSection {
879953 .sect = self.tlv_bss_section_index.?,
880954 };
881955 },
882 macho.S_REGULAR | macho.S_ATTR_PURE_INSTRUCTIONS | macho.S_ATTR_SOME_INSTRUCTIONS => {
883 break :blk .{
884 .seg = self.text_segment_cmd_index.?,
885 .sect = self.text_section_index.?,
886 };
956 macho.S_COALESCED => {
957 // TODO coalesced sections
958 break :blk null;
887959 },
888960 macho.S_REGULAR => {
961 if (sect.isCode()) {
962 break :blk .{
963 .seg = self.text_segment_cmd_index.?,
964 .sect = self.text_section_index.?,
965 };
966 }
967 if (sect.isDebug()) {
968 // TODO debug attributes
969 break :blk null;
970 }
971
889972 if (mem.eql(u8, segname, "__TEXT")) {
890973 if (mem.eql(u8, sectname, "__ustring")) {
891974 break :blk .{
892975 .seg = self.text_segment_cmd_index.?,
893976 .sect = self.ustring_section_index.?,
894977 };
978 } else {
979 break :blk .{
980 .seg = self.text_segment_cmd_index.?,
981 .sect = self.text_const_section_index.?,
982 };
895983 }
896 break :blk .{
897 .seg = self.text_segment_cmd_index.?,
898 .sect = self.text_const_section_index.?,
899 };
900984 }
985
901986 if (mem.eql(u8, segname, "__DATA_CONST")) {
902987 break :blk .{
903988 .seg = self.data_const_segment_cmd_index.?,
904989 .sect = self.data_const_section_index.?,
905990 };
906991 }
992
907993 if (mem.eql(u8, segname, "__DATA")) {
908994 if (mem.eql(u8, sectname, "__const")) {
909995 break :blk .{
......@@ -916,11 +1002,10 @@ fn getMatchingSection(self: *Zld, section: macho.section_64) ?MatchingSection {
9161002 .sect = self.data_section_index.?,
9171003 };
9181004 }
1005
9191006 break :blk null;
9201007 },
921 else => {
922 break :blk null;
923 },
1008 else => break :blk null,
9241009 }
9251010 };
9261011