Что именно делает "- rdynamic " и когда именно это необходимо?

что именно -rdynamic (или --export-dynamic на уровне компоновщика) и как это связано с видимостью символа, определенной -fvisibility* флаги или видимость pragmas и __attribute__s?

на --export-dynamic, ld (1) отмечает:

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

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

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

2 ответов


вот простой пример проекта, чтобы проиллюстрировать использование -rdynamic.

бар.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;
}

make-файл

.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
    ./$<

здесь bar.c становится общей библиотеки libbar.so и main.c будет программы dlopens 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

Я использую rdynamic для печати обратных следов с помощью backtrace()/backtrace_symbols() из Glibc.

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

чтобы узнать больше об backtrace() читаем здесь.