From 6d405c8ef35b4d9311173a22594767934249a36d Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 6 Jan 2025 13:13:47 +0000 Subject: [PATCH] Deployed b07b544eed to develop with MkDocs 1.6.1 and mike 2.1.3 --- develop/callgraphs/index.html | 14 +++++++++----- develop/search/search_index.json | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/develop/callgraphs/index.html b/develop/callgraphs/index.html index 776b7986bd..7c2af28af9 100644 --- a/develop/callgraphs/index.html +++ b/develop/callgraphs/index.html @@ -1327,11 +1327,15 @@

Qilin Pointer Analysis

2 3 4 -5
String MAINCLASS = "dacapo.antlr.Main"; // just an example
-PTAPattern ptaPattern = new PTAPattern("insens"); // "2o"=>2OBJ, "1c"=>1CFA, etc.
-PTA pta = PTAFactory.createPTA(ptaPattern, view, MAINCLASS);
-pta.run();
-CallGraph cg = pta.getCallGraph();
+5
+6
+7
```java
+String MAINCLASS = "dacapo.antlr.Main"; // just an example
+PTAPattern ptaPattern = new PTAPattern("insens"); // "2o"=>2OBJ, "1c"=>1CFA, etc.
+PTA pta = PTAFactory.createPTA(ptaPattern, view, MAINCLASS);
+pta.run();
+CallGraph cg = pta.getCallGraph();
+```
 
diff --git a/develop/search/search_index.json b/develop/search/search_index.json index 72e1ca807c..1912ecefa1 100644 --- a/develop/search/search_index.json +++ b/develop/search/search_index.json @@ -1 +1 @@ -{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"What's SootUp?","text":"

SootUp is a complete overhaul of the good, old static analysis framework Soot.

Important

SootUp is not a version update to Soot, it is a completely new implementation written from scratch that aims to be a leaner, modernized and developer friendly successor of Soot. It is not a Drop-In Replacement! The new architecture and API, renders it not trivial to update existing projects that were built on soot. Therefore we recommend using SootUp for greenfield projects. We hope improved type safety and streamlined mechanisms will aide you implementing and debugging your analysis tool. Unfortunately not every feature has been ported - If you miss something feel free to contribute a feature you miss from good old Soot.

"},{"location":"#why-sootup","title":"Why SootUp?","text":"

Over the 20+ years, SootUps predecessor Soot has evolved into a powerful framework, which is one of the most widely used tools in the static analysis community. This evolution was guided by the needs of the community and carried out with ad-hoc improvements. As a result, Soot has become a tool that can do a multitude of things, but it is heavy and hard to maintain and comprehend. So there was the need to clean up the codebase e.g. improve the software architecture, remove legacy datastructures that weren't in the Java Runtime at the time of Soots creation, enforce validation to have a sane state, removing the necessity of arcane knowledge, document it more and more - to make Soot future prove. So we introduced Design changes in SootUp, which aim to address Soot's shortcomings. The goal is a lighter library that can easily be understood and maintained to be included in other projects.

"},{"location":"#supporters","title":"Supporters","text":"

The development of SootUp is financed by generous support from the German Research Foundation (DFG) and the Heinz Nixdorf Institute (HNI).

Become a sponsor!

"},{"location":"analysisinput/","title":"Analysis Input","text":"

i.e. What should be analyzed. An AnalysisInputLocation points to code input SootUp can analyze. We ship multiple Implementations that can handle different input.

Additionally you can specify a SourceType. This determines what is considered e.g. in the CallGraphs generation. Further you can specify a List of BodyInterceptors, which will optimize the raw Jimple IR that was transformed from the input.

"},{"location":"analysisinput/#java-runtime","title":"Java Runtime","text":""},{"location":"analysisinput/#java-8","title":"Java <=8","text":"

The DefaultRTJaAnalysisInputLocation points to the rt.jar of the executing JVM.

AnalysisInputLocation inputLocation = new DefaultRTJaAnalysisInputLocation();\nJavaView view = new JavaView(inputLocation);\n

To include a different Java Runtime library point to any rt.jar via a JavaClassPathAnalysisInputLocation as its a usual .jar file.

"},{"location":"analysisinput/#java-9","title":"Java >=9","text":"

The JRTFilesystemAnalysisInputLocation points to the jigsawed java runtime of the executing JVM.

AnalysisInputLocation inputLocation = new JrtFileSystemAnalysisInputLocation(); \nJavaView view = new JavaView(inputLocation);\n

If you have errors like Java.lang.String, Java.lang.Object, ... you are most likely missing this AnalysisInputLocation.

"},{"location":"analysisinput/#java-bytecode","title":"Java Bytecode","text":"

File-Extensions: .class, .jar, .war

The JavaClassPathAnalysisInputLocation is the equivalent of the classpath you would pass to the java executable i.e. point to root(s) of package(s).

Directory.jar File.class FileComplete class path
AnalysisInputLocation inputLocation =\n        new JavaClassPathAnalysisInputLocation(\"target/\");  // points to\nJavaView view = new JavaView(inputLocation);\n
AnalysisInputLocation inputLocation = new JavaClassPathAnalysisInputLocation(\"myCode.jar\");\nJavaView view1 = new JavaView(inputLocation);\n\n// if you want to analyze a specific language level of a multi release jar\nAnalysisInputLocation inputLocation =\n        new MultiReleaseJarAnalysisInputLocation(\"myCode.jar\", new JavaLanguage(10) );\nJavaView view2 = new JavaView(inputLocation);\n
// if you omit the package structure while pointing to a file,\n// you have to pass the omitted directories as a parameter\nAnalysisInputLocation inputLocation = new PathBasedAnalysisInputLocation.\n            ClassFileBasedAnalysisInputLocation(\"Banana.class\", \"packageName.subPackage\", SourceType.Application);\nJavaView view = new JavaView(inputLocation);\n
String cp = \"myCode.jar\" + File.pathSeparator + \"dependency.jar\" + File.pathSeparator + \"target/classes/\";\nAnalysisInputLocation inputLocation = new JavaClassPathAnalysisInputLocation(cp);\nJavaView view = new JavaView(inputLocation);\n
"},{"location":"analysisinput/#java-sourcecode","title":"Java Sourcecode","text":"

File-Extensions: .java

With the OTFCompileAnalysisInputLocation you can point directly to .java files or pass a String with Java sourcecode. The AnalysisInputLocation delegates the data to the JavaCompiler and transform the bytecode from the compiler to Jimple.

Single FileMultiple FilesFile as String
AnalysisInputLocation inputLocation = new OTFCompileAnalysisInputLocation(\"Banana.java\");\nJavaView view = new JavaView(inputLocation);\n
List<Path> files = Arrays.asList(Paths.get(\"Apple.java\"), Paths.get(\"Banana.java\"));\nAnalysisInputLocation inputLocation = new OTFCompileAnalysisInputLocation(files);\nJavaView view = new JavaView(inputLocation);\n
String content = \"public class B{ }\";\nAnalysisInputLocation location = new OTFCompileAnalysisInputLocation(\"B.java\", content );\nJavaView view = new JavaView(location);\n

JavaSourcePathInputLocation experimental! - points to a directory that is the root source directory (containing the package directory structure).

"},{"location":"analysisinput/#jimple","title":"Jimple","text":"

File-Extensions: .jimple

The JimpleAnalysisInputLocation needs a Path to a .jimple file or a directory.

Path path = Paths.get(\"Banana.java\");\nAnalysisInputLocation jimpleLocation = new JimpleAnalysisInputLocation(path);\nJavaView view = new JavaView(jimpleLocation);\n
"},{"location":"analysisinput/#android-bytecode","title":"Android Bytecode","text":"

File-Extensions: .apk

The ApkAnalysisInputLocation is the APK frontend written for Sootup

Path path = Paths.get(\"Banana.apk\");\nAnalysisInputLocation inputLocation = new ApkAnalysisInputLocation(path, \"\", DexBodyInterceptors.Default.bodyInterceptors());\nJavaView view = new JavaView(inputLocation);\n
"},{"location":"analysisinput/#android-bytecode-with-dex2jar","title":"Android Bytecode with Dex2Jar","text":"

File-Extensions: .apk

If you prefer to use dex2jar as a base to transform android apps to jimple, you can add the code below to create your own analysis input location. We used the dependency de.femtopedia.dex2jar:dex2jar:2.4.22 in the given example. We recommend to use ApkAnalysisInputLocation

Path path = Paths.get(\"Banana.apk\");\nAnalysisInputLocation inputLocation = new Dex2JarAnalysisInputLocation(path);\nJavaView view = new JavaView(inputLocation);\n
public class Dex2JarAnalysisInputLocation extends ArchiveBasedAnalysisInputLocation {\n\n    public Dex2JarAnalysisInputLocation(@Nonnull Path path, @Nullable SourceType srcType) {\n        super(path, srcType);\n        String jarPath = dex2jar(path);\n        this.path = Paths.get(jarPath);\n    }\n\n    private String dex2jar(Path path) {\n        String apkPath = path.toAbsolutePath().toString();\n        String outDir = \"./tmp/\";\n        int start = apkPath.lastIndexOf(File.separator);\n        int end = apkPath.lastIndexOf(\".apk\");\n        String outputFile = outDir + apkPath.substring(start + 1, end) + \".jar\";\n        Dex2jarCmd.main(\"-f\", apkPath, \"-o\", outputFile);\n        return outputFile;\n    }\n}\n
"},{"location":"analysisinput/#combining-multiple-analysisinputlocations","title":"Combining Multiple AnalysisInputLocations","text":"

But what if I want to point to multiple AnalysisInputLocations?

AnalysisInputLocation mainJar = new JavaClassPathAnalysisInputLocation(\"myCode.jar\");\nAnalysisInputLocation jarA = new JavaClassPathAnalysisInputLocation(\"dependencyA.jar\");\nAnalysisInputLocation jarB = new JavaClassPathAnalysisInputLocation(\"dependencyB.jar\");\n\nList<AnalysisInputLocation> inputlocationList = Arrays.asList(mainJar, jarA, jarB);\n\nJavaView view = new JavaView(inputlocationList);\n

Of course you can combine different types of AnalysisInputLocations as well!

"},{"location":"analysisinput/#maven-project-as-analysis-input-in-sootup","title":"Maven Project as Analysis Input in SootUp","text":"

This uses mvn compile + JavaClassPathAnalysisInputLocation under the hood to include a maven project.

    TODO: let the code sail with the upstream boat to this doc.\n

Unfortunately its harder to extract the path of the binary result of Gradle projects in a unified way for all kinds of models - If you have a solution are looking forward to merge your contribution :-).

"},{"location":"analysisinput/#java-cli-arguments-to-configure-sootup","title":"Java cli arguments to configure SootUp","text":"

We created a Utility that parses a String of java command line arguments and configures SootUp respectively.

"},{"location":"announcement/","title":"Announcements","text":""},{"location":"announcement/#release-announcement","title":"Release Announcement","text":"

We would like to announce Soot\u2019s successor, SootUp.

Over more than 20 years, Soot has become one of the world\u2019s most popular academic tool for Java and Android analysis and instrumentation. We thank all of you who have used and contributed to it over the years! It was your feedback and your contributions that helped it grow into such a versatile tool!

However, over the years, the requirements for Soot have changed a lot, and given its original architecture, it was no longer quite up to the task. Soot was originally developed for ahead-of-time code transformation, particularly optimization, which has become very uncommon in Java. Current use cases center much more around powerful program analyses and program-understanding tasks.

Today we are officially releasing SootUp, a new version of Soot with a completely overhauled architecture. With SootUp, we aim to keep the best things about Soot, yet overcome a lot of its drawbacks. We very much restructured Soot, particularly abolishing the heavy use of singletons. Soot now has a concept of views; each view corresponds to some version or variant of an analyzed program, and multiple views can be kept in memory at the same time. This sets the foundation, for instance, for differential or incremental program analyses.

SootUp is a library that can easily be included in other projects, leaving those projects in control. For those who intend to use it as a framework, with inversion of control, SootUp provides additional templates that help you and novices to get started more easily. The Jimple IR has been slightly simplified, and has been made immutable by default such that internally SootUp can make use of caching where desired. Where required, Jimple transformations are still allowed, but in a systematic manner, for instance assuring that analyses depending on the transformed code are notified about its changes.

Below is an overview of what\u2019s new.

SootUp is not a drop-in replacement for Soot! Due to its completely new architecture and API it is essentially an almost complete rewrite. For a while, Soot and SootUp will coexist, as many existing tools depend on Soot, yet our maintenance efforts will henceforth be focused on SootUp, not Soot, and on extending SootUp with those capabilities that people still find missing. For now, we recommend using SootUp for greenfield projects.

For more details, check out

This Page ;-) and The SootUp repository: https://github.com/soot-oss/SootUp/

We are very much looking forward to your feedback and feature requests. To this end, best create appropriate issues in the repository.

This major upgrade of Soot was made possible by generous competitive funding by the DFG, within the project \u201cFuture-proofing the Soot Framework for Program Analysis and Transformation (FutureSoot)\u201d. It was funded in the DFG\u2019s program on Research Software Sustainability.

"},{"location":"bodyinterceptors/","title":"Body Interceptors","text":"

BodyInterceptors are applied to each Body now by default, if not overridden in the used AnalysisInputLocations. The BodyInterceptors exist to to improve and normalize the raw Jimple that was generated in an earlier step. The \"raw\" generated Jimple from the Bytecodefrontend needs a lot improvements - deficits of raw Jimple are:

Optimizations (method scope)

Standardize Jimple appearance

Soot Equivalent

BodyTransformer

"},{"location":"bodyinterceptors/#localsplitter","title":"LocalSplitter","text":"

LocalSplitter is aBodyInterceptorthat attempts to identify and separate uses of a local variable (as definition) that are independent of each other by renaming local variables.

Example 1:

As shown in the example above, the local variablel1is defined twice. It can be split up into two new local variables: l1#1 and l1#2 because the both definitions are independent of each other.

Look for foldable navigation and tabs for showing old vs new

Example 2:

In the second example, the local variablel2is defined thrice. But it cannot be split up into three new local variables as in the first example, because its definitions in the if-branches are not independent of each other. Therefore, it can only be split up into two local variables as shown in the figure.

"},{"location":"bodyinterceptors/#localpacker","title":"LocalPacker","text":"

LocalPacker is aBodyInterceptorthat attempts to minimize the number of local variables which are used in body by reusing them, when it is possible. It corresponds to the inverse body transformation of LocalSplitter. Note: Every local variable's type should be assigned before running LocalPacker.

Example:

In the given example above, the local variablesl1,l3are summarized to be one local variablel1, because they have the same type without interference with each other. Likewise, the local variablesl2,l4andl5are summarized to be another local variablel2. Although the local variablel0doesn't interfere any other local variables, it cannot be summed up with other local variables because of its distinctive type.

"},{"location":"bodyinterceptors/#traptightener","title":"TrapTightener","text":"

WIP - currently not available!

TrapTightener is aBodyInterceptorthat shrinks the protected area covered by each Trap in a Body.

Example:

We assume in the example above that only theStmt:l2 := 2might throw an exception caught by theTrapwhich is labeled withlabel3. In the jimple body before running the TrapTightener, the protected area covered by the Trap contains threeStmts:l1 := 1; l2 := 2; l2 := 3. But an exception could only arise at theStmt:l2 := 2. After the implementation of TrapTightener, we will get a contractible protected area which contains only theStmtthat might throw an exception, namely theStmt:l2 := 2.

"},{"location":"bodyinterceptors/#emptyswitcheliminator","title":"EmptySwitchEliminator","text":"

EmptySwitchEliminator is aBodyInterceptorthat removes empty switch statements which contain only the default case.

Example:

As shown in the example above, the switch statement in the jimple body always takes the default action. After running EmptySwitchEliminator, the switch statement is replaced with aGotoStmtto the default case.

"},{"location":"bodyinterceptors/#unreachablecodeeliminator","title":"UnreachableCodeEliminator","text":"

UnreachableCodeEliminator is aBodyInterceptorthat removes all unreachable statements.

Example:

Obviously, the code segmentl2 = 2; l3 = 3;is unreachable. It will be removed after running the UreachableCodeEliminator.

"},{"location":"bodyinterceptors/#copypropagator","title":"CopyPropagator","text":"

CopyPropagator is a BodyInterceptor that supports copy propagation and constant propagation.

CopyPropagator

\"Definition 3[Copy Propagation]: The use of a variable y in the statement z=x+y occurring at a point p can be replaced by a variable w if every path from the entry node to point p contains the same definition y=w, for the variable y, and after the definition prior to reaching p, there is no redefinition to the variable y and no redefinition to the variable w.\"

Sreekala, S. K. and Vineeth Kumar Paleri. \u201cCopy Propagation subsumes Constant Propagation.\u201d ArXiv abs/2207.03894 (2022): n. pag.

Example for global copy propagation:

Consider a code segment in the following form:

a = b;\n...\nc = use(a); // a, b, c are local variables\n

According to the copy propagation's definition, the statementc = use(a)can be replaced withc = use(b)iff both conditions are met:

In the example for global copy propagation, the first usedl1is replaced withl0, but the second usedl1cannot be replaced withl3, because the second condition is not satisfied.

Example for constant propagation:

Constant propagation is similar to copy propagation. Consider a code segment in the following form:

a = const;\n...\nb = use(a); // a, b are local variables, const is a constant\n

After perfoming the constant propagation, the statementb = use(a)can be replaced withb = use(const)iffais not redefined on any of the paths froma = consttob = use(a).

Therefore, the first usedl1in the second example can be replaced with the constant1, but the second usedl1cannot be replaced with the constant2, becausel1is redefined on the path froml1 = 2tol4 = use(l1). However, it can be replaced with local variablel2, because the both conditions of copy propagation are met.

"},{"location":"bodyinterceptors/#localnamestandardizer","title":"LocalNameStandardizer","text":"

LocalNameStandardizer is aBodyInterceptorthat assigns a generic name to each local variable. Firstly, it will sort the local variables' order alphabetically by the string representation of their type. If there are two local variables with the same type, then the LocalNameStandardizer will use the sequence of their occurrence in jimple body to determine their order. Each assigned name consists of two parts:

The following table shows the letter corresponding to each type:

Type of Local Variable Letter boolean z byte b short s int i long l float f double d char c null n unknown e reference r"},{"location":"bodyinterceptors/#staticsingleassignmentformer","title":"StaticSingleAssignmentFormer","text":"

StaticSingleAssignmentFormer is aBodyInterceptorthat transforms jimple body into SSA form, so that each local variable is assigned exactly once and defined before its first use.

Example:

In the given example, the StaticSingleAssignmentFormer assigns eachIdentityStmtandAssignStmtto a new local variable . And each use uses the local variable which is most recently defined. Sometimes, it is impossible to determine the most recently defined local variable for a use in a join block. In this case, the StaticSingleAssignmentFormer will insert aPhiStmtin the front of the join block to merge all most recently defined local variables and assign them a new local variable.

"},{"location":"builtin-analyses/","title":"BuiltIn Analyses","text":"

More to come!

"},{"location":"builtin-analyses/#locallivenessanalyser","title":"LocalLivenessAnalyser","text":"

LocalLivenessAnalyser is used for querying for the list of live local variables before and after a given Stmt.

Example:

The live local variables before and after each Stmt will be calculated after generating an instance of LocalLivenessAnalyser as shown the example above. They can be queried by using the methods getLiveLocalsBeforeStmt and getLiveLocalsAfterStmt.

"},{"location":"builtin-analyses/#dominancefinder","title":"DominanceFinder","text":"

DomianceFinder is used for querying for the immediate dominator and dominance frontiers for a given basic block.

Example:

After generating an instance of DominanceFinder for a BlockGraph, we will get the immediate dominator and dominance frontiers for each basic block. The both properties can be queried by using the methodsgetImmediateDominatorandgetDominanceFrontiers.

"},{"location":"callgraphs/","title":"Call Graph Construction","text":"

A call graph shows the method calling relationship of a program. It is a directed graph, whose nodes represent different methods, and edges represent caller -> callee relationship.

SootUp contains several call graph construction algorithms. Below, we show how you can use each of these.

"},{"location":"callgraphs/#creating-the-type-hierarchy","title":"Creating the Type Hierarchy","text":"

All the call graph construction algorithms require the view to access the type hierarchy for resolving method calls based of sub typing relationship. Below, we show how to create a type hierarchy:

SootUpSoot
String cpString = \"src/test/resources/Callgraph/binary\";\nList<AnalysisInputLocation> inputLocations = new ArrayList();\ninputLocations.add(new JavaClassPathAnalysisInputLocation(cpStr));\ninputLocations.add(new DefaultRuntimeAnalysisInputLocation());\n\nJavaView view = new JavaView(inputLocations);\n
String userdir = System.getProperty(\"user.dir\");\nString sootCp = userdir + File.separator + \"target\" + File.separator + \"test-classes\"+ File.pathSeparator + \"lib\"+File.separator+\"rt.jar\";\nString targetTestClassName = target.exercise1.Hierarchy.class.getName();\nG.reset();\nOptions.v().set_whole_program(true);\nOptions.v().set_soot_classpath(sootCp);\nOptions.v().set_no_bodies_for_excluded(true);\nOptions.v().process_dir();\nOptions.v().set_allow_phantom_refs(true);\nOptions.v().setPhaseOption(\"jb\", \"use-original-names:true\");\nOptions.v().set_prepend_classpath(false);\nSootClass c = Scene.v().forceResolve(targetTestClassName, SootClass.BODIES);\nif (c != null)\n    c.setApplicationClass();\nScene.v().loadNecessaryClasses();\n\nHierarchy hierarchy = new Hierarchy();\n
"},{"location":"callgraphs/#defining-an-entry-method","title":"Defining an Entry Method","text":"

All call graph construction algorithms require an entry method to start with. In java application, you usually define the main method. However, it is possible to define arbitrary entry methods depending on your needs. Below, we show how to define such an entry method:

SootUp (performant)SootUp (alternative)Soot
JavaClassType classTypeA = view.getIdentifierFactory().getClassType(\"packageNameA.A\");\n\nMethodSignature entryMethodSignature =\n    view.getIdentifierFactory()\n        .getMethodSignature(\n            classTypeA,\n            \"calc\",\n            VoidType.getInstance(),\n            Collections.singletonList(classTypeA)\n        );\n
String methodSigStr = \"<packageNameA.A: void calc(packageNameA.A)\";\nMethodSignature entryMethodSignature = view\n                    .getIdentifierFactory().parseMethodSignature(methodSigStr));\n
String targetTestClassName = \"packageNameA.A\";\nSootMethod src = Scene.v().getSootClass(targetTestClassName).getMethodByName(\"doStuff\");     \n
"},{"location":"callgraphs/#class-hierarchy-analysis","title":"Class Hierarchy Analysis","text":"

Class Hierarchy Analysis (CHA) algorithm is the most sound call graph construction algorithm available in SootUp. It soundly includes all implementers of an interface, when resolving a method call on an interface. You can construct a call graph with CHA as follows:

SootUpSoot
CallGraphAlgorithm cha = new ClassHierarchyAnalysisAlgorithm(view);\n\nCallGraph cg = cha.initialize(Collections.singletonList(entryMethodSignature));\n\ncg.callsFrom(entryMethodSignature).stream()\n    .forEach(tgt -> System.out.println(entryMethodSignature + \" may call \" + tgt);\n
CHATransformer.v().transform();\nSootMethod src = Scene.v().getSootClass(targetTestClassName).getMethodByName(\"doStuff\");\nCallGraph cg = Scene.v().getCallGraph();\nIterator<MethodOrMethodContext> targets = new Targets(cg.edgesOutOf(src));\nwhile (targets.hasNext()) {\n    SootMethod tgt = (SootMethod)targets.next();\n    System.out.println(src + \" may call \" + tgt);\n}\n
"},{"location":"callgraphs/#rapid-type-analysis","title":"Rapid Type Analysis","text":"

Rapid Type Analysis (RTA) algorithm constructs a rather precise version of the call graph that the CHA constructs. It refines CHA by considering only the instantiated implementers of an interface, when resolving a method call on an interface. You can construct a call graph with RTA as follows:

SootUpSoot
CallGraphAlgorithm rta = new RapidTypeAnalysisAlgorithm(view);\n\nCallGraph cg = rta.initialize(Collections.singletonList(entryMethodSignature));\n\ncg.callsFrom(entryMethodSignature).stream()\n    .forEach(tgt -> System.out.println(entryMethodSignature + \" may call \" + tgt);\n
Transform sparkConfig = new Transform(\"cg.spark\", null);\nPhaseOptions.v().setPhaseOption(sparkConfig, \"enabled:true\");\nPhaseOptions.v().setPhaseOption(sparkConfig, \"rta:true\");\nPhaseOptions.v().setPhaseOption(sparkConfig, \"on-fly-cg:false\");\nMap phaseOptions = PhaseOptions.v().getPhaseOptions(sparkConfig);\nSparkTransformer.v().transform(sparkConfig.getPhaseName(), phaseOptions);\nSootMethod src = Scene.v().getSootClass(targetTestClassName).getMethodByName(\"doStuff\");\nCallGraph cg = Scene.v().getCallGraph();\nIterator<MethodOrMethodContext> targets = new Targets(cg.edgesOutOf(src));\nwhile (targets.hasNext()) {\n    SootMethod tgt = (SootMethod)targets.next();\n    System.out.println(src + \" may call \" + tgt);\n}  \n
"},{"location":"callgraphs/#qilin-pointer-analysis","title":"Qilin Pointer Analysis","text":"

Qilin builds a call graph on the fly with the pointer analysis. You can construct a call graph with Qilin as follows:

===\"SootUp\"

String MAINCLASS = \"dacapo.antlr.Main\"; // just an example\nPTAPattern ptaPattern = new PTAPattern(\"insens\"); // \"2o\"=>2OBJ, \"1c\"=>1CFA, etc.\nPTA pta = PTAFactory.createPTA(ptaPattern, view, MAINCLASS);\npta.run();\nCallGraph cg = pta.getCallGraph();\n
"},{"location":"codepropertygraphs/","title":"Code Property Graphs","text":""},{"location":"codepropertygraphs/#dependencies","title":"Dependencies","text":"MavenGradle
<dependency>\n<groupId>org.soot-oss</groupId>\n<artifactId>sootup.codepropertygraph</artifactId>\n<version>1.3.0</version>\n</dependency>\n
compile \"org.soot-oss:sootup.codepropertygraph:1.3.0\"\n

Code Property Graphs (CPGs) are a representation of program code that combines different code representations into a single graph. This unified representation includes abstract syntax trees (ASTs), control flow graphs (CFGs), control dependence graphs (CDGs), and data dependence graphs (DDGs). CPGs enable comprehensive analysis, which makes them a powerful tool for detecting vulnerabilities and understanding code structure. For further details, refer to this thesis.

"},{"location":"codepropertygraphs/#usage-example","title":"Usage Example","text":"

In this example, we will demonstrate how to create a CPG for a vulnerable Java method and use it to identify a potential vulnerability.

"},{"location":"codepropertygraphs/#vulnerable-java-code","title":"Vulnerable Java Code","text":"

Let's assume we have the following vulnerable Java code in a file named VulnerableClass.java:

Java
public class VulnerableClass {\n    public void vulnerableMethod(String userInput) {\n        if (userInput.equals(\"admin\")) {\n            System.out.println(\"Welcome, admin!\");\n        }\n    }\n}\n
"},{"location":"codepropertygraphs/#step-1-obtain-a-sootmethod","title":"Step 1: Obtain a SootMethod","text":"

First, we assume we have a SootMethod for the vulnerableMethod. For instructions on how to obtain a SootMethod, refer to Retrieving a Method.

"},{"location":"codepropertygraphs/#step-2-create-the-cpg","title":"Step 2: Create the CPG","text":"

We can create the CPG subgraphs using the creators.

ASTCFGCDGDDG
public class AstExample {\n\n    public static void main(String[] args) {\n        // Assuming `sootMethod` is obtained from the setup step\n        SootMethod vulnerableMethod = getVulnerableMethod();\n\n        // Create the AST subgraph\n        AstCreator astCreator = new AstCreator();\n        PropertyGraph astGraph = astCreator.createGraph(vulnerableMethod);\n\n        // Print the DOT representation of the AST\n        System.out.println(astGraph.toDotGraph());\n    }\n}\n
public class CfgExample {\n\n    public static void main(String[] args) {\n        // Assuming `sootMethod` is obtained from the setup step\n        SootMethod vulnerableMethod = getVulnerableMethod();\n\n        // Create the CFG subgraph         \n        CfgCreator cfgCreator = new CfgCreator();\n        PropertyGraph cfgGraph = cfgCreator.createGraph(vulnerableMethod);\n\n        // Print the DOT representation of the CFG\n        System.out.println(cfgGraph.toDotGraph());\n    }\n}\n
public class CdgExample {\n\n    public static void main(String[] args) {\n        // Assuming `sootMethod` is obtained from the setup step\n        SootMethod vulnerableMethod = getVulnerableMethod();\n\n        // Create the CDG subgraph\n        CdgCreator cdgCreator = new CdgCreator();\n        PropertyGraph cdgGraph = cdgCreator.createGraph(vulnerableMethod);\n\n        // Print the DOT representation of the CDG\n        System.out.println(cdgGraph.toDotGraph());\n    }\n}\n
public class DdgExample {\n\n    public static void main(String[] args) {\n        // Assuming `sootMethod` is obtained from the setup step\n        SootMethod vulnerableMethod = getVulnerableMethod();\n\n        // Create the DDG subgraph\n        DdgCreator ddgCreator = new DdgCreator();\n        PropertyGraph ddgGraph = ddgCreator.createGraph(vulnerableMethod);\n\n        // Print the DOT representation of the DDG\n        System.out.println(ddgGraph.toDotGraph());\n    }\n}\n

We can create the combined CPG graph using the CpgCreator.

CPG
public class CpgExample {\n\n    public static void main(String[] args) {\n        // Assuming `sootMethod` is obtained from the setup step\n        SootMethod vulnerableMethod = getVulnerableMethod();\n\n        AstCreator astCreator = new AstCreator();\n        CfgCreator cfgCreator = new CfgCreator();\n        CdgCreator cdgCreator = new CdgCreator();\n        DdgCreator ddgCreator = new DdgCreator();\n\n        // Create the combined CPG\n        CpgCreator cpgCreator = new CpgCreator(astCreator, cfgCreator, cdgCreator, ddgCreator);\n        PropertyGraph cpg = cpgCreator.createCpg(vulnerableMethod);\n\n        // Print the DOT representation of the CPG\n        System.out.println(cpg.toDotGraph());\n    }\n}\n
"},{"location":"codepropertygraphs/#step-3-analyzing-the-cpg","title":"Step 3: Analyzing the CPG","text":"

With the CPG created, you can now analyze it for vulnerabilities. For example, you can check for potential injection vulnerabilities by analyzing data flow dependencies.

SootUp
public class VulnerabilityAnalysis {\n\n    public static void main(String[] args) {\n        // Assuming `cpg` is the PropertyGraph created in the previous step\n        for (DdgEdge edge : cpg.getEdges(DdgEdge.class)) {\n            StmtGraphNode source = (StmtGraphNode) edge.getSource();\n            StmtGraphNode destination = (StmtGraphNode) edge.getDestination();\n\n            if (isPotentiallyVulnerable(source, destination)) {\n                System.out.println(\"Potential vulnerability found between: \");\n                System.out.println(\"Source: \" + source.getStmt());\n                System.out.println(\"Destination: \" + destination.getStmt());\n            }\n        }\n    }\n\n    private static boolean isPotentiallyVulnerable(StmtGraphNode source, StmtGraphNode destination) {\n        // Implement your vulnerability detection logic here\n        return source.getStmt().toString().contains(\"userInput\") && \n               destination.getStmt() instanceof JInvokeStmt && \n               destination.getStmt().toString().contains(\"println\");\n    }\n}\n

In this example, we check for data flow dependencies between the userInput variable and any println calls, which could indicate a potential injection vulnerability.

Similarly, we can define our own queries to detect specific patterns that identify common vulnerabilities.

"},{"location":"docguide/","title":"Docguide","text":""},{"location":"docguide/#general","title":"General","text":""},{"location":"docguide/#mkdocsextensions","title":"MkDocsExtensions","text":""},{"location":"docguide/#tooltip","title":"Tooltip","text":"

Hover me

"},{"location":"docguide/#example-file-inclusion","title":"Example File inclusion","text":"

this enables that tutorial code can be tested and will fail if its not up to date anymore :)

package sootup.examples.basicSetup;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport java.nio.file.Path;\nimport java.nio.file.Paths;\nimport java.util.Collections;\nimport org.junit.jupiter.api.Tag;\nimport org.junit.jupiter.api.Test;\nimport sootup.core.inputlocation.AnalysisInputLocation;\nimport sootup.core.jimple.common.expr.JVirtualInvokeExpr;\nimport sootup.core.jimple.common.stmt.JInvokeStmt;\nimport sootup.core.model.SootClass;\nimport sootup.core.model.SootMethod;\nimport sootup.core.model.SourceType;\nimport sootup.core.signatures.MethodSignature;\nimport sootup.core.types.ClassType;\nimport sootup.core.views.View;\nimport sootup.java.bytecode.frontend.inputlocation.PathBasedAnalysisInputLocation;\nimport sootup.java.core.language.JavaJimple;\nimport sootup.java.core.views.JavaView;\n\n/** This example illustrates how to create and use a new Soot Project. */\n@Tag(\"Java8\")\npublic class BasicSetupTest {\n\n  @Test\n  public void createByteCodeProject() {\n    // Create a AnalysisInputLocation, which points to a directory. All class files will be loaded\n    // from the directory\n    Path pathToBinary = Paths.get(\"src/test/resources/BasicSetup/binary\");\n    AnalysisInputLocation inputLocation =\n        PathBasedAnalysisInputLocation.create(pathToBinary, SourceType.Application);\n\n    // Create a view for project, which allows us to retrieve classes\n    View view = new JavaView(inputLocation);\n\n    // Create a signature for the class we want to analyze\n    ClassType classType = view.getIdentifierFactory().getClassType(\"HelloWorld\");\n\n    // Create a signature for the method we want to analyze\n    MethodSignature methodSignature =\n        view.getIdentifierFactory()\n            .getMethodSignature(\n                classType, \"main\", \"void\", Collections.singletonList(\"java.lang.String[]\"));\n\n    // Assert that class is present\n    assertTrue(view.getClass(classType).isPresent());\n\n    // Retrieve class\n    SootClass sootClass = view.getClass(classType).get();\n\n    // Retrieve method\n    view.getMethod(methodSignature);\n\n    // Alternatively:\n    assertTrue(sootClass.getMethod(methodSignature.getSubSignature()).isPresent());\n    SootMethod sootMethod = sootClass.getMethod(methodSignature.getSubSignature()).get();\n\n    // Read jimple code of method\n    System.out.println(sootMethod.getBody());\n\n    // Assert that Hello world print is present\n    assertTrue(\n        sootMethod.getBody().getStmts().stream()\n            .anyMatch(\n                stmt ->\n                    stmt instanceof JInvokeStmt\n                        && ((JInvokeStmt) stmt).getInvokeExpr().get() instanceof JVirtualInvokeExpr\n                        && ((JInvokeStmt) stmt)\n                            .getInvokeExpr()\n                            .get()\n                            .getArg(0)\n                            .equivTo(JavaJimple.getInstance().newStringConstant(\"Hello World!\"))));\n  }\n}\n
"},{"location":"examples/","title":"SootUp Example projects","text":"

Some examples that use SootUp to get insights about a Java program.

Download

The Examples can be cloned or downloaded from our Example Repository.

"},{"location":"faq/","title":"Frequently Asked Questions","text":""},{"location":"faq/#how-to-setup-the-soot-dependency-in-maven-gradle","title":"How to setup the soot dependency (in Maven, Gradle)?","text":"

See Installation.

"},{"location":"faq/#how-to-retreive-a-sootclass-or-sootmethod","title":"How to retreive a SootClass or SootMethod?","text":"

See Getting Started.

"},{"location":"faq/#is-there-a-github-template-to-quickstart-into-development-with-sootup","title":"Is there a github template to quickstart into development with SootUp?","text":"

Not yet.

"},{"location":"faq/#error-while-using-the-sourcecodefrontend","title":"Error while using the Sourcecodefrontend","text":"

Please make sure to use Java8 to execute.

"},{"location":"faq/#exception-provider-jrt-not-found","title":"Exception: Provider \"jrt\" not found","text":"

java.lang.ExceptionInInitializerError\n    at inputlocation.sootup.java.bytecode.frontend.JrtFileSystemAnalysisInputLocationTest.getClassSource(JrtFileSystemAnalysisInputLocationTest.java:28)\n    ...\nCaused by: java.nio.file.ProviderNotFoundException: Provider \"jrt\" not found\n
To execute SootUp with JavaModules support please make sure you run the code at least the Java9 Runtime.

"},{"location":"faq/#how-to-solve-a-concurrentmodificationexception","title":"How to solve a ConcurrentModificationException?","text":"

Copy the Iterator into an intermediate Collection.

final StmtGraph<?> stmtGraph = builder.getStmtGraph();\n    for (Stmt stmt : Lists.newArrayList(stmtGraph)){\n        ...\n    }\n}\n

"},{"location":"faq/#how-can-i-visualize-a-stmtgraph","title":"How can I visualize a StmtGraph?","text":"

There exists a tool, that converts a StmtGraph to the Graphviz Dot Language.

DotExporter.buildGraph( stmtgraph );\n
or create a convenient link with the exported stmtgraph as HTTP GET Parameter
DotExporter.createUrlToWebeditor( stmtgraph );\n

"},{"location":"faq/#the-sourcecodefrontend","title":"The Sourcecodefrontend...","text":"

is in a experimental state! If you wish to use it, please consider to contribute.

"},{"location":"faq/#is-there-a-way-to-use-code-exploration-and-syntax-highlighting-features-in-my-ide-for-jimple-files","title":"Is there a way to use code exploration and syntax highlighting features in my IDE for .jimple files?","text":"

Try JimpeLsp or the vscode plugin

"},{"location":"faq/#is-there-a-way-to-use-syntax-highlighting-of-jimple-in-my-paper-thesis","title":"Is there a way to use syntax highlighting of .jimple in my paper, thesis, ...?","text":"

Have a look at LspLexer4Pygments. Its the same syntax highlighting you see here in the documentation. You can export it to LaTex as well.

"},{"location":"faq/#how-to-add-an-entry-in-this-list-ie-your-question-is-not-answered-here","title":"How to ... add an entry in this list? i.e. Your question is not answered here?","text":"

Feel free to start a Discussion.

"},{"location":"getting-started/","title":"First Steps with SootUp","text":"

Before you get started with the SootUp library, it helps to learn about the following core data structures:

"},{"location":"getting-started/#creating-a-view","title":"Creating a View","text":"

You can use bytecode analysis typically when you do not have access to the source code of the target program. Following example shows how to create a view for analyzing Java bytecode.

Create a view to analyze Java bytecode

AnalysisInputLocation inputLocation = \n        new JavaClassPathAnalysisInputLocation(\"path2Binary\");\n\nJavaView view = new JavaView(inputLocation);\n

If you have access to the source code, it is also possible to create a view for analyzing source code. Following example shows how to create view for analyzing Java source code.

Experimental! - Create a view to analyze Java source code

The source code frontend is experimental and should only be used for testing purposes. Usually you should compile the code for analysis first and use the bytecode frontend instead (see above).

AnalysisInputLocation inputLocation = \n        new JavaSourcePathAnalysisInputLocation(\"path2Source\");\n\nJavaView view = new JavaView(inputLocation);\n

If you have a Jimple file, you can create a view for analyzing jimple code directly. Following example shows how to create a view for analyzing jimple code.

Create a view to analyze jimple code

Path pathToJimple = Paths.get(\"path2Jimple\");\n\nAnalysisInputLocation inputLocation = \n        new JimpleAnalysisInputLocation(pathToJimple);\n\nJimpleView view = new JimpleView(inputLocation);\n

By default, whenever a class is retrieved, it will be permanently stored in a cache. If you do not want retrieved classes to be stored indefinetly, you can instead provide a different CacheProvider to the created view. To for example use an LRUCache instead, which stores at most e.g. 50 classes, and always replaces the least recently used class by a newly retrieved one, use the following call:

JavaView view = new JavaView(inputLocations, new LRUCacheProvider(50));\n
"},{"location":"getting-started/#retrieving-a-class","title":"Retrieving a Class","text":"

Each class is identified with a unique signature adhering to Java identifier rules, therefore you first need to specify the class signature (ClassType) as shown below.

Let's say the following is the target program that we want to analyze:

Target Program

package example;\n\npublic class HelloWorld {\n\n  public HelloWorld() {\n\n  }\n\n  public static void main(String[] args) {\n    HelloWorld hw = new HelloWorld();\n    hw.hello();\n  }\n\n  public void hello() {\n\n  }\n\n}\n

Then, we could define the ClassType of the HelloWorld class as follows:

Defining a ClassType

JavaClassType classType = \n        view.getIdentifierFactory().getClassType(\"example.HelloWorld\");\n

Once we have a ClassType that identifies the HelloWorld class, we can use it to retrieve the corresponding SootClass object from the view as shown below:

Retrieving a SootClass

JavaSootClass sootClass = view.getClass(classType).get();\n
"},{"location":"getting-started/#retrieving-a-method","title":"Retrieving a Method","text":"

Like the classes, methods also have an identifier which we call MethodSignature. For instance, we can define the method signature for identifying the main method of the HelloWorld class as follows:

Defining a MethodSignature

PureParse from String
MethodSignature methodSignature =\n    view\n        .getIdentifierFactory()\n        .getMethodSignature(\n            \"main\", // method name\n            classType,\n            \"void\", // return type\n            Collections.singletonList(\"java.lang.String[]\")); // args\n
MethodSignature methodSignature =\n    view\n        .getIdentifierFactory()\n        .parseMethodSignature(\n            \"<packageName.classType: void main(java.lang.String[])>\");\n

Once we have a MethodSignature that identifies the main method of the HelloWorld class, we can use it to retrieve the corresponding SootMethod object from the view as shown below:

Retrieving a SootMethod from the View

Optional<SootMethod> opt = view.getMethod(methodSignature);\n\nif(!opt.isPresent()){\n    return;\n}\nSootMethod method = opt.get();\nSystem.out.println(method.getModifiers());\n

Alternatively, we can also retrieve a SootMethod from SootClass that contains it.

Retrieving a SootMethod from a SootClass

MethodSubSignature mss = methodSignature.getSubSignature()\nOptional<JavaSootMethod> opt = sootClass.getMethod(mss);\n\nif(opt.isPresent()){\n  JavaSootMethod method = opt.get();\n}\n
"},{"location":"getting-started/#retrieving-the-control-flow-graph-of-a-method","title":"Retrieving the Control-Flow Graph of a Method","text":"

Each SootMethod contains a Control-Flow Graph (CFG) which is represented via the StmtGraph. This structure is usually used for program analysis. You can retrieve the CFG of a SootMethod as follows:

Retrieving the CFG of a SootMethod

StmtGraph<?> graph = sootMethod.getBody().getStmtGraph();\n
"},{"location":"getting-started/#using-the-stmtgraph","title":"Using the StmtGraph","text":"StmtGraph StmtsStmtGraph BlocksStmtGraph DotExport
for( Stmt stmt : graph.nodes()){\n    // pseudo topological order as Stmts would be serialized to a Jimple file.\n}\n\nfor( Stmt stmt : graph.nodes()){\n    // Stmts are unordered!\n}\n
List<BasicBlock<?>> blocks = graph.getBlocks();\nfor( BasicBlock<?> block : blocks){\n    // e.g. check if its a merge point\n    if(block.getPredecessors().size() > 1){\n        ...\n    }\n\n    // e.g. check if its a branching point\n    if(block.getSuccessors().size() > 1){\n        // or use block.getTail() instanceof BranchingStmt\n        ...\n    }\n\n    // e.g. check if thrown exceptions would be caught in this method\n    if(!block.getExceptionalSuccessors().isEmpty()){\n        ...\n    }\n}\n
String urlToWebeditor = DotExporter.createUrlToWebeditor(this);\nSystem.out.println(urlToWebeditor);\n

Access a complete example of the code used above

Download BasicSetup.java

"},{"location":"installation/","title":"Installation","text":""},{"location":"installation/#use-the-latest-develop-branch","title":"Use the latest develop branch","text":"

For configuration options of your build tool please visit SootUp on Jitpack.io

"},{"location":"installation/#use-releases-on-maven-central","title":"Use Releases on Maven Central","text":"

The code below shows you how to import all submodules of the SootUp repository. You can import fewer modules if your use case allows it.

Add the following dependencies to your pom.xml / build.gradle.

MavenGradle
<dependencies>\n    <dependency>\n        <groupId>org.soot-oss</groupId>\n        <artifactId>sootup.core</artifactId>\n        <version>1.3.0</version>\n    </dependency>\n    <dependency>\n        <groupId>org.soot-oss</groupId>\n        <artifactId>sootup.java.core</artifactId>\n        <version>1.3.0</version>\n    </dependency>\n    <dependency>\n        <groupId>org.soot-oss</groupId>\n        <artifactId>sootup.java.sourcecode.frontend</artifactId>\n        <version>1.3.0</version>\n    </dependency>\n    <dependency>\n        <groupId>org.soot-oss</groupId>\n        <artifactId>sootup.java.bytecode.frontend</artifactId>\n        <version>1.3.0</version>\n    </dependency>\n    <dependency>\n        <groupId>org.soot-oss</groupId>\n        <artifactId>sootup.jimple.frontend</artifactId>\n        <version>1.3.0</version>\n    </dependency>\n    <dependency>\n        <groupId>org.soot-oss</groupId>\n        <artifactId>sootup.apk.frontend</artifactId>\n        <version>1.3.0</version>\n    </dependency>\n    <dependency>\n        <groupId>org.soot-oss</groupId>\n        <artifactId>sootup.callgraph</artifactId>\n        <version>1.3.0</version>\n    </dependency>\n    <dependency>\n        <groupId>org.soot-oss</groupId>\n        <artifactId>sootup.analysis.intraprocedural</artifactId>\n        <version>1.3.0</version>\n    </dependency>\n    <dependency>\n        <groupId>org.soot-oss</groupId>\n        <artifactId>sootup.analysis.interprocedural</artifactId>\n        <version>1.3.0</version>\n    </dependency>\n    <dependency>\n        <groupId>org.soot-oss</groupId>\n        <artifactId>sootup.qilin</artifactId>\n        <version>1.3.0</version>\n    </dependency>\n    <dependency>\n        <groupId>org.soot-oss</groupId>\n        <artifactId>sootup.codepropertygraph</artifactId>\n        <version>1.3.0</version>\n    </dependency>\n</dependencies>\n
repositories {\n    mavenCentral()\n    google()\n}\n\ncompile \"org.soot-oss:sootup.core:1.3.0\"\ncompile \"org.soot-oss:sootup.java.core:1.3.0\"\ncompile \"org.soot-oss:sootup.java.sourcecode.frontend:1.3.0\"\ncompile \"org.soot-oss:sootup.java.bytecode.frontend:1.3.0\"\ncompile \"org.soot-oss:sootup.jimple.frontend:1.3.0\"\ncompile \"org.soot-oss:sootup.apk.frontend:1.3.0\"\ncompile \"org.soot-oss:sootup.callgraph:1.3.0\"\ncompile \"org.soot-oss:sootup.analysis.intraprocedural:1.3.0\"\ncompile \"org.soot-oss:sootup.analysis.interprocedural:1.3.0\"\ncompile \"org.soot-oss:sootup.qilin:1.3.0\"\ncompile \"org.soot-oss:sootup.codepropertygraph:1.3.0\"\n
"},{"location":"installation/#build-from-source","title":"Build from Source","text":"

If you'd like to get the most recent changes, you can build SootUp from source yourself and install it into your local maven repository.

git clone https://github.com/secure-software-engineering/SootUp.git\nmvn install\n

"},{"location":"jimple-body/","title":"Jimple Body","text":"

A SootMethod Body consists of the Modifiers and its StmtGraph - SootUps Control Flow Graph Structure. The StmtGraph models the flow of Stmts.

"},{"location":"jimple-body/#control-flow-graph","title":"Control Flow Graph","text":""},{"location":"jimple-body/#stmts","title":"Stmts","text":"

Learn more about the types of Stmts.

"},{"location":"jimple-body/#traps","title":"Traps","text":"

A Trap is a mechanism to model exceptional flow. A Trap represents the try-catch (finally) construct and therefore defines the type of the caught exception, the try-catch range (from-to) and the actual code that handles the exception (handler). In serialized(!) Jimple Labels are used to denote from,to and handler Stmts.

JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\n  public void <init>()\n  {\n    target.exercise1.DemoClass this;\n    this := @this: target.exercise1.DemoClass;\n    specialinvoke this.<java.lang.Object: void <init>()>();\n    return;\n  }\n\n  public void divideExample(int, int)\n  {\n    int x, y, $stack4;\n    java.io.PrintStream $stack5, $stack7;\n    java.lang.Exception $stack6;\n    target.exercise1.DemoClass this;\n\n    this := @this: target.exercise1.DemoClass;\n    x := @parameter0: int;\n    y := @parameter1: int;\n\n   label1:\n      $stack5 = <java.lang.System: java.io.PrintStream out>;\n      $stack4 = x / y;\n      virtualinvoke $stack5.<java.io.PrintStream: void println(int)>($stack4);\n\n   label2:\n      goto label4;\n\n   label3:\n      $stack6 := @caughtexception;\n      $stack7 = <java.lang.System: java.io.PrintStream out>;\n      virtualinvoke $stack7.<java.io.PrintStream: \n        void println(java.lang.String)>(\"Exception caught\");\n\n   label4:\n      return;\n\n      catch java.lang.Exception from label1 to label2 with label3;\n  }\n}\n/*\n  By calling getTraps() method, we can get the Traip chain.\n  For the above jimple code, we have the below trap:\n  Trap :\n  begin  : $stack5 = <java.lang.System: java.io.PrintStream out>\n  end    : goto [?= return]\n  handler: $stack6 := @caughtexception\n*/\n
package target.exercise1;\n\npublic class DemoClass {\n  public void divideExample(int x, int y){\n    try {\n      System.out.println(x / y);\n    }catch (Exception e){\n      System.out.println(\"Exception caught\");\n    }\n  }\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 3 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n    RETURN\n    L1\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0\n    MAXSTACK = 1\n    MAXLOCALS = 1\n\n// access flags 0x1\npublic divideExample(II)V\n  TRYCATCHBLOCK L0 L1 L2 java/lang/Exception\n  L0\n    LINENUMBER 6 L0\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    ILOAD 1\n    ILOAD 2\n    IDIV\n    INVOKEVIRTUAL java/io/PrintStream.println (I)V\n  L1\n    LINENUMBER 9 L1\n    GOTO L3\n  L2\n    LINENUMBER 7 L2\n    FRAME SAME1 java/lang/Exception\n    ASTORE 3\n  L4\n    LINENUMBER 8 L4\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    LDC \"Exception caught\"\n    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V\n  L3\n    LINENUMBER 10 L3\n    FRAME SAME\n    RETURN\n  L5\n    LOCALVARIABLE e Ljava/lang/Exception; L4 L3 3\n    LOCALVARIABLE this Land Ttarget/exercise1/DemoClass; L0 L5 0\n    LOCALVARIABLE x I L0 L5 1\n    LOCALVARIABLE y I L0 L5 2\n    MAXSTACK = 3\n    MAXLOCALS = 4\n}\n
"},{"location":"jimple-stmts/","title":"Jimple Stmt (\"Statement\")","text":"

Stmts represent instructions of the JVM. Jimple is a 3-address form code so there are max 3 operands used in a (\"manipulating\") Stmt - i.e. this does not apply to invokes as this is just operand/parameter passing.

Stmts can be roughly grouped by the amount of successors (in the StmtGraph of a Body of a Method).

"},{"location":"jimple-stmts/#branching-stmts","title":"Branching Stmts","text":"

A BranchingStmt's job is to model the jumps or conditional branching flow between Stmts.

"},{"location":"jimple-stmts/#jgotostmt","title":"JGotoStmt","text":"

represents unconditional jumps to another Stmt.

JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\n  public void <init>()\n  {\n    target.exercise1.DemoClass this;\n    this := @this: target.exercise1.DemoClass;\n    specialinvoke this.<java.lang.Object: void <init>()>();\n    return;\n  }\n  public static void sampleMethod()\n  {\n    int i;\n    i = 0;\n\n    label1:\n      if i >= 5 goto label3;\n      if i != 3 goto label2;\n      goto label3;\n\n    label2:\n      i = i + 1;\n      goto label1;\n\n    label3:\n      return;\n  }\n}\n/*\n  Here for statements \"goto label3;\" and \"goto label1;\", \n  we have two instances of JGotoStmt : \n    \"goto[?=return]\" and \"goto[?=(branch)]\".\n*/\n
package target.exercise1;\n\npublic class DemoClass {\n  public static void sampleMethod(){\n    label1:\n    for (int i = 0; i < 5; i++){\n      if(i == 3){\n        break label1;\n      }\n    }\n  }\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 3 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n    RETURN\n  L1\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0\n    MAXSTACK = 1\n    MAXLOCALS = 1\n\n// access flags 0x9\npublic static sampleMethod()V\n  L0\n    LINENUMBER 6 L0\n    ICONST_0\n    ISTORE 0\n  L1\n    FRAME APPEND [I]\n    ILOAD 0\n    ICONST_5\n    IF_ICMPGE L2\n  L3\n    LINENUMBER 7 L3\n    ILOAD 0\n    ICONST_3\n    IF_ICMPNE L4\n  L5\n    LINENUMBER 8 L5\n    GOTO L2\n  L4\n    LINENUMBER 6 L4\n    FRAME SAME\n    IINC 0 1\n    GOTO L1\n  L2\n    LINENUMBER 11 L2\n    FRAME CHOP 1\n    RETURN\n    LOCALVARIABLE i I L1 L2 0\n    MAXSTACK = 2\n    MAXLOCALS = 1\n}\n
"},{"location":"jimple-stmts/#jifstmt","title":"JIfStmt","text":"

For conditional jumps depending on the result of the conditional expression AbstractConditionExpr which needs to have boolean result. If the conditional expression is false, the next Stmt is the successor as the JIFStmt is also a FallsthroughStmt. Therefore, the JIfStmt has two successor Stmt's.

JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\n   public void <init>()\n  {\n    target.exercise1.DemoClass this;\n    this := @this: target.exercise1.DemoClass;\n    specialinvoke this.<java.lang.Object: void <init>()>();\n    return;\n  }\n\n  public static void sampleMethod(int)\n  {\n    int x, $stack1;\n    java.io.PrintStream $stack2, $stack3;\n\n    x := @parameter0: int;\n\n    $stack1 = x % 2;\n    if $stack1 != 0 goto label1;\n\n    $stack3 = <java.lang.System: java.io.PrintStream out>;\n    virtualinvoke $stack3.<java.io.PrintStream: \n      void println(java.lang.String)>(\"Even\");\n    goto label2;\n\n    label1:\n      $stack2 = <java.lang.System: java.io.PrintStream out>;\n      virtualinvoke $stack2.<java.io.PrintStream: \n        void println(java.lang.String)>(\"Odd\");\n\n    label2:\n      return;\n  }\n}\n/*\n  For statement \"if $stack1 != 0 goto label1;\", \n  we have an instance of JIfStmt :\n    \"if $stack1 != 0 goto $stack2 \n        = <java.lang.System:java.io.PrintStream out>\".\n*/\n
package target.exercise1;\n\npublic class DemoClass {\n  public static void sampleMethod(int x){\n    if(x % 2 == 0){\n      System.out.println(\"Even\");\n    }else{\n      System.out.println(\"Odd\");\n    }\n  }\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 3 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n    RETURN\n  L1\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0\n    MAXSTACK = 1\n    MAXLOCALS = 1\n\n// access flags 0x9\npublic static sampleMethod(I)V\n  L0\n    LINENUMBER 5 L0\n    ILOAD 0\n    ICONST_2\n    IREM\n    IFNE L1\n  L2\n    LINENUMBER 6 L2\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    LDC \"Even\"\n    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V\n    GOTO L3\n  L1\n    LINENUMBER 8 L1\n    FRAME SAME\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    LDC \"Odd\"\n    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V\n  L3\n    LINENUMBER 10 L3\n    FRAME SAME\n    RETURN\n  L4\n    LOCALVARIABLE x I L0 L4 0\n    MAXSTACK = 2\n    MAXLOCALS = 1\n}\n
"},{"location":"jimple-stmts/#jswitchstmt","title":"JSwitchStmt","text":"

for conditional flow that behaves like a switch-case. It has #numberOfCaseLabels+1 (for default) successor Stmt's.

JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\n  public void <init>()\n  {\n    target.exercise1.DemoClass this;\n    this := @this: target.exercise1.DemoClass;\n    specialinvoke this.<java.lang.Object: void <init>()>();\n    return;\n  }\n\n  public void switchExample(int)\n  {\n    int x;\n    java.io.PrintStream $stack2, $stack3, $stack4;\n    target.exercise1.DemoClass this;\n\n    this := @this: target.exercise1.DemoClass;\n    x := @parameter0: int;\n\n    lookupswitch(x)\n    {\n      case 1: goto label1;\n      case 2: goto label2;\n      default: goto label3;\n    };\n\n    label1:\n      $stack3 = <java.lang.System: java.io.PrintStream out>;\n      virtualinvoke $stack3.<java.io.PrintStream: \n        void println(java.lang.String)>(\"Input 1\");\n      goto label4;\n\n    label2:\n      $stack2 = <java.lang.System: java.io.PrintStream out>;\n      virtualinvoke $stack2.<java.io.PrintStream: \n        void println(java.lang.String)>(\"Input 2\");\n      goto label4;\n\n    label3:\n      $stack4 = <java.lang.System: java.io.PrintStream out>;\n      virtualinvoke $stack4.<java.io.PrintStream: \n        void println(java.lang.String)>(\"Input more than 2\");\n\n    label4:\n      return;\n  }\n}\n/*\n  Here for below statement:\n    lookupswitch(x)\n      {\n        case 1: goto label1;\n        case 2: goto label2;\n        default: goto label3;\n      };\n\n  we have an instance of JLookupSwitchStmt :\n    lookupswitch(x) \n      {     \n        case 1: goto $stack3 \n                        = <java.lang.System: java.io.PrintStream out>;     \n        case 2: goto $stack2 \n                        = <java.lang.System: java.io.PrintStream out>;     \n        default: goto $stack4 \n                        = <java.lang.System: java.io.PrintStream out>; \n      }\n*/\n
package target.exercise1;\n\npublic class DemoClass {\n  public void switchExample(int x){\n    switch (x){\n      case 1:\n        System.out.println(\"Input 1\");\n        break;\n\n      case 2:\n        System.out.println(\"Input 2\");\n        break;\n\n      default:\n        System.out.println(\"Input more than 2\");\n        break;\n\n    }\n  }\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 3 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n    RETURN\n  L1\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0\n    MAXSTACK = 1\n    MAXLOCALS = 1\n\n// access flags 0x1\npublic switchExample(I)V\n  L0\n    LINENUMBER 5 L0\n    ILOAD 1\n    LOOKUPSWITCH\n    1: L1\n    2: L2\n    default: L3\n  L1\n    LINENUMBER 7 L1\n    FRAME SAME\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    LDC \"Input 1\"\n    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V\n  L4\n    LINENUMBER 8 L4\n    GOTO L5\n  L2\n    LINENUMBER 11 L2\n    FRAME SAME\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    LDC \"Input 2\"\n    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V\n  L6\n    LINENUMBER 12 L6\n    GOTO L5\n  L3\n    LINENUMBER 15 L3\n    FRAME SAME\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    LDC \"Input more than 2\"\n    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V\n  L5\n    LINENUMBER 19 L5\n    FRAME SAME\n    RETURN\n  L7\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L7 0\n    LOCALVARIABLE x I L0 L7 1\n    MAXSTACK = 2\n    MAXLOCALS = 2\n}\n
"},{"location":"jimple-stmts/#fallsthrough-stmts","title":"FallsThrough Stmts","text":"

The execution of a FallsthroughStmt goes on with the following Stmt (if no exception was thrown).

"},{"location":"jimple-stmts/#jinvokestmt","title":"JInvokeStmt","text":"

transfers the control flow to another method until the called method returns.

JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\n  public void <init>()\n  {\n    target.exercise1.DemoClass this;\n    this := @this: target.exercise1.DemoClass;\n    specialinvoke this.<java.lang.Object: void <init>()>();\n    return;\n  }\n\n  public void print(int)\n  {\n    target.exercise1.DemoClass this;\n    int x, a;\n    java.io.PrintStream $stack4, $stack6;\n\n    this := @this: target.exercise1.DemoClass;\n    x := @parameter0: int;\n\n    a = virtualinvoke this.<target.exercise1.DemoClass: int increment(int)>(x);\n    $stack4 = <java.lang.System: java.io.PrintStream out>;\n    virtualinvoke $stack4.<java.io.PrintStream: void println(int)>(a);\n\n    a = virtualinvoke this.<target.exercise1.DemoClass: int increment(int)>(a);\n    $stack6 = <java.lang.System: java.io.PrintStream out>;\n    virtualinvoke $stack6.<java.io.PrintStream: void println(int)>(a);\n\n    return;\n  }\n\n  public int increment(int)\n  {\n    int x, $stack2;\n    target.exercise1.DemoClass this;\n\n    this := @this: target.exercise1.DemoClass;\n    x := @parameter0: int;\n\n    $stack2 = x + 1;\n    return $stack2;\n  }\n}\n/*\n  \"specialinvoke this.<java.lang.Object: void <init>()>()\", \n  \"virtualinvoke this.<target.exercise1.DemoClass: int increment(int)>(x)\", \n  \"virtualinvoke this.<target.exercise1.DemoClass: int increment(int)>(a)\" \n    are JInvokeStmts.\n*/\n
package target.exercise1;\n\npublic class DemoClass {\n  public void print(int x){\n    int a = increment(x);\n    System.out.println(a);\n    a = increment(a);\n    System.out.println(a);\n  }\n  public int increment(int x){\n    return x + 1;\n  }\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 3 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n    RETURN\n  L1\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0\n    MAXSTACK = 1\n    MAXLOCALS = 1\n\n// access flags 0x1\npublic print(I)V\n  L0\n    LINENUMBER 5 L0\n    ALOAD 0\n    ILOAD 1\n    INVOKEVIRTUAL target/exercise1/DemoClass.increment (I)I\n    ISTORE 2\n  L1\n    LINENUMBER 6 L1\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    ILOAD 2\n    INVOKEVIRTUAL java/io/PrintStream.println (I)V\n  L2\n    LINENUMBER 7 L2\n    ALOAD 0\n    ILOAD 2\n    INVOKEVIRTUAL target/exercise1/DemoClass.increment (I)I\n    ISTORE 2\n  L3\n    LINENUMBER 8 L3\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    ILOAD 2\n    INVOKEVIRTUAL java/io/PrintStream.println (I)V\n  L4\n    LINENUMBER 9 L4\n    RETURN\n  L5\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L5 0\n    LOCALVARIABLE x I L0 L5 1\n    LOCALVARIABLE a I L1 L5 2\n    MAXSTACK = 2\n    MAXLOCALS = 3\n\n// access flags 0x1\npublic increment(I)I\n  L0\n    LINENUMBER 11 L0\n    ILOAD 1\n    ICONST_1\n    IADD\n    IRETURN\n  L1\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0\n    LOCALVARIABLE x I L0 L1 1\n    MAXSTACK = 2\n    MAXLOCALS = 2\n}\n
"},{"location":"jimple-stmts/#jassignstmt","title":"JAssignStmt","text":"

assigns a Value from the right hand-side to the left hand-side. Left hand-side of an assignment can be a Local referencing a variable (i.e. a Local) or a FieldRef referencing a Field. Right hand-side of an assignment can be an expression (Expr), a Local, a FieldRef or a Constant.

JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\n  public void <init>()\n  {\n    target.exercise1.DemoClass this;\n    this := @this: target.exercise1.DemoClass;\n    specialinvoke this.<java.lang.Object: void <init>()>();\n    this.<target.exercise1.DemoClass: int counter> = 0;\n    return;\n  }\n\n  public int updateCounter()\n  {\n    target.exercise1.DemoClass this;\n    int $stack1, $stack2, $stack3;\n\n    this := @this: target.exercise1.DemoClass;\n\n    $stack1 = this.<target.exercise1.DemoClass: int counter>;\n    $stack2 = $stack1 + 1;\n    this.<target.exercise1.DemoClass: int counter> = $stack2;\n    $stack3 = this.<target.exercise1.DemoClass: int counter>;\n\n    return $stack3;\n  }\n}\n/*\n  \"this.<target.exercise1.DemoClass: int counter> = 0\", \n  \"$stack1 = this.<target.exercise1.DemoClass: int counter>\",\n  \"$stack2 = $stack1 + 1\"\n  \"this.<target.exercise1.DemoClass: int counter> = $stack2\"\n  \"$stack3 = this.<target.exercise1.DemoClass: int counter>\"\n    are JAssignStmts.\n*/\n
package target.exercise1;\n\npublic class DemoClass {\n  private int counter = 0;\n  public int updateCounter(){\n    counter = counter + 1;\n    return counter;\n  }\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x2\nprivate I counter\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 3 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n  L1\n    LINENUMBER 4 L1\n    ALOAD 0\n    ICONST_0\n    PUTFIELD target/exercise1/DemoClass.counter : I\n    RETURN\n  L2\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L2 0\n    MAXSTACK = 2\n    MAXLOCALS = 1\n\n// access flags 0x1\npublic updateCounter()I\n  L0\n    LINENUMBER 6 L0\n    ALOAD 0\n    ALOAD 0\n    GETFIELD target/exercise1/DemoClass.counter : I\n    ICONST_1\n    IADD\n    PUTFIELD target/exercise1/DemoClass.counter : I\n  L1\n    LINENUMBER 7 L1\n    ALOAD 0\n    GETFIELD target/exercise1/DemoClass.counter : I\n    IRETURN\n  L2\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L2 0\n    MAXSTACK = 3\n    MAXLOCALS = 1\n}\n
"},{"location":"jimple-stmts/#jidentitystmt","title":"JIdentityStmt","text":"

is similar to the JAssignStmt and but handles assignments of IdentityRefs to make implicit assignments explicit into the StmtGraph.

JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\n  public void <init>()\n  {\n    target.exercise1.DemoClass this;\n    this := @this: target.exercise1.DemoClass;\n    specialinvoke this.<java.lang.Object: void <init>()>();\n    return;\n  }\n\n  public void DemoClass(int)\n  {\n    target.exercise1.DemoClass this;\n    int counter;\n\n    this := @this: target.exercise1.DemoClass;\n    counter := @parameter0: int;\n    this.<target.exercise1.DemoClass: int counter> = counter;\n    return;\n  }\n}\n/*\n  \"this := @this: target.exercise1.DemoClass\" and \n    \"counter := @parameter0: int\" are JIdentityStmts\n*/\n
package target.exercise1;\n\npublic class DemoClass {\n  private int counter;\n  public void DemoClass(int counter){\n    this.counter = counter;\n  }\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x2\nprivate I counter\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 3 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n    RETURN\n  L1\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0\n    MAXSTACK = 1\n    MAXLOCALS = 1\n\n// access flags 0x1\npublic DemoClass(I)V\n  L0\n    LINENUMBER 6 L0\n    ALOAD 0\n    ILOAD 1\n    PUTFIELD target/exercise1/DemoClass.counter : I\n  L1\n    LINENUMBER 7 L1\n    RETURN\n  L2\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L2 0\n    LOCALVARIABLE counter I L0 L2 1\n    MAXSTACK = 2\n    MAXLOCALS = 2\n}\n
"},{"location":"jimple-stmts/#jentermonitorstmt-jexitmonitorstmt","title":"JEnterMonitorStmt & JExitMonitorStmt","text":"

marks synchronized blocks of code from JEnterMonitorStmt to JExitMonitorStmt.

JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\n  public void <init>()\n  {\n    target.exercise1.DemoClass this;\n    this := @this: target.exercise1.DemoClass;\n    specialinvoke this.<java.lang.Object: void <init>()>();\n    this.<target.exercise1.DemoClass: int counter> = 0;\n    return;\n  }\n\n  public int updateCounter()\n  {\n    target.exercise1.DemoClass this;\n    int $stack4, $stack5, $stack7;\n    java.lang.Throwable $stack8;\n\n    this := @this: target.exercise1.DemoClass;\n\n    entermonitor this;\n\n    label1:\n      $stack4 = this.<target.exercise1.DemoClass: int counter>;\n      $stack5 = $stack4 + 1;\n      this.<target.exercise1.DemoClass: int counter> = $stack5;\n\n      exitmonitor this;\n\n    label2:\n      goto label5;\n\n    label3:\n      $stack8 := @caughtexception;\n\n      exitmonitor this;\n\n    label4:\n      throw $stack8;\n\n    label5:\n      $stack7 = this.<target.exercise1.DemoClass: int counter>;\n      return $stack7;\n\n      catch java.lang.Throwable from label1 to label2 with label3;\n      catch java.lang.Throwable from label3 to label4 with label3;\n  }\n}\n/*\n  \"entermonitor this\" is JEnterMonitorStmt.\n  \"exitmonitor this\" is JExitMonitorStmt.\n*/\n
package target.exercise1;\n\npublic class DemoClass {\n  private int counter = 0;\n  public int updateCounter(){\n    synchronized (this) {\n      counter = counter + 1;\n    }\n    return counter;\n  }\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x2\nprivate I counter\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 3 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n  L1\n    LINENUMBER 4 L1\n    ALOAD 0\n    ICONST_0\n    PUTFIELD target/exercise1/DemoClass.counter : I\n    RETURN\n  L2\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L2 0\n    MAXSTACK = 2\n    MAXLOCALS = 1\n\n// access flags 0x1\npublic updateCounter()I\n    TRYCATCHBLOCK L0 L1 L2 null\n    TRYCATCHBLOCK L2 L3 L2 null\n  L4\n    LINENUMBER 6 L4\n    ALOAD 0\n    DUP\n    ASTORE 1\n    MONITORENTER\n  L0\n    LINENUMBER 7 L0\n    ALOAD 0\n    ALOAD 0\n    GETFIELD target/exercise1/DemoClass.counter : I\n    ICONST_1\n    IADD\n    PUTFIELD target/exercise1/DemoClass.counter : I\n  L5\n    LINENUMBER 8 L5\n    ALOAD 1\n    MONITOREXIT\n  L1\n    GOTO L6\n  L2\n    FRAME FULL [target/exercise1/DemoClass java/lang/Object] \n      [java/lang/Throwable]\n    ASTORE 2\n    ALOAD 1\n    MONITOREXIT\n  L3\n    ALOAD 2\n    ATHROW\n  L6\n    LINENUMBER 9 L6\n    FRAME CHOP 1\n    ALOAD 0\n    GETFIELD target/exercise1/DemoClass.counter : I\n    IRETURN\n  L7\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L4 L7 0\n    MAXSTACK = 3\n    MAXLOCALS = 3\n}\n
"},{"location":"jimple-stmts/#jretstmt","title":"JRetStmt","text":"

// TODO: java 1.6 spec

"},{"location":"jimple-stmts/#jbreakpointstmt","title":"JBreakpointStmt","text":"

models a Breakpoint set by a Debugger. Therefore, not really relevant for static analyses but useful for code generation.

"},{"location":"jimple-stmts/#other-stmts","title":"Other Stmts","text":""},{"location":"jimple-stmts/#jreturnstmt-jreturnvoidstmt","title":"JReturnStmt & JReturnVoidStmt","text":"

They end the execution/flow inside the current method and return (a value) to its caller.

JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\n  public void <init>()\n  {\n    target.exercise1.DemoClass this;\n    this := @this: target.exercise1.DemoClass;\n    specialinvoke this.<java.lang.Object: void <init>()>();\n    return;\n  }\n\n  public int increment(int)\n  {\n    int x, $stack2;\n    target.exercise1.DemoClass this;\n\n    this := @this: target.exercise1.DemoClass;\n    x := @parameter0: int;\n\n    $stack2 = x + 1;\n    return $stack2;\n  }\n\n  public void print()\n  {\n    java.io.PrintStream $stack1;\n    target.exercise1.DemoClass this;\n\n    this := @this: target.exercise1.DemoClass;\n    $stack1 = <java.lang.System: java.io.PrintStream out>;\n    virtualinvoke $stack1.<java.io.PrintStream: \n      void println(java.lang.String)>(\"Inside method print\");\n    return;\n  }\n}\n/*\n  \"return $stack2\" is JReturnStmt.\n  \"return\" is JReturnVoidStmt.\n*/\n
package target.exercise1;\n\npublic class DemoClass {\n  public int increment(int x){\n    return x + 1;\n  }\n  public void print(){\n    System.out.println(\"Inside method print\");\n  }\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 3 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n    RETURN\n  L1\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0\n    MAXSTACK = 1\n    MAXLOCALS = 1\n\n// access flags 0x1\npublic increment(I)I\n  L0\n    LINENUMBER 5 L0\n    ILOAD 1\n    ICONST_1\n    IADD\n    IRETURN\n  L1\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0\n    LOCALVARIABLE x I L0 L1 1\n    MAXSTACK = 2\n    MAXLOCALS = 2\n\n// access flags 0x1\npublic print()V\n  L0\n    LINENUMBER 8 L0\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    LDC \"Inside method print\"\n    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V\n  L1\n    LINENUMBER 9 L1\n    RETURN\n  L2\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L2 0\n    MAXSTACK = 2\n    MAXLOCALS = 1\n}\n
"},{"location":"jimple-stmts/#jthrowstmt","title":"JThrowStmt","text":"

Ends the execution inside the current Method if the thrown exception is not caught by a Trap, which redirects the execution to an exceptionhandler.

JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\n  public void <init>()\n  {\n    target.exercise1.DemoClass this;\n    this := @this: target.exercise1.DemoClass;\n    specialinvoke this.<java.lang.Object: void <init>()>();\n    return;\n  }\n\n  public void divideExample(int, int)\n  {\n    int y, x, $stack6;\n    java.lang.StringBuilder $stack3, $stack5, $stack7;\n    java.io.PrintStream $stack4;\n    java.lang.String $stack8;\n    java.lang.RuntimeException $stack9;\n    target.exercise1.DemoClass this;\n\n    this := @this: target.exercise1.DemoClass;\n    x := @parameter0: int;\n    y := @parameter1: int;\n\n    if y != 0 goto label1;\n\n    $stack9 = new java.lang.RuntimeException;\n    specialinvoke $stack9.<java.lang.RuntimeException: \n      void <init>(java.lang.String)>(\"Divide by zero error\");\n    throw $stack9;\n\n    label1:\n      $stack4 = <java.lang.System: java.io.PrintStream out>;\n      $stack3 = new java.lang.StringBuilder;\n      specialinvoke $stack3.<java.lang.StringBuilder: void <init>()>();\n\n      $stack5 = virtualinvoke $stack3.<java.lang.StringBuilder: \n        java.lang.StringBuilder append(java.lang.String)>(\"Divide result : \");\n      $stack6 = x / y;\n      $stack7 = virtualinvoke $stack5.<java.lang.StringBuilder: \n        java.lang.StringBuilder append(int)>($stack6);\n      $stack8 = virtualinvoke $stack7.<java.lang.StringBuilder: \n        java.lang.String toString()>();\n\n      virtualinvoke $stack4.<java.io.PrintStream: \n        void println(java.lang.String)>($stack8);\n      return;\n  }\n}\n/*\n  \"throw $stack9\" is JThrowStmt.\n*/\n
package target.exercise1;\n\npublic class DemoClass {\n  public void divideExample(int x, int y){\n    if(y == 0){\n      throw new RuntimeException(\"Divide by zero error\");\n    }\n    System.out.println(\"Divide result : \" + x / y);\n  }\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 3 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n    RETURN\n  L1\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0\n    MAXSTACK = 1\n    MAXLOCALS = 1\n\n// access flags 0x1\npublic divideExample(II)V\n  L0\n    LINENUMBER 5 L0\n    ILOAD 2\n    IFNE L1\n  L2\n    LINENUMBER 6 L2\n    NEW java/lang/RuntimeException\n    DUP\n    LDC \"Divide by zero error\"\n    INVOKESPECIAL java/lang/RuntimeException.<init> \n      (Ljava/lang/String;)V\n    ATHROW\n  L1\n    LINENUMBER 8 L1\n    FRAME SAME\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    NEW java/lang/StringBuilder\n    DUP\n    INVOKESPECIAL java/lang/StringBuilder.<init> ()V\n    LDC \"Divide result : \"\n    INVOKEVIRTUAL java/lang/StringBuilder.append \n      (Ljava/lang/String;)Ljava/lang/StringBuilder;\n    ILOAD 1\n    ILOAD 2\n    IDIV\n    INVOKEVIRTUAL java/lang/StringBuilder.append \n      (I)Ljava/lang/StringBuilder;\n    INVOKEVIRTUAL java/lang/StringBuilder.toString \n      ()Ljava/lang/String;\n    INVOKEVIRTUAL java/io/PrintStream.println \n      (Ljava/lang/String;)V\n  L3\n    LINENUMBER 9 L3\n    RETURN\n  L4\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L4 0\n    LOCALVARIABLE x I L0 L4 1\n    LOCALVARIABLE y I L0 L4 2\n    MAXSTACK = 4\n    MAXLOCALS = 3\n}\n
"},{"location":"jimple-stmts/#good-to-know","title":"Good to know","text":"

A lot of the SootUp APIs return the Stmt Interface. To determine and handle its subtypes you can make use of instanceof.

instanceOf & If-Else
    List<Stmt> stmts = ... ;\n    for( Stmt stms : stmts ){\n        if(stmt instanceof JAssignStmt){\n            // found a JAssignStmt\n            Value rhsOp = ((JAssignStmt) stmt).getRightOp();\n            ...\n        }else if(stmt instanceof JInvokeStmt){\n            // found a JInvokeStmt\n            JInvokeStmt ivkStmt = ((JInvokeStmt) stmt);\n            MethodSignature rhsOp = ivkStmt.getInvokeExpr().getMethodSignature();\n                ...\n        }else ...\n    }\n

But this could escalate to a huge if-else-tree - almost a forest. To mitigate such scenario you can implement a subclass of AbstractStmtVisitor. Just subclass the methods to the respective Stmts you need to handle. This is visitor acts like a switch-case, implemented via two dynamic calls.

StmtVisitor
    List<Stmt> stmts = ...;\n    AbstractStmtVisitor visitor = new AbstractStmtVisitor<Integer>() {\n        private int ifStmtsCounter = 0;\n        @Override\n        public void caseIfStmt(@Nonnull JIfStmt stmt) {\n            ifStmtsCounter++;\n            setResult(ifStmtCounter);\n        }\n    };\n\n    for( Stmt stms : stmts ){\n        stmt.accept(visitor);\n    }\n\n    int amountOfIfStmts = visitor.getResult();\n

Sidenote: Of course its possible can create a subclass instead of an anonymous class.

"},{"location":"jimple-types/","title":"Jimple Types","text":"

represents primary types i.e. non-reference types and non-void

"},{"location":"jimple-types/#primarytype","title":"PrimaryType","text":" JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\n  public void <init>()\n  {\n      target.exercise1.DemoClass this;\n      this := @this: target.exercise1.DemoClass;\n      specialinvoke this.<java.lang.Object: void <init>()>();\n      return;\n  }\n\n\n  public void display()\n  {\n      java.io.PrintStream $stack11, $stack13, $stack15, \n        $stack17, $stack19, $stack21, $stack23, $stack25;\n      int $stack12, $stack14, $stack16, $stack18;\n      long $stack20;\n      double $stack22;\n      float $stack24;\n      target.exercise1.DemoClass this;\n      boolean $stack26;\n\n      this := @this: target.exercise1.DemoClass;\n\n      $stack11 = <java.lang.System: java.io.PrintStream out>;\n\n      goto label1;\n\n   label1:\n      $stack26 = 0;\n      virtualinvoke $stack11.<java.io.PrintStream: \n        void println(boolean)>($stack26);\n\n      $stack13 = <java.lang.System: java.io.PrintStream out>;\n      $stack12 = 127 - 1;\n      virtualinvoke $stack13.<java.io.PrintStream: \n        void println(int)>($stack12);\n\n      $stack15 = <java.lang.System: java.io.PrintStream out>;\n      $stack14 = 97 + 1;\n      virtualinvoke $stack15.<java.io.PrintStream: \n        void println(int)>($stack14);\n\n      $stack17 = <java.lang.System: java.io.PrintStream out>;\n      $stack16 = 1123 + 1;\n      virtualinvoke $stack17.<java.io.PrintStream: \n        void println(int)>($stack16);\n\n      $stack19 = <java.lang.System: java.io.PrintStream out>;\n      $stack18 = 123456 + 1;\n      virtualinvoke $stack19.<java.io.PrintStream: \n        void println(int)>($stack18);\n\n      $stack21 = <java.lang.System: java.io.PrintStream out>;\n      $stack20 = 10L + 1L;\n      virtualinvoke $stack21.<java.io.PrintStream: \n        void println(long)>($stack20);\n\n      $stack23 = <java.lang.System: java.io.PrintStream out>;\n      $stack22 = 10.1 + 1.0;\n      virtualinvoke $stack23.<java.io.PrintStream: \n        void println(double)>($stack22);\n\n      $stack25 = <java.lang.System: java.io.PrintStream out>;\n      $stack24 = 10.1F + 1.0F;\n      virtualinvoke $stack25.<java.io.PrintStream: \n        void println(float)>($stack24);\n\n      return;\n  }\n}\n/*\n  The JimpleLocal $stack12, $stack14, $stack16, $stack18 are of IntType. \n  Similarly, $stack20 is of LongType, $stack22 is of DoubleType and so on.\n*/\n
package target.exercise1;\n\npublic class DemoClass {\n  public void display(){\n    boolean varBoolean = true;\n    byte varByte = 127;\n    char varChar = 'a';\n    short varShort = 1123;\n    int varInt = 123456;\n    long varLong = 10L;\n    double varDouble = 10.10;\n    float varFloat = 10.10f;\n\n    System.out.println(!varBoolean);\n    System.out.println(varByte-1);\n    System.out.println(varChar+1);\n    System.out.println(varShort+1);\n    System.out.println(varInt+1);\n    System.out.println(varLong+1);\n    System.out.println(varDouble+1);\n    System.out.println(varFloat+1);\n\n  }\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 3 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n    RETURN\n  L1\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0\n    MAXSTACK = 1\n    MAXLOCALS = 1\n\n// access flags 0x1\npublic display()V\n  L0\n    LINENUMBER 5 L0\n    ICONST_1\n    ISTORE 1\n  L1\n    LINENUMBER 6 L1\n    BIPUSH 127\n    ISTORE 2\n  L2\n    LINENUMBER 7 L2\n    BIPUSH 97\n    ISTORE 3\n  L3\n    LINENUMBER 8 L3\n    SIPUSH 1123\n    ISTORE 4\n  L4\n    LINENUMBER 9 L4\n    LDC 123456\n    ISTORE 5\n  L5\n    LINENUMBER 10 L5\n    LDC 10\n    LSTORE 6\n  L6\n    LINENUMBER 11 L6\n    LDC 10.1\n    DSTORE 8\n  L7\n    LINENUMBER 12 L7\n    LDC 10.1\n    FSTORE 10\n  L8\n    LINENUMBER 14 L8\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    ILOAD 1\n    IFNE L9\n    ICONST_1\n    GOTO L10\n  L9\n    FRAME FULL [target/exercise1/DemoClass I I I I I J D F] \n      [java/io/PrintStream]\n    ICONST_0\n  L10\n    FRAME FULL [target/exercise1/DemoClass I I I I I J D F] \n      [java/io/PrintStream I]\n    INVOKEVIRTUAL java/io/PrintStream.println (Z)V\n  L11\n    LINENUMBER 15 L11\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    ILOAD 2\n    ICONST_1\n    ISUB\n    INVOKEVIRTUAL java/io/PrintStream.println (I)V\n  L12\n    LINENUMBER 16 L12\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    ILOAD 3\n    ICONST_1\n    IADD\n    INVOKEVIRTUAL java/io/PrintStream.println (I)V\n  L13\n    LINENUMBER 17 L13\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    ILOAD 4\n    ICONST_1\n    IADD\n    INVOKEVIRTUAL java/io/PrintStream.println (I)V\n  L14\n    LINENUMBER 18 L14\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    ILOAD 5\n    ICONST_1\n    IADD\n    INVOKEVIRTUAL java/io/PrintStream.println (I)V\n  L15\n    LINENUMBER 19 L15\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    LLOAD 6\n    LCONST_1\n    LADD\n    INVOKEVIRTUAL java/io/PrintStream.println (J)V\n  L16\n    LINENUMBER 20 L16\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    DLOAD 8\n    DCONST_1\n    DADD\n    INVOKEVIRTUAL java/io/PrintStream.println (D)V\n  L17\n    LINENUMBER 21 L17\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    FLOAD 10\n    FCONST_1\n    FADD\n    INVOKEVIRTUAL java/io/PrintStream.println (F)V\n  L18\n    LINENUMBER 23 L18\n    RETURN\n  L19\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L19 0\n    LOCALVARIABLE varBoolean Z L1 L19 1\n    LOCALVARIABLE varByte B L2 L19 2\n    LOCALVARIABLE varChar C L3 L19 3\n    LOCALVARIABLE varShort S L4 L19 4\n    LOCALVARIABLE varInt I L5 L19 5\n    LOCALVARIABLE varLong J L6 L19 6\n    LOCALVARIABLE varDouble D L7 L19 8\n    LOCALVARIABLE varFloat F L8 L19 10\n    MAXSTACK = 5\n    MAXLOCALS = 11\n}\n
"},{"location":"jimple-types/#referencetype","title":"ReferenceType","text":" JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\npublic void <init>()\n  {\n  target.exercise1.DemoClass this;\n  this := @this: target.exercise1.DemoClass;\n  specialinvoke this.<java.lang.Object: void <init>()>();\n  return;\n  }\n\n  public target.exercise1.DemoClass getObject(target.exercise1.DemoClass)\n  {\n  target.exercise1.DemoClass obj, this;\n  this := @this: target.exercise1.DemoClass;\n  obj := @parameter0: target.exercise1.DemoClass;\n  return obj;\n  }\n\n  public void compute(boolean)\n  {\n  int[] b;\n  java.io.PrintStream $stack5, $stack6;\n  boolean check;\n  target.exercise1.DemoClass this;\n  int i;\n  null_type r0;\n  java.lang.NullPointerException soot0;\n  this := @this: target.exercise1.DemoClass;\n  check := @parameter0: boolean;\n  b = newarray (int)[5];\n  i = 0;\n\n  label1:\n    if i >= 5 goto label3;\n      if check == 0 goto label2;\n      r0 = (null_type) i;\n      soot0 = new java.lang.NullPointerException;\n      specialinvoke soot0.<java.lang.NullPointerException: \n        void <init>(java.lang.String)>\n          (\"This statement would have triggered an Exception: a[i#1] = r0\");\n      throw soot0;\n\n  label2:\n  b[i] = i;\n      i = i + 1;\n      goto label1;\n\n  label3:\n      $stack5 = <java.lang.System: java.io.PrintStream out>;\n      virtualinvoke $stack5.<java.io.PrintStream: \n        void println(java.lang.Object)>(b);\n      $stack6 = <java.lang.System: java.io.PrintStream out>;\n      virtualinvoke $stack6.<java.io.PrintStream: \n        void println(java.lang.Object)>(null);\n      return;\n  }\n}\n/*\n  The Local b is of ArrayType,\n    and Local r0 is of NullType.\n*/\n
package target.exercise1;\n\npublic class DemoClass {\n\n  public DemoClass getObject(DemoClass obj){\n    return obj;\n  }\n\n  public void compute(boolean check){\n    int a[] = null;\n    int b[] = new int[5];\n    for (int i = 0; i < 5; i++) {\n      if(check){\n        a[i] = i;\n      }\n        b[i] = i;\n    }\n    System.out.println(b);\n    System.out.println(a);\n  }\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 3 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n    RETURN\n  L1\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0\n    MAXSTACK = 1\n    MAXLOCALS = 1\n\n// access flags 0x1\npublic getObject(Ltarget/exercise1/DemoClass;)Ltarget/exercise1/DemoClass;\n  L0\n    LINENUMBER 6 L0\n    ALOAD 1\n    ARETURN\n  L1\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0\n    LOCALVARIABLE obj Ltarget/exercise1/DemoClass; L0 L1 1\n    MAXSTACK = 1\n    MAXLOCALS = 2\n\n// access flags 0x1\npublic compute(Z)V\n  L0\n    LINENUMBER 10 L0\n    ACONST_NULL\n    ASTORE 2\n  L1\n    LINENUMBER 11 L1\n    ICONST_5\n    NEWARRAY T_INT\n    ASTORE 3\n  L2\n    LINENUMBER 12 L2\n    ICONST_0\n    ISTORE 4\n  L3\n    FRAME APPEND [[I [I I]\n    ILOAD 4\n    ICONST_5\n    IF_ICMPGE L4\n  L5\n    LINENUMBER 13 L5\n    ILOAD 1\n    IFEQ L6\n  L7\n    LINENUMBER 14 L7\n    ALOAD 2\n    ILOAD 4\n    ILOAD 4\n    IASTORE\n  L6\n    LINENUMBER 16 L6\n    FRAME SAME\n    ALOAD 3\n    ILOAD 4\n    ILOAD 4\n    IASTORE\n  L8\n    LINENUMBER 12 L8\n    IINC 4 1\n    GOTO L3\n  L4\n    LINENUMBER 18 L4\n    FRAME CHOP 1\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    ALOAD 3\n    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V\n  L9\n    LINENUMBER 19 L9\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    ALOAD 2\n    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V\n  L10\n    LINENUMBER 20 L10\n    RETURN\n  L11\n    LOCALVARIABLE i I L3 L4 4\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L11 0\n    LOCALVARIABLE check Z L0 L11 1\n    LOCALVARIABLE a [I L1 L11 2\n    LOCALVARIABLE b [I L2 L11 3\n    MAXSTACK = 3\n    MAXLOCALS = 5\n}\n
"},{"location":"jimple-types/#voidtype","title":"VoidType","text":"

Used as a possible return type of a method.

JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\n  public void <init>()\n  {\n  target.exercise1.DemoClass this;\n  this := @this: target.exercise1.DemoClass;\n  specialinvoke this.<java.lang.Object: void <init>()>();\n  return;\n  }\n\n  public void voidMethod()\n  {\n  java.io.PrintStream $stack1;\n  target.exercise1.DemoClass this;\n  this := @this: target.exercise1.DemoClass;\n  $stack1 = <java.lang.System: java.io.PrintStream out>;\n  virtualinvoke $stack1.<java.io.PrintStream: \n      void println(java.lang.String)>(\"In voidMethod().\");\n  return;\n  }\n}\n/*\n  For the SootMethod - <target.exercise1.DemoClass: void voidMethod()>, \n    returnType is instance of VoidType.\n*/\n
package target.exercise1;\n\npublic class DemoClass {\n  public void voidMethod(){\n  System.out.println(\"In voidMethod().\");\n  }\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 3 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n    RETURN\n  L1\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0\n    MAXSTACK = 1\n    MAXLOCALS = 1\n\n// access flags 0x1\npublic voidMethod()V\n  L0\n    LINENUMBER 5 L0\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    LDC \"In voidMethod().\"\n    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V\n  L1\n    LINENUMBER 6 L1\n    RETURN\n  L2\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L2 0\n    MAXSTACK = 2\n    MAXLOCALS = 1\n}\n
"},{"location":"jimple-values/","title":"Jimple Values","text":""},{"location":"jimple-values/#immediate","title":"Immediate","text":"

An Immediate has a given Type and consists of a Local (\"a Variable\", \"Something that contains a Value\") or a Constant (\"Something that is a Value\").

"},{"location":"jimple-values/#local","title":"Local","text":"
i0 \n

A Local is a variable and its scope is inside its method i.e. no referencing from outside a method. Values can be assigned to Locals via JIdentityStmt or JAssignStmt.

JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\n  public void <init>()\n  {\n    target.exercise1.DemoClass this;\n    this := @this: target.exercise1.DemoClass;\n    specialinvoke this.<java.lang.Object: void <init>()>();\n    return;\n  }\n\n  public void compute()\n  {\n    java.io.PrintStream $stack2, $stack3;\n    target.exercise1.DemoClass this;\n    int local2;\n\n    this := @this: target.exercise1.DemoClass;\n    $stack2 = <java.lang.System: java.io.PrintStream out>;\n    virtualinvoke $stack2.<java.io.PrintStream: void println(int)>(1);\n\n    local2 = this.<target.exercise1.DemoClass: int global>;\n    $stack3 = <java.lang.System: java.io.PrintStream out>;\n    virtualinvoke $stack3.<java.io.PrintStream: void println(int)>(local2);\n    return;\n  }\n}\n/*\n  $stack2, this, $stack3, local2 are all Locals.\n\n  \"this := @this: target.exercise1.DemoClass\" is a JIdentityStmt assigning to a Local.\n\n  \"$stack2 = <java.lang.System: java.io.PrintStream out>\", \n    \"local2 = this.<target.exercise1.DemoClass: int global>\", \n      \"$stack3 = <java.lang.System: java.io.PrintStream out>\" \n        are JAssignStmts assigning to a Local.\n\n*/  \n
package target.exercise1;\n\npublic class DemoClass {\n\n  private int global;\n\n  public void compute(){\n    int local;\n    local = 1;\n    System.out.println(local);\n    local = this.global;\n    System.out.println(local);\n  }\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x2\nprivate I global\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 3 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n    RETURN\n  L1\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0\n    MAXSTACK = 1\n    MAXLOCALS = 1\n\n// access flags 0x1\npublic compute()V\n  L0\n    LINENUMBER 9 L0\n    ICONST_1\n    ISTORE 1\n  L1\n    LINENUMBER 10 L1\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    ILOAD 1\n    INVOKEVIRTUAL java/io/PrintStream.println (I)V\n  L2\n    LINENUMBER 11 L2\n    ALOAD 0\n    GETFIELD target/exercise1/DemoClass.global : I\n    ISTORE 1\n  L3\n    LINENUMBER 12 L3\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    ILOAD 1\n    INVOKEVIRTUAL java/io/PrintStream.println (I)V\n  L4\n    LINENUMBER 14 L4\n    RETURN\n  L5\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L5 0\n    LOCALVARIABLE local I L1 L5 1\n    MAXSTACK = 2\n    MAXLOCALS = 2\n}\n
"},{"location":"jimple-values/#constant","title":"Constant","text":"

represents an actual value itself like 42 or \"This is a String\". Constants are usually assigned to Locals or Refs. There exists a constant entity for every Primitive Type.

"},{"location":"jimple-values/#expr","title":"Expr","text":"

An expression is a language construct that calculates an operation and returns a value. E.g. a binary operation AbstracBinopExpr such as an addition a + b, an AbstractInvokeExpr such as virtualinvoke $stack2.<java.io.PrintStream: void println(int)>(1); or an UnaryExpr such as !valid. And a bunch more!

"},{"location":"jimple-values/#ref","title":"Ref","text":""},{"location":"jimple-values/#jarrayref","title":"JArrayRef","text":"

$arr[1] = 42;\n$anotherLocal = arr[99];\n
referencing an array position.

"},{"location":"jimple-values/#jfieldref","title":"JFieldRef","text":"

JFieldRefs are referencing a SootField via its FieldSignature

"},{"location":"jimple-values/#identityref","title":"IdentityRef","text":"

The IdentityRef makes those implicit special value assignments explicit.

"},{"location":"jimple-values/#jthisref","title":"JThisRef","text":"

@this: package.fruit.Banana\n
represents the this pointer of the current class.

"},{"location":"jimple-values/#jcaughtexceptionref","title":"JCaughtExceptionRef","text":"

@caughtexception\n
represents the value of the thrown exception (caught by this exceptionhandler).

"},{"location":"jimple-values/#jparameterref","title":"JParameterRef","text":"

i0 := @parameter0\ni1 := @parameter1 \n
represents a parameter of a method, identified by its index.

"},{"location":"jimple-values/#good-to-know","title":"Good to know","text":"

A lot of the SootUp APIs return the Value Interface. To determine and handle its subtypes you can make use of instanceof.

instanceOf & If-Else
    Value op = assignStmt.getRightOp();\n    if(op instanceof Local){\n        // found a Local\n        ...\n    }else if(stmt instanceof Constant){\n        // found a Constant\n        ...\n    }else ...\n

But this could escalate to a huge if-else-tree - almost a forest. To mitigate such scenario you can implement a subclass of AbstractValueVisitor. Just subclass the methods to the respective Values you need to handle. This is visitor acts like a switch-case, implemented via two dynamic calls.

StmtVisitor
    Value op = assignStmt.getRightOp() ;\n    AbstractValueVisitor visitor = new AbstractValueVisitor<Integer>() {\n        private int intConstantCounter = 0;\n        @Override\n        public void caseConstant(@Nonnull Constant c) {\n            intConstantCounter++;\n            setResult(intConstantCounter);\n        }\n    };\n\n    op.accept(visitor);\n    int amountOfIfStmts = visitor.getResult();\n

If you only need a visitor for a subset of Value, you can consider ImmediateVisitor, ConstantVisitor, ExprVisitor, RefVisitor. Sidenote: Of course its possible can create a subclass instead of an anonymous class.

"},{"location":"jimple/","title":"Jimple","text":"

What is Jimple? Jimple is the intermediate representation IR of Soot, and thus SootUp. Soot's intention is to provide a simplified way to analyze JVM bytecode. JVM bytecode is stack-based, which makes it difficult for program analysis. Java source code, on the other hand, is also not quite suitable for program analysis, due to its nested structures. Therefore, Jimple aims to bring the best of both worlds, a non-stack-based and flat (non-nested) representation. For this purpose Jimple was designed as a representation of JVM bytecode which is human readable.

Info

To learn more about jimple, refer to the thesis by Raja Vallee-Rai.

Lets have a look at the following Jimple code representing Java code of a HelloWorld class.

JimpleJavaBytecode
public class HelloWorld extends java.lang.Object\n{\n  public void <init>()\n  {\n    HelloWorld r0;\n    r0 := @this: HelloWorld;\n    specialinvoke r0.<java.lang.Object: void <init>()>();\n    return;\n  }\n\n  public static void main(java.lang.String[])\n  {\n    java.lang.String[] r0;\n    java.io.PrintStream r1;\n\n    r0 := @parameter0: java.lang.String[];\n    r1 = <java.lang.System: java.io.PrintStream out>;\n    virtualinvoke r1.<java.io.PrintStream: \n    void println(java.lang.String)>(\"Hello world!\");\n    return;\n  }\n}\n
public class HelloWorld {\n\n  public HelloWorld() {\n\n  }\n\n  public static void main(String[] var0) {\n    System.out.println(\"Hello World!\");\n  }\n\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class analysis/HelloWorld {\n\n// compiled from: HelloWorld.java\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 4 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n  L1\n    LINENUMBER 6 L1\n    RETURN\n  L2\n    LOCALVARIABLE this Lanalysis/HelloWorld; L0 L2 0\n    MAXSTACK = 1\n    MAXLOCALS = 1\n\n// access flags 0x9\npublic static main([Ljava/lang/String;)V\n  L0\n    LINENUMBER 9 L0\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    LDC \"Hello World!\"\n    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V\n  L1\n    LINENUMBER 10 L1\n    RETURN\n  L2\n    LOCALVARIABLE var0 [Ljava/lang/String; L0 L2 0\n    MAXSTACK = 2\n    MAXLOCALS = 1\n}\n

The Java Sourcecode is the easiest representation - So why all the fuzz and just use that? Sometimes we have no access to the sourcecode but have a binary with the bytecode. For most People reading bytecode is not that intuitive. So SootUp generates Jimple from the bytecode. Jimple is very verbose, but makes everything explicit, that the JVM does implicitly and transforms the stack-machine strategy by a register-machine strategy i.e. Variable (Local) handling .

"},{"location":"jimple/#jimple-grammar-structure","title":"Jimple Grammar Structure","text":"

Jimple mimics the JVMs class file structure. Therefore it is object oriented. A Single Class (or Interface) per file. Three-Address-Code which means there are no nested expressions. (nested expressions can be modeled via Locals that store intermediate calculation results.)

"},{"location":"jimple/#signatures-and-classtypes","title":"Signatures and ClassTypes","text":"

Signatures are used to identify Classes,Methods or Fields uniquely/globally. Sidenote: Locals, do not have a signature, since they are referenced within method boundaries.

JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\n  public void <init>()\n  {\n    target.exercise1.DemoClass this;\n    this := @this: target.exercise1.DemoClass;\n\n    specialinvoke this.<java.lang.Object: void <init>()>();\n    this.<target.exercise1.DemoClass: double pi> = 3.14;\n    return;\n  }\n\n  public void demoMethod()\n  {\n    java.io.PrintStream $stack3, $stack5;\n    java.lang.StringBuilder $stack4, $stack6, $stack7;\n    java.lang.String $stack8;\n    target.exercise1.DemoClass this;\n\n    this := @this: target.exercise1.DemoClass;\n    $stack3 = <java.lang.System: java.io.PrintStream out>;\n\n    virtualinvoke $stack3.<java.io.PrintStream: \n      void println(java.lang.String)>(\"pi : 3.14\");\n    $stack5 = <java.lang.System: java.io.PrintStream out>;\n    $stack4 = new java.lang.StringBuilder;\n\n    specialinvoke $stack4.<java.lang.StringBuilder: void <init>()>();\n    $stack6 = virtualinvoke $stack4.<java.lang.StringBuilder: \n      java.lang.StringBuilder append(java.lang.String)>\n        (\"pi : \");\n    $stack7 = virtualinvoke $stack6.<java.lang.StringBuilder: \n      java.lang.StringBuilder append(double)>(3.1415);\n    $stack8 = virtualinvoke $stack7.<java.lang.StringBuilder: \n      java.lang.String toString()>();\n\n    virtualinvoke $stack5.<java.io.PrintStream:     \n      void println(java.lang.String)>($stack8);\n    return;\n  }\n}\n/*\n  For JInstanceFieldRef \"this.<target.exercise1.DemoClass: double pi>\" \n    signature is <target.exercise1.DemoClass: double pi>\n  Similarly, we have other signatures like \n    <java.lang.Object: void <init>()>, \n    <java.io.PrintStream: void println(java.lang.String)> \n    and so on. \n*/\n
package target.exercise1;\n\npublic class DemoClass {\n  private final double pi = 3.14;\n\n  public void demoMethod(){\n    double localPi = 3.1415;\n    System.out.println(\"pi : \" + pi);\n    System.out.println(\"pi : \" + localPi);\n  }\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x12\nprivate final D pi = 3.14\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 3 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n  L1\n    LINENUMBER 4 L1\n    ALOAD 0\n    LDC 3.14\n    PUTFIELD target/exercise1/DemoClass.pi : D\n    RETURN\n  L2\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L2 0\n    MAXSTACK = 3\n    MAXLOCALS = 1\n\n// access flags 0x1\npublic demoMethod()V\n  L0\n    LINENUMBER 6 L0\n    LDC 3.1415\n    DSTORE 1\n  L1\n    LINENUMBER 7 L1\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    LDC \"pi : 3.14\"\n    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V\n  L2\n    LINENUMBER 8 L2\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    NEW java/lang/StringBuilder\n    DUP\n    INVOKESPECIAL java/lang/StringBuilder.<init> ()V\n    LDC \"pi : \"\n      INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)\n        Ljava/lang/StringBuilder;\n    DLOAD 1\n    INVOKEVIRTUAL java/lang/StringBuilder.append (D)Ljava/lang/StringBuilder;\n    INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;\n    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V\n  L3\n    LINENUMBER 9 L3\n    RETURN\n  L4\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L4 0\n    LOCALVARIABLE localPi D L1 L4 1\n    MAXSTACK = 4\n    MAXLOCALS = 3\n}\n
"},{"location":"jimple/#sootclass","title":"SootClass","text":"

A SootClass consists of SootFields and SootMethods. It is referenced by its global identifier the ClassType like java.lang.String.

JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\n  public void <init>()\n  {\n    target.exercise1.DemoClass this;\n    this := @this: target.exercise1.DemoClass;\n    specialinvoke this.<java.lang.Object: void <init>()>();\n    return;\n  }\n}\n
package target.exercise1;\n\npublic class DemoClass {}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 3 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n    RETURN\n  L1\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0\n    MAXSTACK = 1\n    MAXLOCALS = 1\n}\n
"},{"location":"jimple/#sootfield","title":"SootField","text":"

A SootField is a piece of memory which can store a value that is accessible according to its visibility modifier. It is referenced by its FieldSignature like <java.lang.String: int hash>.

JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\n  public void <init>()\n  {\n    target.exercise1.DemoClass this;\n    this := @this: target.exercise1.DemoClass;\n    specialinvoke this.<java.lang.Object: void <init>()>();\n    this.<target.exercise1.DemoClass: double pi> = 3.14;\n    return;\n  }\n}\n/*\n  \"this.<target.exercise1.DemoClass: double pi>\" is JInstanceFieldRef\n*/\n
package target.exercise1;\n\npublic class DemoClass {\n  private final double pi = 3.14;\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x12\nprivate final D pi = 3.14\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 3 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n  L1\n    LINENUMBER 4 L1\n    ALOAD 0\n    LDC 3.14\n    PUTFIELD target/exercise1/DemoClass.pi : D\n    RETURN\n  L2\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L2 0\n    MAXSTACK = 3\n    MAXLOCALS = 1\n}\n
"},{"location":"jimple/#sootmethod-and-its-body","title":"SootMethod and its Body","text":"

The interesting part is a method. A method is a \"piece of code\" that can be executed. It is referenced by its MethodSignature like <java.lang.Object: java.lang.String toString()>.

JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\n  public void <init>()\n  {\n    target.exercise1.DemoClass this;\n    this := @this: target.exercise1.DemoClass;\n    specialinvoke this.<java.lang.Object: void <init>()>();\n    virtualinvoke this.<target.exercise1.DemoClass: \n    void demoMethod()>();\n    return;\n  }\n\n  public void demoMethod()\n  {\n    java.io.PrintStream $stack1;\n    target.exercise1.DemoClass this;\n\n    this := @this: target.exercise1.DemoClass;\n    $stack1 = <java.lang.System: java.io.PrintStream out>;\n\n    virtualinvoke $stack1.<java.io.PrintStream: \n    void println(java.lang.String)>(\"Inside method.\");\n    return;\n  }\n}\n/*\n  \"<target.exercise1.DemoClass: void demoMethod()>\" \n        and \"<target.exercise1.DemoClass: void <init>()>\" \n        are instances of SootMethod \n*/\n
package target.exercise1;\n\npublic class DemoClass {\n  DemoClass(){\n    demoMethod();\n  }\n  public void demoMethod(){\n    System.out.println(\"Inside method.\");\n  }\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x0\n<init>()V\n  L0\n    LINENUMBER 5 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n  L1\n    LINENUMBER 6 L1\n    ALOAD 0\n    INVOKEVIRTUAL target/exercise1/DemoClass.demoMethod ()V\n  L2\n    LINENUMBER 7 L2\n    RETURN\n  L3\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L3 0\n    MAXSTACK = 1\n    MAXLOCALS = 1\n\n// access flags 0x1\npublic demoMethod()V\n  L0\n    LINENUMBER 10 L0\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    LDC \"Inside method.\"\n    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V\n  L1\n    LINENUMBER 11 L1\n    RETURN\n  L2\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L2 0\n    MAXSTACK = 2\n    MAXLOCALS = 1\n}\n

More about the Body of the SootMethod.

"},{"location":"migrating/","title":"Migration Help","text":""},{"location":"migrating/#version-130","title":"Version 1.3.0","text":""},{"location":"migrating/#version-120","title":"Version 1.2.0","text":""},{"location":"migrating/#from-soot","title":"From Soot","text":"

Below we show a comparison of the code so far with the same functionality in sootup.

SootUpSoot
AnalysisInputLocation<JavaSootClass> inputLocation =\nnew JavaClassPathAnalysisInputLocation(\"path2Binary\");\n\nJavaView view = new JavaView(inputLocation);\n\nJavaClassType classType = \n        view.getIdentifierFactory().getClassType(\"HelloWorld\");\n\nMethodSignature methodSignature =\n    view\n        .getIdentifierFactory()\n        .getMethodSignature(\n            \"main\", classType, \"void\",\n            Collections.singletonList(\"java.lang.String[]\"));\n\nJavaSootClass sootClass = view.getClass(classType).get();\n\nMethodSubSignature mss = methodSignature.getSubSignature();\nJavaSootMethod sootMethod =  sootClass.getMethod(mss).get();\n\nsootMethod.getBody().getStmts();\n
G.reset();\nString userdir = System.getProperty(\"user.dir\");\nString sootCp = \n        userdir \n        + File.separator \n        + \"target\" \n        + File.separator \n        + \"test-classes\"\n        + File.pathSeparator + \"lib\"+File.separator+\"rt.jar\";\n\nOptions.v().set_soot_classpath(sootCp);\nOptions.v().set_whole_program(true);\nOptions.v().setPhaseOption(\"cg.cha\", \"on\");\nOptions.v().setPhaseOption(\"cg\", \"all-reachable:true\");\nOptions.v().set_no_bodies_for_excluded(true);\nOptions.v().set_allow_phantom_refs(true);\nOptions.v().setPhaseOption(\"jb\", \"use-original-names:true\");\nOptions.v().set_prepend_classpath(false);\n\nScene.v().addBasicClass(\"java.lang.StringBuilder\");\nSootClass c = \n    Scene.v().forceResolve(targetTestClassName, SootClass.BODIES);\nif (c != null) {\n    c.setApplicationClass();\n}\nScene.v().loadNecessaryClasses();\n\nSootMethod method;\nfor (SootClass c : Scene.v().getApplicationClasses()) {\n    if(c.getName().equals(\"example.HelloWorld\")){\n        for (SootMethod m : c.getMethods()) {\n            if (!m.hasActiveBody()) {\n                continue;\n            }\n            if (m.getName().equals(\"entryPoint\")) {\n                method = m;\n                break;\n            }\n        }\n    }\n}\n\nmethod.getActiveBody().getUnits();\n
"},{"location":"qilin/","title":"Incorporate Qilin Pointer Analysis","text":""},{"location":"qilin/#dependencies","title":"Dependencies","text":"MavenGradle
<dependency>\n    <groupId>org.soot-oss</groupId>\n    <artifactId>sootup.java.sourcecode</artifactId>\n    <version>1.3.0</version>\n</dependency>\n
compile \"org.soot-oss:sootup.qilin:1.3.0\"\n
"},{"location":"qilin/#how-to-create-a-pointer-analysis","title":"How to create a pointer analysis","text":"

WIP: Beware most likely the API will change so you only need to specify SootUp objects!

One can create an Andersen's context-insensitive analysis with following code:

Java
String entrypoint = \"dacapo.antlr.Main\";\nPTAPattern ptaPattern = new PTAPattern(\"insens\");\nPTA pta = PTAFactory.createPTA(ptaPattern, view, entrypoint);\npta.run();\n

Users must specify the program's View, select a PTAPattern (indicating the desired types of pointer analyses to perform), and designate the entrypoint - which is serving as the entry point for the analysis.

"},{"location":"qilin/#how-to-use-pointer-analysis-results","title":"How to use pointer analysis results","text":"

First, we can use Qilin's pointer analysis to get a On-the-Fly constructed callgraph:

OnFlyCallGraph cg = pta.getCallGraph();\n

Second, we can use it to get the points-to results for some interested local variables, fields, etc.

PointsToSet pts0 = pta.reachingObjects(method, v0);\nPointsToSet pts1 = pta.reachingObjects(method, v1, f); // PTS(v1.f)\n

Third, we can check whether two variables, a and b, are aliases by checking whether there is an object that exists in both of their points-to sets.

Qilin does not currently offer a isMayAlias API within the PTA class. However, a similar functionality can be found in qilin.test.util.AliasAssertion with the method: boolean isMayAlias(PTA pta, Value va, Value vb) This method allows to check for potential aliasing between two values given a PTA instance.

"},{"location":"qilin/#a-full-list-of-pointer-analyses","title":"A Full list of Pointer Analyses","text":"

Qilin's toolbox includes a rich set of pointer analyses, which are given below:

Note that the symbol k used in the table should be replaced with a concrete small constant like 1 or 2.

PTA patterns Description Reference insens Andersen's context-insensitive analysis Paper kc k-callsite-sensitive pointer analysis (denoted kCFA). Paper ko k-object-sensitive pointer analysis (denoted kOBJ). Paper kt k-type-sensitive pointer analysis (denoted kTYPE). Paper kh hybrid k-object-sensitive pointer analysis. Paper kht hybrid k-type-sensitive pointer analysis. Paper B-2o BEAN-guided 2OBJ. Only k=2 is supported. Paper D-2o Data-driven 2OBJ. Only k=2 is supported. Paper D-2c Data-driven 2CFA. Only k=2 is supported. Paper M-ko MAHJONG-guided kOBJ. Paper M-kc MAHJONG-guided kCFA. Paper E-ko EAGLE-guided kOBJ. Paper T-ko TURNER-guided kOBJ. Paper Z-ko ZIPPER-guided kOBJ. Paper Z-kc ZIPPER-guided kCFA. Paper Z-ko -cd The context debloated version of ZIPPER-guided kOBJ. Paper ko -cd -cda=CONCH The context debloated version of kOBJ using Conch. Paper ko -cd -cda=DEBLOATERX The context debloated version of kOBJ using DebloaterX. Paper s-kc SELECTX-guided kCFA. Paper"},{"location":"tool_setup/","title":"From Prototype to an intuitive Tool","text":"

How was the parameter order again? For a lot of cli tools we see an arbitrary order of cli parameters, different options for giving a working directory etc.. So in the wild you can see a lot from run.sh/run.bat to make files just to reorder arguments to execute a tool.

In SootUp we thought we could help on improving this madness while saving your time.

The command line parser mimics the options the java executable accepts - at least for what is supported by SootUp. This makes it very simple to just copy the execution paramaters you use for execution, to use them more or less as is four the analysis tool.

"},{"location":"tool_setup/#dependencies","title":"Dependencies","text":"MavenGradle
<dependency>\n    <groupId>commons-cli</groupId>\n    <artifactId>commons-cli</artifactId>\n    <version>1.8.0</version>\n</dependency>\n
    implementation(\"commons-cli:commons-cli:1.8.0\")\n
"},{"location":"tool_setup/#java-code","title":"Java Code","text":"
```java\n\nclass SootUpConfiguration{\n    // TODO incorporate from downstream\n}\n\n```\n

We are happy if you steal the following code to create a tool where the setup is just simple.

"},{"location":"tools/","title":"Who uses SootUp","text":""},{"location":"typehierarchy/","title":"TypeHierarchy","text":"

The TypeHierarchy models the relationship of Classes or Interfaces of a OOP program.

"},{"location":"typehierarchy/#creating-typehierarchy","title":"Creating TypeHierarchy","text":"SootUpSoot
String cpString = \"src/test/resources/Callgraph/binary\";\nList<AnalysisInputLocation> inputLocations = new ArrayList();\ninputLocations.add(new JavaClassPathAnalysisInputLocation(cpStr));\ninputLocations.add(new DefaultRuntimeAnalysisInputLocation());\n\nJavaView view = new JavaView(inputLocations);\nTypeHierarchy typehierarchy = view.getTypeHierarchy();\n
String userdir = System.getProperty(\"user.dir\");\nString sootCp = userdir + File.separator + \"target\" + File.separator + \"test-classes\"+ File.pathSeparator + \"lib\"+File.separator+\"rt.jar\";\n\nString targetTestClassName = target.exercise1.Hierarchy.class.getName();\nG.reset();\nOptions.v().set_whole_program(true);\nOptions.v().set_soot_classpath(sootCp);\nOptions.v().set_no_bodies_for_excluded(true);\nOptions.v().process_dir();\nOptions.v().set_allow_phantom_refs(true);\nOptions.v().setPhaseOption(\"jb\", \"use-original-names:true\");\nOptions.v().set_prepend_classpath(false);\nSootClass c = Scene.v().forceResolve(targetTestClassName, SootClass.BODIES);\nif (c != null)\n    c.setApplicationClass();\nScene.v().loadNecessaryClasses();\n\nHierarchy hierarchy = new Hierarchy();\n
"},{"location":"typehierarchy/#create-a-javaclasstype","title":"Create a JavaClassType","text":"SootUpSoot
JavaClassType classTypeA = view.getIdentifierFactory().getClassType(\"packageName.A\");\nJavaClassType classTypeB = view.getIdentifierFactory().getClassType(\"packageName.B\");\nJavaClassType classTypeC = view.getIdentifierFactory().getClassType(\"packageName.C\");\n
String targetTestClassName = \"packageNameA.A\";\nSootClass methodA = Scene.v().getSootClass(targetTestClassName);\n
"},{"location":"typehierarchy/#query-the-typehierarchy","title":"Query the TypeHierarchy","text":""},{"location":"typehierarchy/#classes","title":"Classes","text":"
    // if the assertion fails, the following methods will throw an Exception (you don't have to call it - it's just to illustrate the assumption)\n    assert typehierarchy.contains(classTypeA);\n\n    typehierarchy.superclassOf(classTypeA);\n\n    typehierarchy.subclassesOf(classTypeA);\n\n    typehierarchy.isSubtypeOf(classTypeA, classTypeB);\n
"},{"location":"typehierarchy/#interfaces","title":"Interfaces","text":"
    JavaClassType iterableInterface = view.getIdentifierFactory().getClassType(\"java.lang.Iterable\");\n\n    // if any of the assertions fail, the following methods will throw an Exception (you don't have to call these - it's just to illustrate the assumptions)\n    assert typehierarchy.contains(iterableInterface);\n    assert typehierarchy.isInterface(iterableInterface);\n\n    // transitive relations as well\n    typehierarchy.implementedInterfacesOf(iterableInterface);\n    typehierarchy.implementersOf(iterableInterface);\n\n    // only the direct related relations\n    typehierarchy.directlyImplementedInterfacesOf(iterableInterface);\n    typehierarchy.directlyExtendedInterfacesOf(iterableInterface);\n
"},{"location":"whatsnew/","title":"What's new in SootUp?","text":""},{"location":"whatsnew/#library-by-default","title":"Library by default","text":"

While Soot is a library and a stand-alone command-line application. SootUp, on the other hand, is designed to be a core library. It assumes that it is embedded in a client application that owns the thread of control. It can be extended with a command-line interface, included in other software projects as a library, or integrated into IDEs with JimpleLSP.

"},{"location":"whatsnew/#modular-architecture","title":"Modular Architecture","text":"

SootUp has a modular architecture, which enables its clients to include only the necessary functionality to their applications.

"},{"location":"whatsnew/#no-more-singletons","title":"No More Singletons","text":"

Singletons offer a single view of a single program version, which makes it impossible to analyze multiple programs or multiple versions of the same program. SootUp does not make use of singletons such the Scene class in the old Soot any more. It enables analyzing multiple programs simultaneously.

"},{"location":"whatsnew/#new-source-code-frontend","title":"New Source Code Frontend","text":"

Soot's JastAdd-based java frontend is not maintained anymore. In SootUp, we use WALA's well-maintained source code frontend, which will not only allow Soot to analyze Java source code, but also JavaScript and Python.

"},{"location":"whatsnew/#immutable-by-design","title":"Immutable by Design","text":"

SootUp has been designed with the goal of immutability in mind. This makes sharing objects between several entities easier, because there is no need to worry about unintended changes to other entities.

"},{"location":"whatsnew/#withers-instead-of-setters","title":"Withers instead of Setters","text":"

Due to the goal of immutability, many classes do not have setters anymore. For example, a Body does not have a method setStmts(List<Stmt> stmts). Instead, a method called withStmts(List<Stmt> stmts) has been added. This does not modify the original instance, but returns a copy of the Body but with the provided stmts in its instance. This concept of so-called with-ers can be found all throughout SootUp.

A simplified example

class Body {\n  final List<Stmt> stmts;\n  final List<Local> locals;\n\n  Body(List<Stmt> stmts, List<Local> locals) {\n    this.stmts = stmts;\n    this.locals = locals;\n  }  \n\n  Body withStmts(List<Stmt> stmts) { return new Body(stmts, this.locals); }\n  Body withLocals(List<Local> locals) { return new Body(this.stmts, locals); }\n}\n
"},{"location":"whatsnew/#intermediate-representation","title":"Intermediate Representation","text":"

Jimple is the only intermediate representation (IR) in SootUp. We modified it slightly to be able to accommodate different programming languages in the future.

"},{"location":"write_analyses/","title":"Write your own Interprocedural Dataflow Analysis","text":""},{"location":"write_analyses/#dependencies","title":"Dependencies","text":"MavenGradle
<dependency>\n    <groupId>org.soot-oss</groupId>\n    <artifactId>sootup.analysis</artifactId>\n    <version></version>\n</dependency>\n
    compile \"org.soot-oss:sootup.analysis:1.3.0\"\n
"},{"location":"write_analyses/#useful-knowledge","title":"Useful Knowledge","text":"

Background Knowledge as online lectures are available on YouTube.

"},{"location":"write_analyses/#examples","title":"Examples","text":"

Taint Analysis, TypeState Analysis, Linear Constant Propagation, ...

// TODO incorporate & guide through examples\n\nIn the meantime please have a look into the test cases of the\nanalysis submodule to see example implementations of interprocedural\ndata-flow analysis via the IFDS or IDE Framework.\n
"}]} \ No newline at end of file +{"config":{"lang":["en"],"separator":"[\\s\\-]+","pipeline":["stopWordFilter"]},"docs":[{"location":"","title":"What's SootUp?","text":"

SootUp is a complete overhaul of the good, old static analysis framework Soot.

Important

SootUp is not a version update to Soot, it is a completely new implementation written from scratch that aims to be a leaner, modernized and developer friendly successor of Soot. It is not a Drop-In Replacement! The new architecture and API, renders it not trivial to update existing projects that were built on soot. Therefore we recommend using SootUp for greenfield projects. We hope improved type safety and streamlined mechanisms will aide you implementing and debugging your analysis tool. Unfortunately not every feature has been ported - If you miss something feel free to contribute a feature you miss from good old Soot.

"},{"location":"#why-sootup","title":"Why SootUp?","text":"

Over the 20+ years, SootUps predecessor Soot has evolved into a powerful framework, which is one of the most widely used tools in the static analysis community. This evolution was guided by the needs of the community and carried out with ad-hoc improvements. As a result, Soot has become a tool that can do a multitude of things, but it is heavy and hard to maintain and comprehend. So there was the need to clean up the codebase e.g. improve the software architecture, remove legacy datastructures that weren't in the Java Runtime at the time of Soots creation, enforce validation to have a sane state, removing the necessity of arcane knowledge, document it more and more - to make Soot future prove. So we introduced Design changes in SootUp, which aim to address Soot's shortcomings. The goal is a lighter library that can easily be understood and maintained to be included in other projects.

"},{"location":"#supporters","title":"Supporters","text":"

The development of SootUp is financed by generous support from the German Research Foundation (DFG) and the Heinz Nixdorf Institute (HNI).

Become a sponsor!

"},{"location":"analysisinput/","title":"Analysis Input","text":"

i.e. What should be analyzed. An AnalysisInputLocation points to code input SootUp can analyze. We ship multiple Implementations that can handle different input.

Additionally you can specify a SourceType. This determines what is considered e.g. in the CallGraphs generation. Further you can specify a List of BodyInterceptors, which will optimize the raw Jimple IR that was transformed from the input.

"},{"location":"analysisinput/#java-runtime","title":"Java Runtime","text":""},{"location":"analysisinput/#java-8","title":"Java <=8","text":"

The DefaultRTJaAnalysisInputLocation points to the rt.jar of the executing JVM.

AnalysisInputLocation inputLocation = new DefaultRTJaAnalysisInputLocation();\nJavaView view = new JavaView(inputLocation);\n

To include a different Java Runtime library point to any rt.jar via a JavaClassPathAnalysisInputLocation as its a usual .jar file.

"},{"location":"analysisinput/#java-9","title":"Java >=9","text":"

The JRTFilesystemAnalysisInputLocation points to the jigsawed java runtime of the executing JVM.

AnalysisInputLocation inputLocation = new JrtFileSystemAnalysisInputLocation(); \nJavaView view = new JavaView(inputLocation);\n

If you have errors like Java.lang.String, Java.lang.Object, ... you are most likely missing this AnalysisInputLocation.

"},{"location":"analysisinput/#java-bytecode","title":"Java Bytecode","text":"

File-Extensions: .class, .jar, .war

The JavaClassPathAnalysisInputLocation is the equivalent of the classpath you would pass to the java executable i.e. point to root(s) of package(s).

Directory.jar File.class FileComplete class path
AnalysisInputLocation inputLocation =\n        new JavaClassPathAnalysisInputLocation(\"target/\");  // points to\nJavaView view = new JavaView(inputLocation);\n
AnalysisInputLocation inputLocation = new JavaClassPathAnalysisInputLocation(\"myCode.jar\");\nJavaView view1 = new JavaView(inputLocation);\n\n// if you want to analyze a specific language level of a multi release jar\nAnalysisInputLocation inputLocation =\n        new MultiReleaseJarAnalysisInputLocation(\"myCode.jar\", new JavaLanguage(10) );\nJavaView view2 = new JavaView(inputLocation);\n
// if you omit the package structure while pointing to a file,\n// you have to pass the omitted directories as a parameter\nAnalysisInputLocation inputLocation = new PathBasedAnalysisInputLocation.\n            ClassFileBasedAnalysisInputLocation(\"Banana.class\", \"packageName.subPackage\", SourceType.Application);\nJavaView view = new JavaView(inputLocation);\n
String cp = \"myCode.jar\" + File.pathSeparator + \"dependency.jar\" + File.pathSeparator + \"target/classes/\";\nAnalysisInputLocation inputLocation = new JavaClassPathAnalysisInputLocation(cp);\nJavaView view = new JavaView(inputLocation);\n
"},{"location":"analysisinput/#java-sourcecode","title":"Java Sourcecode","text":"

File-Extensions: .java

With the OTFCompileAnalysisInputLocation you can point directly to .java files or pass a String with Java sourcecode. The AnalysisInputLocation delegates the data to the JavaCompiler and transform the bytecode from the compiler to Jimple.

Single FileMultiple FilesFile as String
AnalysisInputLocation inputLocation = new OTFCompileAnalysisInputLocation(\"Banana.java\");\nJavaView view = new JavaView(inputLocation);\n
List<Path> files = Arrays.asList(Paths.get(\"Apple.java\"), Paths.get(\"Banana.java\"));\nAnalysisInputLocation inputLocation = new OTFCompileAnalysisInputLocation(files);\nJavaView view = new JavaView(inputLocation);\n
String content = \"public class B{ }\";\nAnalysisInputLocation location = new OTFCompileAnalysisInputLocation(\"B.java\", content );\nJavaView view = new JavaView(location);\n

JavaSourcePathInputLocation experimental! - points to a directory that is the root source directory (containing the package directory structure).

"},{"location":"analysisinput/#jimple","title":"Jimple","text":"

File-Extensions: .jimple

The JimpleAnalysisInputLocation needs a Path to a .jimple file or a directory.

Path path = Paths.get(\"Banana.java\");\nAnalysisInputLocation jimpleLocation = new JimpleAnalysisInputLocation(path);\nJavaView view = new JavaView(jimpleLocation);\n
"},{"location":"analysisinput/#android-bytecode","title":"Android Bytecode","text":"

File-Extensions: .apk

The ApkAnalysisInputLocation is the APK frontend written for Sootup

Path path = Paths.get(\"Banana.apk\");\nAnalysisInputLocation inputLocation = new ApkAnalysisInputLocation(path, \"\", DexBodyInterceptors.Default.bodyInterceptors());\nJavaView view = new JavaView(inputLocation);\n
"},{"location":"analysisinput/#android-bytecode-with-dex2jar","title":"Android Bytecode with Dex2Jar","text":"

File-Extensions: .apk

If you prefer to use dex2jar as a base to transform android apps to jimple, you can add the code below to create your own analysis input location. We used the dependency de.femtopedia.dex2jar:dex2jar:2.4.22 in the given example. We recommend to use ApkAnalysisInputLocation

Path path = Paths.get(\"Banana.apk\");\nAnalysisInputLocation inputLocation = new Dex2JarAnalysisInputLocation(path);\nJavaView view = new JavaView(inputLocation);\n
public class Dex2JarAnalysisInputLocation extends ArchiveBasedAnalysisInputLocation {\n\n    public Dex2JarAnalysisInputLocation(@Nonnull Path path, @Nullable SourceType srcType) {\n        super(path, srcType);\n        String jarPath = dex2jar(path);\n        this.path = Paths.get(jarPath);\n    }\n\n    private String dex2jar(Path path) {\n        String apkPath = path.toAbsolutePath().toString();\n        String outDir = \"./tmp/\";\n        int start = apkPath.lastIndexOf(File.separator);\n        int end = apkPath.lastIndexOf(\".apk\");\n        String outputFile = outDir + apkPath.substring(start + 1, end) + \".jar\";\n        Dex2jarCmd.main(\"-f\", apkPath, \"-o\", outputFile);\n        return outputFile;\n    }\n}\n
"},{"location":"analysisinput/#combining-multiple-analysisinputlocations","title":"Combining Multiple AnalysisInputLocations","text":"

But what if I want to point to multiple AnalysisInputLocations?

AnalysisInputLocation mainJar = new JavaClassPathAnalysisInputLocation(\"myCode.jar\");\nAnalysisInputLocation jarA = new JavaClassPathAnalysisInputLocation(\"dependencyA.jar\");\nAnalysisInputLocation jarB = new JavaClassPathAnalysisInputLocation(\"dependencyB.jar\");\n\nList<AnalysisInputLocation> inputlocationList = Arrays.asList(mainJar, jarA, jarB);\n\nJavaView view = new JavaView(inputlocationList);\n

Of course you can combine different types of AnalysisInputLocations as well!

"},{"location":"analysisinput/#maven-project-as-analysis-input-in-sootup","title":"Maven Project as Analysis Input in SootUp","text":"

This uses mvn compile + JavaClassPathAnalysisInputLocation under the hood to include a maven project.

    TODO: let the code sail with the upstream boat to this doc.\n

Unfortunately its harder to extract the path of the binary result of Gradle projects in a unified way for all kinds of models - If you have a solution are looking forward to merge your contribution :-).

"},{"location":"analysisinput/#java-cli-arguments-to-configure-sootup","title":"Java cli arguments to configure SootUp","text":"

We created a Utility that parses a String of java command line arguments and configures SootUp respectively.

"},{"location":"announcement/","title":"Announcements","text":""},{"location":"announcement/#release-announcement","title":"Release Announcement","text":"

We would like to announce Soot\u2019s successor, SootUp.

Over more than 20 years, Soot has become one of the world\u2019s most popular academic tool for Java and Android analysis and instrumentation. We thank all of you who have used and contributed to it over the years! It was your feedback and your contributions that helped it grow into such a versatile tool!

However, over the years, the requirements for Soot have changed a lot, and given its original architecture, it was no longer quite up to the task. Soot was originally developed for ahead-of-time code transformation, particularly optimization, which has become very uncommon in Java. Current use cases center much more around powerful program analyses and program-understanding tasks.

Today we are officially releasing SootUp, a new version of Soot with a completely overhauled architecture. With SootUp, we aim to keep the best things about Soot, yet overcome a lot of its drawbacks. We very much restructured Soot, particularly abolishing the heavy use of singletons. Soot now has a concept of views; each view corresponds to some version or variant of an analyzed program, and multiple views can be kept in memory at the same time. This sets the foundation, for instance, for differential or incremental program analyses.

SootUp is a library that can easily be included in other projects, leaving those projects in control. For those who intend to use it as a framework, with inversion of control, SootUp provides additional templates that help you and novices to get started more easily. The Jimple IR has been slightly simplified, and has been made immutable by default such that internally SootUp can make use of caching where desired. Where required, Jimple transformations are still allowed, but in a systematic manner, for instance assuring that analyses depending on the transformed code are notified about its changes.

Below is an overview of what\u2019s new.

SootUp is not a drop-in replacement for Soot! Due to its completely new architecture and API it is essentially an almost complete rewrite. For a while, Soot and SootUp will coexist, as many existing tools depend on Soot, yet our maintenance efforts will henceforth be focused on SootUp, not Soot, and on extending SootUp with those capabilities that people still find missing. For now, we recommend using SootUp for greenfield projects.

For more details, check out

This Page ;-) and The SootUp repository: https://github.com/soot-oss/SootUp/

We are very much looking forward to your feedback and feature requests. To this end, best create appropriate issues in the repository.

This major upgrade of Soot was made possible by generous competitive funding by the DFG, within the project \u201cFuture-proofing the Soot Framework for Program Analysis and Transformation (FutureSoot)\u201d. It was funded in the DFG\u2019s program on Research Software Sustainability.

"},{"location":"bodyinterceptors/","title":"Body Interceptors","text":"

BodyInterceptors are applied to each Body now by default, if not overridden in the used AnalysisInputLocations. The BodyInterceptors exist to to improve and normalize the raw Jimple that was generated in an earlier step. The \"raw\" generated Jimple from the Bytecodefrontend needs a lot improvements - deficits of raw Jimple are:

Optimizations (method scope)

Standardize Jimple appearance

Soot Equivalent

BodyTransformer

"},{"location":"bodyinterceptors/#localsplitter","title":"LocalSplitter","text":"

LocalSplitter is aBodyInterceptorthat attempts to identify and separate uses of a local variable (as definition) that are independent of each other by renaming local variables.

Example 1:

As shown in the example above, the local variablel1is defined twice. It can be split up into two new local variables: l1#1 and l1#2 because the both definitions are independent of each other.

Look for foldable navigation and tabs for showing old vs new

Example 2:

In the second example, the local variablel2is defined thrice. But it cannot be split up into three new local variables as in the first example, because its definitions in the if-branches are not independent of each other. Therefore, it can only be split up into two local variables as shown in the figure.

"},{"location":"bodyinterceptors/#localpacker","title":"LocalPacker","text":"

LocalPacker is aBodyInterceptorthat attempts to minimize the number of local variables which are used in body by reusing them, when it is possible. It corresponds to the inverse body transformation of LocalSplitter. Note: Every local variable's type should be assigned before running LocalPacker.

Example:

In the given example above, the local variablesl1,l3are summarized to be one local variablel1, because they have the same type without interference with each other. Likewise, the local variablesl2,l4andl5are summarized to be another local variablel2. Although the local variablel0doesn't interfere any other local variables, it cannot be summed up with other local variables because of its distinctive type.

"},{"location":"bodyinterceptors/#traptightener","title":"TrapTightener","text":"

WIP - currently not available!

TrapTightener is aBodyInterceptorthat shrinks the protected area covered by each Trap in a Body.

Example:

We assume in the example above that only theStmt:l2 := 2might throw an exception caught by theTrapwhich is labeled withlabel3. In the jimple body before running the TrapTightener, the protected area covered by the Trap contains threeStmts:l1 := 1; l2 := 2; l2 := 3. But an exception could only arise at theStmt:l2 := 2. After the implementation of TrapTightener, we will get a contractible protected area which contains only theStmtthat might throw an exception, namely theStmt:l2 := 2.

"},{"location":"bodyinterceptors/#emptyswitcheliminator","title":"EmptySwitchEliminator","text":"

EmptySwitchEliminator is aBodyInterceptorthat removes empty switch statements which contain only the default case.

Example:

As shown in the example above, the switch statement in the jimple body always takes the default action. After running EmptySwitchEliminator, the switch statement is replaced with aGotoStmtto the default case.

"},{"location":"bodyinterceptors/#unreachablecodeeliminator","title":"UnreachableCodeEliminator","text":"

UnreachableCodeEliminator is aBodyInterceptorthat removes all unreachable statements.

Example:

Obviously, the code segmentl2 = 2; l3 = 3;is unreachable. It will be removed after running the UreachableCodeEliminator.

"},{"location":"bodyinterceptors/#copypropagator","title":"CopyPropagator","text":"

CopyPropagator is a BodyInterceptor that supports copy propagation and constant propagation.

CopyPropagator

\"Definition 3[Copy Propagation]: The use of a variable y in the statement z=x+y occurring at a point p can be replaced by a variable w if every path from the entry node to point p contains the same definition y=w, for the variable y, and after the definition prior to reaching p, there is no redefinition to the variable y and no redefinition to the variable w.\"

Sreekala, S. K. and Vineeth Kumar Paleri. \u201cCopy Propagation subsumes Constant Propagation.\u201d ArXiv abs/2207.03894 (2022): n. pag.

Example for global copy propagation:

Consider a code segment in the following form:

a = b;\n...\nc = use(a); // a, b, c are local variables\n

According to the copy propagation's definition, the statementc = use(a)can be replaced withc = use(b)iff both conditions are met:

In the example for global copy propagation, the first usedl1is replaced withl0, but the second usedl1cannot be replaced withl3, because the second condition is not satisfied.

Example for constant propagation:

Constant propagation is similar to copy propagation. Consider a code segment in the following form:

a = const;\n...\nb = use(a); // a, b are local variables, const is a constant\n

After perfoming the constant propagation, the statementb = use(a)can be replaced withb = use(const)iffais not redefined on any of the paths froma = consttob = use(a).

Therefore, the first usedl1in the second example can be replaced with the constant1, but the second usedl1cannot be replaced with the constant2, becausel1is redefined on the path froml1 = 2tol4 = use(l1). However, it can be replaced with local variablel2, because the both conditions of copy propagation are met.

"},{"location":"bodyinterceptors/#localnamestandardizer","title":"LocalNameStandardizer","text":"

LocalNameStandardizer is aBodyInterceptorthat assigns a generic name to each local variable. Firstly, it will sort the local variables' order alphabetically by the string representation of their type. If there are two local variables with the same type, then the LocalNameStandardizer will use the sequence of their occurrence in jimple body to determine their order. Each assigned name consists of two parts:

The following table shows the letter corresponding to each type:

Type of Local Variable Letter boolean z byte b short s int i long l float f double d char c null n unknown e reference r"},{"location":"bodyinterceptors/#staticsingleassignmentformer","title":"StaticSingleAssignmentFormer","text":"

StaticSingleAssignmentFormer is aBodyInterceptorthat transforms jimple body into SSA form, so that each local variable is assigned exactly once and defined before its first use.

Example:

In the given example, the StaticSingleAssignmentFormer assigns eachIdentityStmtandAssignStmtto a new local variable . And each use uses the local variable which is most recently defined. Sometimes, it is impossible to determine the most recently defined local variable for a use in a join block. In this case, the StaticSingleAssignmentFormer will insert aPhiStmtin the front of the join block to merge all most recently defined local variables and assign them a new local variable.

"},{"location":"builtin-analyses/","title":"BuiltIn Analyses","text":"

More to come!

"},{"location":"builtin-analyses/#locallivenessanalyser","title":"LocalLivenessAnalyser","text":"

LocalLivenessAnalyser is used for querying for the list of live local variables before and after a given Stmt.

Example:

The live local variables before and after each Stmt will be calculated after generating an instance of LocalLivenessAnalyser as shown the example above. They can be queried by using the methods getLiveLocalsBeforeStmt and getLiveLocalsAfterStmt.

"},{"location":"builtin-analyses/#dominancefinder","title":"DominanceFinder","text":"

DomianceFinder is used for querying for the immediate dominator and dominance frontiers for a given basic block.

Example:

After generating an instance of DominanceFinder for a BlockGraph, we will get the immediate dominator and dominance frontiers for each basic block. The both properties can be queried by using the methodsgetImmediateDominatorandgetDominanceFrontiers.

"},{"location":"callgraphs/","title":"Call Graph Construction","text":"

A call graph shows the method calling relationship of a program. It is a directed graph, whose nodes represent different methods, and edges represent caller -> callee relationship.

SootUp contains several call graph construction algorithms. Below, we show how you can use each of these.

"},{"location":"callgraphs/#creating-the-type-hierarchy","title":"Creating the Type Hierarchy","text":"

All the call graph construction algorithms require the view to access the type hierarchy for resolving method calls based of sub typing relationship. Below, we show how to create a type hierarchy:

SootUpSoot
String cpString = \"src/test/resources/Callgraph/binary\";\nList<AnalysisInputLocation> inputLocations = new ArrayList();\ninputLocations.add(new JavaClassPathAnalysisInputLocation(cpStr));\ninputLocations.add(new DefaultRuntimeAnalysisInputLocation());\n\nJavaView view = new JavaView(inputLocations);\n
String userdir = System.getProperty(\"user.dir\");\nString sootCp = userdir + File.separator + \"target\" + File.separator + \"test-classes\"+ File.pathSeparator + \"lib\"+File.separator+\"rt.jar\";\nString targetTestClassName = target.exercise1.Hierarchy.class.getName();\nG.reset();\nOptions.v().set_whole_program(true);\nOptions.v().set_soot_classpath(sootCp);\nOptions.v().set_no_bodies_for_excluded(true);\nOptions.v().process_dir();\nOptions.v().set_allow_phantom_refs(true);\nOptions.v().setPhaseOption(\"jb\", \"use-original-names:true\");\nOptions.v().set_prepend_classpath(false);\nSootClass c = Scene.v().forceResolve(targetTestClassName, SootClass.BODIES);\nif (c != null)\n    c.setApplicationClass();\nScene.v().loadNecessaryClasses();\n\nHierarchy hierarchy = new Hierarchy();\n
"},{"location":"callgraphs/#defining-an-entry-method","title":"Defining an Entry Method","text":"

All call graph construction algorithms require an entry method to start with. In java application, you usually define the main method. However, it is possible to define arbitrary entry methods depending on your needs. Below, we show how to define such an entry method:

SootUp (performant)SootUp (alternative)Soot
JavaClassType classTypeA = view.getIdentifierFactory().getClassType(\"packageNameA.A\");\n\nMethodSignature entryMethodSignature =\n    view.getIdentifierFactory()\n        .getMethodSignature(\n            classTypeA,\n            \"calc\",\n            VoidType.getInstance(),\n            Collections.singletonList(classTypeA)\n        );\n
String methodSigStr = \"<packageNameA.A: void calc(packageNameA.A)\";\nMethodSignature entryMethodSignature = view\n                    .getIdentifierFactory().parseMethodSignature(methodSigStr));\n
String targetTestClassName = \"packageNameA.A\";\nSootMethod src = Scene.v().getSootClass(targetTestClassName).getMethodByName(\"doStuff\");     \n
"},{"location":"callgraphs/#class-hierarchy-analysis","title":"Class Hierarchy Analysis","text":"

Class Hierarchy Analysis (CHA) algorithm is the most sound call graph construction algorithm available in SootUp. It soundly includes all implementers of an interface, when resolving a method call on an interface. You can construct a call graph with CHA as follows:

SootUpSoot
CallGraphAlgorithm cha = new ClassHierarchyAnalysisAlgorithm(view);\n\nCallGraph cg = cha.initialize(Collections.singletonList(entryMethodSignature));\n\ncg.callsFrom(entryMethodSignature).stream()\n    .forEach(tgt -> System.out.println(entryMethodSignature + \" may call \" + tgt);\n
CHATransformer.v().transform();\nSootMethod src = Scene.v().getSootClass(targetTestClassName).getMethodByName(\"doStuff\");\nCallGraph cg = Scene.v().getCallGraph();\nIterator<MethodOrMethodContext> targets = new Targets(cg.edgesOutOf(src));\nwhile (targets.hasNext()) {\n    SootMethod tgt = (SootMethod)targets.next();\n    System.out.println(src + \" may call \" + tgt);\n}\n
"},{"location":"callgraphs/#rapid-type-analysis","title":"Rapid Type Analysis","text":"

Rapid Type Analysis (RTA) algorithm constructs a rather precise version of the call graph that the CHA constructs. It refines CHA by considering only the instantiated implementers of an interface, when resolving a method call on an interface. You can construct a call graph with RTA as follows:

SootUpSoot
CallGraphAlgorithm rta = new RapidTypeAnalysisAlgorithm(view);\n\nCallGraph cg = rta.initialize(Collections.singletonList(entryMethodSignature));\n\ncg.callsFrom(entryMethodSignature).stream()\n    .forEach(tgt -> System.out.println(entryMethodSignature + \" may call \" + tgt);\n
Transform sparkConfig = new Transform(\"cg.spark\", null);\nPhaseOptions.v().setPhaseOption(sparkConfig, \"enabled:true\");\nPhaseOptions.v().setPhaseOption(sparkConfig, \"rta:true\");\nPhaseOptions.v().setPhaseOption(sparkConfig, \"on-fly-cg:false\");\nMap phaseOptions = PhaseOptions.v().getPhaseOptions(sparkConfig);\nSparkTransformer.v().transform(sparkConfig.getPhaseName(), phaseOptions);\nSootMethod src = Scene.v().getSootClass(targetTestClassName).getMethodByName(\"doStuff\");\nCallGraph cg = Scene.v().getCallGraph();\nIterator<MethodOrMethodContext> targets = new Targets(cg.edgesOutOf(src));\nwhile (targets.hasNext()) {\n    SootMethod tgt = (SootMethod)targets.next();\n    System.out.println(src + \" may call \" + tgt);\n}  \n
"},{"location":"callgraphs/#qilin-pointer-analysis","title":"Qilin Pointer Analysis","text":"

Qilin builds a call graph on the fly with the pointer analysis. You can construct a call graph with Qilin as follows:

===\"SootUp\"

```java\nString MAINCLASS = \"dacapo.antlr.Main\"; // just an example\nPTAPattern ptaPattern = new PTAPattern(\"insens\"); // \"2o\"=>2OBJ, \"1c\"=>1CFA, etc.\nPTA pta = PTAFactory.createPTA(ptaPattern, view, MAINCLASS);\npta.run();\nCallGraph cg = pta.getCallGraph();\n```\n
"},{"location":"codepropertygraphs/","title":"Code Property Graphs","text":""},{"location":"codepropertygraphs/#dependencies","title":"Dependencies","text":"MavenGradle
<dependency>\n<groupId>org.soot-oss</groupId>\n<artifactId>sootup.codepropertygraph</artifactId>\n<version>1.3.0</version>\n</dependency>\n
compile \"org.soot-oss:sootup.codepropertygraph:1.3.0\"\n

Code Property Graphs (CPGs) are a representation of program code that combines different code representations into a single graph. This unified representation includes abstract syntax trees (ASTs), control flow graphs (CFGs), control dependence graphs (CDGs), and data dependence graphs (DDGs). CPGs enable comprehensive analysis, which makes them a powerful tool for detecting vulnerabilities and understanding code structure. For further details, refer to this thesis.

"},{"location":"codepropertygraphs/#usage-example","title":"Usage Example","text":"

In this example, we will demonstrate how to create a CPG for a vulnerable Java method and use it to identify a potential vulnerability.

"},{"location":"codepropertygraphs/#vulnerable-java-code","title":"Vulnerable Java Code","text":"

Let's assume we have the following vulnerable Java code in a file named VulnerableClass.java:

Java
public class VulnerableClass {\n    public void vulnerableMethod(String userInput) {\n        if (userInput.equals(\"admin\")) {\n            System.out.println(\"Welcome, admin!\");\n        }\n    }\n}\n
"},{"location":"codepropertygraphs/#step-1-obtain-a-sootmethod","title":"Step 1: Obtain a SootMethod","text":"

First, we assume we have a SootMethod for the vulnerableMethod. For instructions on how to obtain a SootMethod, refer to Retrieving a Method.

"},{"location":"codepropertygraphs/#step-2-create-the-cpg","title":"Step 2: Create the CPG","text":"

We can create the CPG subgraphs using the creators.

ASTCFGCDGDDG
public class AstExample {\n\n    public static void main(String[] args) {\n        // Assuming `sootMethod` is obtained from the setup step\n        SootMethod vulnerableMethod = getVulnerableMethod();\n\n        // Create the AST subgraph\n        AstCreator astCreator = new AstCreator();\n        PropertyGraph astGraph = astCreator.createGraph(vulnerableMethod);\n\n        // Print the DOT representation of the AST\n        System.out.println(astGraph.toDotGraph());\n    }\n}\n
public class CfgExample {\n\n    public static void main(String[] args) {\n        // Assuming `sootMethod` is obtained from the setup step\n        SootMethod vulnerableMethod = getVulnerableMethod();\n\n        // Create the CFG subgraph         \n        CfgCreator cfgCreator = new CfgCreator();\n        PropertyGraph cfgGraph = cfgCreator.createGraph(vulnerableMethod);\n\n        // Print the DOT representation of the CFG\n        System.out.println(cfgGraph.toDotGraph());\n    }\n}\n
public class CdgExample {\n\n    public static void main(String[] args) {\n        // Assuming `sootMethod` is obtained from the setup step\n        SootMethod vulnerableMethod = getVulnerableMethod();\n\n        // Create the CDG subgraph\n        CdgCreator cdgCreator = new CdgCreator();\n        PropertyGraph cdgGraph = cdgCreator.createGraph(vulnerableMethod);\n\n        // Print the DOT representation of the CDG\n        System.out.println(cdgGraph.toDotGraph());\n    }\n}\n
public class DdgExample {\n\n    public static void main(String[] args) {\n        // Assuming `sootMethod` is obtained from the setup step\n        SootMethod vulnerableMethod = getVulnerableMethod();\n\n        // Create the DDG subgraph\n        DdgCreator ddgCreator = new DdgCreator();\n        PropertyGraph ddgGraph = ddgCreator.createGraph(vulnerableMethod);\n\n        // Print the DOT representation of the DDG\n        System.out.println(ddgGraph.toDotGraph());\n    }\n}\n

We can create the combined CPG graph using the CpgCreator.

CPG
public class CpgExample {\n\n    public static void main(String[] args) {\n        // Assuming `sootMethod` is obtained from the setup step\n        SootMethod vulnerableMethod = getVulnerableMethod();\n\n        AstCreator astCreator = new AstCreator();\n        CfgCreator cfgCreator = new CfgCreator();\n        CdgCreator cdgCreator = new CdgCreator();\n        DdgCreator ddgCreator = new DdgCreator();\n\n        // Create the combined CPG\n        CpgCreator cpgCreator = new CpgCreator(astCreator, cfgCreator, cdgCreator, ddgCreator);\n        PropertyGraph cpg = cpgCreator.createCpg(vulnerableMethod);\n\n        // Print the DOT representation of the CPG\n        System.out.println(cpg.toDotGraph());\n    }\n}\n
"},{"location":"codepropertygraphs/#step-3-analyzing-the-cpg","title":"Step 3: Analyzing the CPG","text":"

With the CPG created, you can now analyze it for vulnerabilities. For example, you can check for potential injection vulnerabilities by analyzing data flow dependencies.

SootUp
public class VulnerabilityAnalysis {\n\n    public static void main(String[] args) {\n        // Assuming `cpg` is the PropertyGraph created in the previous step\n        for (DdgEdge edge : cpg.getEdges(DdgEdge.class)) {\n            StmtGraphNode source = (StmtGraphNode) edge.getSource();\n            StmtGraphNode destination = (StmtGraphNode) edge.getDestination();\n\n            if (isPotentiallyVulnerable(source, destination)) {\n                System.out.println(\"Potential vulnerability found between: \");\n                System.out.println(\"Source: \" + source.getStmt());\n                System.out.println(\"Destination: \" + destination.getStmt());\n            }\n        }\n    }\n\n    private static boolean isPotentiallyVulnerable(StmtGraphNode source, StmtGraphNode destination) {\n        // Implement your vulnerability detection logic here\n        return source.getStmt().toString().contains(\"userInput\") && \n               destination.getStmt() instanceof JInvokeStmt && \n               destination.getStmt().toString().contains(\"println\");\n    }\n}\n

In this example, we check for data flow dependencies between the userInput variable and any println calls, which could indicate a potential injection vulnerability.

Similarly, we can define our own queries to detect specific patterns that identify common vulnerabilities.

"},{"location":"docguide/","title":"Docguide","text":""},{"location":"docguide/#general","title":"General","text":""},{"location":"docguide/#mkdocsextensions","title":"MkDocsExtensions","text":""},{"location":"docguide/#tooltip","title":"Tooltip","text":"

Hover me

"},{"location":"docguide/#example-file-inclusion","title":"Example File inclusion","text":"

this enables that tutorial code can be tested and will fail if its not up to date anymore :)

package sootup.examples.basicSetup;\n\nimport static org.junit.jupiter.api.Assertions.assertTrue;\n\nimport java.nio.file.Path;\nimport java.nio.file.Paths;\nimport java.util.Collections;\nimport org.junit.jupiter.api.Tag;\nimport org.junit.jupiter.api.Test;\nimport sootup.core.inputlocation.AnalysisInputLocation;\nimport sootup.core.jimple.common.expr.JVirtualInvokeExpr;\nimport sootup.core.jimple.common.stmt.JInvokeStmt;\nimport sootup.core.model.SootClass;\nimport sootup.core.model.SootMethod;\nimport sootup.core.model.SourceType;\nimport sootup.core.signatures.MethodSignature;\nimport sootup.core.types.ClassType;\nimport sootup.core.views.View;\nimport sootup.java.bytecode.frontend.inputlocation.PathBasedAnalysisInputLocation;\nimport sootup.java.core.language.JavaJimple;\nimport sootup.java.core.views.JavaView;\n\n/** This example illustrates how to create and use a new Soot Project. */\n@Tag(\"Java8\")\npublic class BasicSetupTest {\n\n  @Test\n  public void createByteCodeProject() {\n    // Create a AnalysisInputLocation, which points to a directory. All class files will be loaded\n    // from the directory\n    Path pathToBinary = Paths.get(\"src/test/resources/BasicSetup/binary\");\n    AnalysisInputLocation inputLocation =\n        PathBasedAnalysisInputLocation.create(pathToBinary, SourceType.Application);\n\n    // Create a view for project, which allows us to retrieve classes\n    View view = new JavaView(inputLocation);\n\n    // Create a signature for the class we want to analyze\n    ClassType classType = view.getIdentifierFactory().getClassType(\"HelloWorld\");\n\n    // Create a signature for the method we want to analyze\n    MethodSignature methodSignature =\n        view.getIdentifierFactory()\n            .getMethodSignature(\n                classType, \"main\", \"void\", Collections.singletonList(\"java.lang.String[]\"));\n\n    // Assert that class is present\n    assertTrue(view.getClass(classType).isPresent());\n\n    // Retrieve class\n    SootClass sootClass = view.getClass(classType).get();\n\n    // Retrieve method\n    view.getMethod(methodSignature);\n\n    // Alternatively:\n    assertTrue(sootClass.getMethod(methodSignature.getSubSignature()).isPresent());\n    SootMethod sootMethod = sootClass.getMethod(methodSignature.getSubSignature()).get();\n\n    // Read jimple code of method\n    System.out.println(sootMethod.getBody());\n\n    // Assert that Hello world print is present\n    assertTrue(\n        sootMethod.getBody().getStmts().stream()\n            .anyMatch(\n                stmt ->\n                    stmt instanceof JInvokeStmt\n                        && ((JInvokeStmt) stmt).getInvokeExpr().get() instanceof JVirtualInvokeExpr\n                        && ((JInvokeStmt) stmt)\n                            .getInvokeExpr()\n                            .get()\n                            .getArg(0)\n                            .equivTo(JavaJimple.getInstance().newStringConstant(\"Hello World!\"))));\n  }\n}\n
"},{"location":"examples/","title":"SootUp Example projects","text":"

Some examples that use SootUp to get insights about a Java program.

Download

The Examples can be cloned or downloaded from our Example Repository.

"},{"location":"faq/","title":"Frequently Asked Questions","text":""},{"location":"faq/#how-to-setup-the-soot-dependency-in-maven-gradle","title":"How to setup the soot dependency (in Maven, Gradle)?","text":"

See Installation.

"},{"location":"faq/#how-to-retreive-a-sootclass-or-sootmethod","title":"How to retreive a SootClass or SootMethod?","text":"

See Getting Started.

"},{"location":"faq/#is-there-a-github-template-to-quickstart-into-development-with-sootup","title":"Is there a github template to quickstart into development with SootUp?","text":"

Not yet.

"},{"location":"faq/#error-while-using-the-sourcecodefrontend","title":"Error while using the Sourcecodefrontend","text":"

Please make sure to use Java8 to execute.

"},{"location":"faq/#exception-provider-jrt-not-found","title":"Exception: Provider \"jrt\" not found","text":"

java.lang.ExceptionInInitializerError\n    at inputlocation.sootup.java.bytecode.frontend.JrtFileSystemAnalysisInputLocationTest.getClassSource(JrtFileSystemAnalysisInputLocationTest.java:28)\n    ...\nCaused by: java.nio.file.ProviderNotFoundException: Provider \"jrt\" not found\n
To execute SootUp with JavaModules support please make sure you run the code at least the Java9 Runtime.

"},{"location":"faq/#how-to-solve-a-concurrentmodificationexception","title":"How to solve a ConcurrentModificationException?","text":"

Copy the Iterator into an intermediate Collection.

final StmtGraph<?> stmtGraph = builder.getStmtGraph();\n    for (Stmt stmt : Lists.newArrayList(stmtGraph)){\n        ...\n    }\n}\n

"},{"location":"faq/#how-can-i-visualize-a-stmtgraph","title":"How can I visualize a StmtGraph?","text":"

There exists a tool, that converts a StmtGraph to the Graphviz Dot Language.

DotExporter.buildGraph( stmtgraph );\n
or create a convenient link with the exported stmtgraph as HTTP GET Parameter
DotExporter.createUrlToWebeditor( stmtgraph );\n

"},{"location":"faq/#the-sourcecodefrontend","title":"The Sourcecodefrontend...","text":"

is in a experimental state! If you wish to use it, please consider to contribute.

"},{"location":"faq/#is-there-a-way-to-use-code-exploration-and-syntax-highlighting-features-in-my-ide-for-jimple-files","title":"Is there a way to use code exploration and syntax highlighting features in my IDE for .jimple files?","text":"

Try JimpeLsp or the vscode plugin

"},{"location":"faq/#is-there-a-way-to-use-syntax-highlighting-of-jimple-in-my-paper-thesis","title":"Is there a way to use syntax highlighting of .jimple in my paper, thesis, ...?","text":"

Have a look at LspLexer4Pygments. Its the same syntax highlighting you see here in the documentation. You can export it to LaTex as well.

"},{"location":"faq/#how-to-add-an-entry-in-this-list-ie-your-question-is-not-answered-here","title":"How to ... add an entry in this list? i.e. Your question is not answered here?","text":"

Feel free to start a Discussion.

"},{"location":"getting-started/","title":"First Steps with SootUp","text":"

Before you get started with the SootUp library, it helps to learn about the following core data structures:

"},{"location":"getting-started/#creating-a-view","title":"Creating a View","text":"

You can use bytecode analysis typically when you do not have access to the source code of the target program. Following example shows how to create a view for analyzing Java bytecode.

Create a view to analyze Java bytecode

AnalysisInputLocation inputLocation = \n        new JavaClassPathAnalysisInputLocation(\"path2Binary\");\n\nJavaView view = new JavaView(inputLocation);\n

If you have access to the source code, it is also possible to create a view for analyzing source code. Following example shows how to create view for analyzing Java source code.

Experimental! - Create a view to analyze Java source code

The source code frontend is experimental and should only be used for testing purposes. Usually you should compile the code for analysis first and use the bytecode frontend instead (see above).

AnalysisInputLocation inputLocation = \n        new JavaSourcePathAnalysisInputLocation(\"path2Source\");\n\nJavaView view = new JavaView(inputLocation);\n

If you have a Jimple file, you can create a view for analyzing jimple code directly. Following example shows how to create a view for analyzing jimple code.

Create a view to analyze jimple code

Path pathToJimple = Paths.get(\"path2Jimple\");\n\nAnalysisInputLocation inputLocation = \n        new JimpleAnalysisInputLocation(pathToJimple);\n\nJimpleView view = new JimpleView(inputLocation);\n

By default, whenever a class is retrieved, it will be permanently stored in a cache. If you do not want retrieved classes to be stored indefinetly, you can instead provide a different CacheProvider to the created view. To for example use an LRUCache instead, which stores at most e.g. 50 classes, and always replaces the least recently used class by a newly retrieved one, use the following call:

JavaView view = new JavaView(inputLocations, new LRUCacheProvider(50));\n
"},{"location":"getting-started/#retrieving-a-class","title":"Retrieving a Class","text":"

Each class is identified with a unique signature adhering to Java identifier rules, therefore you first need to specify the class signature (ClassType) as shown below.

Let's say the following is the target program that we want to analyze:

Target Program

package example;\n\npublic class HelloWorld {\n\n  public HelloWorld() {\n\n  }\n\n  public static void main(String[] args) {\n    HelloWorld hw = new HelloWorld();\n    hw.hello();\n  }\n\n  public void hello() {\n\n  }\n\n}\n

Then, we could define the ClassType of the HelloWorld class as follows:

Defining a ClassType

JavaClassType classType = \n        view.getIdentifierFactory().getClassType(\"example.HelloWorld\");\n

Once we have a ClassType that identifies the HelloWorld class, we can use it to retrieve the corresponding SootClass object from the view as shown below:

Retrieving a SootClass

JavaSootClass sootClass = view.getClass(classType).get();\n
"},{"location":"getting-started/#retrieving-a-method","title":"Retrieving a Method","text":"

Like the classes, methods also have an identifier which we call MethodSignature. For instance, we can define the method signature for identifying the main method of the HelloWorld class as follows:

Defining a MethodSignature

PureParse from String
MethodSignature methodSignature =\n    view\n        .getIdentifierFactory()\n        .getMethodSignature(\n            \"main\", // method name\n            classType,\n            \"void\", // return type\n            Collections.singletonList(\"java.lang.String[]\")); // args\n
MethodSignature methodSignature =\n    view\n        .getIdentifierFactory()\n        .parseMethodSignature(\n            \"<packageName.classType: void main(java.lang.String[])>\");\n

Once we have a MethodSignature that identifies the main method of the HelloWorld class, we can use it to retrieve the corresponding SootMethod object from the view as shown below:

Retrieving a SootMethod from the View

Optional<SootMethod> opt = view.getMethod(methodSignature);\n\nif(!opt.isPresent()){\n    return;\n}\nSootMethod method = opt.get();\nSystem.out.println(method.getModifiers());\n

Alternatively, we can also retrieve a SootMethod from SootClass that contains it.

Retrieving a SootMethod from a SootClass

MethodSubSignature mss = methodSignature.getSubSignature()\nOptional<JavaSootMethod> opt = sootClass.getMethod(mss);\n\nif(opt.isPresent()){\n  JavaSootMethod method = opt.get();\n}\n
"},{"location":"getting-started/#retrieving-the-control-flow-graph-of-a-method","title":"Retrieving the Control-Flow Graph of a Method","text":"

Each SootMethod contains a Control-Flow Graph (CFG) which is represented via the StmtGraph. This structure is usually used for program analysis. You can retrieve the CFG of a SootMethod as follows:

Retrieving the CFG of a SootMethod

StmtGraph<?> graph = sootMethod.getBody().getStmtGraph();\n
"},{"location":"getting-started/#using-the-stmtgraph","title":"Using the StmtGraph","text":"StmtGraph StmtsStmtGraph BlocksStmtGraph DotExport
for( Stmt stmt : graph.nodes()){\n    // pseudo topological order as Stmts would be serialized to a Jimple file.\n}\n\nfor( Stmt stmt : graph.nodes()){\n    // Stmts are unordered!\n}\n
List<BasicBlock<?>> blocks = graph.getBlocks();\nfor( BasicBlock<?> block : blocks){\n    // e.g. check if its a merge point\n    if(block.getPredecessors().size() > 1){\n        ...\n    }\n\n    // e.g. check if its a branching point\n    if(block.getSuccessors().size() > 1){\n        // or use block.getTail() instanceof BranchingStmt\n        ...\n    }\n\n    // e.g. check if thrown exceptions would be caught in this method\n    if(!block.getExceptionalSuccessors().isEmpty()){\n        ...\n    }\n}\n
String urlToWebeditor = DotExporter.createUrlToWebeditor(this);\nSystem.out.println(urlToWebeditor);\n

Access a complete example of the code used above

Download BasicSetup.java

"},{"location":"installation/","title":"Installation","text":""},{"location":"installation/#use-the-latest-develop-branch","title":"Use the latest develop branch","text":"

For configuration options of your build tool please visit SootUp on Jitpack.io

"},{"location":"installation/#use-releases-on-maven-central","title":"Use Releases on Maven Central","text":"

The code below shows you how to import all submodules of the SootUp repository. You can import fewer modules if your use case allows it.

Add the following dependencies to your pom.xml / build.gradle.

MavenGradle
<dependencies>\n    <dependency>\n        <groupId>org.soot-oss</groupId>\n        <artifactId>sootup.core</artifactId>\n        <version>1.3.0</version>\n    </dependency>\n    <dependency>\n        <groupId>org.soot-oss</groupId>\n        <artifactId>sootup.java.core</artifactId>\n        <version>1.3.0</version>\n    </dependency>\n    <dependency>\n        <groupId>org.soot-oss</groupId>\n        <artifactId>sootup.java.sourcecode.frontend</artifactId>\n        <version>1.3.0</version>\n    </dependency>\n    <dependency>\n        <groupId>org.soot-oss</groupId>\n        <artifactId>sootup.java.bytecode.frontend</artifactId>\n        <version>1.3.0</version>\n    </dependency>\n    <dependency>\n        <groupId>org.soot-oss</groupId>\n        <artifactId>sootup.jimple.frontend</artifactId>\n        <version>1.3.0</version>\n    </dependency>\n    <dependency>\n        <groupId>org.soot-oss</groupId>\n        <artifactId>sootup.apk.frontend</artifactId>\n        <version>1.3.0</version>\n    </dependency>\n    <dependency>\n        <groupId>org.soot-oss</groupId>\n        <artifactId>sootup.callgraph</artifactId>\n        <version>1.3.0</version>\n    </dependency>\n    <dependency>\n        <groupId>org.soot-oss</groupId>\n        <artifactId>sootup.analysis.intraprocedural</artifactId>\n        <version>1.3.0</version>\n    </dependency>\n    <dependency>\n        <groupId>org.soot-oss</groupId>\n        <artifactId>sootup.analysis.interprocedural</artifactId>\n        <version>1.3.0</version>\n    </dependency>\n    <dependency>\n        <groupId>org.soot-oss</groupId>\n        <artifactId>sootup.qilin</artifactId>\n        <version>1.3.0</version>\n    </dependency>\n    <dependency>\n        <groupId>org.soot-oss</groupId>\n        <artifactId>sootup.codepropertygraph</artifactId>\n        <version>1.3.0</version>\n    </dependency>\n</dependencies>\n
repositories {\n    mavenCentral()\n    google()\n}\n\ncompile \"org.soot-oss:sootup.core:1.3.0\"\ncompile \"org.soot-oss:sootup.java.core:1.3.0\"\ncompile \"org.soot-oss:sootup.java.sourcecode.frontend:1.3.0\"\ncompile \"org.soot-oss:sootup.java.bytecode.frontend:1.3.0\"\ncompile \"org.soot-oss:sootup.jimple.frontend:1.3.0\"\ncompile \"org.soot-oss:sootup.apk.frontend:1.3.0\"\ncompile \"org.soot-oss:sootup.callgraph:1.3.0\"\ncompile \"org.soot-oss:sootup.analysis.intraprocedural:1.3.0\"\ncompile \"org.soot-oss:sootup.analysis.interprocedural:1.3.0\"\ncompile \"org.soot-oss:sootup.qilin:1.3.0\"\ncompile \"org.soot-oss:sootup.codepropertygraph:1.3.0\"\n
"},{"location":"installation/#build-from-source","title":"Build from Source","text":"

If you'd like to get the most recent changes, you can build SootUp from source yourself and install it into your local maven repository.

git clone https://github.com/secure-software-engineering/SootUp.git\nmvn install\n

"},{"location":"jimple-body/","title":"Jimple Body","text":"

A SootMethod Body consists of the Modifiers and its StmtGraph - SootUps Control Flow Graph Structure. The StmtGraph models the flow of Stmts.

"},{"location":"jimple-body/#control-flow-graph","title":"Control Flow Graph","text":""},{"location":"jimple-body/#stmts","title":"Stmts","text":"

Learn more about the types of Stmts.

"},{"location":"jimple-body/#traps","title":"Traps","text":"

A Trap is a mechanism to model exceptional flow. A Trap represents the try-catch (finally) construct and therefore defines the type of the caught exception, the try-catch range (from-to) and the actual code that handles the exception (handler). In serialized(!) Jimple Labels are used to denote from,to and handler Stmts.

JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\n  public void <init>()\n  {\n    target.exercise1.DemoClass this;\n    this := @this: target.exercise1.DemoClass;\n    specialinvoke this.<java.lang.Object: void <init>()>();\n    return;\n  }\n\n  public void divideExample(int, int)\n  {\n    int x, y, $stack4;\n    java.io.PrintStream $stack5, $stack7;\n    java.lang.Exception $stack6;\n    target.exercise1.DemoClass this;\n\n    this := @this: target.exercise1.DemoClass;\n    x := @parameter0: int;\n    y := @parameter1: int;\n\n   label1:\n      $stack5 = <java.lang.System: java.io.PrintStream out>;\n      $stack4 = x / y;\n      virtualinvoke $stack5.<java.io.PrintStream: void println(int)>($stack4);\n\n   label2:\n      goto label4;\n\n   label3:\n      $stack6 := @caughtexception;\n      $stack7 = <java.lang.System: java.io.PrintStream out>;\n      virtualinvoke $stack7.<java.io.PrintStream: \n        void println(java.lang.String)>(\"Exception caught\");\n\n   label4:\n      return;\n\n      catch java.lang.Exception from label1 to label2 with label3;\n  }\n}\n/*\n  By calling getTraps() method, we can get the Traip chain.\n  For the above jimple code, we have the below trap:\n  Trap :\n  begin  : $stack5 = <java.lang.System: java.io.PrintStream out>\n  end    : goto [?= return]\n  handler: $stack6 := @caughtexception\n*/\n
package target.exercise1;\n\npublic class DemoClass {\n  public void divideExample(int x, int y){\n    try {\n      System.out.println(x / y);\n    }catch (Exception e){\n      System.out.println(\"Exception caught\");\n    }\n  }\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 3 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n    RETURN\n    L1\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0\n    MAXSTACK = 1\n    MAXLOCALS = 1\n\n// access flags 0x1\npublic divideExample(II)V\n  TRYCATCHBLOCK L0 L1 L2 java/lang/Exception\n  L0\n    LINENUMBER 6 L0\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    ILOAD 1\n    ILOAD 2\n    IDIV\n    INVOKEVIRTUAL java/io/PrintStream.println (I)V\n  L1\n    LINENUMBER 9 L1\n    GOTO L3\n  L2\n    LINENUMBER 7 L2\n    FRAME SAME1 java/lang/Exception\n    ASTORE 3\n  L4\n    LINENUMBER 8 L4\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    LDC \"Exception caught\"\n    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V\n  L3\n    LINENUMBER 10 L3\n    FRAME SAME\n    RETURN\n  L5\n    LOCALVARIABLE e Ljava/lang/Exception; L4 L3 3\n    LOCALVARIABLE this Land Ttarget/exercise1/DemoClass; L0 L5 0\n    LOCALVARIABLE x I L0 L5 1\n    LOCALVARIABLE y I L0 L5 2\n    MAXSTACK = 3\n    MAXLOCALS = 4\n}\n
"},{"location":"jimple-stmts/","title":"Jimple Stmt (\"Statement\")","text":"

Stmts represent instructions of the JVM. Jimple is a 3-address form code so there are max 3 operands used in a (\"manipulating\") Stmt - i.e. this does not apply to invokes as this is just operand/parameter passing.

Stmts can be roughly grouped by the amount of successors (in the StmtGraph of a Body of a Method).

"},{"location":"jimple-stmts/#branching-stmts","title":"Branching Stmts","text":"

A BranchingStmt's job is to model the jumps or conditional branching flow between Stmts.

"},{"location":"jimple-stmts/#jgotostmt","title":"JGotoStmt","text":"

represents unconditional jumps to another Stmt.

JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\n  public void <init>()\n  {\n    target.exercise1.DemoClass this;\n    this := @this: target.exercise1.DemoClass;\n    specialinvoke this.<java.lang.Object: void <init>()>();\n    return;\n  }\n  public static void sampleMethod()\n  {\n    int i;\n    i = 0;\n\n    label1:\n      if i >= 5 goto label3;\n      if i != 3 goto label2;\n      goto label3;\n\n    label2:\n      i = i + 1;\n      goto label1;\n\n    label3:\n      return;\n  }\n}\n/*\n  Here for statements \"goto label3;\" and \"goto label1;\", \n  we have two instances of JGotoStmt : \n    \"goto[?=return]\" and \"goto[?=(branch)]\".\n*/\n
package target.exercise1;\n\npublic class DemoClass {\n  public static void sampleMethod(){\n    label1:\n    for (int i = 0; i < 5; i++){\n      if(i == 3){\n        break label1;\n      }\n    }\n  }\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 3 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n    RETURN\n  L1\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0\n    MAXSTACK = 1\n    MAXLOCALS = 1\n\n// access flags 0x9\npublic static sampleMethod()V\n  L0\n    LINENUMBER 6 L0\n    ICONST_0\n    ISTORE 0\n  L1\n    FRAME APPEND [I]\n    ILOAD 0\n    ICONST_5\n    IF_ICMPGE L2\n  L3\n    LINENUMBER 7 L3\n    ILOAD 0\n    ICONST_3\n    IF_ICMPNE L4\n  L5\n    LINENUMBER 8 L5\n    GOTO L2\n  L4\n    LINENUMBER 6 L4\n    FRAME SAME\n    IINC 0 1\n    GOTO L1\n  L2\n    LINENUMBER 11 L2\n    FRAME CHOP 1\n    RETURN\n    LOCALVARIABLE i I L1 L2 0\n    MAXSTACK = 2\n    MAXLOCALS = 1\n}\n
"},{"location":"jimple-stmts/#jifstmt","title":"JIfStmt","text":"

For conditional jumps depending on the result of the conditional expression AbstractConditionExpr which needs to have boolean result. If the conditional expression is false, the next Stmt is the successor as the JIFStmt is also a FallsthroughStmt. Therefore, the JIfStmt has two successor Stmt's.

JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\n   public void <init>()\n  {\n    target.exercise1.DemoClass this;\n    this := @this: target.exercise1.DemoClass;\n    specialinvoke this.<java.lang.Object: void <init>()>();\n    return;\n  }\n\n  public static void sampleMethod(int)\n  {\n    int x, $stack1;\n    java.io.PrintStream $stack2, $stack3;\n\n    x := @parameter0: int;\n\n    $stack1 = x % 2;\n    if $stack1 != 0 goto label1;\n\n    $stack3 = <java.lang.System: java.io.PrintStream out>;\n    virtualinvoke $stack3.<java.io.PrintStream: \n      void println(java.lang.String)>(\"Even\");\n    goto label2;\n\n    label1:\n      $stack2 = <java.lang.System: java.io.PrintStream out>;\n      virtualinvoke $stack2.<java.io.PrintStream: \n        void println(java.lang.String)>(\"Odd\");\n\n    label2:\n      return;\n  }\n}\n/*\n  For statement \"if $stack1 != 0 goto label1;\", \n  we have an instance of JIfStmt :\n    \"if $stack1 != 0 goto $stack2 \n        = <java.lang.System:java.io.PrintStream out>\".\n*/\n
package target.exercise1;\n\npublic class DemoClass {\n  public static void sampleMethod(int x){\n    if(x % 2 == 0){\n      System.out.println(\"Even\");\n    }else{\n      System.out.println(\"Odd\");\n    }\n  }\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 3 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n    RETURN\n  L1\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0\n    MAXSTACK = 1\n    MAXLOCALS = 1\n\n// access flags 0x9\npublic static sampleMethod(I)V\n  L0\n    LINENUMBER 5 L0\n    ILOAD 0\n    ICONST_2\n    IREM\n    IFNE L1\n  L2\n    LINENUMBER 6 L2\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    LDC \"Even\"\n    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V\n    GOTO L3\n  L1\n    LINENUMBER 8 L1\n    FRAME SAME\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    LDC \"Odd\"\n    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V\n  L3\n    LINENUMBER 10 L3\n    FRAME SAME\n    RETURN\n  L4\n    LOCALVARIABLE x I L0 L4 0\n    MAXSTACK = 2\n    MAXLOCALS = 1\n}\n
"},{"location":"jimple-stmts/#jswitchstmt","title":"JSwitchStmt","text":"

for conditional flow that behaves like a switch-case. It has #numberOfCaseLabels+1 (for default) successor Stmt's.

JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\n  public void <init>()\n  {\n    target.exercise1.DemoClass this;\n    this := @this: target.exercise1.DemoClass;\n    specialinvoke this.<java.lang.Object: void <init>()>();\n    return;\n  }\n\n  public void switchExample(int)\n  {\n    int x;\n    java.io.PrintStream $stack2, $stack3, $stack4;\n    target.exercise1.DemoClass this;\n\n    this := @this: target.exercise1.DemoClass;\n    x := @parameter0: int;\n\n    lookupswitch(x)\n    {\n      case 1: goto label1;\n      case 2: goto label2;\n      default: goto label3;\n    };\n\n    label1:\n      $stack3 = <java.lang.System: java.io.PrintStream out>;\n      virtualinvoke $stack3.<java.io.PrintStream: \n        void println(java.lang.String)>(\"Input 1\");\n      goto label4;\n\n    label2:\n      $stack2 = <java.lang.System: java.io.PrintStream out>;\n      virtualinvoke $stack2.<java.io.PrintStream: \n        void println(java.lang.String)>(\"Input 2\");\n      goto label4;\n\n    label3:\n      $stack4 = <java.lang.System: java.io.PrintStream out>;\n      virtualinvoke $stack4.<java.io.PrintStream: \n        void println(java.lang.String)>(\"Input more than 2\");\n\n    label4:\n      return;\n  }\n}\n/*\n  Here for below statement:\n    lookupswitch(x)\n      {\n        case 1: goto label1;\n        case 2: goto label2;\n        default: goto label3;\n      };\n\n  we have an instance of JLookupSwitchStmt :\n    lookupswitch(x) \n      {     \n        case 1: goto $stack3 \n                        = <java.lang.System: java.io.PrintStream out>;     \n        case 2: goto $stack2 \n                        = <java.lang.System: java.io.PrintStream out>;     \n        default: goto $stack4 \n                        = <java.lang.System: java.io.PrintStream out>; \n      }\n*/\n
package target.exercise1;\n\npublic class DemoClass {\n  public void switchExample(int x){\n    switch (x){\n      case 1:\n        System.out.println(\"Input 1\");\n        break;\n\n      case 2:\n        System.out.println(\"Input 2\");\n        break;\n\n      default:\n        System.out.println(\"Input more than 2\");\n        break;\n\n    }\n  }\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 3 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n    RETURN\n  L1\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0\n    MAXSTACK = 1\n    MAXLOCALS = 1\n\n// access flags 0x1\npublic switchExample(I)V\n  L0\n    LINENUMBER 5 L0\n    ILOAD 1\n    LOOKUPSWITCH\n    1: L1\n    2: L2\n    default: L3\n  L1\n    LINENUMBER 7 L1\n    FRAME SAME\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    LDC \"Input 1\"\n    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V\n  L4\n    LINENUMBER 8 L4\n    GOTO L5\n  L2\n    LINENUMBER 11 L2\n    FRAME SAME\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    LDC \"Input 2\"\n    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V\n  L6\n    LINENUMBER 12 L6\n    GOTO L5\n  L3\n    LINENUMBER 15 L3\n    FRAME SAME\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    LDC \"Input more than 2\"\n    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V\n  L5\n    LINENUMBER 19 L5\n    FRAME SAME\n    RETURN\n  L7\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L7 0\n    LOCALVARIABLE x I L0 L7 1\n    MAXSTACK = 2\n    MAXLOCALS = 2\n}\n
"},{"location":"jimple-stmts/#fallsthrough-stmts","title":"FallsThrough Stmts","text":"

The execution of a FallsthroughStmt goes on with the following Stmt (if no exception was thrown).

"},{"location":"jimple-stmts/#jinvokestmt","title":"JInvokeStmt","text":"

transfers the control flow to another method until the called method returns.

JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\n  public void <init>()\n  {\n    target.exercise1.DemoClass this;\n    this := @this: target.exercise1.DemoClass;\n    specialinvoke this.<java.lang.Object: void <init>()>();\n    return;\n  }\n\n  public void print(int)\n  {\n    target.exercise1.DemoClass this;\n    int x, a;\n    java.io.PrintStream $stack4, $stack6;\n\n    this := @this: target.exercise1.DemoClass;\n    x := @parameter0: int;\n\n    a = virtualinvoke this.<target.exercise1.DemoClass: int increment(int)>(x);\n    $stack4 = <java.lang.System: java.io.PrintStream out>;\n    virtualinvoke $stack4.<java.io.PrintStream: void println(int)>(a);\n\n    a = virtualinvoke this.<target.exercise1.DemoClass: int increment(int)>(a);\n    $stack6 = <java.lang.System: java.io.PrintStream out>;\n    virtualinvoke $stack6.<java.io.PrintStream: void println(int)>(a);\n\n    return;\n  }\n\n  public int increment(int)\n  {\n    int x, $stack2;\n    target.exercise1.DemoClass this;\n\n    this := @this: target.exercise1.DemoClass;\n    x := @parameter0: int;\n\n    $stack2 = x + 1;\n    return $stack2;\n  }\n}\n/*\n  \"specialinvoke this.<java.lang.Object: void <init>()>()\", \n  \"virtualinvoke this.<target.exercise1.DemoClass: int increment(int)>(x)\", \n  \"virtualinvoke this.<target.exercise1.DemoClass: int increment(int)>(a)\" \n    are JInvokeStmts.\n*/\n
package target.exercise1;\n\npublic class DemoClass {\n  public void print(int x){\n    int a = increment(x);\n    System.out.println(a);\n    a = increment(a);\n    System.out.println(a);\n  }\n  public int increment(int x){\n    return x + 1;\n  }\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 3 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n    RETURN\n  L1\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0\n    MAXSTACK = 1\n    MAXLOCALS = 1\n\n// access flags 0x1\npublic print(I)V\n  L0\n    LINENUMBER 5 L0\n    ALOAD 0\n    ILOAD 1\n    INVOKEVIRTUAL target/exercise1/DemoClass.increment (I)I\n    ISTORE 2\n  L1\n    LINENUMBER 6 L1\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    ILOAD 2\n    INVOKEVIRTUAL java/io/PrintStream.println (I)V\n  L2\n    LINENUMBER 7 L2\n    ALOAD 0\n    ILOAD 2\n    INVOKEVIRTUAL target/exercise1/DemoClass.increment (I)I\n    ISTORE 2\n  L3\n    LINENUMBER 8 L3\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    ILOAD 2\n    INVOKEVIRTUAL java/io/PrintStream.println (I)V\n  L4\n    LINENUMBER 9 L4\n    RETURN\n  L5\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L5 0\n    LOCALVARIABLE x I L0 L5 1\n    LOCALVARIABLE a I L1 L5 2\n    MAXSTACK = 2\n    MAXLOCALS = 3\n\n// access flags 0x1\npublic increment(I)I\n  L0\n    LINENUMBER 11 L0\n    ILOAD 1\n    ICONST_1\n    IADD\n    IRETURN\n  L1\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0\n    LOCALVARIABLE x I L0 L1 1\n    MAXSTACK = 2\n    MAXLOCALS = 2\n}\n
"},{"location":"jimple-stmts/#jassignstmt","title":"JAssignStmt","text":"

assigns a Value from the right hand-side to the left hand-side. Left hand-side of an assignment can be a Local referencing a variable (i.e. a Local) or a FieldRef referencing a Field. Right hand-side of an assignment can be an expression (Expr), a Local, a FieldRef or a Constant.

JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\n  public void <init>()\n  {\n    target.exercise1.DemoClass this;\n    this := @this: target.exercise1.DemoClass;\n    specialinvoke this.<java.lang.Object: void <init>()>();\n    this.<target.exercise1.DemoClass: int counter> = 0;\n    return;\n  }\n\n  public int updateCounter()\n  {\n    target.exercise1.DemoClass this;\n    int $stack1, $stack2, $stack3;\n\n    this := @this: target.exercise1.DemoClass;\n\n    $stack1 = this.<target.exercise1.DemoClass: int counter>;\n    $stack2 = $stack1 + 1;\n    this.<target.exercise1.DemoClass: int counter> = $stack2;\n    $stack3 = this.<target.exercise1.DemoClass: int counter>;\n\n    return $stack3;\n  }\n}\n/*\n  \"this.<target.exercise1.DemoClass: int counter> = 0\", \n  \"$stack1 = this.<target.exercise1.DemoClass: int counter>\",\n  \"$stack2 = $stack1 + 1\"\n  \"this.<target.exercise1.DemoClass: int counter> = $stack2\"\n  \"$stack3 = this.<target.exercise1.DemoClass: int counter>\"\n    are JAssignStmts.\n*/\n
package target.exercise1;\n\npublic class DemoClass {\n  private int counter = 0;\n  public int updateCounter(){\n    counter = counter + 1;\n    return counter;\n  }\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x2\nprivate I counter\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 3 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n  L1\n    LINENUMBER 4 L1\n    ALOAD 0\n    ICONST_0\n    PUTFIELD target/exercise1/DemoClass.counter : I\n    RETURN\n  L2\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L2 0\n    MAXSTACK = 2\n    MAXLOCALS = 1\n\n// access flags 0x1\npublic updateCounter()I\n  L0\n    LINENUMBER 6 L0\n    ALOAD 0\n    ALOAD 0\n    GETFIELD target/exercise1/DemoClass.counter : I\n    ICONST_1\n    IADD\n    PUTFIELD target/exercise1/DemoClass.counter : I\n  L1\n    LINENUMBER 7 L1\n    ALOAD 0\n    GETFIELD target/exercise1/DemoClass.counter : I\n    IRETURN\n  L2\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L2 0\n    MAXSTACK = 3\n    MAXLOCALS = 1\n}\n
"},{"location":"jimple-stmts/#jidentitystmt","title":"JIdentityStmt","text":"

is similar to the JAssignStmt and but handles assignments of IdentityRefs to make implicit assignments explicit into the StmtGraph.

JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\n  public void <init>()\n  {\n    target.exercise1.DemoClass this;\n    this := @this: target.exercise1.DemoClass;\n    specialinvoke this.<java.lang.Object: void <init>()>();\n    return;\n  }\n\n  public void DemoClass(int)\n  {\n    target.exercise1.DemoClass this;\n    int counter;\n\n    this := @this: target.exercise1.DemoClass;\n    counter := @parameter0: int;\n    this.<target.exercise1.DemoClass: int counter> = counter;\n    return;\n  }\n}\n/*\n  \"this := @this: target.exercise1.DemoClass\" and \n    \"counter := @parameter0: int\" are JIdentityStmts\n*/\n
package target.exercise1;\n\npublic class DemoClass {\n  private int counter;\n  public void DemoClass(int counter){\n    this.counter = counter;\n  }\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x2\nprivate I counter\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 3 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n    RETURN\n  L1\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0\n    MAXSTACK = 1\n    MAXLOCALS = 1\n\n// access flags 0x1\npublic DemoClass(I)V\n  L0\n    LINENUMBER 6 L0\n    ALOAD 0\n    ILOAD 1\n    PUTFIELD target/exercise1/DemoClass.counter : I\n  L1\n    LINENUMBER 7 L1\n    RETURN\n  L2\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L2 0\n    LOCALVARIABLE counter I L0 L2 1\n    MAXSTACK = 2\n    MAXLOCALS = 2\n}\n
"},{"location":"jimple-stmts/#jentermonitorstmt-jexitmonitorstmt","title":"JEnterMonitorStmt & JExitMonitorStmt","text":"

marks synchronized blocks of code from JEnterMonitorStmt to JExitMonitorStmt.

JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\n  public void <init>()\n  {\n    target.exercise1.DemoClass this;\n    this := @this: target.exercise1.DemoClass;\n    specialinvoke this.<java.lang.Object: void <init>()>();\n    this.<target.exercise1.DemoClass: int counter> = 0;\n    return;\n  }\n\n  public int updateCounter()\n  {\n    target.exercise1.DemoClass this;\n    int $stack4, $stack5, $stack7;\n    java.lang.Throwable $stack8;\n\n    this := @this: target.exercise1.DemoClass;\n\n    entermonitor this;\n\n    label1:\n      $stack4 = this.<target.exercise1.DemoClass: int counter>;\n      $stack5 = $stack4 + 1;\n      this.<target.exercise1.DemoClass: int counter> = $stack5;\n\n      exitmonitor this;\n\n    label2:\n      goto label5;\n\n    label3:\n      $stack8 := @caughtexception;\n\n      exitmonitor this;\n\n    label4:\n      throw $stack8;\n\n    label5:\n      $stack7 = this.<target.exercise1.DemoClass: int counter>;\n      return $stack7;\n\n      catch java.lang.Throwable from label1 to label2 with label3;\n      catch java.lang.Throwable from label3 to label4 with label3;\n  }\n}\n/*\n  \"entermonitor this\" is JEnterMonitorStmt.\n  \"exitmonitor this\" is JExitMonitorStmt.\n*/\n
package target.exercise1;\n\npublic class DemoClass {\n  private int counter = 0;\n  public int updateCounter(){\n    synchronized (this) {\n      counter = counter + 1;\n    }\n    return counter;\n  }\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x2\nprivate I counter\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 3 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n  L1\n    LINENUMBER 4 L1\n    ALOAD 0\n    ICONST_0\n    PUTFIELD target/exercise1/DemoClass.counter : I\n    RETURN\n  L2\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L2 0\n    MAXSTACK = 2\n    MAXLOCALS = 1\n\n// access flags 0x1\npublic updateCounter()I\n    TRYCATCHBLOCK L0 L1 L2 null\n    TRYCATCHBLOCK L2 L3 L2 null\n  L4\n    LINENUMBER 6 L4\n    ALOAD 0\n    DUP\n    ASTORE 1\n    MONITORENTER\n  L0\n    LINENUMBER 7 L0\n    ALOAD 0\n    ALOAD 0\n    GETFIELD target/exercise1/DemoClass.counter : I\n    ICONST_1\n    IADD\n    PUTFIELD target/exercise1/DemoClass.counter : I\n  L5\n    LINENUMBER 8 L5\n    ALOAD 1\n    MONITOREXIT\n  L1\n    GOTO L6\n  L2\n    FRAME FULL [target/exercise1/DemoClass java/lang/Object] \n      [java/lang/Throwable]\n    ASTORE 2\n    ALOAD 1\n    MONITOREXIT\n  L3\n    ALOAD 2\n    ATHROW\n  L6\n    LINENUMBER 9 L6\n    FRAME CHOP 1\n    ALOAD 0\n    GETFIELD target/exercise1/DemoClass.counter : I\n    IRETURN\n  L7\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L4 L7 0\n    MAXSTACK = 3\n    MAXLOCALS = 3\n}\n
"},{"location":"jimple-stmts/#jretstmt","title":"JRetStmt","text":"

// TODO: java 1.6 spec

"},{"location":"jimple-stmts/#jbreakpointstmt","title":"JBreakpointStmt","text":"

models a Breakpoint set by a Debugger. Therefore, not really relevant for static analyses but useful for code generation.

"},{"location":"jimple-stmts/#other-stmts","title":"Other Stmts","text":""},{"location":"jimple-stmts/#jreturnstmt-jreturnvoidstmt","title":"JReturnStmt & JReturnVoidStmt","text":"

They end the execution/flow inside the current method and return (a value) to its caller.

JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\n  public void <init>()\n  {\n    target.exercise1.DemoClass this;\n    this := @this: target.exercise1.DemoClass;\n    specialinvoke this.<java.lang.Object: void <init>()>();\n    return;\n  }\n\n  public int increment(int)\n  {\n    int x, $stack2;\n    target.exercise1.DemoClass this;\n\n    this := @this: target.exercise1.DemoClass;\n    x := @parameter0: int;\n\n    $stack2 = x + 1;\n    return $stack2;\n  }\n\n  public void print()\n  {\n    java.io.PrintStream $stack1;\n    target.exercise1.DemoClass this;\n\n    this := @this: target.exercise1.DemoClass;\n    $stack1 = <java.lang.System: java.io.PrintStream out>;\n    virtualinvoke $stack1.<java.io.PrintStream: \n      void println(java.lang.String)>(\"Inside method print\");\n    return;\n  }\n}\n/*\n  \"return $stack2\" is JReturnStmt.\n  \"return\" is JReturnVoidStmt.\n*/\n
package target.exercise1;\n\npublic class DemoClass {\n  public int increment(int x){\n    return x + 1;\n  }\n  public void print(){\n    System.out.println(\"Inside method print\");\n  }\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 3 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n    RETURN\n  L1\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0\n    MAXSTACK = 1\n    MAXLOCALS = 1\n\n// access flags 0x1\npublic increment(I)I\n  L0\n    LINENUMBER 5 L0\n    ILOAD 1\n    ICONST_1\n    IADD\n    IRETURN\n  L1\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0\n    LOCALVARIABLE x I L0 L1 1\n    MAXSTACK = 2\n    MAXLOCALS = 2\n\n// access flags 0x1\npublic print()V\n  L0\n    LINENUMBER 8 L0\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    LDC \"Inside method print\"\n    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V\n  L1\n    LINENUMBER 9 L1\n    RETURN\n  L2\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L2 0\n    MAXSTACK = 2\n    MAXLOCALS = 1\n}\n
"},{"location":"jimple-stmts/#jthrowstmt","title":"JThrowStmt","text":"

Ends the execution inside the current Method if the thrown exception is not caught by a Trap, which redirects the execution to an exceptionhandler.

JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\n  public void <init>()\n  {\n    target.exercise1.DemoClass this;\n    this := @this: target.exercise1.DemoClass;\n    specialinvoke this.<java.lang.Object: void <init>()>();\n    return;\n  }\n\n  public void divideExample(int, int)\n  {\n    int y, x, $stack6;\n    java.lang.StringBuilder $stack3, $stack5, $stack7;\n    java.io.PrintStream $stack4;\n    java.lang.String $stack8;\n    java.lang.RuntimeException $stack9;\n    target.exercise1.DemoClass this;\n\n    this := @this: target.exercise1.DemoClass;\n    x := @parameter0: int;\n    y := @parameter1: int;\n\n    if y != 0 goto label1;\n\n    $stack9 = new java.lang.RuntimeException;\n    specialinvoke $stack9.<java.lang.RuntimeException: \n      void <init>(java.lang.String)>(\"Divide by zero error\");\n    throw $stack9;\n\n    label1:\n      $stack4 = <java.lang.System: java.io.PrintStream out>;\n      $stack3 = new java.lang.StringBuilder;\n      specialinvoke $stack3.<java.lang.StringBuilder: void <init>()>();\n\n      $stack5 = virtualinvoke $stack3.<java.lang.StringBuilder: \n        java.lang.StringBuilder append(java.lang.String)>(\"Divide result : \");\n      $stack6 = x / y;\n      $stack7 = virtualinvoke $stack5.<java.lang.StringBuilder: \n        java.lang.StringBuilder append(int)>($stack6);\n      $stack8 = virtualinvoke $stack7.<java.lang.StringBuilder: \n        java.lang.String toString()>();\n\n      virtualinvoke $stack4.<java.io.PrintStream: \n        void println(java.lang.String)>($stack8);\n      return;\n  }\n}\n/*\n  \"throw $stack9\" is JThrowStmt.\n*/\n
package target.exercise1;\n\npublic class DemoClass {\n  public void divideExample(int x, int y){\n    if(y == 0){\n      throw new RuntimeException(\"Divide by zero error\");\n    }\n    System.out.println(\"Divide result : \" + x / y);\n  }\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 3 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n    RETURN\n  L1\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0\n    MAXSTACK = 1\n    MAXLOCALS = 1\n\n// access flags 0x1\npublic divideExample(II)V\n  L0\n    LINENUMBER 5 L0\n    ILOAD 2\n    IFNE L1\n  L2\n    LINENUMBER 6 L2\n    NEW java/lang/RuntimeException\n    DUP\n    LDC \"Divide by zero error\"\n    INVOKESPECIAL java/lang/RuntimeException.<init> \n      (Ljava/lang/String;)V\n    ATHROW\n  L1\n    LINENUMBER 8 L1\n    FRAME SAME\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    NEW java/lang/StringBuilder\n    DUP\n    INVOKESPECIAL java/lang/StringBuilder.<init> ()V\n    LDC \"Divide result : \"\n    INVOKEVIRTUAL java/lang/StringBuilder.append \n      (Ljava/lang/String;)Ljava/lang/StringBuilder;\n    ILOAD 1\n    ILOAD 2\n    IDIV\n    INVOKEVIRTUAL java/lang/StringBuilder.append \n      (I)Ljava/lang/StringBuilder;\n    INVOKEVIRTUAL java/lang/StringBuilder.toString \n      ()Ljava/lang/String;\n    INVOKEVIRTUAL java/io/PrintStream.println \n      (Ljava/lang/String;)V\n  L3\n    LINENUMBER 9 L3\n    RETURN\n  L4\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L4 0\n    LOCALVARIABLE x I L0 L4 1\n    LOCALVARIABLE y I L0 L4 2\n    MAXSTACK = 4\n    MAXLOCALS = 3\n}\n
"},{"location":"jimple-stmts/#good-to-know","title":"Good to know","text":"

A lot of the SootUp APIs return the Stmt Interface. To determine and handle its subtypes you can make use of instanceof.

instanceOf & If-Else
    List<Stmt> stmts = ... ;\n    for( Stmt stms : stmts ){\n        if(stmt instanceof JAssignStmt){\n            // found a JAssignStmt\n            Value rhsOp = ((JAssignStmt) stmt).getRightOp();\n            ...\n        }else if(stmt instanceof JInvokeStmt){\n            // found a JInvokeStmt\n            JInvokeStmt ivkStmt = ((JInvokeStmt) stmt);\n            MethodSignature rhsOp = ivkStmt.getInvokeExpr().getMethodSignature();\n                ...\n        }else ...\n    }\n

But this could escalate to a huge if-else-tree - almost a forest. To mitigate such scenario you can implement a subclass of AbstractStmtVisitor. Just subclass the methods to the respective Stmts you need to handle. This is visitor acts like a switch-case, implemented via two dynamic calls.

StmtVisitor
    List<Stmt> stmts = ...;\n    AbstractStmtVisitor visitor = new AbstractStmtVisitor<Integer>() {\n        private int ifStmtsCounter = 0;\n        @Override\n        public void caseIfStmt(@Nonnull JIfStmt stmt) {\n            ifStmtsCounter++;\n            setResult(ifStmtCounter);\n        }\n    };\n\n    for( Stmt stms : stmts ){\n        stmt.accept(visitor);\n    }\n\n    int amountOfIfStmts = visitor.getResult();\n

Sidenote: Of course its possible can create a subclass instead of an anonymous class.

"},{"location":"jimple-types/","title":"Jimple Types","text":"

represents primary types i.e. non-reference types and non-void

"},{"location":"jimple-types/#primarytype","title":"PrimaryType","text":" JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\n  public void <init>()\n  {\n      target.exercise1.DemoClass this;\n      this := @this: target.exercise1.DemoClass;\n      specialinvoke this.<java.lang.Object: void <init>()>();\n      return;\n  }\n\n\n  public void display()\n  {\n      java.io.PrintStream $stack11, $stack13, $stack15, \n        $stack17, $stack19, $stack21, $stack23, $stack25;\n      int $stack12, $stack14, $stack16, $stack18;\n      long $stack20;\n      double $stack22;\n      float $stack24;\n      target.exercise1.DemoClass this;\n      boolean $stack26;\n\n      this := @this: target.exercise1.DemoClass;\n\n      $stack11 = <java.lang.System: java.io.PrintStream out>;\n\n      goto label1;\n\n   label1:\n      $stack26 = 0;\n      virtualinvoke $stack11.<java.io.PrintStream: \n        void println(boolean)>($stack26);\n\n      $stack13 = <java.lang.System: java.io.PrintStream out>;\n      $stack12 = 127 - 1;\n      virtualinvoke $stack13.<java.io.PrintStream: \n        void println(int)>($stack12);\n\n      $stack15 = <java.lang.System: java.io.PrintStream out>;\n      $stack14 = 97 + 1;\n      virtualinvoke $stack15.<java.io.PrintStream: \n        void println(int)>($stack14);\n\n      $stack17 = <java.lang.System: java.io.PrintStream out>;\n      $stack16 = 1123 + 1;\n      virtualinvoke $stack17.<java.io.PrintStream: \n        void println(int)>($stack16);\n\n      $stack19 = <java.lang.System: java.io.PrintStream out>;\n      $stack18 = 123456 + 1;\n      virtualinvoke $stack19.<java.io.PrintStream: \n        void println(int)>($stack18);\n\n      $stack21 = <java.lang.System: java.io.PrintStream out>;\n      $stack20 = 10L + 1L;\n      virtualinvoke $stack21.<java.io.PrintStream: \n        void println(long)>($stack20);\n\n      $stack23 = <java.lang.System: java.io.PrintStream out>;\n      $stack22 = 10.1 + 1.0;\n      virtualinvoke $stack23.<java.io.PrintStream: \n        void println(double)>($stack22);\n\n      $stack25 = <java.lang.System: java.io.PrintStream out>;\n      $stack24 = 10.1F + 1.0F;\n      virtualinvoke $stack25.<java.io.PrintStream: \n        void println(float)>($stack24);\n\n      return;\n  }\n}\n/*\n  The JimpleLocal $stack12, $stack14, $stack16, $stack18 are of IntType. \n  Similarly, $stack20 is of LongType, $stack22 is of DoubleType and so on.\n*/\n
package target.exercise1;\n\npublic class DemoClass {\n  public void display(){\n    boolean varBoolean = true;\n    byte varByte = 127;\n    char varChar = 'a';\n    short varShort = 1123;\n    int varInt = 123456;\n    long varLong = 10L;\n    double varDouble = 10.10;\n    float varFloat = 10.10f;\n\n    System.out.println(!varBoolean);\n    System.out.println(varByte-1);\n    System.out.println(varChar+1);\n    System.out.println(varShort+1);\n    System.out.println(varInt+1);\n    System.out.println(varLong+1);\n    System.out.println(varDouble+1);\n    System.out.println(varFloat+1);\n\n  }\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 3 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n    RETURN\n  L1\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0\n    MAXSTACK = 1\n    MAXLOCALS = 1\n\n// access flags 0x1\npublic display()V\n  L0\n    LINENUMBER 5 L0\n    ICONST_1\n    ISTORE 1\n  L1\n    LINENUMBER 6 L1\n    BIPUSH 127\n    ISTORE 2\n  L2\n    LINENUMBER 7 L2\n    BIPUSH 97\n    ISTORE 3\n  L3\n    LINENUMBER 8 L3\n    SIPUSH 1123\n    ISTORE 4\n  L4\n    LINENUMBER 9 L4\n    LDC 123456\n    ISTORE 5\n  L5\n    LINENUMBER 10 L5\n    LDC 10\n    LSTORE 6\n  L6\n    LINENUMBER 11 L6\n    LDC 10.1\n    DSTORE 8\n  L7\n    LINENUMBER 12 L7\n    LDC 10.1\n    FSTORE 10\n  L8\n    LINENUMBER 14 L8\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    ILOAD 1\n    IFNE L9\n    ICONST_1\n    GOTO L10\n  L9\n    FRAME FULL [target/exercise1/DemoClass I I I I I J D F] \n      [java/io/PrintStream]\n    ICONST_0\n  L10\n    FRAME FULL [target/exercise1/DemoClass I I I I I J D F] \n      [java/io/PrintStream I]\n    INVOKEVIRTUAL java/io/PrintStream.println (Z)V\n  L11\n    LINENUMBER 15 L11\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    ILOAD 2\n    ICONST_1\n    ISUB\n    INVOKEVIRTUAL java/io/PrintStream.println (I)V\n  L12\n    LINENUMBER 16 L12\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    ILOAD 3\n    ICONST_1\n    IADD\n    INVOKEVIRTUAL java/io/PrintStream.println (I)V\n  L13\n    LINENUMBER 17 L13\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    ILOAD 4\n    ICONST_1\n    IADD\n    INVOKEVIRTUAL java/io/PrintStream.println (I)V\n  L14\n    LINENUMBER 18 L14\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    ILOAD 5\n    ICONST_1\n    IADD\n    INVOKEVIRTUAL java/io/PrintStream.println (I)V\n  L15\n    LINENUMBER 19 L15\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    LLOAD 6\n    LCONST_1\n    LADD\n    INVOKEVIRTUAL java/io/PrintStream.println (J)V\n  L16\n    LINENUMBER 20 L16\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    DLOAD 8\n    DCONST_1\n    DADD\n    INVOKEVIRTUAL java/io/PrintStream.println (D)V\n  L17\n    LINENUMBER 21 L17\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    FLOAD 10\n    FCONST_1\n    FADD\n    INVOKEVIRTUAL java/io/PrintStream.println (F)V\n  L18\n    LINENUMBER 23 L18\n    RETURN\n  L19\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L19 0\n    LOCALVARIABLE varBoolean Z L1 L19 1\n    LOCALVARIABLE varByte B L2 L19 2\n    LOCALVARIABLE varChar C L3 L19 3\n    LOCALVARIABLE varShort S L4 L19 4\n    LOCALVARIABLE varInt I L5 L19 5\n    LOCALVARIABLE varLong J L6 L19 6\n    LOCALVARIABLE varDouble D L7 L19 8\n    LOCALVARIABLE varFloat F L8 L19 10\n    MAXSTACK = 5\n    MAXLOCALS = 11\n}\n
"},{"location":"jimple-types/#referencetype","title":"ReferenceType","text":" JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\npublic void <init>()\n  {\n  target.exercise1.DemoClass this;\n  this := @this: target.exercise1.DemoClass;\n  specialinvoke this.<java.lang.Object: void <init>()>();\n  return;\n  }\n\n  public target.exercise1.DemoClass getObject(target.exercise1.DemoClass)\n  {\n  target.exercise1.DemoClass obj, this;\n  this := @this: target.exercise1.DemoClass;\n  obj := @parameter0: target.exercise1.DemoClass;\n  return obj;\n  }\n\n  public void compute(boolean)\n  {\n  int[] b;\n  java.io.PrintStream $stack5, $stack6;\n  boolean check;\n  target.exercise1.DemoClass this;\n  int i;\n  null_type r0;\n  java.lang.NullPointerException soot0;\n  this := @this: target.exercise1.DemoClass;\n  check := @parameter0: boolean;\n  b = newarray (int)[5];\n  i = 0;\n\n  label1:\n    if i >= 5 goto label3;\n      if check == 0 goto label2;\n      r0 = (null_type) i;\n      soot0 = new java.lang.NullPointerException;\n      specialinvoke soot0.<java.lang.NullPointerException: \n        void <init>(java.lang.String)>\n          (\"This statement would have triggered an Exception: a[i#1] = r0\");\n      throw soot0;\n\n  label2:\n  b[i] = i;\n      i = i + 1;\n      goto label1;\n\n  label3:\n      $stack5 = <java.lang.System: java.io.PrintStream out>;\n      virtualinvoke $stack5.<java.io.PrintStream: \n        void println(java.lang.Object)>(b);\n      $stack6 = <java.lang.System: java.io.PrintStream out>;\n      virtualinvoke $stack6.<java.io.PrintStream: \n        void println(java.lang.Object)>(null);\n      return;\n  }\n}\n/*\n  The Local b is of ArrayType,\n    and Local r0 is of NullType.\n*/\n
package target.exercise1;\n\npublic class DemoClass {\n\n  public DemoClass getObject(DemoClass obj){\n    return obj;\n  }\n\n  public void compute(boolean check){\n    int a[] = null;\n    int b[] = new int[5];\n    for (int i = 0; i < 5; i++) {\n      if(check){\n        a[i] = i;\n      }\n        b[i] = i;\n    }\n    System.out.println(b);\n    System.out.println(a);\n  }\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 3 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n    RETURN\n  L1\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0\n    MAXSTACK = 1\n    MAXLOCALS = 1\n\n// access flags 0x1\npublic getObject(Ltarget/exercise1/DemoClass;)Ltarget/exercise1/DemoClass;\n  L0\n    LINENUMBER 6 L0\n    ALOAD 1\n    ARETURN\n  L1\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0\n    LOCALVARIABLE obj Ltarget/exercise1/DemoClass; L0 L1 1\n    MAXSTACK = 1\n    MAXLOCALS = 2\n\n// access flags 0x1\npublic compute(Z)V\n  L0\n    LINENUMBER 10 L0\n    ACONST_NULL\n    ASTORE 2\n  L1\n    LINENUMBER 11 L1\n    ICONST_5\n    NEWARRAY T_INT\n    ASTORE 3\n  L2\n    LINENUMBER 12 L2\n    ICONST_0\n    ISTORE 4\n  L3\n    FRAME APPEND [[I [I I]\n    ILOAD 4\n    ICONST_5\n    IF_ICMPGE L4\n  L5\n    LINENUMBER 13 L5\n    ILOAD 1\n    IFEQ L6\n  L7\n    LINENUMBER 14 L7\n    ALOAD 2\n    ILOAD 4\n    ILOAD 4\n    IASTORE\n  L6\n    LINENUMBER 16 L6\n    FRAME SAME\n    ALOAD 3\n    ILOAD 4\n    ILOAD 4\n    IASTORE\n  L8\n    LINENUMBER 12 L8\n    IINC 4 1\n    GOTO L3\n  L4\n    LINENUMBER 18 L4\n    FRAME CHOP 1\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    ALOAD 3\n    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V\n  L9\n    LINENUMBER 19 L9\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    ALOAD 2\n    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V\n  L10\n    LINENUMBER 20 L10\n    RETURN\n  L11\n    LOCALVARIABLE i I L3 L4 4\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L11 0\n    LOCALVARIABLE check Z L0 L11 1\n    LOCALVARIABLE a [I L1 L11 2\n    LOCALVARIABLE b [I L2 L11 3\n    MAXSTACK = 3\n    MAXLOCALS = 5\n}\n
"},{"location":"jimple-types/#voidtype","title":"VoidType","text":"

Used as a possible return type of a method.

JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\n  public void <init>()\n  {\n  target.exercise1.DemoClass this;\n  this := @this: target.exercise1.DemoClass;\n  specialinvoke this.<java.lang.Object: void <init>()>();\n  return;\n  }\n\n  public void voidMethod()\n  {\n  java.io.PrintStream $stack1;\n  target.exercise1.DemoClass this;\n  this := @this: target.exercise1.DemoClass;\n  $stack1 = <java.lang.System: java.io.PrintStream out>;\n  virtualinvoke $stack1.<java.io.PrintStream: \n      void println(java.lang.String)>(\"In voidMethod().\");\n  return;\n  }\n}\n/*\n  For the SootMethod - <target.exercise1.DemoClass: void voidMethod()>, \n    returnType is instance of VoidType.\n*/\n
package target.exercise1;\n\npublic class DemoClass {\n  public void voidMethod(){\n  System.out.println(\"In voidMethod().\");\n  }\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 3 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n    RETURN\n  L1\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0\n    MAXSTACK = 1\n    MAXLOCALS = 1\n\n// access flags 0x1\npublic voidMethod()V\n  L0\n    LINENUMBER 5 L0\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    LDC \"In voidMethod().\"\n    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V\n  L1\n    LINENUMBER 6 L1\n    RETURN\n  L2\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L2 0\n    MAXSTACK = 2\n    MAXLOCALS = 1\n}\n
"},{"location":"jimple-values/","title":"Jimple Values","text":""},{"location":"jimple-values/#immediate","title":"Immediate","text":"

An Immediate has a given Type and consists of a Local (\"a Variable\", \"Something that contains a Value\") or a Constant (\"Something that is a Value\").

"},{"location":"jimple-values/#local","title":"Local","text":"
i0 \n

A Local is a variable and its scope is inside its method i.e. no referencing from outside a method. Values can be assigned to Locals via JIdentityStmt or JAssignStmt.

JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\n  public void <init>()\n  {\n    target.exercise1.DemoClass this;\n    this := @this: target.exercise1.DemoClass;\n    specialinvoke this.<java.lang.Object: void <init>()>();\n    return;\n  }\n\n  public void compute()\n  {\n    java.io.PrintStream $stack2, $stack3;\n    target.exercise1.DemoClass this;\n    int local2;\n\n    this := @this: target.exercise1.DemoClass;\n    $stack2 = <java.lang.System: java.io.PrintStream out>;\n    virtualinvoke $stack2.<java.io.PrintStream: void println(int)>(1);\n\n    local2 = this.<target.exercise1.DemoClass: int global>;\n    $stack3 = <java.lang.System: java.io.PrintStream out>;\n    virtualinvoke $stack3.<java.io.PrintStream: void println(int)>(local2);\n    return;\n  }\n}\n/*\n  $stack2, this, $stack3, local2 are all Locals.\n\n  \"this := @this: target.exercise1.DemoClass\" is a JIdentityStmt assigning to a Local.\n\n  \"$stack2 = <java.lang.System: java.io.PrintStream out>\", \n    \"local2 = this.<target.exercise1.DemoClass: int global>\", \n      \"$stack3 = <java.lang.System: java.io.PrintStream out>\" \n        are JAssignStmts assigning to a Local.\n\n*/  \n
package target.exercise1;\n\npublic class DemoClass {\n\n  private int global;\n\n  public void compute(){\n    int local;\n    local = 1;\n    System.out.println(local);\n    local = this.global;\n    System.out.println(local);\n  }\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x2\nprivate I global\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 3 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n    RETURN\n  L1\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0\n    MAXSTACK = 1\n    MAXLOCALS = 1\n\n// access flags 0x1\npublic compute()V\n  L0\n    LINENUMBER 9 L0\n    ICONST_1\n    ISTORE 1\n  L1\n    LINENUMBER 10 L1\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    ILOAD 1\n    INVOKEVIRTUAL java/io/PrintStream.println (I)V\n  L2\n    LINENUMBER 11 L2\n    ALOAD 0\n    GETFIELD target/exercise1/DemoClass.global : I\n    ISTORE 1\n  L3\n    LINENUMBER 12 L3\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    ILOAD 1\n    INVOKEVIRTUAL java/io/PrintStream.println (I)V\n  L4\n    LINENUMBER 14 L4\n    RETURN\n  L5\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L5 0\n    LOCALVARIABLE local I L1 L5 1\n    MAXSTACK = 2\n    MAXLOCALS = 2\n}\n
"},{"location":"jimple-values/#constant","title":"Constant","text":"

represents an actual value itself like 42 or \"This is a String\". Constants are usually assigned to Locals or Refs. There exists a constant entity for every Primitive Type.

"},{"location":"jimple-values/#expr","title":"Expr","text":"

An expression is a language construct that calculates an operation and returns a value. E.g. a binary operation AbstracBinopExpr such as an addition a + b, an AbstractInvokeExpr such as virtualinvoke $stack2.<java.io.PrintStream: void println(int)>(1); or an UnaryExpr such as !valid. And a bunch more!

"},{"location":"jimple-values/#ref","title":"Ref","text":""},{"location":"jimple-values/#jarrayref","title":"JArrayRef","text":"

$arr[1] = 42;\n$anotherLocal = arr[99];\n
referencing an array position.

"},{"location":"jimple-values/#jfieldref","title":"JFieldRef","text":"

JFieldRefs are referencing a SootField via its FieldSignature

"},{"location":"jimple-values/#identityref","title":"IdentityRef","text":"

The IdentityRef makes those implicit special value assignments explicit.

"},{"location":"jimple-values/#jthisref","title":"JThisRef","text":"

@this: package.fruit.Banana\n
represents the this pointer of the current class.

"},{"location":"jimple-values/#jcaughtexceptionref","title":"JCaughtExceptionRef","text":"

@caughtexception\n
represents the value of the thrown exception (caught by this exceptionhandler).

"},{"location":"jimple-values/#jparameterref","title":"JParameterRef","text":"

i0 := @parameter0\ni1 := @parameter1 \n
represents a parameter of a method, identified by its index.

"},{"location":"jimple-values/#good-to-know","title":"Good to know","text":"

A lot of the SootUp APIs return the Value Interface. To determine and handle its subtypes you can make use of instanceof.

instanceOf & If-Else
    Value op = assignStmt.getRightOp();\n    if(op instanceof Local){\n        // found a Local\n        ...\n    }else if(stmt instanceof Constant){\n        // found a Constant\n        ...\n    }else ...\n

But this could escalate to a huge if-else-tree - almost a forest. To mitigate such scenario you can implement a subclass of AbstractValueVisitor. Just subclass the methods to the respective Values you need to handle. This is visitor acts like a switch-case, implemented via two dynamic calls.

StmtVisitor
    Value op = assignStmt.getRightOp() ;\n    AbstractValueVisitor visitor = new AbstractValueVisitor<Integer>() {\n        private int intConstantCounter = 0;\n        @Override\n        public void caseConstant(@Nonnull Constant c) {\n            intConstantCounter++;\n            setResult(intConstantCounter);\n        }\n    };\n\n    op.accept(visitor);\n    int amountOfIfStmts = visitor.getResult();\n

If you only need a visitor for a subset of Value, you can consider ImmediateVisitor, ConstantVisitor, ExprVisitor, RefVisitor. Sidenote: Of course its possible can create a subclass instead of an anonymous class.

"},{"location":"jimple/","title":"Jimple","text":"

What is Jimple? Jimple is the intermediate representation IR of Soot, and thus SootUp. Soot's intention is to provide a simplified way to analyze JVM bytecode. JVM bytecode is stack-based, which makes it difficult for program analysis. Java source code, on the other hand, is also not quite suitable for program analysis, due to its nested structures. Therefore, Jimple aims to bring the best of both worlds, a non-stack-based and flat (non-nested) representation. For this purpose Jimple was designed as a representation of JVM bytecode which is human readable.

Info

To learn more about jimple, refer to the thesis by Raja Vallee-Rai.

Lets have a look at the following Jimple code representing Java code of a HelloWorld class.

JimpleJavaBytecode
public class HelloWorld extends java.lang.Object\n{\n  public void <init>()\n  {\n    HelloWorld r0;\n    r0 := @this: HelloWorld;\n    specialinvoke r0.<java.lang.Object: void <init>()>();\n    return;\n  }\n\n  public static void main(java.lang.String[])\n  {\n    java.lang.String[] r0;\n    java.io.PrintStream r1;\n\n    r0 := @parameter0: java.lang.String[];\n    r1 = <java.lang.System: java.io.PrintStream out>;\n    virtualinvoke r1.<java.io.PrintStream: \n    void println(java.lang.String)>(\"Hello world!\");\n    return;\n  }\n}\n
public class HelloWorld {\n\n  public HelloWorld() {\n\n  }\n\n  public static void main(String[] var0) {\n    System.out.println(\"Hello World!\");\n  }\n\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class analysis/HelloWorld {\n\n// compiled from: HelloWorld.java\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 4 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n  L1\n    LINENUMBER 6 L1\n    RETURN\n  L2\n    LOCALVARIABLE this Lanalysis/HelloWorld; L0 L2 0\n    MAXSTACK = 1\n    MAXLOCALS = 1\n\n// access flags 0x9\npublic static main([Ljava/lang/String;)V\n  L0\n    LINENUMBER 9 L0\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    LDC \"Hello World!\"\n    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V\n  L1\n    LINENUMBER 10 L1\n    RETURN\n  L2\n    LOCALVARIABLE var0 [Ljava/lang/String; L0 L2 0\n    MAXSTACK = 2\n    MAXLOCALS = 1\n}\n

The Java Sourcecode is the easiest representation - So why all the fuzz and just use that? Sometimes we have no access to the sourcecode but have a binary with the bytecode. For most People reading bytecode is not that intuitive. So SootUp generates Jimple from the bytecode. Jimple is very verbose, but makes everything explicit, that the JVM does implicitly and transforms the stack-machine strategy by a register-machine strategy i.e. Variable (Local) handling .

"},{"location":"jimple/#jimple-grammar-structure","title":"Jimple Grammar Structure","text":"

Jimple mimics the JVMs class file structure. Therefore it is object oriented. A Single Class (or Interface) per file. Three-Address-Code which means there are no nested expressions. (nested expressions can be modeled via Locals that store intermediate calculation results.)

"},{"location":"jimple/#signatures-and-classtypes","title":"Signatures and ClassTypes","text":"

Signatures are used to identify Classes,Methods or Fields uniquely/globally. Sidenote: Locals, do not have a signature, since they are referenced within method boundaries.

JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\n  public void <init>()\n  {\n    target.exercise1.DemoClass this;\n    this := @this: target.exercise1.DemoClass;\n\n    specialinvoke this.<java.lang.Object: void <init>()>();\n    this.<target.exercise1.DemoClass: double pi> = 3.14;\n    return;\n  }\n\n  public void demoMethod()\n  {\n    java.io.PrintStream $stack3, $stack5;\n    java.lang.StringBuilder $stack4, $stack6, $stack7;\n    java.lang.String $stack8;\n    target.exercise1.DemoClass this;\n\n    this := @this: target.exercise1.DemoClass;\n    $stack3 = <java.lang.System: java.io.PrintStream out>;\n\n    virtualinvoke $stack3.<java.io.PrintStream: \n      void println(java.lang.String)>(\"pi : 3.14\");\n    $stack5 = <java.lang.System: java.io.PrintStream out>;\n    $stack4 = new java.lang.StringBuilder;\n\n    specialinvoke $stack4.<java.lang.StringBuilder: void <init>()>();\n    $stack6 = virtualinvoke $stack4.<java.lang.StringBuilder: \n      java.lang.StringBuilder append(java.lang.String)>\n        (\"pi : \");\n    $stack7 = virtualinvoke $stack6.<java.lang.StringBuilder: \n      java.lang.StringBuilder append(double)>(3.1415);\n    $stack8 = virtualinvoke $stack7.<java.lang.StringBuilder: \n      java.lang.String toString()>();\n\n    virtualinvoke $stack5.<java.io.PrintStream:     \n      void println(java.lang.String)>($stack8);\n    return;\n  }\n}\n/*\n  For JInstanceFieldRef \"this.<target.exercise1.DemoClass: double pi>\" \n    signature is <target.exercise1.DemoClass: double pi>\n  Similarly, we have other signatures like \n    <java.lang.Object: void <init>()>, \n    <java.io.PrintStream: void println(java.lang.String)> \n    and so on. \n*/\n
package target.exercise1;\n\npublic class DemoClass {\n  private final double pi = 3.14;\n\n  public void demoMethod(){\n    double localPi = 3.1415;\n    System.out.println(\"pi : \" + pi);\n    System.out.println(\"pi : \" + localPi);\n  }\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x12\nprivate final D pi = 3.14\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 3 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n  L1\n    LINENUMBER 4 L1\n    ALOAD 0\n    LDC 3.14\n    PUTFIELD target/exercise1/DemoClass.pi : D\n    RETURN\n  L2\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L2 0\n    MAXSTACK = 3\n    MAXLOCALS = 1\n\n// access flags 0x1\npublic demoMethod()V\n  L0\n    LINENUMBER 6 L0\n    LDC 3.1415\n    DSTORE 1\n  L1\n    LINENUMBER 7 L1\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    LDC \"pi : 3.14\"\n    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V\n  L2\n    LINENUMBER 8 L2\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    NEW java/lang/StringBuilder\n    DUP\n    INVOKESPECIAL java/lang/StringBuilder.<init> ()V\n    LDC \"pi : \"\n      INVOKEVIRTUAL java/lang/StringBuilder.append (Ljava/lang/String;)\n        Ljava/lang/StringBuilder;\n    DLOAD 1\n    INVOKEVIRTUAL java/lang/StringBuilder.append (D)Ljava/lang/StringBuilder;\n    INVOKEVIRTUAL java/lang/StringBuilder.toString ()Ljava/lang/String;\n    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V\n  L3\n    LINENUMBER 9 L3\n    RETURN\n  L4\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L4 0\n    LOCALVARIABLE localPi D L1 L4 1\n    MAXSTACK = 4\n    MAXLOCALS = 3\n}\n
"},{"location":"jimple/#sootclass","title":"SootClass","text":"

A SootClass consists of SootFields and SootMethods. It is referenced by its global identifier the ClassType like java.lang.String.

JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\n  public void <init>()\n  {\n    target.exercise1.DemoClass this;\n    this := @this: target.exercise1.DemoClass;\n    specialinvoke this.<java.lang.Object: void <init>()>();\n    return;\n  }\n}\n
package target.exercise1;\n\npublic class DemoClass {}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 3 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n    RETURN\n  L1\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0\n    MAXSTACK = 1\n    MAXLOCALS = 1\n}\n
"},{"location":"jimple/#sootfield","title":"SootField","text":"

A SootField is a piece of memory which can store a value that is accessible according to its visibility modifier. It is referenced by its FieldSignature like <java.lang.String: int hash>.

JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\n  public void <init>()\n  {\n    target.exercise1.DemoClass this;\n    this := @this: target.exercise1.DemoClass;\n    specialinvoke this.<java.lang.Object: void <init>()>();\n    this.<target.exercise1.DemoClass: double pi> = 3.14;\n    return;\n  }\n}\n/*\n  \"this.<target.exercise1.DemoClass: double pi>\" is JInstanceFieldRef\n*/\n
package target.exercise1;\n\npublic class DemoClass {\n  private final double pi = 3.14;\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x12\nprivate final D pi = 3.14\n\n// access flags 0x1\npublic <init>()V\n  L0\n    LINENUMBER 3 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n  L1\n    LINENUMBER 4 L1\n    ALOAD 0\n    LDC 3.14\n    PUTFIELD target/exercise1/DemoClass.pi : D\n    RETURN\n  L2\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L2 0\n    MAXSTACK = 3\n    MAXLOCALS = 1\n}\n
"},{"location":"jimple/#sootmethod-and-its-body","title":"SootMethod and its Body","text":"

The interesting part is a method. A method is a \"piece of code\" that can be executed. It is referenced by its MethodSignature like <java.lang.Object: java.lang.String toString()>.

JimpleJavaBytecode
public class target.exercise1.DemoClass extends java.lang.Object\n{\n  public void <init>()\n  {\n    target.exercise1.DemoClass this;\n    this := @this: target.exercise1.DemoClass;\n    specialinvoke this.<java.lang.Object: void <init>()>();\n    virtualinvoke this.<target.exercise1.DemoClass: \n    void demoMethod()>();\n    return;\n  }\n\n  public void demoMethod()\n  {\n    java.io.PrintStream $stack1;\n    target.exercise1.DemoClass this;\n\n    this := @this: target.exercise1.DemoClass;\n    $stack1 = <java.lang.System: java.io.PrintStream out>;\n\n    virtualinvoke $stack1.<java.io.PrintStream: \n    void println(java.lang.String)>(\"Inside method.\");\n    return;\n  }\n}\n/*\n  \"<target.exercise1.DemoClass: void demoMethod()>\" \n        and \"<target.exercise1.DemoClass: void <init>()>\" \n        are instances of SootMethod \n*/\n
package target.exercise1;\n\npublic class DemoClass {\n  DemoClass(){\n    demoMethod();\n  }\n  public void demoMethod(){\n    System.out.println(\"Inside method.\");\n  }\n}\n
// class version 52.0 (52)\n// access flags 0x21\npublic class target/exercise1/DemoClass {\n\n// compiled from: DemoClass.java\n\n// access flags 0x0\n<init>()V\n  L0\n    LINENUMBER 5 L0\n    ALOAD 0\n    INVOKESPECIAL java/lang/Object.<init> ()V\n  L1\n    LINENUMBER 6 L1\n    ALOAD 0\n    INVOKEVIRTUAL target/exercise1/DemoClass.demoMethod ()V\n  L2\n    LINENUMBER 7 L2\n    RETURN\n  L3\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L3 0\n    MAXSTACK = 1\n    MAXLOCALS = 1\n\n// access flags 0x1\npublic demoMethod()V\n  L0\n    LINENUMBER 10 L0\n    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;\n    LDC \"Inside method.\"\n    INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V\n  L1\n    LINENUMBER 11 L1\n    RETURN\n  L2\n    LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L2 0\n    MAXSTACK = 2\n    MAXLOCALS = 1\n}\n

More about the Body of the SootMethod.

"},{"location":"migrating/","title":"Migration Help","text":""},{"location":"migrating/#version-130","title":"Version 1.3.0","text":""},{"location":"migrating/#version-120","title":"Version 1.2.0","text":""},{"location":"migrating/#from-soot","title":"From Soot","text":"

Below we show a comparison of the code so far with the same functionality in sootup.

SootUpSoot
AnalysisInputLocation<JavaSootClass> inputLocation =\nnew JavaClassPathAnalysisInputLocation(\"path2Binary\");\n\nJavaView view = new JavaView(inputLocation);\n\nJavaClassType classType = \n        view.getIdentifierFactory().getClassType(\"HelloWorld\");\n\nMethodSignature methodSignature =\n    view\n        .getIdentifierFactory()\n        .getMethodSignature(\n            \"main\", classType, \"void\",\n            Collections.singletonList(\"java.lang.String[]\"));\n\nJavaSootClass sootClass = view.getClass(classType).get();\n\nMethodSubSignature mss = methodSignature.getSubSignature();\nJavaSootMethod sootMethod =  sootClass.getMethod(mss).get();\n\nsootMethod.getBody().getStmts();\n
G.reset();\nString userdir = System.getProperty(\"user.dir\");\nString sootCp = \n        userdir \n        + File.separator \n        + \"target\" \n        + File.separator \n        + \"test-classes\"\n        + File.pathSeparator + \"lib\"+File.separator+\"rt.jar\";\n\nOptions.v().set_soot_classpath(sootCp);\nOptions.v().set_whole_program(true);\nOptions.v().setPhaseOption(\"cg.cha\", \"on\");\nOptions.v().setPhaseOption(\"cg\", \"all-reachable:true\");\nOptions.v().set_no_bodies_for_excluded(true);\nOptions.v().set_allow_phantom_refs(true);\nOptions.v().setPhaseOption(\"jb\", \"use-original-names:true\");\nOptions.v().set_prepend_classpath(false);\n\nScene.v().addBasicClass(\"java.lang.StringBuilder\");\nSootClass c = \n    Scene.v().forceResolve(targetTestClassName, SootClass.BODIES);\nif (c != null) {\n    c.setApplicationClass();\n}\nScene.v().loadNecessaryClasses();\n\nSootMethod method;\nfor (SootClass c : Scene.v().getApplicationClasses()) {\n    if(c.getName().equals(\"example.HelloWorld\")){\n        for (SootMethod m : c.getMethods()) {\n            if (!m.hasActiveBody()) {\n                continue;\n            }\n            if (m.getName().equals(\"entryPoint\")) {\n                method = m;\n                break;\n            }\n        }\n    }\n}\n\nmethod.getActiveBody().getUnits();\n
"},{"location":"qilin/","title":"Incorporate Qilin Pointer Analysis","text":""},{"location":"qilin/#dependencies","title":"Dependencies","text":"MavenGradle
<dependency>\n    <groupId>org.soot-oss</groupId>\n    <artifactId>sootup.java.sourcecode</artifactId>\n    <version>1.3.0</version>\n</dependency>\n
compile \"org.soot-oss:sootup.qilin:1.3.0\"\n
"},{"location":"qilin/#how-to-create-a-pointer-analysis","title":"How to create a pointer analysis","text":"

WIP: Beware most likely the API will change so you only need to specify SootUp objects!

One can create an Andersen's context-insensitive analysis with following code:

Java
String entrypoint = \"dacapo.antlr.Main\";\nPTAPattern ptaPattern = new PTAPattern(\"insens\");\nPTA pta = PTAFactory.createPTA(ptaPattern, view, entrypoint);\npta.run();\n

Users must specify the program's View, select a PTAPattern (indicating the desired types of pointer analyses to perform), and designate the entrypoint - which is serving as the entry point for the analysis.

"},{"location":"qilin/#how-to-use-pointer-analysis-results","title":"How to use pointer analysis results","text":"

First, we can use Qilin's pointer analysis to get a On-the-Fly constructed callgraph:

OnFlyCallGraph cg = pta.getCallGraph();\n

Second, we can use it to get the points-to results for some interested local variables, fields, etc.

PointsToSet pts0 = pta.reachingObjects(method, v0);\nPointsToSet pts1 = pta.reachingObjects(method, v1, f); // PTS(v1.f)\n

Third, we can check whether two variables, a and b, are aliases by checking whether there is an object that exists in both of their points-to sets.

Qilin does not currently offer a isMayAlias API within the PTA class. However, a similar functionality can be found in qilin.test.util.AliasAssertion with the method: boolean isMayAlias(PTA pta, Value va, Value vb) This method allows to check for potential aliasing between two values given a PTA instance.

"},{"location":"qilin/#a-full-list-of-pointer-analyses","title":"A Full list of Pointer Analyses","text":"

Qilin's toolbox includes a rich set of pointer analyses, which are given below:

Note that the symbol k used in the table should be replaced with a concrete small constant like 1 or 2.

PTA patterns Description Reference insens Andersen's context-insensitive analysis Paper kc k-callsite-sensitive pointer analysis (denoted kCFA). Paper ko k-object-sensitive pointer analysis (denoted kOBJ). Paper kt k-type-sensitive pointer analysis (denoted kTYPE). Paper kh hybrid k-object-sensitive pointer analysis. Paper kht hybrid k-type-sensitive pointer analysis. Paper B-2o BEAN-guided 2OBJ. Only k=2 is supported. Paper D-2o Data-driven 2OBJ. Only k=2 is supported. Paper D-2c Data-driven 2CFA. Only k=2 is supported. Paper M-ko MAHJONG-guided kOBJ. Paper M-kc MAHJONG-guided kCFA. Paper E-ko EAGLE-guided kOBJ. Paper T-ko TURNER-guided kOBJ. Paper Z-ko ZIPPER-guided kOBJ. Paper Z-kc ZIPPER-guided kCFA. Paper Z-ko -cd The context debloated version of ZIPPER-guided kOBJ. Paper ko -cd -cda=CONCH The context debloated version of kOBJ using Conch. Paper ko -cd -cda=DEBLOATERX The context debloated version of kOBJ using DebloaterX. Paper s-kc SELECTX-guided kCFA. Paper"},{"location":"tool_setup/","title":"From Prototype to an intuitive Tool","text":"

How was the parameter order again? For a lot of cli tools we see an arbitrary order of cli parameters, different options for giving a working directory etc.. So in the wild you can see a lot from run.sh/run.bat to make files just to reorder arguments to execute a tool.

In SootUp we thought we could help on improving this madness while saving your time.

The command line parser mimics the options the java executable accepts - at least for what is supported by SootUp. This makes it very simple to just copy the execution paramaters you use for execution, to use them more or less as is four the analysis tool.

"},{"location":"tool_setup/#dependencies","title":"Dependencies","text":"MavenGradle
<dependency>\n    <groupId>commons-cli</groupId>\n    <artifactId>commons-cli</artifactId>\n    <version>1.8.0</version>\n</dependency>\n
    implementation(\"commons-cli:commons-cli:1.8.0\")\n
"},{"location":"tool_setup/#java-code","title":"Java Code","text":"
```java\n\nclass SootUpConfiguration{\n    // TODO incorporate from downstream\n}\n\n```\n

We are happy if you steal the following code to create a tool where the setup is just simple.

"},{"location":"tools/","title":"Who uses SootUp","text":""},{"location":"typehierarchy/","title":"TypeHierarchy","text":"

The TypeHierarchy models the relationship of Classes or Interfaces of a OOP program.

"},{"location":"typehierarchy/#creating-typehierarchy","title":"Creating TypeHierarchy","text":"SootUpSoot
String cpString = \"src/test/resources/Callgraph/binary\";\nList<AnalysisInputLocation> inputLocations = new ArrayList();\ninputLocations.add(new JavaClassPathAnalysisInputLocation(cpStr));\ninputLocations.add(new DefaultRuntimeAnalysisInputLocation());\n\nJavaView view = new JavaView(inputLocations);\nTypeHierarchy typehierarchy = view.getTypeHierarchy();\n
String userdir = System.getProperty(\"user.dir\");\nString sootCp = userdir + File.separator + \"target\" + File.separator + \"test-classes\"+ File.pathSeparator + \"lib\"+File.separator+\"rt.jar\";\n\nString targetTestClassName = target.exercise1.Hierarchy.class.getName();\nG.reset();\nOptions.v().set_whole_program(true);\nOptions.v().set_soot_classpath(sootCp);\nOptions.v().set_no_bodies_for_excluded(true);\nOptions.v().process_dir();\nOptions.v().set_allow_phantom_refs(true);\nOptions.v().setPhaseOption(\"jb\", \"use-original-names:true\");\nOptions.v().set_prepend_classpath(false);\nSootClass c = Scene.v().forceResolve(targetTestClassName, SootClass.BODIES);\nif (c != null)\n    c.setApplicationClass();\nScene.v().loadNecessaryClasses();\n\nHierarchy hierarchy = new Hierarchy();\n
"},{"location":"typehierarchy/#create-a-javaclasstype","title":"Create a JavaClassType","text":"SootUpSoot
JavaClassType classTypeA = view.getIdentifierFactory().getClassType(\"packageName.A\");\nJavaClassType classTypeB = view.getIdentifierFactory().getClassType(\"packageName.B\");\nJavaClassType classTypeC = view.getIdentifierFactory().getClassType(\"packageName.C\");\n
String targetTestClassName = \"packageNameA.A\";\nSootClass methodA = Scene.v().getSootClass(targetTestClassName);\n
"},{"location":"typehierarchy/#query-the-typehierarchy","title":"Query the TypeHierarchy","text":""},{"location":"typehierarchy/#classes","title":"Classes","text":"
    // if the assertion fails, the following methods will throw an Exception (you don't have to call it - it's just to illustrate the assumption)\n    assert typehierarchy.contains(classTypeA);\n\n    typehierarchy.superclassOf(classTypeA);\n\n    typehierarchy.subclassesOf(classTypeA);\n\n    typehierarchy.isSubtypeOf(classTypeA, classTypeB);\n
"},{"location":"typehierarchy/#interfaces","title":"Interfaces","text":"
    JavaClassType iterableInterface = view.getIdentifierFactory().getClassType(\"java.lang.Iterable\");\n\n    // if any of the assertions fail, the following methods will throw an Exception (you don't have to call these - it's just to illustrate the assumptions)\n    assert typehierarchy.contains(iterableInterface);\n    assert typehierarchy.isInterface(iterableInterface);\n\n    // transitive relations as well\n    typehierarchy.implementedInterfacesOf(iterableInterface);\n    typehierarchy.implementersOf(iterableInterface);\n\n    // only the direct related relations\n    typehierarchy.directlyImplementedInterfacesOf(iterableInterface);\n    typehierarchy.directlyExtendedInterfacesOf(iterableInterface);\n
"},{"location":"whatsnew/","title":"What's new in SootUp?","text":""},{"location":"whatsnew/#library-by-default","title":"Library by default","text":"

While Soot is a library and a stand-alone command-line application. SootUp, on the other hand, is designed to be a core library. It assumes that it is embedded in a client application that owns the thread of control. It can be extended with a command-line interface, included in other software projects as a library, or integrated into IDEs with JimpleLSP.

"},{"location":"whatsnew/#modular-architecture","title":"Modular Architecture","text":"

SootUp has a modular architecture, which enables its clients to include only the necessary functionality to their applications.

"},{"location":"whatsnew/#no-more-singletons","title":"No More Singletons","text":"

Singletons offer a single view of a single program version, which makes it impossible to analyze multiple programs or multiple versions of the same program. SootUp does not make use of singletons such the Scene class in the old Soot any more. It enables analyzing multiple programs simultaneously.

"},{"location":"whatsnew/#new-source-code-frontend","title":"New Source Code Frontend","text":"

Soot's JastAdd-based java frontend is not maintained anymore. In SootUp, we use WALA's well-maintained source code frontend, which will not only allow Soot to analyze Java source code, but also JavaScript and Python.

"},{"location":"whatsnew/#immutable-by-design","title":"Immutable by Design","text":"

SootUp has been designed with the goal of immutability in mind. This makes sharing objects between several entities easier, because there is no need to worry about unintended changes to other entities.

"},{"location":"whatsnew/#withers-instead-of-setters","title":"Withers instead of Setters","text":"

Due to the goal of immutability, many classes do not have setters anymore. For example, a Body does not have a method setStmts(List<Stmt> stmts). Instead, a method called withStmts(List<Stmt> stmts) has been added. This does not modify the original instance, but returns a copy of the Body but with the provided stmts in its instance. This concept of so-called with-ers can be found all throughout SootUp.

A simplified example

class Body {\n  final List<Stmt> stmts;\n  final List<Local> locals;\n\n  Body(List<Stmt> stmts, List<Local> locals) {\n    this.stmts = stmts;\n    this.locals = locals;\n  }  \n\n  Body withStmts(List<Stmt> stmts) { return new Body(stmts, this.locals); }\n  Body withLocals(List<Local> locals) { return new Body(this.stmts, locals); }\n}\n
"},{"location":"whatsnew/#intermediate-representation","title":"Intermediate Representation","text":"

Jimple is the only intermediate representation (IR) in SootUp. We modified it slightly to be able to accommodate different programming languages in the future.

"},{"location":"write_analyses/","title":"Write your own Interprocedural Dataflow Analysis","text":""},{"location":"write_analyses/#dependencies","title":"Dependencies","text":"MavenGradle
<dependency>\n    <groupId>org.soot-oss</groupId>\n    <artifactId>sootup.analysis</artifactId>\n    <version></version>\n</dependency>\n
    compile \"org.soot-oss:sootup.analysis:1.3.0\"\n
"},{"location":"write_analyses/#useful-knowledge","title":"Useful Knowledge","text":"

Background Knowledge as online lectures are available on YouTube.

"},{"location":"write_analyses/#examples","title":"Examples","text":"

Taint Analysis, TypeState Analysis, Linear Constant Propagation, ...

// TODO incorporate & guide through examples\n\nIn the meantime please have a look into the test cases of the\nanalysis submodule to see example implementations of interprocedural\ndata-flow analysis via the IFDS or IDE Framework.\n
"}]} \ No newline at end of file