为什么链接的二进制文件大小符号不能正常工作?

问题描述 投票:0回答:2

我使用'ld -r -b binary -o binary.o foo.jpeg'将资源嵌入到我的程序中。工作得很棒。我只是想知道为什么int _binary_size符号永远不会正确读取,负数或太大的数字,但在程序运行之间保持不变。我总是要做_binary_end - _binary_start,它完美无瑕。它似乎对任何人都没有... like here ....为什么会这样?

没有理由不使用end-start,因为它取代了size符号,但它仍然让我很好奇。

编辑:代码示例。

extern const unsigned char _binary_scna4_jpg_start;
extern const unsigned char _binary_scna4_jpg_end;
extern const int _binary_scna4_jpg_size;

int size = &_binary_scna4_jpg_end - &_binary_scna4_jpg_start;
printf("Size is %d vs %d \n", size, _binary_scna4_jpg_size);

这打印:

Size is 1192071 vs -385906356 

第一个数字是二进制文件的正确大小,我的所有图像都完美无缺。

输出nm以获得良好的衡量标准:

0000000000123087 D _binary_scna4_jpg_end
0000000000123087 A _binary_scna4_jpg_size
0000000000000000 D _binary_scna4_jpg_start
c gcc ld
2个回答
1
投票

问题出现是因为Position-Independent Executables(PIE)。早期的可执行文件被加载到相同的内存地址(在编译/链接时确定),这导致可能的攻击,因为攻击者知道程序的特定部分在哪个地址。因此Address Space Layout Randomization得以实施。这有副作用,即大小符号被定义为绝对地址(_binary_scna4_jpg_size不是整数值,它是一个“指针”,就像_start和_end)在加载时也会重新定位。

如果使用选项-no-pie编译代码,则可以禁用位置独立性,_binary_scna4_jpg_size将输出正确的值,因为它不会被重定位。由于PIE默认处于启用状态,因此指针的值基本上是垃圾。如果您知道重定位内存的开始,也可以使用它,但由于您已经拥有_binary_scna4_jpg_start_binary_scna4_jpg_end,因此使用它们也是一样的。


0
投票

你的_binary_scna4_jpg_size符号不是整数。这是一个绝对的地址符号。为了获得大小,您需要获取它的地址并转换为适当的整数类型:

printf("The real size is %td\n", (ptrdiff_t) &_binary_scna4_jpg_size);

但这仅在禁用PIE(gcc -fPIC -no-pie)或静态链接(gcc -static)时有效。

© www.soinside.com 2019 - 2024. All rights reserved.