【问题标题】:Questions about loading executables into memory关于将可执行文件加载到内存中的问题
【发布时间】:2014-01-08 01:15:41
【问题描述】:

所以我在虚拟机上使用 linux 0.11 内核,我需要编写一个程序来分析在该内核上运行的可执行文件。文件格式为 a.out。我想知道的是,操作系统如何决定在(虚拟?)内存中加载文件的位置?它是由所谓的“基地址”决定的吗?如果是这样,我怎么在 a.out 标头中找不到任何提及它的内容?

//where is base address?
struct exec {
  unsigned long a_magic;    /* Use macros N_MAGIC, etc for access */
  unsigned a_text;          /* length of text, in bytes */
  unsigned a_data;          /* length of data, in bytes */
  unsigned a_bss;           /* length of uninitialized data area for file, in bytes */
  unsigned a_syms;          /* length of symbol table data in file, in bytes */
  unsigned a_entry;         /* start address */
  unsigned a_trsize;        /* length of relocation info for text, in bytes */
  unsigned a_drsize;        /* length of relocation info for data, in bytes */
};

我尝试查找有关格式的文档,但我找到的唯一信息只是解释了这些字段中的每一个是什么,a_magic 可以具有哪些值等。

我需要知道它,因为程序需要在给定可执行文件中指令的内存地址时打印出文件和行号,并且调试符号仅将其地址作为偏移量(例如,相对于文本部分等)。

另外,出于好奇,我知道在 C 中,“(void*)0”是 NULL,您不能取消引用。那么如何获取内存地址 0 的内容呢?

如您所见,我对linux内核和操作系统的一般知识知之甚少,所以请从基础开始...

感谢您提供的任何帮助,谢谢。

【问题讨论】:

标签: c linux


【解决方案1】:

基地址是a_entry 字段。

另外,出于好奇,我知道在 C 中,“(void*)0”是 NULL,您不能取消引用。那么如何获取内存地址 0 的内容呢?

任何将 C 程序可用内存置于地址 0 的系统都必须以某种方式使其工作。虽然人们可以想象可能的方法来做到这一点,但我不知道有谁会打扰。出于所有意图和目的,虚拟地址零从未使用过。

【讨论】:

  • 那么如何从进程内存中的指令地址获取偏移地址呢?
  • 内存地址减去基地址。但我强烈建议使用实际映射而不是标题。 (在linux上,你可以从/proc/<pid>/maps读取映射。)
  • 你能告诉我们更多关于文件的作用,它与问题的关系,以及为什么读取 a.out 标头不是那么好吗?谢谢
  • 该文件告诉你正在运行的进程有哪些映射。它与问题有关,因为这正是您想要找出的——进程如何映射可执行文件。读取a.out 标头不是很好,因为它不能告诉您链接器/加载器实际做了什么,只能告诉您可执行文件要求它做什么。
【解决方案2】:

操作系统可以在它选择的任何位置加载应用程序,然后将嵌入的地址重新定位到相对于该点的位置。此重定位信息记录在a.out 文件中。基地址取决于架构和其他细节,通常不为零。

如果您查看链接器映射文件,您应该会看到一个符号,该符号要么位于内存映像的开头,要么位于与其固定的偏移处。在运行时,从您记录的用于调试的实际地址中减去该值,以获得您感兴趣的位置的相对地址。

请注意,如果您的链接描述文件去除了符号,则可执行文件中不会出现这些符号。

【讨论】:

  • 重定位是否也与可执行文件(已链接)相关?我如何从可执行文件中获取您提到的信息?
  • a.out 格式是一种混合格式,可以根据需要重新链接(参见手册页参考),并且它可以选择包含符号。
【解决方案3】:

另外,出于好奇,我知道在 C 中,“(void*)0”是 NULL,您不能取消引用。那么如何获取内存地址 0 的内容呢?

其实你可以取消引用NULL,但是结果没有定义。为方便起见,大多数操作系统都会捕获访问权限以帮助您调试指针问题。

此外,进程空间中地址为 0 的内存位置与“硬件空间”中地址为 0 的内存位置不同。 CPU 和操作系统中的“分页”支持将物理内存与虚拟内存“解耦”。虚拟页面可能会映射到地址 0,尽管您通常有中断向量和其他特殊设备内存,而不是真正的 RAM。

【讨论】:

    猜你喜欢
    • 2016-03-09
    • 2015-10-10
    • 1970-01-01
    • 2011-03-11
    • 2013-12-14
    • 1970-01-01
    • 2015-10-16
    • 2022-01-18
    • 2018-01-18
    相关资源
    最近更新 更多