Here is a Hello World code in C:
// a.c
#include
int main() {
printf(\"Hello world\\n\");
return 0;
}
I compile it
The other answers only address how to avoid this, not the actual question of what happened.
The gcc -c a.c; ld -lc a.o commands you gave produce a pretty obvious warning:
ld: warning: cannot find entry symbol _start; defaulting to 0000000000400260
So even if this file could be executed, it will probably crash right away. See @EmployedRussian's answer for an explanation of what you should have done.
$ strace ./a.out
execve("./a.out", ["./a.out"], [/* 72 vars */]) = -1 ENOENT (No such file or directory)
execve(2) returns ENOENT because it can't find the interpreter (which I figured out from file and so on, see below). You'd get the same error from trying to run a file that started with
#!/usr/non-existant-path/bin/bash
As you discovered, the usual reason for this error message is when running an ELF binary on a system without the right dynamic linker and dynamic libraries installed (e.g. a 64bit system without 32bit support installed). In your case, it's because you used a bad link command and made a dynamic executable with a bad interpreter path.
I'm on Ubuntu 15.10, where GNU file version 5.22 reports:
a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib/ld64.so.1, not stripped
There is no /lib/ld64.so.1 on my system. ldd output is confusing, because ldd uses its default ELF interpreter, not the one specified by the binary.
$ ldd a.out
linux-vdso.so.1 => (0x00007ffc18d2b000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f0e0a79f000)
/lib/ld64.so.1 => /lib64/ld-linux-x86-64.so.2 (0x0000559dbc9d2000)
So it assumes that the runtime interpreter in the binary resolved to the one ldd used itself, I guess.
Your ldd output is probably from an old version too, since it just shows /lib64/ld-linux-x86-64.so.2 for that line. Not taking a bad guess is probably better behaviour, for a weird case like this, but doesn't help you see that your binary has a weird interpreter path.
readelf -l a.out
will decode the ELF headers for you, including the interpreter path. (Thanks to @EmployedRussian's comment for pointing this out.)