O ShlibvisibilityChecker é uma pequena ferramenta que localiza símbolos internos exportados desnecessariamente de bibliotecas compartilhadas. Tais símbolos são indesejáveis porque causam
--gc-sections ) O ShlibvisibilityChecker compara as APIs declaradas em cabeçalhos públicos contra APIs exportadas de bibliotecas compartilhadas e alerta sobre discrepâncias. Na maioria dos casos, esses símbolos são símbolos internos da biblioteca que devem ser ocultos (em casos raros, esses são símbolos internos que são usados por outras bibliotecas ou executáveis no mesmo pacote e shlibvischeck-debian tenta não relatar tais casos).
Tais discrepâncias devem ser corrigidas pelo pacote de recompilação com -fvisibility=hidden (veja aqui para obter detalhes). Uma correção típica, para um projeto típico do AutoConf, pode ser encontrado aqui.
O ShlibvisibilityChecker não deve ser 100% preciso, mas prestar assistência na localização de pacotes que podem se beneficiar mais das anotações de visibilidade (e para entender o quão ruim a situação com visibilidade é nas distros modernas).
Para verificar um pacote bruto, ou seja, vários cabeçalhos e bibliotecas compartilhadas, colete interfaces de origem e binários e compare -os:
$ 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'
Outro cenário útil é localizar símbolos exportados das bibliotecas compartilhadas do Debian Package, mas não são declaradas em seus cabeçalhos. A principal ferramenta para isso é um script shlibvischeck-debian .
Para aplicá -lo a um pacote, execute
$ 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
Para pular símbolos autogenerados como _init ou _edata (causados por scripts de ligação LD e arquivos de inicialização libgcc) Adicionar --permissive .
Você também pode verificar os problemas de visibilidade em um conjunto arbitrário de cabeçalhos e bibliotecas:
$ 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*
Os pré-requisitos de tempo de construção são python3 (módulo setuptools ), clang , llvm , libclang-dev , g++ e make . As dependências em tempo de execução são python3 (módulo python-magic ), pkg-config e aptitude . Para instalar tudo no Ubuntu, execute
$ sudo apt-get install python3 clang llvm libclang-dev g++ make pkg-config aptitude
$ sudo python3 -mensurepip
$ sudo pip3 install setuptools python-magic
(Você também pode usar scripts scripts/install-deps.sh ).
Você também precisa permitir o acesso aos pacotes de origem do Ubuntu via
$ sudo sed -Ei 's/^# *deb-src /deb-src /' /etc/apt/sources.list
$ sudo apt-get update
Os componentes python e binários são construídos separadamente:
$ make clean all && make install
$ ./setup.py build && pip3 install .
Durante a análise, shlibvischeck-debian instala novos pacotes Debian, por isso é recomendável executá-lo sob Chroot ou na VM. Existem muitas instruções sobre como configurar o Chroot, por exemplo, este.
Uma lista de pacotes para análise pode ser obtida da Classificação Debian:
$ curl https://popcon.debian.org/by_vote | awk '/^[0-9]+ +lib/{print $2}' > by_vote
$ shlibvischeck-debian $(head -500 by_vote | tr 'n' ' ')
Depois de encontrar um pacote problemático, você pode corrigi -lo restringindo a visibilidade dos símbolos internos. A melhor maneira de controlar a visibilidade do símbolo em um pacote é
-fvisibility=hidden aos CFLAGS no projeto BuildScripts ( Makefile.in ou CMakeLists.txt )__attribute__((visibility("default")))Consulte Fix no Libcaca, por exemplo.
No momento, a ferramenta funciona apenas em sistemas baseados em Debian (por exemplo, Ubuntu). Isso deve ser bom, pois o BuildScripts é o mesmo em todas as distros, portanto, a detecção de problemas no Ubuntu também serviria a todos os outros.
Uma questão importante de design é que a ferramenta não pode detectar símbolos que são usados indiretamente, ou seja, não através de uma API, mas através de dlsym ou declaração explícita de protótipo fora do cabeçalho no arquivo de origem. Isso acontece em plugins ou shlibs fortemente interconectados no mesmo projeto. Esperamos que esses casos sejam raros.
O ShlibvisibilityChecker é uma ferramenta heurística, para que não seja capaz de analisar todos os pacotes. A taxa de sucesso atual é de cerca de 60%. As principais razões para os erros são
libatasmart falha em incluir stddef.h e tdb falha em incluir sys/types.h ).lzma/container.h )dpkg/macros.h requer LIBDPKG_VOLATILE_API )libverto-dev usa cabeçalhos de glib, mas não declara isso)Outros problemas:
A ferramenta encontrou um grande número de pacotes que não tinham anotações de visibilidade (na prática, cada segundo pacote possui exportações espúrias). Aqui estão alguns que eu tentei consertar:
Mais pacotes de perspectiva (do Debian Top 100): libpopt1, libgpg-error0, libxml2, libwrap0, libpcre3, libkeyutils1, libitit2, liblcms2-2.