2011-08-27 13 views
25

he recibido recientemente una:¿Por qué es fPIC absolutamente necesario en 64 y no en plataformas de 32 bits?

... R_X86_64_32 reubicación contra `un símbolo local' no se pueden utilizar cuando se hace un objeto compartido; recompile con -fPIC

error al intentar compilar un programa como una biblioteca compartida.

Ahora la solución a esto no es muy difícil (recompile todas las dependencias con -fPIC), pero después de algunas investigaciones resulta que este problema solo está presente en las plataformas x86-64. En 32 bits, cualquier código dependiente de la posición aún puede ser reubicado por el cargador dinámico.

answer La mejor que pude encontrar es:

x 86 tiene soporte para las reubicaciones .text (que es lo que sucede cuando se tiene código de posición-dependend). Este soporte tiene un costo, es decir, que cada página que contiene dicha reubicación queda básicamente sin compartir, incluso si se encuentra en una biblioteca compartida, lo que arruina el concepto mismo de las bibliotecas compartidas . Por lo tanto, decidimos no permitir esto en amd64 (además de que crea problemas si el valor necesita más de 32 bits, ya que todos los reubicaciones .text única tienen un tamaño 'word32')

Pero no encuentro esto muy adecuada . Si es el caso de que las reubicaciones estropeen el concepto de bibliotecas compartidas, ¿por qué se puede hacer en plataformas de 32 bits? Además, si había cambios que debían hacerse en el formato ELF para admitir 64 bits, ¿por qué no todos los campos aumentaron de tamaño para adaptarse?

Esto puede ser un punto menor, pero está motivado por el hecho de que a) el código en cuestión es un código científico y sería bueno no tener que tomar un golpe de rendimiento yb) esta información era casi imposible para encontrar en primer lugar!

[Editar: 'La respuesta'

@awoodlands answer es probablemente la mejor 'respuesta literal', @servn added una buena información.

En una búsqueda para encontrar más información sobre los diferentes tipo de movimientos que encontré this y en última instancia un x86_64 ABI reference (véase la página 68) ]

+1

no sé la respuesta a su pregunta, pero usted debe ser consciente de que el ' -El rendimiento de fPIC' se reduce en x86-64 (relativo a x86-32) porque tiene más registros, direccionamiento relativo de PC y un ABI diseñado con PIC en mente. No voy a decir que se ha ido *, pero mídelo y podría estar gratamente sorprendido. – zwol

+0

Ese parece ser el consenso, una pequeña penalización en el desempeño por lo que es una gran conveniencia. Tendré que intentarlo yo mismo. –

+0

La pregunta principal es, por supuesto, por qué un compilador tiene una "opción obligatoria". "No dijiste la palabra mágica" es un juego bastante infantil. – MSalters

Respuesta

10

como yo lo entiendo el problema es x86-64 parece introducir un nuevo, más rápido forma de referenciar los datos relativos al puntero de instrucción, que no existía para x86-32.

This article tiene un buen análisis en profundidad de la misma, y ​​da el siguiente resumen:

La capacidad de utilizar la instrucción x86-64-puntero con relación a la compensación direcciones de datos es una buena optimización, pero en una situación de biblioteca compartida , las suposiciones sobre la ubicación relativa de los datos no son válidas y no se pueden usar. En este caso, el acceso a los datos globales (es decir, cualquier cosa que pueda modificarse) debe pasar por una capa de abstracción, es decir, la tabla de compensación global.

I.e. El direccionamiento -fPIC agrega una capa adicional de abstracción al direccionamiento, para hacer que lo que era previamente posible (y una característica deseable) en el estilo de direccionamiento habitual aún funcione con la arquitectura más nueva.

+0

¡Es un gran artículo, gracias! –

7

Pero no me parece adecuado. Si es el caso de que las reubicaciones estropeen el concepto de bibliotecas compartidas, ¿por qué se puede hacer en plataformas de 32 bits?

Se puede hacer, simplemente no es particularmente eficiente ... el cálculo de los costes de ejecución reubicaciones tiene, los ejecutables reubicados toman memoria adicional, y el mecanismo presenta una gran complejidad en el cargador ejecutable. Además, las distribuciones de Linux realmente quieren fomentar que todo el código se compile con -fPIC porque cambiar la dirección base de un ejecutable es una estrategia de mitigación que dificulta la escritura de exploits para las vulnerabilidades de seguridad.

También vale la pena mencionar que -fPIC no es generalmente un costo de rendimiento significativo, especialmente si usa -fisibilidad = oculto o equivalente.

¿por qué no todos los campos aumentaron en tamaño para adaptarse?

El "campo" en cuestión es el campo inmediato de los modos de direccionamiento x86-64, que no está bajo el control de los desarrolladores de ELF.

+0

Gracias por su respuesta, realmente agrega mucho al enlace provisto por @awoodland, particularmente el reconocimiento de que se puede hacer, pero en un momento se vuelve una tontería. Para aclarar: fvisibility = hidden significa que todas las funciones no exportadas explícitamente no serán llamadas a través del PLT y, por lo tanto, se eliminará un nivel de indirección. –

+0

Sí, fvisibility = hidden quita la indirección PLT. – servn

Cuestiones relacionadas