| ... | @@ -920,6 +920,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { | ... | @@ -920,6 +920,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { |
| 920 | try self.parseObjectsIntoAtoms(); | 920 | try self.parseObjectsIntoAtoms(); |
| 921 | | 921 | |
| 922 | if (use_stage1) { | 922 | if (use_stage1) { |
| | 923 | try self.sortSections(); |
| 923 | try self.allocateTextSegment(); | 924 | try self.allocateTextSegment(); |
| 924 | try self.allocateDataConstSegment(); | 925 | try self.allocateDataConstSegment(); |
| 925 | try self.allocateDataSegment(); | 926 | try self.allocateDataSegment(); |
| ... | @@ -4849,6 +4850,160 @@ fn nextSegmentAddressAndOffset(self: *MachO) NextSegmentAddressAndOffset { | ... | @@ -4849,6 +4850,160 @@ fn nextSegmentAddressAndOffset(self: *MachO) NextSegmentAddressAndOffset { |
| 4849 | }; | 4850 | }; |
| 4850 | } | 4851 | } |
| 4851 | | 4852 | |
| | 4853 | fn sortSections(self: *MachO) !void { |
| | 4854 | var text_index_mapping = std.AutoHashMap(u16, u16).init(self.base.allocator); |
| | 4855 | defer text_index_mapping.deinit(); |
| | 4856 | var data_const_index_mapping = std.AutoHashMap(u16, u16).init(self.base.allocator); |
| | 4857 | defer data_const_index_mapping.deinit(); |
| | 4858 | var data_index_mapping = std.AutoHashMap(u16, u16).init(self.base.allocator); |
| | 4859 | defer data_index_mapping.deinit(); |
| | 4860 | |
| | 4861 | { |
| | 4862 | // __TEXT segment |
| | 4863 | const seg = &self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| | 4864 | var sections = seg.sections.toOwnedSlice(self.base.allocator); |
| | 4865 | defer self.base.allocator.free(sections); |
| | 4866 | try seg.sections.ensureTotalCapacity(self.base.allocator, sections.len); |
| | 4867 | |
| | 4868 | const indices = &[_]*?u16{ |
| | 4869 | &self.text_section_index, |
| | 4870 | &self.stubs_section_index, |
| | 4871 | &self.stub_helper_section_index, |
| | 4872 | &self.gcc_except_tab_section_index, |
| | 4873 | &self.cstring_section_index, |
| | 4874 | &self.ustring_section_index, |
| | 4875 | &self.text_const_section_index, |
| | 4876 | &self.objc_methlist_section_index, |
| | 4877 | &self.objc_methname_section_index, |
| | 4878 | &self.objc_methtype_section_index, |
| | 4879 | &self.objc_classname_section_index, |
| | 4880 | &self.eh_frame_section_index, |
| | 4881 | }; |
| | 4882 | for (indices) |maybe_index| { |
| | 4883 | const new_index: u16 = if (maybe_index.*) |index| blk: { |
| | 4884 | const idx = @intCast(u16, seg.sections.items.len); |
| | 4885 | seg.sections.appendAssumeCapacity(sections[index]); |
| | 4886 | try text_index_mapping.putNoClobber(index, idx); |
| | 4887 | break :blk idx; |
| | 4888 | } else continue; |
| | 4889 | maybe_index.* = new_index; |
| | 4890 | } |
| | 4891 | } |
| | 4892 | |
| | 4893 | { |
| | 4894 | // __DATA_CONST segment |
| | 4895 | const seg = &self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; |
| | 4896 | var sections = seg.sections.toOwnedSlice(self.base.allocator); |
| | 4897 | defer self.base.allocator.free(sections); |
| | 4898 | try seg.sections.ensureTotalCapacity(self.base.allocator, sections.len); |
| | 4899 | |
| | 4900 | const indices = &[_]*?u16{ |
| | 4901 | &self.got_section_index, |
| | 4902 | &self.mod_init_func_section_index, |
| | 4903 | &self.mod_term_func_section_index, |
| | 4904 | &self.data_const_section_index, |
| | 4905 | &self.objc_cfstring_section_index, |
| | 4906 | &self.objc_classlist_section_index, |
| | 4907 | &self.objc_imageinfo_section_index, |
| | 4908 | }; |
| | 4909 | for (indices) |maybe_index| { |
| | 4910 | const new_index: u16 = if (maybe_index.*) |index| blk: { |
| | 4911 | const idx = @intCast(u16, seg.sections.items.len); |
| | 4912 | seg.sections.appendAssumeCapacity(sections[index]); |
| | 4913 | try data_const_index_mapping.putNoClobber(index, idx); |
| | 4914 | break :blk idx; |
| | 4915 | } else continue; |
| | 4916 | maybe_index.* = new_index; |
| | 4917 | } |
| | 4918 | } |
| | 4919 | |
| | 4920 | { |
| | 4921 | // __DATA segment |
| | 4922 | const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| | 4923 | var sections = seg.sections.toOwnedSlice(self.base.allocator); |
| | 4924 | defer self.base.allocator.free(sections); |
| | 4925 | try seg.sections.ensureTotalCapacity(self.base.allocator, sections.len); |
| | 4926 | |
| | 4927 | // __DATA segment |
| | 4928 | const indices = &[_]*?u16{ |
| | 4929 | &self.la_symbol_ptr_section_index, |
| | 4930 | &self.objc_const_section_index, |
| | 4931 | &self.objc_selrefs_section_index, |
| | 4932 | &self.objc_classrefs_section_index, |
| | 4933 | &self.objc_data_section_index, |
| | 4934 | &self.data_section_index, |
| | 4935 | &self.tlv_section_index, |
| | 4936 | &self.tlv_data_section_index, |
| | 4937 | &self.tlv_bss_section_index, |
| | 4938 | &self.bss_section_index, |
| | 4939 | }; |
| | 4940 | for (indices) |maybe_index| { |
| | 4941 | const new_index: u16 = if (maybe_index.*) |index| blk: { |
| | 4942 | const idx = @intCast(u16, seg.sections.items.len); |
| | 4943 | seg.sections.appendAssumeCapacity(sections[index]); |
| | 4944 | try data_index_mapping.putNoClobber(index, idx); |
| | 4945 | break :blk idx; |
| | 4946 | } else continue; |
| | 4947 | maybe_index.* = new_index; |
| | 4948 | } |
| | 4949 | } |
| | 4950 | |
| | 4951 | { |
| | 4952 | var transient: std.AutoHashMapUnmanaged(MatchingSection, *Atom) = .{}; |
| | 4953 | try transient.ensureTotalCapacity(self.base.allocator, self.atoms.count()); |
| | 4954 | |
| | 4955 | var it = self.atoms.iterator(); |
| | 4956 | while (it.next()) |entry| { |
| | 4957 | const old = entry.key_ptr.*; |
| | 4958 | const sect = if (old.seg == self.text_segment_cmd_index.?) |
| | 4959 | text_index_mapping.get(old.sect).? |
| | 4960 | else if (old.seg == self.data_const_segment_cmd_index.?) |
| | 4961 | data_const_index_mapping.get(old.sect).? |
| | 4962 | else |
| | 4963 | data_index_mapping.get(old.sect).?; |
| | 4964 | transient.putAssumeCapacityNoClobber(.{ |
| | 4965 | .seg = old.seg, |
| | 4966 | .sect = sect, |
| | 4967 | }, entry.value_ptr.*); |
| | 4968 | } |
| | 4969 | |
| | 4970 | self.atoms.clearAndFree(self.base.allocator); |
| | 4971 | self.atoms.deinit(self.base.allocator); |
| | 4972 | self.atoms = transient; |
| | 4973 | } |
| | 4974 | |
| | 4975 | { |
| | 4976 | // Create new section ordinals. |
| | 4977 | self.section_ordinals.clearRetainingCapacity(); |
| | 4978 | const text_seg = self.load_commands.items[self.text_segment_cmd_index.?].Segment; |
| | 4979 | for (text_seg.sections.items) |_, sect_id| { |
| | 4980 | const res = self.section_ordinals.getOrPutAssumeCapacity(.{ |
| | 4981 | .seg = self.text_segment_cmd_index.?, |
| | 4982 | .sect = @intCast(u16, sect_id), |
| | 4983 | }); |
| | 4984 | assert(!res.found_existing); |
| | 4985 | } |
| | 4986 | const data_const_seg = self.load_commands.items[self.data_const_segment_cmd_index.?].Segment; |
| | 4987 | for (data_const_seg.sections.items) |_, sect_id| { |
| | 4988 | const res = self.section_ordinals.getOrPutAssumeCapacity(.{ |
| | 4989 | .seg = self.data_const_segment_cmd_index.?, |
| | 4990 | .sect = @intCast(u16, sect_id), |
| | 4991 | }); |
| | 4992 | assert(!res.found_existing); |
| | 4993 | } |
| | 4994 | const data_seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment; |
| | 4995 | for (data_seg.sections.items) |_, sect_id| { |
| | 4996 | const res = self.section_ordinals.getOrPutAssumeCapacity(.{ |
| | 4997 | .seg = self.data_segment_cmd_index.?, |
| | 4998 | .sect = @intCast(u16, sect_id), |
| | 4999 | }); |
| | 5000 | assert(!res.found_existing); |
| | 5001 | } |
| | 5002 | } |
| | 5003 | |
| | 5004 | self.sections_order_dirty = false; |
| | 5005 | } |
| | 5006 | |
| 4852 | fn updateSectionOrdinals(self: *MachO) !void { | 5007 | fn updateSectionOrdinals(self: *MachO) !void { |
| 4853 | if (!self.sections_order_dirty) return; | 5008 | if (!self.sections_order_dirty) return; |
| 4854 | | 5009 | |