| author | |
| committer | |
| log | 91a29d7074a61ba192fcefb351a10a26d60b85c8 |
| tree | 952c66662f1c2334ec08a00aab5b499d8cb640ff |
| parent | 2aa8f3d3f5bf98d1a6a7396c608e24203cf094be |
| parent | 72e09893686613bd65369faf9272171d272fbee3 |
Reviewed-on: https://codeberg.org/ziglang/zig/pulls/363083 files changed, 64 insertions(+), 8 deletions(-)
lib/std/macho.zig+19| ... | ... | @@ -588,6 +588,25 @@ pub const rpath_command = extern struct { |
| 588 | 588 | path: u32, |
| 589 | 589 | }; |
| 590 | 590 | |
| 591 | pub const encryption_info_command = extern struct { | |
| 592 | cmd: LC = .ENCRYPTION_INFO, | |
| 593 | cmdsize: u32 = @sizeOf(encryption_info_command), | |
| 594 | ||
| 595 | cryptoff: u32, | |
| 596 | cryptsize: u32, | |
| 597 | cryptid: u32 = 0, | |
| 598 | }; | |
| 599 | ||
| 600 | pub const encryption_info_command_64 = extern struct { | |
| 601 | cmd: LC = .ENCRYPTION_INFO_64, | |
| 602 | cmdsize: u32 = @sizeOf(encryption_info_command_64), | |
| 603 | ||
| 604 | cryptoff: u32, | |
| 605 | cryptsize: u32, | |
| 606 | cryptid: u32 = 0, | |
| 607 | _pad: u32 = 0, | |
| 608 | }; | |
| 609 | ||
| 591 | 610 | /// The segment load command indicates that a part of this file is to be |
| 592 | 611 | /// mapped into the task's address space. The size of this segment in memory, |
| 593 | 612 | /// vmsize, maybe equal to or larger than the amount to map from this file, |
src/link/MachO.zig+23-3| ... | ... | @@ -24,6 +24,8 @@ dylibs: std.ArrayList(File.Index) = .empty, |
| 24 | 24 | |
| 25 | 25 | segments: std.ArrayList(macho.segment_command_64) = .empty, |
| 26 | 26 | sections: std.MultiArrayList(Section) = .{}, |
| 27 | /// Populated by `allocateSections`. | |
| 28 | header_size: ?u32 = null, | |
| 27 | 29 | |
| 28 | 30 | resolver: SymbolResolver = .{}, |
| 29 | 31 | /// This table will be populated after `scanRelocs` has run. |
| ... | ... | @@ -2209,13 +2211,14 @@ fn initSegments(self: *MachO) !void { |
| 2209 | 2211 | } |
| 2210 | 2212 | |
| 2211 | 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 | 2216 | var vmaddr: u64 = if (self.pagezero_seg_index) |index| |
| 2214 | 2217 | self.segments.items[index].vmaddr + self.segments.items[index].vmsize |
| 2215 | 2218 | else |
| 2216 | 2219 | 0; |
| 2217 | vmaddr += headerpad; | |
| 2218 | var fileoff = headerpad; | |
| 2220 | vmaddr += header_size; | |
| 2221 | var fileoff = header_size; | |
| 2219 | 2222 | var prev_seg_id: u8 = if (self.pagezero_seg_index) |index| index + 1 else 0; |
| 2220 | 2223 | |
| 2221 | 2224 | const page_size = self.getPageSize(); |
| ... | ... | @@ -2895,6 +2898,11 @@ fn writeLoadCommands(self: *MachO) !struct { usize, usize, u64 } { |
| 2895 | 2898 | ncmds += 1; |
| 2896 | 2899 | } |
| 2897 | 2900 | |
| 2901 | if (self.needsEncryptionInfo()) { | |
| 2902 | try load_commands.writeEncryptionInfoLC(self, &writer); | |
| 2903 | ncmds += 1; | |
| 2904 | } | |
| 2905 | ||
| 2898 | 2906 | for (self.rpath_list) |rpath| { |
| 2899 | 2907 | try load_commands.writeRpathLC(rpath, &writer); |
| 2900 | 2908 | ncmds += 1; |
| ... | ... | @@ -5410,6 +5418,18 @@ pub fn alignPow(macho_file: *MachO, x: u32) error{AlreadyReported}!u32 { |
| 5410 | 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 | 5433 | /// Branch instruction has 26 bits immediate but is 4 byte aligned. |
| 5414 | 5434 | const jump_bits = @bitSizeOf(i28); |
| 5415 | 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 | 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 | 69 | // LC_RPATH |
| 66 | 70 | { |
| 67 | 71 | for (macho_file.rpath_list) |rpath| { |
| ... | ... | @@ -163,23 +167,29 @@ pub fn calcLoadCommandsSizeObject(macho_file: *MachO) u32 { |
| 163 | 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 | 171 | var padding: u32 = (try calcLoadCommandsSize(macho_file, false)) + |
| 168 | 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 | 175 | if (macho_file.headerpad_max_install_names) { |
| 172 | 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 | 178 | min_headerpad_size + @sizeOf(macho.mach_header_64), |
| 175 | 179 | }); |
| 176 | 180 | padding = @max(padding, min_headerpad_size); |
| 177 | 181 | } |
| 178 | 182 | |
| 179 | 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 | 195 | pub fn writeDylinkerLC(writer: *Writer) !void { |
| ... | ... | @@ -260,6 +270,13 @@ pub fn writeDylibIdLC(macho_file: *MachO, writer: *Writer) !void { |
| 260 | 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 | 280 | pub fn writeRpathLC(rpath: []const u8, writer: *Writer) !void { |
| 264 | 281 | const rpath_len = rpath.len + 1; |
| 265 | 282 | const cmdsize = @as(u32, @intCast(mem.alignForward( |