2011-09-04 9 views
12

Hice un fragmento de código que consiste en una biblioteca dinámica (lib.c) y un ejecutable principal (main.c). En ambos archivos defino una variable global llamada: int global. No es muy inteligente pero no es la pregunta.Variables globales, bibliotecas compartidas y -fPIC efecto

Cuando puedo compilar la biblioteca dinámica de la opción -fPIC parece obligatorios:

gcc lib.c -fPIC -shared -o lib.so 

de lo contrario me sale:

/usr/bin/ld: /tmp/ccpUvIPj.o: relocation R_X86_64_32 against '.rodata' can not be used when making a shared object; recompile with -fPIC 

Cuando puedo compilar el ejecutable no lo es.

gcc main.c -fPIC -ldl 
gcc main.c -ldl 

Ambos funcionan, pero tienen comportamientos diferentes que no puedo explicar, ¿o sí? :

con -fPIC, global en main.c y global en lib.c son las mismas variables:

global main: 23 (0x601050) 
global lib: 23 (0x601050) 

sin -fPIC, global en lib.c no se correlaciona con global en main.c :

global main: 23 (0x601048) 
global lib: 0 (0x7f7742e64028) 

Aquí está la fuente:

lib.c

#include <stdio.h> 
#include <stdlib.h> 

int global; 

int f_one() { 

    printf("global lib: %d (%p)\n", global, &global); 

    return EXIT_SUCCESS; 
} 

main.c

#include <stdio.h> 
#include <stdlib.h> 
#include <dlfcn.h> 

void * handle; 
int global; 

int main() { 

    int q = 7; 

    int (* f_one_p)(int a) = NULL; 

    global = 23; 

    handle = dlopen("./lib.so", RTLD_NOW); 

    if (handle == 0) { 
     return EXIT_FAILURE; 
    } 

    f_one_p = dlsym(handle, "f_one"); 

    printf("global main: %d (%p)\n", global, &global); 

    f_one_p(q); 

    return EXIT_SUCCESS; 

} 

gcc --version: gcc (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2

uname -a: xxx Linux 2.6.38-11-generiC# 48-Ubuntu SMP Vie Jul 29 de 2011 19:02:55 GMT x86_64 x86_64 x86_64 GNU/Linux

edición: código de prueba bajo SUN/SPARC y x86/arquitecturas de Linux con el mismo tipo de variables globales compartidas (con inesperados -fPIC).

+0

Relacionados: http://stackoverflow.com/q/7216244/168175 – Flexo

Respuesta

7

Al compilar con -fPIC, el objeto en cuestión determinará la dirección de los símbolos globales utilizando Tabla de compensación global. Sin embargo, lo que ocurre cuando parte del código es -fPIC y la parte no lo es, es que uno de sus int global s usará esta tabla para determinar la dirección, mientras que la otra parte no.

Si tenía dos objetos compartidos vinculados con -fPIC, pero su programa principal no, entonces todavía tendría dos direcciones para int global, una usando la tabla de compensación global y otra que era solo local para el código que no era PIC.

Hay un really great discussion on PIC vs pic vs non PIC si desea leer más.

1

De forma predeterminada, al construir un archivo ejecutable, las referencias a variables se realizan internamente, con un desplazamiento fijo y sin reubicación.

Sin embargo, está pasando -fPIC y el acceso a los datos globales se convierte en acceso a través de GOT y se añaden las reubicaciones GOT.

Cuestiones relacionadas