-
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 |
- 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
close
method 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
InMemoryHierarchy
feature. - 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 |
// 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) |