How do I find where a symbol is defined among static libraries

删除回忆录丶 提交于 2019-12-04 19:21:53

问题


Suppose you work with a codebase comprising several tools and libraries and you want to port (or resurrect) some component within such codebase but any clue about where symbols lie within the various libs is either lost or will take ages to find out by looking at the code itself (yes improved documentation can avoid such issues but is quite demanding). What is the fastest way to discover in which library you can find symbols used in the code?


回答1:


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.




回答2:


Using nm's --defined-only switch is helpful here since it will remove the undefined references. 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



回答3:


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 seconds
  • find | parallel takes around 10 seconds
  • fd takes around 8 seconds


来源:https://stackoverflow.com/questions/19916119/how-do-i-find-where-a-symbol-is-defined-among-static-libraries

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!