有关将可执行文件加载到内存的问题

时间:2014-01-08 01:15:42

标签: c linux

所以我在虚拟机上使用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内核和操作系统的了解很少,所以请从基础知识开始......

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

3 个答案:

答案 0 :(得分:1)

基地址是a_entry字段。

  

另外,出于好奇,我知道在C中,“(void *)0”是NULL,你不能解除引用。那你怎么会得到内存地址0的内容?

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

答案 1 :(得分:0)

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

如果查看链接器映射文件,您应该看到一个符号,该符号位于内存映像的开头,或者与它有固定的偏移量。在运行时,从您为调试注意到的实际地址中减去此值,以获得您感兴趣的位置的相对地址。

请注意,如果链接描述文件剥离符号,则符号将不会出现在可执行文件中。

答案 2 :(得分:0)

  

另外,出于好奇,我知道在C中,“(void *)0”是NULL,你不能解除引用。那你怎么会得到内存地址0的内容?

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

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