2011-08-05 14 views
13

La compilación del código en un archivo de objeto debe realizarse independientemente de la posición si el archivo está destinado a ser cargado como biblioteca compartida (.so), porque la dirección virtual base en la que se carga el archivo de objeto compartido en diferentes procesos puede ser diferente.¿El código de 32 bits x86 debe compilarse especialmente en PIC para los archivos de bibliotecas compartidas?

Ahora no encontré errores cuando intenté cargar un archivo .so compilado y enlazado sin la opción -fpic GCC en equipos 32bit x86, mientras falla en equipos bit 64 bit x86.

sitios web al azar que he encontrado dicen que no necesito -fpic de 32 bits ya que el código compilado sin -fpic obras de coincidencia de acuerdo con el X86 de 32 bits ABI también cuando se utiliza de una manera independiente de la posición. Pero aún encontré un software que incluye versiones separadas de bibliotecas en sus versiones de 32 bits: una para PIC y otra para no PIC. Por ejemplo, el compilador de inteligencia se envía con libirc.a y libirc_pic.a, este último se compila para el modo de posición independiente (si se quiere vincular ese archivo .a en un archivo).

Me pregunto cuál es la diferencia exacta entre usar -fpic y no utilizarlo para el código de 32 bits, y por qué algunos paquetes, como el compilador de inteligencia, todavía se entregan con versiones separadas de bibliotecas?

+0

¿Intentó la compilación de código no-fp usando TLS? ¿O cargar varias librerías que no sean pic con rangos de memoria superpuestos? Las librerías estáticas separadas son para enlazar los programas estáticamente (libirc.a; no pic es un poco más rápido) y en las bibliotecas .so estáticamente (_pic.a versión). – osgx

+0

Consulte http://stackoverflow.com/questions/3146744/difference-in-position-independent-code-x86-vs-x86-64 – AProgrammer

Respuesta

0

la dirección virtual de base que el archivo de objeto compartido se carga en en diferentes procesos puede ser diferente

Dado que los objetos compartidos normalmente se cargan en su dirección preferida, pueden parecen funcionar correctamente . Pero fPIC es una buena idea para todos los códigos compartidos.

Creo que la razón de que no haya dos versiones de la biblioteca es que muchas distribuciones usan fPIC como el valor predeterminado para todos los códigos.

+3

Los objetos compartidos generalmente están vinculados a la carga en la dirección 0, y definitivamente no se cargan ahí. –

+0

Lo que @Employed Russian dijo. Además, puede 'prelink 'bibliotecas para hacer que tengan una dirección base preferida, pero es un paso separado (y opcional) de la vinculación normal. – ninjalj

+1

@Employed Russian: ¿Es eso solo un linux?Otros sistemas operativos no son tan estúpidos como para establecer de forma predeterminada conflictos de dirección 100% base. –

10

No es que el código no PIC funcione "por coincidencia" en x86 (32 bits). Es que el enlazador dinámico para x86 admite los "textos" necesarios para que funcione. Esto tiene un costo muy alto en consumo de memoria y tiempo de inicio, ya que básicamente todo el segmento de código debe ser remendado en el momento de la carga (y por lo tanto se convierte en memoria no compartible).

Los mantenedores del vinculador dinámico afirman que las bibliotecas compartidas que no son PIC no pueden ser soportadas en x86_64 debido a problemas fundamentales en la arquitectura (los desplazamientos de direcciones inmediatos no pueden superar los 32 bits) pero este problema podría resolverse fácilmente simplemente siempre cargando bibliotecas en los primeros 4 gb del espacio de direcciones virtuales. Por supuesto, el código PIC es muy económico en x86_64 (el PIC no es un asesino de rendimiento como en el de 32 bits x86), por lo que probablemente tengan razón al mantenerlo sin soporte y evitar que los tontos hagan librerías sin PIC ...

+0

Gracias, eso tiene sentido. Si compilo una lib de PIC en x86, ya no usaré textres, sospecho? ¿Por qué sigue siendo un asesino de rendimiento entonces? –

+6

El código PIC requiere un registro adicional para mantener la dirección base. En x86 ya tiene muy pocos registros, por lo que reservar uno más hace que el compilador derrame registros en la memoria aún más a menudo. –

+2

PIC es un asesino de rendimiento en x86 porque cargar el registro GOT es costoso. Requiere una llamada de función y leer/guardar la dirección de retorno de la pila. x86_64 tiene un direccionamiento 'eip' relativo, por lo que no es necesario un registro GOT. –

Cuestiones relacionadas