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

标签 c gcc ld

我使用“ld -r -b binary -o binary.o foo.jpeg”将资源嵌入到我的程序中。效果非常棒。我只是想知道为什么 int _binary_size 符号永远不会正确读取、负数或太大的数字,但在程序运行之间保持不变。 我总是必须执行 _binary_end - _binary_start,这可以完美地工作。看来它对任何人都不起作用... like here ....这是为什么?

没有理由不使用结束开始,因为它取代了大小符号,但它仍然让我好奇。

编辑:代码示例。

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

最佳答案

出现此问题的原因是 Position-Independent Executables (馅饼)。早期的可执行文件被加载到相同的内存地址(在编译/链接时确定),这导致可能的攻击,因为攻击者知道程序的特定部分位于哪个地址。因此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,所以使用它们是一样的。

关于c - 为什么链接的二进制文件的 _size 符号不能正常工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54844677/

相关文章:

c - 打印整数和字符的总和*

c - 通过 SunRPC 发送带缓冲区的链表 (c)

linux - 在没有 root 的非标准位置使用 glibc 构建 GCC

c++ - 无借位快速减法

ios - ld:架构 armv7 Xcode 项目的 xx 重复符号

c - 在不平衡树上拆分 OpenMP 线程

c - 嵌套结构分配内存

c - 使用 GDB 调试 va_list args

android - 在 elf 中重写链接表

c - 在C中访问链接脚本变量的“值”是否未定义行为?