2016-04-18 39 views
14

Che cosa fa esattamente -rdynamic (o --export-dynamic a livello di linker) e come si riferisce alla visibilità dei simboli definita dai flag -fvisibility* o dalla visibilità pragma s e __attribute__ s?Che cosa fa esattamente `-rdynamic` e quando è esattamente necessario?

Per --export-dynamic, ld(1) menzioni:

... Se si utilizza "dlopen" per caricare un oggetto dinamico che deve rinviare ai simboli definiti dal programma, piuttosto che qualche altra dinamica oggetto, quindi sarà probabilmente necessario utilizzare questa opzione quando si collega il programma stesso. ...

Non sono sicuro di averlo capito completamente. Potresti fornire un esempio che non funzioni senza -rdynamic ma con esso?

Edit: realtà ho provato la compilazione di un paio di librerie fittizie (file singolo, multi-file, diversi livelli di -O, alcune chiamate inter-funzione, alcuni simboli nascosti, alcuni visibili), con e senza -rdynamic, e fino ad ora ho ottenuto output identici al byte (mantenendo ovviamente tutte le altre bandiere ovviamente), il che è piuttosto sconcertante.

risposta

16

Ecco un semplice esempio di progetto per illustrare l'uso di -rdynamic.

bar.c

extern void foo(void); 

void bar(void) 
{ 
    foo(); 
} 

main.c

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

void foo(void) 
{ 
    puts("Hello world"); 
} 

int main(void) 
{ 
    void * dlh = dlopen("./libbar.so", RTLD_NOW); 
    if (!dlh) { 
     fprintf(stderr, "%s\n", dlerror()); 
     exit(EXIT_FAILURE); 
    } 
    void (*bar)(void) = dlsym(dlh,"bar"); 
    if (!bar) { 
     fprintf(stderr, "%s\n", dlerror()); 
     exit(EXIT_FAILURE); 
    } 
    bar(); 
    return 0; 
} 

Makefile

.PHONY: all clean test 

LDEXTRAFLAGS ?= 

all: prog 

bar.o: bar.c 
    gcc -c -Wall -fpic -o [email protected] $< 

libbar.so: bar.o 
    gcc -shared -o [email protected] $< 

main.o: main.c 
    gcc -c -Wall -o [email protected] $< 

prog: main.o | libbar.so 
    gcc $(LDEXTRAFLAGS) -o [email protected] $< -L. -lbar -ldl 

clean: 
    rm -f *.o *.so prog 

test: prog 
    ./$< 

Qui, bar.c essere arriva una libreria condivisa libbar.so e main.c diventa un programma che dlopen s libbar e chiama bar() da quella libreria. bar() chiamate foo(), che è esterno in bar.c e definito in main.c.

Così, senza -rdynamic:

$ make test 
gcc -c -Wall -o main.o main.c 
gcc -c -Wall -fpic -o bar.o bar.c 
gcc -shared -o libbar.so bar.o 
gcc -o prog main.o -L. -lbar -ldl 
./prog 
./libbar.so: undefined symbol: foo 
Makefile:23: recipe for target 'test' failed 

E con -rdynamic:

$ make clean 
rm -f *.o *.so prog 
$ make test LDEXTRAFLAGS=-rdynamic 
gcc -c -Wall -o main.o main.c 
gcc -c -Wall -fpic -o bar.o bar.c 
gcc -shared -o libbar.so bar.o 
gcc -rdynamic -o prog main.o -L. -lbar -ldl 
./prog 
Hello world 
+0

L'esempio rende perfettamente chiaro cosa significa la manpage. Molte grazie! – PSkocik