gcc编译器学习
Posted jetson-xie
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了gcc编译器学习相关的知识,希望对你有一定的参考价值。
gcc编译器
- -o [file] [origin_file] 将源代码文件编译生成file文件。如gcc -o hello hello.c,也可以直接将 gcc origin_file,那么gcc将会生成a.out文件。
- gcc编译器在编译一个C语言程序文件时需要经过4步:
² 将源程序文件经过预处理生成.i文件
² 将.i文件进行汇编生成.s文件
² 将.s文件编译生成.o文件
² 将各个模块的.o文件链接生成程序可执行文件
- gcc编译器中的几种常用的编译选项:
a) -c 编译、汇编指定的源程序,但是不进行链接
b) -S 编译指定的源文件,但是不进行汇编
c) -E 预处理指定的源程序,但是不进行汇编
d) -o [file] [origin_file]将origin_file编译生成可执行文件file
e) -I directory 指定include包含文件的搜索目录
f) -g 生成调试信息,这些信息可以被调试器捕捉调试
- gcc编译器区分大小写,譬如-o选项和-O选项两者之间是不一样的,-o选项表示将origin_fie编译链接后生成file可执行文件,而-O选项表示编译生成并且进行代码优化。
- 汇编源程序后指的是生成.o二进制文件,编译源文件指的是生成.s文件
- 如果使用gcc编译器的除-o选项外生成文件,再后跟-o选项,则生成的文件为-o 选项指定文件名称。如gcc -S hello.c -o hello.s则生成指定hello.s汇编代码文件。
- gcc -o 选项不仅可以接收输入为源代码文件,同时还可以接收目标文件如 gcc main.c test.c -o test
- -I 后跟参数为指定的源程序包含代码头文件所在的位置
- 链接器的任务:将多个目标文件连接成为一个完整,可加载,可执行的目标文件,其输入是可重定位的目标文件。链接主要任务如下:
a) 符号解析:将目标文件内的引用符号和该符号的定义联系起来
b) 将符号定义与存储器的位置联系起来,修改对这些符号的引用。
- 目标文件可分为三种类型:
a) 可重定位的目标文件:这种文件中包含了二进制代码和数据,这些代码和数据已经转换成了机器指令代码和数据,但是这种目标文件还不能够立刻被执行,原因是这些指令和模块使用了别的模块中的内容,但是却还没有连接这些模块,其他模块的符号对于本模块来说是未知的,这些符号的解析需要链接器进行链接,可重定位的目标文件后面通常后缀是.o
b) 可执行目标文件:这种文件也包含二进制代码和数据,但是这些文件已经经过了链接操作,和所有模块之间已经产生了联系,在链接器的解析和链接后,所有的目标文件中的符号都已经得到了解析和重定位,因此每个符号都是已经知道的,该文件可以被直接执行。
c) 共享目标文件:这是一种特殊类型的可重定位的目标文件,可以在需要它的程序运行或者加载时,动态地加载到内存之中运行,这种文件又被称作动态库文件或者共享库文件,后缀是.so
- ELF格式是Linux环境下最常用的目标文件格式,在大多数情况下,无论是可执行目标文件还是重定位目标文件,都使用该种格式进行存储,ELF格式目标文件由两部分组成:ELF文件头和目标文件的段。ELF文件头的前16个字节存储该文件系统的字长和字节序,剩下的部分包含了该文件的其他信息,包括ELF文件头的大小,目标文件的类型,目标机的类型,段头部表在目标文件内的文件偏移位置等。
- ELF文件的段部分包含:
a) 可执行文件和重定位文件均有部分
- .text: 代码段,存储二进制机器指令,这些指令可以直接被执行
- .rodata: 只读数据端。存储程序中使用的复杂常量,例如字符串
- .data: 数据段,存储程序中已经明确初始化的全局数据,如果某一全局变量初始化为0或者未被初始化,则会被放置于块存储段中,C语言的局部变量保存在栈上,不保存在数据段中。
- .bss: 块存储段。存储未被明确初始化的全局数据,在目标文件中这个段并不占用实际的空间,而只是一个占位符,告知指定位置应该预留全局数据的空间,块存储段存在的原因是为了提高磁盘空间的利用率。
以上四个段会被实际地加载到内存中,是实际的程序段,目标文件中还有一些其他段,这些信息不会加载到内存中,在生成可执行文件时已经被删除了。
b) 其他不一定存在的程序段
- .symtab: 符号表 存储定义和引用的函数和全局变量,所有引用本模块的全局符号,以及其他模块的符号,都会在符号表中有一个登记,用于链接器查找解析和重定位的位置查找。每个重定位目标文件都需要有这样一个表。
- .rel.text 代码段需要重定位的信息 存储需要靠重定位操作修改位置的符号表(在源代码文件中被声明但是并没有被定义的函数)
- .rel.data:数据段需要重定位的信息。存储需要靠重定位操作修改位置的符号汇总,这些符号在数据段中,是一些全局变量。
- .debug:调试信息。存储用于调试时产生的符号表,在编译程序时通过-g才能生成这个段。
- .line:源程序调试时的行号映射,存储源程序中每个语句的行号,在编译程序时通过-g选项才会生成。
- .strtab: 字符串表, 存储.symtab符号表和.debug符号表中符号的名字,这些名字是一些字符串,并且以’