-rdynamic`的功能是什么?何时需要? [英] What exactly does `-rdynamic` do and when exactly is it needed?

查看:1232
本文介绍了-rdynamic`的功能是什么?何时需要?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

-rdynamic(或在链接器级别的--export-dynamic)到底是做什么的,它与-fvisibility*标志或可见性pragma s和__attribute__ s定义的符号可见性有什么关系? >

对于--export-dynamic ld(1)提到:

... 如果使用"dlopen"加载动态对象,则需要回溯 到程序定义的符号,而不是其他动态 对象,那么您可能需要 在链接程序本身时使用此选项. ...

我不确定我是否完全理解这一点.您能否提供一个没有-rdynamic不能使用但可以使用的示例?

修改: 我实际上尝试过使用-rdynamic和不使用-rdynamic编译几个虚拟库(单个文件,多个文件,各种-O级别,一些函数间调用,一些隐藏符号,一些可见). (在保持所有其他标志不变的情况下)获得与字节相同的输出,这非常令人困惑.

解决方案

下面是一个简单的示例项目,用于说明-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成为共享库 一个dlopen s 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

What exactly does -rdynamic (or --export-dynamic at the linker level) do and how does it relate to symbol visibility as defined by the -fvisibility* flags or visibility pragmas and __attribute__s?

For --export-dynamic, ld(1) mentions:

... If you use "dlopen" to load a dynamic object which needs to refer back to the symbols defined by the program, rather than some other dynamic object, then you will probably need to use this option when linking the program itself. ...

I'm not sure I completely understand this. Could you please provide an example that doesn't work without -rdynamic but does with it?

Edit: I actually tried compiling a couple of dummy libraries (single file, multi-file, various -O levels, some inter-function calls, some hidden symbols, some visible), with and without -rdynamic, and so far I've been getting byte-identical outputs (when keeping all other flags constant of course), which is quite puzzling.

解决方案

Here is a simple example project to illustrate the use of -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
    ./$<

Here, bar.c becomes a shared library libbar.so and main.c becomes a program that dlopens libbar and calls bar() from that library. bar() calls foo(), which is external in bar.c and defined in main.c.

So, without -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

And with -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`的功能是什么?何时需要?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆