How to find where a symbol is defined among static libraries

Suppose you are working with a codebase consisting of several tools and libraries, and you want to transfer (or resurrect) a component to such a codebase, but any hint about where the characters are in different libraries is lost. or it will take time to find out looking at the code itself (yes, improved documentation can avoid such problems, but it is quite demanding). What is the fastest way to find out which library you can find the characters used in the code?

+8
c ++ libraries linker undefined-symbol
source share
3 answers

Assuming that the nm tool appears in the linux window, listing the names in the library files.

It can be used to perform an advanced search as follows: first you can find all available libraries (provided that the project was successfully compiled without the component you are adding) using find, then such a find can be enclosed in a loop where you call nm on all discovered libraries; at the output, you will be grep to drop the "U" links (undefined characters, otherwise, where the character is still used). On one line of bash, which 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 code base
  • my_symbol is the character you are looking for

The echo generates a list of all found libraries, which is not so clean, because it displays the names of libraries that do not contain a symbol, but this was the fastest way with which I found a direct link to the library, so when you see

 base_path/component/libA.a 0000000000000080 D my_symbol 

You have found your usual suspect.

+16
source share

Using the nm --defined-only switch here is useful as it will remove undefined links. Below is a csh script that may be useful to others.

 #!/bin/csh # #recurse from current dir and output name of any .a files #that contain the desired symbol. echo "Search for: $1" foreach i (`find . -name '*.a'`) nm --defined-only $i | grep $1 if ($status == 0) then echo $i endif end 
+1
source share

Using nm , you can enumerate characters defined in binary format, and the --defined-only key ignores undefined references.

Option 1: find

In one team:

 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 character you are looking for.

Option 2: find + GNU parallel

Running nm for all files may take some time, so it may be useful to process find results in parallel (using parallel GNU):

 find $path -name \*.a | parallel "nm --defined-only {} 2>/dev/null | grep $symbol && echo {}" 

Option 3: fd

And finally, my favorite. Using the fd tool, which has a simpler syntax than find , is usually faster and processes the results in parallel by default:

 fd '.*\.a$' -x bash -c "nm --defined-only {} 2>/dev/null | grep $symbol && echo {}" 

Simple test

Search for the gz_write character in /usr/lib on a laptop with i7-6560U:

  • find takes about 23 seconds
  • find | parallel find | parallel find | parallel find | parallel takes about 10 seconds
  • fd takes about 8 seconds
0
source share

All Articles