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:
En general, el código de nivel de usuario nunca debe usar
lddirectamente, y siempre usar el frente de compilación apropiado (gccaquí) para realizar el enlace.Como ha descubierto, la línea de comando de enlace que construye
gcces 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
gccsolo ligeramente (por ejemplo, algunos sistemas operativos requierencrt1.odiferente 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 usarlddirectamente).Las bibliotecas deben seguir los archivos de objetos en la línea de comandos. Entonces
ld -lc aonunca 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