11

我有一个简单的 C 应用程序:

#include <stdio.h>

int main() {
  printf("Hello, world!\n");
}

当我:

  1. 在 Apple Silicon 设备上构建它
  2. 瞄准 arm64
  3. 使用为 x86_64 编译的构建系统
  4. 替换现有的二进制文件(例如在重建期间)

最终的二进制文件无法执行,并根据 shell 报告为“已终止”:

% rm hello

# arch simulates the build system which is still compiled for x86_64
% arch -x86_64 cc -arch arm64 hello.c -o hello

% ./hello
Hello, world!

% arch -x86_64 cc -arch arm64 hello.c -o hello

% ./hello
zsh: killed     ./hello

如果我的构建系统是原生 arm64(或 arm64e),那么就没有问题:

% rm hello

% arch -arm64e cc -arch arm64 hello.c -o hello

% ./hello
Hello, world!

% arch -arm64e cc -arch arm64 hello.c -o hello

% ./hello
Hello, world!

如果我将二进制文件复制到新路径然后替换代码签名,那么它可以工作:

% cp hello hello2

% codesign -s - -f hello2
hello2: replacing existing signature

% ./hello2
Hello, world!

原版复现步骤及调试

当我在 Apple Silicon 设备上构建它时,针对 arm64,但使用为 x86_64 编译的构建系统,最终的二进制文件无法执行,并且根据 shell 报告为“已终止”:

# arch simulates the build system which is still compiled for x86_64
% arch -x86_64 cc -arch arm64 hello.c -o hello

% file hello
hello: Mach-O 64-bit executable arm64

% ./hello
zsh: killed     ./hello

即使尝试调试它也会失败:

% lldb hello
(lldb) target create "hello"
zsh: killed     lldb hello

作为一种解决方法,我可以在调用之前使用 shim 编译器“重置”回 arm64 环境cc,但这很不雅,而且感觉我缺少一些配置以避免跳过这么多的障碍。

% cc --version
Apple clang version 12.0.0 (clang-1200.0.32.27)
Target: arm64-apple-darwin20.1.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

这是在 macOS Big Sur 11.0.1 上。

从 x86_64 交叉编译

如果我从 x86_64 机器交叉编译并 scp 周围的二进制文件,文件执行得很好:

% SDKROOT=$(xcrun -sdk macosx11.0 --show-sdk-path) \
MACOSX_DEPLOYMENT_TARGET=$(xcrun -sdk macosx11.0 --show-sdk-platform-version) \
cc -arch arm64 hello.c -o hello

% scp hello silicon:/tmp/hello-cross

换机...

% file /tmp/hello-cross
/tmp/hello-cross: Mach-O 64-bit executable arm64

% /tmp/hello-cross
Hello, world!

跟踪子进程

添加--verbosecc调用会打印出子进程(我添加了换行符以突出显示其他调试中的那些):

% arch -x86_64 cc --verbose -arch arm64 hello.c -o hello
Apple clang version 12.0.0 (clang-1200.0.32.27)
Target: aarch64-apple-darwin20.1.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin

 "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang" -cc1 -triple arm64-apple-macosx11.0.0 -Wdeprecated-objc-isa-usage -Werror=deprecated-objc-isa-usage -Werror=implicit-function-declaration -emit-obj -mrelax-all -disable-free -disable-llvm-verifier -discard-value-names -main-file-name hello.c -mrelocation-model pic -pic-level 2 -mthread-model posix -mframe-pointer=non-leaf -fno-strict-return -masm-verbose -munwind-tables -target-sdk-version=11.0 -target-cpu vortex -target-feature +v8.3a -target-feature +fp-armv8 -target-feature +neon -target-feature +crc -target-feature +crypto -target-feature +fullfp16 -target-feature +ras -target-feature +lse -target-feature +rdm -target-feature +rcpc -target-feature +zcm -target-feature +zcz -target-feature +sha2 -target-feature +aes -target-abi darwinpcs -fallow-half-arguments-and-returns -dwarf-column-info -debugger-tuning=lldb -target-linker-version 609.6 -v -resource-dir /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/12.0.0 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk -I/usr/local/include -internal-isystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/local/include -internal-isystem /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/12.0.0/include -internal-externc-isystem /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include -internal-externc-isystem /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include -Wno-reorder-init-list -Wno-implicit-int-float-conversion -Wno-c99-designator -Wno-final-dtor-non-final-class -Wno-extra-semi-stmt -Wno-misleading-indentation -Wno-quoted-include-in-framework-header -Wno-implicit-fallthrough -Wno-enum-enum-conversion -Wno-enum-float-conversion -fdebug-compilation-dir /tmp/example -ferror-limit 19 -fmessage-length 237 -stack-protector 1 -fstack-check -mdarwin-stkchk-strong-link -fblocks -fencode-extended-block-signature -fregister-global-dtors-with-atexit -fgnuc-version=4.2.1 -fobjc-runtime=macosx-11.0.0 -fmax-type-align=16 -fdiagnostics-show-option -fcolor-diagnostics -o /var/folders/j2/g4_hr3jd2sz415vrf7b1d6300000gp/T/hello-232f6b.o -x c hello.c

clang -cc1 version 12.0.0 (clang-1200.0.32.27) default target x86_64-apple-darwin20.1.0
ignoring nonexistent directory "/usr/local/include"
ignoring nonexistent directory "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/local/include"
ignoring nonexistent directory "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/Library/Frameworks"
#include "..." search starts here:
#include <...> search starts here:
 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/12.0.0/include
 /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include
 /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include
 /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks (framework directory)
End of search list.

 "/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld" -demangle -lto_library /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/libLTO.dylib -no_deduplicate -dynamic -arch arm64 -platform_version macos 11.0.0 11.0 -syslibroot /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk -o hello -L/usr/local/lib /var/folders/j2/g4_hr3jd2sz415vrf7b1d6300000gp/T/hello-232f6b.o -lSystem /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/clang/12.0.0/lib/darwin/libclang_rt.osx.a

编译器调用 has-triple arm64-apple-macosx11.0.0和链接器调用 has -arch arm64,因此似乎正在传递适当的值。

比较失败和成功的二进制文件

正如评论中所建议的,我尝试比较这两个二进制文件。不幸的是,一旦打开失败的可执行文件,建议的Beyond Compare工具也会崩溃。我怀疑这与 LLDB 报告被杀的根本原因相同。

同时,这是比较原始十六进制数据的输出:

--- /tmp/hello-cross.hex        2020-11-14 05:07:04.000000000 -0800
+++ ./hello.hex 2020-11-14 05:06:52.000000000 -0800
@@ -74,10 +74,10 @@
 00000490: 0000 0000 0000 0000 0000 0000 0000 0000  ................
 000004a0: 0e00 0000 2000 0000 0c00 0000 2f75 7372  .... ......./usr
 000004b0: 2f6c 6962 2f64 796c 6400 0000 0000 0000  /lib/dyld.......
-000004c0: 1b00 0000 1800 0000 7b34 532d f414 3f99  ........{4S-..?.
-000004d0: a866 f4d8 29bf f7ce 3200 0000 2000 0000  .f..)...2... ...
+000004c0: 1b00 0000 1800 0000 0ad8 b6d9 c6c4 32f0  ..............2.
+000004d0: 9522 80e2 f036 54f7 3200 0000 2000 0000  ."...6T.2... ...
 000004e0: 0100 0000 0000 0b00 0000 0b00 0100 0000  ................
-000004f0: 0300 0000 0006 6102 2a00 0000 1000 0000  ......a.*.......
+000004f0: 0300 0000 0007 6102 2a00 0000 1000 0000  ......a.*.......
 00000500: 0000 0000 0000 0000 2800 0080 1800 0000  ........(.......
 00000510: 543f 0000 0000 0000 0000 0000 0000 0000  T?..............
 00000520: 0c00 0000 3800 0000 1800 0000 0200 0000  ....8...........
@@ -3094,9 +3094,9 @@
 0000c150: 0000 0000 0000 0000 0000 0000 0000 0000  ................
 0000c160: 0000 0000 0000 0000 0000 0000 0000 0000  ................
 0000c170: 0000 4000 0000 0000 0000 0001 6865 6c6c  ..@.........hell
-0000c180: 6f00 e40f cd6f 1abe f672 0c10 0915 8b30  o....o...r.....0
-0000c190: 5c9a 4a69 c9eb efdd a655 11c8 f5dc 3d86  \.Ji.....U....=.
-0000c1a0: b3d5 ad7f acb2 586f c6e9 66c0 04d7 d1d1  ......Xo..f.....
+0000c180: 6f00 29f3 685d 60bf c358 4179 1735 b8b0  o.).h]`..XAy.5..
+0000c190: d018 3ec5 aa3c 0f60 cc8b a4f2 23bf b37d  ..>..<.`....#..}
+0000c1a0: 9ee8 ad7f acb2 586f c6e9 66c0 04d7 d1d1  ......Xo..f.....
 0000c1b0: 6b02 4f58 05ff 7cb4 7c7a 85da bd8b 4889  k.OX..|.|z....H.
 0000c1c0: 2ca7 ad7f acb2 586f c6e9 66c0 04d7 d1d1  ,.....Xo..f.....
 0000c1d0: 6b02 4f58 05ff 7cb4 7c7a 85da bd8b 4889  k.OX..|.|z....H.

在两个文件上运行otool -fahlLDtvV并比较输出结果:

--- /tmp/hello-cross.dump       2020-11-14 05:41:10.000000000 -0800
+++ hello.dump  2020-11-14 05:41:22.000000000 -0800
@@ -226,7 +226,7 @@
 Load command 9
      cmd LC_UUID
  cmdsize 24
-    uuid 7B34532D-F414-3F99-A866-F4D829BFF7CE
+    uuid 0AD8B6D9-C6C4-32F0-9522-80E2F03654F7
 Load command 10
        cmd LC_BUILD_VERSION
    cmdsize 32
@@ -235,7 +235,7 @@
      minos 11.0
     ntools 1
       tool ld
-   version 609.6
+   version 609.7
 Load command 11
       cmd LC_SOURCE_VERSION
   cmdsize 16

这似乎对应于原始十六进制转储的第一个大块,这表明重要的区别在于第二个大块。

代码签名

MachOView指示地址0xc180出现在“代码签名”部分中。但是,签名似乎足够有效:

% codesign --verify --verbose hello
hello: valid on disk
hello: satisfies its Designated Requirement

查看 Console.app,我确实看到了以下几行:

CODE SIGNING: cs_invalid_page(0x10439c000): p=32470[hello] final status 0x23020200, denying page sending SIGKILL
CODE SIGNING: process 32470[hello]: rejecting invalid page at address 0x10439c000 from offset 0x0 in file "/private/tmp/example/hello" (cs_mtime:1605366572.426749233 == mtime:1605366572.426749233) (signed:1 validated:1 tainted:1 nx:0 wpmapped:1 dirty:0 depth:0)
4

0 回答 0