| ... | ... | @@ -49,6 +49,10 @@ const alloc_den = 3; |
| 49 | 49 | /// Default path to dyld |
| 50 | 50 | const DEFAULT_DYLD_PATH: [*:0]const u8 = "/usr/lib/dyld"; |
| 51 | 51 | |
| 52 | /// We always have to link against libSystem since macOS Catalina (TODO link) |
| 53 | const LIB_SYSTEM_NAME: [*:0]const u8 = "System"; |
| 54 | const LIB_SYSTEM_PATH: [*:0]const u8 = "/usr/lib/libSystem.B.dylib"; |
| 55 | |
| 52 | 56 | pub const TextBlock = struct { |
| 53 | 57 | pub const empty = TextBlock{}; |
| 54 | 58 | }; |
| ... | ... | @@ -226,12 +230,41 @@ pub fn flush(self: *MachO, module: *Module) !void { |
| 226 | 230 | |
| 227 | 231 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(load_dylinker[0..1]), self.command_file_offset.?); |
| 228 | 232 | |
| 229 | | const padded_path = try self.base.allocator.alloc(u8, cmdsize - @sizeOf(macho.dylinker_command)); |
| 230 | | defer self.base.allocator.free(padded_path); |
| 231 | | mem.set(u8, padded_path[0..], 0); |
| 232 | | mem.copy(u8, padded_path[0..], mem.spanZ(DEFAULT_DYLD_PATH)); |
| 233 | const file_offset = self.command_file_offset.? + @sizeOf(macho.dylinker_command); |
| 234 | try self.addPadding(cmdsize - @sizeOf(macho.dylinker_command), file_offset); |
| 233 | 235 | |
| 234 | | try self.base.file.?.pwriteAll(padded_path, self.command_file_offset.? + @sizeOf(macho.dylinker_command)); |
| 236 | try self.base.file.?.pwriteAll(mem.spanZ(DEFAULT_DYLD_PATH), file_offset); |
| 237 | self.command_file_offset.? += cmdsize; |
| 238 | } |
| 239 | |
| 240 | { |
| 241 | // Link against libSystem |
| 242 | const cmdsize = commandSize(@intCast(u32, @sizeOf(macho.dylib_command) + mem.lenZ(LIB_SYSTEM_PATH))); |
| 243 | const version = std.c.NSVersionOfRunTimeLibrary(LIB_SYSTEM_NAME); |
| 244 | const dylib = .{ |
| 245 | .name = @sizeOf(macho.dylib_command), |
| 246 | .timestamp = 2, // not sure why not simply 0; this is reverse engineered from Mach-O files |
| 247 | .current_version = version, |
| 248 | .compatibility_version = 0x10000, // not sure why this either; value from reverse engineering |
| 249 | }; |
| 250 | const load_dylib = [1]macho.dylib_command{ |
| 251 | .{ |
| 252 | .cmd = macho.LC_LOAD_DYLIB, |
| 253 | .cmdsize = cmdsize, |
| 254 | .dylib = dylib, |
| 255 | }, |
| 256 | }; |
| 257 | try self.commands.append(self.base.allocator, .{ |
| 258 | .cmd = macho.LC_LOAD_DYLIB, |
| 259 | .cmdsize = cmdsize, |
| 260 | }); |
| 261 | |
| 262 | try self.base.file.?.pwriteAll(mem.sliceAsBytes(load_dylib[0..1]), self.command_file_offset.?); |
| 263 | |
| 264 | const file_offset = self.command_file_offset.? + @sizeOf(macho.dylib_command); |
| 265 | try self.addPadding(cmdsize - @sizeOf(macho.dylib_command), file_offset); |
| 266 | |
| 267 | try self.base.file.?.pwriteAll(mem.spanZ(LIB_SYSTEM_PATH), file_offset); |
| 235 | 268 | self.command_file_offset.? += cmdsize; |
| 236 | 269 | } |
| 237 | 270 | }, |
| ... | ... | @@ -431,3 +464,14 @@ fn commandSize(min_size: u32) u32 { |
| 431 | 464 | const div = min_size / @sizeOf(u64); |
| 432 | 465 | return (div + 1) * @sizeOf(u64); |
| 433 | 466 | } |
| 467 | |
| 468 | fn addPadding(self: *MachO, size: u32, file_offset: u64) !void { |
| 469 | if (size == 0) return; |
| 470 | |
| 471 | const buf = try self.base.allocator.alloc(u8, size); |
| 472 | defer self.base.allocator.free(buf); |
| 473 | |
| 474 | mem.set(u8, buf[0..], 0); |
| 475 | |
| 476 | try self.base.file.?.pwriteAll(buf, file_offset); |
| 477 | } |