引用外部全局变量失败了

时间:2016-10-20 06:51:31

标签: c gcc linker binary ld

我试图在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
  4. 这是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

    我做错了什么?

1 个答案:

答案 0 :(得分:2)

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