动态链接下,无论时可执行文件还是共享对象,一旦对其他共享对象有依赖,也就是所有导入的符号时,那么代码或数据中就会有对于导入符号的引用。而在编译时期这些导入符号的确切地址时未知的。只有在运行期才能确定真正确切的地址

静态编译下,这些未知的地址会被编译器一一修正。

对于动态链接来说,共享文件有两种编译方式(gcc -shared 和 gcc -fPIC -shared)

如果不使用PIC模式编译,那么装载时肯定是要重定位的,而且时每个进程都有一个副本(相对比较占用内存)

如果使用PIC模式编译,将会在编译期生成地址无关代码(PIC Position-Independent Code),则代码段可以实现多程序共享,而仅数据段部分会在每个程序中有一个副本(节省内存)

对于这两种模式来说都是要重定位的,当相对PIC模式编译的模块仅需要对数据段进行重定位(因为代码段中的绝对地址引用部分被分离到了GOT中,而GOT是数据段的一部分;数据段中也可能包含绝对地址的引用,正好重定位数据段)

静态链接中,目标文件里面包含有用于重定位的表:代码段重定位表“.rel.text”;数据段重定位表“.rel.data”。

动态链接中,目标文件的重定位表:“.rel.dyn”对数据引用的修正,修正的位置位于“.got”和数据段;“.rel.plt”对函数引用的修正,修正位置位于“.got.plt”。

可以通过readelf 查看一个动态链接文件的重定位表

 readelf -r XXX.so

这里可以看到几种重定位入口类型:

R_386_RELATIVE  R_386_GLOB_DATR_386_JUMP_SLOT

R_386_GLOB_DAT(.rel.dyn中针对.got)R_386_JUMP_SLOT(.rel.plt中针对.got.plt)表示被修正的位置只需要直接将符号的地址填入。

而在重定位表中的列Offset 表明了当前符号在“.got" 或“.got.plt”中的偏移,可以根据该值在两个GOT表中寻找对应的位置,填入(连接器在全局符号表中查找)真实的外部符号地址。

R_386_RELATIVE 是基址重置。有些共享对象的数据段是无法做到地址无关的,比如:

static int a;
static int *p = &a;

由于共享对象编译时,基址是从0开始的,所以a的地址(在未重定位时)是相对与起始地址0的偏移(假设为B),则此时p的值为B;

而当共享对象装载到指定进程中的地址C时,则变量a的地址将编程B+C,即p的值需要加上装载的地址B。

R_386_RELATIVE 类型就是专门用来重定位指针变量p这种类型的。

ELF 动态链接 - so 的 重定位表的更多相关文章

  1. ELF动态链接

    为什么要使用动态链接? 在现代的linux系统中,假设一个普通的程序会使用到c语言静态库至少1MB以上,那么,如果我们的机器运行100个这样的程序,就用浪费近100MB的内存:如果磁盘有2000个这样 ...

  2. ELF 动态链接 - so 的 .dynamic 段

    动态链接文件中最重要的段就是 .dynamic段 这个段里保存了动态链接器需要的最基本的信息 比如:1.  依赖于哪些共享对象, d_tag = DT_NEED,  d_ptr 表示共享对象文件名 2 ...

  3. Reverse Core 第二部分 - 16&17章 - 基址重定位表&.reloc节区

    第16-17章 - 基址重定位表&.reloc节区 @date: 2016/11/31 @author: dlive 0x00 前言 这几天忙着挖邮箱漏洞,吃火锅,马上要被关禁闭,看书进度比较 ...

  4. PE格式第七讲,重定位表

    PE格式第七讲,重定位表 作者:IBinary出处:http://www.cnblogs.com/iBinary/版权所有,欢迎保留原文链接进行转载:) 一丶何为重定位(注意,不是重定位表格) 首先, ...

  5. PE文件 03 重定位表

    0x01  重定位表结构   重定位表是由数据目录表中的第六个成员指出的: typedef struct _IMAGE_DATA_DIRECTORY { DWORD VirtualAddress; D ...

  6. 基址重定位表&.reloc节区

    第16-17章 - 基址重定位表&.reloc节区 @date: 2016/11/31 @author: dlive 0x01 PE重定位 若加载的是DLL.SYS文件,且在ImageBase ...

  7. 逆向-PE重定位表

    重定位表 ​ 当链接器生成一个PE文件时,会假设这个文件在执行时被装载到默认的基地址处(基地址+RVA就是VA).并把code和data的相关地址写入PE文件.如果像EXE一样首先加载就是它image ...

  8. PE结构之重定位表

    什么是重定位: 重定位就是你本来这个程序理论上要占据这个地址,但是由于某种原因,这个地址现在不能让你占用,你必须转移到别的地址,这就需要基址重定位.你可能会问,不是说过每个进程都有自己独立的虚拟地址空 ...

  9. PE知识复习之PE的重定位表

    PE知识复习之PE的重定位表 一丶何为重定位 重定位的意思就是修正偏移的意思.  如一个地址位 0x401234 ,Imagebase = 0x400000 . 那么RVA就是 1234.  如果Im ...

随机推荐

  1. [ExtJS5学习笔记]第十九节 Extjs5中通过设置form.Panel的FieldSet集合属性控制多个field集合

    本文地址:http://blog.csdn.net/sushengmiyan/article/details/39209533 官方例子:http://docs.sencha.com/extjs/5. ...

  2. UNIX环境高级编程——单实例的守护进程

    #include <stdio.h> #include <stdlib.h> #include <string.h> #include <signal.h&g ...

  3. Android计时器Chronometer-android学习之旅(二十一)

    Chronometer简介 Chronometer和DigitalColok都继承与TextView,但是Chronometer不是显示的当前时间,而是从某个时间开始又过去了多少时间,是一个时间差. ...

  4. UNIX网络编程——sockatmark函数

    每当收到一个带外数据时,就有一个与之关联的带外标记.这是发送进程发送带外字节时该字节在发送端普通数据流中的位置.在从套接字读入期间,接收进程通过调用sockatmark函数确定是否处于带外标记. #i ...

  5. Android的actionBar的菜单使用-android学习之旅(四十三)

    ActionBar简介 ActionBar是3.0以后加入的新特性,可用于在顶部显示应用名称和标题.初次之外右边还可以显示活动项. ActionBar应用 ActionBar用法 <?xml v ...

  6. Android的DatePicker和TimePicker-android学习之旅(三十八)

    DatePicker和TimePicker简介 DatePicker和TimePicker是从FrameLayout继承而来,他们都是比较简单的组件.时间改变时间分别添加OnDateChangeLis ...

  7. APACHE,NGINX 详细分析

    Apache是目前最流行的Web应用服务器,占据了互联网应用服务器70%以上的份额.Apache能取得如此成功并不足为奇:它免费.稳定且性能卓越:但Apache能取得如此佳绩的另一个原因是,当时互联网 ...

  8. Android ToggleButton 实践

    在android的开发过程中,对于ToggleButton的使用频率也是相当的高的,下面我就来说一下,这个组件的两种使用方式. 第一种是简单的使用,利用Toast的方式弹出提示语句 需要注意的是要想自 ...

  9. Linux信号实践(1) --Linux信号编程概述

    中断 中断是系统对于异步事件的响应, 进程执行代码的过程中可以随时被打断,然后去执行异常处理程序; 计算机系统的中断场景:中断源发出中断信号 -> CPU判断中断是否屏蔽屏蔽以及保护现场 -&g ...

  10. input驱动12种事件类型Event types的含义

    linux2.6 input subsystem中部分相关结构体的分析  最近在做linux2.6的键盘驱动程序的工作,接触到了input subsystem这一概念,现把我对其中相关结构体的理解写出 ...