`bash: ./a.out: No such file or directory` on running executable produced by `ld`
c, dynamic-linking, gcc, linker, linux
Solution
Link dynamic executables with `gcc foo.o` (to use the right paths for CRT and libc, and the dynamic linker / ELF interpreter `ld-linux-x86-64.so.2`). Or `gcc -nostartfiles foo.o` for libc but not CRT `_start`, if you have a hand-written `_start`
(For static executables without libc or CRT, you can use `ld` directly or `gcc -nostdlib -static`.)
`gcc -v foo.o` will show you the actual paths GCC used on your system.
The other answers only address how to avoid this1, 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.
The question of why it can't even be executed is still interesting:
$ 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.)
Problem
Here is a Hello World code in C: ``` // a.c #include <stdio.h> int main() { printf("Hello world\n"); return 0; } ``` I compile it as `gcc a.c`, which produces `a.out` as expected and `./a.out` prints `Hello world`... as expected. Now if I do the compile and link separately: `gcc -c a.c; ld -lc a.o`, it run the `a.out` produced as `./a.out` I get the message: ``` bash: ./a.out: No such file or directory ``` I Googled that error and it seems that happens when the executable produced is a 32-bit ELF and the machine architecture is 64-bit. I'm running a 64-bit machine and running `file a.out` gives: ``` a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), not stripped ``` Why does this happen? EDIT: Output of `uname -m` ``` $ uname -m x86_64 ``` Output of `ldd a.out` ``` $ ldd a.out linux-vdso.so.1 => (0x00007ffeeedfb000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa13a7b8000) /lib64/ld-linux-x86-64.so.2 (0x00007fa13abab000) ``` `gcc a.c` produces `a.out` which runs correctly.