我正在尝试使用在Ubuntu上运行的交叉编译器来编译一些Raspberry Pi代码。我已经测试了可执行文件,并且可以正常工作,但是将该可执行文件与本机编译器(Raspberry Pi上的gcc)生成的可执行文件进行比较,我发现二进制文件之间存在一些差异。
本机编译器gcc (Raspbian 8.3.0-6+rpi1) 8.3.0
在Raspbian GNU / Linux 10(破坏程序)上运行。交叉编译器是arm-linux-gnueabihf-gcc-8 (Ubuntu/Linaro 8.4.0-1ubuntu1~18.04) 8.4.0
,可在Ubuntu 18.04.4(Bionic Beaver)上运行。
我试图确保交叉编译器使用与Pi默认使用的相同的编译标志:
marm
生成以ARM状态(而不是Thumb)运行的代码march=armv6
mfpu=vfp
O0
,我关闭了优化功能以确保没有“有趣”的事情发生我写了我能想到的最基本的C代码:
int main() {}
,然后使用统一汇编语言语法将其编译为汇编。两种编译器都生成完全相同的程序集(.ident
行除外,但是那无关紧要):
.arch armv6
.eabi_attribute 28, 1
.eabi_attribute 20, 1
.eabi_attribute 21, 1
.eabi_attribute 23, 3
.eabi_attribute 24, 1
.eabi_attribute 25, 1
.eabi_attribute 26, 2
.eabi_attribute 30, 6
.eabi_attribute 34, 1
.eabi_attribute 18, 4
.file "main.c"
.text
.align 2
.global main
.arch armv6
.syntax unified
.arm
.fpu vfp
.type main, %function
main:
@ args = 0, pretend = 0, frame = 0
@ frame_needed = 1, uses_anonymous_args = 0
@ link register save eliminated.
str fp, [sp, #-4]!
add fp, sp, #0
mov r3, #0
mov r0, r3
add sp, fp, #0
@ sp needed
ldr fp, [sp], #4
bx lr
.size main, .-main
.ident "GCC: (Ubuntu/Linaro 8.4.0-1ubuntu1~18.04) 8.4.0"
.section .note.GNU-stack,"",%progbits
然后我尝试了其他方法:在将目标文件链接到任何共享库之前,我只是构建了目标文件,但是即使那样,本机文件和交叉编译的文件之间也会存在差异。因此,这不是Raspbian和Ubuntu之间安装的库不同的问题。
如果我使用本机编译器和交叉编译器编译此汇编代码,即使它们以相同的方式运行,我也将获得不同的可执行文件。
尽管这没什么大不了,因为两个可执行文件都能按预期工作(它们什么也不做,返回0),我想知道:
答案 0 :(得分:1)
链接器可以在二进制文件中添加“内部版本ID”。造成虚假的“差异”。
尝试使用 -Wl,--build-id=none
进行编译。
还有.comment
部分,其中包含有关编译器版本和运行平台的信息。之后,您可以使用 strip -R .comment your_binary
剥离它。
除了使用临时linker script(可能不实际)之外,我不知道有什么方法可以让gcc不创建该.comment
部分:
SECTIONS { /DISCARD/ : { *(.comment) } } INSERT BEFORE .bss
愚蠢的例子:
cc -Wall -o no_comment \
-include stdio.h -xc - <<<'int main(){printf("test\n");}' \
-xnone -Wl,-T /dev/fd/7 /dev/fd/7 7<<<'SECTIONS { /DISCARD/ : { *(.comment) } } INSERT BEFORE .bss' \
-Wl,--build-id=none
答案 1 :(得分:1)
是的,@ user414777是正确的。
还有
.ident
行,但没关系
...实际上以二进制结尾:
尝试readelf -p .comment a.out