| ... | ... | @@ -920,6 +920,7 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void { |
| 920 | 920 | try self.parseObjectsIntoAtoms(); |
| 921 | 921 | |
| 922 | 922 | if (use_stage1) { |
| 923 | try self.sortSections(); |
| 923 | 924 | try self.allocateTextSegment(); |
| 924 | 925 | try self.allocateDataConstSegment(); |
| 925 | 926 | try self.allocateDataSegment(); |
| ... | ... | @@ -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 | 5007 | fn updateSectionOrdinals(self: *MachO) !void { |
| 4853 | 5008 | if (!self.sections_order_dirty) return; |
| 4854 | 5009 | |