用mingw gcc各个版本编译出来的exe文件,都比VS编译的大一点。
分析文件发现是每个exe文件都包含一个叫作".eh_frame"的节,然而却没有找到去除这个数据节的办法!!!
测试方法:
编译一个空的main.c文件,如下内容:
#include <stdio.h>
void main(void)
{
printf("hello\n");
}
1.使用命令#gcc main.c 得到a.exe,这时包含调试信息,再用#strip a.exe去除调试信息。
发现a.exe里面也有.eh_frame章节。
2.使用命令#gcc -s main.c得到a.exe
这时a.exe还有是.eh_fram章节,注意与上面的a.exe有区别。
3.使用strip -R .eh_frame 强制去除这个数据节,结果程序不能正常运行了。
网上找了半天资料,试过加上如下各种参数:
-fno-exceptions
-fno-unwind-tables
-fno-asynchronous-unwind-tables
依然没能解决问题。
----------------------------------------------------------------
24小时后......
终于找到原因了,换了另外一个版本的gcc,编译出来的a.exe竟然没有.eh_frame段,而且体积会小2KB.
经过比较区别就是这个版本的gcc没有使用dwarf的异常模型!
使用gcc -v查看GCC的版本,会提示这个GCC的configure,如果带有--with-dwarf则说明是支持dwarf异常。
还记得Mingw-W64下载GCC的时候会选择线程模型(win32/posix)和异常模型(sjlj/dwarf)吗?
下载sjls异常的GCC编译出来的exe就没有.eh_frame!!!
之所以有这两种区别都是C++的事,只是没想到会影响我这个纯C开发者。
25小时后............
事情好像不是我想像中的那样,似乎与异常模型没有关系???
因为我交换了两个版本GCC自带的win32 library之后,原本出现.eh_frame的GCC竟然没有出现!
进一步研究,好像是CRT库搞的鬼。具体就是crt1.o和crt2.o这两个文件!
使用ojbdump查看crt1.o,这是自带.eh_frame的那个版本:
$../bin/objdump.exe -h crt1.o
crt1.o: file format pe-i386
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000500 00000000 00000000 00000294 2**4
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .data 00000004 00000000 00000000 00000794 2**2
CONTENTS, ALLOC, LOAD, DATA
2 .bss 0000001c 00000000 00000000 00000000 2**2
ALLOC
3 .text.unlikely 00000000 00000000 00000000 00000000 2**2
ALLOC, LOAD, READONLY, CODE
4 .CRT$XCAA 00000004 00000000 00000000 00000798 2**2
CONTENTS, ALLOC, LOAD, RELOC, DATA
5 .CRT$XIAA 00000004 00000000 00000000 0000079c 2**2
CONTENTS, ALLOC, LOAD, RELOC, DATA
6 .drectve 00000054 00000000 00000000 000007a0 2**2
CONTENTS, ALLOC, LOAD, DATA
7 .debug_info 00002203 00000000 00000000 000007f4 2**0
CONTENTS, RELOC, READONLY, DEBUGGING
8 .debug_abbrev 00000441 00000000 00000000 000029f7 2**0
CONTENTS, READONLY, DEBUGGING
9 .debug_loc 000002e3 00000000 00000000 00002e38 2**0
CONTENTS, RELOC, READONLY, DEBUGGING
10 .debug_aranges 00000020 00000000 00000000 0000311b 2**0
CONTENTS, RELOC, READONLY, DEBUGGING
11 .debug_ranges 00000088 00000000 00000000 0000313b 2**0
CONTENTS, READONLY, DEBUGGING
12 .debug_line 0000031c 00000000 00000000 000031c3 2**0
CONTENTS, RELOC, READONLY, DEBUGGING
13 .debug_str 000002f0 00000000 00000000 000034df 2**0
CONTENTS, READONLY, DEBUGGING
14 .rdata$zzz 0000002c 00000000 00000000 000037cf 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
15 .eh_frame 000000c8 00000000 00000000 000037fb 2**2
CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
下面是不带.eh_frame的版本
$../bin/objdump.exe -h crt1.o
crt1.o: file format pe-i386
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000500 00000000 00000000 0000026c 2**4
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .data 00000004 00000000 00000000 0000076c 2**2
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000020 00000000 00000000 00000000 2**2
ALLOC
3 .CRT$XCAA 00000004 00000000 00000000 00000770 2**2
CONTENTS, ALLOC, LOAD, RELOC, DATA
4 .CRT$XIAA 00000004 00000000 00000000 00000774 2**2
CONTENTS, ALLOC, LOAD, RELOC, DATA
5 .drectve 00000054 00000000 00000000 00000778 2**2
CONTENTS, ALLOC, LOAD, DATA
6 .debug_info 000023b4 00000000 00000000 000007cc 2**0
CONTENTS, RELOC, READONLY, DEBUGGING
7 .debug_abbrev 0000046f 00000000 00000000 00002b80 2**0
CONTENTS, READONLY, DEBUGGING
8 .debug_loc 000002e3 00000000 00000000 00002fef 2**0
CONTENTS, RELOC, READONLY, DEBUGGING
9 .debug_aranges 00000020 00000000 00000000 000032d2 2**0
CONTENTS, RELOC, READONLY, DEBUGGING
10 .debug_ranges 00000088 00000000 00000000 000032f2 2**0
CONTENTS, READONLY, DEBUGGING
11 .debug_line 00000361 00000000 00000000 0000337a 2**0
CONTENTS, RELOC, READONLY, DEBUGGING
12 .debug_str 00000235 00000000 00000000 000036db 2**0
CONTENTS, READONLY, DEBUGGING
13 .rdata$zzz 00000014 00000000 00000000 00003910 2**2
CONTENTS, ALLOC, LOAD, READONLY, DATA
14 .debug_frame 000000c0 00000000 00000000 00003924 2**2
CONTENTS, RELOC, READONLY, DEBUGGING
可以看出来,那个去不掉的.eh_frame竟然来自crt,暂时不知道如何生成这种版本的crt.o,待研究。。。
顺便记录一下,在这期间用到了几个有用的编译选项:
--pipe 不创建临时文件,加快编译速度
-s 编译后自动执行strip
-Os 优化目标文件体积
-fomit-frame-pointer
-march=i686
-Wl,--xxxx 设置链接参数