c - 引用外部全局变量惨遭失败

标签 c gcc linker binary ld

我试图在链接时将二进制文件 B 嵌入到可执行文件 A 中,在 Linux(64 位)上。

B 是一个简单的文本文件...

您好,我是纯 ASCII 文本文件。

...使用 ld -r -bbinary -oB.o B 将其转换为可重定位对象。它的 symtab 报告了三个全局变量,它们的名称是不言自明的:

  1. _binary_B_start
  2. _binary_B_end
  3. _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/

相关文章:

将字符值转换为整数值

c++ - C 执行期间记录错误

c++ - 在 C++03 中的未评估上下文中使用表示非静态数据成员的 id 表达式是否有效

c++ - 指针链接器错误

ubuntu - 如何解决 Ubuntu 中的链接错误?

C _ 求和函数没有给出期望的结果

c - 启动内核时共享内存和流

c - 我没有得到此代码的输出(反转字符串)。谁能告诉我为什么?

c - OpenCL 中的奇怪段错误

c - 使用结构变量时出现链接器错误