- 一、Linux常用的gcc命令
- 二、程序编译演示
- 1、准备工作
- 2、编译过程
- 三、分析ELF文件
- 1、ELF文件的段
- 2、反汇编ELF
- 四、总结
- 五、参考资料
程序运行常用工具
| 工具名称 | 功能 |
|---|---|
| addr2line | 帮助调试器在调试过程中定位对应的源代码位置 |
| as | 主要用于汇编 |
| ld | 主要用于链接 |
| ar | 主要用于创建静态库 |
| ldd | 用于查看一个可执行程序所依赖的共享库 |
| objdump | 将一个对象文件翻译成另外一种格式 |
| objcopy | 主要作用是用于反汇编 |
| readelf | 显示有关ELF文件的信息 |
| size | 列出可执行文件的每个部分的尺寸和大小 |
Linux环境下创建工作目录test0,创建文件hello.c
hello.c
#include2、编译过程//这是一个很简单的程序 int main(void) { printf("hello world! n"); return 0; }
1、预处理
(1) 删除将所有的#define,并且展开所有的宏定义,并且处理所有的条件预编译指令,比如#if #ifdef #elif #else #endif 等。
(2) 处理#include预编译指令,将被包含的文件插入到该预编译指令的位置。
(3) 删除所有注释“//”和“”。
(4) 添加行号和文件标识,以便编译时产生调试用的行号及编译错误警告行号。
(5) 保留所有的#pragma编译器指令,后续编译过程需要使用它们。
使用gcc进行预处理的命令如下:gcc -E hello.c -o hello.i
hello.i
int main(void )
{
printf("hello world!" "n");
return 0;
}
2、编译
编译过程就是对预处理完的文件进行一系列的词法分析,语法分析,语义分析及优化后生成相应的汇编代码。
控制终端输入命令:gcc -S hello.i -o hello.s生产hello.s文件
3、汇编
汇编过程调用对汇编代码进行处理,生成处理器能识别的指令,保存在后缀为.o的目标文件中。当要执行多个程序文件的时候,每个文件都先完成汇编工作,才能够进行下一步链接工作。
控制终端输入命令:gcc -c hello.s -o hello.o或是输入as -c hello.s -o hello.o汇编生成.o文件。
注: hello.o目标文件为ELF格式的可重定向文件。
4、链接
链接分为静态链接和动态链接
静态链接
运行以下命令:gcc -static hello.c -o hello使用静态库链接‘;size hello查看大小;ldd hello验证是有进行动态链接
动态链接
运行以下命令:gcc hello.c -o hello使用动态库链接;size hello查看大小;ldd hello验证是有进行动态链接,可以看出该可执行文件链接了很多其他动态库
可以看出进行动态链接的文件要比静态链接的小
ELF文件格式如下图所示:
位于ELF Header和Section Header Table之间的都是段(Section)
| 段名 | 含义 |
|---|---|
| .text | 已编译的指令代码段 |
| .rodata | ro代码read only ,即只读取数据(列入参数const) |
| .data | 已初始化的C程序全局变量和静态局部变量 |
| .bss | 未初始化的C程序全局变量和静态局部变量 |
| debug | 调试符号表,调试器用此段的信息帮助调试 |
运行命令readef -S hello查看各个section的信息:
尾部信息:
由于ELF文件无法被当做普通文本文件打开,如果需要打开查看一个ELF文件,则需要需要用到反汇编的方法。
使用obdjump -D进行反汇编
运行obdjump -D hello命令:
使用obdjump -S将其反汇编并且将其C语言源代码混合显示出来
先运行gcc -o hello -g hello.c,再运行objdump -S hello:
在本次对gcc常用的工具的使用过程中,学习了这些工具的具体使用方式和它的具体作用,并且在对静态库和动态库的使用更为熟练。
五、参考资料使用gcc和gcc的伙伴



