在python脚本中调用joern批量生成C/C++代码属性图

链接导航

如果大家对安装等基本操作有疑问的话可以参考我写的一篇JOERN基本使用介绍
JOERN基本使用介绍

1 解析前的准备

joern在解析C/C++代码时,输入形式是一个独立的文件夹,每个文件夹包含着要解析的.cpp文件,具体如下:
在python脚本中调用joern批量生成C/C++代码属性图_第1张图片
每一个文件夹的内容都只包含一个独立的.cpp文件
在python脚本中调用joern批量生成C/C++代码属性图_第2张图片
也就是说:我有一个很大的数据集,里面是很多的C++代码段,我需要先把这些C++代码段包装成一个个独立的.cpp代码文件,然后再使用与.cpp文件数量相等的文件夹来包裹住每一个独立的.cpp文件,即每个文件夹里面只有一个.cpp文件。

我的文件目录结构为:

data
     data/c_code
         data/c_code/dirs
            data/c_code/dirs/1-29500
                data/c_code/dirs/1-29500/1-29500.zpp
             

输入到joern中的是data/c_code/dirs/1-29500

调用joern批量生成cpg的.dot文件

import subprocess
import os
import shutil
import pandas as pd
from tqdm import tqdm
# path-to-joern-parse
JOERNPATH="/home/se/joern-cli/"
root_dir = './data/'
# location of source code dirs
source_dir = "./data/c_code/dirs"

parse_source_code_to_dot函数
输入要解析的文件夹, 文件名称
输出解析好的dot文件并存储到指定文件夹中(out_dir_pdg/out_dir_cpg)

import subprocess

def parse_source_code_to_dot(file_path, f, out_dir_pdg='/parsed/dot/pdg/', out_dir_cpg='/parsed/dot/cpg/'):
    root_path = './data'
    try :
        os.makedirs(root_path+out_dir_pdg)
        os.makedirs(root_path+out_dir_cpg)
    except:
        pass
    out_dir_cpg=root_path + '/parsed/dot/cpg/'
    # parse source code into cpg
    print('parseing source code into cpg...')
    shell_str = "sh " + JOERNPATH + "./joern-parse " + file_path
    subprocess.call(shell_str, shell=True) 
    print('exporting cpg from cpg root...')
    # 导出cpg的dot文件到指定的文件夹中
    # 本处指定的是:out_dir_cpg + fname
    # 即:'./data/parsed/dot/cpg/'
    shell_export_cpg = "sh " + JOERNPATH + "joern-export " + "--repr cpg14 --out " + out_dir_cpg + f.split('.')[0] + os.sep
    subprocess.call(shell_export_cpg, shell=True)

main_func()调用parse_source_code_to_dot函数,批量地生成cpg的dot文件
source_dir = “./data/c_code/dirs”,为带解析的全部源代码文件所在路径

import os
def main_func(source_dir = "./data/c_code/dirs", out_dir_cpg="解析好的cpg的dot文件的存放路径"):
    # all source code files, each file include a .cpp file
    dirs = os.listdir(source_dir)
    for c_folder in tqdm(dirs)# 待解析的文件夹路径
        file_path = source_dir + '/' + c_folder
        # 解析好的cpg的dot文件的存放路径
        cpg_path = out_dir_cpg + '/' + c_folder
        # 如果cpg_path已经存在且解析出来的.dot文件个数大于0,说明该文件夹之前已经解析过了,就不再解析,避免重复工作
        if os.path.exists(cpg_path) and len(os.listdir(cpg_path)) > 0:
            print(f'{file_path} file has been processed')
            continue
        print(f'starting to process {file_path}')
        # 得到待解析的.cpp文件的名称 "filename.cpp"
        f = os.listdir(file_path)[0]
        #print(f)
        parse_source_code_to_dot(file_path, f)

# 调用main_func函数批量解析c++文件
if __name__ == "__main__":
    main_func()

解析效果示例

解析好的cpg文件夹效果
在python脚本中调用joern批量生成C/C++代码属性图_第3张图片
在python脚本中调用joern批量生成C/C++代码属性图_第4张图片

PDG的解析

PDG和CPG一样的流程,只需要修改parse_source_code_to_dot函数里面的shell_export_cpg语句

shell_export_pdg = "sh " + JOERNPATH + "joern-export " + "--repr pdg --out " + out_dir_pdg + f.split('.')[0] + os.sep

你可能感兴趣的:(程序依赖图,程序语义理解,joern)