Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Trying to run a cross-compiled executable on target device fails with: No such file or directory

I've got caught in the not-so-sunny world of cross-compilation.

I'm trying to compile a simple hello world application for my BeagleBone Black (which runs a TI Cortex-A8 processor).

First of all, I compiled and ran successfully the hello world application on x86 with gcc

Then I changed my compilation settings to the following:

arm-linux-gnueabi-gcc -c -O0 -g3 -Wall main.c -o bin/obj/main.o
arm-linux-gnueabi-gcc bin/obj/main.o -o bin/hello_world

I transferred the file via SCP to the BeagleBone, and set executable permissions with chmod +x hello_world

Upon running it (./hello_world), my only response is:

-bash: ./hello_world: No such file or directory

The output of file matches that of /sbin/init as I would expect:

$ file hello_world
hello_world: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, BuildID[sha1]=0x24b659b7a41fe043a6f4649d4ebfb5e692ebf0c7, not stripped
$ file /sbin/init
/sbin/init: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.26, BuildID[sha1]=0xd21f6957ec031a27d567b3d5e6aa14b9e0c30c37, stripped

The result of ldd is:

$ ldd hello_world
    not a dynamic executable

I tried adding a suitable platform and CPU type, changing my compilation to:

arm-linux-gnueabi-gcc -c -O0 -g3 -Wall -march=armv7-a -mtune=cortex-a8  main.c -o bin/obj/main.o
arm-linux-gnueabi-gcc bin/obj/main.o -o bin/hello_world

This initially started giving me a new error: Text file busy, but I have since been unable to get that error back again as it now returns No such file or directory. I'm guessing that particular attempt was just a bad transfer or something.

like image 399
Chris Watts Avatar asked Aug 10 '15 21:08

Chris Watts


People also ask

Which software is used for cross-compilation?

GCC, a free software collection of compilers, can be set up to cross compile. It supports many platforms and languages. Cross-compiling GCC requires that a portion of the target platform's C standard library be available on the host platform.

Why is cross-compiling so hard?

"building a cross-compiler is significantly harder than building a compiler that targets the platform it runs on." The problem exists due to the way libraries are built and accessed. In the normal situation all the libraries are located in a specific spot, and are used by all apps on that system.


1 Answers

Since nobody from the comments posted the answer, I guess I get the pleasure ;)

No such file or directory comes from when the kernel tries to invoke the dynamic linker specified by the ELF executable's .interp field, but no such file exists.

The .interp field can be found with the following command:

objdump -j .interp -s ./hello_world

In the case of this example, the executable's .interp field was /lib/ld-linux.so.3, but the name of the dynamic linker on the BeagleBone Black is /lib/ld-linux-armhf.so.3.

This happened because the program was compiled with a slightly different toolchain to the one required for the platform. It should be arm-linux-gnueabihf-* rather than arm-linux-gnueabi-*.

The difference between the two is that the Cortex-A8 uses specific floating point registers with the hard-float version (armhf) of the EABI, but the original EABI (armel) uses integer registers for passing around floating point numbers. As a result, armel programs will run on armhf (provided the dynamic linker is set to the correct path!), but not vice versa.

Simply adding a symbolic link ln -s /lib/ld-linux-armhf.so.3 /lib/ld-linux.so.3 is enough to resolve this issue, but the correct fix is to use the right toolchain when compiling the program in the first place.

like image 135
Chris Watts Avatar answered Sep 19 '22 12:09

Chris Watts