2020-09-30

Generate the same object file with a native compiler and a cross compiler

I'm trying to use a cross compiler running on Ubuntu to compile some Raspberry Pi code. I have already tested the executable and it works fine, but comparing that executable to the one generated by the native compiler (gcc on Raspberry Pi) I see there are some differences between the binary files.

Setup

The native compiler is gcc (Raspbian 8.3.0-6+rpi1) 8.3.0 running on Raspbian GNU/Linux 10 (buster). The cross compiler is arm-linux-gnueabihf-gcc-8 (Ubuntu/Linaro 8.4.0-1ubuntu1~18.04) 8.4.0 running on Ubuntu 18.04.4 (Bionic Beaver).

I tried to make sure that the cross compiler is using the same compilation flags as the one on the Pi uses by default:

  • marm to generate code that runs in ARM state (instead of Thumb)
  • march=armv6
  • mfpu=vfp
  • O0 and I turned off the optimizations to make sure nothing "funny" is going on

What I have tried

I wrote the most bare-bones C code I could think of:

int main() {}

And then compiled it into assembly using Unified Assembly Language syntax. Both compilers generated the exact same assembly (except for the .ident line, but that one doesn't matter):

    .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

I then tried something else: I just built the object file before linking it to any shared libraries, but even then there will be differences between the native and cross compiled files. Therefore, it's not an issue of the installed libraries being different between Raspbian and Ubuntu.

Problem

If I compile this assembly code using the native compiler and the cross compiler, I will get different executables even though they function the same way.

Question

Even though it's not a big deal since both executables work as expected (they do nothing and return 0) I would like to know:

  • Why does this happen?
  • Is it a matter of using slightly different versions of gcc (8.3.0 vs 8.4.0)?
  • Or are these differences inherent to the operating system that runs the compiler?
  • And is it possible to use a cross compiler to build the exact same executable as a native compiler would? Even when the code is very big and complex?


from Recent Questions - Stack Overflow https://ift.tt/349bZSZ
https://ift.tt/eA8V8J

No comments:

Post a Comment