| author | |
| committer | |
| log | 72e09893686613bd65369faf9272171d272fbee3 |
| tree | af35966b4a2a6fee13cad0aa755d2feb2ddc4bec |
| parent | 2ae38cbd2599af06beebc4ae9e3cdbbbc6cefc89 |
| signature |
closes https://codeberg.org/ziglang/zig/issues/362852 files changed, 45 insertions(+), 8 deletions(-)
src/link/MachO.zig+23-3| ... | @@ -24,6 +24,8 @@ dylibs: std.ArrayList(File.Index) = .empty, | ... | @@ -24,6 +24,8 @@ dylibs: std.ArrayList(File.Index) = .empty, |
| 24 | 24 | ||
| 25 | segments: std.ArrayList(macho.segment_command_64) = .empty, | 25 | segments: std.ArrayList(macho.segment_command_64) = .empty, |
| 26 | sections: std.MultiArrayList(Section) = .{}, | 26 | sections: std.MultiArrayList(Section) = .{}, |
| 27 | /// Populated by `allocateSections`. | ||
| 28 | header_size: ?u32 = null, | ||
| 27 | 29 | ||
| 28 | resolver: SymbolResolver = .{}, | 30 | resolver: SymbolResolver = .{}, |
| 29 | /// This table will be populated after `scanRelocs` has run. | 31 | /// This table will be populated after `scanRelocs` has run. |
| ... | @@ -2209,13 +2211,14 @@ fn initSegments(self: *MachO) !void { | ... | @@ -2209,13 +2211,14 @@ fn initSegments(self: *MachO) !void { |
| 2209 | } | 2211 | } |
| 2210 | 2212 | ||
| 2211 | fn allocateSections(self: *MachO) !void { | 2213 | fn allocateSections(self: *MachO) !void { |
| 2212 | const headerpad = try load_commands.calcMinHeaderPadSize(self); | 2214 | const header_size = try load_commands.calcMinHeaderSize(self); |
| 2215 | self.header_size = header_size; | ||
| 2213 | var vmaddr: u64 = if (self.pagezero_seg_index) |index| | 2216 | var vmaddr: u64 = if (self.pagezero_seg_index) |index| |
| 2214 | self.segments.items[index].vmaddr + self.segments.items[index].vmsize | 2217 | self.segments.items[index].vmaddr + self.segments.items[index].vmsize |
| 2215 | else | 2218 | else |
| 2216 | 0; | 2219 | 0; |
| 2217 | vmaddr += headerpad; | 2220 | vmaddr += header_size; |
| 2218 | var fileoff = headerpad; | 2221 | var fileoff = header_size; |
| 2219 | var prev_seg_id: u8 = if (self.pagezero_seg_index) |index| index + 1 else 0; | 2222 | var prev_seg_id: u8 = if (self.pagezero_seg_index) |index| index + 1 else 0; |
| 2220 | 2223 | ||
| 2221 | const page_size = self.getPageSize(); | 2224 | const page_size = self.getPageSize(); |
| ... | @@ -2895,6 +2898,11 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } { | ... | @@ -2895,6 +2898,11 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } { |
| 2895 | ncmds += 1; | 2898 | ncmds += 1; |
| 2896 | } | 2899 | } |
| 2897 | 2900 | ||
| 2901 | if (self.needsEncryptionInfo()) { | ||
| 2902 | try load_commands.writeEncryptionInfoLC(self, &writer); | ||
| 2903 | ncmds += 1; | ||
| 2904 | } | ||
| 2905 | |||
| 2898 | for (self.rpath_list) |rpath| { | 2906 | for (self.rpath_list) |rpath| { |
| 2899 | try load_commands.writeRpathLC(rpath, &writer); | 2907 | try load_commands.writeRpathLC(rpath, &writer); |
| 2900 | ncmds += 1; | 2908 | ncmds += 1; |
| ... | @@ -5410,6 +5418,18 @@ pub fn alignPow(macho_file: *MachO, x: u32) error{AlreadyReported}!u32 { | ... | @@ -5410,6 +5418,18 @@ pub fn alignPow(macho_file: *MachO, x: u32) error{AlreadyReported}!u32 { |
| 5410 | return result; | 5418 | return result; |
| 5411 | } | 5419 | } |
| 5412 | 5420 | ||
| 5421 | pub fn needsEncryptionInfo(macho_file: *MachO) bool { | ||
| 5422 | const target = macho_file.getTarget(); | ||
| 5423 | return switch (target.os.tag) { | ||
| 5424 | .ios, | ||
| 5425 | .tvos, | ||
| 5426 | .visionos, | ||
| 5427 | .watchos, | ||
| 5428 | => target.abi != .simulator, | ||
| 5429 | else => false, | ||
| 5430 | }; | ||
| 5431 | } | ||
| 5432 | |||
| 5413 | /// Branch instruction has 26 bits immediate but is 4 byte aligned. | 5433 | /// Branch instruction has 26 bits immediate but is 4 byte aligned. |
| 5414 | const jump_bits = @bitSizeOf(i28); | 5434 | const jump_bits = @bitSizeOf(i28); |
| 5415 | const max_distance = (1 << (jump_bits - 1)); | 5435 | const max_distance = (1 << (jump_bits - 1)); |
src/link/MachO/load_commands.zig+22-5| ... | @@ -62,6 +62,10 @@ pub fn calcLoadCommandsSize(macho_file: *MachO, assume_max_path_len: bool) !u32 | ... | @@ -62,6 +62,10 @@ pub fn calcLoadCommandsSize(macho_file: *MachO, assume_max_path_len: bool) !u32 |
| 62 | assume_max_path_len, | 62 | assume_max_path_len, |
| 63 | ); | 63 | ); |
| 64 | } | 64 | } |
| 65 | // LC_ENCRYPTION_INFO_64 | ||
| 66 | if (macho_file.needsEncryptionInfo()) { | ||
| 67 | sizeofcmds += @sizeOf(macho.encryption_info_command_64); | ||
| 68 | } | ||
| 65 | // LC_RPATH | 69 | // LC_RPATH |
| 66 | { | 70 | { |
| 67 | for (macho_file.rpath_list) |rpath| { | 71 | for (macho_file.rpath_list) |rpath| { |
| ... | @@ -163,23 +167,29 @@ pub fn calcLoadCommandsSizeObject(macho_file: *MachO) u32 { | ... | @@ -163,23 +167,29 @@ pub fn calcLoadCommandsSizeObject(macho_file: *MachO) u32 { |
| 163 | return @as(u32, @intCast(sizeofcmds)); | 167 | return @as(u32, @intCast(sizeofcmds)); |
| 164 | } | 168 | } |
| 165 | 169 | ||
| 166 | pub fn calcMinHeaderPadSize(macho_file: *MachO) !u32 { | 170 | pub fn calcMinHeaderSize(macho_file: *MachO) !u32 { |
| 167 | var padding: u32 = (try calcLoadCommandsSize(macho_file, false)) + | 171 | var padding: u32 = (try calcLoadCommandsSize(macho_file, false)) + |
| 168 | (macho_file.headerpad_size orelse MachO.default_headerpad_size); | 172 | (macho_file.headerpad_size orelse MachO.default_headerpad_size); |
| 169 | log.debug("minimum requested headerpad size 0x{x}", .{padding + @sizeOf(macho.mach_header_64)}); | 173 | log.debug("minimum requested header + padding size 0x{x}", .{padding + @sizeOf(macho.mach_header_64)}); |
| 170 | 174 | ||
| 171 | if (macho_file.headerpad_max_install_names) { | 175 | if (macho_file.headerpad_max_install_names) { |
| 172 | const min_headerpad_size: u32 = try calcLoadCommandsSize(macho_file, true); | 176 | const min_headerpad_size: u32 = try calcLoadCommandsSize(macho_file, true); |
| 173 | log.debug("headerpad_max_install_names minimum headerpad size 0x{x}", .{ | 177 | log.debug("headerpad_max_install_names minimum header + padding size 0x{x}", .{ |
| 174 | min_headerpad_size + @sizeOf(macho.mach_header_64), | 178 | min_headerpad_size + @sizeOf(macho.mach_header_64), |
| 175 | }); | 179 | }); |
| 176 | padding = @max(padding, min_headerpad_size); | 180 | padding = @max(padding, min_headerpad_size); |
| 177 | } | 181 | } |
| 178 | 182 | ||
| 179 | const offset = @sizeOf(macho.mach_header_64) + padding; | 183 | const offset = @sizeOf(macho.mach_header_64) + padding; |
| 180 | log.debug("actual headerpad size 0x{x}", .{offset}); | 184 | log.debug("actual header + padding size 0x{x}", .{offset}); |
| 181 | 185 | ||
| 182 | return offset; | 186 | // Encryption is done at page granularity, so if the output needs a load |
| 187 | // command for encryption info, ensure that the header + load commands have | ||
| 188 | // at least one full, unencrypted page. | ||
| 189 | return if (macho_file.needsEncryptionInfo()) | ||
| 190 | mem.alignForward(u32, offset, macho_file.getPageSize()) | ||
| 191 | else | ||
| 192 | offset; | ||
| 183 | } | 193 | } |
| 184 | 194 | ||
| 185 | pub fn writeDylinkerLC(writer: *Writer) !void { | 195 | pub fn writeDylinkerLC(writer: *Writer) !void { |
| ... | @@ -260,6 +270,13 @@ pub fn writeDylibIdLC(macho_file: *MachO, writer: *Writer) !void { | ... | @@ -260,6 +270,13 @@ pub fn writeDylibIdLC(macho_file: *MachO, writer: *Writer) !void { |
| 260 | }, writer); | 270 | }, writer); |
| 261 | } | 271 | } |
| 262 | 272 | ||
| 273 | pub fn writeEncryptionInfoLC(macho_file: *MachO, writer: *Writer) !void { | ||
| 274 | try writer.writeAll(mem.asBytes(&macho.encryption_info_command_64{ | ||
| 275 | .cryptoff = macho_file.header_size.?, | ||
| 276 | .cryptsize = @as(u32, @intCast(macho_file.getTextSegment().filesize)) - macho_file.header_size.?, | ||
| 277 | })); | ||
| 278 | } | ||
| 279 | |||
| 263 | pub fn writeRpathLC(rpath: []const u8, writer: *Writer) !void { | 280 | pub fn writeRpathLC(rpath: []const u8, writer: *Writer) !void { |
| 264 | const rpath_len = rpath.len + 1; | 281 | const rpath_len = rpath.len + 1; |
| 265 | const cmdsize = @as(u32, @intCast(mem.alignForward( | 282 | const cmdsize = @as(u32, @intCast(mem.alignForward( |