2016-04-18 3 views
14

Что именно делает -rdynamic (или --export-dynamic на уровне компоновщика) и как оно относится к видимости символов, как определено флагами -fvisibility* или видимостью pragma s и __attribute__ s?Что именно делает `-rdynamic` и когда он нужен?

Для --export-dynamic, ld(1) упоминает:

... Если вы используете «dlopen», чтобы загрузить динамический объект, который необходимо передать обратно к символам, определенных программой, а не какой-либо другой динамический , то вам, вероятно, понадобится , чтобы использовать этот параметр при связывании самой программы. ...

Я не уверен, что полностью понимаю это. Не могли бы вы привести пример, который не работает без -rdynamic, но делает с ним?

Edit: Я на самом деле пытался компиляции пару фиктивных библиотек (один файл, несколько файлов, различных -O уровней, некоторые между вызовы функций, некоторые скрытые символы, некоторые видимые), с и без -rdynamic, и до сих пор я получал байт-идентичные выходы (при постоянном сохранении всех остальных флагов), что довольно озадачивает.

ответ

16

Вот простой пример, иллюстрирующий использование -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 
    ./$< 

Здесь bar.c быть приходит общая библиотека libbar.so и main.c становится программой, которая dlopen с libbar и звонит bar() из этой библиотеки. bar() звонки foo(), который является внешним в bar.c и определен в main.c.

Итак, без -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 

И -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

Вы, например, прекрасно понимаете, что означает man-страница. Большое спасибо! – PSkocik

2

Я использую rdynamic распечатать с помощью цепочек вызовов трассировку()/backtrace_symbols() из LIBC.

Без rdynamic вы не можете получить имена функций.

Чтобы узнать больше о backtrace(), прочитайте его здесь. https://www.gnu.org/software/libc/manual/html_node/Backtraces.html