gpt4 book ai didi

c - 链接器如何生成最终的虚拟内存地址?

转载 作者:行者123 更新时间:2023-12-04 08:10:40 25 4
gpt4 key购买 nike

假设这个简单的代码:

int main(){return 0;}
使用 objdump我们可以看到内存地址:
0000000100003fa0 _main:
100003fa0: 55 pushq %rbp
100003fa1: 48 89 e5 movq %rsp, %rbp
100003fa4: 31 c0 xorl %eax, %eax
100003fa6: c7 45 fc 00 00 00 00 movl $0, -4(%rbp)
100003fad: 5d popq %rbp
100003fae: c3 retq
我知道 0x100003fa0 (例如)是一个虚拟内存地址。
加载我的程序时,操作系统会将其映射到物理内存。
2个问题:
1- main 的初始地址可以是随机的吗?因为它们是虚拟的,我猜它可能是
任何值(value),因为虚拟内存会照顾其余的?即我可以从字面上开始 0x1 (不是 0x0,因为它保留为 null)?
2-链接器如何得出初始地址? (同样是起始地址是随机的吗?)

最佳答案

Can the initial address of main be random? as they are virtual I'm guessing it can be any value as the virtual memory will take care of the rest? i.e I can start literally from 0x1 (not 0x0 as it's reserved for null)?


内存是虚拟的并不意味着所有的虚拟地址空间都是你可以随意使用的。在大多数操作系统上,可执行模块(程序和库)需要使用地址空间的子集,否则加载器将拒绝加载它们。当然,这高度依赖于平台。
所以地址可以是任何你想要的,只要它在平台特定的范围内。我怀疑任何平台都会允许 0x1,不仅仅是因为某些平台需要将代码对齐到大于一个字节的东西。
此外,在许多平台上,地址只是提示:如果它们可以按原样使用,则加载程序不必重新定位二进制文​​件中的给定部分。否则,它会将其移动到可用的地址空间 block 中。这是相当普遍的,例如在 Windows 上,32 位二进制文​​件(例如 DLL)具有基地址:如果可用,加载程序可以更快地加载二进制文件。因此,在“初始地址”为 0x1 的假设情况下,假设对齐不是问题,地址最终会被移动到地址空间中的其他位置。
还值得注意的是,“初始地址”是一个不明确的术语。可执行文件启动时加载的二进制模块由类似于部分的内容组成。每个部分都有自己的基地址,并且可能还有内部(相对)地址或列表中的地址引用。此外,一个或多个可执行部分也将有一个“入口”地址。加载程序将使用这些地址来执行初始化代码(例如 Windows 上的 DllMain 概念) - 该代码总是快速返回。最终,没有其他依赖的部分之一将有一个适当命名的入口点,并将成为您编写的“实际”程序 - 一个将继续运行并仅在程序退出时返回。此时控制可能会返回到加载程序,加载程序会注意到没有其他内容要执行,并且进程将被拆除。所有这些的细节都高度依赖于平台——我只是给出一个高级别的概述,它并不是在任何特定平台上都以这种方式完成的。

How does the linker come up with the initial address? (again is the starting address random?)


链接器不知道自己要做什么。当您链接您的程序时,链接器会收到平台本身附带的更多文件。这些文件是使代码能够启动所需的链接器脚本和各种静态库。链接器脚本为链接器提供了它可以分配地址的约束。所以这又是高度特定于平台的。链接器可以以完全确定的方式分配地址,即。相同的输入总是产生相同的输出,或者可以告诉它随机分配某些类型的地址(当然以不重叠的方式)。这就是所谓的 ASLR(地址空间随机化)。

关于c - 链接器如何生成最终的虚拟内存地址?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65983756/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com