我正在尝试编写一个没有 main 的 C++ 程序。是否可以将 mach-o 可执行文件的入口点更改为自定义函数(除了main())?
如果没有,那么,是否可以在main调用实际的 C 之前包装以调用我的 main 版本main?
编辑:
我想我的自定义函数调用 C main。如果我给它一个构造函数属性或将它添加到 ctor 列表,那么main将被调用两次。我不希望这种情况发生。
PS 我正在 Mac OS X High Sierra 中使用 clang 版本 9.1.0 构建可执行文件
您可以使用-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_MAIN和LC_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.
只需确保声明derp为extern "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)