首页 > 其他分享 >可重定位文件

可重定位文件

时间:2022-10-30 14:23:13浏览次数:47  
标签:定位 可重 文件 程序 地址 运行 OS 虚拟内存

可重定位文件介绍

目标文件是可重定位文件,可以根据链接脚本把section内的代码映射到实际运行的地址。

 

 

 

 

 .line:原始C源程序中的行号和 .text节中机器指令之间的映射

查看符号表举例如下:

重定位含义

重定位地址举例:

 

 左侧全部使用 0 1 来表示程序, 0010 表示“跳转”指令,指令后接的就是跳转的地址,现在跳转的地址是 0101 (即 5),但是如果在 3 的位置插入一条指令的话,那么需要跳转的地址可能就不是 0101 了,从而导致程序的修改。

 

1 重定位

链接器在完成了符号解析之后,就可以进行重定位了。

不过由于重定位的内容比较复杂,当然如果你是做编译器或者逆向的话,重定位的原理是必须要求掌握的,但是作为应用开发者来说这不需要,因为了解详细原理的意义不大,因此有关重定位,我们这里只介绍基本内容。

1.1 重定位的种类

重定位的种类其实有两种,

(1)第一种:动态重定位

        所谓动态重定位就是,重定位的动作是在程序运行的过程中动态完成的,因此被称为动态重定位。加载动态链接库就是动态重定位。

(2)第二种:静态重定位

        所谓静态重定位就是,由链接阶段完成的重定位,因为是在程序运行之前做的重定位,因此被称为静态重定位。

        所以我们现在要讲的由链接器完成的静态重定位。

1.2 静态重定位做什么事情

做两件很重要的事情:

        · 将同名节整合为新的同名聚合节

        · 将可执行目标文件中各聚合节的地址,重定位为实际运行的地址

(1)将同名节整合为新的同名聚合节

其中重点是将.text和.data节聚合为新的同名聚合节,为了能够将.text和.data节聚合为新的聚合节,需要依赖一些信息,这些信息存储在了.rel.text和.rel.data中。

        .rel.text中的信息:实现.text的聚合

        .rel.data中的信息:实现.data的聚合

(2)将可执行目标文件中各聚合节的地址,重定位为实际运行的地址

其实就是将程序在内存中实际运行时的内存地址赋给聚合节,程序在内存中运行时,就是按照重定位的地址来运行的,至于重定位的地址具体是多少,要分裸机和OS两种情况来看。

1)如果程序是直接裸机运行的话(没有OS)

程序是直接运行在物理内存上的,所以重定位的运行地址就是物理地址,所以CPU取指时所取得的指令地址就是物理地址。

2)如果程序是基于OS运行的话

大部分的OS都有提供虚拟内存机制,所以程序是运行在OS虚拟内存上的,虚拟内存所提供的地址就是虚拟地址,所以CPU取指时,所取得的指令地址就是虚拟地址。

虚拟内存是基于真实的物理存储器构建出来的,所以程序最终其实还是运行在物理内存上的,因此虚拟地址最终还是会被转为物理地址,然后到物理内存上该物理地址所指定的位置读取指令。

 

疑问:反正程序最终都是运行在物理内存上的,为什么要在真实物理存储器上弄出一个虚拟内存呢?

        有关这个原因,请大家看《计算机体系结构———操作系统》的课程,里面介绍虚拟内存时有详细介绍。

        我们都知道现在的OS基本都支持多进程并发运行,其实多进程并发运行与虚拟内存机制有着莫大关系。

 

疑问:什么是进程,与程序什么关系?

        · 进程:动态运行的程序,进程有生有死,是一个动态运行的过程

        · 程序:存放在硬盘上,没有运行的静态的可执行目标文件。

 

疑问:什么是进程的并发运行?

        多个进程同时运行,这就并发运行,比如酷狗/浏览器/wps同时运行着,这几个程序就是并发运行的。

        我们这里简单认为,单个程序对应单个的进程,实际上一程序可以是多进程的,有关这一点,请大家看《Linux系统编程、网络编程》这门课,有详细介绍。

 

为什么能够并发运行?

实际上与虚拟内存有很大关系。因为有虚拟内存这个东西,所以每个程序运行时,虚拟内存机制会给每一个进程都弄一个虚拟内存,也就是说每一个进程都是运行在自己独立的虚拟内存上的。

由于进程是运行在虚拟内存上的,因此“虚拟内存空间”也被称为了“进程空间”。

进程运行在自己的虚拟内存上时,每个进程运行了一个短暂的时间片(ms)后,快速切换到其它进程上运行,此时cpu就会取指运行不同进程的指令。

如此在宏观上,我们会感觉所有的进程都是同时运行的,这就是进程的并发运行,从介绍可以看出,进程间的并发运行与虚拟内存机制有着密切的关系。

与并发运行相对应的还有一个概念,那就是“并行运行”,有关这两个概念的异同请看《Linux系统编程、网络编程》的课程。

我们这里所面对的OS是Linux,Linux有虚拟内存机制,所以gcc编译得到的程序基于Linux运行时,就是运行在虚拟内存上的。

(3)如何指定重定位运行地址

实际上是通过“链接脚本文件”来指定的,“链接脚本文件”里面会说明实际的运行地址是多少,重定位时会把实际的运行地址赋值给新的聚合节,如此一来,函数和全局变量就有了真正可以运行的运行地址。

实际运行时,将程序拷贝到运行地址所指定的内存位置,cpu的pc存放第一条指令地址(指向第一条指令_start),然后整个程序就运行起来了。

至于重定位时,给聚合节具体指定的运行地址应该是多少,这里要分裸机和OS两种情况来定。

1)裸机运行

运行地址(物理地址)是多少,可以由程序员自己来定,比如我们一般可以指定为0,表示程序需要拷贝到物理内存的0地址处,从0地址处开始存放。

我们将0地址写到链接脚本文件中,gcc编译时给他指定链接脚本,重定位后运行地址就从0开始。

裸机运行时,整个计算机上就一个程序,由于没有OS虚拟内存的参与,所以裸机只能运行一个程序(单进程)。

2)基于OS运行

运行地址(虚拟地址)为一个固定值,不同OS这个固定值不一样,比如在Linux这边

        32位OS:从0x08048000开始

        64位OS:从0x0000000000400000开始

程序运行时,程序会被拷贝到虚拟内存的0x08048000或者0x0000000000400000位置处,然后pc指向_start,程序就运行起来了。

这个地址也是指定在链接脚本中的,gcc编译基于Linux运行的程序时,这个链接脚本不需要我们自己给,是自动给的,这个脚本中会指定0x08048000或者0x0000000000400000的地址。

而且gcc编译每一个程序,链接重定位所指定的地址都是0x08048000或者0x0000000000400000。

 

疑问:重定位时,如果每个程序都是相同的0x08048000或者0x0000000000400000的话,运行时不会冲突吗?

不会冲突,因为每个进程的虚拟内存是独立的,虽然都是相同的地址,但是底层实际对应的都是不同的物理空间,

 

将虚拟地址转换为物理地址后,得到的物理地址是不同的,所以不同的物理地址所指向的物理空间不同,自然不同物理内存空间中存放的是不同程序的指令。

 

标签:定位,可重,文件,程序,地址,运行,OS,虚拟内存
From: https://www.cnblogs.com/god-of-death/p/16841209.html

相关文章

  • 文件名编码转换工具
    简介基于python开发的编码转换工具,图形化界面基于pyside2(也就是qt5)开发。支持批量转换任意格式的文件编码;可将文件编码转为UTF-8BOM、UTF-8、GB2312中的任意一种......
  • 将本地Markdown文件上传到博客教程
    一、需求原因因为平时记笔记用的是typora,这个用来记笔记挺好用的,但是唯一的缺陷就是没有云端。于是我在网上查了一下,有木有将本地md文件上传到博客园的方法。参考了几个,我......
  • 删掉Win11 22h2文件管理器中的 “主文件夹”
    Win1122h2升级后,文件管理器左侧多了一个"主文件夹"的链接,没啥用还占位置,之前一直较忙没有管它,今天研究了一下,可以通过注册表干掉它:WindowsRegistryEditorVersion5.......
  • C语言学习--文件操作--文件流指针--打开文件
    当打开一个文件时,系统会返回一个结构体,这个结构体有对此文件操作的所有信息调用fopen时,系统返回这个结构体的地址FILE*p=fopen("a.txt")   打开一个文件FIL......
  • 解压文件时报错gzip: stdin:not in gzip format
     tar-vxfjexus-5.8.2-x64.tar.gzgzip:stdin:notingzipformattar:Childreturnedstatus1tar:Errorisnotrecoverable:exitingnow查询 原因:filejexus-5.8.2......
  • Java 读取 Excel 模板,将数据填入Excel表格,后转换为PDF文件(实用)
    前言我在互联网上冲浪的时候,看到有的小伙伴说可以使用​​Excel​​模板,来实现这个功能。这个方式我是喜欢的~(ps:因为不要用代码去画表格,是真的舒服~)大致流程如下:编写一个E......
  • 驱动开发:内核监控FileObject文件回调
    本篇文章与上一篇文章`《驱动开发:内核注册并监控对象回调》`所使用的方式是一样的都是使用`ObRegisterCallbacks`注册回调事件,只不过上一篇博文中`LyShar......
  • 使用Three.js 心得系列一 如何创建三维网格三、使用Three.js 心得系列三 Three.js 如
    一、使用Three.js心得系列一如何创建三维网格二、使用Three.js心得系列二如何改变三维场景的GlTF模型的位置三、使用Three.js心得系列三Three.js如何加载GlTF文件 ......
  • 文件路径问题( ./ 和 ../ 和 @/ )
    作为前端小白,最近在使用vue脚手架的时候,经常会遇到各种文件的引用。由于以前没有特别注意过这类问题,这次就写个文档给自己参考“./”指的是同级文件,后面可以跟同一文......
  • 任意文件下载漏洞
    任意文件下载漏洞概述网站由于业务需求,提供文件查看或下载功能,如果对用户查看或下载的文件不做限制,恶意用户就能够查看或下载任意文件,任意文件类型包含源代码文件、敏感......