How do I find where a symbol is defined among static libraries
Using nm
, it is possible to list the symbols defined in a binary, and the --defined-only
switch ignores undefined references.
Option 1: find
In a single command:
find $path -name \*.a -exec bash -c "nm --defined-only {} 2>/dev/null | grep $symbol && echo {}" \;
where $path
is the root of the file tree containing the binaries, and $symbol
is the name of the symbol you are looking for.
Option 2: find
+ GNU parallel
Running nm
on all files can take time, so it could be helpful to process the results of find
in parallel (using GNU parallel
):
find $path -name \*.a | parallel "nm --defined-only {} 2>/dev/null | grep $symbol && echo {}"
Option 3: fd
And at last, my favourite. Using the fd
tool, that has a simpler syntax than find
, is generally faster, and processes the results in parallel by default:
fd '.*\.a$' -x bash -c "nm --defined-only {} 2>/dev/null | grep $symbol && echo {}"
Simple benchmark
Searching for the gz_write
symbol in /usr/lib
on my laptop:
find
takes around 23 secondsfind | parallel
takes around 10 secondsfd
takes around 8 seconds
Assuming a linux box, the nm tool, listing names in library files, comes to the rescue.
It can be used to do an extensive search as follows: one can first find all the libraries available (assuming the project have been successfully compiled without the component you are adding) with a find, then such find can be enclosed in a loop where you call nm on all discovered libraries; the output you then grep for discarding "U" references (undefined symbols, aka where else the symbol is being used). On a single bash line that gives:
for lib in $(find base_path -name \*.a) ; do echo $lib ; nm $lib | grep my_symbol | grep -v " U " ; done
where:
- base_path is the root of your codebase
- my_symbol is the symbol you are looking for
The echo generates a list of all libraries found, which is not so clean since it outputs names of libs not holding the symbol, but it was the fastest way I found to have a direct reference to the library so when you see a:
base_path/component/libA.a
0000000000000080 D my_symbol
You have found your usual suspect.