如何在 Mac OS X 上构建包含入口点的 C 程序?
Posted
技术标签:
【中文标题】如何在 Mac OS X 上构建包含入口点的 C 程序?【英文标题】:How do you build a C program that includes the entry point on Mac OS X? 【发布时间】:2011-05-20 05:30:41 【问题描述】:我要建造:
start()
/* exit system call */
asm("movl $1,%eax;"
"xorl %ebx,%ebx;"
"int $0x80"
);
但是当我跑步时:
gcc -nostdlib min.c
我总是得到:
ld: could not find entry point "start" (perhaps missing crt1.o)
collect2: ld returned 1 exit status
我为了看看它在做什么而进行的另一次尝试是运行:
gcc -nostdlib -c min.c && otool -tV min.o
输出是:
(__TEXT,__text) section
_start:
0000000000000000 pushq %rbp
0000000000000001 movq %rsp,%rbp
0000000000000004 leave
0000000000000005 ret
那么在“开始”函数之前的下划线是从哪里来的呢?我该如何防止这种情况发生?或者更简单地说:
谢谢, CrazyChenz
【问题讨论】:
_start 可能是一个错误的名称。在创建开始之前,请注意必须进行大量预处理,否则各种问题都会中断。要了解符号,您必须定义 try nm crt1.o。 gcc -e main 使“main”成为入口点而不是 start。您可以通过这种方式定义您想要的任何功能。我不知道如何为 Xcode 设置该选项。其他人可能会。 IIRC,MacOS call numbers 与 Linux 不同,所以 eax=1 / int 0x80 可能不是 sys_exit。并且 32 位系统 MacOS 调用采用 FreeBSD 风格的堆栈参数,而不是 EBX、ECX、EDX,...。当然,如果制作 64 位可执行文件,您需要使用syscall
进行适当的调用数字/ arg-passing regs。
【参考方案1】:
gcc -e 选项定义了入口点,当您希望入口点不是 start 时。这样您就可以创建 mystart() 作为入口点。
gcc -e mystart mycode.c -o mycode
我不知道如何在 Xcode 中设置 -e 选项。
【讨论】:
MacOS 会使用前导_
来破坏名称,所以我认为您需要 gcc -e _mystart
。【参考方案2】:
你可以通过asm
单独声明来控制gcc赋予函数的符号:
void start() asm ("start");
确保这是一个独立的声明,与函数定义分开。
您可以在此处阅读有关控制生成符号的更多详细信息:https://***.com/a/1035937/12928775
此外,正如 Peter Cordes 所指出的,您可能应该在函数定义中包含 __attribute__((naked))
,以防止 gcc 在入口时生成堆栈帧。
完整的代码是:
void start() asm ("start");
__attribute__((naked)) void start()
/* exit system call */
asm("movl $1,%eax;"
"xorl %ebx,%ebx;"
"int $0x80"
);
【讨论】:
原型中不需要extern
。 godbolt.org/z/Vz77nS 表明 void start(void) asm("_mystart");
产生指定的名称。此外,您可能想要void
而不是使用旧版 C 隐式-int
。 __attribute__((naked))
对定义来说是个好主意; start
不是一个函数,所以你不希望 -O0 在入口处创建一个堆栈帧。
要获得额外积分,请记住 C 中的 ()
(与 C++ 不同)未指定 arg 类型,而不像 (void)
。不妨具体一点,它不需要任何参数。以上是关于如何在 Mac OS X 上构建包含入口点的 C 程序?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Mac OS X 主机上为 MIPS 目标构建 GCC 4.8.x
如何在 OS X Mavericks 上使用 Clang 设置自定义 C 入口点?
如何检查库是不是是在 Mac OS X 上构建的 32 位/64 位?