一.一次性编译
1、新建、编辑源文件
- 首先,建个名为“测试”的文件夹,cd进入文件夹
- 接下来用touch在文件夹内创建一个空白的 hello.c 源文件。(hello.c 其实就是一个纯文本文件,并没有任何特殊格式)
- 再用gedit编辑源文件
2、生成可执行程序
$ cd 测试 #进入源文件所在的目录
$ gcc hello.c #在gcc命令后面紧跟源文件名
这样的话就会在文件夹中生成一个a.out的可执行程序,这就是最终生成的可执行文件。
*Linux不以文件后缀来区分可执行文件,Linux下的可执行文件后缀理论上可以是任意的,这里的.out只是用来表明它是 GCC 的输出文件。不管源文件的名字是什么,GCC 生成的可执行文件的默认名字始终是a.out
通过-o可以自定义执行文件名称,也可以将文件输入到其他目录中(其他目录必须存在)
gcc hello.c -o a/hello.out
3、运行可执行程序
./a.out
表示运行当前目录下a.out程序
*如果不写./,Linux会到系统路径下查找 a.out,而系统路径下不存在这个程序,所以会运行失败
运行结果如下:
4.总结
$ cd 测试 #进入源文件所在目录(cd)
$ touch hello.c #新建源文件(touch)
$ gedit hello.c #编辑源文件(gedit)
$ gcc hello.c #生成可执行程序
$ ./a.out #运行可执行程序
二.分两步编译
1.编译
利用-c将源文件(hello.c)编译为目标文件(hello.o)
gcc -c hello.c
2.链接
在gcc命令后紧跟目标文件的名字,就可以将目标文件(.o)链接成可执行文件(.out)
gcc hello.o
3.总结
$ cd 测试 #进入源文件所在目录(cd)
$ gcc -c hello.c #编译源文件为目标文件(-c)
$ gcc hello.o #链接目标文件为可执行文件(紧跟)
$ ./a.out #运行可执行程序
三.pwn所需的分四步编译
首先如果我们在编译时添加-save temps和- -verbose编译选项,那么我们就可以保存下来编译的中间文件。
由此可以看到,GCC的编译过程主要分四部分
1.预处理
这个阶段输入.c源文件,主要处理文件中的带“#”的语句,将要包含(include)的文件插入原文件中、将宏定义展开、根据条件编译命令选择要使用的代码,最后将这些代码输出到一个“.i”文件中等待进一步处理。在命令选项中添加编译选项-E可以单独执行预处理:
$ gcc -E hello.c -o hello.i
hello.i的部分内容
预处理的一些处理规则:
1.递归处理“#include”预处理命令,将对应文件的内容复制到指定的位置;
2.删除所有“#define”指令,并且在其引用的位置递归展开所有的宏定义
3.处理所有条件预处理指令:“#if”,”#ifdef”,“#elif”,”#else”,”#endif”等;
4.删除所有注释
5.添加行号和文件名标识
2.编译
这个阶段输入第一阶段生成的 .i 文件,输出成汇编语言 .s 文件:
gcc -S hello.i -o hello.s
gcc -S hello.i -o hello.s -masm=intel -fno-asynchronous-unwind-tables
//-masm=intel可以将汇编文件制定成Intel模式,
//-fno-asynchronous-unwind-tables则可以生成没有的cfi宏的汇编指令,以提高可读性
hello.s汇编文件的内容
![在这里插入图片描述](https://img-blog.csdnimg.cn/2648472edb7c4a5f8bf5dcf222d05b14.pn在汇编代码中函数printf()被换成了puts()函数,是因为在有单一参数的时候,两者十分类似,而GCC 的优化策略就进行了替换以提高性能
3.汇编阶段
这个阶段输入第二阶段的汇编文件 .s 文件,然后编译成机器语言 .o 文件,在Linux系统上一般表现为ELF目标文件(OBJ文件):
gcc -c hello.s -o hello.o
gcc -c hello.c -o hello.o
//操作对象也可以是.c,直接生成目标文件
此时的hello.o是一个可重定位文件,可使用objdump命令打开,即:
objdump -sd hello.o -M intel
//利用此命令可以打开hello.o目标文件
4.链接
gcc hello.o –o hello -static
从而得到hello文件,通过./hello从而运行该程序
如果我们通过上述objdump命令的话,可以得到一个静态连接的可执行文件,即:
objdump -sd hello -M intel
其中包含大量的库,以下只是部分: