Que fait exactement -rdynamic
(ou --export-dynamic
au niveau de l'éditeur de liens) faire et comment cela se rapporte-t-il à la visibilité des symboles telle que définie par -fvisibility*
indicateurs ou visibilité pragma
s et __attribute__
s?
Pour --export-dynamic
, ld (1) mentionne:
... Si vous utilisez "dlopen" pour charger un objet dynamique qui doit se référer aux symboles définis par le programme, plutôt qu'à un autre objet dynamique, vous devrez probablement utiliser cette option lors de la liaison du programme lui-même. ...
Je ne suis pas sûr de bien comprendre cela. Pourriez-vous s'il vous plaît fournir un exemple qui ne fonctionne pas sans -rdynamic
mais avec ça?
Edit : J'ai en fait essayé de compiler quelques bibliothèques factices (fichier unique, multi-fichier, divers niveaux -O, certains appels inter-fonctions, certains cachés symboles, certains visibles), avec et sans -rdynamic
, et jusqu'à présent, j'ai obtenu des sorties identiques octets (en gardant tous les autres drapeaux constants bien sûr), ce qui est assez déroutant.
Voici un exemple de projet simple pour illustrer l'utilisation de -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 $@ $<
libbar.so: bar.o
gcc -shared -o $@ $<
main.o: main.c
gcc -c -Wall -o $@ $<
prog: main.o | libbar.so
gcc $(LDEXTRAFLAGS) -o $@ $< -L. -lbar -ldl
clean:
rm -f *.o *.so prog
test: prog
./$<
Ici, bar.c
Devient une bibliothèque partagée libbar.so
Et main.c
Devient un programme qui dlopen
s libbar
et appelle bar()
de cette bibliothèque. bar()
appelle foo()
, qui est externe dans bar.c
et définie dans main.c
.
Donc, sans -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
Et avec -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
J'utilise rdynamic pour imprimer des backtraces en utilisant la backtrace()
/backtrace_symbols()
de Glibc.
Sans -rdynamic
, Vous ne pouvez pas obtenir les noms de fonction.
Pour en savoir plus sur la backtrace()
relisez-la ici .