为什么macOS会杀死clang创建的静态可执行文件



我有一个用于m1 arm cpu的最小c程序,它返回42:

void _start() {
asm("mov x0, #42;");
asm("mov x16, #1;");
asm("svc 0x80;");
}

此代码在告诉clang使用_start符号并返回正确的值后进行编译。

clang -Wl,-e, -Wl,__start test.c -o dyn.out
./dyn.out ; echo $?
42

然而,根据otool:,这个二进制文件仍然有动态链接

otool -L ./dyn.out 
./dyn.out:
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1311.100.3)

在告诉clang生成一个无符号静态二进制文件后,macOS在尝试运行时立即杀死该二进制文件。

clang -Wl,-e, -Wl,__start -static -nostdlib test.c -o static_no_sign.out
zsh: killed     ./static_no_sign.out

在运行之前对二进制文件进行签名也会产生同样的问题。

clang -Wl,-e, -Wl,__start -static -nostdlib test.c -o static_sign.out 
codesign -s - static_sign.out 
./static_sign.out 
zsh: killed     ./static_sign.out

控制台中生成以下消息:

taskgated: UNIX error exception: 3
taskgated: no signature for pid=93166 (cannot make code: UNIX[No such process])

但代码签名可以验证签名

codesign -v -v static_sign.out 
static_sign.out: valid on disk
static_sign.out: satisfies its Designated Requirement

有人能澄清为什么macOS决定杀死clang生成的二进制文件吗?

因为静态二进制文件在x86_64以外的任何体系结构上都是明确禁止的。
XNU在Mach-O加载程序中包含以下代码段:

case MH_EXECUTE:
if (depth != 1 && depth != 3) {
return LOAD_FAILURE;
}
if (header->flags & MH_DYLDLINK) {
/* Check properties of dynamic executables */
if (!(header->flags & MH_PIE) && pie_required(header->cputype, header->cpusubtype & ~CPU_SUBTYPE_MASK)) {
return LOAD_FAILURE;
}
result->needs_dynlinker = TRUE;
} else if (header->cputype == CPU_TYPE_X86_64) {
/* x86_64 static binaries allowed */
} else {
/* Check properties of static executables (disallowed except for development) */
#if !(DEVELOPMENT || DEBUG)
return LOAD_FAILURE;
#endif
}
break;

如果你在x86_64上做同样的事情,它会起作用:

void _start()
{
__asm__ volatile
(
".intel_syntax noprefixn"
"mov eax, 0x2000001n"
"mov edi, 42n"
"syscall"
);
}
% clang -Wl,-e,__start -static -nostdlib t.c -o t -arch x86_64
% ./t
% echo $?
42

相关内容

  • 没有找到相关文章

最新更新