使用 SVF 进行代码分析时,需要一个bitcode文件(.bc),但对于复杂的项目,一般只能得到分散的 bitcode 文件。GitHub上的项目 Whole Program LLVM 旨在解决这个问题,使用该工具将整个项目编译成单个 bitcode 文件。
点这里:WLLVM官方教程
点这里:SVF官方教程
在实际操作时,我没有完全按照官方教程来,因为年代有些久远了。
直接参考下面这篇文章即可
点这里:Ubuntu快速安装miniconda(付费了!)
mkdir -p ~/miniconda3
#wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda3/miniconda.sh
wget https://mirrors.zju.edu.cn/anaconda/miniconda/Miniconda3-latest-Linux-x86_64.sh -O ~/miniconda3/miniconda.sh
bash ~/miniconda3/miniconda.sh -b -u -p ~/miniconda3
rm -rf ~/miniconda3/miniconda.sh
cd ~/miniconda3/bin
./conda init bash
配置好了记得重启一下 shell ,终端显示类似 (base) a@Legend:~$
的内容,说明配置成功,然后换源。
首先给 conda 换源
vim ~/.condarc
# 浙大源,只需要复制 <
<<ZJU
channels:
- defaults
show_channel_urls: true
default_channels:
- https://mirrors.zju.edu.cn/anaconda/pkgs/main
- https://mirrors.zju.edu.cn/anaconda/pkgs/r
- https://mirrors.zju.edu.cn/anaconda/pkgs/msys2
custom_channels:
conda-forge: https://mirrors.zju.edu.cn/anaconda/cloud
msys2: https://mirrors.zju.edu.cn/anaconda/cloud
bioconda: https://mirrors.zju.edu.cn/anaconda/cloud
menpo: https://mirrors.zju.edu.cn/anaconda/cloud
pytorch: https://mirrors.zju.edu.cn/anaconda/cloud
pytorch-lts: https://mirrors.zju.edu.cn/anaconda/cloud
simpleitk: https://mirrors.zju.edu.cn/anaconda/cloud
nvidia: https://mirrors.zju.edu.cn/anaconda-r
ZJU
# 清华源,只需要复制 <
<<Tsinghua
channels:
- defaults
show_channel_urls: true
default_channels:
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/msys2
custom_channels:
conda-forge: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
msys2: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
bioconda: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
menpo: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
pytorch: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
pytorch-lts: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
simpleitk: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
Tsinghua
conda 的浙大源
channels:
- defaults
show_channel_urls: true
default_channels:
- https://mirrors.zju.edu.cn/anaconda/pkgs/main
- https://mirrors.zju.edu.cn/anaconda/pkgs/r
- https://mirrors.zju.edu.cn/anaconda/pkgs/msys2
custom_channels:
conda-forge: https://mirrors.zju.edu.cn/anaconda/cloud
msys2: https://mirrors.zju.edu.cn/anaconda/cloud
bioconda: https://mirrors.zju.edu.cn/anaconda/cloud
menpo: https://mirrors.zju.edu.cn/anaconda/cloud
pytorch: https://mirrors.zju.edu.cn/anaconda/cloud
pytorch-lts: https://mirrors.zju.edu.cn/anaconda/cloud
simpleitk: https://mirrors.zju.edu.cn/anaconda/cloud
nvidia: https://mirrors.zju.edu.cn/anaconda-r
conda 的清华源
channels:
- defaults
show_channel_urls: true
default_channels:
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/main
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/r
- https://mirrors.tuna.tsinghua.edu.cn/anaconda/pkgs/msys2
custom_channels:
conda-forge: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
msys2: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
bioconda: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
menpo: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
pytorch: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
pytorch-lts: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
simpleitk: https://mirrors.tuna.tsinghua.edu.cn/anaconda/cloud
然后给 pip 换源
pip config set global.index-url https://mirrors.zju.edu.cn/pypi/web/simple # 浙大源,仅推荐浙江大学校内使用
pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/ # 阿里源
conda换国内源&pip换国内源
如果 VS Code 的终端出现两个环境名,可以执行这个命令
conda config --set auto_activate_base False # 取消自动激活 conda 的 base 环境
不建议在 base 环境下折腾,而是建议用 conda 创建一个新的环境进行操作,我选择的 Python 版本是 3.8.10 。conda 创建环境时会自动安装 pip ,所以不需要自己再装了。
conda create --name py38 python=3.8.10
conda activate py38
conda deactivate # 退出 py38 时用这个,这里不要用
给 conda 安装命令行补全插件
conda install conda-bash-completion -n base -c conda-forge
Python 环境配置好了,就可以安装 WLLVM 以及其它必要的组件了。
pip install wllvm
sudo apt update
sudo apt install llvm clang libapr1-dev libaprutil1-dev
配置 WLLVM 使用 Clang
vim ~/.bashrc
# 在合适的位置添加以下内容↓↓↓
export LLVM_COMPILER=clang
# 在合适的位置添加以上内容↑↑↑
source ~/.bashrc
下载、解压、编译
wget https://archive.apache.org/dist/httpd/httpd-2.4.18.tar.gz
tar xfz httpd-2.4.18.tar.gz
cd httpd-2.4.18
CC=wllvm ./configure
# 报错
configure: error: pcre-config for libpcre not found. PCRE is required and available from http://pcre.org/
# 解决方法
sudo apt install libpcre3 libpcre3-dev
CC=wllvm ./configure
make
extract-bc -l llvm-link httpd
我在 Docker 创建的 debian 容器中又做了一遍,结果遇到如下错误
(py38) root@02683b632459:~/my-syf/httpd-2.4.18/build # extract-bc -l llvm-link httpd
ERROR:WLLVM Failed to execute: ['file', '/root/my-syf/httpd-2.4.18/build/httpd']
这是因为 Docker 的 debian 镜像太简洁了,连 file
都没有,所以还要装一下这个工具
apt install file
装好后再重新构建一遍 httpd ,应该就可以正常提取 bitcode 文件了
ls -la httpd.bc
# 得到 http.bc 文件,显示如下内容
# -rw-rw-r-- 1 a a 1217256 8月 11 11:20 httpd.bc
把httpd.bc
挪到一个空文件夹再进行分析,接下来可以参考 SVF的官方教程
wpa -ander -dump-constraint-graph httpd.bc
执行 ls -a
,显示如下内容
-rw-rw-r-- 1 a a 592837 8月 11 11:25 callgraph_final.dot
-rw-rw-r-- 1 a a 590899 8月 11 11:25 callgraph_initial.dot
-rw-rw-r-- 1 a a 1217256 8月 11 11:20 httpd.bc
推荐把所有的编译优化都关掉,本章给出的命令都以下面的配置为基础
CC="wllvm -O0 -Xclang -optnone -g -save-temps=obj -fno-discard-value-names -w"
CXX="wllvm++ -O0 -Xclang -optnone -g -save-temps=obj -fno-discard-value-names -w"
推荐把 WLLVM 调整成 debug 模式,在 ~/.bashrc
中加入以下内容
export WLLVM_OUTPUT_LEVEL=DEBUG
configure
文件执行 ./configure
之前,假设源代码目录叫 src
,建议从在这个目录外创建一个 build
目录,在 build
下执行 ./configure
和 make
,这样可以把构建出来的文件和源代码分开。
cd ..
mkdir build
cd build
CC="wllvm -O0 -Xclang -optnone -g -save-temps=obj -fno-discard-value-names -w" \
CXX="wllvm++ -O0 -Xclang -optnone -g -save-temps=obj -fno-discard-value-names -w" \
../src/configure
make
但有时候把构建文件和源代码分开会出现 include
失败之类的错误,这时候只能在 src
目录下构建了。
autogen.sh
文件如果没有 configure
文件,但是有 autogen.sh
,则先执行 ./autogen,sh
,然后就会出现 configure
文件了,再参考4.1即可。
apt install autoconf # 容器中可能需要安装这个包,然后会自动安装 automake 和 autotools-dev 等包
Makefile
文件如果只有 Makefile
,那么在 src
目录外创建 build
目录,再在该目录下执行如下命令。
make -C ../src \
CC="wllvm -O0 -Xclang -optnone -g -save-temps=obj -fno-discard-value-names -w" \
CXX="wllvm++ -O0 -Xclang -optnone -g -save-temps=obj -fno-discard-value-names -w"
有时候如果编译出来的文件无法使用 extract-bc
提取文件,则需要查看 Makefile
,重点查看编译器相关的参数。比如编译 FFmpeg
的时候,就需要把命令改成这样(CC
和 CXX
改成小写)
make -C ../src \
cc="wllvm -O0 -Xclang -optnone -g -save-temps=obj -fno-discard-value-names -w" \
cxx="wllvm++ -O0 -Xclang -optnone -g -save-temps=obj -fno-discard-value-names -w"
CMakeLists.txt
文件如果只有 CMakeLists.txt
,则需要先生成 Makefile
,再进行构建
cmake -B ../build \
-DCMAKE_C_COMPILER=wllvm \
-DCMAKE_CXX_COMPILER=wllvm++ \
-DCMAKE_C_FLAGS="-O0 -Xclang -optnone -g -save-temps=obj -fno-discard-value-names -w" \
-DCMAKE_CXX_FLAGS="-O0 -Xclang -optnone -g -save-temps=obj -fno-discard-value-names -w"