¿Por qué no todo el código compilado es independiente de la posición?

4 minutos de lectura

Al compilar bibliotecas compartidas en gcc, la opción -fPIC compila el código como posición independiente. ¿Hay alguna razón (rendimiento o de otro tipo) por la que no compilaría todas las posiciones del código de forma independiente?

  • Pero wowest no es del todo correcto. Muchas llamadas a funciones y saltos usan saltos relativos, por lo que ni siquiera necesitan una tabla de saltos después de moverse.

    – Desconocido

    2 de mayo de 2009 a las 2:47

  • mirando el código ensamblador generado, parece que la dirección de la función está cargada, mientras que el código no fpic parece que es simplemente un salto. ¿Estoy malinterpretando su afirmación?

    – ojblass

    2 de mayo de 2009 a las 5:21

  • @ojblass lo que quiero decir es que algunos saltos son como “saltar 50 instrucciones por delante de aquí” o “saltar 5 instrucciones hacia atrás” en lugar de “saltar a 0x400000”. Entonces, decir que tiene que cargar una dirección cada vez con -fPIC no es del todo cierto.

    – Desconocido

    2 de mayo de 2009 a las 5:47

  • la wikipedia artículo proporciona una buena descripción. Básicamente, en algunas arquitecturas no existe una forma directa de saltar a una dirección relativa. Por lo tanto, PIC es más caro de usar en esos arhcs. Consulte la respuesta de @EvanTeran para obtener más información.

    – Alexei Sholik

    25 de agosto de 2013 a las 15:05


Añade una indirección. Con el código independiente de la posición, debe cargar la dirección de su función y luego saltar a ella. Normalmente, la dirección de la función ya está presente en el flujo de instrucciones.

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

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

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

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 son X bytes del puntero de instrucción actual. Esto simplificaría mucho el código PIC.

Los saltos y las llamadas suelen ser relativos a EIP, por lo que realmente no representan un problema. Sin embargo, acceder a los datos requerirá un pequeño truco adicional. A veces, un registro se reservará temporalmente como un “puntero base” a los datos que requiere el código. 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

Esta y otras técnicas añaden una capa de direccionamiento indirecto a los accesos a los datos. Por ejemplo, la GOT (tabla de compensación global) utilizada por los compiladores gcc.

x86-64 agregó un modo “RIP relativo” que hace que las cosas sean lote más simple

  • IIRC MIPS tampoco tiene direccionamiento relativo a PC, excepto por saltos relativos

    – phuclv

    8 de agosto de 2014 a las 8:17

  • Esta es una técnica común utilizada en shellcode para obtener la dirección desde la que se está ejecutando. He usado esto en algunas soluciones CTF.

    – sherrellbc

    24 de marzo de 2018 a las 0:53


position-independent code tiene una sobrecarga de rendimiento en la mayoría de las arquitecturas, porque requiere un registro adicional.

Por lo tanto, esto es para fines de rendimiento.

Además, el hardware de memoria virtual en la mayoría de los procesadores modernos (utilizado por la mayoría de los sistemas operativos modernos) significa que una gran cantidad de código (todas las aplicaciones del espacio del usuario, salvo el uso peculiar de mmap o similares) no necesita ser independiente de la posición. Cada programa obtiene su propio espacio de direcciones que cree que comienza en cero.

  • Pero incluso con un código PIC de VM-MMU, se necesita garantizar que la misma biblioteca .so se carga solo una vez en la memoria cuando la usan diferentes ejecutables.

    – mmmmmmmm

    27 de mayo de 2009 a las 18:26

¿Por que no todo el codigo compilado es independiente de
Govardhan Murali

Hoy en día, el sistema operativo y el compilador por defecto hacen que todo el código sea independiente de la posición. Intente compilar sin el indicador -fPIC, el código se compilará bien pero solo recibirá una advertencia. Los sistemas operativos como Windows usan una técnica llamada mapeo de memoria para lograr esto.

  • Pero incluso con un código PIC de VM-MMU, se necesita garantizar que la misma biblioteca .so se carga solo una vez en la memoria cuando la usan diferentes ejecutables.

    – mmmmmmmm

    27 de mayo de 2009 a las 18:26

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad