Soot Error: Failed to load java.lang.CharSequence
应用Soot进行控制流和数据依赖分析时,遇到报错:
Exception in thread "main" java.lang.Error: Error: Failed to load java.lang.CharSequence.
at soot.JastAddJ.PathPart.getCompilationUnit(PathPart.java:109)
at soot.JastAddJ.Program.getCompilationUnit(Program.java:873)
at soot.JastAddJ.Program.getLibCompilationUnit_compute(Program.java:1517)
at soot.JastAddJ.Program.getLibCompilationUnit(Program.java:1500)
at soot.JastAddJ.Program.lookupLibType_compute(Program.java:1465)
at soot.JastAddJ.Program.lookupLibType(Program.java:1433)
at soot.JastAddJ.Program.lookupType_compute(Program.java:1412)
at soot.JastAddJ.Program.lookupType(Program.java:1393)
at soot.JastAddJ.Program.Define_TypeDecl_lookupType(Program.java:1981)
问题分析
显而易见,尽管Soot早已支持对Java9以上版本进行分析,但Soot提供的直接针对Java前端代码的分析确是过时的,所以我们的解决方案有两种。
方案一:
降JDK版本,尽管有时这是不能被接受的,但绝对好用。
方案二:
直接分析 .class字节文件。这才是软件分析嘛!(Soot:前端谁惜得管!)
方案二 简易代码示例:
Options.v().set_whole_program(true);
// 容错
Options.v().set_allow_phantom_refs(true);
// 不分析我们的测试代码
// Options.v().set_exclude(getExcluded());
Options.v().set_no_bodies_for_excluded(true);
Options.v().set_prepend_classpath(true);
Options.v().set_process_dir(
Arrays.asList(new String[] { /*这里直接放.class文件路径*/ }));
// 保留变量原始的名字
Options.v().setPhaseOption("jb", "use-original-names:true");
// 保留原始行号
Options.v().set_keep_line_number(true);
// 输出Jimple IR文件到sootOutput目录中,方便调试查看
Options.v().set_output_format(Options.output_format_jimple);
// 加载所有类
Scene.v().loadNecessaryClasses();
String packPhaseName = "jtp";
String transformerPhaseName = "jtp.intra_cp";
Transformer transformer = new TransfornTest();
Transform transform = new Transform(transformerPhaseName, transformer);
PackManager.v().getPack(packPhaseName).add(transform);
// 只分析应用类
for (SootClass appClazz : Scene.v().getApplicationClasses()) {
System.out.println(String.format("===== %s =========", appClazz.getFilePath()));
for (SootMethod method : appClazz.getMethods()) {
Body body = method.retrieveActiveBody();
PackManager.v().getPack(packPhaseName).apply(body);
}
}