-
Notifications
You must be signed in to change notification settings - Fork 18
Soot migration
Alexey Volkov edited this page Dec 13, 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 |
- do not forget to close resource:
JcClasspath,JacoDB. - Creating classpath is a heavy operation involving I/O. All jars/folders passed to classpath are checked for:
- processed before
- has changed since processed before
- processing if they are not processed
As a result good code should try to reuse classpath instance. After that it's recommended to call
closemethod to take JacoDB possibility to delete processed resources that are out-of-date with file-system
- If there is a chance that code will call for class hierarchies then it's better to install
InMemoryHierarchyfeature. - Persist data in file system is usable if your code base is huge enough or live after process restart is possible.
- Install only features that are required for this database.
| Soot | JacoDB |
// 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(); |
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 | JacoDB |
SootClass clazz = Scene.v().getSootClass("java.lang.String"); |
val clazz = classpath.findClassOrNull("java.lang.String") |
| Soot | JacoDB |
SootClass clazz = Scene.v().getSootClass("java.lang.String");
clazz.getMethod("length", Lists.emptyList()).retrieveActiveBody() |
val clazz = classpath.findClassOrNull("java.lang.String") ?: throw IllegalStateException()
classpath.findMethod("length").instructionList() |
| Soot | JacoDB |
new ClassicCompleteUnitGraph(sootMmthod.getActiveBody()); |
val cfg = jcMethod.instructionList().graph() |
| Soot | JacoDB |
Hierarchy h = new Hierarchy();
h.getDirectSubclassesOf(clazz);
h.getDirectSubinterfacesOf(clazz); |
val db = jacodb {
// highly recommend to install this extension
install(InMemoryHierarchy)
}
val ext = classpath.hierarchyExt()
ext.findSubClasses(clazz, allHierarchy = true)
ext.findOverrides(method) |
| Soot | JacoDB |
CallGraph cg = new CallGraph();
cg.edgesInto(edge);
cg.edgesOutOf(edge); |
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) |