authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-12-21 23:15:55+01:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-12-21 23:16:00+01:00
logf106a46fd293605fab7cb776d36bb22cc482e692
treee41216eaa58050b1f6f8e76bba6156b2c2adcd6e
parent3f21f9155fe8e10e3990ee5738b190accbdffd3a

macho: enable binding and lazy binding info writes


1 files changed, 47 insertions(+), 38 deletions(-)

src/link/MachO.zig+47-38
...@@ -114,6 +114,8 @@ error_flags: File.ErrorFlags = File.ErrorFlags{},...@@ -114,6 +114,8 @@ error_flags: File.ErrorFlags = File.ErrorFlags{},
114offset_table_count_dirty: bool = false,114offset_table_count_dirty: bool = false,
115header_dirty: bool = false,115header_dirty: bool = false,
116load_commands_dirty: bool = false,116load_commands_dirty: bool = false,
117binding_info_dirty: bool = false,
118lazy_binding_info_dirty: bool = false,
117export_info_dirty: bool = false,119export_info_dirty: bool = false,
118string_table_dirty: bool = false,120string_table_dirty: bool = false,
119121
...@@ -322,6 +324,8 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -322,6 +324,8 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
322 main_cmd.entryoff = addr - text_segment.inner.vmaddr;324 main_cmd.entryoff = addr - text_segment.inner.vmaddr;
323 self.load_commands_dirty = true;325 self.load_commands_dirty = true;
324 }326 }
327 try self.writeBindingInfoTable();
328 try self.writeLazyBindingInfoTable();
325 try self.writeExportTrie();329 try self.writeExportTrie();
326 try self.writeAllGlobalAndUndefSymbols();330 try self.writeAllGlobalAndUndefSymbols();
327 try self.writeStringTable();331 try self.writeStringTable();
...@@ -354,6 +358,8 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {...@@ -354,6 +358,8 @@ pub fn flushModule(self: *MachO, comp: *Compilation) !void {
354 assert(!self.offset_table_count_dirty);358 assert(!self.offset_table_count_dirty);
355 assert(!self.header_dirty);359 assert(!self.header_dirty);
356 assert(!self.load_commands_dirty);360 assert(!self.load_commands_dirty);
361 assert(!self.binding_info_dirty);
362 assert(!self.lazy_binding_info_dirty);
357 assert(!self.export_info_dirty);363 assert(!self.export_info_dirty);
358 assert(!self.string_table_dirty);364 assert(!self.string_table_dirty);
359365
...@@ -831,7 +837,7 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {...@@ -831,7 +837,7 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
831 symbol.dylib_ordinal = next_ordinal;837 symbol.dylib_ordinal = next_ordinal;
832 }838 }
833839
834 // Write update dyld info840 // Write updated dyld info.
835 const dyld_info = self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfoOnly;841 const dyld_info = self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfoOnly;
836 {842 {
837 const size = try self.binding_info_table.calcSize();843 const size = try self.binding_info_table.calcSize();
...@@ -861,6 +867,9 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {...@@ -861,6 +867,9 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
861 // Write updated load commands and the header867 // Write updated load commands and the header
862 try self.writeLoadCommands();868 try self.writeLoadCommands();
863 try self.writeHeader();869 try self.writeHeader();
870
871 assert(!self.header_dirty);
872 assert(!self.load_commands_dirty);
864 }873 }
865 if (self.code_signature_cmd_index == null) outer: {874 if (self.code_signature_cmd_index == null) outer: {
866 if (target.cpu.arch != .aarch64) break :outer; // This is currently needed only for aarch64 targets.875 if (target.cpu.arch != .aarch64) break :outer; // This is currently needed only for aarch64 targets.
...@@ -896,6 +905,9 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {...@@ -896,6 +905,9 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
896 try self.writeHeader();905 try self.writeHeader();
897 // Generate adhoc code signature906 // Generate adhoc code signature
898 try self.writeCodeSignature();907 try self.writeCodeSignature();
908
909 assert(!self.header_dirty);
910 assert(!self.load_commands_dirty);
899 }911 }
900 }912 }
901 }913 }
...@@ -2136,7 +2148,7 @@ fn writeExportTrie(self: *MachO) !void {...@@ -2136,7 +2148,7 @@ fn writeExportTrie(self: *MachO) !void {
2136 dyld_info.export_off = @intCast(u32, self.findFreeSpace(&linkedit_segment, needed_size, 1));2148 dyld_info.export_off = @intCast(u32, self.findFreeSpace(&linkedit_segment, needed_size, 1));
2137 }2149 }
2138 dyld_info.export_size = @intCast(u32, needed_size);2150 dyld_info.export_size = @intCast(u32, needed_size);
2139 log.debug("writing export trie from 0x{x} to 0x{x}", .{ dyld_info.export_off, dyld_info.export_off + dyld_info.export_size });2151 log.debug("writing export info from 0x{x} to 0x{x}", .{ dyld_info.export_off, dyld_info.export_off + dyld_info.export_size });
21402152
2141 try self.base.file.?.pwriteAll(buffer, dyld_info.export_off);2153 try self.base.file.?.pwriteAll(buffer, dyld_info.export_off);
2142 self.load_commands_dirty = true;2154 self.load_commands_dirty = true;
...@@ -2144,65 +2156,62 @@ fn writeExportTrie(self: *MachO) !void {...@@ -2144,65 +2156,62 @@ fn writeExportTrie(self: *MachO) !void {
2144}2156}
21452157
2146fn writeBindingInfoTable(self: *MachO) !void {2158fn writeBindingInfoTable(self: *MachO) !void {
2147 const size = self.binding_info_table.calcSize();2159 if (!self.binding_info_dirty) return;
2160
2161 const tracy = trace(@src());
2162 defer tracy.end();
2163
2164 const size = try self.binding_info_table.calcSize();
2148 var buffer = try self.base.allocator.alloc(u8, size);2165 var buffer = try self.base.allocator.alloc(u8, size);
2149 defer self.base.allocator.free(buffer);2166 defer self.base.allocator.free(buffer);
21502167
2151 var stream = std.io.fixedBufferStream(buffer);2168 var stream = std.io.fixedBufferStream(buffer);
2152 try self.binding_info_table.write(stream.writer());2169 try self.binding_info_table.write(stream.writer());
21532170
2171 const linkedit_segment = self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;
2154 const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfoOnly;2172 const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfoOnly;
2155 const bind_size = @intCast(u32, mem.alignForward(buffer.len, @sizeOf(u64)));2173 const allocated_size = self.allocatedSize(&linkedit_segment, dyld_info.bind_off);
2156 dyld_info.bind_off = self.linkedit_segment_next_offset.?;2174 const needed_size = mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64));
2157 dyld_info.bind_size = bind_size;
2158
2159 log.debug("writing binding info table from 0x{x} to 0x{x}", .{ dyld_info.bind_off, dyld_info.bind_off + bind_size });
21602175
2161 if (bind_size > buffer.len) {2176 if (needed_size > allocated_size) {
2162 // Pad out to align(8).2177 dyld_info.bind_off = 0;
2163 try self.base.file.?.pwriteAll(&[_]u8{0}, dyld_info.bind_off + bind_size);2178 dyld_info.bind_off = @intCast(u32, self.findFreeSpace(&linkedit_segment, needed_size, 1));
2164 }2179 }
2165 try self.base.file.?.pwriteAll(buffer, dyld_info.bind_off);
21662180
2167 self.linkedit_segment_next_offset = dyld_info.bind_off + dyld_info.bind_size;2181 dyld_info.bind_size = @intCast(u32, needed_size);
2168 // Advance size of __LINKEDIT segment2182 log.debug("writing binding info from 0x{x} to 0x{x}", .{ dyld_info.bind_off, dyld_info.bind_off + dyld_info.bind_size });
2169 const linkedit = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;2183
2170 linkedit.inner.filesize += dyld_info.bind_size;2184 try self.base.file.?.pwriteAll(buffer, dyld_info.bind_off);
2171 if (linkedit.inner.vmsize < linkedit.inner.filesize) {2185 self.load_commands_dirty = true;
2172 linkedit.inner.vmsize = mem.alignForwardGeneric(u64, linkedit.inner.filesize, self.page_size);2186 self.binding_info_dirty = false;
2173 }
2174 self.cmd_table_dirty = true;
2175}2187}
21762188
2177fn writeLazyBindingInfoTable(self: *MachO) !void {2189fn writeLazyBindingInfoTable(self: *MachO) !void {
2178 const size = self.lazy_binding_info_table.calcSize();2190 if (!self.lazy_binding_info_dirty) return;
2191
2192 const size = try self.lazy_binding_info_table.calcSize();
2179 var buffer = try self.base.allocator.alloc(u8, size);2193 var buffer = try self.base.allocator.alloc(u8, size);
2180 defer self.base.allocator.free(buffer);2194 defer self.base.allocator.free(buffer);
21812195
2182 var stream = std.io.fixedBufferStream(buffer);2196 var stream = std.io.fixedBufferStream(buffer);
2183 try self.lazy_binding_info_table.write(stream.writer());2197 try self.lazy_binding_info_table.write(stream.writer());
21842198
2199 const linkedit_segment = self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;
2185 const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfoOnly;2200 const dyld_info = &self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfoOnly;
2186 const bind_size = @intCast(u32, mem.alignForward(buffer.len, @sizeOf(u64)));2201 const allocated_size = self.allocatedSize(&linkedit_segment, dyld_info.lazy_bind_off);
2187 dyld_info.lazy_bind_off = self.linkedit_segment_next_offset.?;2202 const needed_size = mem.alignForwardGeneric(u64, buffer.len, @alignOf(u64));
2188 dyld_info.lazy_bind_size = bind_size;
2189
2190 log.debug("writing lazy binding info table from 0x{x} to 0x{x}", .{ dyld_info.lazy_bind_off, dyld_info.lazy_bind_off + bind_size });
21912203
2192 if (bind_size > buffer.len) {2204 if (needed_size > allocated_size) {
2193 // Pad out to align(8).2205 dyld_info.lazy_bind_off = 0;
2194 try self.base.file.?.pwriteAll(&[_]u8{0}, dyld_info.lazy_bind_off + bind_size);2206 dyld_info.lazy_bind_off = @intCast(u32, self.findFreeSpace(&linkedit_segment, needed_size, 1));
2195 }2207 }
2196 try self.base.file.?.pwriteAll(buffer, dyld_info.lazy_bind_off);
21972208
2198 self.linkedit_segment_next_offset = dyld_info.lazy_bind_off + dyld_info.lazy_bind_size;2209 dyld_info.lazy_bind_size = @intCast(u32, needed_size);
2199 // Advance size of __LINKEDIT segment2210 log.debug("writing lazy binding info from 0x{x} to 0x{x}", .{ dyld_info.lazy_bind_off, dyld_info.lazy_bind_off + dyld_info.lazy_bind_size });
2200 const linkedit = &self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;2211
2201 linkedit.inner.filesize += dyld_info.lazy_bind_size;2212 try self.base.file.?.pwriteAll(buffer, dyld_info.lazy_bind_off);
2202 if (linkedit.inner.vmsize < linkedit.inner.filesize) {2213 self.load_commands_dirty = true;
2203 linkedit.inner.vmsize = mem.alignForwardGeneric(u64, linkedit.inner.filesize, self.page_size);2214 self.lazy_binding_info_dirty = false;
2204 }
2205 self.cmd_table_dirty = true;
2206}2215}
22072216
2208fn writeStringTable(self: *MachO) !void {2217fn writeStringTable(self: *MachO) !void {