binary hacks读数笔记(ld 链接讲解 一)
首先我们先看两段代码:
a.c
extern int shared;
int main(){
int a=100;
swap(&a,&shared);
}
b.c
int shared=1;
void swap(int* a,int* b){
*a^=*b^=*a^=*b;
}
gcc -c a.c b.c 得到a.o 与b.o
1、查看a.o:
[root@tlinux misc]# objdump -h a.o a.o: file format elf64-x86-64 Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000027 0000000000000000 0000000000000000 00000040 2**0
CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE
1 .data 00000000 0000000000000000 0000000000000000 00000067 2**0
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 0000000000000000 0000000000000000 00000067 2**0
ALLOC
3 .comment 0000002e 0000000000000000 0000000000000000 00000067 2**0
CONTENTS, READONLY
4 .note.GNU-stack 00000000 0000000000000000 0000000000000000 00000095 2**0
CONTENTS, READONLY
5 .eh_frame 00000038 0000000000000000 0000000000000000 00000098 2**3
CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
2、查看b.o:
[root@tlinux misc]# objdump -h b.o b.o: file format elf64-x86-64 Sections:
Idx Name Size VMA LMA File off Algn
0 .text 0000004a 0000000000000000 0000000000000000 00000040 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .data 00000004 0000000000000000 0000000000000000 0000008c 2**2
CONTENTS, ALLOC, LOAD, DATA
2 .bss 00000000 0000000000000000 0000000000000000 00000090 2**0
ALLOC
3 .comment 0000002e 0000000000000000 0000000000000000 00000090 2**0
CONTENTS, READONLY
4 .note.GNU-stack 00000000 0000000000000000 0000000000000000 000000be 2**0
CONTENTS, READONLY
5 .eh_frame 00000038 0000000000000000 0000000000000000 000000c0 2**3
CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA
3、链接之前,VMA与LMA都是0,即目标文件的虚拟空间地址与装载地址都无效。经过链接ld过程,才会给链接文件分配虚拟地址空间。
ld a.o b.o -e main -o ab
链接过程,合并了a.o与b.o的代码段、数据段,具体的位置与大小如下所示:
具体信息如下所示
[root@tlinux misc]# objdump -h ab ab: file format elf64-x86-64 Sections:
Idx Name Size VMA LMA File off Algn
0 .text 00000071 00000000004000e8 00000000004000e8 000000e8 2**0
CONTENTS, ALLOC, LOAD, READONLY, CODE
1 .eh_frame 00000058 0000000000400160 0000000000400160 00000160 2**3
CONTENTS, ALLOC, LOAD, READONLY, DATA
2 .data 00000004 0000000000601000 0000000000601000 00001000 2**2
CONTENTS, ALLOC, LOAD, DATA
3 .comment 0000002d 0000000000000000 0000000000000000 00001004 2**0
CONTENTS, READONLY
同时,我们可以看一下,链接后,各个源文件的符号表也合成一张全局符号表,且符号表中表明各个符号的虚拟空间位置:
readelf -s ab
Symbol table '.symtab' contains 13 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000004000e8 0 SECTION LOCAL DEFAULT 1
2: 0000000000400160 0 SECTION LOCAL DEFAULT 2
3: 0000000000601000 0 SECTION LOCAL DEFAULT 3
4: 0000000000000000 0 SECTION LOCAL DEFAULT 4
5: 0000000000000000 0 FILE LOCAL DEFAULT ABS a.c
6: 0000000000000000 0 FILE LOCAL DEFAULT ABS b.c
7: 000000000040010f 74 FUNC GLOBAL DEFAULT 1 swap
8: 0000000000601000 4 OBJECT GLOBAL DEFAULT 3 shared
9: 0000000000601004 0 NOTYPE GLOBAL DEFAULT 3 __bss_start
10: 00000000004000e8 39 FUNC GLOBAL DEFAULT 1 main
11: 0000000000601004 0 NOTYPE GLOBAL DEFAULT 3 _edata
12: 0000000000601008 0 NOTYPE GLOBAL DEFAULT 3 _end
4、接下来介绍一下符号的解析与重定位:
首先查看一下未重定位之前,a.o中是怎么处理shared变量与swap函数的:
利用 objdump -d a.o查看一下,a.o的反汇编代码
[root@tlinux misc]# objdump -d a.o a.o: file format elf64-x86-64 Disassembly of section .text: 0000000000000000 <main>:
0: 55 push %rbp
1: 48 89 e5 mov %rsp,%rbp
4: 48 83 ec 10 sub $0x10,%rsp
8: c7 45 fc 64 00 00 00 movl $0x64,-0x4(%rbp)
f: 48 8d 45 fc lea -0x4(%rbp),%rax
13: be 00 00 00 00 mov $0x0,%esi //00 00 00 00 shared 未给地址
18: 48 89 c7 mov %rax,%rdi
1b: b8 00 00 00 00 mov $0x0,%eax
20: e8 00 00 00 00 callq 25 <main+0x25> //swap函数也未给地址
25: c9 leaveq
26: c3 retq
5、经过ld链接之后,在最后文件ab中,shared 与 swap都知道了地址。因为链接过程会分配虚拟地址,那么根据前面第三点链接过后的信息,可以知道各个段的虚拟地址,那么
其中各个符号的地址也会知道。那么,经过连接之后,ab中的代码反汇编结果如何,如下所示:
[root@tlinux misc]# objdump -d ab ab: file format elf64-x86-64 Disassembly of section .text: 00000000004000e8 <main>:
4000e8: 55 push %rbp
4000e9: 48 89 e5 mov %rsp,%rbp
4000ec: 48 83 ec 10 sub $0x10,%rsp
4000f0: c7 45 fc 64 00 00 00 movl $0x64,-0x4(%rbp)
4000f7: 48 8d 45 fc lea -0x4(%rbp),%rax
4000fb: be 00 10 60 00 mov $0x601000,%esi //00 60 10 00 详见ab文件的数据段
400100: 48 89 c7 mov %rax,%rdi
400103: b8 00 00 00 00 mov $0x0,%eax
400108: e8 02 00 00 00(相对下一行命令偏移 02) callq 40010f <swap> // 由下面swap在 40010f处可知,a.o b.o链接到一起后,swap的函数虚拟地址可知 call 命令: 40010d+00000002
40010d: c9 leaveq
40010e: c3 retq 000000000040010f <swap>:
40010f: 55 push %rbp
400110: 48 89 e5 mov %rsp,%rbp
400113: 48 89 7d f8 mov %rdi,-0x8(%rbp)
400117: 48 89 75 f0 mov %rsi,-0x10(%rbp)
40011b: 48 8b 45 f8 mov -0x8(%rbp),%rax
40011f: 8b 10 mov (%rax),%edx
400121: 48 8b 45 f0 mov -0x10(%rbp),%rax
400125: 8b 08 mov (%rax),%ecx
400127: 48 8b 45 f8 mov -0x8(%rbp),%rax
40012b: 8b 30 mov (%rax),%esi
40012d: 48 8b 45 f0 mov -0x10(%rbp),%rax
400131: 8b 00 mov (%rax),%eax
400133: 31 c6 xor %eax,%esi
400135: 48 8b 45 f8 mov -0x8(%rbp),%rax
400139: 89 30 mov %esi,(%rax)
40013b: 48 8b 45 f8 mov -0x8(%rbp),%rax
40013f: 8b 00 mov (%rax),%eax
400141: 31 c1 xor %eax,%ecx
400143: 48 8b 45 f0 mov -0x10(%rbp),%rax
400147: 89 08 mov %ecx,(%rax)
400149: 48 8b 45 f0 mov -0x10(%rbp),%rax
40014d: 8b 00 mov (%rax),%eax
40014f: 31 c2 xor %eax,%edx
400151: 48 8b 45 f8 mov -0x8(%rbp),%rax
400155: 89 10 mov %edx,(%rax)
400157: 5d pop %rbp
400158: c3 retq
6、重定位表信息:
对于可重定位文件,必须包含重定位表,用来描述如何修改相应的段。可以利用objdump -r a.o查看重定位表
[root@tlinux misc]# objdump -r a.o a.o: file format elf64-x86-64 RELOCATION RECORDS FOR [.text]:
OFFSET TYPE VALUE
0000000000000014 R_X86_64_32 shared
0000000000000021 R_X86_64_PC32 swap-0x0000000000000004
OFFSET指的是需要被重定位的内容在可重定位文件中的位置,看第4点的反汇编内容可知,0x14位置和0x21位置分别为shared 与 swap.需要被重定位
binary hacks读数笔记(ld 链接讲解 一)的更多相关文章
- binary hacks读数笔记(ld 链接讲解 二)
这块将介绍一下ld链接命令的具体使用.ld的作用:ld是GNU binutils工具集中的一个,是众多Linkers(链接器)的一种.完成的功能自然也就是链接器的基本功能:把各种目标文件和库文件链接起 ...
- binary hacks读数笔记(堆、栈 VMA的分布)
一.首先看一个简单的程序: #include<stdlib.h> int main() { while(1) { sleep(1000); } return 0; } gcc -stati ...
- binary hacks读数笔记(共享库)
共享库从文件结构上来讲,与共享对象没什么区别.Linux下,共享库就是普通的ELF共享对象. 1.共享库命名: libname.so.x.y.z :其中最前面使用前缀lib,中间是库的名字和后缀&qu ...
- binary hacks读数笔记(readelf基本命令)
一.首先对readelf常用的参数进行简单说明: readelf命令是Linux下的分析ELF文件的命令,这个命令在分析ELF文件格式时非常有用,下面以ELF格式可执行文件test为例详细介绍: 1. ...
- binary hacks读数笔记(装载)
1.地址空间 在linux系统中,每个进程拥有自己独立的虚拟地址空间,这个虚拟地址空间的大小是由计算机硬件决定的,具体地说,是由CPU的位数决定的.比如,32位硬件平台决定的虚拟地址空间大小:0--2 ...
- binary hacks读数笔记(nm命令)
nm命令(names):输出包含三个部分:1 符号值.默认显示十六进制,也可以指定: 2 符号类型.小写表示是本地符号,大写表示全局符号(external); 3 符号名称. 例如:nm Simple ...
- binary hacks读数笔记(file命令与magic file)
file命令的作用是用于检验文件的类型,并打印至终端.file命令检验文件类型按以下顺序来完成: 检验文件系统(Filesystem)中支持的文件类型. 检验magic file规则. 检验文件内容的 ...
- binary hacks读数笔记(dlopen、dlsym、dlerror、dlclose)
1.dlopen是一个强大的库函数.该函数将打开一个动态库,并把它装入内存.该函数主要用来加载库中的符号,这些符号在编译的时候是不知道的.比如 Apache Web 服务器利用这个函数在运行过程中加载 ...
- binary hacks读数笔记(readelf命令)
可以用readelf命令来查看elf文件内容,跟objdump相比,这个命令更详细. 1. readelf -h SimpleSection.o ELF Header: Magic: 7f 45 4c ...
随机推荐
- 多测师讲解 自动化测试理论(1)_高级讲师肖sir
自动化测试理论什么是自动化测试?广义的:通过工具或程序替代或辅助人工测试的行为叫自动化测试狭义的:通过工具录制或编写脚本模拟手工测试的过程,通过回放或运行脚本执行测试用例,从而代替人工对系统的功能验证 ...
- 华为方舟编译器正式支持C语言:完全开源
投递人 itwriter 发布于 2020-10-14 19:08 评论(15) 有1938人阅读 原文链接 2019 年 8 月底,华为方舟编译器(OpenArkCompiler)正式开源,迈出了跨 ...
- python BeautifulSoup的使用方法
BeautifulSoup的使用 我们学习了正则表达式的相关用法,但是一旦正则写的有问题,可能得到的就不是我们想要的结果了,而且对于一个网页来说,都有一定的特殊的结构和层级关系,而且很多标签都有id或 ...
- vi/vim系统编辑命令使用技巧
01前言 在Linux系统中会有很多的文件信息,这些文件的内容如果需要编辑,就必须借助vi或vim编辑命令. vi是Linux命令行界面下的重要文字编辑器.vim是vi命令的增强版. [语法格式] v ...
- 为什么说 Python 内置函数并不是万能的?
本文出自"Python为什么"系列,请查看全部文章 在Python猫的上一篇文章中,我们对比了两种创建列表的方法,即字面量用法 [] 与内置类型用法 list(),进而分析出它们在 ...
- spring cloud:搭建基于consul的服务提供者集群(spring cloud hoxton sr8 / spring boot 2.3.4)
一,搭建基于consul的服务提供者集群 1,consul集群,共3个实例: 2, 服务提供者集群:共2个实例: 3,服务消费者:一个实例即可 4,consul集群的搭建,请参考: https://w ...
- linux(centos8):使用zip/unzip压缩和解压缩文件
一,查看zip命令所属的rpm包 1,zip [root@kubemaster ~]# whereis zip zip: /usr/bin/zip /usr/share/man/man1/zip.1. ...
- dubbo配置加载优先级
优先级从高到低: JVM 启动 -D 参数优先,这样可以使用户在部署和启动时进行参数重写,比如在启动时需改变协议的端口: XML 次之,如果在 XML 中有配置,则 dubbo.properties ...
- 支持向量机SVM基本问题
1.SVM的原理是什么? SVM是一种二类分类模型.它的基本模型是在特征空间中寻找间隔最大化的分离超平面的线性分类器.(间隔最大是它有别于感知机) 试图寻找一个超平面来对样本分割,把样本中的正例和反例 ...
- 联赛模拟测试25 C. Repulsed 贪心+树形DP
题目描述 分析 考虑自底向上贪心 \(f[x][k]\) 表示 \(x\) 下面距离为 \(k\) 的需要灭火器的房间数,\(g[x][k]\) 表示 \(x\) 下面距离为 \(k\) 的多余灭火器 ...