0%

记一次CodeQL与OpenJDK的联动

序言

夜来风雨声,花落知多少。

使用CodeQL为OpenJDK生成数据库,过程中踩了很多坑,写篇博客详细记录一下。

CodeQL数据库生成流程

image-20220303101229869

CodeQL引擎内的Extractor会对程序中的语义信息进行分析与提取,用来构建后续用来分析的数据库。

编译型语言:在本地编译的过程中,可以将Extractor视作探针。它监视编译过程,捕获程序语义信息。

解释性语言:直接分析程序源码。

数据库里有什么:源代码src.zip、语义信息、关系数据。

CodeQL数据库获取途径

LGTM平台对CodeQL做了非常好的数据支持,不仅可以在上面直接编写QL脚本查询,还可以下载到特定组件对应的数据库。

当然,LGTM也支持与用户的GitHub仓库联动的Workflow,具体操作看参考官方文档

但痛点是,LGTM平台并没有OpenJDK的Database。。。

为了解决它,我去openjdk/jdk8u项目找到对应版本的tag,本地编译了一下,也就有了这篇博客。

过程记录

编译环境

操作系统:ubuntu 16.04

Boot_JDK:jdk 1.7.0_80

Target_OpenJDK:OpenJDK 8u73

准备Boot_JDK

我选择的是直接解压tar.gz方式进行Boot_JDK的安装,jdk-7u80-linux-x64.tar.gz

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# 解压
mkdir /usr/lib/jvm
tar -zxvf jdk-7u80-linux-x64.gz -C /usr/lib/jvm
# 配置环境变量
vim ~/.bashrc
export JAVA_HOME=/usr/lib/jvm/jdk1.7.0_80
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH
# 环境变量生效
source ~/.bashrc
# 配置系统默认的JDK版本
update-alternatives --install /usr/bin/java java /usr/lib/jvm/jdk1.7.0_80/bin/java 300
update-alternatives --install /usr/bin/javac javac /usr/lib/jvm/jdk1.7.0_80/bin/javac 300
update-alternatives --install /usr/bin/jar jar /usr/lib/jvm/jdk1.7.0_80/bin/jar 300
update-alternatives --install /usr/bin/javah javah /usr/lib/jvm/jdk1.7.0_80/bin/javah 300
update-alternatives --install /usr/bin/javap javap /usr/lib/jvm/jdk1.7.0_80/bin/javap 300
update-alternatives --config java
# 检查是否配置成功
java -version

准备Toolchain

软件包更新:

1
2
apt-get update
apt-get upgrade

安装编译工具:

1
apt-get install -y build-essential gdb cmake cpio file unzip zip wget ccache
1
apt-get install -y --no-install-recommends  libfontconfig1-dev libfreetype6-dev  libcups2-dev libx11-dev  libxext-dev  libxrender-dev  libxrandr-dev  libxtst-dev  libxt-dev libasound2-dev  libffi-dev  autoconf

降级cmake到3.81版本:

1
2
3
4
5
6
7
8
9
cd ~/OpenJDK8u73
wget http://ftp.gnu.org/gnu/make/make-3.81.tar.gz
&& tar -zxvf make-3.81.tar.gz
&& cd make-3.81
&& bash configure -prefix=/usr
&& make
&& make install
# 查看cmake版本
cmake -v

OpenJDK编译环境检查:

1
2
chmod 777 configure
./configure --with-target-bits=64 --with-boot-jdk=/usr/lib/jvm/jdk1.7.0_80 --with-debug-level=slowdebug --enable-debug-symbols ZIP_DEBUGINFO_FILES=0

当你看到这个画面,恭喜你,你的编译环境没问题:

image-20220303105226017

编译&数据库生成

到这里,下面这行命令就可以编译了:

1
make all DISABLE_HOTSPOT_OS_VERSION_CHECK=OK ZIP_DEBUGINFO_FILES=0

但我们想要的是CodeQL数据库,所以需要改一下命令:

1
codeql database create Openjdk8u73_db --language="java" --command="make all DISABLE_HOTSPOT_OS_VERSION_CHECK=OK ZIP_DEBUGINFO_FILES=0"

编译成功之后,cd到build/linux-x86_64-normal-server-slowdebug/jdk/bin目录下:

image-20220303110254754

编译好的OpenJDK在build目录下,对应的CodeQL数据库在源码目录下:

image-20220303105954416

CodeQL查询

有了Database,导入到VSCode插件中,写个脚本简单查询一下:

image-20220303111013521

后记

  1. MacOS上面Xcode,clang那一套编译工具实在是头大,为了省事,选择了Toolchain更简单清晰的Linux;
  2. 下载Linux版本的CodeQL CLI以及CodeQL Lib,构建数据库之前,别忘了修改环境变量;
  3. 降级make是为了保证稳定编译;
  4. Boot_JDK一定要选择比Target_JDK版本低的JDK;
  5. 目前闭源第三方Jar包依然是CodeQL痛点;

参考

手把手教你搭建单步调试openjdk环境(值得收藏)

编译OpenJDK8并生成CodeQL数据库

openjdk/jdk8u

官方Build OpenJDK

fnmsd/OpenJDK8-BuildEnv-Docker