gpt4 book ai didi

您能否编译一个共享对象以优先使用本地符号,即使它是由使用 -rdynamic 编译的程序加载的?

转载 作者:IT王子 更新时间:2023-10-29 00:47:47 27 4
gpt4 key购买 nike

我正在用 C 语言构建一个共享库,该库由我没有源代码访问权限的程序动态加载。目标平台是 64 位 Linux 平台,我们使用 gcc 来构建。我能够在大约 100 行内构建该问题的重现,但它仍然有点难以阅读。希望它是说明性的。

核心问题是我在共享库中定义了两个非静态函数(barbaz)。两者都需要是非静态的,因为我们希望调用者能够对它们进行 dlsym。此外,baz 调用 bar。使用我的库的程序还有一个名为 bar 的函数,这通常不是问题,但调用程序是用 -rdynamic 编译的,因为它有需要在我的共享库中调用的函数 foo。结果是我的共享库最终在运行时链接到调用程序的 bar 版本,产生了不直观的结果。

在理想情况下,我可以在编译我的共享库时包含一些命令行开关,以防止这种情况发生。

我目前的解决方案是将我的非静态函数重命名为 funname_local 并将它们声明为静态的。然后我定义了一个新函数:funname() { 返回 funname_local(); },并将我的共享库中对 funname 的任何引用更改为 funname_local。这行得通,但感觉很麻烦,我更愿意告诉链接器更喜欢在本地编译单元中定义的符号。

内部.c

#include <stdio.h>
#include "internal.h"

void
bar(void)
{
printf("I should only be callable from the main program\n");
}

内部.h

#if !defined(__INTERNAL__)
#define __INTERNAL__

void
bar(void);

#endif /* defined(__INTERNAL__) */

主.c

#include <dlfcn.h>
#include <stdio.h>
#include "internal.h"

void
foo(void)
{
printf("It's important that I am callable from both main and from any .so "
"that we dlopen, that's why we compile with -rdynamic\n");
}

int
main()
{
void *handle;
void (*fun1)(void);
void (*fun2)(void);
char *error;

if(NULL == (handle = dlopen("./shared.so", RTLD_NOW))) { /* Open library */
fprintf(stderr, "dlopen: %s\n", dlerror());
return 1;
}
dlerror(); /* Clear any existing error */

*(void **)(&fun1) = dlsym(handle, "baz"); /* Get function pointer */
if(NULL != (error = dlerror())) {
fprintf(stderr, "dlsym: %s\n", error);
dlclose(handle);
return 1;
}
*(void **)(&fun2) = dlsym(handle, "bar"); /* Get function pointer */
if(NULL != (error = dlerror())) {
fprintf(stderr, "dlsym: %s\n", error);
dlclose(handle);
return 1;
}

printf("main:\n");
foo();
bar();
fun1();
fun2();

dlclose(handle);
return 0;
}

主要.h

#if !defined(__MAIN__)
#define __MAIN__

extern void
foo(void);

#endif /* defined(__MAIN__) */

共享.c

#include <stdio.h>
#include "main.h"

void
bar(void)
{
printf("bar:\n");
printf("It's important that I'm callable from a program that loads shared.so"
" as well as from other functions in shared.so\n");
}

void
baz(void)
{
printf("baz:\n");
foo();
bar();
return;
}

编译:

$ gcc -m64 -std=c89 -Wall -Wextra -Werror -pedantic -o main main.c internal.c -l dl -rdynamic
$ gcc -m64 -std=c89 -Wall -Wextra -Werror -pedantic -shared -fPIC -o shared.so shared.c

运行:

$ ./main
main:
It's important that I am callable from both main and from any .so that we dlopen, that's why we compile with -rdynamic
I should only be callable from the main program
baz:
It's important that I am callable from both main and from any .so that we dlopen, that's why we compile with -rdynamic
I should only be callable from the main program
bar:
It's important that I'm callable from a program that loads shared.so as well as from other functions in shared.so

最佳答案

您是否尝试过 -Bsymbolic 链接器选项(或 -Bsymbolic-functions)?引用自 ld 人:

-Bsymbolic

When creating a shared library, bind references to global symbols to the definition within the shared library, if any. Normally, it is possible for a program linked against a shared library to override the definition within the shared library. This option can also be used with the --export-dynamic option, when creating a position independent executable, to bind references to global symbols to the definition within the executable. This option is only meaningful on ELF platforms which support shared libraries and position independent executables.

似乎解决了问题:

$ gcc -m64 -std=c89 -Wall -Wextra -Werror -pedantic -shared -fPIC -o shared.so shared.c
$ gcc -m64 -std=c89 -Wall -Wextra -Werror -pedantic -o main main.c internal.c -l dl -rdynamic
$ ./main
main:
It's important that I am callable from both main and from any .so that we dlopen, that's why we compile with -rdynamic
I should only be callable from the main program
baz:
It's important that I am callable from both main and from any .so that we dlopen, that's why we compile with -rdynamic
I should only be callable from the main program
bar:
It's important that I'm callable from a program that loads shared.so as well as from other functions in shared.so
$ gcc -m64 -std=c89 -Wall -Wextra -Werror -pedantic -shared -fPIC -Wl,-Bsymbolic -o shared.so shared.c
$ ./main
main:
It's important that I am callable from both main and from any .so that we dlopen, that's why we compile with -rdynamic
I should only be callable from the main program
baz:
It's important that I am callable from both main and from any .so that we dlopen, that's why we compile with -rdynamic
bar:
It's important that I'm callable from a program that loads shared.so as well as from other functions in shared.so
bar:
It's important that I'm callable from a program that loads shared.so as well as from other functions in shared.so

关于您能否编译一个共享对象以优先使用本地符号,即使它是由使用 -rdynamic 编译的程序加载的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39477163/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com