【问题标题】:Referencing external global variables fails miserably引用外部全局变量惨遭失败
【发布时间】:2016-10-20 06:51:31
【问题描述】:

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

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

Hi, I'm a text file in plain 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 终止。

我做错了什么?

【问题讨论】:

    标签: c gcc linker binary ld


    【解决方案1】:

    显然你误解了_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 左值。它实际上是一个常量,其值在编译时预先确定。它没有理由占用存储空间。您在上面看到的是在目标文件中编码此类常量值的一种方法。

    【讨论】:

      猜你喜欢
      • 2018-04-25
      • 1970-01-01
      • 2017-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多