将二进制blob与GCC链接时的奇怪行为

时间:2016-07-11 07:01:13

标签: c gcc linker ld

我将ARM Cortex-M的C程序中的二进制数据与GCC链接,如下所示:

arm-none-eabi-ld.exe -r -b binary -o html.o index.html

要处理数据,我有以下外部变量:

extern const unsigned char _binary_index_html_start;
extern const unsigned char _binary_index_html_end;
extern const uint32_t _binary_index_html_size;

static const char* html = &_binary_index_html_start;
static const size_t html_len = &_binary_index_html_size;

我不明白为什么我需要让_binary_index_html_size变量的地址具有大小值?

这意味着_binary_index_html_size变量的内存地址(指针)表示blob的大小值(以字节为单位)。当我调试它似乎是正确的,但对我来说,这似乎是一个非常奇怪的解决方案来解决这个问题。

修改
我猜这个的原因可能是:因为blob的大小永远不会大于本机数据大小(在我的情况下是2 ^ 32),而不是浪费空间并存储大小GCC只是创建一个指向内存地址,表示blob的大小。所以这个值是完全随机的,取决于其他代码(我测试了这个)。这似乎是一个聪明的事情,因为大小不占用空间并且指针在编译时被解析。因此,如果一个人不需要这个尺寸,就不会浪费空间 我想我会使用(&_binary_index_html_end) - (&_binary_index_html_start),这似乎更好,并得到所有编译器的支持。

1 个答案:

答案 0 :(得分:1)

您正在处理的所有符号都是链接器脚本定义的变量,它们的访问方式与您完全相同。 ld documentation中非常明确地给出了对此的解释。

  

当用C等高级语言声明符号时,两个   事情发生。首先是编译器保留足够的空间   程序的内存保存符号的值。第二是   编译器在程序的符号表中创建一个条目   持有符号的地址。即符号表包含地址   保存符号值的内存块。

然后,稍后在文档中,我们可以找到以下内容。

  相比之下,

链接器脚本符号声明会创建一个条目   符号表但不为它们分配任何内存。因此他们是   没有价值的地址。

这意味着链接器定义变量的地址确实是它的实际值,这就是为什么你必须采用这样的地址才能读取与链接符号相关的值。