我试图在链接时将二进制文件 B
嵌入到可执行文件 A
中,在 Linux(64 位)上。
B
是一个简单的文本文件...
您好,我是纯 ASCII 文本文件。
...使用 ld -r -bbinary -oB.o B
将其转换为可重定位对象。它的 symtab
报告了三个全局变量,它们的名称是不言自明的:
_binary_B_start
_binary_B_end
_binary_B_size
这是A.c
...
#include <stdio.h>
extern const size_t _binary_B_size;
int main(int argc, char * * argv)
{
printf("size: %zu\n", _binary_B_size);
return 0;
}
...用 B.o
编译和链接:gcc -oA A.c B.o
。
不幸的是,一旦可执行文件 A
尝试访问 _binary_B_size
,它就会突然终止并收到 SIGSEGV
。
我做错了什么?
最佳答案
显然您误解了 _binary_B_size
的语义。它不是 size_t
左值,正如您似乎相信的那样。它是一个零大小的绝对定位部分(一个标签),其地址等于二进制 blob 数据的大小。在您的文件上尝试 objdump -t
,您将在相应的列中看到 *ABS*
。
所以正确的用法是
extern unsigned char _binary_B_size[];
int main()
{
printf("size: %zu\n", (size_t) _binary_B_size);
}
你也可以使用end - start
方法得到同样的结果
extern unsigned char _binary_B_start[];
extern unsigned char _binary_B_end[];
int main()
{
printf("size: %zu\n", (size_t) (_binary_B_end - _binary_B_start));
}
基本上,这里的主要考虑是 _binary_B_size
没有理由成为 size_t
左值。它实际上是一个常量,其值在编译时预先确定。它没有理由占用存储空间。您在上面看到的是一种在目标文件中对此类常量值进行编码的方法。
关于c - 引用外部全局变量惨遭失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40147367/