首页 > 其他分享 >动态链接的执行过程

动态链接的执行过程

时间:2024-03-21 19:12:37浏览次数:25  
标签:动态 函数 process create PLT 动态链接库 GOT 执行 链接

背景:静态链接库一旦链接进去,代码和变量的 section 都合并了,因而程序运行的时候,就不依赖于这个库是否存在。但是这样有一个缺点:

  • 就是相同的代码段,如果被多个程序使用的话,在内存里面就有多份

  • 而且一旦静态链接库更新了,如果二进制执行文件不重新编译, 也不随着更新

因而就出现了另一种,动态链接库(Shared Libraries),不仅仅是一组对象文件的简单归档,而是多个对象文件的重新组合,可被多个程序共享。

当一个动态链接库被链接到一个程序文件中的时候,最后的程序文件并不包括动态链接库中的代码,而仅仅包括对动态链接库的引用,并且不保存动态链接库的全路径,仅仅保存动态链接库的名称。当运行这个程序的时候,首先寻找动态链接库,然后加载它。

动态链接库,就是 ELF 的第三种类型,共享对象文件(Shared Object)(目标文件、可执行文件)。

基于动态连接库创建出来的二进制文件格式还是 ELF,但是稍有不同。

  • 首先,多了一个.interp 的 Segment,这里面是 ld-linux.so,这是动态链接器,也就是说,运行时的链接动作都是它做的

  • 另外,ELF 文件中还多了两个 section,一个是.plt,过程链接表Procedure Linkage Table,PLT),一个是.got.plt,全局偏移量表Global Offset Table,GOT)。

它们是怎么工作的,使得程序运行的时候,可以将 so 文件动态链接到进程空间的呢?

dynamiccreateprocess 这个程序要调用 libdynamicprocess.so 里的 create_process 函数。由于是运行时才去找,编译的时候,压根不知道这个函数在哪里,所以就在 PLT 里面 建立一项 PLT[x]。这一项也是一些代码,有点像一个本地的代理,在二进制程序里面,不直接调用 create_process 函数,而是调用 PLT[x] 里面的代理代码,这个代理代码会在运行的时候找真正的 create_process 函数

去哪里找代理代码呢?这就用到了 GOT,这里面也会为 create_process 函数创建一项 GOT[y]。这一项是运行时 create_process 函数在内存中真正的地址。

如果这个地址在,dynamiccreateprocess 调用 PLT[x] 里面的代理代码,代理代码调用 GOT 表中对应项 GOT[y],调用的就是加载到内存中的 libdynamicprocess.so 里面的 create_process 函数了。

但是 GOT 怎么知道的呢?对于 create_process 函数,GOT 一开始就会创建一项 GOT[y],但是这里面没有真正的地址,因为它也不知道,但是它有办法,它又回调 PLT, 告诉它,你里面的代理代码来找我要 create_process 函数的真实地址,我不知道,你想想 办法吧。

PLT 这个时候会转而调用 PLT[0],也即第一项,PLT[0] 转而调用 GOT[2],这里面是 ldlinux.so 的入口函数这个函数会找到加载到内存中的 libdynamicprocess.so 里面的 create_process 函数的地址,然后把这个地址放在 GOT[y] 里面。下次,PLT[x] 的代理函 数就能够直接调用了。

标签:动态,函数,process,create,PLT,动态链接库,GOT,执行,链接
From: https://www.cnblogs.com/love-9/p/18088075

相关文章

  • 代码随想录算法训练营第五十三天 | 53. 最大子序和 动态规划,1035.不相交的线,1143.最
    53.最大子数组和 已解答中等 相关标签相关企业 给你一个整数数组 nums ,请你找出一个具有最大和的连续子数组(子数组最少包含一个元素),返回其最大和。 子数组 是数组中的一个连续部分。  示例1:输入:nums=[-2,1,-3,4,-1,2,1,-5,4]......
  • 插件-js实现动态时钟效果
    <divid="updatetime"></div>constupdateTime=()=>{varnow=newDate();varyear=now.getFullYear();varmonth=now.getMonth()+1;//getMonth()返回0-11varday=now.getDate();varhours=now.getHour......
  • 动态开点并查集+树上差分
    https://www.acwing.com/problem/content/description/2071/每次合并的时候需要开一个新点去实现信息的无后效性,也就是合并之前的两个连通块信息是无法共享的,发现这样开点连边最后形成一棵树,每次我们将信息传递到新点,也是两个合并点的lca,这使得最后求答案的直接求一边树上前缀和......
  • xshell链接不上hadoop虚拟机
    输入ifconfig查看是否有ens33没有的话解决方案如下:systemctlstopNetworkManagersystemctlrestartnetwork.serviceservicenetworkrestartsys 依次输入以上命令如果报错或者没用的话,进入root重新输入一遍这三个命令大功告成! ......
  • .NET Emit 入门教程:第二部分:构建动态程序集(追加构建静态程序集教程)
    前言:在本部分中,我们将深入探讨如何使用C#Emit来创建动态程序集。动态程序集是在运行时生成的,为我们提供了一种灵活、动态地构建和加载程序集的能力。1.程序集的概念程序集是.NET中的基本部署单位,它包含了可执行代码、资源、元数据等信息,是.NET应用程序的基本组成单元之一。......
  • Jmeter的元件作用域和执行顺序
    一、元件的基本介绍元件:多个类似功能组件的容器(类似于类) 取样器 逻辑控制器 前置处理器 后置处理器 断言 定时器 测试片段 配置元件 监听器 组件:实现独立的某个功能(类似于方法)2、元件作用域在JMeter中,元件的作用域是靠测试计划的树形结构中元件的父子关......
  • Asp-Net-Core开发笔记:实现动态审计日志功能
    前言最近一直在写Go和Python,好久没写C#,重新回来写C#代码时竟有一种亲切感~说回正题。在当今这个数字化迅速发展的时代,每一个操作都可能对业务产生深远的影响,无论是对数据的简单查询,还是对系统配置的修改。在这样的背景下,审计日志不仅仅是一种遵循最佳实践的手段,更是确......
  • linq链接数据库SQL封装类
    linq链接数据库SQL封装类首先,需要定义一个LINQtoSQL的上下文类,这个类是从DataContext继承而来,并且包含了映射到数据库表的实体类。[Database(Name="MyDatabase")]publicclassMyDataContext:DataContext{publicTable<User>Users;publicMyDataContext(stri......
  • SpringBoot:如何读取 .sql文件的内容并执行
    摘要:在复杂查询、统计等应用场景,直接写sql并执行是一种高效的方法。此文记录工作中解决的将查询统计sql直接写在文件中,代码中读取相应的文件即可获得要执行的sql。要点:.sql文件要放到Resource目录下,读取时路径要正确一种正确的方式和关键代码这里提供的是一种尝试过的......
  • 深入理解 SpringAOP(二):AOP的执行流程
    概述在之前的文章中,我们已经对SpringAOP的关键组件进行了描述,并且了解了其基本操作和流程。在本文中,我们将进一步深入源码,揭示SpringAOP的内部实现细节,理解其运行机制的每个环节,包括切面的织入方式、代理对象的创建过程、连接点的定位与匹配等。通过对完整运行流程的深入研究......