编译时的加载地址是在RAM中复制可执行文件的地方吗?

我正在尝试编写自己的装载机。 在这个程序中,我将程序复制到RAM中的特定地址,并通过读取精灵的入口点跳转到入口点地址。 但是,我无法理解装载程序地址是什么? 这是否意味着只需要在编译时指定的加载器地址复制二进制文件。 我不能在其他位置加载程序而不是在编译时指定的加载地址? 我的基本问题是:“我不能在其他位置加载程序而不是在编译时指定的加载地址吗?”

正是。

完全链接的ELF程序不包含重定位信息,这些信息允许您在将程序加载到不同的地址后修复引用。

使用链接器的-Ur选项(或适当的链接描述文件),可以生成带有重定位的ELF文件 – 为这些编写加载器更加困难。

您是否以任何机会瞄准ARM?

您的问题的解决方案是PIC / PIE(位置无关代码/可执行文件)。 这样,程序编译如下:

  • 任何函数内跳转都是相对的(如ifs,case,loops等)
  • 任何段内跳转都是使用GOT(全局偏移表)两步间接进行的
  • 截面间跳转是相对的或间接的,取决于链接器参数“long-jumps”
  • 任何全局数据访问都是使用GOT间接进行的

这样,程序在代码中的任何地方都不包含绝对地址。 它在代码中也没有重定位。 唯一需要的搬迁是GOT本身的放置。

GOT是一个包含所有全局对象,函数和数据的地址的表。 在非PIC代码中,数据的绝对地址直接嵌入代码中。 该函数需要知道GOT表地址和GOT表中与特定对象相对应的条目号。 对象编号是PIC代码中唯一嵌入的内容。 GOT地址通过我遇到的两种方式之一呈现给函数:附加在函数体末端或预定义CPU寄存器中的重定位。 我发现后一种选择更好。

如果您的程序最初加载了内存映射ROM,并且您希望将其复制到RAM以使事情更快并允许修改数据,则PIC非常有用。

请注意,您可以在没有PIC的情况下完成上述所有操作,这更麻烦。 您将在代码中进行大量重定位(如果PIC移动函数代码只是一个简单的memcpy),您必须立即复制所有数据块(正确编写的PIC可执行文件允许移动不同的单个对象)记忆区域)。

如果您很好奇,那么我可以向您发送一些用于ARM体系结构的链接描述文件。

您需要了解ELF文件格式,这有点复杂。 您可以在维基百科上找到并概述。

以下SOpost可能是相关的:

  • 如何在没有任何符号信息的情况下找到elf可执行文件的主要function入口点?
  • ELF可执行文件的起点?
  • 为什么ELF执行入口点虚拟地址为0x80xxxxx而不是0x0?