-
Notifications
You must be signed in to change notification settings - Fork 17
Soot migration
Alexey Volkov edited this page Dec 20, 2022
·
10 revisions
Terminology:
Soot | JacoDB | |
---|---|---|
bytecode storage | - | JacoDB |
scope of visible classes | Scene | JcClasspath |
class | SootClass | JcClassOrInterface |
class method | SootMethod | JcMethod |
class field | SootField | JcField |
type (with generics substitution) | - | JcJvmType |
3-address bytecode representation | JimpleBody | JcRawInstList |
control flow graph | ClassicCompleteUnitGraph | JcGraph |
class hierarchy | Hierarchy | HierarchyExt |
call graph | CallGraph | UsagesExt |
- Remember to close the resource:
JcClasspath
,JacoDB
. - Creating classpath is a heavy operation involving I/O. All the JAR files or folders passed to a classpath are checked. We check:
- whether they have been processed already,
- whether they have been changed since having been processed before,
- whether they are being processed right now as they have not been processed already.
As a result, the code should try to reuse a classpath instance. After that, we recommend to call the
close
method as JacoDB is able to delete the processed resources which seem to be out of date with regard to the file system.
- If there is a chance that the code calls for class hierarchies, then it's better to install the
InMemoryHierarchy
feature. - Use persisted data in the file system if your code base is huge enough or if living after the process restart is possible.
- Install only those features that are required for this database.
Soot |
// points to specific runtime version
G.v().initJdk(new G.JreInfo(location, version));
Options options = Options.v();
options.set_soot_classpath(files);
Scene.v().loadNecessaryClasses();
PackManager.v().runPacks(); |
JacoDB(Java) |
var db = JacoDB.async(new JcSettings()
// points to specific runtime version
.useJavaRuntime(runtimeFolder)
// jars to process
.loadByteCode(Arrays.asList(jar1, jar2))
// persist all information to improve performance between restarts
.persistent("/home/user/jcdb.db", false)
).get();
var classpath = db.asyncClasspath(listOf(jar1)).get(); |
JacoDB(Kotlin) |
val db = jacodb {
// points to specific runtime version
useJavaRuntime(runtimeFolder)
// jars to process
loadByteCode(listOf(jar1, jar2))
// persist all information to improve performance between restarts
persistent(location = "/home/user/jcdb.db", clearOnStart = false)
}
val classpath = db.classpath(listOf(jar1)) |
Soot |
SootClass clazz = Scene.v().getSootClass("java.lang.String"); |
JacoDB(Java) |
var clazz = classpath.findClassOrNull("java.lang.String") |
JacoDB(Kotlin) |
val clazz = classpath.findClassOrNull("java.lang.String") |
Soot |
SootClass clazz = Scene.v().getSootClass("java.lang.String");
clazz.getMethod("length", Lists.emptyList()).retrieveActiveBody() |
JacoDB(Java) |
var clazz = classpath.findClassOrNull("java.lang.String");
Api.findMethodOrNull(clazz, "length").instructionList(); |
JacoDB(Kotlin) |
val clazz = classpath.findClassOrNull("java.lang.String") ?: throw IllegalStateException()
classpath.findMethodOrNull("length").instructionList() |
Soot |
new ClassicCompleteUnitGraph(sootMethod.getActiveBody()); |
JacoDB(Java) |
var cfg = jcMethod.instructionList().graph() |
JacoDB(Kotlin) |
val cfg = jcMethod.instructionList().graph() |
Soot |
Hierarchy h = new Hierarchy();
h.getDirectSubclassesOf(clazz);
h.getDirectSubinterfacesOf(clazz); |
JacoDB(Java) |
var db = JacoDB.async(new JcSettings()
.install(InMemoryHierarchy.INSTANCE)
).get();
val ext = classpath.asyncHierarchy().get();
ext.findSubClasses(clazz, allHierarchy = true)
ext.findOverrides(method) |
JacoDB(Kotlin) |
val db = jacodb {
// highly recommend to install this extension
install(InMemoryHierarchy)
}
val ext = classpath.hierarchyExt()
ext.findSubClasses(clazz, allHierarchy = true)
ext.findOverrides(method) |
Soot |
CallGraph cg = new CallGraph();
cg.edgesInto(edge);
cg.edgesOutOf(edge); |
JacoDB(Java) |
var db = JacoDB.async(new JcSettings()
// highly recommend to install InMemoryHierarchy extension
.install(InMemoryHierarchy.INSTANCE, Usages.INSTANCE)
).get();
var ext = classpath.asyncUsages();
ext.findUsages(field, FieldUsageMode.READ);
ext.findUsages(field, FieldUsageMode.WRITE);
ext.findUsages(method); |
JacoDB(Kotlin) |
val db = jacodb {
// highly recommend to install InMemoryHierarchy extension
install(Usages, InMemoryHierarchy)
}
val ext = classpath.usagesExt()
ext.findUsages(field, FieldUsageMode.READ)
ext.findUsages(field, FieldUsageMode.WRITE)
ext.findUsages(method) |