New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
macOS: lld lacks code signing for macOS/arm64 #6971
Comments
Thanks @daurnimator! Although code singing would be something! ;-) |
OK, I can't replicate the issue on my x86_64 MBP running Big Sur Public Beta which is a good news wrt to 0.7.0 release. On the other hand, I'm still not sure why there is this additional requirement/limitation on ARM64 Big Sur Public Beta. |
👀 Zig seems pretty usable on Big Sur arm64 today — I don't think I'm accidentally using the system linker hack, either, as the binary called appears to be $ cat hello.zig
const std = @import("std");
pub fn main() void {
std.debug.print("Hello from {} {}\n", .{ std.builtin.os.tag, std.builtin.arch });
}
$ zig run --verbose-link hello.zig
ld64.lld -error-limit 0 -demangle -dynamic -arch arm64 -macosx_version_min 11.1.0 -sdk_version 11.1.0 -pie -o /Users/kameliya/.cache/zig/o/83ffe50c4e7a24c53c08701f0e40de60/hello -syslibroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk /Users/kameliya/.cache/zig/o/83ffe50c4e7a24c53c08701f0e40de60/hello.o /Users/kameliya/.cache/zig/o/caa476c6b81d0829f3d079cc3e94fba2/libcompiler_rt.a -lSystem
Hello from Tag.macos Arch.aarch64
$ Not sure if this is news or not, just wanted to share since I'm motivated and happy to see Zig working on macos/aarch64. |
Hey @kivikakk! I'm glad you're having good experience with Zig on Apple Silicon!
You're right, you are using LLD to do the linking on Apple Silicon. However, it's Zig that does the code signing postmortem, after LLD spits out the linked final binary here: if (self.code_signature_cmd_index == null) outer: {
if (target.cpu.arch != .aarch64) break :outer; // This is currently needed only for aarch64 targets.
const text_segment = self.load_commands.items[self.text_segment_cmd_index.?].Segment;
const text_section = text_segment.sections.items[self.text_section_index.?];
const after_last_cmd_offset = self.header.?.sizeofcmds + @sizeOf(macho.mach_header_64);
const needed_size = @sizeOf(macho.linkedit_data_command) * alloc_num / alloc_den;
if (needed_size + after_last_cmd_offset > text_section.offset) {
std.log.err("Unable to extend padding between the end of load commands and start of __text section.", .{});
std.log.err("Re-run the linker with '-headerpad 0x{x}' option if available, or", .{needed_size});
std.log.err("fall back to the system linker by exporting 'ZIG_SYSTEM_LINKER_HACK=1'.", .{});
return error.NotEnoughPadding;
}
const linkedit_segment = self.load_commands.items[self.linkedit_segment_cmd_index.?].Segment;
// TODO This is clunky.
self.linkedit_segment_next_offset = @intCast(u32, mem.alignForwardGeneric(u64, linkedit_segment.inner.fileoff + linkedit_segment.inner.filesize, @sizeOf(u64)));
// Add code signature load command
self.code_signature_cmd_index = @intCast(u16, self.load_commands.items.len);
try self.load_commands.append(self.base.allocator, .{
.LinkeditData = .{
.cmd = macho.LC_CODE_SIGNATURE,
.cmdsize = @sizeOf(macho.linkedit_data_command),
.dataoff = 0,
.datasize = 0,
},
});
// Pad out space for code signature
try self.writeCodeSignaturePadding();
// Write updated load commands and the header
try self.writeLoadCommands();
try self.writeHeader();
// Generate adhoc code signature
try self.writeCodeSignature();
}
} Sadly, LLD itself doesn't have code signing mechanism in place yet, so we've decided to patch up the binary ourselves in the pipeline. This will work 99 out of 100 times; however we rely on the fact that there will be enough padding between the end of the load commands and the beginning of the
As an added bonus, did you know that cross-compiling Zig and C to Apple Silicon should also generate valid (i.e., code signed and runnable) binaries? Something like this, on any platform of your choosing, should generate a valid Mach-O for Apple Silicon:
The changes required to get this working landed in upstream yesterday in this PR #7318. This again involves a postmortem analysis and patching of the LLD generated binary, and works for Zig and C. For C++ on the other hand, there are other outstanding problems which it looks like will need to be fixed by LLD itself to get this working. |
I should probably update the issue to reflect what's mentioned above. Thanks for pointing this out @kivikakk! |
As reported by @jedisct1 (and confirmed by myself):
This is tracker issue for upstream
lld
implementation of code signing.EDIT: It is now possible to build Zig without falling back to system linker due to the fact Zig now patches the LLD generated binary and adds the missing code signature. The changes making it possible landed in #7273. As mentioned in the discussion below, this will work 99 out of 100 times; however we rely on the fact that there will be enough padding between the end of the load commands and the beginning of the
__text
section left by the LLD to be able to insert theLC_CODE_SIGNATURE
load command, and this 1 out of 100 times this will not be the case, but Zig will inform of this error and gracefully exit. In such cases, you can either add more code to your binary (yeah, no kidding), or fall back to the system linker. Once LLD adds-headerpad <size>
option, even if they don't add code signing, we should be able to always generate a valid code signature.The text was updated successfully, but these errors were encountered: