如何更改 c++ 文件的 mach-o 可执行文件的入口点?

Roh*_*hit 3 c++ mach-o clang

我正在尝试编写一个没有 main 的 C++ 程序。是否可以将 mach-o 可执行文件的入口点更改为自定义函数(除了main())?

如果没有,那么,是否可以在main调用实际的 C 之前包装以调用我的 main 版本main

编辑:

我想我的自定义函数调用 C main。如果我给它一个构造函数属性或将它添加到 ctor 列表,那么main将被调用两次。我不希望这种情况发生。

PS 我正在 Mac OS X High Sierra 中使用 clang 版本 9.1.0 构建可执行文件

Sig*_*uza 5

您可以使用-e <symbol>ld 选项,您可以-Wl,-e,_<symbol>从 clang 中调用该选项。从历史上看,程序的入口点将_start来自 crt0.o,但是自从 Mac OS X 10.8 和 iOS 6.0LC_MAIN引入(替换LC_UNIXTHREAD)加载命令后,Darwin 就不再存在这种情况。“旧”方式仍然可以使用,但必须使用-no_new_main链接器标志显式启用(-new_main如果您需要它,它有一个对应的)。一旦通过的crt0.o携带的占空比已转移到动态链接程序,/usr/lib/dyld,它可以同时处理LC_MAINLC_UNIXTHREAD根据需要。

所以给定一个 C 程序main

// t.c
#include <stdio.h>

int main(int argc, const char **argv)
{
    printf("test %i\n", argc);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

您可以轻松地创建一个 C++ 文件,如下所示:

// t.cpp

extern int main(int, const char**);

extern "C" int derp(int argc, const char **argv)
{
    return main(0, (const char*[]){ (const char*)0 });
}
Run Code Online (Sandbox Code Playgroud)

并用clang++ -o t t.cpp -xc t.c -Wl,-e,_derp.
只需确保声明derpextern "C",或在命令行上指定损坏的符号。

您还可以检查生成的可执行文件otool以确保它使用LC_MAIN而不是LC_UNIXTHREAD

bash$ otool -l ./t | fgrep -B1 -A3 LC_MAIN
Load command 11
       cmd LC_MAIN
   cmdsize 24
  entryoff 3808
 stacksize 0
Run Code Online (Sandbox Code Playgroud)