2009-10-19 23 views
26

Al menos en Linux y Solaris, las bibliotecas estáticas son en realidad un montón de .o's compilados arrojados a un gran archivo. Al compilar una biblioteca estática, generalmente se omite el indicador -fpic, por lo que el código generado depende de la posición.Vinculación de una biblioteca compartida con una biblioteca estática: ¿la biblioteca estática debe compilarse de forma diferente que si una aplicación estuviera vinculándola?

Ahora diga que mi biblioteca estática es B. Lo he construido y tengo el archivo resultante .a que en realidad es solo un glob de todos los archivos .o dependientes de la posición. Ahora tengo una biblioteca compartida que me gustaría construir, A, y quiero que enlace estáticamente B. Cuando construyo A, usaré el indicador -fpic para hacer que la posición del código generado sea independiente. Pero si hago un enlace contra B, ¿no estoy mezclando los archivos de objeto dependientes de la posición y la posición independiente?

Recibo muchos errores de reubicación de texto a menos que también especifique -mimpure-text, y creo que esta puede ser la causa. Parece que cuando compilo una biblioteca, realmente necesito compilarla veces, una versión compartida, una versión estática y una versión estática que se puede usar por compartido. ¿Estoy en lo cierto? Podría seguir usando -mimpure-text pero la página de manual de g ++ dice que si haces eso, el objeto en realidad no termina siendo compartido (no está claro si todo está sin compartir o solo las partes estáticamente vinculadas, ¿alguien lo sabe?) .

+0

La pregunta se expresa correctamente, él 'omite' '-fpic' en el primer párrafo, lo que lleva al código dependiente de la posición, luego lo usa en el segundo párrafo, lo que lleva al código de posición independiente. –

Respuesta

24

No tiene que usar el código PIC en objetos compartidos (ya que ha descubierto que puede usar la opción -mimpure-text para permitir eso).

Dicho esto, el código no PIC en objetos compartidos es más pesado. Con el código PIC, las páginas de texto en la memoria son solo asignaciones de memoria directa de las páginas de texto en el disco. Esto significa que si varios procesos usan el objeto compartido, pueden compartir la página de memoria.

Pero si no tiene código PIC, cuando el vinculador de tiempo de ejecución carga el objeto compartido, tendrá que aplicar correcciones a las páginas de texto. Esto significa que cada proceso que use el objeto compartido tendrá su propia versión única de cualquier página de texto que tenga una corrección (incluso si el objeto compartido se carga en la misma dirección que copiar-en-escribir solo advierte que la página fue modificado y no que haya sido modificado de la misma manera).

Para mí, la cuestión importante es si simultáneamente se ejecutarán varios procesos que cargan cada uno el objeto compartido. Si lo hace, definitivamente vale la pena asegurarse de que todo el código dentro del SO sea PIC.

Pero si ese no es el caso y solo un proceso único tiene el objeto compartido cargado, no es tan crítico.

+0

En realidad, si sabes que solo un proceso va a cargarlo, ¿no puede ser un beneficio de rendimiento compilar sin foto? Debido a guardar un registro. –

+1

@JosephGarvin PIC consume un registro en código x86 de 32 bits, pero no en código de 64 bits. El conjunto de instrucciones x64 es compatible con el direccionamiento relativo del contador de programas: carga los datos que son desvíos de NNNN desde la dirección de la memoria de la siguiente instrucción (siguiente instrucción) que está ejecutando la instrucción.El código PIC en x64 no requiere un registro de puntero GOT. – dthorpe

+0

¡Gracias por una gran explicación! – rkellerm

1

Como alternativa, envíe dos bibliotecas: la compartida y la estática con la que está enlazando. Deben enlazar al ejecutable final correctamente.

3

hago lo siguiente en la etapa de enlace de la versión de la biblioteca de objetos compartidos de una biblioteca estática: g ++ -shared -o libshared.so -Wl, - todo el archivo -fPIC -lstatic -Wl, - no- archivo completo. Como --whole-archive vincula cada objeto en una (lista de) libs estáticas (de la forma libstatic.a) creo que preceder a eso (list) con -fPIC es todo lo que OP necesita hacer.

+0

¿podría explicarme más claramente? – gyro

Cuestiones relacionadas