authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-08-27 13:47:43+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-08-27 13:47:43+02:00
logad4a8e76654cbb6cab8b2de49a3b83c941bb26c7
treeae55b2114a8b17effae109d9711035fa670641ad
parent1e65d41a659894eed6beb92ae89ca531f6f9dfd0

macho: keep actual file offset for zerofill sections separately

This way, we will conform to the standard practice of setting the offset within the section header to the beginning of the file and we will be able to track the location of the section in the file for incremental updates.

1 files changed, 55 insertions(+), 19 deletions(-)

src/link/MachO.zig+55-19
......@@ -133,6 +133,9 @@ objc_selrefs_section_index: ?u16 = null,
133133objc_classrefs_section_index: ?u16 = null,
134134objc_data_section_index: ?u16 = null,
135135
136bss_file_offset: ?u64 = null,
137tlv_bss_file_offset: ?u64 = null,
138
136139locals: std.ArrayListUnmanaged(macho.nlist_64) = .{},
137140globals: std.ArrayListUnmanaged(macho.nlist_64) = .{},
138141undefs: std.ArrayListUnmanaged(macho.nlist_64) = .{},
......@@ -1714,11 +1717,30 @@ fn allocateSegment(self: *MachO, index: u16, offset: u64) !void {
17141717
17151718 // Allocate the sections according to their alignment at the beginning of the segment.
17161719 var start: u64 = offset;
1717 for (seg.sections.items) |*sect| {
1720 for (seg.sections.items) |*sect, sect_id| {
17181721 const alignment = try math.powi(u32, 2, sect.@"align");
17191722 const start_aligned = mem.alignForwardGeneric(u64, start, alignment);
17201723 const end_aligned = mem.alignForwardGeneric(u64, start_aligned + sect.size, alignment);
1721 sect.offset = @intCast(u32, seg.inner.fileoff + start_aligned);
1724 const file_offset = @intCast(u32, seg.inner.fileoff + start_aligned);
1725
1726 blk: {
1727 if (index == self.data_segment_cmd_index.?) {
1728 if (self.bss_section_index) |idx| {
1729 if (sect_id == idx) {
1730 self.bss_file_offset = file_offset;
1731 break :blk;
1732 }
1733 }
1734 if (self.tlv_bss_section_index) |idx| {
1735 if (sect_id == idx) {
1736 self.tlv_bss_file_offset = file_offset;
1737 break :blk;
1738 }
1739 }
1740 }
1741 sect.offset = @intCast(u32, seg.inner.fileoff + start_aligned);
1742 }
1743
17221744 sect.addr = seg.inner.vmaddr + start_aligned;
17231745 start = end_aligned;
17241746 }
......@@ -1821,6 +1843,18 @@ fn writeTextBlocks(self: *MachO) !void {
18211843 var code = try self.base.allocator.alloc(u8, sect.size);
18221844 defer self.base.allocator.free(code);
18231845
1846 const file_offset: u64 = blk: {
1847 if (self.data_segment_cmd_index.? == match.seg) {
1848 if (self.bss_section_index) |idx| {
1849 if (idx == match.sect) break :blk self.bss_file_offset.?;
1850 }
1851 if (self.tlv_bss_section_index) |idx| {
1852 if (idx == match.sect) break :blk self.tlv_bss_file_offset.?;
1853 }
1854 }
1855 break :blk sect.offset;
1856 };
1857
18241858 if (sect_type == macho.S_ZEROFILL or sect_type == macho.S_THREAD_LOCAL_ZEROFILL) {
18251859 mem.set(u8, code, 0);
18261860 } else {
......@@ -1856,7 +1890,7 @@ fn writeTextBlocks(self: *MachO) !void {
18561890 mem.set(u8, code[base_off..], 0);
18571891 }
18581892
1859 try self.base.file.?.pwriteAll(code, sect.offset);
1893 try self.base.file.?.pwriteAll(code, file_offset);
18601894 }
18611895}
18621896
......@@ -1925,7 +1959,18 @@ pub fn writeAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !void {
19251959 const seg = self.load_commands.items[match.seg].Segment;
19261960 const sect = seg.sections.items[match.sect];
19271961 const sym = self.locals.items[atom.local_sym_index];
1928 const file_offset = sect.offset + sym.n_value - sect.addr;
1962 const sect_offset: u64 = blk: {
1963 if (self.data_segment_cmd_index.? == match.seg) {
1964 if (self.bss_section_index) |idx| {
1965 if (idx == match.sect) break :blk self.bss_file_offset.?;
1966 }
1967 if (self.tlv_bss_section_index) |idx| {
1968 if (idx == match.sect) break :blk self.tlv_bss_file_offset.?;
1969 }
1970 }
1971 break :blk sect.offset;
1972 };
1973 const file_offset = sect_offset + sym.n_value - sect.addr;
19291974 try atom.resolveRelocs(self);
19301975 log.debug("writing atom for symbol {s} at file offset 0x{x}", .{ self.getString(sym.n_strx), file_offset });
19311976 try self.base.file.?.pwriteAll(atom.code.items, file_offset);
......@@ -2873,19 +2918,6 @@ fn addLoadDylibLCs(self: *MachO) !void {
28732918
28742919fn flushZld(self: *MachO) !void {
28752920 try self.writeTextBlocks();
2876
2877 // if (self.bss_section_index) |index| {
2878 // const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
2879 // const sect = &seg.sections.items[index];
2880 // sect.offset = 0;
2881 // }
2882
2883 // if (self.tlv_bss_section_index) |index| {
2884 // const seg = &self.load_commands.items[self.data_segment_cmd_index.?].Segment;
2885 // const sect = &seg.sections.items[index];
2886 // sect.offset = 0;
2887 // }
2888
28892921 try self.setEntryPoint();
28902922 try self.writeRebaseInfoTableZld();
28912923 try self.writeBindInfoTableZld();
......@@ -4203,10 +4235,12 @@ pub fn populateMissingMetadata(self: *MachO) !void {
42034235
42044236 log.debug("found __thread_bss section free space 0x{x} to 0x{x}", .{ off, off + needed_size });
42054237
4238 // We keep offset to the section in a separate variable as the actual section is usually pointing at the
4239 // beginning of the file.
4240 self.tlv_bss_file_offset = off;
42064241 try data_segment.addSection(self.base.allocator, "__thread_bss", .{
42074242 .addr = data_segment.inner.vmaddr + off - data_segment.inner.fileoff,
42084243 .size = needed_size,
4209 .offset = @intCast(u32, off),
42104244 .@"align" = 3, // 2^3 = @sizeOf(u64)
42114245 .flags = macho.S_THREAD_LOCAL_ZEROFILL,
42124246 });
......@@ -4229,10 +4263,12 @@ pub fn populateMissingMetadata(self: *MachO) !void {
42294263
42304264 log.debug("found __bss section free space 0x{x} to 0x{x}", .{ off, off + needed_size });
42314265
4266 // We keep offset to the section in a separate variable as the actual section is usually pointing at the
4267 // beginning of the file.
4268 self.bss_file_offset = off;
42324269 try data_segment.addSection(self.base.allocator, "__bss", .{
42334270 .addr = data_segment.inner.vmaddr + off - data_segment.inner.fileoff,
42344271 .size = 0,
4235 .offset = @intCast(u32, off),
42364272 .@"align" = 3, // 2^3 = @sizeOf(u64)
42374273 .flags = macho.S_ZEROFILL,
42384274 });