从配置到演示:使用 WLLVM 将复杂项目编译成一个 bitcode 文件,并使用 SVF 工具进行分析

使用 SVF 进行代码分析时,需要一个bitcode文件(.bc),但对于复杂的项目,一般只能得到分散的 bitcode 文件。GitHub上的项目 Whole Program LLVM 旨在解决这个问题,使用该工具将整个项目编译成单个 bitcode 文件。

点这里:WLLVM官方教程
点这里:SVF官方教程
在实际操作时,我没有完全按照官方教程来,因为年代有些久远了。

1. 安装 conda 并创建所需的 Python 环境

直接参考下面这篇文章即可

点这里: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

2. 安装 WLLVM 以及相关工具

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

3. 以 httpd 2.4.18 为例进行代码分析

下载、解压、编译

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 

从配置到演示:使用 WLLVM 将复杂项目编译成一个 bitcode 文件,并使用 SVF 工具进行分析_第1张图片

执行 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

4. 重要注意事项

推荐把所有的编译优化都关掉,本章给出的命令都以下面的配置为基础

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

4.1 只有 configure 文件

执行 ./configure 之前,假设源代码目录叫 src ,建议从在这个目录外创建一个 build 目录,在 build 下执行 ./configuremake ,这样可以把构建出来的文件和源代码分开。

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 目录下构建了。

4.2 只有 autogen.sh 文件

如果没有 configure 文件,但是有 autogen.sh ,则先执行 ./autogen,sh ,然后就会出现 configure 文件了,再参考4.1即可。

apt install autoconf # 容器中可能需要安装这个包,然后会自动安装 automake 和 autotools-dev 等包

4.3 只有 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 的时候,就需要把命令改成这样(CCCXX 改成小写)

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" 

4.4 只有 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"

你可能感兴趣的:(从配置到演示:使用 WLLVM 将复杂项目编译成一个 bitcode 文件,并使用 SVF 工具进行分析)