construyendo un .so que también es un ejecutable

Así que probablemente todos sepan que glibc /lib/libc.so.6 se puede ejecutar en el shell como un ejecutable normal, en cuyo caso imprime su información de versión y sale. Esto se hace mediante la definición de un punto de entrada en .so. En algunos casos, podría ser interesante usar esto también para otros proyectos. Desafortunadamente, el punto de entrada de bajo nivel que puede establecer mediante la opción -e de ld es un nivel demasiado bajo: el cargador dynamic no está disponible, por lo que no puede llamar a ninguna función de biblioteca adecuada. glibc por esta razón implementa la llamada al sistema write () a través de una llamada al sistema desnuda en este punto de entrada.

Mi pregunta ahora es, ¿alguien puede pensar de una buena manera cómo uno puede arrancar un enlazador dynamic completo desde ese punto de entrada para poder acceder a las funciones de otros .so?

La creación de su biblioteca compartida con la opción -pie parece darle todo lo que desea:

 /* 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 implementa write(3) través de la llamada al sistema porque no tiene otro lugar para llamar (ya es el nivel más bajo). Esto no tiene nada que ver con poder ejecutar libc.so.6 .

No es una buena manera, pero crearía un pequeño envoltorio ejecutable alrededor del .so que llama a la función de punto de entrada que quiero ejecutar.

Supongo que tendrías tu ld -e apuntar a un punto de entrada que luego usaría la familia de funciones dlopen() para encontrar y cargar el rest del enlazador dynamic. Por supuesto, debe asegurarse de que dlopen() mismo esté enlazado estáticamente o tenga que implementar suficiente de su propio código auxiliar de enlace para llegar a él (utilizando interfaces de llamadas del sistema como mmap() tal como lo hace libc.

Nada de eso me suena “agradable”. De hecho, solo la idea de leer las fonts glibc (y el código fuente ld-linux , como un ejemplo) lo suficiente como para evaluar el tamaño del trabajo me parece bastante canoso. También podría ser una pesadilla de portabilidad. Puede haber diferencias importantes entre cómo Linux implementa ld-linux y cómo se realizan los enlaces en OpenSolaris, FreeBSD, etc. (No lo sé).