When building or debugging software on Linux, you may encounter missing symbol errors during linking. If the project depends on multiple static libraries (.a files), it can be tricky to know which library actually contains the symbol (function, variable, or other entity). This tutorial explains how to find which static library defines symbol on Linux.
The nm utility, part of the Binutils package, lists symbols in object files and libraries. By combining it with find and grep, we can automatically search through all static libraries on the system for a specific symbol.
For example, to locate which static library in the /usr/lib directory defines the symbol gz_open, you can run:
find /usr/lib -name "*.a" -exec bash -c "nm --defined-only {} 2>/dev/null | grep gz_open && echo {}" \;
Example output:
0000000000000000 t gz_open
/usr/lib/x86_64-linux-gnu/libz.a
This indicates that the gz_open symbol is present in the libz.a static library.
Breaking down the command:
find /usr/lib -name "*.a"- searches recursively under/usr/libfor all files ending in.a(static libraries).-exec bash -c '...' \;- for each.afile found, execute the command inside the quotes in a new Bash shell.nm --defined-only {}- lists only the symbols that are defined (not undefined) in the current library file{}.2>/dev/null- suppresses error messages, e.g., ifnmcannot read a file.grep gz_open- filters the output to only show lines containing the symbolgz_open.&& echo {}- ifgrepfinds a match, print the name of the library file{}that contains it.
C++ symbols are often mangled, meaning their names include extra characters to encode namespaces, classes, and parameters. To convert them back into a readable format, use the -C option with nm.
For example, to find which static library in the /usr/lib directory contains std::filesystem::rename:
find /usr/lib -name "*.a" -exec bash -c "nm -C --defined-only {} 2>/dev/null | grep std::filesystem::rename && echo {}" \;
Example output:
0000000000000000 T std::filesystem::rename(std::filesystem::path const&, std::filesystem::path const&)
0000000000000000 t std::filesystem::rename(std::filesystem::path const&, std::filesystem::path const&) [clone .cold]
0000000000000000 T std::filesystem::rename(std::filesystem::path const&, std::filesystem::path const&, std::error_code&)
0000000000000000 T std::filesystem::rename(std::filesystem::__cxx11::path const&, std::filesystem::__cxx11::path const&)
0000000000000000 t std::filesystem::rename(std::filesystem::__cxx11::path const&, std::filesystem::__cxx11::path const&) [clone .cold]
0000000000000000 T std::filesystem::rename(std::filesystem::__cxx11::path const&, std::filesystem::__cxx11::path const&, std::error_code&)
/usr/lib/gcc/x86_64-linux-gnu/11/libstdc++.a
This indicates that the symbol is in libstdc++.a.
Leave a Comment
Cancel reply