ShlibVisibilityChecker est un petit outil qui localise des symboles internes qui sont inutilement exportés à partir de bibliothèques partagées. De tels symboles ne sont pas souhaitables car ils provoquent
--gc-sections ) ShlibVisibilityChecker compare les API déclarées dans les en-têtes publics contre les API exportées des bibliothèques partagées et met en garde contre les écarts. Dans la majorité des cas, ces symboles sont des symboles de bibliothèque interne qui doivent être cachés (dans de rares cas, ce sont des symboles internes qui sont utilisés par d'autres bibliothèques ou exécutables dans le même package et shlibvischeck-debian s'efforce de ne pas signaler ces cas).
Ces divergences doivent ensuite être corrigées en recompilant le package avec -fvisibility=hidden (voir ici pour plus de détails). Un correctif typique, pour un projet AutoConf typique, peut être trouvé ici.
ShlibvisibilityChecker n'est pas censé être 100% précis mais plutôt fournir une assistance pour localiser les packages qui peuvent profiter le plus des annotations de visibilité (et comprendre à quel point la situation avec la visibilité est mauvaise dans les distros modernes).
Pour vérifier un package brut, c'est-à-dire un tas d'en-têtes et des LIB partagés, collecter les interfaces source et binaires et les comparer:
$ 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'
Un autre scénario utile consiste à localiser les symboles qui sont exportés des bibliothèques partagées de Debian Package mais qui ne sont pas déclarées dans ses en-têtes. L'outil principal pour cela est un script shlibvischeck-debian .
Pour l'appliquer à un package, exécutez
$ 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
Pour ignorer les symboles autogenits comme _init ou _edata (causés par les scripts de linker LD et les fichiers de démarrage libgcc), ajoutez --permissive .
Vous pouvez également vérifier les problèmes de visibilité dans un ensemble arbitraire d'en-têtes et de bibliothèques:
$ 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*
Les conditions de construction-temps sont python3 (module setuptools ), clang , llvm , libclang-dev , g++ et make . Les dépendances d'exécution sont python3 (module python-magic ), pkg-config et aptitude . Pour tout installer sur Ubuntu, courez
$ sudo apt-get install python3 clang llvm libclang-dev g++ make pkg-config aptitude
$ sudo python3 -mensurepip
$ sudo pip3 install setuptools python-magic
(vous pouvez également utiliser scripts/install-deps.sh ).
Vous devez également permettre l'accès aux packages source Ubuntu via
$ sudo sed -Ei 's/^# *deb-src /deb-src /' /etc/apt/sources.list
$ sudo apt-get update
Python et les composants binaires sont construits séparément:
$ make clean all && make install
$ ./setup.py build && pip3 install .
Pendant l'analyse, shlibvischeck-debian installe de nouveaux packages Debian, il est donc recommandé de l'exécuter sous chroot ou en VM. Il existe de nombreuses instructions sur la configuration du chroot, par exemple celle-ci.
Une liste de packages pour l'analyse peut être obtenu à partir de la notation Debian:
$ curl https://popcon.debian.org/by_vote | awk '/^[0-9]+ +lib/{print $2}' > by_vote
$ shlibvischeck-debian $(head -500 by_vote | tr 'n' ' ')
Une fois que vous avez trouvé un package problématique, vous pouvez le réparer en restreignant la visibilité des symboles internes. La meilleure façon de contrôler la visibilité du symbole dans un paquet est de
-fvisibility=hidden à CFLAGS dans Project Buildscripts ( Makefile.in ou CMakeLists.txt )__attribute__((visibility("default")))Voir Fix dans Libcaca par exemple.
À l'heure actuelle, l'outil ne fonctionne que sur les systèmes basés à Debian (par exemple Ubuntu). Cela devrait être bien car les constructions de construction sont les mêmes dans toutes les distros, donc la détection des problèmes sur Ubuntu servirait également tout le monde.
Un problème de conception important est que l'outil ne peut pas détecter des symboles qui sont utilisés indirectement, à savoir non pas via une API mais via dlsym ou la déclaration de prototype hors tête explicite dans le fichier source. Cela se produit dans les plugins ou les shlibs étroitement interconnectés dans le même projet. De tels cas devraient être rares.
ShlibVisibilityChecker est un outil heuristique afin qu'il ne puisse pas analyser tous les packages. Le taux de réussite actuel est d'environ 60%. Les principales raisons des erreurs sont
libatasmart ne parvient pas à inclure stddef.h et tdb ne parvient pas à inclure sys/types.h ).lzma/container.h )dpkg/macros.h il faut LIBDPKG_VOLATILE_API )libverto-dev utilise des en-têtes glib mais ne le déclare pas)Autres problèmes:
L'outil a trouvé un grand nombre de packages qui manquaient d'annotations de visibilité (en pratique, chaque deuxième package a des exportations parasites). En voici quelques-uns que j'ai essayés de corriger:
Plus de forfaits de perspective (du top-100 debian): libpopt1, libgpg-error0, libxml2, libwrap0, libpcre3, libkeyutils1, lidit2, liblcms2-2.