centosGCC 编译器集合,在安装 centos 时就自带了,
实际上MingW目录下的 GCC 编译器集合一样都是GNU组织开发的,只不过MingW是面向 windows

注意区分大写的GCC和小写的gcc

  • GCC:指编译器集合
  • gcc:指集合中的gcc程序

编译时,必须用到的基本程序 cpp、cc1、as、collect2/ld、gcc


一、cpp 预编译

通过which可以查看cpp的安装目录

$ which cpp
/usr/bin/cpp

演示

cpp helloword.c -o helloword.i

不指定目标文件,会直接将预处理后的结果输出到控制台(命令行)

二、cc1 编译

路径:/usr/libexec/gcc/x86_64-redhat-linux/4.8.2
无法通过which查看cc1的安装目录,因为cc1的安装目录没有加入环境变量

演示

/usr/libexec/gcc/x86_64-redhat-linux/4.8.2/cc1 helloword.i -o helloword.s

为什么要加路径?因为cc1所在的路径,没有加入Linux的环境变量


三、as 汇编编译

汇编程序(汇编器):将汇编源码翻译为纯二进制的机器指令,放到 .o 文件中

通过which可以查看as的安装目录

$ which as
/usr/bin/as

演示

as helloword.s -o helloword.o

不指定目标文件,会自动保存到同名的目标文件


四、collect2/ld 链接

路径

  • ld:/usr/bin/ld
  • collect2:/usr/libexec/gcc/x86_64-redhat-linux/4.8.2/collect2

同样的,如果直接使用collect2/ld来链接的话,我们需要自己指定很多的选项和参数,
所以我们一般不自己调用collect2/ld来链接,而是使用gcc来链接(gcc自动调用collect2/ld

gcc helloword.o -o helloword # 不指定可执行文件的名字的话,就默认为a.out

不要以为默认的名字时a.out,就认为Linux可执行文件的尾缀是.outLinux下的可执行文件并没有尾缀要求

我们后面会介绍默认的a.out这个名字是怎么来的


编译器集合中的其它程序:nm、strip、objdump、ar、readelf、debug,这程序都在/usr/bin/目录下,可以使用witch命令查看所在的目录

五、nm 查看 .o 和可执行文件中各种符号

演示:

$ nm main.o
0000000000000000 T main
                 U puts
$ nm main
000000000060102c B __bss_start
000000000060102c b completed.6355
......
000000000040051d T main
                 U puts@@GLIBC_2.2.5
0000000000400490 t register_tm_clones
0000000000400430 T _start
0000000000601030 D __TMC_END__

六、strip 对可执行文件进行瘦身

gcc指定-s选项时,gcc就是调用strip来瘦身的,我们也可以gcc时先不指定-s,然后自己主动使用strip来瘦身

$ gcc main.c -o main
$ ls -al main
-rwxr-xr-x 1 root root 8440 May 22 22:27 main # 没有 -s 选项,大小是 8840

$ gcc main.c -o main -s
$ ls -al main
-rwxr-xr-x 1 root root 6296 May 22 22:27 main # 加 -s 后,大小只有 6296
$ gcc main.c -o main
$ strip main # 前面不加 -s,这里直接使用 strip 瘦身
$ ls -al main
-rwxr-xr-x 1 root root 6296 May 22 22:30 main

七、objdump 反汇编

将机器指令反翻译为可以被人识别的汇编指令,这就反汇编

.o文件进行反汇编,> 将反汇编结果保存到 m.s

objdump -D main.o >  m.s

对可执行文件进行反汇编

objdump -D main > m.s

反汇编的意义

  • 其实对于做应用程序开发的我们来说,反汇编的意义不大,但是对于做逆向开发的人来说,这就很有意义,
    因为做逆向开发的人,需要分析二进制的机器指令,但是纯二进制的机器指令很难阅读,
    所以必须将二进制机器指令反翻译为ascii的汇编指令,才能阅读

八、ar

用来制作静态库文件,讲c函数库时再介绍

九、readelf

读取elf格式信息,后面用到时在介绍

十、debug

调试程序用的,后面课程介绍