Cross compilation issue: binary appears to be a shared object

Hello

I am trying to build a binary for the Intel “silvermont” architecture. I do not want to build on the concerned systems directly because it is slow and there is not enough disk space to download dependencies.

I tried to mess with cargo configuration (with RUSTFLAGS and target) but every time I get the same issue: I cannot run the binary on the target machine because it appears to be a shared object.

Look at the output of file command:

hello: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-x86-64.so.2, BuildID[sha1]=0396fa8dd3bafd192286090eb2792e042137aa09, for GNU/Linux 3.2.0, not stripped

And on the machine that compiled the binary:

hello: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-x86-64.so.2, BuildID[sha1]=0396fa8dd3bafd192286090eb2792e042137aa09, for GNU/Linux 3.2.0, with debug_info, not stripped

Any ideas?

I think older versions of file just didn’t recognize PIE – such executables have the same ELF type as shared objects, ET_DYN. And fun fact, you can execute shared objects anyway if they have a defined entry point – for example libc.so has this.

What is the problem you encounter on the target?

1 Like

This is what I get when trying to run the executable on the target machine:

$ ./hello
-bash: ./hello: No such file or directory

silvermont is x86_64 like the machine where I compile so it should run and maybe crash if there is an invalid instruction.

Is that interpreter path valid on the target? I think that usually needs to be /lib64/. It might be a distro idiosyncrasy, but I thought this much was pretty standard, not sure…

The host machine is running void linux, the target is ubuntu.

I just added a symlink to match the path and it worked.

I would prefer to not have to do that. How can I change the path of the interpreter in the build?

You could set RUSTFLAGS=-Clink-arg=-Wl,--dynamic-linker=/lib64/....

1 Like