2009-08-17 17 views
6

Tengo un programa que implementa un sistema de complemento cargando dinámicamente una función desde algún plugin_name.so (como de costumbre).GCC/Linux: agregar una biblioteca estática a .so?

Pero a su vez tengo una biblioteca "auxiliar" estática (llamémosle helper.a) cuyas funciones se usan tanto desde el programa principal como desde la función principal del complemento. No tienen que interoperar de ninguna manera, solo son funciones auxiliares para la manipulación de texto y tal.

Este programa, una vez iniciado, no se puede volver a cargar o reiniciar, es por eso que espero tener una nueva funcionalidad de "ayuda" desde el complemento, no desde el programa principal.

Así que mi pregunta es ... ¿es posible forzar este "código de función del complemento" en .so para usar (¿estáticamente enlace contra?) Una versión diferente (quizás más nueva) de "ayuda" que el programa principal?

¿Cómo se pudo hacer esto? quizás al vincular estáticamente o agregar helper.a a plugin_name.so?

+0

Me gustaría agregar que no quiero o no espero utilizar la nueva biblioteca auxiliar del programa principal. Solo me gustaría vincular cada nuevo complemento con una biblioteca auxiliar más nueva/mejor. – conejoroy

+0

¿Hay alguna razón por la que no pueda usar el enlace dinámico para la función auxiliar? –

+0

una vez que se inicia, el programa principal no puede detener la ejecución, incluso para volver a cargar un helper.so más nuevo, y el programa solo necesita una funcionalidad auxiliar muy básica, ya que es solo un marcador de posición para los complementos. entonces prefiero compilar todo el complemento nuevamente si tengo una biblioteca de ayudante nueva/mejorada o extendida. Creo que es más práctico distribuir un solo .so (el complemento) que dos .so (complemento y el asistente más actualizado que usa el complemento) – conejoroy

Respuesta

6

La respuesta de Nick Meyer es correcta en Windows y AIX, pero es poco probable que sea correcta en todas las demás plataformas UNIX de forma predeterminada.

En la mayoría de las plataformas UNIX, el cargador de tiempo de ejecución mantiene un único espacio nombre para todos los símbolos, por lo que si se define foo_helper en a.out, y también en plugin.so, y luego llamar a foo_helper de cualquiera, la primera definición visible para el tiempo de ejecución Loader (por lo general, desde a.out) se utiliza por defecto para llamadas.

Además, el cuadro se complica por el hecho de que foo_helper no podrá exportarse a.out (y por lo tanto puede ser invisible para cargador de tiempo de ejecución), a menos que utilice -rdynamic bandera, o algunos otros compartidos de biblioteca hace referencia a ella. En otras palabras, las cosas pueden aparecer para que funcionen como Nick las describió, luego agrega una biblioteca compartida a la línea de enlace a.out, y ya no funcionan de esa manera.

En las plataformas ELF (como Linux), tiene un gran control sobre la visibilidad y encuadernación de los símbolos. Consulte la descripción de -fvisibility=hidden y -rdynamic en la página de manual de GCC, y también -Bsymbolic en la página man del vinculador.

La mayoría de las demás plataformas UNIX también tienen alguna forma de controlar las asociaciones de símbolos, pero esto es necesariamente específico de la plataforma.

1

Si su programa principal y su biblioteca dinámica se vinculan estáticamente a helper.a, entonces no debería tener que preocuparse de mezclar versiones de helper.a (siempre que no haga cosas como punteros de pase asignados en helper) .a entre los límites .exe y .so).

El código requerido por el helper.a se inserta en el binario real cuando se enlaza con él. Entonces, cuando llamas a helper.a desde .exe, estarás ejecutando código desde el segmento de código de tu imagen ejecutable, y cuando llamas a helper.a desde .so, estarás ejecutando código de la parte del espacio de direcciones donde se cargó .so Incluso si está llamando a la misma función dentro de helper.a, está llamando a dos 'instancias' diferentes de esa función dependiendo de si la llamada se realizó desde el .exe o .so.

+0

Ya veo. pero ¿cómo podría agregar el código en libhelper.a a plugin.so en tiempo de compilación? ¿debo especificar algo como "gcc -lhelper.a -static" al compilar plugin.so? – conejoroy

+0

Si su biblioteca es libhelper.a, pase -L * dir * -hellar a gcc al compilar plugin.so, donde * dir * es la ruta a libhelper.a. No es necesario especificar -static, eso se usa cuando está creando una biblioteca estática. –

+0

Esta respuesta es correcta solo bajo condiciones limitadas, que no están indicadas. –

Cuestiones relacionadas