tabby是做成一个springboot项目启动,为什么这么做,暂时不清楚(后面清楚了,方便数据库操作)
App.class#run()
流程如下,判断是否是jdk8,然后加载settings配置,然后设置配置,解析配置,最后基于配置运行分析
配置分析
配置文件如下
简单解释下参数
tabby.build.target: 要分析的目标,可以是一个目录,也可以是一个jar包。
tabby.build.isJDKProcess: 将jre中的三个jar包也加入到target进行分析,"lib/rt.jar","lib/jce.jar","lib/ext/nashorn.jar"
tabby.build.withAllJDK: 在上述jre是三个jar包之外,还会增加jdk里的jar包分析,共19个jar包
tabby.build.checkFatJar: 这个是因为像项目打包成一个fatjar时,内部可能还有jar包,需要进一步解析
tabby.build.libraries: 依赖包目录, 这个是为了让target在解析到依赖包时,可以递归依赖解析,不会全量解析,默认是只有jre的3个jar包做依赖。PS: 如果不设置,默认是libs目录。
tabby.load.enable:开启后,会自动导入neo4j,如果没开启也不要紧,后续再看,因为之前jar包都分析过了,就自动跳过到导入步骤。
这里有两个配置可以注意下,tabby.build.enable
和tabby.load.enable
如果先进行分析不导入neo4j,tabby.load.enable
可先设置为false,分析完后再把tabby.build.enable
设置为false,开启tabby.load.enable
,只做导入,什么情况可能会使用,我已经生成过多个graphdb,我需要根据需要导入,就可以关闭build,只load。
load分析
这个比较简单,先过一下
一共两步,reset和save
reset就是将soot里的一些属性重置。G类是soot里的
接着就是save,可以看到三步,保存到csv,然后再保存到neo4j,最后清除csv
save2CSV,将类、方法、关系都保存。
关系类型分为以下5种,alias(别名)、has(类拥有的方法)、extend、call(方法调用)、interfaces(接口)
最终都是通过@Qquery
注解使用默认的hibernate(CrudRepository
)执行查询,这样就不依赖第三方数据库来转换存储,这可能也是为啥使用springboot的理由之一吧。
接着就是导入neo4j
比如方法导入使用的methodService.importMethodRef()
,如下找到对应csv导入
src/main/java/tabby/dal/neo4j/repository/MethodRefRepository.java,对应如下,可以看到是继承neo4j相关类(Neo4jRepository
),然后也是@Query
来执行,这样只要配置springboot的application.yml,都不需要配置neo4j的连接、执行,非常方便的导入,估计也是因为这使用了springboot。
PS: 如果需要添加其他方法属性,就需要改动这块导入的语句了。
最后的buildEdge也就是导入各种关系类型
最后clean就是删除csv
如果要做调试,查看中间文件csv,其实只需要保留csv的生成即可。
1 2 3 | dataContainer.save2CSV(); // dataContainer.save2Neo4j(); // clean(); |
这样你就能查看一些需要的信息,可以用来排查吧。
build分析
先是获取jdk依赖,3个还是19个,然后收集目标jar、class等,这里判断是否是IS_JDK_ONLY,来判断是收集jdk还是收集指定target目录,接着添加依赖包,。
getTargetDirectoryJarFiles简单来说就是获取目标的所有jar包、war包和class,判断是一个jar包还是目录来选择不同收集方式。这里只是做收集,比如jar包,除非是fatjar,都不会解压成class,只是将路径存放到paths里。
cps和targets都是hashmap,key是md5,value是jar、class等路径。
targets用于存储分析目标,cps用于存储依赖包,会把targets也存储进去
解析过程大致如下