Find Which Shared Library Defines Symbol on Linux

Find Which Shared Library Defines Symbol on Linux

When linking or debugging software on Linux, you may sometimes face undefined symbol errors. If the application relies on several shared libraries (.so files), determining which one actually provides a specific symbol (function, variable, or other entity) can be challenging. This tutorial shows how to find which shared library defines symbol on Linux.

The nm utility (part of the Binutils suite) lists symbols from object files and libraries. By combining it with find and grep, we can quickly search through all shared libraries on the system to pinpoint where a symbol is defined.

For instance, to find which shared library under /usr/lib provides the symbol gzopen, you can run:

find /usr/lib -name "*.so" -exec bash -c "nm -D --defined-only {} 2>/dev/null | grep gzopen && echo {}" \;

Example output:

0000000000010d20 T gzopen
0000000000010d40 T gzopen64@@ZLIB_1.2.3.3
/usr/lib/x86_64-linux-gnu/libz.so

The result indicates that the symbol gzopen is defined in the libz.so.

Understanding the command:

  • find /usr/lib -name "*.so" - searches recursively within /usr/lib for files ending with .so (shared libraries).
  • -exec bash -c '...' \; - executes the specified Bash command for each file found.
  • nm -D --defined-only {} - lists only defined dynamic symbols (excluding undefined ones) from the current .so file.
  • 2>/dev/null - suppresses error messages, e.g., if nm cannot read a file.
  • grep gzopen - filters results to show only lines containing the symbol name.
  • && echo {} - prints the library path if a match is found.

C++ symbols are often mangled, meaning their names contain additional characters that encode information such as namespaces, classes, and function parameters. To make them readable, pass the -C option to nm.

For example, to determine which shared library in the /usr/lib directory contains the std::filesystem::rename, run:

find /usr/lib -name "*.so" -exec bash -c "nm -DC --defined-only {} 2>/dev/null | grep std::filesystem::rename && echo {}" \;

Example output:

00000000001962f0 T std::filesystem::rename(std::filesystem::path const&, std::filesystem::path const&)@@GLIBCXX_3.4.26
0000000000195580 T std::filesystem::rename(std::filesystem::path const&, std::filesystem::path const&, std::error_code&)@@GLIBCXX_3.4.26
000000000017df70 T std::filesystem::rename(std::filesystem::__cxx11::path const&, std::filesystem::__cxx11::path const&)@@GLIBCXX_3.4.26
000000000017df20 T std::filesystem::rename(std::filesystem::__cxx11::path const&, std::filesystem::__cxx11::path const&, std::error_code&)@@GLIBCXX_3.4.26
/usr/lib/gcc/x86_64-linux-gnu/11/libstdc++.so

This indicates that the std::filesystem::rename symbol defined in the libstdc++.so.

Leave a Comment

Cancel reply

Your email address will not be published.