18

我想生成一个可以加载到内存中的文件(例如使用mmap),然后跳转到该内存的开头以运行代码。

理想情况下,我希望选择使代码可重定位(这可能效率低下)或指定代码期望加载的显式地址(这很痛苦),但任何一个都可能单独工作.

4

2 回答 2

16

您可以这样做,但您需要检查目标文件格式。特别是,该objcopy命令可以将可执行文件转换为“平面”二进制文件(取决于您的目标平台)。也许是这样的:

gcc -o test test.c
objcopy -O binary test test.bin

有关更多详细信息,请参见man objcopy您的平台。

于 2010-09-01T06:35:14.113 回答
8

您想了解该实用程序objcopy,它通常与 GCC 一起提供。它是binutils工具包的一个组件,其中最明显的成员是链接器,ld.

这个过程是你编译你的源文件并像往常一样链接它们。这为您提供了 elf(或其他可重定位的依赖于平台的二进制文件)格式的完成的可执行文件。然后使用 objcopy 将可执行文件转换为平面二进制图像。

这对于准备要从 ROM 运行的代码非常有用,在这种情况下,您需要确保为您的目标平台使用合适的 C 运行时库,并且可能需要自定义链接器脚本文件以及提供您自己的 C 运行时启动代码。

如果您的目标是获取类似于 .so 文件的内容,并将其加载到现有进程中,请注意共享库加载器的一些工作是实际完成链接,以便 .so 中的符号引用主可执行文件(或其他 .so 文件)中地址的文件在加载时得到解析。使用 objcopy 不会这样做,因此以这种方式加载的函数可能很难正确使用现有的 C 运行时库和它维护的对象,例如打开的文件。

无论您的目标是什么,您都需要控制链接器,以便将二进制文件定位到已知地址。为此,您需要制作一个链接描述文件。脚本语言的文档在binutils 手册中。您将主要对“.text*”部分感兴趣,如果您计划有任何已初始化的全局变量,则可能对“.rodata*”部分感兴趣。实际安排初始化留给读者练习。

总的来说,这只是一个非常大的冰山一角。我建议花一些时间来构建交叉编译器,看看这些东西在实践中是如何使用的。AVR 和 MSP430 社区使用 GCC,积极参与,并以廉价(通常甚至是开源)硬件开始。

于 2010-09-01T06:40:00.570 回答