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 ...
随机推荐
- 多测师讲解自动化测试 _接口面试题(001)_高级讲师肖sir
1.为什么要做接口测试(必要性)1.可以发现很多在页面上操作发现不了的bug2.检查系统的异常处理能力3.检查系统的安全性.稳定性4.前端随便变,接口测好了,后端不用变5.可以测试并发情况,一个账号, ...
- Linux发行版教你如何选 给入门者的选择通法
Linux的发行版何止琳琅满目,简直是乱入你眼. 本篇将介绍选择发行版的经验和通用法则,主要会从PC角度去谈. 更新于2020年,初次发布于2017年 选择发行版需考虑哪些因素 选择发行版时需要考虑的 ...
- linux磁盘空间满的处理
Java中运行SQL插入数据时报错: linux磁盘空间满处理: 1.df -h 查看磁盘空间占用,实际上是查看磁盘块占用的文件(block) 2.分别查看输入以下命令 (面对磁盘满了,通过下列命令 ...
- 面经手册 · 第14篇《volatile 怎么实现的内存可见?没有 volatile 一定不可见吗?》
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.码场心得 你是个能吃苦的人吗? 从前的能吃苦大多指的体力劳动的苦,但现在的能吃苦已经包括太 ...
- poj1011 Sticks (搜索经典好题)
poj1011 Sticks 题目连接: poj1011 Description George took sticks of the same length and cut them randomly ...
- Android测试工具 UIAutomator介绍
UI Automator 测试工具定义以及用途 UI Automator 测试框架提供了一组 API,用于构建在用户应用和系统应用上执行交互的界面测试.通过 UI Automator API,您可以执 ...
- # ThreeJS学习7_裁剪平面(clipping)
ThreeJS学习7_裁剪平面(clipping) 目录 ThreeJS学习7_裁剪平面(clipping) 1. 裁剪平面简介 2. 全局裁剪和局部裁剪 3. 被多个裁剪平面裁剪后 4. 被多个裁剪 ...
- 多线程之Callable
多线程实现Callable的好处有三点 1.Callable支持泛型 2.Callable支持返回值 3.Callable可以抛出异常 class MyThread2 implements Calla ...
- git每次提交代码都要设置账号密码的问题
git config --global credential.helper store 待下一次提交代码的时候,输入了正确的用户名和密码,之后 就不需要输入用户名密码
- 02 HTML 常见标记 选择器 样式
no.02今天主要学习了在web中的HTML CSS,并在其中制作了明信片,在制作明信片途中有几个知识点需要总结:1.HTML 全称hyper text markup language 超文本标记语言 ...