Windows与Linux下objcopy生成二进制输出的行为差异问题
Mingw GCC与Ubuntu GCC生成二进制转储差异的原因
核心差异根源
目标文件格式不同
Ubuntu下GCC生成ELF格式的可重定位目标文件,而Windows Mingw GCC生成PE格式目标文件,objcopy对这两种格式的节(Section)处理逻辑存在本质区别。全局符号的节处理规则差异
- 在ELF格式中,全局数组
arr默认被放入.data节,即便没有被其他代码引用,gcc -r生成的可重定位目标文件也会保留这个节。objcopy -S -X -O binary会将所有已分配的可加载节(包括.data)转换为二进制内容,所以能看到数组的数值。 - 在PE格式中,未被引用的全局变量默认会被放入COMDAT协作节,这类节的特性是:如果没有被外部引用,编译器/链接器会默认将其丢弃。
gcc -r生成的可重定位目标文件里,未被引用的arr所在的COMDAT节不会被标记为“必须保留”,objcopy处理时就会忽略它,仅保留编译器默认的标识信息。
- 在ELF格式中,全局数组
解决方法
- 强制编译器保留数组所在的节:给数组添加
__attribute__((used))属性,告诉编译器无论是否被引用都要保留这个符号和对应节:unsigned char arr[4] __attribute__((used)) = {1,2,3,77}; - 或者编译时通过链接选项强制保留符号:在编译命令中加入
-Wl,--undefined=arr,让链接器认为arr被外部引用,从而保留对应的节:gcc -r -Wl,--undefined=arr hello.c -o hello.o
内容的提问来源于stack exchange,提问作者Sterpu Mihai
相关产品推荐
相关产品推荐

