authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2021-03-18 08:32:27+01:00
committergravatar for jakubkonka@microsoft.comJakub Konka <jakubkonka@microsoft.com> 2021-03-18 11:09:47+01:00
log861ea640090f5c4a36889cf65f32c575cbe3b505
tree179a42d021d37559b262116c3aeb1411c41bf525
parent7516dfff83368df4d67e3c10923c3d6da1b72879

macho: remove now obsolete LLD fixups


1 files changed, 0 insertions(+), 284 deletions(-)

src/link/MachO.zig-284
......@@ -947,119 +947,6 @@ fn linkWithLLD(self: *MachO, comp: *Compilation) !void {
947947 log.warn("unexpected LLD stderr:\n{s}", .{stderr});
948948 }
949949 }
950
951 // At this stage, LLD has done its job. It is time to patch the resultant
952 // binaries up!
953 const out_file = try directory.handle.openFile(self.base.options.emit.?.sub_path, .{ .write = true });
954 try self.parseFromFile(out_file);
955
956 if (self.libsystem_cmd_index == null and self.header.?.filetype == macho.MH_EXECUTE) {
957 const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
958 const text_section = text_segment.sections.items[self.text_section_index.?];
959 const after_last_cmd_offset = self.header.?.sizeofcmds + @sizeOf(macho.mach_header_64);
960 const needed_size = padToIdeal(@sizeOf(macho.linkedit_data_command));
961
962 if (needed_size + after_last_cmd_offset > text_section.offset) {
963 log.err("Unable to extend padding between the end of load commands and start of __text section.", .{});
964 log.err("Re-run the linker with '-headerpad 0x{x}' option if available, or", .{needed_size});
965 log.err("fall back to the system linker by exporting 'ZIG_SYSTEM_LINKER_HACK=1'.", .{});
966 return error.NotEnoughPadding;
967 }
968
969 // Calculate next available dylib ordinal.
970 const next_ordinal = blk: {
971 var ordinal: u32 = 1;
972 for (self.load_commands.items) |cmd| {
973 switch (cmd) {
974 .Dylib => ordinal += 1,
975 else => {},
976 }
977 }
978 break :blk ordinal;
979 };
980
981 // Add load dylib load command
982 self.libsystem_cmd_index = @intCast(u16, self.load_commands.items.len);
983 const cmdsize = @intCast(u32, mem.alignForwardGeneric(
984 u64,
985 @sizeOf(macho.dylib_command) + mem.lenZ(LIB_SYSTEM_PATH),
986 @sizeOf(u64),
987 ));
988 // TODO Find a way to work out runtime version from the OS version triple stored in std.Target.
989 // In the meantime, we're gonna hardcode to the minimum compatibility version of 0.0.0.
990 const min_version = 0x0;
991 var dylib_cmd = emptyGenericCommandWithData(macho.dylib_command{
992 .cmd = macho.LC_LOAD_DYLIB,
993 .cmdsize = cmdsize,
994 .dylib = .{
995 .name = @sizeOf(macho.dylib_command),
996 .timestamp = 2, // not sure why not simply 0; this is reverse engineered from Mach-O files
997 .current_version = min_version,
998 .compatibility_version = min_version,
999 },
1000 });
1001 dylib_cmd.data = try self.base.allocator.alloc(u8, cmdsize - dylib_cmd.inner.dylib.name);
1002 mem.set(u8, dylib_cmd.data, 0);
1003 mem.copy(u8, dylib_cmd.data, mem.spanZ(LIB_SYSTEM_PATH));
1004 try self.load_commands.append(self.base.allocator, .{ .Dylib = dylib_cmd });
1005 self.header_dirty = true;
1006 self.load_commands_dirty = true;
1007
1008 if (self.symtab_cmd_index == null or self.dysymtab_cmd_index == null) {
1009 log.err("Incomplete Mach-O binary: no LC_SYMTAB or LC_DYSYMTAB load command found!", .{});
1010 log.err("Without the symbol table, it is not possible to patch up the binary for cross-compilation.", .{});
1011 return error.NoSymbolTableFound;
1012 }
1013
1014 // Patch dyld info
1015 try self.fixupBindInfo(next_ordinal);
1016 try self.fixupLazyBindInfo(next_ordinal);
1017
1018 // Write updated load commands and the header
1019 try self.writeLoadCommands();
1020 try self.writeHeader();
1021
1022 assert(!self.header_dirty);
1023 assert(!self.load_commands_dirty);
1024 }
1025 if (self.code_signature_cmd_index == null) outer: {
1026 if (target.cpu.arch != .aarch64) break :outer; // This is currently needed only for aarch64 targets.
1027 const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
1028 const text_section = text_segment.sections.items[self.text_section_index.?];
1029 const after_last_cmd_offset = self.header.?.sizeofcmds + @sizeOf(macho.mach_header_64);
1030 const needed_size = padToIdeal(@sizeOf(macho.linkedit_data_command));
1031
1032 if (needed_size + after_last_cmd_offset > text_section.offset) {
1033 log.err("Unable to extend padding between the end of load commands and start of __text section.", .{});
1034 log.err("Re-run the linker with '-headerpad 0x{x}' option if available, or", .{needed_size});
1035 log.err("fall back to the system linker by exporting 'ZIG_SYSTEM_LINKER_HACK=1'.", .{});
1036 return error.NotEnoughPadding;
1037 }
1038
1039 // Add code signature load command
1040 self.code_signature_cmd_index = @intCast(u16, self.load_commands.items.len);
1041 try self.load_commands.append(self.base.allocator, .{
1042 .LinkeditData = .{
1043 .cmd = macho.LC_CODE_SIGNATURE,
1044 .cmdsize = @sizeOf(macho.linkedit_data_command),
1045 .dataoff = 0,
1046 .datasize = 0,
1047 },
1048 });
1049 self.header_dirty = true;
1050 self.load_commands_dirty = true;
1051
1052 // Pad out space for code signature
1053 try self.writeCodeSignaturePadding();
1054 // Write updated load commands and the header
1055 try self.writeLoadCommands();
1056 try self.writeHeader();
1057 // Generate adhoc code signature
1058 try self.writeCodeSignature();
1059
1060 assert(!self.header_dirty);
1061 assert(!self.load_commands_dirty);
1062 }
1063950 }
1064951 }
1065952
......@@ -3375,177 +3262,6 @@ fn writeHeader(self: *MachO) !void {
33753262 self.header_dirty = false;
33763263}
33773264
3378/// Parse MachO contents from existing binary file.
3379fn parseFromFile(self: *MachO, file: fs.File) !void {
3380 self.base.file = file;
3381 var reader = file.reader();
3382 const header = try reader.readStruct(macho.mach_header_64);
3383 try self.load_commands.ensureCapacity(self.base.allocator, header.ncmds);
3384 var i: u16 = 0;
3385 while (i < header.ncmds) : (i += 1) {
3386 const cmd = try LoadCommand.read(self.base.allocator, reader);
3387 switch (cmd.cmd()) {
3388 macho.LC_SEGMENT_64 => {
3389 const x = cmd.Segment;
3390 if (parseAndCmpName(&x.inner.segname, "__PAGEZERO")) {
3391 self.pagezero_segment_cmd_index = i;
3392 } else if (parseAndCmpName(&x.inner.segname, "__LINKEDIT")) {
3393 self.linkedit_segment_cmd_index = i;
3394 } else if (parseAndCmpName(&x.inner.segname, "__TEXT")) {
3395 self.text_segment_cmd_index = i;
3396 for (x.sections.items) |sect, j| {
3397 if (parseAndCmpName(&sect.sectname, "__text")) {
3398 self.text_section_index = @intCast(u16, j);
3399 }
3400 }
3401 } else if (parseAndCmpName(&x.inner.segname, "__DATA")) {
3402 self.data_segment_cmd_index = i;
3403 } else if (parseAndCmpName(&x.inner.segname, "__DATA_CONST")) {
3404 self.data_const_segment_cmd_index = i;
3405 }
3406 },
3407 macho.LC_DYLD_INFO_ONLY => {
3408 self.dyld_info_cmd_index = i;
3409 },
3410 macho.LC_SYMTAB => {
3411 self.symtab_cmd_index = i;
3412 },
3413 macho.LC_DYSYMTAB => {
3414 self.dysymtab_cmd_index = i;
3415 },
3416 macho.LC_LOAD_DYLINKER => {
3417 self.dylinker_cmd_index = i;
3418 },
3419 macho.LC_VERSION_MIN_MACOSX, macho.LC_VERSION_MIN_IPHONEOS, macho.LC_VERSION_MIN_WATCHOS, macho.LC_VERSION_MIN_TVOS => {
3420 self.version_min_cmd_index = i;
3421 },
3422 macho.LC_SOURCE_VERSION => {
3423 self.source_version_cmd_index = i;
3424 },
3425 macho.LC_UUID => {
3426 self.uuid_cmd_index = i;
3427 },
3428 macho.LC_MAIN => {
3429 self.main_cmd_index = i;
3430 },
3431 macho.LC_LOAD_DYLIB => {
3432 const x = cmd.Dylib;
3433 if (parseAndCmpName(x.data, mem.spanZ(LIB_SYSTEM_PATH))) {
3434 self.libsystem_cmd_index = i;
3435 }
3436 },
3437 macho.LC_FUNCTION_STARTS => {
3438 self.function_starts_cmd_index = i;
3439 },
3440 macho.LC_DATA_IN_CODE => {
3441 self.data_in_code_cmd_index = i;
3442 },
3443 macho.LC_CODE_SIGNATURE => {
3444 self.code_signature_cmd_index = i;
3445 },
3446 else => {
3447 log.warn("Unknown load command detected: 0x{x}.", .{cmd.cmd()});
3448 },
3449 }
3450 self.load_commands.appendAssumeCapacity(cmd);
3451 }
3452 self.header = header;
3453}
3454
3455fn parseAndCmpName(name: []const u8, needle: []const u8) bool {
3456 const len = mem.indexOfScalar(u8, name, @as(u8, 0)) orelse name.len;
3457 return mem.eql(u8, name[0..len], needle);
3458}
3459
3460fn parseSymbolTable(self: *MachO) !void {
3461 const symtab = self.load_commands.items[self.symtab_cmd_index.?].Symtab;
3462 const dysymtab = self.load_commands.items[self.dysymtab_cmd_index.?].Dysymtab;
3463
3464 var buffer = try self.base.allocator.alloc(macho.nlist_64, symtab.nsyms);
3465 defer self.base.allocator.free(buffer);
3466 const nread = try self.base.file.?.preadAll(@ptrCast([*]u8, buffer)[0 .. symtab.nsyms * @sizeOf(macho.nlist_64)], symtab.symoff);
3467 assert(@divExact(nread, @sizeOf(macho.nlist_64)) == buffer.len);
3468
3469 try self.locals.ensureCapacity(self.base.allocator, dysymtab.nlocalsym);
3470 try self.globals.ensureCapacity(self.base.allocator, dysymtab.nextdefsym);
3471 try self.undef_symbols.ensureCapacity(self.base.allocator, dysymtab.nundefsym);
3472
3473 self.locals.appendSliceAssumeCapacity(buffer[dysymtab.ilocalsym .. dysymtab.ilocalsym + dysymtab.nlocalsym]);
3474 self.globals.appendSliceAssumeCapacity(buffer[dysymtab.iextdefsym .. dysymtab.iextdefsym + dysymtab.nextdefsym]);
3475 self.undef_symbols.appendSliceAssumeCapacity(buffer[dysymtab.iundefsym .. dysymtab.iundefsym + dysymtab.nundefsym]);
3476}
3477
3478fn parseStringTable(self: *MachO) !void {
3479 const symtab = self.load_commands.items[self.symtab_cmd_index.?].Symtab;
3480
3481 var buffer = try self.base.allocator.alloc(u8, symtab.strsize);
3482 defer self.base.allocator.free(buffer);
3483 const nread = try self.base.file.?.preadAll(buffer, symtab.stroff);
3484 assert(nread == buffer.len);
3485
3486 try self.string_table.ensureCapacity(self.base.allocator, symtab.strsize);
3487 self.string_table.appendSliceAssumeCapacity(buffer);
3488}
3489
3490fn fixupBindInfo(self: *MachO, dylib_ordinal: u32) !void {
3491 const dyld_info = self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfoOnly;
3492 var buffer = try self.base.allocator.alloc(u8, dyld_info.bind_size);
3493 defer self.base.allocator.free(buffer);
3494 const nread = try self.base.file.?.preadAll(buffer, dyld_info.bind_off);
3495 assert(nread == buffer.len);
3496 try self.fixupInfoCommon(buffer, dylib_ordinal);
3497 try self.base.file.?.pwriteAll(buffer, dyld_info.bind_off);
3498}
3499
3500fn fixupLazyBindInfo(self: *MachO, dylib_ordinal: u32) !void {
3501 const dyld_info = self.load_commands.items[self.dyld_info_cmd_index.?].DyldInfoOnly;
3502 var buffer = try self.base.allocator.alloc(u8, dyld_info.lazy_bind_size);
3503 defer self.base.allocator.free(buffer);
3504 const nread = try self.base.file.?.preadAll(buffer, dyld_info.lazy_bind_off);
3505 assert(nread == buffer.len);
3506 try self.fixupInfoCommon(buffer, dylib_ordinal);
3507 try self.base.file.?.pwriteAll(buffer, dyld_info.lazy_bind_off);
3508}
3509
3510fn fixupInfoCommon(self: *MachO, buffer: []u8, dylib_ordinal: u32) !void {
3511 var stream = std.io.fixedBufferStream(buffer);
3512 var reader = stream.reader();
3513
3514 while (true) {
3515 const inst = reader.readByte() catch |err| switch (err) {
3516 error.EndOfStream => break,
3517 else => return err,
3518 };
3519 const imm: u8 = inst & macho.BIND_IMMEDIATE_MASK;
3520 const opcode: u8 = inst & macho.BIND_OPCODE_MASK;
3521
3522 switch (opcode) {
3523 macho.BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM => {
3524 var next = try reader.readByte();
3525 while (next != @as(u8, 0)) {
3526 next = try reader.readByte();
3527 }
3528 },
3529 macho.BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB => {
3530 _ = try std.leb.readULEB128(u64, reader);
3531 },
3532 macho.BIND_OPCODE_SET_DYLIB_SPECIAL_IMM, macho.BIND_OPCODE_SET_DYLIB_ORDINAL_IMM => {
3533 // Perform the fixup.
3534 try stream.seekBy(-1);
3535 var writer = stream.writer();
3536 try writer.writeByte(macho.BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | @truncate(u4, dylib_ordinal));
3537 },
3538 macho.BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB => {
3539 _ = try std.leb.readULEB128(u64, reader);
3540 },
3541 macho.BIND_OPCODE_SET_ADDEND_SLEB => {
3542 _ = try std.leb.readILEB128(i64, reader);
3543 },
3544 else => {},
3545 }
3546 }
3547}
3548
35493265pub fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) {
35503266 // TODO https://github.com/ziglang/zig/issues/1284
35513267 return std.math.add(@TypeOf(actual_size), actual_size, actual_size / ideal_factor) catch