using nm to track down the origin of an undefined symbol.
Posted by peeterjoot on March 22, 2010
The shared library for our product for historical reasons is built with the (evil) -Bsymbolic flag.
This has a number of unfortunate side effects, one of which is deferring link errors due to unresolved symbols to executable link time, instead of when we build the shared library itself.
Having screwed up in my own build over the weekend, I see a link error in my build summary this morning:
/view/peeterj_m20/vbs/engn/lib/libdb2.so: undefined reference to `XXYY'
I happen to know exactly what caused this (this time), but just the other day I was asked by somebody to help them figure out something similar. So the topic seems worthy of a quick blog post.
Suppose one collects all the archive names that contribute to the shared library in question (for DB2 builders one can relink the library having done an ‘export VERY_VERBOSE=true’ on the command line).
A good way to get this is to redirect that build output to a file, grab just the link line and run something like:
# cat filewithRawLinkLine.txt | tr ' ' '\n' | grep -F -e .a -e .o > archivesAndObjectNames.txt
In my case, this looked like:
# head -5 archivesAndObjectNames.txt
This now leaves you in the position to search for the archive(s) that contributed the undefined symbol. This can be done with:
# for i in `cat archivesAndObjectNames.txt` ; do echo $i ; nm $i | grep XXYY ; done | tee nm.out | grep -B1 XXYY
/view/peeterj_m20/vbs/engn/sqe/alibsqe.a U XXYY
So, the archive supplying a reference to this symbol is ‘alibsqe.a’ This completes the task of doing a first localization of where the link error is coming from. One can continue to do this in a brute force way finding the object file within the archive, or solve it by source inspection once one knows where to look a bit better. In an extremely large source base, where nobody really knows any sizeable portion of it, narrowing down the problem is often an important first step.