加载时间重定位和虚拟内存 [英] load time relocation and virtual memory

查看:136
本文介绍了加载时间重定位和虚拟内存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道在具有虚拟内存支持的系统上加载时重定位实际上意味着什么.我想在具有虚拟内存的系统中,每个可执行文件的地址都将从零开始,并且在运行时这些地址将被转换为使用页表的物理地址,因此可执行文件可以在内存中的任何位置加载而无需任何重定位.但是,这篇关于共享库的文章提到,链接器在可执行文件中指定了要加载可执行文件的地址(入口点地址).

I am wondering what load-time relocation actually means on a system with virtual memory support.I was thinking that in a system with virtual memory every executable will have addresses starting from zero and at run-time the addresses will be translated into physical addresses using page tables.Therefore the executable can be loaded anywhere in memory without the need of any relocation. However this article on shared libraries mentions that linker specifies an address in the executable where the executable is to be loaded (Entry-point address).

http://eli.thegreenplace .net/2011/08/25/load-time-relocation-of-shared-libraries/

也有很多关于动态链接的文章,它们讨论了绝对地址. 我的理解错了吗?

Also there are many articles on dynamic linking which talk about absolute addresses. Is my understanding wrong ?

推荐答案

加载时重定位和虚拟内存支持是两个不同的概念.如今,几乎所有的CPU和OS都具有虚拟内存支持.了解虚拟内存的唯一真正重要的一点是:忘记物理地址.现在这是硬件和操作系统的责任,除非您正在编写分页系统,否则您可以忽略物理地址.程序使用的所有地址都是虚拟地址.这是一个巨大的优势,极大地简化了编程模型.在32位系统上,这仅表示每个进程都有自己的4 GiB内存空间,范围从0x000000000xffffffff.

Load-time relocation and virtual memory support are two different concepts. Almost all CPUs and OSes these days have virtual memory support. The only really important point to understand about virtual memory is this: forget physical addresses. That is now a hardware and OS responsibility and, unless you are writing a paging system, you can forget about physical addresses. All addresses that a program uses are virtual addresses. This is a huge advantage and immensely simplifies the programming model. On 32-bit systems, this simply means that each process gets its own 4 GiB memory space, ranging from 0x00000000 to 0xffffffff.

.exe代表一个进程.链接器从.obj文件生成.exe.虽然两个都是二进制文件,但.obj文件不能执行,因为它们不包含所有变量和函数的地址.链接器的工作是提供这些地址,该地址的确定是通过端对端放置这些.obj文件,然后计算所有符号(函数和变量)的确切地址来进行的.因此,创建的.exe具有硬编码"的函数和变量的每个地址.但是,在创建.exe之前仍然需要一个关键信息.链接器必须具有内部知识,以了解.exe在内存中的加载位置.它是在地址0x00000000还是在0xffff0000还是其他地方?例如,在Windows中,所有.exe总是以绝对起始地址0x00400000加载.这称为基地址.当链接器生成符号的最终地址(函数和变量)时,它将从该地址开始计算这些地址.

An .exe represents a process. A linker produces .exe from .obj files. While both are binary files, .obj files are not executable because they do not contain the addresses of all the variables and functions. It is the job of the linker to provide these addresses, which it determines by placing these .obj files end-to-end and then computing the exact addresses of all the symbols (functions and variables). Thus, the .exe that is created has every address of functions and variables "hard-coded" into it. But there is still one critical information needed before the .exe can be created. The linker has to have insider knowledge about where in memory the .exe will be loaded. Will it be at address 0x00000000, or at 0xffff0000, or somewhere else? For example, in Windows all .exes are always loaded at an absolute starting address of 0x00400000. This is called the base address. When the linker generates the final addresses of symbols (functions and variables), it computes those from this address onward.

现在,.exe几乎不需要加载到任何其他地址.但是对于.dll来说并非如此. .ddl.exe相同(两者均以可移植可执行(PE)文件格式格式化,它描述了内存布局,例如,文本在哪里,数据在哪里以及如何查找哪一个) . .dll也有一个首选地址.这仅表示链接器在计算.dll内部符号的地址时将使用此值.如果.dll加载到该地址,则表示我们已经准备就绪.

Now, .exes rarely need to be loaded at any other address. But the same is not true for .dlls. .ddls are the same as .exes (both are formatted in the portable executable (PE) file format, which describes the memory layout, for example, where text goes, where data goes, and how to find which one). .dlls have a preferred address, too. This simply means that the linker uses this value when it computes the addresses for symbols inside the .dll. If the .dll is loaded at this address, then we are all set.

但是如果由于已经在该地址加载了其他.dll而无法在该地址加载.dll(例如,它是0x10000000),则加载器将在内存中找到其他空间并加载.dll在那里.但是,.dll中的函数和符号的全局地址现在不正确.因此,加载程序必须进行重定位(也称为修复"),在该过程中,加载程序将调整所有全局符号和函数的地址以反映其实际地址.

But if the .dll cannot be loaded at this address (say it was 0x10000000) because some other .dll had already been loaded at this address, then the loader will find some other space in memory and load the .dll there. However, the global addresses of functions and symbols in the .dll are now incorrect. Thus, the loader has to do a relocation (also called "fixup"), in which it adjusts the addresses of all global symbols and functions to reflect their actual addresses.

为了进行此调整,加载程序需要能够在.dll中找到所有此类符号. PE文件有一个.reloc节,其中包含所有此类符号的内部偏移量.

In order to do this adjustment, the loader needs to be able to find all such symbols in the .dll. The PE file has a .reloc section that contains the internal offset of all such symbols.

当然,还有其他一些细节,例如,有关在编译器生成代码时如何使用间接的信息,这样,间接调用而不是直接调用,而是通过标头中的已知内存位置访问变量,而不是直接调用.exe.

Of course, there are other details, for example, regarding how indirection can be used when the compiler generated the code so that, instead of making direct calls, the calls are indirect and variables are accessed via known memory locations in the header of the .exe.

最后,要点是:当代码未加载到该位置(在4 GiB地址空间内)时,需要重定位(某种方式)以调整调用和跳转中的地址以及变量访问指令.预计会加载.当操作系统加载.exe时,它必须在这4 GiB地址空间中选择一个合适的位置,它将在磁盘上从该.exe复制代码和数据块.

Finally, the gist is this: You need relocation (of some sort) to adjust addresses in the call and jump as well as variable access instructions when the code does not load at the position (within the 4 GiB address space) it was expected to load. When the OS loads a .exe, it has to pick a suitable place in this 4 GiB address space where it will copy the code and data chunks from this .exe on disk.

这篇关于加载时间重定位和虚拟内存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆