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。