c linux linker shared-libraries elf

¿Cuáles son las diferencias de encabezado ELF entre un archivo de objeto ELF y un objeto compartido?



linux linker (1)

Una de las principales diferencias que encontrará es que, durante la etapa final del enlace, una serie de componentes de la biblioteca C están vinculados estáticamente a la biblioteca, formando los símbolos INIT y FINI, entre otras cosas. Estos se especifican con las entradas DT_INIT y DT_FINI en el encabezado del programa; Tendrá que transformarlos en entradas estáticas de constructor / destructor. Las entradas DT_NEEDED se perderán en una transformación en .o; tendrá que volver a agregarlos manualmente.

El PLT generado en la etapa de enlace final debe fusionarse con el archivo de salida final o transformarse de nuevo en reubicaciones normales; Esto no es trivial, ya que el PLT es solo un código. El GOT también es un problema; se encuentra en un desplazamiento relativo fijo del segmento .text y contiene punteros a miembros de datos. Sin embargo, también contiene un puntero a la estructura _DYNAMIC, de la cual solo puede haber uno por biblioteca o ejecutable. Y no puede cambiar las compensaciones en el GOT, porque se hace referencia directamente desde el código.

Así que es bastante difícil convertir un .so de nuevo a un verdadero .o; Se ha perdido información en la conversión a PLT / GOTs. Un mejor enfoque podría ser alterar el enlazador dinámico en la biblioteca de C para que sea compatible con la vinculación de una biblioteca compartida que ya está asignada en la memoria como una imagen estática. Es decir, convertirías el .so a un .o simplemente convirtiéndolo en una sección de solo lectura alineada con la página; luego pase esto al vinculador dinámico para volver a asignar con los permisos apropiados y realizar la inicialización normal de la biblioteca compartida. Luego agregue un constructor estático para llamar a la biblioteca de C para inicializar la biblioteca compartida. Finalmente, agregue los símbolos exportados apropiados para corresponder a los símbolos dinámicos en el segmento .text de la biblioteca compartida.

Sin embargo, un problema con este enfoque es que los constructores estáticos pueden ejecutarse antes que el constructor estático que inicializa su falso solib. En este caso, no deben intentar llamar a funciones desde el solib, o probablemente se bloqueará, ya que el solib aún no está inicializado. Esto podría evitarse potencialmente haciendo que los símbolos exportados apunten a una función de trampolín que garantice que el solib se inicialice primero (aunque no es tan fácil con los símbolos de datos).

También puede encontrar que esta pregunta anterior podría serle de alguna utilidad.

En primer lugar, estoy preguntando esto desde una perspectiva técnica, no desde la perspectiva del usuario del código de biblioteca. Un ejemplo de una diferencia es que los objetos compartidos contienen encabezados de programas y los archivos de objetos comunes no. ¿Cuáles son las otras diferencias?

En cuanto al propósito de mi pregunta, estoy tratando de averiguar qué contenido debería eliminarse de un archivo de objeto compartido para que el vinculador lo trate como un archivo de objeto común e intente reubicarlo y vincularlo estáticamente con el ejecutable generado. archivo, en lugar de identificarlo como una biblioteca compartida y generar una referencia DT_NEEDED . Este, a su vez, es el primer paso hacia la "conversión" primitiva de una biblioteca compartida a algo que puede vincularse estáticamente (sin embargo, es posible que se requiera más trabajo para que las reubicaciones sean satisfactorias).