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,...@@ -133,6 +133,9 @@ 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: ?u64 = null,
137tlv_bss_file_offset: ?u64 = null,
138
136locals: std.ArrayListUnmanaged(macho.nlist_64) = .{},139locals: std.ArrayListUnmanaged(macho.nlist_64) = .{},
137globals: std.ArrayListUnmanaged(macho.nlist_64) = .{},140globals: std.ArrayListUnmanaged(macho.nlist_64) = .{},
138undefs: std.ArrayListUnmanaged(macho.nlist_64) = .{},141undefs: std.ArrayListUnmanaged(macho.nlist_64) = .{},
...@@ -1714,11 +1717,30 @@ fn allocateSegment(self: *MachO, index: u16, offset: u64) !void {...@@ -1714,11 +1717,30 @@ fn allocateSegment(self: *MachO, index: u16, offset: u64) !void {
17141717
1715 // Allocate the sections according to their alignment at the beginning of the segment.1718 // Allocate the sections according to their alignment at the beginning of the segment.
1716 var start: u64 = offset;1719 var start: u64 = offset;
1717 for (seg.sections.items) |*sect| {1720 for (seg.sections.items) |*sect, sect_id| {
1718 const alignment = try math.powi(u32, 2, sect.@"align");1721 const alignment = try math.powi(u32, 2, sect.@"align");
1719 const start_aligned = mem.alignForwardGeneric(u64, start, alignment);1722 const start_aligned = mem.alignForwardGeneric(u64, start, alignment);
1720 const end_aligned = mem.alignForwardGeneric(u64, start_aligned + sect.size, alignment);1723 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
1722 sect.addr = seg.inner.vmaddr + start_aligned;1744 sect.addr = seg.inner.vmaddr + start_aligned;
1723 start = end_aligned;1745 start = end_aligned;
1724 }1746 }
...@@ -1821,6 +1843,18 @@ fn writeTextBlocks(self: *MachO) !void {...@@ -1821,6 +1843,18 @@ fn writeTextBlocks(self: *MachO) !void {
1821 var code = try self.base.allocator.alloc(u8, sect.size);1843 var code = try self.base.allocator.alloc(u8, sect.size);
1822 defer self.base.allocator.free(code);1844 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
1824 if (sect_type == macho.S_ZEROFILL or sect_type == macho.S_THREAD_LOCAL_ZEROFILL) {1858 if (sect_type == macho.S_ZEROFILL or sect_type == macho.S_THREAD_LOCAL_ZEROFILL) {
1825 mem.set(u8, code, 0);1859 mem.set(u8, code, 0);
1826 } else {1860 } else {
...@@ -1856,7 +1890,7 @@ fn writeTextBlocks(self: *MachO) !void {...@@ -1856,7 +1890,7 @@ fn writeTextBlocks(self: *MachO) !void {
1856 mem.set(u8, code[base_off..], 0);1890 mem.set(u8, code[base_off..], 0);
1857 }1891 }
18581892
1859 try self.base.file.?.pwriteAll(code, sect.offset);1893 try self.base.file.?.pwriteAll(code, file_offset);
1860 }1894 }
1861}1895}
18621896
...@@ -1925,7 +1959,18 @@ pub fn writeAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !void {...@@ -1925,7 +1959,18 @@ pub fn writeAtom(self: *MachO, atom: *TextBlock, match: MatchingSection) !void {
1925 const seg = self.load_commands.items[match.seg].Segment;1959 const seg = self.load_commands.items[match.seg].Segment;
1926 const sect = seg.sections.items[match.sect];1960 const sect = seg.sections.items[match.sect];
1927 const sym = self.locals.items[atom.local_sym_index];1961 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;
1929 try atom.resolveRelocs(self);1974 try atom.resolveRelocs(self);
1930 log.debug("writing atom for symbol {s} at file offset 0x{x}", .{ self.getString(sym.n_strx), file_offset });1975 log.debug("writing atom for symbol {s} at file offset 0x{x}", .{ self.getString(sym.n_strx), file_offset });
1931 try self.base.file.?.pwriteAll(atom.code.items, file_offset);1976 try self.base.file.?.pwriteAll(atom.code.items, file_offset);
...@@ -2873,19 +2918,6 @@ fn addLoadDylibLCs(self: *MachO) !void {...@@ -2873,19 +2918,6 @@ fn addLoadDylibLCs(self: *MachO) !void {
28732918
2874fn flushZld(self: *MachO) !void {2919fn flushZld(self: *MachO) !void {
2875 try self.writeTextBlocks();2920 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
2889 try self.setEntryPoint();2921 try self.setEntryPoint();
2890 try self.writeRebaseInfoTableZld();2922 try self.writeRebaseInfoTableZld();
2891 try self.writeBindInfoTableZld();2923 try self.writeBindInfoTableZld();
...@@ -4203,10 +4235,12 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -4203,10 +4235,12 @@ pub fn populateMissingMetadata(self: *MachO) !void {
42034235
4204 log.debug("found __thread_bss section free space 0x{x} to 0x{x}", .{ off, off + needed_size });4236 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;
4206 try data_segment.addSection(self.base.allocator, "__thread_bss", .{4241 try data_segment.addSection(self.base.allocator, "__thread_bss", .{
4207 .addr = data_segment.inner.vmaddr + off - data_segment.inner.fileoff,4242 .addr = data_segment.inner.vmaddr + off - data_segment.inner.fileoff,
4208 .size = needed_size,4243 .size = needed_size,
4209 .offset = @intCast(u32, off),
4210 .@"align" = 3, // 2^3 = @sizeOf(u64)4244 .@"align" = 3, // 2^3 = @sizeOf(u64)
4211 .flags = macho.S_THREAD_LOCAL_ZEROFILL,4245 .flags = macho.S_THREAD_LOCAL_ZEROFILL,
4212 });4246 });
...@@ -4229,10 +4263,12 @@ pub fn populateMissingMetadata(self: *MachO) !void {...@@ -4229,10 +4263,12 @@ pub fn populateMissingMetadata(self: *MachO) !void {
42294263
4230 log.debug("found __bss section free space 0x{x} to 0x{x}", .{ off, off + needed_size });4264 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;
4232 try data_segment.addSection(self.base.allocator, "__bss", .{4269 try data_segment.addSection(self.base.allocator, "__bss", .{
4233 .addr = data_segment.inner.vmaddr + off - data_segment.inner.fileoff,4270 .addr = data_segment.inner.vmaddr + off - data_segment.inner.fileoff,
4234 .size = 0,4271 .size = 0,
4235 .offset = @intCast(u32, off),
4236 .@"align" = 3, // 2^3 = @sizeOf(u64)4272 .@"align" = 3, // 2^3 = @sizeOf(u64)
4237 .flags = macho.S_ZEROFILL,4273 .flags = macho.S_ZEROFILL,
4238 });4274 });