我正在尝试编写没有main的c ++程序。可以将mach-o可执行文件的入口点更改为自定义函数(main()
以外的其他函数)吗?
如果没有,那么是否可以在调用实际的C main
之前包装main
来调用我的main版本?
编辑:
我想在自定义函数中调用C main
。如果我给它一个构造函数属性或将其添加到ctor列表,那么main
将被调用两次。我不希望那样发生。
P.S我正在Mac OS X High Sierra中使用9.1.0版创建可执行文件
答案 0 :(得分:4)
您可以使用ld的-e <symbol>
选项,可以从clang中以-Wl,-e,_<symbol>
的身份调用。从历史上看,程序的入口点是来自crt0.o的_start
,但是自Mac OS X 10.8和iOS 6.0引入LC_MAIN
load命令以来,这在Darwin上就不存在了(替换LC_UNIXTHREAD
)。仍然可以使用“旧”方式,但是必须使用-no_new_main
链接器标志(如果需要,可以使用对应的-new_main
)显式启用它。由crt0.o承担的职责已转移到动态链接程序/usr/lib/dyld
,该链接程序可以根据需要处理LC_MAIN
和LC_UNIXTHREAD
。
给定一个带有main
的C程序:
// t.c
#include <stdio.h>
int main(int argc, const char **argv)
{
printf("test %i\n", argc);
return 0;
}
您可以轻松地创建一个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 });
}
并使用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
答案 1 :(得分:3)
您可以将-e <symbol name>
选项传递给链接器(ld
),以指定其他入口点。默认入口点不是main
; start
由crt1.o提供,并依次调用main
。
答案 2 :(得分:1)
您可以使用_start()
它设置一些东西,填充参数数组argv
,计算那里有多少参数,然后调用main
。 main
返回后,将调用exit
。
以下是一些参考:
https://stackoverflow.com/a/29694977/2302572
http://learningpearls.blogspot.com/2011/02/start-function-inside-c.html