在Linux下我们编号程序都会输入 gcc test.c -o test的gcc的编译命令,那么gcc还有其他的什么操作?
知识储备:
预处理:
预处理阶段gcc主要进行宏替换,其功能还包括宏定义,文件包含,条件编译,去注释等。
预处理命令: gcc -E test.c -o test.i
E作用是让gcc在与处理结束时停止编译过程。 -o指目标文件, i表示文件已经过预处理。
编译阶段:
编译阶段gcc 首先检查语法规范,然后将文件翻译成汇编语言。
编译命令: gcc -S test.i -o test.s
汇编阶段:
gcc将文件转换成机器码
汇编命令: gcc -c test.s -o test.o
链接:
生成可执行文件或库函数
gcc test.o -o test
从左至右依次是:test.s test.o test.i
gcc其他指令:
-O0 -O1 -O2 - O3 四个优化等级,O0 表示没有优化,O1为缺省优化等级, O3优化级别最高
在gcc内部分别调用了
1.cc1 编译器 2.as汇编器 3.clloect2 连接器
Linux的调试器gdb:
l(list) 查看源码
r(run) 执行
b(break) 设置断点
i b(info break)查看断点
n(单步执行) 不进入函数
s(单步执行) 进入函数
p 打印变量
whatis 查看变量类型
bt 查看函数的调用栈
d 断点编号
q 退出
调试段错误:1.gcc -g a.out
2.ulimit - c unlimited
3. ./a.out
4.gdb ./a.out core.9527
#include <stdio.h>
int main()
{
int i = 0;
printf("enter\n");
scanf("%d",i); //此处错误
printf("%d\n",i);
return 0;
}


解惑:在gdb调试时为什么要加上-g选项?
“-g”标志是对程序进行调试性编译时常用的选项。我们需要给每一个需要调试的源文件都加上这个选项。它将使用特殊版本的C语言标准库完成编译和链接操作,给库函数加上程序调试方面的支持。编译器会把这些标志自动传给链接器。
readelf命令调研:
readelf用来显示一个或者多个elf格式的目标文件的信息,可以通过它的选项来控制显示哪些信息。这里的elf-file(s)就表示那些被检查的文件。可以支持32位,64位的elf格式文件,也支持包含elf文件的文档(这里一般指的是使用ar命令将一些elf文件打包之后生成的例如lib*.a之类的“静态库”文件)。 这个程序和objdump提供的功能类似,但是它显示的信息更为具体,并且它不依赖BFD库(BFD库是一个GNU项目,它的目标就是希望通过一种统一的接口来处理不同的目标文件),所以即使BFD库有什么bug存在的话也不会影响到readelf程序。
ELF文件类型:
a)可重定位文件:用户和其他目标文件一起创建可执行文件或者共享目标文件,例如lib*.a文件。
b)可执行文件:用于生成进程映像,载入内存执行,例如编译好的可执行文件a.out。
c)共享目标文件:用于和其他共享目标文件或者可重定位文件一起生成elf目标文件或者和执行文件一起创建进程映像,例如lib*.so文件。
ELF文件作用:
ELF文件参与程序的连接(建立一个程序)和程序的执行(运行一个程序),所以可以从不同的角度来看待elf格式的文件:
a)如果用于编译和链接(可重定位文件),则编译器和链接器将把elf文件看作是节头表描述的节的集合,程序头表可选。
b)如果用于加载执行(可执行文件),则加载器则将把elf文件看作是程序头表描述的段的集合,一个段可能包含多个节,节头表可选。
c)如果是共享文件,则两者都含有。
ELF文件总体组成:
elf文件头描述elf文件的总体信息。
包括:系统相关,类型相关,加载相关,链接相关。
系统相关表示:elf文件标识的魔术数,以及硬件和平台等相关信息,增加了elf文件的移植性,使交叉编译成为可能。
类型相关就是前面说的那个类型。
加载相关:包括程序头表相关信息。 链接相关:节头表相关信息。