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

前端 未结 3 1700
无人共我
无人共我 2021-02-01 23:22

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

相关标签:
3条回答
  • 2021-02-01 23:32

    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
    0 讨论(0)
  • 2021-02-01 23:36

    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
    
    0 讨论(0)
  • 2021-02-01 23:42

    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.

    0 讨论(0)
提交回复
热议问题