1

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

4

3 回答 3

1

Precisely.

Fully linked ELF programs contain no relocation information which would allow you to fix up references after loading the program at a different address.

Using the -Ur option to the linker (or an appropriate linker script), you can generate an ELF file with relocations -- writing a loader for these is more difficult though.

于 2013-09-10T07:50:46.230 回答
1

您是否有机会瞄准 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 架构的链接器脚本。

于 2013-09-10T12:08:06.983 回答
0

You need to understand ELF file format which is a bit complicated. You can find and overview on Wikipedia.

Following SO posts may be relevant:

于 2013-09-10T07:51:35.977 回答