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 ...
随机推荐
- 多测师讲解接口测试 _postman(下)_高级讲师肖sir
关联接口 定义:上个接口返回的参数作为下一个接口的入参 1)接口1:查询出所有的州,自治区,直辖市,省(且发送请求不需要入参) 接口url地址: http://www.webxml.com.cn/We ...
- spring boot:用swagger3生成接口文档,支持全局通用参数(swagger 3.0.0 / spring boot 2.3.2)
一,什么是swagger? 1, Swagger 是一个规范和完整的文档框架, 用于生成.描述.调用和可视化 RESTful 风格的 Web 服务文档 官方网站: https://swagger.i ...
- SQL报表语句;SQL获取今日、本周、本月数据
SQL报表语句 SQL获取今日.本周.本月数据 本日:select * from table where datediff(dd,C_CALLTIME,getdate())=0 --C ...
- Jmeter入门(3)- Jmeter录制脚本
一. 录制web端 1. Badboy的介绍和安装 1.1 使用第三方工具Badboy来录制. 免费的web自动化测试工具 一个浏览器模拟工具 主要进行脚本的录制和回访,和对录制脚本进行调试,可以将脚 ...
- C#Socket通讯(1)
前言 因为自己需要开发一款自己的游戏,因为设计网络方面,所以我找了很多的资料,再加上考虑到Unity游戏客户端直接连接数据库很容易导致数据库泄露,再加上网上很多的服务端都是用控制台做的,所以我就想做个 ...
- RedisManager2020.4最最最最简单的破解方式
前言 redis manager是一款很优秀的redis数据库可视化工具,果然优秀的软件最终都走向了收费,贫民玩家越来越难了.赶时间的直接拉到最后,有下载方式. 破解 无需破解,已是破解版 安装 下载 ...
- collection v1.3.1升级全记录
collection v1.3.1升级全记录 项目地址: https://github.com/jianfengye/collection 欢迎star. collection 手册地址: http: ...
- Linux入门到放弃之一《在VMware虚拟机中安装Linux系统(RedHat)》
1.启动VMware: 2.新建虚拟机: 3.自定义配置(1安装客户机操作系统点击"稍后安装操作系统"2选择客户机操作系统为Linux,版本为Red Hat Enterprise ...
- SpringBook+Lombok 使用教程
什么是Lombok? Lombok项目是一个Java库,它会自动插入编辑器和构建工具中,Lombok提供了一组有用的注释,用来消除Java类中的大量样板代码. Lombok也存在一定风险,在一些开发工 ...
- C 语言编程习惯总结
笔者能力有限,如果文中出现错误的地方,还请各位朋友能够给我指出来,我将不胜感激,谢谢~ 引言 编程习惯的培养需要的是一个长期的过程,需要不断地总结,积累,并且我们需要从意识上认识其重要性,一个良好的编 ...