`bash: ./un.: Aucun fichier ou répertoire` sur l'exécution du fichier exécutable généré par `ld`
Ici est un Hello World code en C:
//a.c
#include <stdio.h>
int main() {
printf("Hello world\n");
return 0;
}
Je le compiler en tant que gcc a.c
, qui produit a.out
comme prévu et ./a.out
imprime Hello world
... comme prévu.
Maintenant, si je dois le compiler et lier séparément:
gcc -c a.c; ld -lc a.o
, de l'exécution du a.out
produit comme ./a.out
je reçois le message:
bash: ./a.out: No such file or directory
J'ai Googlé cette erreur et il semble que ce qui se passe lorsque l'exécutable produit est un 32 bits, l'ELFE et l'architecture de la machine est de 64 bits.
Je fais tourner une machine 64 bits et en cours d'exécution file a.out
donne:
a.out: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), not stripped
Pourquoi cela se produit?
EDIT:
Sortie de uname -m
$ uname -m
x86_64
Sortie 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 a.c
produit a.out
qui fonctionne correctement.
Une machine 64 bits ne signifie pas nécessairement un OS 64 bits. Quel est le résultat de
Ce n'
Ajouté le sorties, des modifications à la question
vous pouvez exécuter la commande: gcc-v un.c et vérifier le lien de la scène (avez-vous besoin de lien avec l'objet de démarrage habituellement crt0.o)
Pourquoi ne voulez-vous pas laisser gcc poignée de la liaison?
uname -m
?Ce n'
ldd a.out
produire? Ce qui se passe lorsque vous ne gcc a.c
?Ajouté le sorties, des modifications à la question
vous pouvez exécuter la commande: gcc-v un.c et vérifier le lien de la scène (avez-vous besoin de lien avec l'objet de démarrage habituellement crt0.o)
Pourquoi ne voulez-vous pas laisser gcc poignée de la liaison?
OriginalL'auteur pratyaksh | 2015-11-28
Vous devez vous connecter pour publier un commentaire.
L'autre ne répond qu'à une adresse comment faire pour éviter cela, ne pas le question réelle de ce qui s'est passé.
La
gcc -c a.c; ld -lc a.o
commandes que vous avez donné à produire une assez évident avertissement:Donc, même si ce fichier peut être exécuté, il sera probablement planter tout de suite. Voir @EmployedRussian la réponse de pour une explication de ce que vous devriez avoir fait.
La question de savoir pourquoi il ne peut même pas être exécutée est toujours intéressant:
execve(2)
renvoie ENOENT car il ne peut pas trouver l'interprète (qui, j'ai réalisé à partir defile
et ainsi de suite, voir ci-dessous). Vous obtiendrez le même message d'erreur en essayant d'exécuter un fichier qui a commencé avecComme vous l'avez découvert, la raison habituelle pour ce message d'erreur lors de l'exécution d'un binaire ELF sur un système sans le droit de l'éditeur de liens dynamiques et bibliothèques dynamiques installé (par exemple, un système 64 bits, sans 32bit soutien installé). Dans votre cas, c'est parce que vous avez utilisé une mauvaise liaison de commande et de fait une dynamique exécutable avec un mauvais interprète chemin.
Je suis sur Ubuntu 15.10, où GNU
file
version 5.22 rapports:Il n'y a pas de
/lib/ld64.so.1
sur mon système.ldd
sortie est de la confusion, carldd
utilise sa valeur par défaut ELFE interprète, pas celui spécifié par le binaire.De sorte qu'il suppose que le moteur d'exécution de l'interprète dans le binaire résolu à l'un
ldd
utilisé lui-même, je suppose.Votre
ldd
de sortie est probablement à partir d'une ancienne version de trop, car il montre juste/lib64/ld-linux-x86-64.so.2
pour cette ligne. Ne pas prendre une mauvaise conjecture est probablement un meilleur comportement, pour un drôle de cas comme cela, mais ne pas vous aider à voir que votre binaire a un truc bizarre interprète chemin.décoder l'ELFE en-têtes pour vous, y compris l'interprète chemin. (Merci à @EmployedRussian commentaire pour le signaler.)
readelf -l a.out | grep interpreter
OriginalL'auteur Peter Cordes
Il y a plusieurs choses qui clochent dans cette ligne de commande:
En général, le code de niveau utilisateur doit jamais utilisation
ld
directement, et toujours utilisation appropriée compilateur frontal (gcc
ici) pour faire le lien.Que vous avez découvert, la ligne de commande de liaison qui
gcc
constructions est assez compliqué, et la ligne de commande que vous avez accepté dans Joan Esteban la réponse est fausse.Si vous voulez voir la réelle de commande de liaison, examinant la sortie de
gcc -v a.o
.Également noter que le lien de commande modifie de façon significative lorsque vous modifiez
gcc
commande seulement légèrement (par exemple, certains Systèmes d'exploitation nécessitent différentscrt1.o
en fonction de si vous créez un lien multi-thread exécutable ou non), et de la ligne de commande est toujours spécifiques aux systèmes d'exploitation (ce qui est une raison de plus pour jamais utilisationld
directement).Les bibliothèques devraient suivre fichiers de l'objet sur la ligne de commande. Donc
ld -lc a.o
est jamais correct, et devrait toujours être (une variante de)ld a.o -lc
. Explication.OriginalL'auteur Employed Russian
L'utiliser:
crt1.o
,crti.o
, etcrtn.o
sont présents dans/usr/lib/x86_64-linux-gnu/
sur ma machine. Après la modification et l'exécution deld
et puis lea.out
, j'obtiens l'erreur:bash: ./a.out: Accessing a corrupted shared library
Vous avez également besoin de s'adapter à l'éditeur de liens
/lib64/ld-linux-x86-64.so.2
.C'est le mal de réponse à cette question.
OriginalL'auteur Joan Esteban