一、Linux常用的gcc命令
???程序运行常用工具
工具名称 | 功能 |
---|
addr2line | 帮助调试器在调试过程中定位对应的源代码位置 | as | 主要用于汇编 | ld | 主要用于链接 | ar | 主要用于创建静态库 | ldd | 用于查看一个可执行程序所依赖的共享库 | objdump | 将一个对象文件翻译成另外一种格式 | objcopy | 主要作用是用于反汇编 | readelf | 显示有关ELF文件的信息 | size | 列出可执行文件的每个部分的尺寸和大小 |
二、程序编译演示
1、准备工作
Linux环境下创建工作目录test0,创建文件hello.c hello.c
#include <stdio.h>
int main(void)
{
printf("hello world! \n");
return 0;
}
2、编译过程
?? 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文件
1、ELF文件的段
ELF文件格式如下图所示: 位于ELF Header 和Section Header Table 之间的都是段(Section)
段名 | 含义 |
---|
.text | 已编译的指令代码段 | .rodata | ro代码read only ,即只读取数据(列入参数const) | .data | 已初始化的C程序全局变量和静态局部变量 | .bss | 未初始化的C程序全局变量和静态局部变量 | debug | 调试符号表,调试器用此段的信息帮助调试 |
运行命令readef -S hello 查看各个section的信息: 尾部信息:
2、反汇编ELF
??由于ELF文件无法被当做普通文本文件打开,如果需要打开查看一个ELF文件,则需要需要用到反汇编的方法。 ??使用obdjump -D 进行反汇编 运行obdjump -D hello 命令: 使用obdjump -S 将其反汇编并且将其C语言源代码混合显示出来 先运行gcc -o hello -g hello.c ,再运行objdump -S hello :
四、总结
在本次对gcc常用的工具的使用过程中,学习了这些工具的具体使用方式和它的具体作用,并且在对静态库和动态库的使用更为熟练。
五、参考资料
使用gcc和gcc的伙伴
|