【发布时间】:2021-08-08 15:32:04
【问题描述】:
由于没有更好的术语,我想将一组函数编译成一个平面库。有很多函数,比如
// add.c
int add (int a, int b) {
return a + b;
}
// multiply.c
int multiply (int a, int b) {
int result = 0;
if (a >= 0)
for (; a > 0; --a) result = add(result, b);
else
for (; a < 0; ++a) result = add(result, b);
return result;
}
// double.c
int two = 2;
int double_ (int x) {
return multiply(x, two);
}
编译后的二进制文件应该有
- 没有
main或__start入口点(它是一个库,而不是可执行文件), - 只有指令和数据,没有标题,
- 与位置无关的代码,
- 没有外部依赖项(我没有使用任何外部库,但 GCC 似乎总是包含我不需要的标准库内容),并且
- 几乎没有填充(即没有过多的空字节用于页面/扇区对齐)
为了能够从二进制文件外部调用函数,我需要知道它们从二进制文件开头的偏移量,或在二进制文件的开头有一个跳转表。
使用 GCC 第 3 点和第 4 点可能可以通过 -fPIC 和 -nostdlib 来实现。如果这些函数彼此独立,我可以通过简单地单独编译文件并手动连接它们来实现 5. 这也会给我函数偏移量,但这里的函数不是相互独立的,所以我依靠 GCC用最小的填充将函数缝合在一起。对于第 2 点,可能有一些 objcopy --oformat binary 技巧或类似的东西。但我不知道如何让第 1 点起作用。到目前为止,我在网上找到的每一个指南都用于编译自定义/“hello world”内核,所有这些内核都是可执行文件并具有入口点。如果我不提供入口点ld 抱怨找不到符号__start。此外,我不知道如何获取已编译二进制文件的函数偏移量或如何告诉 GCC 包含一个跳转表(两者中的任何一个都可能)。
关于如何编译上面的示例以使编译的二进制文件满足点 1 到 5 并且可以从二进制文件外部调用(通过偏移量或通过开头的跳转表)有什么想法吗?
【问题讨论】:
标签: gcc