web-dev-qa-db-fra.com

Que fait exactement `-rdynamic` et quand est-il exactement nécessaire?

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é pragmas 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.

35
PSkocik

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 dlopens 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
51
Mike Kinghan

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 .

8
deep_rugs