编译知识

四个过程:预处理Preprocessing、编译Compile、汇编Assembly、链接Linking

Preprocessing:通常完成一些宏扩展、包含头文件、删除注视等,生成.i文件;

Compile:gcc -S hello.i -o hello.S生成汇编文件,把预处理的文件进行一系列的词法分析、语法分析、语义分析及优化后生产相应的汇编代码文件;汇编过程也可以使用汇编器as hello.s -o hello.o来完成。

Assembly:gcc -c hello.s -o hello.o生成目标.o文件,汇编器是将汇编代码编程机器可以执行的指令;

最后再将不同的.o文件链接成可执行文件。简单来说,编译器就是将高级语言翻译成机器语言的一个工具,直接使用汇编代码或者使用机器指令效率比较低。


编译器生成的一些.o可重定位文件,里面引用了一些定义在其它模块的函数或者全局变量,这些函数或者变量的地址只有在链接的时候才能被确定下来。

在Linux下,.o可重定位文件,可执行文件/bin/bash,共享目标文件.so,核心存储文件,都可以称为目标文件,采用Elf格式存储。

.o目标文件的ELF格式大致如下

      ELF Header
.text
.data
.bss
.rel.text

..

other sections

Section header Table

String Tables        

Symbol Tables

objdump也能查看ELF文件中包含的段,但它会省略一些符号表、重定位表、字符串表;如果使用readelf命令,则可以玩到ELF所有的信息,如ELF header或者Section Header Table,Symbol Tables。

一般来说,生成的.o文件都包括重定位表和符号表,这两个表也以段的形式表现。

重定位表:rel.text;rel.data等,如果引用了其余目标中间中的函数或全局变量,就会在这两个段中标明出来,通过指明段类型为SHT_REL,来标明该段是重定位段。

符号表:段名一般叫.symtab,每个符号都由如下结构体来表现:

typedef struct{

Elf32_Word st_name;//符号名字

Elf32_Addr st_value;//符号直,可能是绝对值,也可能是一个地址

Elf32_Word st_size;//符号大小

unsigned char st_info;//符号绑定信息以及符号类型

unsigned char st_other;

Elf32_Half st_shndx;

}Elf32_Sym;


熟悉单个目标文件的格式以后,就能更好的理解链接过程了。

编译器和汇编器生成从地址零开始的代码和数据段,连接器通过把每个符号定义与一个存储器位置联系起来,然后修改所有对这些符号的引用,使得它们指向这个存储器位置,从而重定位这些指令。

链接器在链接多个.o文件时,首先会合并各个.o文件的重定位表段以及符号表段,链接时先确定目标文件的虚拟地址,随后就能知道各个符号的绝对的虚拟地址。得知此地址后再去更新新的符号表段中各个符号的地址;符号确定后,再按照重定位表段,去更新指令中需要重定位的地址或数值。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值