web-dev-qa-db-ja.com

`-rdynamic`は何を正確に行い、いつ必要になるのですか?

-rdynamic(またはリンカーレベルで--export-dynamic)が正確に行うことと、-fvisibility*フラグまたは可視性pragmasおよび__attribute__s?

--export-dynamicの場合、 ld(1) 言及:

...「dlopen」を使用して、他の動的オブジェクトではなく、プログラムで定義されたシンボルを参照する必要がある動的オブジェクトをロードする場合、おそらくプログラム自体をリンクするときにこのオプションを使用する必要があります。 ...

私はこれを完全に理解しているかどうかはわかりません。 -rdynamicなしでは機能しないが、それで機能する例を提供してください。

Edit:実際にいくつかのダミーライブラリ(シングルファイル、マルチファイル、さまざまな-Oレベル、いくつかの関数間呼び出し、いくつかの非表示)をコンパイルしようとしましたシンボル、いくつかは可視)、-rdynamicの有無にかかわらず、これまでのところbyte-identical出力(他のすべてを保持する場合)フラグ定数はもちろん)、これは非常に不可解です。

35
PSkocik

_-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;
}
_

メイクファイル

_.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
_
51
Mike Kinghan

Glibcのbacktrace()/backtrace_symbols()を使用して、rdynamicを使用してバックトレースを出力します。

_-rdynamic_がないと、関数名を取得できません。

backtrace()の詳細については、 here をお読みください。

8
deep_rugs