2009-05-02 11 views
57

Al compilar bibliotecas compartidas en gcc, la opción -fPIC compila el código como independiente de la posición. ¿Hay alguna razón (rendimiento o no) por la cual no compilaría todas las posiciones de códigos independientes?¿Por qué no todo el código compilado es independiente de la posición?

+1

Pero wowest no es del todo correcto. Muchas llamadas de función y saltos usan saltos relativos, por lo que ni siquiera necesitan una tabla de salto después de moverse. – Unknown

+0

mirando el código ensamblador generado parece que la dirección de la función se carga cuando aparece un código que no es fpico, es simplemente un salto. ¿Estoy malinterpretando tu declaración? – ojblass

+0

@ojblass lo que quiero decir es que algunos saltos son como "saltar 50 instrucciones antes que aquí" o "saltar 5 instrucciones hacia atrás" en lugar de "saltar a 0x400000". Por lo tanto, decir que tiene que cargar una dirección cada vez con -fPIC no es del todo cierto. – Unknown

Respuesta

45

Se añade una indirección. Con el código de posición independiente, debes cargar la dirección de tu función y luego saltar a ella. Normalmente, la dirección de la función ya está presente en la secuencia de instrucciones.

+2

Elegido por simplicidad. – ojblass

24

Sí, hay motivos de rendimiento. Algunos accesos están efectivamente bajo otra capa de indirección para obtener la posición absoluta en la memoria.

También está el GOT (tabla de compensación global) que almacena compensaciones de variables globales. Para mí, esto parece una tabla de corrección de IAT, que está clasificada como dependiente de la posición por wikipedia y algunas otras fuentes.

http://en.wikipedia.org/wiki/Position_independent_code

+1

Estoy votando pero seleccionando el otro por pura simplidumbre. – ojblass

1

Además, el hardware de memoria virtual en la mayoría de los procesadores modernos (utilizado por la mayoría de los SO modernos) significa que gran cantidad de código (todas las aplicaciones de espacio de usuario, salvo el uso peculiar de mmap o similar) no necesitan ser independientes de posición. Cada programa obtiene su propio espacio de direcciones que piensa que comienza en cero.

+0

¿Es más fácil codificar esas aplicaciones de esa manera? – ojblass

+3

Pero incluso con un VM-MMU, el código PIC es necesario para garantizar que la misma biblioteca .so se cargue solo una vez en la memoria cuando sea utilizada por diferentes ejecutables. – mmmmmmmm

14

Además de la respuesta aceptada. Una cosa que perjudica mucho el rendimiento del código PIC es la falta de "direccionamiento relativo de IP" en x86. Con el "direccionamiento relativo de IP", puede solicitar datos que sean X bytes del puntero de instrucción actual. Esto haría que el código PIC sea mucho más simple.

Los saltos y las llamadas, por lo general son EIP relativos, por lo que realmente no suponen un problema. Sin embargo, acceder a los datos requerirá un pequeño truco extra. A veces, un registro se reservará temporalmente como un "puntero base" a los datos que el código requiere. Por ejemplo, una técnica común es abusar de la forma en que funcionan las llamadas en x86:

call label_1 
.dd 0xdeadbeef 
.dd 0xfeedf00d 
.dd 0x11223344 
label_1: 
pop ebp   ; now ebp holds the address of the first dataword 
        ; this works because the call pushes the **next** 
        ; instructions address 
        ; real code follows 
mov eax, [ebp + 4] ; for example i'm accessing the '0xfeedf00d' in a PIC way 

Ésta y otras técnicas de añadir una capa de direccionamiento indirecto a los datos de accesos. Por ejemplo, el GOT (tabla de compensación global) utilizado por los compiladores gcc.

x86-64 agregó un modo "RIP relative" que hace que las cosas sean lot simpler.

+1

IIRC MIPS no tiene direcciones relativas a PC, excepto saltos relativos –

2

Porque la implementación de código completamente independiente de posición agrega una restricción al generador de código que puede evitar el uso de operaciones más rápidas, o agrega pasos adicionales para preservar esa restricción.

Esto podría ser una compensación aceptable para obtener multiprocesamiento sin un sistema de memoria virtual, donde confíe en que los procesos no invaden la memoria de los demás y pueden necesitar cargar una aplicación en particular en cualquier dirección base.

En muchos sistemas modernos las compensaciones de rendimiento son diferentes, y un cargador de reubicación a menudo es menos costoso (cuesta cualquier código de tiempo que se cargue primero) que lo mejor que un optimizador puede hacer si tiene dominio libre. Además, la disponibilidad de espacios de direcciones virtuales oculta la mayor parte de la motivación para la independencia de posición en primer lugar.

21

This article explica cómo funciona PIC y lo compara con la alternativa - load time relocation. Creo que es relevante para tu pregunta.

+4

publicación relevante! = Respuesta – Nick

+10

@Nick: No estoy de acuerdo. Si ayuda al asker, es una respuesta. Señalar un artículo relevante o dos puede proporcionar una gran cantidad de información. –

+3

No hay conclusión en esta publicación, solo un enlace a un artículo. Ni siquiera una pista de que el PIC no se utiliza de forma predeterminada debido a problemas de rendimiento. – Nick

1

position-independent code tiene una sobrecarga de rendimiento en la mayoría de la arquitectura, ya que requiere un registro adicional.

Por lo tanto, esto es para fines de rendimiento.

0

En la actualidad, el sistema operativo y el compilador establecen por defecto todo el código como código de posición independiente. Intenta compilar sin el distintivo -fPIC, el código se compilará bien, pero recibirás una advertencia. Las ventanas similares a OS usan una técnica llamada asignación de memoria para lograr esto.

Cuestiones relacionadas