我正在寻找一种正确的方法来为以下架构创建固件组件,而无需发明轮子。 考虑到系统有多个固件可执行文件,它们可以动态加载,也可以通过将控制权传递给彼此来按顺序执行。并且有一个通用功能,它静态加载到已知的内存地址中,并且可由每个可执行固件组件调用:
|-------------------|
| Executable 1 |
|-------------------|
| ... |
|-------------------|
| Executable 2 |
|-------------------|
| ... |
|-------------------| <--- fixed address
| Shared "library" |
|-------------------|
我希望能够通过将其代码与“库”的构建过程生成的一些工件链接来创建可执行文件,就像:
ld <some options and input objects> --just-symbols=library.syms executable.elf
(库工件和可执行文件稍后都将被展平为原始二进制文件,但这一步是隐含的,对于问题而言并不重要)。
现在的问题是如何实际构建这个库并知道它的最终存储位置?传统的静态库通常与可执行文件链接,并根据其链接描述文件放置。我看到的一种方法是实际生成另一个带有虚拟
main
函数和特定链接器脚本的(elf)可执行文件,并将其用作问题中的“库”,但对我来说,它看起来有点黑客风格。此外,我不确定它是否安全,并且没有优化预期导出的功能。
** 假设 GNU 交叉工具链和处置中的任何 binutils
这是通过“链接器脚本”完成的。 https://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_chapter/ld_3.html
作为一个非常原始的例子,你可以这样做:
SECTIONS {
SecA 0x10000 : {
foo.o (.text)
bar.o (.text)
}
SecB : { * (.text) }
.data : { *(.data) }
}
这会将目标文件
foo.o
中的所有函数放在指定的绝对地址处。一旦对象 foo.o
完成,来自 bar.o
的函数将是第二个。
来自所有其他对象的函数,不考虑对对象文件进行排序,将在后面。
最后你会有一个单独的全局变量部分。
请注意,您无法指定功能的位置。如果一个对象中有两个或多个函数 - 它们将作为一批放入最终输出中。但您可以采用“一个文件=一个函数”的方法。至少对于需要绝对放置的功能来说是这样。