authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-12-05 22:20:13+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-12-05 22:46:53+01:00
log397a11c107f3ac75bdcbafa2f410ba22f3016b60
tree99a29f8165516a00032d4def2a83b9d66436f999
parentc86f2402d077077489154a14af73ff5616722036

macho: sort sections when linking stage1 binary


1 files changed, 155 insertions(+), 0 deletions(-)

src/link/MachO.zig+155
...@@ -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();
921921
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}
48514852
4853fn 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
4852fn updateSectionOrdinals(self: *MachO) !void {5007fn updateSectionOrdinals(self: *MachO) !void {
4853 if (!self.sections_order_dirty) return;5008 if (!self.sections_order_dirty) return;
48545009