gpt4 book ai didi

point - 为什么ELF执行入口点虚拟地址的形式是0x80xxxxxx而不是0x0?

转载 作者:行者123 更新时间:2023-12-03 12:30:25 25 4
gpt4 key购买 nike

执行时,程序将从虚拟地址 0x80482c0 开始运行。这个地址不指向我们的main()过程,而是一个名为 _start 的过程这是由链接器创建的。

到目前为止,我的谷歌研究只是让我做出了一些(模糊的)历史推测,比如:

There is folklore that 0x08048000 once was STACK_TOP (that is, the stack grew downwards from near 0x08048000 towards 0) on a port of *NIX to i386 that was promulgated by a group from Santa Cruz, California. This was when 128MB of RAM was expensive, and 4GB of RAM was unthinkable.



任何人都可以确认/否认这一点吗?

最佳答案

正如 Mads 指出的那样,为了通过空指针捕获大多数访问,类 Unix 系统倾向于使地址为零的页面“未映射”。因此,访问会立即触发 CPU 异常,即段错误。这比让应用程序流氓要好得多。然而,异常向量表可以在任何地址,至少在 x86 处理器上是这样(有一个特殊的寄存器,加载 lidt 操作码)。
起始地址是一组描述内存布局方式的约定的一部分。链接器在生成可执行二进制文件时,必须知道这些约定,因此它们不太可能改变。基本上,对于 Linux,内存布局约定是从 90 年代初的 Linux 的第一个版本继承而来的。一个进程必须能够访问多个区域:

  • 代码必须在包含起点的范围内。
  • 一定有栈。
  • 必须有一个堆,其限制随着 brk() 的增加而增加。和 sbrk()系统调用。
  • mmap() 必须有一些空间系统调用,包括共享库加载。

  • 如今,堆,其中 malloc()去,由 mmap() 支持在内核认为合适的任何地址获取内存块的调用。但在过去,Linux 就像以前的类 Unix 系统一样,它的堆在一个不间断的 block 中需要一个很大的区域,这可能会随着地址的增加而增长。因此,无论约定是什么,它都必须将代码和堆栈填充到低地址,并将给定点之后的地址空间的每一 block 都分配给堆。
    但也有堆栈,它通常很小,但在某些情况下可能会显着增长。堆栈向下增长,当堆栈已满时,我们真的希望进程可以预见地崩溃,而不是覆盖某些数据。所以堆栈必须有一个广阔的区域,在该区域的低端,一个未映射的页面。瞧!在地址 0 处有一个未映射的页面,用于捕获空指针取消引用。因此,定义堆栈将获得前 128 MB 的地址空间,但第一页除外。这意味着代码必须在这 128 MB 之后,位于类似于 0x080xxxxx 的地址处。
    正如迈克尔指出的那样,“丢失” 128 MB 的地址空间没什么大不了的,因为地址空间对于实际使用的内容来说非常大。当时,Linux内核将单个进程的地址空间限制为1 GB,超过硬件允许的最大4 GB,这被认为不是什么大问题。

    关于point - 为什么ELF执行入口点虚拟地址的形式是0x80xxxxxx而不是0x0?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2187484/

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