Symbol conflict, hiding and mandatory use of library symbols in dynamic libraries under linux

The problem of symbol conflict was encountered when docking with the customer.

Our company provides customers with sdk packages for development and use, which are several so files. In the so files, our company encapsulates the tinyxml2 library. The customers also use the tinyxml2 library when they do development, but the versions used are different. , causing it to crash when running again. It should be that when the program is running, their tinyxml library is loaded first, and then our sdk is looking for the relevant symbols of the tinyxml library and finds the symbols of their library.


 SIGSEGV : 段错误
16 stack frames.
./test.out() [0x804e314]
[0x618400]
/lib/libc.so.6() [0x7a07b0]
./test.out(_ZN8tinyxml28DynArrayIPKcLi10EE14EnsureCapacityEi+0x4f) [0x8054c87]
./test.out(_ZN8tinyxml28DynArrayIPKcLi10EE4PushES2_+0x1e) [0x80548a4]
./test.out() [0x8052fac]
./test.out(_ZN8tinyxml210XMLPrinter10VisitEnterERKNS_10XMLElementEPKNS_12XMLAttributeE+0x21) [0x80536f1]
./test.out(_ZNK8tinyxml210XMLElement6AcceptEPNS_10XMLVisitorE+0x29) [0x8051fcf]
./libnmchelper.so(+0x61336) [0xc8a336]
./libnmchelper.so(+0x421df) [0xc6b1df]
./libnmchelper.so(+0x38fd6) [0xc61fd6]
./libnmchelper.so(+0x37a91) [0xc60a91]
./libnmchelper.so(nmc_login+0x56) [0xc7d85c]
./test.out() [0x804ee09]
/lib/libc.so.6(__libc_start_main+0xe6) [0x680ce6]
./test.out() [0x804e0e1]



*** glibc detected *** ./test.out: munmap_chunk(): invalid pointer: 0xbf9252c4 ***
======= Backtrace: =========
/lib/libc.so.6[0x6dae31]
/usr/lib/libstdc++.so.6(_ZdlPv+0x22)[0x3a26552]
./test.out(_ZN8tinyxml211XMLDocumentD0Ev+0x1c)[0x805229c]
./libnmchelper.so(_ZN8tinyxml211XMLDocument5ParseEv+0x85)[0xbdc987]
./libnmchelper.so(+0x626e4)[0xbdc6e4]
./libnmchelper.so(+0x3da59)[0xbb7a59]
./libnmchelper.so(+0x33fc9)[0xbadfc9]
./libnmchelper.so(+0x32715)[0xbac715]
./libnmchelper.so(nmc_login+0x65)[0xbcbc46]
./test.out[0x804ee09]
/lib/libc.so.6(__libc_start_main+0xe6)[0x680ce6]
./test.out[0x804e0e1]


After a period of exploration, the first solution is as follows:

First of all, we require the so file to use the symbols in its own library file first, so the -Wl, -Bsymbolic parameter is used in the compilation, which is a link parameter, which will be passed to the linker ld for use, telling so to use the symbols in the library first .


Translation:

-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 is only meaningful on ELF platforms which support shared libraries.

When creating a dynamic library, if there is a reference to a global symbol, the reference is bound to the definition in the dynamic library. Often, programs linking against a dynamic library are defined by symbols that may overwrite the dynamic library. This option is only useful on platforms that support ELF format dynamic libraries.


Secondly, we also need to consider that if the symbols of our own library are loaded first, they will not overwrite the symbols of other libraries or programs. Therefore, we need to hide the symbols that do not need to be exported, and only export the symbols that need to be used externally.

Here we use the -fvisibility=hidden parameter to hide symbols at compile time, but only in this way will hide all symbols in the library, including the functions needed by the caller, so we add the functions and variables that need to be exported. superior

__attribute__ ((visibility ("default"))) attribute so that exported functions can be used.

For convenience, the macro definition is defined as follows

[cpp]  view plain copy  
  1. #ifdef WIN32 //windows platform  
  2.   
  3. #ifdef NMC_USER_MODULE_EXPORTS  
  4. #define NMC_API __declspec(dllexport)  
  5. #else  
  6. #define NMC_API __declspec(dllimport)  
  7. #endif  
  8.   
  9. #ifndef NMC_CALL_TYPE  
  10. #define NMC_CALL_TYPE   __stdcall    
  11. #endif  
  12.   
  13. #else //linux platform  
  14.   
  15. #ifndef NMC_API  
  16. #define NMC_API __attribute__ ((visibility ("default")))  
  17. #endif  
  18.   
  19. #ifndef NMC_CALL_TYPE  
  20. #define NMC_CALL_TYPE  
  21. #endif  
  22.   
  23. #endif  

http://gcc.gnu.org/wiki/Visibility

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326071856&siteId=291194637