Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Problem getting the GNU linker (ld) to export a symbol

Tags:

gnu

linker

ld

I am using certain GNU tools, i.e. the GNU C++ Compiler (g++) and the GNU Linker (ld) to create a shared library (.so) file as well as a binary executable file.

The binary executable file makes use of the dlopen function to dynamically load the shared library file at runtime. In addition to this, the shared library file needs to invoke a particular class method (called ToolboxManager::registerToolbox) which is defined within the binary executable. This is accommodated by forcing the binary executable to export the class method, which in turn is accomplished at link time by linking the binary executable with the following command line options ;

-Wl,--dynamic-list=${top_srcdir}/dynamic_symbol_table.txt

where the file ${top_srcdir}/dynamic_symbol_table.txt contains the following content ;

{
  extern "C++"
  {
    "ToolboxManager::registerToolbox*";
  };
};

Note the use of the asterisk (*) in the file to force the linker to export all symbols that begin with ToolboxManager::registerToolbox.

When I run the GNU nm utility (nm -C -g ./a.out) on the resulting binary executable, it displays the following information about the afore-mentioned class method ;

08053da0 T ToolboxManager::registerToolbox  
           (  
            std::string&,  
            std::string&,  
            std::map  
            <  
             std::string,  
             Factory_DSPB_Base*,  
             std::less  
             <  
              std::string  
             >,  
             std::allocator  
             <  
              std::pair  
              <  
               std::string const,  
               Factory_DSPB_Base*  
              >  
             >  
            >&  
           )

or, if the nm utility is invoked as above, but this time without the use of the -C command line switch ;

08053da0 T _ZN14ToolboxManager15registerToolboxERSsS0_RSt3mapISsP17Factory_DSPB_BaseSt4lessISsESaISt4pairIKSsS3_EEE

So far, this looks fine. The "T" in front of the definition of the class method ToolboxManager::registerToolbox, denotes that the method resides within the Text/Code section of the file.

Similarly, if I run the nm utility (nm -C -g ./toolbox.so) on the shared library file, it displays the following information about the same afore-mentioned class method ;

U ToolboxManager::registerToolbox
  (
   std::string&,
   std::string&,
   std::map
   <
    std::string,
    Factory_DSPB_Base*,
    std::less
    <
     std::string
    >,
    std::allocator
    <
     std::pair
     <
      std::string const,
      Factory_DSPB_Base*
     >
    >
   >&
  )

This also looks fine. The "U" in front of the definition of the class method ToolboxManager::registerToolbox, denotes that the method is undefined in the shared library file.

However, a problem occurs when I run the binary exectable from the command line and this problem results in the following error message being displayed ;

./toolbox.so: undefined symbol: _ZN14ToolboxManager15registerToolboxERSsS0_RSt3mapISsP17Factory_DSPB_BaseSt4lessISsESaISt4pairIKSsS3_EEE

The mangled class method name which appears in this runtime message is shown below, as the first of the two lines. For comparison purposes, the mangled class method name from above (and which was generated using the the nm -g command) is shown below as the second of the two lines ;

_ZN14ToolboxManager15registerToolboxERSsS0_RSt3mapISsP17Factory_DSPB_BaseSt4lessISsESaISt4pairIKSsS3_EEE

_ZN14ToolboxManager15registerToolboxERSsS0_RSt3mapISsP17Factory_DSPB_BaseSt4lessISsESaISt4pairIKSsS3_EEE

As can be seen, the two mangled names are identical. Therefore, I cannot understand why the undefined symbol cannot be resolved at runtime.

I then re-linked the binary executable, however this time I replaced the following linker command ;

-Wl,--dynamic-list=${top_srcdir}/dynamic_symbol_table.txt

with the this one ;

-Wl,--export-dynamic

The --export-dynamic linker option instructs the GNU Linker to add all the symbols to the dynamic symbol table.

If then ran the binary executable again. This time it executed correctly and the call to the dlopen function did not result in an undefined symbol error. This has me utterly perplexed, as it looks as though the symbol is being exported correctly in the initial version of the binary executable. Is anyone able to see the problem here? Any assistance would be immensely appreciated.

Thanks in advance.

like image 506
Craig Sanders Avatar asked Sep 13 '11 01:09

Craig Sanders


1 Answers

I have managed to solve this problem. I have found that if I remove the quotation marks from the following line ;

"ToolboxManager::registerToolbox*"

within the file ${top_srcdir}/dynamic_symbol_table.txt and then re-link the binary executable, then it works. That is, the dlopen function will not fail anymore.

I can't help but wonder if it would have been more appropriate to ask this question on the GNU binutils mailing list than here on this web-site.

like image 125
Craig Sanders Avatar answered Nov 11 '22 17:11

Craig Sanders