authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-09-06 17:43:24+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-09-06 17:43:24+02:00
log81e5320973e8cffd585f240b20321e6afc15e8f9
tree29aa5bd951549b135cea233fe8ed3bd8997a6170
parent29d2e19c3ea50c9caec036b52e978297a04bb969

macho: set and reset file offset to zerofill sections in flush

This way, there's no need to special the set/reset behaviour at every stage of updating sections/atoms.

1 files changed, 49 insertions(+), 57 deletions(-)

src/link/MachO.zig+49-57
...@@ -133,8 +133,8 @@ objc_selrefs_section_index: ?u16 = null,...@@ -133,8 +133,8 @@ objc_selrefs_section_index: ?u16 = null,
133objc_classrefs_section_index: ?u16 = null,133objc_classrefs_section_index: ?u16 = null,
134objc_data_section_index: ?u16 = null,134objc_data_section_index: ?u16 = null,
135135
136bss_file_offset: ?u32 = null,136bss_file_offset: u32 = 0,
137tlv_bss_file_offset: ?u32 = null,137tlv_bss_file_offset: u32 = 0,
138138
139locals: std.ArrayListUnmanaged(macho.nlist_64) = .{},139locals: std.ArrayListUnmanaged(macho.nlist_64) = .{},
140globals: std.ArrayListUnmanaged(macho.nlist_64) = .{},140globals: std.ArrayListUnmanaged(macho.nlist_64) = .{},
...@@ -749,6 +749,17 @@ pub fn flush(self: *MachO, comp: *Compilation) !void {...@@ -749,6 +749,17 @@ pub fn flush(self: *MachO, comp: *Compilation) !void {
749 try self.parseInputFiles(positionals.items, self.base.options.sysroot);749 try self.parseInputFiles(positionals.items, self.base.options.sysroot);
750 try self.parseLibs(libs.items, self.base.options.sysroot);750 try self.parseLibs(libs.items, self.base.options.sysroot);
751751
752 if (self.bss_section_index) |idx| {
753 const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
754 const sect = &seg.sections.items[idx];
755 sect.offset = self.bss_file_offset;
756 }
757 if (self.tlv_bss_section_index) |idx| {
758 const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
759 const sect = &seg.sections.items[idx];
760 sect.offset = self.tlv_bss_file_offset;
761 }
762
752 try self.resolveSymbols();763 try self.resolveSymbols();
753 try self.addRpathLCs(rpath_table.keys());764 try self.addRpathLCs(rpath_table.keys());
754 try self.addLoadDylibLCs();765 try self.addLoadDylibLCs();
...@@ -781,6 +792,20 @@ pub fn flush(self: *MachO, comp: *Compilation) !void {...@@ -781,6 +792,20 @@ pub fn flush(self: *MachO, comp: *Compilation) !void {
781 }792 }
782 }793 }
783 try self.writeAtoms();794 try self.writeAtoms();
795
796 if (self.bss_section_index) |idx| {
797 const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
798 const sect = &seg.sections.items[idx];
799 self.bss_file_offset = sect.offset;
800 sect.offset = 0;
801 }
802 if (self.tlv_bss_section_index) |idx| {
803 const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
804 const sect = &seg.sections.items[idx];
805 self.tlv_bss_file_offset = sect.offset;
806 sect.offset = 0;
807 }
808
784 try self.flushModule(comp);809 try self.flushModule(comp);
785 }810 }
786811
...@@ -1687,8 +1712,7 @@ pub fn writeAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !void {...@@ -1687,8 +1712,7 @@ pub fn writeAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !void {
1687 const seg = self.load_commands.items[match.seg].Segment;1712 const seg = self.load_commands.items[match.seg].Segment;
1688 const sect = seg.sections.items[match.sect];1713 const sect = seg.sections.items[match.sect];
1689 const sym = self.locals.items[atom.local_sym_index];1714 const sym = self.locals.items[atom.local_sym_index];
1690 const sect_offset = self.getPtrToSectionOffset(match).*;1715 const file_offset = sect.offset + sym.n_value - sect.addr;
1691 const file_offset = sect_offset + sym.n_value - sect.addr;
1692 try atom.resolveRelocs(self);1716 try atom.resolveRelocs(self);
1693 log.debug("writing atom for symbol {s} at file offset 0x{x}", .{ self.getString(sym.n_strx), file_offset });1717 log.debug("writing atom for symbol {s} at file offset 0x{x}", .{ self.getString(sym.n_strx), file_offset });
1694 try self.base.file.?.pwriteAll(atom.code.items, file_offset);1718 try self.base.file.?.pwriteAll(atom.code.items, file_offset);
...@@ -3469,13 +3493,9 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -3469,13 +3493,9 @@ pub fn populateMissingMetadata(self: *MachO) !void {
3469 .flags = macho.S_THREAD_LOCAL_ZEROFILL,3493 .flags = macho.S_THREAD_LOCAL_ZEROFILL,
3470 },3494 },
3471 );3495 );
34723496 const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
3473 // We keep offset to the section in a separate variable as the actual section is usually pointing at the3497 const sect = seg.sections.items[self.tlv_bss_section_index.?];
3474 // beginning of the file.3498 self.tlv_bss_file_offset = sect.offset;
3475 const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
3476 const out_sect = &seg.sections.items[self.tlv_bss_section_index.?];
3477 self.tlv_bss_file_offset = out_sect.offset;
3478 out_sect.offset = 0;
3479 }3499 }
34803500
3481 if (self.bss_section_index == null) {3501 if (self.bss_section_index == null) {
...@@ -3490,13 +3510,9 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -3490,13 +3510,9 @@ pub fn populateMissingMetadata(self: *MachO) !void {
3490 .flags = macho.S_ZEROFILL,3510 .flags = macho.S_ZEROFILL,
3491 },3511 },
3492 );3512 );
34933513 const seg = self.load_commands.items[self.data_segment_cmd_index.?].Segment;
3494 // We keep offset to the section in a separate variable as the actual section is usually pointing at the3514 const sect = seg.sections.items[self.bss_section_index.?];
3495 // beginning of the file.3515 self.bss_file_offset = sect.offset;
3496 const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
3497 const out_sect = &seg.sections.items[self.bss_section_index.?];
3498 self.bss_file_offset = out_sect.offset;
3499 out_sect.offset = 0;
3500 }3516 }
35013517
3502 if (self.linkedit_segment_cmd_index == null) {3518 if (self.linkedit_segment_cmd_index == null) {
...@@ -3767,8 +3783,7 @@ fn growSection(self: *MachO, match: MatchingSection, new_size: u32) !void {...@@ -3767,8 +3783,7 @@ fn growSection(self: *MachO, match: MatchingSection, new_size: u32) !void {
3767 const sect = &seg.sections.items[match.sect];3783 const sect = &seg.sections.items[match.sect];
37683784
3769 const alignment = try math.powi(u32, 2, sect.@"align");3785 const alignment = try math.powi(u32, 2, sect.@"align");
3770 const sect_offset = self.getPtrToSectionOffset(match);3786 const max_size = self.allocatedSize(match.seg, sect.offset);
3771 const max_size = self.allocatedSize(match.seg, sect_offset.*);
3772 const ideal_size = padToIdeal(new_size);3787 const ideal_size = padToIdeal(new_size);
3773 const needed_size = mem.alignForwardGeneric(u32, ideal_size, alignment);3788 const needed_size = mem.alignForwardGeneric(u32, ideal_size, alignment);
37743789
...@@ -3830,24 +3845,22 @@ fn growSection(self: *MachO, match: MatchingSection, new_size: u32) !void {...@@ -3830,24 +3845,22 @@ fn growSection(self: *MachO, match: MatchingSection, new_size: u32) !void {
3830 });3845 });
38313846
3832 for (next_seg.sections.items) |*moved_sect, moved_sect_id| {3847 for (next_seg.sections.items) |*moved_sect, moved_sect_id| {
3833 const moved_match = MatchingSection{3848 moved_sect.offset += @intCast(u32, seg_offset_amt);
3834 .seg = @intCast(u16, next),
3835 .sect = @intCast(u16, moved_sect_id),
3836 };
3837 const ptr_sect_offset = self.getPtrToSectionOffset(moved_match);
3838 ptr_sect_offset.* += @intCast(u32, seg_offset_amt);
3839 moved_sect.addr += seg_offset_amt;3849 moved_sect.addr += seg_offset_amt;
38403850
3841 log.warn(" (new {s},{s} file offsets from 0x{x} to 0x{x} (in memory 0x{x} to 0x{x}))", .{3851 log.warn(" (new {s},{s} file offsets from 0x{x} to 0x{x} (in memory 0x{x} to 0x{x}))", .{
3842 commands.segmentName(moved_sect.*),3852 commands.segmentName(moved_sect.*),
3843 commands.sectionName(moved_sect.*),3853 commands.sectionName(moved_sect.*),
3844 ptr_sect_offset.*,3854 moved_sect.offset,
3845 ptr_sect_offset.* + moved_sect.size,3855 moved_sect.offset + moved_sect.size,
3846 moved_sect.addr,3856 moved_sect.addr,
3847 moved_sect.addr + moved_sect.size,3857 moved_sect.addr + moved_sect.size,
3848 });3858 });
38493859
3850 try self.allocateLocalSymbols(moved_match, @intCast(i64, seg_offset_amt));3860 try self.allocateLocalSymbols(.{
3861 .seg = @intCast(u16, next),
3862 .sect = @intCast(u16, moved_sect_id),
3863 }, @intCast(i64, seg_offset_amt));
3851 }3864 }
3852 }3865 }
3853 }3866 }
...@@ -3867,25 +3880,23 @@ fn growSection(self: *MachO, match: MatchingSection, new_size: u32) !void {...@@ -3867,25 +3880,23 @@ fn growSection(self: *MachO, match: MatchingSection, new_size: u32) !void {
38673880
3868 var next = match.sect + 1;3881 var next = match.sect + 1;
3869 while (next < seg.sections.items.len) : (next += 1) {3882 while (next < seg.sections.items.len) : (next += 1) {
3870 const moved_match = MatchingSection{
3871 .seg = match.seg,
3872 .sect = next,
3873 };
3874 const moved_sect = &seg.sections.items[next];3883 const moved_sect = &seg.sections.items[next];
3875 const ptr_sect_offset = self.getPtrToSectionOffset(moved_match);3884 moved_sect.offset += @intCast(u32, offset_amt);
3876 ptr_sect_offset.* += @intCast(u32, offset_amt);
3877 moved_sect.addr += offset_amt;3885 moved_sect.addr += offset_amt;
38783886
3879 log.warn(" (new {s},{s} file offsets from 0x{x} to 0x{x} (in memory 0x{x} to 0x{x}))", .{3887 log.warn(" (new {s},{s} file offsets from 0x{x} to 0x{x} (in memory 0x{x} to 0x{x}))", .{
3880 commands.segmentName(moved_sect.*),3888 commands.segmentName(moved_sect.*),
3881 commands.sectionName(moved_sect.*),3889 commands.sectionName(moved_sect.*),
3882 ptr_sect_offset.*,3890 moved_sect.offset,
3883 ptr_sect_offset.* + moved_sect.size,3891 moved_sect.offset + moved_sect.size,
3884 moved_sect.addr,3892 moved_sect.addr,
3885 moved_sect.addr + moved_sect.size,3893 moved_sect.addr + moved_sect.size,
3886 });3894 });
38873895
3888 try self.allocateLocalSymbols(moved_match, @intCast(i64, offset_amt));3896 try self.allocateLocalSymbols(.{
3897 .seg = match.seg,
3898 .sect = next,
3899 }, @intCast(i64, offset_amt));
3889 }3900 }
3890 }3901 }
38913902
...@@ -3916,25 +3927,6 @@ fn getSectionMaxAlignment(self: *MachO, segment_id: u16, start_sect_id: u16) !u3...@@ -3916,25 +3927,6 @@ fn getSectionMaxAlignment(self: *MachO, segment_id: u16, start_sect_id: u16) !u3
3916 return max_alignment;3927 return max_alignment;
3917}3928}
39183929
3919fn getPtrToSectionOffset(self: *MachO, match: MatchingSection) *u32 {
3920 if (self.data_segment_cmd_index.? == match.seg) {
3921 if (self.bss_section_index) |idx| {
3922 if (idx == match.sect) {
3923 return &self.bss_file_offset.?;
3924 }
3925 }
3926 if (self.tlv_bss_section_index) |idx| {
3927 if (idx == match.sect) {
3928 return &self.tlv_bss_file_offset.?;
3929 }
3930 }
3931 }
3932
3933 const seg = &self.load_commands.items[match.seg].Segment;
3934 const sect = &seg.sections.items[match.sect];
3935 return &sect.offset;
3936}
3937
3938fn allocateTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 {3930fn allocateTextBlock(self: *MachO, text_block: *TextBlock, new_block_size: u64, alignment: u64) !u64 {
3939 const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;3931 const text_segment = &self.load_commands.items[self.text_segment_cmd_index.?].Segment;
3940 const text_section = &text_segment.sections.items[self.text_section_index.?];3932 const text_section = &text_segment.sections.items[self.text_section_index.?];