ShlibvisibleChecker是一个小工具,可以找到内部符号,这些符号不必要地从共享库中导出。这样的符号是不可取的,因为它们会导致
--gc-sections闭合)ShlibvisibilityChecker比较了公共标题中声明的API与从共享库中导出的API,并警告有关差异的警告。在大多数情况下,这些符号是内部库符号,应隐藏起来(在极少数情况下,这些是内部符号,在同一软件包中使用其他库或可执行文件使用, shlibvischeck-debian试图不报告这种情况)。
然后,应通过以-fvisibility=hidden重新编译软件包来修复此类差异(有关详细信息,请参见此处)。对于典型的AutoConf项目,可以在此处找到一个典型的修复程序。
ShlibvisibilityChecker并不是要100%精确,而是在找到可以从可见性注释中受益最大的包装方面提供帮助(并了解现代发行版中可见性的情况有多糟)。
要检查一个原始软件包,即一堆标头并共享libs,收集源和二进制接口并比较它们:
$ 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软件包共享库中导出的符号,但并未在其标题中声明。主要工具是一个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 Linker脚本和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模块), 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 )。
您还需要通过
$ 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或VM下运行它。有很多有关设置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在project buildscript中的CFLAGS ( Makefile.in或CMakeLists.txt )中隐藏所有符号__attribute__((visibility("default")))例如,请参见Libcaca中的修复。
目前,工具仅适用于基于Debian的系统(例如Ubuntu)。这应该很好,因为在所有发行版中构建订阅都是相同的,因此在Ubuntu上检测问题也将为其他所有人服务。
一个重要的设计问题是,该工具无法检测到不是通过API而是通过dlsym或源文件中明确的外部原型声明来检测IE的符号。这发生在插件或同一项目中紧密相互连接的shlibs中。希望这种情况应该很少见。
ShlibvisibilityChecker是一种启发式工具,因此无法分析所有软件包。当前的成功率约为60%。错误的主要原因是
libatasmart未能包括stddef.h ,而tdb未能包括sys/types.h )。lzma/container.h )dpkg/macros.h需要LIBDPKG_VOLATILE_API )libverto-dev使用glib标头,但没有声明这一点)其他问题:
该工具发现大量缺乏可见性注释的软件包(实际上每个第二个软件包都有虚假的出口)。这是我试图修复的一些:
更多的透视包(来自Debian Top-100):libpopt1,libgpg-error0,libxml2,libwrap0,libpcre3,libkeyutils1,libedit2,libedit2,liblcms2-2。