Niveau :
Résumé : ldd ; readelf ; ld-linux
Savez vous ce qui se passe quand vous lancez un logiciel ? Si c'est à travers votre shell, il analyse votre ligne de commande puis d'une façon ou d'une autre appelle execve qui demande au noyau de charger le fichier en question et de l'exécuter. Si ce n'est pas le shell, un autre fera à peu près le même chose.
Vous pensez probablement que le binaire est mis en mémoire à un endroit donné et que le point d'entrée correspondant est appelé et que c'est tout. Vous auriez eu raison il y a 15 ans. Mais le format de fichier aout a été remplacé par le format elf et les choses ne se passent plus tout à fait de cette façon.
Le format elf a été inventé entre autre pour permettre le chargement dynamique de bibliothèque. Pour lancer un fichier elf, le noyau lance d'abord ce qu'il appelle un interpréteur. L'interpréteur est une information donnée dans le programme lui-même. Il apparaît dans a liste des bibliothèques chargées avec un programme qu'on voit avec la commande ldd :
$ ldd /bin/ls
Vous pouvez aussi le voir avec la commande readelf :
$ readelf -l /bin/ls
Donc en pratique lorsque vous tapez ls, le noyau comprend la commande suivante :
$ /lib64/ld-linux-x86-64.so.2 /bin/ls # vous constatez que je suis en architecture 64 bits
D'ailleurs vous pouvez aussi lancer la commande telle quelle.
Ld-linux va à son tour lire les en-têtes elf et charger toutes les bibliothèques dont dépend le programme en question. C'est lui qui appellera le point de départ du programme. Les symboles (comme par exemple les fonctions) seront eux résolus lorsqu'ils seront appelés, le premier appel d'une fonction est donc toujours légèrement plus long que les suivants.
Sachez que vous pouvez influencer le comportement de ld-linux avec des variables d'environnement, attention des restrictions s'appliquent pour les programmes setuid. Les variables les plus courantes sont les 2 premières :
continue reading...