`bash: ./a.out: No such file or directory` on running executable produced by `ld`

后端 未结 3 1682
温柔的废话
温柔的废话 2020-12-15 23:57

Here is a Hello World code in C:

// a.c
#include 

int main() {
    printf(\"Hello world\\n\");
    return 0;
}

I compile it

3条回答
  •  心在旅途
    2020-12-16 00:55

    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.


    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.)

提交回复
热议问题