views:

795

answers:

3

I've got an application that loads .so files as plugins at startup, using dlopen()

The build environment is running on x86 hardware, but the application is being cross compiled for another platform.

It would be great if I could (as part of the automated build process) do a check to make sure that there aren't any unresolved symbols in a combination of the .so files and the application, without having to actually deploy the application.

Before I write a script to test symbols using the output of nm, I'm wondering if anyone knows of a utility that already does this?


edit 1: changed the description slightly - I'm not just trying to test symbols in the .so, but rather in a combination of several .so's and the application itself - ie. after the application loaded all of the .so's whether there would still be unresolved symbols.

As has been suggested in answers (thanks Martin v. Löwis and tgamblin), nm will easily identify missing symbols in a single file but won't easily identify which of those symbols has been resolved in one of the other loaded modules.

+1  A: 

Ideally, a cross-nm tool is part of your cross-compiler suite. For example, if you build GNU binutils for cross-compilation, a cross-nm will be provided as well (along with a cross-objdump).

Martin v. Löwis
+1  A: 

Could you use a recursive version of ldd for this? Someone seems to have written a script that might help. This at least tell you that all the dependency libs could be resolved, if they were specified in the .so correctly in the first place. You can guarantee that all the dependencies are referenced in the .so with linker options, and this plus recursive ldd would guarantee you no unresolved symbols.

Linkers will often have an option to make unresolved symbols in shared libraries an error, and you could use this to avoid having to check at all. For GNU ld you can just pass --no-allow-shlib-undefined and you're guaranteed that if it makes a .so, it won't have unresolved symbols. From the GNU ld docs:

   --no-undefined
       Report  unresolved  symbol  references  from regular object files.
       This is done even if the linker is creating a non-symbolic shared 
       library.  The switch --[no-]allow-shlib-undefined controls the 
       behaviour for reporting  unresolved references found in shared
       libraries being linked in.

   --allow-shlib-undefined
   --no-allow-shlib-undefined
       Allows (the default) or disallows undefined symbols in shared 
       libraries.  This switch is  similar  to  --no-undefined  except
       that  it determines the behaviour when the undefined symbols are
       in a shared library rather than a regular object file.  It does 
       not affect how undefined symbols in regular object files are 
       handled.

       The reason that --allow-shlib-undefined is the default is that the 
       shared library being specified  at  link  time may  not  be  the  
       same as the one that is available at load time, so the symbols might 
       actually be resolvable at load time.  Plus there are some systems, 
       (eg BeOS) where undefined symbols in shared libraries is  normal.   
       (The kernel patches them at load time to select which function is most
       appropriate for the current architecture.  This is used for example to
       dynamically select an appropriate memset function).  Apparently it is 
       also normal for HPPA shared libraries to have undefined symbols.

If you are going to go with a post-link check, I agree with Martin that nm is probably your best bet. I usually just grep for ' U ' in the output to check for unresolved symbols, so I think it would be a pretty simple script to write.

tgamblin
A: 

The restrictions in ldd turned out to mean that it wasn't possible to use for a comprehensive symbol checker. In particular, ldd would only list exported symbols.

However, readelf will produce a comprehensive list, along with all of the library dependencies.

Using readelf it was possible to build up a script that would: Create a list of all of the libraries used, Build up a list of symbols in an executable (or .so) Build up a list of unresolved symbols - if there are any unresolved symbols at this point, there would have been an error at load time.

This is then repeated until no new libraries are found.

If this is done for the executable and all of the dlopen()ed .so files it will give a good check on unresolved dependencies that would be encountered at run time.

Andrew Edgecombe