演示流程
- gcc -v 查看gcc版本
- cd fanzhuan 切换演示目录
- sudo vim hello.c 查看源代码
- gcc -E hello.c -o hello.i 预处理
- gcc -S hello.i -o hello.s 编译
- gcc -c hello.s -o hello.o 汇编
- gcc -c hello.c 前三个过程可以合并为一条命令 源代码->目标文件
- gcc hello.o -o hello 链接
- gcc hello.c -o hello 四个过程可以合并为一条命令 源代码->可执行文件
- ./hello 运行可执行文件
- objdump -h hello.o 查看目标文件
- readelf -S hello.o 查看段表
- readelf -s hello.o 查看符号表
- gcc hello.c hello2.c -o hello2 编译两个.c文件,不能同时有两个main函数
- gcc -g -Wall hello.c -o hello 将调试信息写入目标文件,Wall开启警告
编译步骤及说明
步骤 | 命令 | 说明 |
---|---|---|
预处理 | gcc -E hello.c -o hello.i | 1. 将所有#define删除,并且展开所有的宏定义 2. 处理所有的条件预编译指令,如#if #ifdef #undef #ifndef #endif #elif 3. 处理#include,将包含的文件插入到此处,这是一个递归的过程 4. 删除所有注释 // /* */ 5. 添加行号和文件名标识,以便于编译时产生的错误警告能显示行号 6. 保留#pragma编译器指令 |
编译 | gcc -S hello.i -o hello.s | 将预处理完的.i文件进行一系列的词法分析、语法分析、语义分析及优化后生成响应的汇编代码文件,这是整个程序构建的最核心的部分,也是最复杂的部分 |
汇编 | gcc -c hello.s -o hello.o或者as hello.s -o hello.o | 汇编是将第二步生成的汇编代码编程机器可执行的指令,每一个汇编语句几乎都对应一条机器指令 |
链接 | 链接动态库和静态库 |
基本编译流程
- gcc -E hello.c -o hello.i 预处理
- gcc -S hello.i -o hello.s 编译
- gcc -c hello.s -o hello.o 汇编(生成目标代码)
编译后成成的文件
- gcc -c hello.c 直接进行编译
目标文件
目标文件就是源代码经过编译后但未进行链接的那些中间文件Linux下的 .o文件就是目标文件,目标文件和可执行文件内容和格式几乎都一样,所以我们可以广义地将目标文件和可执行文化看成一类型文件。他们都是按照ELF文件格式存储的。
查看目标文件命令
命令 | 说明 |
---|---|
objdump -h filename.o | 打印主要段的信息 |
objdump -x filename.o | 打印更多的详细信息 |
objdump -s filename.o | 将所有段的内容以16进制方式打印出来 |
objdump -d filename.o 或者-S | 将所有包含指令的段反汇编 |
objdump -t filename.o | 查看所有的符号以及他们所在段 |
readelf -h filename.o | 查看.o文件的文件头详细信息 |
readelf -S filename.o | 显示.o文件中的所有段,即查看段表 |
readelf -s filename.o | 查看符号表 |
size filename.o | 查看.o文件中各个段所占大小 |
nm filename.o | 查看.o文件中所有的符号 |
演示
- objdump -h hello.o 查看目标文件
行字段说明:
字段 | 说明 |
---|---|
.text | 代码段(存放函数的二进制机器指令) |
.data | 数据段(存已初始化的局部/全局静态变量、未初始化的全局静态变量) |
.bss | bss段(声明未初始化变量所占大小) |
.rodata | 只读数据段(存放 " " 引住的只读字符串) |
.comment | 注释信息段 |
.node.GUN-stack | 堆栈提示段 |
列字段说明
字段 | 说明 |
---|---|
Size | 段的长度 |
File Off | 段的所在位置(即距离文件头的偏移位置) |
段的属性说明
段属性 | 说明 |
---|---|
CONTENTS | 表示该段在文件中存在 |
ALLOC | 表示只分配了大小,但没有存内容 |
- readelf -S hello.o 查看段表
- readelf -s hello.o 查看符号表