fix(macos): add LC_BUILD_VERSION + codesign diagnostics

Modern macOS binaries require LC_BUILD_VERSION to declare platform
and minimum OS version. Without it, the kernel may reject the binary.

- Add LC_BUILD_VERSION (platform=macOS, minos=11.0, sdk=14.0) to both
  MachOWriter (x64) and MachOWriterArm64 (arm64)
- ncmds 9→10, sizeofcmds += 24
- Add codesign -dv / codesign --verify / spctl / otool -l diagnostics
  to macOS workflow smoke test to identify why binaries get Killed:9
这个提交包含在:
2026-08-03 22:16:03 +08:00
父节点 3f7eef64da
当前提交 38faa8347b
修改 3 个文件,包含 44 行新增20 行删除
+20 -16
查看文件
@@ -93,26 +93,30 @@ jobs:
- name: Smoke test — compile hello.pe - name: Smoke test — compile hello.pe
env: env:
# arm64 构建用 --arch arm 产出 arm64 Mach-O;x64 用默认 AMD64。
# x64 产物在 macos-14 (arm64) 上经 Rosetta 2 运行。
ARCH_FLAG: ${{ matrix.arch == 'arm64' && '--arch arm' || '' }} ARCH_FLAG: ${{ matrix.arch == 'arm64' && '--arch arm' || '' }}
run: | run: |
BIN="staging/paze-${{ steps.meta.outputs.version }}-macos-${{ matrix.arch }}/bin" BIN="staging/paze-${{ steps.meta.outputs.version }}-macos-${{ matrix.arch }}/bin"
if [ -f "$BIN/paze" ]; then PAZE="$BIN/paze"
"$BIN/paze" tests/hello.pe --target macos $ARCH_FLAG -o /tmp/hello.macos if [ -f "$BIN/paze.dll" ] && [ ! -f "$PAZE" ]; then PAZE="dotnet $BIN/paze.dll"; fi
file /tmp/hello.macos if [ -z "$PAZE" ] || [ ! -f "$BIN/paze" ]; then
chmod +x /tmp/hello.macos echo "WARN: paze binary not found, listing bin/:"; ls -la "$BIN"; exit 0
# macOS 上执行编译产物(Mach-O 原生可执行;x64 经 Rosetta 2
/tmp/hello.macos || true
elif [ -f "$BIN/paze.dll" ]; then
dotnet "$BIN/paze.dll" tests/hello.pe --target macos $ARCH_FLAG -o /tmp/hello.macos
file /tmp/hello.macos
chmod +x /tmp/hello.macos
/tmp/hello.macos || true
else
echo "WARN: paze binary not found, listing bin/:"
ls -la "$BIN"
fi fi
$PAZE tests/hello.pe --target macos $ARCH_FLAG -o /tmp/hello.macos
file /tmp/hello.macos
chmod +x /tmp/hello.macos
# 诊断代码签名
echo "=== codesign display ==="
codesign -dv --verbose=4 /tmp/hello.macos 2>&1 || true
echo "=== codesign verify ==="
codesign --verify --deep --strict /tmp/hello.macos 2>&1 && echo "SIGNATURE OK" || echo "SIGNATURE FAILED"
echo "=== spctl assessment ==="
spctl --assess --type execute /tmp/hello.macos 2>&1 || true
echo "=== try run ==="
/tmp/hello.macos 2>&1; echo "exit code: $?"
- name: Dump Mach-O load commands
run: |
otool -l /tmp/hello.macos 2>&1 | head -120 || true
- name: Upload artifact - name: Upload artifact
uses: actions/upload-artifact@v4 uses: actions/upload-artifact@v4
+12 -2
查看文件
@@ -29,6 +29,7 @@ public sealed class MachOWriter : IExecutableWriter
private const uint LC_DYSYMTAB = 0x0B; private const uint LC_DYSYMTAB = 0x0B;
private const uint LC_MAIN = 0x80000028; private const uint LC_MAIN = 0x80000028;
private const uint LC_CODE_SIGNATURE = 0x1D; private const uint LC_CODE_SIGNATURE = 0x1D;
private const uint LC_BUILD_VERSION = 0x32;
private const int VM_PROT_READ = 1, VM_PROT_WRITE = 2, VM_PROT_EXECUTE = 4; private const int VM_PROT_READ = 1, VM_PROT_WRITE = 2, VM_PROT_EXECUTE = 4;
private const int S_NON_LAZY_SYMBOL_POINTERS = 0x06; private const int S_NON_LAZY_SYMBOL_POINTERS = 0x06;
// nlist n_type // nlist n_type
@@ -160,8 +161,9 @@ public sealed class MachOWriter : IExecutableWriter
int lcSymtab = 24; int lcSymtab = 24;
int lcDysymtab = 80; int lcDysymtab = 80;
int lcCodeSig = 16; // linkedit_data_commandcmd+cmdsize+dataoff+datasize int lcCodeSig = 16; // linkedit_data_commandcmd+cmdsize+dataoff+datasize
int sizeofcmds = segTextCmd + segDataCmd + segLinkCmd + lcDylinker + lcDylib + lcMain + lcSymtab + lcDysymtab + lcCodeSig; int lcBuildVer = 24; // build_version_commandcmd+cmdsize+platform+minos+sdk+ntools
int ncmds = 9; int sizeofcmds = segTextCmd + segDataCmd + segLinkCmd + lcDylinker + lcDylib + lcMain + lcSymtab + lcDysymtab + lcCodeSig + lcBuildVer;
int ncmds = 10;
int headerSize = 32; int headerSize = 32;
int textFileOff = headerSize + sizeofcmds; // __text 文件偏移 int textFileOff = headerSize + sizeofcmds; // __text 文件偏移
@@ -331,6 +333,14 @@ public sealed class MachOWriter : IExecutableWriter
Write32At(f2, 0); Write32At(f2, 0); // extreloff, nextrel Write32At(f2, 0); Write32At(f2, 0); // extreloff, nextrel
Write32At(f2, 0); Write32At(f2, 0); // locreloff, nlocrel Write32At(f2, 0); Write32At(f2, 0); // locreloff, nlocrel
// ---- LC_BUILD_VERSION ----
Write32At(f2, LC_BUILD_VERSION);
Write32At(f2, 24); // cmdsize
Write32At(f2, 1); // platform = PLATFORM_MACOS
Write32At(f2, 0x000B0000); // minos = macOS 11.0.0
Write32At(f2, 0x000E0000); // sdk = macOS 14.0.0
Write32At(f2, 0); // ntools = 0
// ---- LC_CODE_SIGNATURE ---- // ---- LC_CODE_SIGNATURE ----
Write32At(f2, LC_CODE_SIGNATURE); Write32At(f2, LC_CODE_SIGNATURE);
Write32At(f2, 16); // cmdsize (linkedit_data_command) Write32At(f2, 16); // cmdsize (linkedit_data_command)
+12 -2
查看文件
@@ -32,6 +32,7 @@ public sealed class MachOWriterArm64 : IExecutableWriter
private const uint LC_DYSYMTAB = 0x0B; private const uint LC_DYSYMTAB = 0x0B;
private const uint LC_MAIN = 0x80000028; private const uint LC_MAIN = 0x80000028;
private const uint LC_CODE_SIGNATURE = 0x1D; private const uint LC_CODE_SIGNATURE = 0x1D;
private const uint LC_BUILD_VERSION = 0x32;
private const int VM_PROT_READ = 1, VM_PROT_WRITE = 2, VM_PROT_EXECUTE = 4; private const int VM_PROT_READ = 1, VM_PROT_WRITE = 2, VM_PROT_EXECUTE = 4;
private const int S_NON_LAZY_SYMBOL_POINTERS = 0x06; private const int S_NON_LAZY_SYMBOL_POINTERS = 0x06;
private const byte N_EXT = 0x01, N_SECT = 0x0e; private const byte N_EXT = 0x01, N_SECT = 0x0e;
@@ -139,8 +140,9 @@ public sealed class MachOWriterArm64 : IExecutableWriter
int lcSymtab = 24; int lcSymtab = 24;
int lcDysymtab = 80; int lcDysymtab = 80;
int lcCodeSig = 16; // linkedit_data_commandcmd+cmdsize+dataoff+datasize int lcCodeSig = 16; // linkedit_data_commandcmd+cmdsize+dataoff+datasize
int sizeofcmds = segTextCmd + segDataCmd + segLinkCmd + lcDylinker + lcDylib + lcMain + lcSymtab + lcDysymtab + lcCodeSig; int lcBuildVer = 24; // build_version_commandcmd+cmdsize+platform+minos+sdk+ntools
int ncmds = 9; int sizeofcmds = segTextCmd + segDataCmd + segLinkCmd + lcDylinker + lcDylib + lcMain + lcSymtab + lcDysymtab + lcCodeSig + lcBuildVer;
int ncmds = 10;
int headerSize = 32; int headerSize = 32;
int textFileOff = headerSize + sizeofcmds; int textFileOff = headerSize + sizeofcmds;
@@ -329,6 +331,14 @@ public sealed class MachOWriterArm64 : IExecutableWriter
Write32At(f2, 0); Write32At(f2, 0); Write32At(f2, 0); Write32At(f2, 0);
Write32At(f2, 0); Write32At(f2, 0); Write32At(f2, 0); Write32At(f2, 0);
// ---- LC_BUILD_VERSION ----
Write32At(f2, LC_BUILD_VERSION);
Write32At(f2, 24); // cmdsize
Write32At(f2, 1); // platform = PLATFORM_MACOS
Write32At(f2, 0x000B0000); // minos = macOS 11.0.0
Write32At(f2, 0x000E0000); // sdk = macOS 14.0.0
Write32At(f2, 0); // ntools = 0
// ---- LC_CODE_SIGNATURE ---- // ---- LC_CODE_SIGNATURE ----
Write32At(f2, LC_CODE_SIGNATURE); Write32At(f2, LC_CODE_SIGNATURE);
Write32At(f2, 16); // cmdsize (linkedit_data_command) Write32At(f2, 16); // cmdsize (linkedit_data_command)