Compilation completes, the linker comes in and surprise!
/bin/ld: path/to/libfoo.so: undefined reference to `some_symbol`
error: ld returned 1 exit status
The linker cannot find some symbols used in the program from third-party libraries. This errors usually happens due to:
- the list of linker flags (
-l
) lacks the library name providing those missing symbols, being either shared or static libraries - the collection of shared libraries used by the linker do not depend (or have a broken dependency) on the library providing those missing symbols
Listing symbols in library
The nm
command in GNU Linux is the common tool used to print all symbols found in a shared library:
Shared libraries
$ nm -D /usr/lib64/libc.so.6
000000000001ac00 T a64l@@GLIBC_2.2.5
00000000000016aa T abort@@GLIBC_2.2.5
00000000001e9b40 B __abort_msg@@GLIBC_PRIVATE
000000000001ad00 T abs@@GLIBC_2.2.5
The output of nm
for a shared library shows all symbols defined or referenced in the library. Each line corresponds to one symbol and it contains its value, type and name.
Static libraries
$ nm -C /lib/gcc/x86_64-redhat-linux/15/libgcc.a
_muldi3.o:
0000000000000000 T __multi3
_negdi2.o:
0000000000000000 T __negti2
The output of nm
for a static library shows the name of all objects contained in it and all the symbols defined or referenced in them. Each line corresponds to one symbol and it contains its value, type and name.
Note
The man page of nm defines the meaning of all single character symbol types.
Finding libraries with a symbol
Finding which library in your system provides a given symbol can be simply done by executing nm
on all shared or static libraries found in some given directory:
Shared libraries
fd '.*\.so$' /path/to/target/libdir -x bash -c \
"nm -D --defined-only {} 2>/dev/null \
| grep 'symbol_name' && echo '╰╴>>> found in: {}'"
ref: stackoverflow.com
Static libraries
fd '.*\.a$' /path/to/target/libdir -x bash -c \
"nm --defined-only {} 2>/dev/null \
| grep 'symbol_name' && echo '╰╴>>> found in: {}'"
ref: stackoverflow.com
Remove the --defined-only
option from nm
to find libraries referencing the given symbol_name
in any way.
Usual suspects
The first place to look are the library search paths defined in the active shell. GCC searches for linker files in the locations defined in $LIBRARY_PATH
, while $LD_LIBRARY_PATH
is used at runtime.
IFS=:
for libdir in $LD_LIBRARY_PATH; do
echo "=== checking $libdir ..."
fd '.*\.so$' $libdir -x bash -c \
"nm -D {} 2>/dev/null \
| grep 'symbol_name' && echo '╰╴>>> found in: {}'"
done