Mach-O 的动态链接(Lazy Bind 机制)
动态链接
要解决空间浪费和更新困难这两个问题最简单的方法就是把程序的模块相互分割开来,形成独立的文件,而不再将它们静态的链接在一起。简单地讲,就是不对那些组成程序的目标文件进行链接,等到程序要运行时才进行链接。也就是说,把链接过程推迟到了运行时再进行,这就是 _动态链接(Dynamic Linking)_的思想。
延迟绑定(PLT)
动态链接比静态链接性能低,主要原因是动态链接下对于全局和静态的数据访问都要进行复杂的GOT定位,间接寻址;对于模块间的调用也要先定位GOT,间接跳转, 程序的运行速度一定会减慢。 另外因为动态链接是在运行时完成链接的工作:在程序开始执行时,动态链接器都要进行一次链接工作,动态链接器会 search 并 load 所需要的 共享对象,然后进行符号查询 地址重定位,这一系列动作会减慢程序的启动速度。
PLT 就是为了优化动态链接性能而存在,基本思想就是 当函数第一次被调用到时才进行绑定(符号查找,重定位),如果没有用到则不进行 bind。 这样在程序执行时,模块间的函数调用都没有进行 bind , 而是需要调用时才由 动态链接器来负责 bind 。这样可以加速程序的启动速度。
Mach-O Lazy Bind
Mach-O 文件通过dyld 加载的时候并没有确定每一个函数的具体地址在哪里,而是在真正调用该函数的时候通过 过程链接表(procedure linkage table),简称 PLT,来进行一次lazybind。
结合Mach-O 文件的分析与代码的调试简单的分析一下。
源代码如下:

分别在两个printf函数处下 断点。
第一个调用printf函数

在0x100000f52 \<+34\>行处通过callq 0x100000f76 来调用printf。
执行callq指令 之后代码跳转到这里:

这里的jmpq 要跳转到 0x0000000100000F8C ,这个地址是从 —Data , —la-symbol-ptr 中的Lazy Symbol Pointers 中获取到的。

通过lldb 的命令 查看 0x100001010处的地址 获取了同样的值。
通过—stub—helper进行lazybind
在Mach-O 中每一个Symbol Stub 可能有以下两种行为其中之一:跳转到函数的指令,执行函数体,通过动态动态库链接器查找函数的Symbol,然后执行函数体
查看 —stubs的Section 数据,发现只有一个函数就是 printf

这里的Data 其实就是上面看到的 jmpq 的代码。执行之后代码跳转到了这样的代码片段。

这里就是通过 —stub-helper来调用 dyld-stubbinder函数来计算printf 函数的真是地址。 通过下面的 信息可以看出来,jmpq 0x100000f7c ,就是在压如入参数0x0 (函数的link 的时候给的编号) 之后跳转到Section的起始处,调用 binder(一段汇编代码, 作用就是计算具体的函数地址,并调用printf 函数)

第二次调用printf 函数

执行指令之后发现和第一次调用printf 已经不一样了。

再一次查看 0x100001010 处内存值。已经很第一次不同了,也就是说, —Data, —la-symbol-ptr 中指向printf地址的值已经发生了变化,指向了 printf的指令。
这就证明了,延迟绑定只会在第一次调用的时候发生。整个流程与 linux中的PLT 和GOT 在实现逻辑上基本相同,只是实现代码不同而已。
参考《Mac OS X and iOS Internals》、《链接,装载与库》
原文链接:http://blog.tingyun.com/web/article/detail/1347
Mach-O 的动态链接(Lazy Bind 机制)的更多相关文章
- [CSAPP-II] 链接[符号解析和重定位] 静态链接 动态链接 动态链接接口
1 平台 转http://blog.csdn.net/misskissc/article/details/43063419 1.1 硬件 Table 1. 硬件(lscpu) Architecture ...
- 程序员的自我修养九Windows下的动态链接
9.1 DLL简介 DLL即动态链接库的缩写,它相对于Linux下的共享对象. Windows下的DLL文件和EXE文件实际上是一个概念,它们都是有PE格式的二进制文件. 微软希望通过DLL机制加强软 ...
- Android so 文件进阶<二> 从dlsym()源码看android 动态链接过程
0x00 前言 这篇文章其实是我之前学习elf文件关于符号表的学习笔记,网上也有很多关于符号表的文章,怎么说呢,感觉像是在翻译elf文件格式的文档一样,千篇一律,因此把自己的学习笔记分享出来.dls ...
- 聊聊动态链接和dl_runtime_resolve
写在前面 linux下的动态链接相关结构,重新回顾_dl_runtime_resolve的流程以及利用方法 动态链接相关结构 为了高效率的利用内存,多个进程可以共享代码段.程序模块化方便更新维护等,动 ...
- 实例分析ELF文件动态链接
参考文献: <ELF V1.2> <程序员的自我修养---链接.装载与库>第6章 可执行文件的装载与进程 第7章 动态链接 <Linux GOT与PLT> 开发平台 ...
- Linux下实现C++类的动态链接
1. 背景 在java中,jvm支持类的动态链接(Class.forName(String className)),用起来也很方便.动态链接是实现IOC(Inversion of Control,控制 ...
- 再探Linux动态链接 -- 关于动态库的基础知识
在近一段时间里,由于多次参与相关专业软件Linux运行环境建设,深感有必要将这些知识理一理,供往后参考. 编译时和运行时 纵观程序编译整个过程,细分可分为编译(Compiling,指的是语言到平台 ...
- linux 下动态链接实现原理
符号重定位 讲动态链接之前,得先说说符号重定位. c/c++ 程序的编译是以文件为单位进行的,因此每个 c/cpp 文件也叫作一个编译单元(translation unit), 源文件先是被编译成一个 ...
- Python 调度算法 死锁 静动态链接 分页分段
1 select poll epoll的区别基本上select有3个缺点: 连接数受限查找配对速度慢数据由内核拷贝到用户态poll改善了第一个缺点 epoll改了三个缺点. (1)select,pol ...
随机推荐
- 对抗密码破解 —— Web 前端慢 Hash
(更新:https://www.cnblogs.com/index-html/p/frontend_kdf.html ) 0x00 前言 天下武功,唯快不破.但在密码学中则不同.算法越快,越容易破. ...
- Hawk 6. 高级话题:子流程系统
子流程的定义 当流程设计的越来越复杂,越来越长时,就难以进行管理了.因此,采用模块化的设计才会更加合理.本节我们介绍子流程的原理和使用. 所谓子流程,就是能先构造出一个流程,然后被其他流程调用.被调用 ...
- JQuery 选择器
选择器是JQuery的根基,在JQuery中,对事件的处理,遍历DOM和AJAX操作都依赖于选择器.如果能够熟练地使用选择器,不仅能简化代码,而且还可以事半功倍. JQuery选择器的优势 1.简洁的 ...
- Web安全相关(五):SQL注入(SQL Injection)
简介 SQL注入攻击指的是通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击者所要的操作,其主要原因是程序没有细致地过滤用户输入的数据 ...
- spring boot 部署为jar
前言 一直在ide中敲代码,使用命令行mvn spring-boot:run或者gradlew bootRun来运行spring boot项目.想来放到prod上面也应该很简单.然而今天试了下,各种问 ...
- MFC中成员变量的声明顺序与析构顺序
第一次用博客,第一篇随笔,就写今天遇到的一个问题吧. 在VS2008的MFC对话框程序,窗口成员变量的声明顺序与其析构顺序相反,即,先声明的变量后析构,后声明的变量先析构.未在其他模式下测试. cla ...
- VIM教程
vim 的环境设定参数 :set nu :set nonu 就是设定与取消行号啊! :set hlsearch :set nohlsearch hlsearch 就是 ...
- 将css和js缓存到localStorage缓存,提高网页响应速度
适用于小站点,这很极致,很快速~~ /** * Created by SevenNight on 2016/9/21 0021. * 插件功能:使用localStorage缓存js和css文件,减少h ...
- 使用EntityFramework6连接MySql数据库(code first方式)
demo托管地址:http://git.oschina.net/uustudy/ASP.NET-CodeFirst-MySQL-Demo.git 之前的是db first(地址:http://www. ...
- ReactNative入门(安卓)——API(下)
LayoutAnimation - layout动画 当布局发生改变时的动画模块,它有两个方法: 1. 最常用的方法是 LayoutAnimation.configureNext(conf<Ob ...