Can you compile a shared object to prefer local symbols even if it's being loaded by a program compiled with -rdynamic?

落花浮王杯 提交于 2019-12-01 05:49:33

Have you tried -Bsymbolic linker option (or -Bsymbolic-functions)? Quoting from ld man:

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

It seems to solve the problem:

$ 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

A common solution for this problem is to not actually depend on a global symbol not being overriden. Instead do the following:

  • Call the function bar from your library mylib_bar or something like that
  • Hide mylib_bar with __attribute__((visibility("hidden"))) or similar
  • Make bar a weak symbol, referring to mylib_bar like this:

    #pragma weak bar = mylib_bar
    
  • Make your library call mylib_bar everywhere instead of bar

Now everything works as expected:

  • When your library calls mylib_bar, this always refers to the definition in the library as the visibility is hidden.
  • When other code calls bar, this calls mylib_bar by default.
  • If someone defines his own bar, this overrides bar but not mylib_bar, leaving your library untouched.
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!