Which function is used when loading two shared lib

2019-08-01 12:51发布

问题:

I been reading and trying to understand how symbols get resolved within a shared library in Linux. So here is a description of what I am faced with.

I am using an application (APP) that can load user created shared libraries to add features. I have two such libraries, LIB_A.so and LIB_B.so that perform separate things and do not depend on another to work. They are independently compiled and based on the compiler arguments (-fPIC), will seem it will make the symbols interposable (from my research on the topic). So most symbols will be exported by default.

Now, there is this common code that both LIB_A and LIB_B uses that is compiled and statically linked with each library. The common code does not use any namespaces or static functions, so I am assuming they will be exported as well. Both LIB_A and LIB_B load and work as intended in the APP.

But what if there was a bug found inside the common code but only LIB_A can be recompiled because it needs the fixed code. My question is, when LIB_A is recompiled to pick up this change in the common code and get loaded in the APP, would there be separate copies of the common code for both LIB_A (that has the bug fix) and LIB_B (that does not have the bug fix) and each would use their respective copies or would both link and share one of the versions of the common code in both? Is there a way for me to discover the source of the symbol using a debugger perhaps?

To just to get answer questions ahead of time, I do not know which order the libraries will be loaded, I can not recompiled LIB_B to pick up the changes, only LIB_A. I do not have the source code of the APP to know how it's dynamically loading the libraries.

I know there is a great deal with the compiler flags but assume it's just -fPIC, no -fvisibility-hidden, -Wl,-Bsymbolic, -fno-semantic-interposition flags are set. Would these solve this issue if there was a conflict?

I looked at using the nm -D command and I see some of the symbols are W, does that mean it will use an existing symbol if it already exists before using the one that was statically built with the library?

I been reading articles and search, but this one things I am not sure I 100% nailed down.

EDIT For further information, I am loading these libraries at runtime on demand. Would this change anything by using dlopen with RTLD_LOCAL vs RTLD_GLOBAL? From the description, RTLD_LOCAL seems to prevent symbols from being loaded globally and therefore will not conflict or link to other symbols outside of the library?

回答1:

Would there be separate copies of the common code for both LIB_A (that has the bug fix) and LIB_B (that does not have the bug fix)

In absence of -fvisibility=hidden (or other similar flags you mention) runtime linker will ensure that all duplicate symbols are resolved to the same implementation (either in LIB_A or LIB_B). So libs will effectively share code.

Is there a way for me to discover the source of the symbol using a debugger perhaps?

In general, symbols would be taken from the first loaded library that provides them (LIB_A or LIB_B). Libraries will be loaded in the order they are listed in .dynamic section of executable (run readelf -d app to be sure or simply run your app with LD_DEBUG variable set to symbols). If you want to force LIB_A to be loaded first, you can set LD_PRELOAD accordingly.

I know there is a great deal with the compiler flags but assume it's just -fPIC, no -fvisibility-hidden, -Wl,-Bsymbolic, -fno-semantic-interposition flags are set. Would these solve this issue if there was a conflict?

I assume you want each library to use it's own version of common symbols? The most standard way to achieve this is -fvisibility=hidden. This will prevent common symbols from being exported and then they'll be statically resolved to local copies. Of course then you'll need to find and annotate other functions that need to be exported.

-Bsymbolic may also help but this would forcefully resolve all locally resolvable references i.e. you want be able to limit it to a subset of symbols you're interested in. Also it's less widely used.

As for -fno-semantic-interposition, I do not have recent GCC at hand but my impression was that it's an optimization flag for compiler and generally would not guarantee local resolution of symbols.

I looked at using the nm -D command and I see some of the symbols are W, does that mean it will use an existing symbol if it already exists before using the one that was statically built with the library?

No, runtime linker does not take weakness of symbol into account (at least without LD_DYNAMIC_WEAK environment variable which I do not recommend to use).