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 ...
随机推荐
- 修改LiveChart的提示显示位置
问题:修改LiveChart的提示显示位置 摘要:相信WPF开发者在用LiveCharts的时候会有遇到这个需求.就是产品要求折线图的提示要显示的正常点. 需求:如下图所示.原本显示是在下方并且没有小 ...
- MeteoInfoLab脚本示例:FY-3C全球火点HDF数据
FY-3C全球火点HDF数据包含一个FIRES二维变量,第一维是火点数,第二维是一些属性,其中第3.4列分别是火点的纬度和经度.下面的脚本示例读出所有火点经纬度并绘图.脚本程序: #Add data ...
- scp远程上传
scp -P 22 /Users/mac/Downloads/VBoxGuestAdditions_5.2.12.iso root@192.168.1.210:/usr/local/src s ...
- centos8平台:用fontconfig安装及管理字体(fc-list/fc-match/fc-cache)
一,fc-list所属的rpm包 [root@blog ~]$ whereis fc-list fc-list: /usr/bin/fc-list /usr/share/man/man1/fc-lis ...
- Redis基础——剖析基础数据结构及其用法
这是一个系列的文章,打算把Redis的基础数据结构.高级数据结构.持久化的方式以及高可用的方式都讲一遍,公众号会比其他的平台提前更新,感兴趣的可以提前关注,「SH的全栈笔记」,下面开始正文. 如果你是 ...
- Java9系列第8篇-Module模块化编程
我计划在后续的一段时间内,写一系列关于java 9的文章,虽然java 9 不像Java 8或者Java 11那样的核心java版本,但是还是有很多的特性值得关注.期待您能关注我,我将把java 9 ...
- CAS 算法与 Java 原子类
乐观锁 一般而言,在并发情况下我们必须通过一定的手段来保证数据的准确性,如果没有做好并发控制,就可能导致脏读.幻读和不可重复度等一系列问题.乐观锁是人们为了应付并发问题而提出的一种思想,具体的实现则有 ...
- C#一行代码实现(06)跨线程获取控件值,结合BeginInvoke和EndInvoke使用,以DataGridView为例
主要功能 跨线程获取控件值,以DataGridView为例,结合BeginInvoke和EndInvoke使用 一行代码 object cellValue = dataGridView.ExInvok ...
- gethub网址链接
https://github.com/fraser-in-school/suduku 之前这个网址是手动提交的,现在从新更新下,这是用Visio studio提交的,应该不会缺少并不必要的文件 htt ...
- react-native中textInput在androidTV上的焦点处理(坑篇)
react-native中,开发androidTV输入框的焦点处理. 复述流程: 安卓TV上,无法通过上下左右键,以及遥控器的上下左右来获取输入框焦点. 原因: 脸书的锅,但没修,这里官方的说法,Te ...