(九)ELF和动态链接
前言:
我们都知道我们所写的程序是被编译为一条条的CPU指令去执行的,但是在linux系统下能够运行的程序在windows环境下却运行不起来,但是我们使用的CPU明明是一样的,这又是为什么呢?
一、程序的执行:编译、链接和装载
程序示例1:
// add_lib.c
int add(int a, int b)
{
return a+b;
}
// link_example.c #include <stdio.h>
int main()
{
int a = 10;
int b = 5;
int c = add(a, b);
printf("c = %d\n", c);
}
单独编译:
$ gcc -g -c add_lib.c link_example.c
$ objdump -d -M intel -S add_lib.o
$ objdump -d -M intel -S link_example.o
编译结果:
add_lib.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <add>:
0: 55 push rbp
1: 48 89 e5 mov rbp,rsp
4: 89 7d fc mov DWORD PTR [rbp-0x4],edi
7: 89 75 f8 mov DWORD PTR [rbp-0x8],esi
a: 8b 55 fc mov edx,DWORD PTR [rbp-0x4]
d: 8b 45 f8 mov eax,DWORD PTR [rbp-0x8]
10: 01 d0 add eax,edx
12: 5d pop rbp
13: c3 ret
link_example.o: file format elf64-x86-64
Disassembly of section .text:
0000000000000000 <main>:
0: 55 push rbp
1: 48 89 e5 mov rbp,rsp
4: 48 83 ec 10 sub rsp,0x10
8: c7 45 fc 0a 00 00 00 mov DWORD PTR [rbp-0x4],0xa
f: c7 45 f8 05 00 00 00 mov DWORD PTR [rbp-0x8],0x5
16: 8b 55 f8 mov edx,DWORD PTR [rbp-0x8]
19: 8b 45 fc mov eax,DWORD PTR [rbp-0x4]
1c: 89 d6 mov esi,edx
1e: 89 c7 mov edi,eax
20: b8 00 00 00 00 mov eax,0x0
25: e8 00 00 00 00 call 2a <main+0x2a>
2a: 89 45 f4 mov DWORD PTR [rbp-0xc],eax
2d: 8b 45 f4 mov eax,DWORD PTR [rbp-0xc]
30: 89 c6 mov esi,eax
32: 48 8d 3d 00 00 00 00 lea rdi,[rip+0x0] # 39 <main+0x39>
39: b8 00 00 00 00 mov eax,0x0
3e: e8 00 00 00 00 call 43 <main+0x43>
43: b8 00 00 00 00 mov eax,0x0
48: c9 leave
49: c3 ret
分析:实际上以上编译结果是无法运行的,下面来分析一下
- 编译结果的两个文件左侧指令地址行都从0开始显然是重复的,这必然导致call指令无法寻址,它也不知道应该跳转去哪个文件。
- 实际上以上编译结果的两个文件并不是可执行文件,只是目标文件,只有通过链接器将多个目标文件以及调用库链接起来,才能成为一个可执行文件。
gcc -o 命令进行链接:
$ gcc -o link-example add_lib.o link_example.o
$ ./link_example
c = 15
链接结果:
link_example: file format elf64-x86-64
Disassembly of section .init:
...
Disassembly of section .plt:
...
Disassembly of section .plt.got:
...
Disassembly of section .text:
... 6b0: 55 push rbp
6b1: 48 89 e5 mov rbp,rsp
6b4: 89 7d fc mov DWORD PTR [rbp-0x4],edi
6b7: 89 75 f8 mov DWORD PTR [rbp-0x8],esi
6ba: 8b 55 fc mov edx,DWORD PTR [rbp-0x4]
6bd: 8b 45 f8 mov eax,DWORD PTR [rbp-0x8]
6c0: 01 d0 add eax,edx
6c2: 5d pop rbp
6c3: c3 ret
00000000000006c4 <main>:
6c4: 55 push rbp
6c5: 48 89 e5 mov rbp,rsp
6c8: 48 83 ec 10 sub rsp,0x10
6cc: c7 45 fc 0a 00 00 00 mov DWORD PTR [rbp-0x4],0xa
6d3: c7 45 f8 05 00 00 00 mov DWORD PTR [rbp-0x8],0x5
6da: 8b 55 f8 mov edx,DWORD PTR [rbp-0x8]
6dd: 8b 45 fc mov eax,DWORD PTR [rbp-0x4]
6e0: 89 d6 mov esi,edx
6e2: 89 c7 mov edi,eax
6e4: b8 00 00 00 00 mov eax,0x0
6e9: e8 c2 ff ff ff call 6b0 <add>
6ee: 89 45 f4 mov DWORD PTR [rbp-0xc],eax
6f1: 8b 45 f4 mov eax,DWORD PTR [rbp-0xc]
6f4: 89 c6 mov esi,eax
6f6: 48 8d 3d 97 00 00 00 lea rdi,[rip+0x97] # 794 <_IO_stdin_used+0x4>
6fd: b8 00 00 00 00 mov eax,0x0
702: e8 59 fe ff ff call 560 <printf@plt>
707: b8 00 00 00 00 mov eax,0x0
70c: c9 leave
70d: c3 ret
70e: 66 90 xchg ax,ax
...
Disassembly of section .fini:
...
分析:
- 可以发现通过链接生成的可执行文件和之前生成的目标文件在格式上并无区别,这中文件格式称为 ELF(Execuatable and Linkable File Format)
- 文件中包含函数(如main和add),此外还包含一些定义的全局可访问的变量名称,这些变量被存储在被称为符号表的位置,符号表用于关联名称和地址;
- 在该文件中main函数调用add函数也不再是跳转下一指令地址,而是直接跳转到add函数入口。
由c语言生成汇编码再到机器码执行的过程分两部分:
- 编译、汇编、链接生成可执行文件
- 通过装载器将可执行文件装载到内存,而CPU是从内存中读取指令并运行的。
二、ELF文件结构
- ELF文件分为多个部分,称为多个section,并且有一个基本的文件头用来保存文件的基本属性,包括是否为可执行文件、操作系统、CPU型号等
- .text Section 保存代码段和指令段
- .data Section 保存程序里设置好的初始化信息
- .real.text Section 保存程序里面我们暂时位置的跳转地址,比如链接之前的目标文件中add函数的跳转地址
- .symtab Section 符号表,保存当前文件里面我们未知的函数名称和地址的对应关系
三、ELF文件链接过程
链接时,扫描所有目标文件,收集所有符号表,将所有符号表合并成一个符号表;
根据重定向表所有不确定的地址进行修正;
将代码段进行合并,生成一个可执行文件;
总结:
讲了这么多,为什么linux环境下的可执行文件和windows环境下的不同呢?这是因为两种环境下运行的可执行文件的文件格式是不一样的,而想要在linux环境运行windows环境的可执行文件,需要通过一种能够兼容ELF格式文件的装载器。
扩展:这里可以联系java的类装载机制,class被加载到方法区才能运行,其实jvm内的方法区就是一个大的.text Section,全局的。
(九)ELF和动态链接的更多相关文章
- 实例分析ELF文件动态链接
参考文献: <ELF V1.2> <程序员的自我修养---链接.装载与库>第6章 可执行文件的装载与进程 第7章 动态链接 <Linux GOT与PLT> 开发平台 ...
- ELF 文件 动态链接 - 地址无关代码(GOT)
Linux 系统中,ELF动态链接文件被称为 动态共享对象(DSO,Dynamic Shared Object),简称共享对象 文件拓展名为".so" 动态链接下 一个程序可以被分 ...
- ELF动态链接
为什么要使用动态链接? 在现代的linux系统中,假设一个普通的程序会使用到c语言静态库至少1MB以上,那么,如果我们的机器运行100个这样的程序,就用浪费近100MB的内存:如果磁盘有2000个这样 ...
- 程序员的自我修养九Windows下的动态链接
9.1 DLL简介 DLL即动态链接库的缩写,它相对于Linux下的共享对象. Windows下的DLL文件和EXE文件实际上是一个概念,它们都是有PE格式的二进制文件. 微软希望通过DLL机制加强软 ...
- ELF 动态链接 - so 的 .dynamic 段
动态链接文件中最重要的段就是 .dynamic段 这个段里保存了动态链接器需要的最基本的信息 比如:1. 依赖于哪些共享对象, d_tag = DT_NEED, d_ptr 表示共享对象文件名 2 ...
- ELF文件加载与动态链接(一)
关于ELF文件的详细介绍,推荐阅读: ELF文件格式分析 —— 滕启明.ELF文件由ELF头部.程序头部表.节区头部表以及节区4部分组成. 通过objdump工具和readelf工具,可以观察ELF文 ...
- ELF文件加载与动态链接(二)
GOT应该保存的是puts函数的绝对虚地址,这里为什么保存的却是puts@plt的第二条指令呢? 原来“解释器”将动态库载入内存后,并没有直接将函数地址更新到GOT表中,而是在函数第一次被调用时,才会 ...
- ELF 动态链接 - so 的 重定位表
动态链接下,无论时可执行文件还是共享对象,一旦对其他共享对象有依赖,也就是所有导入的符号时,那么代码或数据中就会有对于导入符号的引用.而在编译时期这些导入符号的确切地址时未知的.只有在运行期才能确定真 ...
- ELF 动态链接 so的动态符号表(.dynsym)
静态链接中有一个专门的段叫符号表 -- ".symtab"(Symbol Table), 里面保存了所有关于该目标文件的符号的定义和引用. 动态链接中同样有一个段叫 动态符号表 - ...
随机推荐
- c#分割习题
2.从一个记录了学生成绩的文本文档,每个学生成绩是一行,每行是用 | 分割的数据,用 | 分割的域分别是姓名.年龄.成绩.年级,写程序取出各个年级成绩最高学生的成绩.年级放到集合中.提示:(1)使用 ...
- 10、Django与Ajax
AJAX准备知识:JSON 什么是 JSON ? JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation) JSON 是轻量级的文本数据交换格式 JS ...
- CSS3:overflow属性详解
1.Overflow overflow为溢出(容器),当内容超出容器时只需添加overflow属性值为hidden, 就可以把超出容器的部分隐藏起来: 如果内容超出容器却又不想其隐藏时可以将其属性值设 ...
- UNP——第二章,常见协议概述
1.为什么要了解协议 程序员与协议合作,完成应用. 了解协议是为了了解协议完成了什么,提供了什么服务,自己还应该做什么. 2.从协议的角度,套接字是什么 套接字是协议的接口, IP套接字,代表可使用I ...
- linux域名解析引起登陆慢
linux域名解析引起登陆慢的问题在于,ssh去登录这个台机器的时候,本机会去通过域名解析获取登录主机的主机名,所有一旦域名解析是无效的,需要等待较长时间 解决办法一: 将域名解析指到127.0.0. ...
- 系统运行后修改linux系统时区
在网上看了很多改时间的帖子,都没能最终解决问题.最后还是下面的博客最终解决的时间的问题,感谢原作者 安装系统过程时没有选对当前的时区,即CST,Asia/Shanghai,而是按默认的,EDT时区,这 ...
- Python博文_爬虫工程师是干什么的
程序员有时候很难和外行人讲明白自己的工作是什么,甚至有些时候,跟同行的人讲清楚"你是干什么的"也很困难.比如我自己,就对Daivd在搞的语义网一头雾水.所以我打算写一篇博客,讲一下 ...
- Python_算法汇总
1. 约瑟夫环: # 约瑟夫环:共31个数,每隔9个删除一个,要求输出前15个号码 a=[x for x in range(1,31)] #生成编号 del_number = 8 #该删除的编号 fo ...
- 理解Java对象:要从内存布局及底层机制说起,话说….
前言 大家好,又见面了,今天是JVM专题的第二篇文章,在上一篇文章中我们说了Java的类和对象在JVM中的存储方式,并使用HSDB进行佐证,没有看过上一篇文章的小伙伴可以点这里:<类和对象在JV ...
- tp5 删除图片以及文件
控制器调用 /** * [delimg 删除单张图片] * @return [type] [description] */ public function delimg(){ if (request( ...