¿Por qué fPIC es absolutamente necesario en plataformas de 64 y no en plataformas de 32 bits?

Recientemente recibí un:

... la reubicación R_X86_64_32 contra "un símbolo local" no se puede utilizar al hacer un objeto compartido; recompilar con -fPIC

Error al intentar compilar un programa como biblioteca compartida.

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

El mejor https://www.youtube.com/watch?v=xB-eutXNUMXJtA&feature=youtu.be Que pude encontrar es:

x86 tiene soporte para reubicaciones de .text (que es lo que sucede cuando tiene un código dependiente de la posición). Este soporte tiene un costo, es decir, que todas las páginas que contienen dicha reubicación básicamente no se comparten, incluso si se encuentran en una biblioteca compartida, lo que arruina el concepto mismo de bibliotecas compartidas. Por lo tanto, decidimos no permitir esto en amd64 (además, crea problemas si el valor necesita más de 32 bits, porque todos los relocs .text solo tienen el tamaño 'word32')

Pero no encuentro esto del todo adecuado. Si se da 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 hubiera que realizar cambios en el formato ELF para admitir 64 bits, ¿por qué no se aumentaron de tamaño todos los campos para adaptarse?

Este 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 sufrir un impacto en el rendimiento yb) esta información nunca fue imposible de encontrar en el ¡primer lugar!

[Editar: 'La respuesta'

@awoodlands https://www.youtube.com/watch?v=xB-eutXNUMXJtA&feature=youtu.be es probablemente la mejor 'respuesta literal', @servn adicional buena información.

En una búsqueda para encontrar más sobre diferentes tipos de reubicaciones, encontré este y finalmente un Referencia de ABI x86_64 (vea la página 68)]

preguntado el 27 de agosto de 11 a las 17:08

No sé la respuesta a su pregunta, pero debe tener en cuenta que el -fPIC el impacto en el rendimiento se reduce en x86-64 (en relación con x86-32) porque tiene más registros, direccionamiento relativo a PC y una ABI que se diseñó teniendo en cuenta el PIC. No voy a decir que es pasado, pero mídelo y te sorprenderá gratamente. -

Ese parece ser el consenso, una pequeña penalización en el rendimiento por lo que sin duda es una gran conveniencia. Tendré que probarlo yo mismo. -

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. -

3 Respuestas

Según tengo entendido, el problema es que x86-64 parece introducir una forma nueva y más rápida de referenciar datos en relación con el puntero de instrucción, que no existía para x86-32.

Este artículo tiene un buen análisis en profundidad y ofrece el siguiente resumen ejecutivo:

La capacidad de x86-64 para usar la compensación relativa del puntero de instrucción a las 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 en usted) debe pasar por una capa de abstracción, es decir, la tabla de compensación global.

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

Respondido 28 ago 11, 00:08

Pero no encuentro esto del todo adecuado. Si se da 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 ... calcular las reubicaciones tiene costos de tiempo de ejecución, los ejecutables reubicados requieren memoria adicional y el mecanismo introduce mucha complejidad en el cargador de ejecutables. Además, las distribuciones de Linux realmente quieren alentar a 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 vulnerabilidades de seguridad.

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

¿Por qué no se aumentaron de tamaño todos los campos para dar cabida?

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.

Respondido 28 ago 11, 06:08

Gracias por su respuesta, realmente agrega mucho al enlace provisto por @awoodland, particularmente el reconocimiento de que enlatado hacerse pero en un momento se vuelve tonto. Para aclarar: fvisibility = hidden significa que todas las funciones que no se exportan explícitamente no se llamarán a través del PLT y, por lo tanto, se elimina un nivel de indirección. - Bojan B

Sí, fvisibility = hidden elimina la indirección PLT. - servn

Puede usar la opción -mcmodel = large para crear bibliotecas compartidas sin -fpic en x86_64

Referencia: http://eli.thegreenplace.net/2012/01/03/understanding-the-x64-code-models/

Respondido 08 Abr '13, 23:04

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.