分类:
2006-06-30 14:19:18
通常我们运行gcc来编译一个c语言程序,但是你编译知道背后的事情吗? 在嵌入式系统开发中,由于存储空间的限制,通常想尽办法来减小程序 的大小和运行效率,这里是一个怎样减小程序大小的例子:
源代码:
/***************** halo.c ***************************/
int main(void)
{
write(1,"hello\n", 6);
return 0;
}
/***************** end ******************************/
这样来编译:
(1)先把它变成汇编代码,使用gcc的-S选项
[root@localhost c]# gcc -S halo.c
(2)使用as汇编器进行汇编
[root@localhost c]# as -o halo.o halo.s
(3)使用连接器连接目标文件,并使用简洁的uClibc库
[root@localhost c]# ld -static -o halo halo.o /opt/uClibc/lib/crt0.o -L/opt/uClibc/lib -lc
(4)运行程序
[root@localhost c]# ./halo
hello
使用objdump和objcopy
====================
上面我们使用了uClibc库以减小整个程序的大小,其实在可执行二进制 文件中,有很多不必要的信息,我们可以使用objcopy把它们抽取掉, 程序仍然可以正常运行。
(1)检验抽取之前的大小:
#ls -l halo
-rwxr-xr-x 1 root root 2222 8 4 14:29 halo
(2)使用objdump进行进行信息检验
[root@localhost c]# objdump -h halo
halo: file format elf32-i386
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000198 08048074 08048074 00000074 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .rodata 00000007 0804820c 0804820c 0000020c 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .data 00000010 08049214 08049214 00000214 2**2
CONTENTS, ALLOC, LOAD, DATA
3 .got 00000034 08049224 08049224 00000224 2**2
CONTENTS, ALLOC, LOAD, DATA
4 .bss 00000000 08049258 08049258 00000258 2**2
ALLOC
5 .comment 00000037 00000000 00000000 00000258 2**0
CONTENTS, READONLY
6 .note 00000014 00000000 00000000 0000028f 2**0
CONTENTS, READONLY
[root@localhost c]#
(3)使用objcopy把不用的信息去掉:
[root@localhost c]# objcopy -R .comment -R .note halo halo.min
(4)再看一看程序的大小吧:
[root@localhost c]# ll
total 24
-rwxr-xr-x 1 root root 2222 8 4 14:29 halo
[root@localhost c]#
-rw-r--r-- 1 root root 54 8 4 14:23 halo.c
-rwxr-xr-x 1 root root 2022 8 4 14:35 halo.min
-rw-r--r-- 1 root root 912 8 4 14:28 halo.o
-rw-r--r-- 1 root root 393 8 4 14:28 halo.s
-rw-r--r-- 1 root root 1431 8 4 14:34 readme
咦........我们生成的halo.min比以前的halo小了一些哦:),还能不能运行啊?
检验一下:
[root@localhost c]# ./halo.min
hello
哈。。。还可以啊,能不能再减小一些呢?
(5)再减小!
同样先查看一下:
[root@localhost c]# objdump -h halo.min
halo.min: file format elf32-i386
Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000198 08048074 08048074 00000074 2**2
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .rodata 00000007 0804820c 0804820c 0000020c 2**0
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .data 00000010 08049214 08049214 00000214 2**2
CONTENTS, ALLOC, LOAD, DATA
3 .got 00000034 08049224 08049224 00000224 2**2
CONTENTS, ALLOC, LOAD, DATA
4 .bss 00000000 08049258 08049258 00000258 2**2
ALLOC
把comment段去掉,这些好像是注释信息吧:)
[root@localhost c]# objcopy -S -R .comment -R .note halo halo.min
看看大小先:
[root@localhost c]# ll
total 24
-rwxr-xr-x 1 root root 2222 8 4 14:29 halo
-rw-r--r-- 1 root root 54 8 4 14:23 halo.c
-rwxr-xr-x 1 root root 924 8 4 14:37 halo.min
-rw-r--r-- 1 root root 912 8 4 14:28 halo.o
-rw-r--r-- 1 root root 393 8 4 14:28 halo.s
-rw-r--r-- 1 root root 1972 8 4 14:36 readme
更小了啊,halo.min只有924个字节了,运行一下:
[root@localhost c]# ./halo.min
hello
[root@localhost c]#
还是可以的啊:)
接下来比较一下使用标准的c库与使用uClibc库的差距吧:
=================================================
[root@localhost c]# gcc -O2 -o halo-std halo.c
[root@localhost c]# ll
total 48
-rwxr-xr-x 1 root root 167 8 4 15:06 b
-rwxr-xr-x 1 root root 42 8 4 15:04 c
-rwxr-xr-x 1 root root 2218 8 4 15:07 halo
-rw-r--r-- 1 root root 79 8 4 15:07 halo.c
-rwxr-xr-x 1 root root 920 8 4 15:07 halo.min
-rw-r--r-- 1 root root 912 8 4 15:07 halo.o
-rw-r--r-- 1 root root 396 8 4 15:07 halo.s
-rwxr-xr-x 1 root root 13506 8 4 15:08 halo-std
-rw-r--r-- 1 root root 3194 8 4 14:43 readme
把程序strip一下:
[root@localhost c]# strip halo-std
[root@localhost c]# ll
total 36
-rwxr-xr-x 1 root root 167 8 4 15:06 b
-rwxr-xr-x 1 root root 42 8 4 15:04 c
-rwxr-xr-x 1 root root 2218 8 4 15:07 halo
-rw-r--r-- 1 root root 79 8 4 15:07 halo.c
-rwxr-xr-x 1 root root 920 8 4 15:07 halo.min
-rw-r--r-- 1 root root 912 8 4 15:07 halo.o
-rw-r--r-- 1 root root 396 8 4 15:07 halo.s
-rwxr-xr-x 1 root root 3088 8 4 15:09 halo-std
-rw-r--r-- 1 root root 3194 8 4 14:43 readme
可以看出,生成的最小的halo是2218个字节,比我们的924个字节还是多不少的哦:)