具有以下值CFLAGS:
-Wall -Werror -Wextra -pedantic -std=c99 -O3 -nostartfiles -nodefaultlibs
我的入口点__start(注意-nostartfiles)编译成功并将其放入可执行文件中。
但是,在添加标志时-flto,优化器会抛出入口点本身和仅由它调用的所有函数。此外,进一步链接的执行没有错误和警告,但具有不正确的(随机)入口点。
问题:如何防止删除函数__start?了解为什么链接器在优化期间“忘记”在没有内置入口点的情况下存在对我的入口点的依赖性也很有趣。
GCC 版本:gcc(i686-posix-dwarf-rev1,由 MinGW-W64 项目构建)4.9.2。
源代码(已更正以反映有关 Windows ABI 功能的注释[在原始版本中是注释,但在这里我将其添加到答案中 - 大约 Per.]):
#include <windows.h>
void _start()
{
MessageBox(NULL, TEXT("Hello world."), TEXT(""), MB_OK);
ExitProcess(0);
}
链接器发出的汇编代码(-S):
没有的选项
-flto:Disassembly of section .text: 00401000 <__start>: 401000: 83 ec 1c sub $0x1c,%esp 401003: c7 44 24 0c 00 00 00 movl $0x0,0xc(%esp) 40100a: 00 40100b: c7 44 24 08 00 20 40 movl $0x402000,0x8(%esp) 401012: 00 401013: c7 44 24 04 0d 20 40 movl $0x40200d,0x4(%esp) 40101a: 00 40101b: c7 04 24 00 00 00 00 movl $0x0,(%esp) 401022: ff 15 54 40 40 00 call *0x404054 401028: 83 ec 10 sub $0x10,%esp 40102b: c7 04 24 00 00 00 00 movl $0x0,(%esp) 401032: ff 15 4c 40 40 00 call *0x40404c 401038: 90 nop 401039: 90 nop 40103a: 90 nop 40103b: 90 nop 40103c: 90 nop 40103d: 90 nop 40103e: 90 nop 40103f: 90 nop 00401040 <__CTOR_LIST__>: 401040: ff (bad) 401041: ff (bad) 401042: ff (bad) 401043: ff 00 incl (%eax) 401045: 00 00 add %al,(%eax) ... 00401048 <__DTOR_LIST__>: 401048: ff (bad) 401049: ff (bad) 40104a: ff (bad) 40104b: ff 00 incl (%eax) 40104d: 00 00 add %al,(%eax)选项 c
-flto(注意没有_start,但有 API 函数的适配器):Disassembly of section .text: 00401000 <_ExitProcess@4>: 401000: ff 25 4c 30 40 00 jmp *0x40304c 401006: 90 nop 401007: 90 nop 00401008 <_MessageBoxA@16>: 401008: ff 25 54 30 40 00 jmp *0x403054 40100e: 90 nop 40100f: 90 nop 00401010 <__CTOR_LIST__>: 401010: ff (bad) 401011: ff (bad) 401012: ff (bad) 401013: ff 00 incl (%eax) 401015: 00 00 add %al,(%eax) ... 00401018 <__DTOR_LIST__>: 401018: ff (bad) 401019: ff (bad) 40101a: ff (bad) 40101b: ff 00 incl (%eax) 40101d: 00 00 add %al,(%eax)
这道题翻译的是《Prevent __start entry point from being optimized out》。
您需要确保此符号被视为入口点,而不是被链接器级优化丢弃。
要指定入口点,您必须将以下键传递给链接器:
或编写声明此符号的规范文件。但是,关键方法更简单。
并进一步。使用 Windows ABI 时,编译器会在 C 函数名称前隐式添加一个额外的下划线。结果
void __start()变成了___start,链接器看不到。这个答案是Jean-François Fabre的回答和fuz的评论的翻译。