ShlibvisibilityChecker - это небольшой инструмент, который определяет внутренние символы, которые излишне экспортируются из общих библиотек. Такие символы нежелательны, потому что они вызывают
--gc-sections ) ShlibvisibilityChecker сравнивает API, объявленные в общественных заголовках с API, экспортированными из общих библиотек, и предупреждает о несоответствиях. В большинстве случаев такие символы являются внутренними библиотечными символами, которые должны быть скрыты (в редких случаях это внутренние символы, которые используются другими библиотеками или исполняемыми файлами в одном и том же пакете, и shlibvischeck-debian старается не сообщать о таких случаях).
Такие расхождения должны затем быть зафиксированы путем перекомпилирования пакета с -fvisibility=hidden (см. Здесь для деталей). Типичное исправление для типичного проекта AutoConf можно найти здесь.
ShlibvisibilityChecker не предназначен для того, чтобы быть на 100% точным, а скорее оказывать помощь в поиске пакетов, которые могут наибольшей выгоды от аннотаций видимости (и понять, насколько плоха находится ситуация с видимостью в современных дистрибуциях).
Чтобы проверить пакет RAW, то есть куча заголовков и общих либеров, собирайте источники и двоичные интерфейсы и сравните их:
$ bin/read_header_api --only-args /usr/include/xcb/* > api.txt
$ ./read_binary_api --permissive /usr/lib/x86_64-linux-gnu/libxcb*.so > abi.txt
$ vimdiff api.txt abi.txt # Or `comm -13 api.txt abi.txt'
Другим полезным сценарием является поиск символов, которые экспортируются из общих библиотек Debian Package, но не объявляются в его заголовках. Основным инструментом для этого является сценарий shlibvischeck-debian .
Чтобы применить его к упаковке, запустите
$ shlibvischeck-debian libacl1
The following exported symbols in package 'libacl1' are private:
__acl_extended_file
__acl_from_xattr
__acl_to_xattr
__bss_start
_edata
_end
_fini
_init
closed
head
high_water_alloc
next_line
num_dir_handles
walk_tree
Чтобы пропустить автогенерируемые символы, такие как _init или _edata (вызванные сценариями LD -линкеров и файлами запуска LIBGCC) добавить --permissive .
Вы также можете проверить проблемы видимости в произвольном наборе заголовков и библиотек:
$ shlibvischeck-common --permissive --cflags="-I/usr/include -I$AUDIT_INSTALL/include -I/usr/lib/llvm-5.0/lib/clang/5.0.0/include" $AUDIT_INSTALL/include/*.h $AUDIT_INSTALL/lib/*.so*
Пререквизитами времени построения являются python3 (модуль setuptools ), clang , llvm , libclang-dev , g++ и make . Зависимость от времени выполнения- python3 ( python-magic Module), pkg-config и aptitude . Чтобы установить все на Ubuntu, запустите
$ sudo apt-get install python3 clang llvm libclang-dev g++ make pkg-config aptitude
$ sudo python3 -mensurepip
$ sudo pip3 install setuptools python-magic
(Вы также можете использовать скрипты scripts/install-deps.sh ).
Вам также необходимо включить доступ к исходным пакетам Ubuntu через
$ sudo sed -Ei 's/^# *deb-src /deb-src /' /etc/apt/sources.list
$ sudo apt-get update
Python и бинарные компоненты построены отдельно:
$ make clean all && make install
$ ./setup.py build && pip3 install .
Во время анализа shlibvischeck-debian устанавливает новые пакеты Debian, поэтому рекомендуется запустить их под Chroot или в виртуальной машине. Есть много инструкций по настройке Chroot, например.
Список пакетов для анализа может быть получен из рейтинга Debian:
$ curl https://popcon.debian.org/by_vote | awk '/^[0-9]+ +lib/{print $2}' > by_vote
$ shlibvischeck-debian $(head -500 by_vote | tr 'n' ' ')
После того, как вы нашли проблемный пакет, вы можете исправить его, ограничивая видимость внутренних символов. Лучший способ контролировать видимость символа в упаковке - это
-fvisibility=hidden к CFLAGS в проектах Buildscripts ( Makefile.in или CMakeLists.txt )__attribute__((visibility("default")))Смотрите исправление в Libcaca, например.
На данный момент инструмент работает только в системах Debian (например, Ubuntu). Это должно быть хорошо, так как строительные приписания одинаковы во всех дистрибуциях, поэтому обнаружение проблем на Ubuntu будет служить всем остальным.
Важной проблемой дизайна является то, что инструмент не может обнаружить символы, которые используются косвенно, т. Е. Не через API, а через dlsym или явное объявление прототипа вне заголовки в исходном файле. Это происходит в плагинах или тесно взаимосвязанных Shlibs в одном и том же проекте. Такие случаи, надеюсь, должны быть редкими.
ShlibvisibilityChecker - это эвристический инструмент, поэтому он не сможет проанализировать все пакеты. Текущий показатель успеха составляет около 60%. Основные причины ошибок - это
libatasmart не включает в себя stddef.h и tdb не включает в себя sys/types.h ).lzma/container.h )dpkg/macros.h требуют LIBDPKG_VOLATILE_API )libverto-dev использует заголовки из скольжения, но не объявляет это)Другие проблемы:
Инструмент обнаружил огромное количество пакетов, в которых не было аннотаций видимости (на практике каждый второй пакет имеет ложный экспорт). Вот некоторые, которые я пытался исправить:
Больше перспективных пакетов (от Debian Top-100): Libpopt1, Libgpg-error0, libxml2, libwrap0, libpcre3, libkeyutils1, libedit2, liblcms2-2.