scripts script programa hacer ejemplos ejecutar desde compilar como c linux gcc linker dynamic-linking

script - `bash:./a.out: No existe ningún archivo o directorio` en ejecutar ejecutable producido por` ld`



script linux ejemplos (3)

ld -lc ao

Hay varias cosas mal con esta línea de comando:

  1. En general, el código de nivel de usuario nunca debe usar ld directamente, y siempre usar el frente de compilación apropiado ( gcc aquí) para realizar el enlace.

    Como ha descubierto, la línea de comando de enlace que construye gcc es bastante complicada, y la línea de comando que ha aceptado en la respuesta de Joan Esteban es incorrecta.

    Si desea ver el comando de enlace real , examine la salida de gcc -v ao .

    También tenga en cuenta que el comando de enlace cambia significativamente cuando cambia el comando gcc solo ligeramente (por ejemplo, algunos sistemas operativos requieren crt1.o diferente dependiendo de si está vinculando ejecutable de subprocesos múltiples o no), y la línea de comandos siempre es específica del sistema operativo (que es uno más razón para nunca usar ld directamente).

  2. Las bibliotecas deben seguir los archivos de objetos en la línea de comandos. Entonces ld -lc ao nunca es correcto, y siempre debe ser (una variante de) ld ao -lc . Explicación

Aquí hay un código Hello World en C:

// a.c #include <stdio.h> int main() { printf("Hello world/n"); return 0; }

Lo compilo como gcc ac , que produce a.out como se esperaba y ./a.out imprime Hello world ... como se esperaba.

Ahora si hago la compilación y el enlace por separado: gcc -c ac; ld -lc ao gcc -c ac; ld -lc ao , ejecuta el a.out producido como ./a.out recibo el mensaje:

bash: ./a.out: No such file or directory

Busqué ese error en Google y parece que sucede cuando el ejecutable producido es un ELF de 32 bits y la arquitectura de la máquina es de 64 bits.

Estoy ejecutando un equipo de 64 bits y ejecutando el file a.out da:

a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), not stripped

¿Por qué pasó esto?

EDITAR:

Salida de uname -m

$ uname -m x86_64

Salida de 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 ac produce a.out que se ejecuta correctamente.


Las otras respuestas solo abordan cómo evitar esto, no la cuestión real de lo que sucedió .

El gcc -c ac; ld -lc ao gcc -c ac; ld -lc ao comandos gcc -c ac; ld -lc ao usted dio produjeron una advertencia bastante obvia:

ld: warning: cannot find entry symbol _start; defaulting to 0000000000400260

Entonces, incluso si este archivo pudiera ejecutarse, probablemente se bloquee de inmediato. Consulte la respuesta de @ EmployedRussian para obtener una explicación de lo que debería haber hecho.

La pregunta de por qué ni siquiera se puede ejecutar sigue siendo interesante:

$ strace ./a.out execve("./a.out", ["./a.out"], [/* 72 vars */]) = -1 ENOENT (No such file or directory)

execve(2) devuelve ENOENT porque no puede encontrar el intérprete (que encontré en el file etc.). Obtendrá el mismo error al intentar ejecutar un archivo que comenzó con

#!/usr/non-existant-path/bin/bash

Como descubrió, el motivo habitual para este mensaje de error es cuando se ejecuta un binario ELF en un sistema sin el enlazador dinámico correcto y las bibliotecas dinámicas instaladas (por ejemplo, un sistema de 64 bits sin soporte de 32 bits instalado). En su caso, es porque utilizó un comando de enlace incorrecto e hizo un ejecutable dinámico con una ruta de intérprete incorrecta.

Estoy en Ubuntu 15.10, donde el file GNU versión 5.22 informa:

a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib/ld64.so.1, not stripped

No hay /lib/ld64.so.1 en mi sistema. ldd salida de ldd es confusa, porque ldd usa su intérprete de ELF predeterminado, no el especificado por el binario.

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

Por lo tanto, se supone que el intérprete de tiempo de ejecución en el binario resuelto a la que ldd utilizó, supongo.

Su salida de ldd es probablemente también de una versión anterior, ya que solo muestra /lib64/ld-linux-x86-64.so.2 para esa línea. No tomar una mala estimación es probablemente un mejor comportamiento, para un caso raro como este, pero no ayuda a ver que su binario tiene una extraña ruta de interpretación.

readelf -l a.out

decodificará los encabezados ELF para usted, incluida la ruta del intérprete. (Gracias al comentario de @ EmployedRussian para señalar esto).


Usa eso:

ld -o a.out -dynamic-linker /lib/ld-linux.so.2 /usr/lib/crt1.o /usr/lib/crti.o -lc c.o /usr/lib/crtn.o