construire un .so qui est aussi un exécutable

Donc tout le monde sait probablement que /lib/libc.so.6 de glibc peut être exécuté dans le shell comme un exécutable normal, auquel cas il imprime ses informations de version et quitte. Cela se fait via la définition d’un point d’entrée dans le .so. Dans certains cas, il pourrait être intéressant de l’utiliser pour d’autres projets également. Malheureusement, le point d’entrée de bas niveau que vous pouvez définir avec l’option -d de ld est un peu trop bas: le chargeur dynamic n’est pas disponible, vous ne pouvez donc pas appeler les fonctions de bibliothèque appropriées. Pour cette raison, glibc implémente l’appel système write () via un appel système nu dans ce point d’entrée.

Ma question est la suivante: est-ce que quelqu’un peut penser à la façon dont on pourrait amorcer un éditeur de liens dynamic complet à partir de ce point d’entrée afin de pouvoir accéder aux fonctions d’autres fichiers .so?

Construire votre bibliothèque partagée avec l’option -pie semble vous donner tout ce que vous voulez:

 /* pie.c */ #include  int foo() { printf("in %s %s:%d\n", __func__, __FILE__, __LINE__); return 42; } int main() { printf("in %s %s:%d\n", __func__, __FILE__, __LINE__); return foo(); } /* main.c */ #include  extern int foo(void); int main() { printf("in %s %s:%d\n", __func__, __FILE__, __LINE__); return foo(); } $ gcc -fPIC -pie -o pie.so pie.c -Wl,-E $ gcc main.c ./pie.so $ ./pie.so in main pie.c:9 in foo pie.c:4 $ ./a.out in main main.c:6 in foo pie.c:4 $ 

PS glibc implémente write(3) via l’appel système car il n’a nulle part où appeler (c’est déjà le niveau le plus bas). Cela n’a rien à voir avec la possibilité d’exécuter libc.so.6 .

Ce n’est pas un bon moyen, mais je créerais un petit exécutable wrapper autour du .so qui appelle la fonction de point d’entrée que je veux exécuter.

Je suppose que vous auriez votre point ld -e sur un point d’entrée qui utiliserait alors la famille de fonctions dlopen() pour trouver et amorcer le rest de l’éditeur de liens dynamic. Bien sûr, vous devez vous assurer que dlopen() est lui-même lié de manière statique ou que vous devez implémenter suffisamment de stub d’éditeur de liens pour y accéder (en utilisant des interfaces d’appels système telles que mmap() .

Rien de tout cela ne me semble “gentil”. En fait, l’idée de lire les sources de la glibc (et le code source de ld-linux , par exemple) suffit à évaluer la taille du travail. Ce pourrait aussi être un cauchemar de portabilité. Il peut y avoir des différences majeures entre la manière dont Linux implémente ld-linux et la façon dont les liaisons sont effectuées sous OpenSolaris, FreeBSD, etc. (Je ne sais pas).