一、binutils包
binutils包为elf格式文件提供查看、编辑、反汇编等命令
通过yum provides */objdump 或rpm -qif /usr/bin/objdump得到
提供objdump命令的安装包为binutils,通过rpm -qpl 查看包内容,得知,
binutils除了提供objdump,还提供ar as ld nm readelf size strip objcopy等
二进制相关命令。
下面提供objdump常用的参数
-h 把elf文件各段的基本信息打印出来,-x把更多信息打印出来
objdump -h
-s 可以将所有段的内容以16进制打印出来,-d可以将所有包含指令的段反汇编
objdump -s -d
-r 查看需要重定位的地方
readelf命令读取elf文件信息输出到屏幕,其常用参数
readelf -h 获取elf文件的文件头,其内容包含了描述整个文件的基本属性,如elf
文件版本、目标机器型号、程序入口等。
-S 显示段表,描述各个段的基本属性,如段名、段类型、在elf中的偏移、段大小、加载后的虚拟地址
ar -t libc.a 查看静态库包含哪些目标文件
二、elf文件格式
elf文件头:其内容包括elf魔数、机器字节长度、elf文件版本、目标机器型号、程序入口、段表位置及长度等。
段表:段表在elf文件的位置由elf文件头的e_shoff成员决定
.text //代码(各指令)
0x000f10 main:0101010.....
0x000bf2 func:1101000...
.data
0x000cf2 var1:0x01000000
.symtab //符号表描述符号所在的段、符号的值(变量的虚拟地址或变量在文件的偏移),符号类型
main 0x000f10
func 0x000bf2
var1 0x3
.strtab //字符串表存放着各个段名、变量名、函数名等字符串,字符串以偏移进行引用
main\0 func\0 var1\0.text\0.data\0
sectionheader //段表描述.text等各个段的文件偏移,及段的大小,各个段名在字符串表的偏移
Name off size
.text 34 5b
.data 90 08
.bss ..
.strtab ..
.symtab 2d0 f0
三、静态链接(ld)
包含2个步骤
空间与地址分配:扫描所有输入目标文件,获得其长度、位置,将所有符号收集起来,统一放到全局符号表,
链接器获得所有目标文件的段长度,并且将他们合并,计算输出文件各段合并后的长度与位置。
空间与地址分配后,就可以确定所有符号的虚拟地址了,就可以进行下一步,根据符号的地址对每个
需要重定位的指令进行修正
符合解析与重定位:读取所有输入文件中段的数据、重定位信息,进行符号解析和重定位、调整代码中的地址。
四、装载
页映射装载
进程的建立:
1创建一个独立的虚拟空间:虚拟空间由一组页映射函数将虚拟空间的各个页映射至相应的物理空间
创建虚拟空间并不是创建空间而是创建映射函数所需要的相应的数据结构。
2建立虚拟空间与可执行文件之间的映射关系:当程序执行发生页错误时,操作系统将从物理内存中
分配一个物理页,然后将该缺页从磁盘中读取到内存,再设置缺页的虚拟页和物理页的映射关系,这样程序
才得以正常运行。当操作系统捕获到缺页错误时,它应该知道程序当前所需要的页在可执行文件中的哪一个位置
3将cpu程序寄存器设置成可执行文件的入口地址 ,运行
Linux加载elf过程 execve->sys_execve->do_execve->search_binary_handle->load_elf_binary
1检查elf可执行文件格式的有效性
2寻找动态链接.interp段
3根据elf可执行文件的程序头表的描述,对elf文件进行映射,如代码、数据、只读数据
4初始化elf进程环境
5将系统调用的返回地址修改成elf可执行文件的入口