Как найти, где символ определен среди статических библиотек

Предположим, вы работаете с кодовой базой, состоящей из нескольких инструментов и библиотек, и вы хотите портировать (или воскресить) какой-то компонент в этой кодовой базе, но любая подсказка о том, где символы лежат в различных библиотеках, либо потеряна, либо потребуется время, чтобы выяснить это, глядя на код. сам код (да, улучшенная документация может избежать таких проблем, но она довольно требовательна). Как быстрее всего узнать, в какой библиотеке можно найти символы, используемые в коде?


person a1an    schedule 11.11.2013    source источник


Ответы (3)


Предполагая, что это Linux-система, на помощь приходит инструмент nm, перечисляющий имена в библиотечных файлах.

Его можно использовать для расширенного поиска следующим образом: сначала можно найти все доступные библиотеки (при условии, что проект был успешно скомпилирован без добавляемого компонента) с помощью поиска, затем такой поиск можно заключить в цикл, в котором вы вызывать nm для всех обнаруженных библиотек; вывод, который вы затем выполняете grep для отбрасывания ссылок «U» (неопределенные символы, то есть где еще используется символ). В одной строке bash, которая дает:

for lib in $(find base_path -name \*.a) ; do echo $lib ; nm $lib | grep my_symbol | grep -v " U "   ; done

куда:

  • base_path — это корень вашей кодовой базы.
  • my_symbol — это символ, который вы ищете

Эхо генерирует список всех найденных библиотек, что не так чисто, поскольку выводит имена библиотек, не содержащих символ, но это был самый быстрый способ получить прямую ссылку на библиотеку, поэтому, когда вы видите:

base_path/component/libA.a
0000000000000080 D my_symbol

Вы нашли своего обычного подозреваемого.

person a1an    schedule 11.11.2013
comment
опция -A для nm напечатает имя файла. Устранение необходимости повторять $lib в вашем примере. - person Tyson Hilmer; 12.11.2019

Используя nm, можно перечислить символы, определенные в двоичном формате, а переключатель --defined-only игнорирует неопределенные ссылки.

Вариант 1: find

В одной команде:

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

где $path — корень дерева файлов, содержащего двоичные файлы, а $symbol — имя искомого символа.

Вариант 2: find + GNU parallel

Выполнение nm для всех файлов может занять некоторое время, поэтому было бы полезно обрабатывать результаты find параллельно (используя GNU parallel):

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

Вариант 3: fd

И, наконец, мой любимый. Использование инструмента fd с более простым синтаксисом, чем find, как правило, быстрее и обрабатывает результаты параллельно. по умолчанию:

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

Простой тест

Поиск символа gz_write в /usr/lib на моем ноутбуке:

  • find занимает около 23 секунд
  • find | parallel занимает около 10 секунд
  • fd занимает около 8 секунд
person m-pilia    schedule 25.05.2019

Здесь полезно использовать переключатель nm --defined-only, так как он удалит неопределенные ссылки. Ниже приведен скрипт csh, который может быть полезен другим.

#!/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
person eric gilbertson    schedule 24.05.2016