diff --git a/.github/workflows/gh-pages.yml b/.github/workflows/gh-pages.yml index 01b15dc8dea..463ccc35a2b 100644 --- a/.github/workflows/gh-pages.yml +++ b/.github/workflows/gh-pages.yml @@ -51,11 +51,7 @@ jobs: python-version: 3.x # install dependencies - - run: pip install mike - - run: pip install mkdocs-material - - run: pip install mkdocs-tooltips - - run: pip install git+https://github.com/RedisLabs/mkdocs-include.git - - run: pip install git+https://github.com/swissiety/LspLexer4Pygments.git + - run: pip install mike mkdocs-material mkdocs-tooltips git+https://github.com/RedisLabs/mkdocs-include.git git+https://github.com/swissiety/LspLexer4Pygments.git # grab latest release url of the JimpleLSP jar and download it - run: curl -s -L -o ./jimplelsp.jar $(curl -s https://api.github.com/repos/swissiety/jimpleLsp/releases/latest | grep 'browser_download_url".*jar"' | cut -d ':' -f 2,3 | tr -d \") @@ -68,8 +64,8 @@ jobs: git config --local user.email "github-actions[bot]@users.noreply.github.com" git config --local user.name "github-actions[bot]" - # sanitive head_ref name - - run: echo "DOC_VERSION_NAME=$(echo ${{ github.head_ref }} | sed "s/[^[:alnum:]-]/_/g" )" >> $GITHUB_ENV + # sanitize head_ref name + - run: echo "DOC_VERSION_NAME=$(echo ${{ github.head_ref }} | sed "s/[^([[:alnum:]_.-]/_/g" )" >> $GITHUB_ENV # on push to develop branch - keep a doc around for develop to show the current state - name: deploy doc in subdirectory diff --git a/README.md b/README.md index cda231d7048..d8bb2535dd1 100644 --- a/README.md +++ b/README.md @@ -47,7 +47,7 @@ You want to collaborate? Please read our [coding guidelines and the contributors ## Publications [the SootUp paper](https://doi.org/10.1007/978-3-031-57246-3_13) explains further details and the design decision behind SootUp. -[Preprint](/docs/SootUp-paper.pdf) is also available. +[Preprint](/docs/assets/SootUp-paper.pdf) is also available. If you use SootUp in your research work, feel free to cite it as follows: diff --git a/docs/analysisinputlocations.md b/docs/analysisinputlocations.md new file mode 100644 index 00000000000..3c2773364b4 --- /dev/null +++ b/docs/analysisinputlocations.md @@ -0,0 +1,26 @@ +# Analysis Input +i.e. What should be analyzed - an `AnalysisInputLocation` points to code input SootUp can analyze. +We ship multiple Subclasses that can handle different code input. + +### Java Runtime +- Java <=8: `DefaultRTJaAnalysisInputLocation` current rt.jar (or point to any rt.jar as its just a usual .jar file) +- Java >=9: `JRTFilesystemAnalysisInputLocation` + +If you have errors like Java.lang.String, Java.lang.Object, ... you are most likely missing this AnalysisInput. + +### Java Bytecode .class, .jar, .war +- `JavaClassPathAnalysisInputLocation` - its the equivalent of the classpath you would pass to the java executable i.e. point to root(s) of package(s). + +### Java Sourcecode .java +- `OTFCompileAnalysisInputLocation` - you can point directly to .java files or pass a String with Java sourcecode, SootUp delegates to the `JavaCompiler` and transform the bytecode from the compiler to Jimple +- `JavaSourcePathInputLocation` [***experimental!***]{Has huge problems with exceptional flow!} - points to a directory that is the root source directory (containing the package directory structure). + +### Jimple .jimple +- `JimpleAnalysisInputLocation` - needs a Path to a .jimple file or a directory. + +### Android Bytecode .dex +- `ApkAnalysisInputLocation` - currenlty uses dex2jar internally - A SootUp solution to directly generate Jimple is WIP! + + +### Java cli arguments to configure SootUp +We created a [Utility](tool_setup.md) that parses a String of java command line arguments and configures SootUp respectively. \ No newline at end of file diff --git a/docs/announce.md b/docs/announcement.md similarity index 82% rename from docs/announce.md rename to docs/announcement.md index 76ecf8b2fe8..78941b91c18 100644 --- a/docs/announce.md +++ b/docs/announcement.md @@ -12,17 +12,17 @@ SootUp is a library that can easily be included in other projects, leaving those Below is an overview of what’s new. -* Library by default, framework as an option -* Modular Architecture, no more singletons -* New source code frontend -* Immutable Jimple IR -* Greatly increased testability and test coverage +- Library by default, framework as an option +- Modular Architecture, no more singletons +- New source code frontend +- Immutable Jimple IR +- Greatly increased testability and test coverage ![Coverage](https://camo.githubusercontent.com/adc4ab244f7c0c2b2f3fec0a6e5d778421ddc0be7f89a608c16533c9a964766f/68747470733a2f2f636f6465636f762e696f2f67682f736f6f742d6f73732f536f6f7455702f6272616e63682f646576656c6f702f67726170682f62616467652e7376673f746f6b656e3d454c4137553749415744) 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 -* The SootUp home page: https://soot-oss.github.io/SootUp/, and -* The SootUp repository: https://github.com/soot-oss/SootUp/ + +[This Page ;-)](https://soot-oss.github.io/SootUp/) and The SootUp repository: [https://github.com/soot-oss/SootUp/](https://soot-oss.github.io/SootUp/) We are very much looking forward to your feedback and feature requests. To this end, best create appropriate issues in the repository. diff --git a/docs/SootUp-paper.pdf b/docs/assets/SootUp-paper.pdf similarity index 100% rename from docs/SootUp-paper.pdf rename to docs/assets/SootUp-paper.pdf diff --git a/docs/figures/CopyPropagator Example_1.png b/docs/assets/figures/CopyPropagator Example_1.png similarity index 100% rename from docs/figures/CopyPropagator Example_1.png rename to docs/assets/figures/CopyPropagator Example_1.png diff --git a/docs/figures/CopyPropagator Example_2.png b/docs/assets/figures/CopyPropagator Example_2.png similarity index 100% rename from docs/figures/CopyPropagator Example_2.png rename to docs/assets/figures/CopyPropagator Example_2.png diff --git a/docs/figures/DominanceFinder Example.png b/docs/assets/figures/DominanceFinder Example.png similarity index 100% rename from docs/figures/DominanceFinder Example.png rename to docs/assets/figures/DominanceFinder Example.png diff --git a/docs/figures/EmptySwitchEliminator Example.png b/docs/assets/figures/EmptySwitchEliminator Example.png similarity index 100% rename from docs/figures/EmptySwitchEliminator Example.png rename to docs/assets/figures/EmptySwitchEliminator Example.png diff --git a/docs/figures/LocalLiveness Example.png b/docs/assets/figures/LocalLiveness Example.png similarity index 100% rename from docs/figures/LocalLiveness Example.png rename to docs/assets/figures/LocalLiveness Example.png diff --git a/docs/figures/LocalPacker Example.png b/docs/assets/figures/LocalPacker Example.png similarity index 100% rename from docs/figures/LocalPacker Example.png rename to docs/assets/figures/LocalPacker Example.png diff --git a/docs/figures/LocalSplitter Example_1.png b/docs/assets/figures/LocalSplitter Example_1.png similarity index 100% rename from docs/figures/LocalSplitter Example_1.png rename to docs/assets/figures/LocalSplitter Example_1.png diff --git a/docs/figures/LocalSplitter Example_2.png b/docs/assets/figures/LocalSplitter Example_2.png similarity index 100% rename from docs/figures/LocalSplitter Example_2.png rename to docs/assets/figures/LocalSplitter Example_2.png diff --git a/docs/figures/SSA Example_1.png b/docs/assets/figures/SSA Example_1.png similarity index 100% rename from docs/figures/SSA Example_1.png rename to docs/assets/figures/SSA Example_1.png diff --git a/docs/figures/SSA Example_2.png b/docs/assets/figures/SSA Example_2.png similarity index 100% rename from docs/figures/SSA Example_2.png rename to docs/assets/figures/SSA Example_2.png diff --git a/docs/figures/TrapTightener Example.png b/docs/assets/figures/TrapTightener Example.png similarity index 100% rename from docs/figures/TrapTightener Example.png rename to docs/assets/figures/TrapTightener Example.png diff --git a/docs/figures/UnreachableCodeEliminator Example.png b/docs/assets/figures/UnreachableCodeEliminator Example.png similarity index 100% rename from docs/figures/UnreachableCodeEliminator Example.png rename to docs/assets/figures/UnreachableCodeEliminator Example.png diff --git a/docs/bodyinterceptors.md b/docs/bodyinterceptors.md index 7963174a0fa..4039ee4508e 100644 --- a/docs/bodyinterceptors.md +++ b/docs/bodyinterceptors.md @@ -9,7 +9,8 @@ The "raw" generated Jimple from the Bytecodefrontend needs a lot improvements - - The Locals we get from the Java bytecode are typically untyped. Therefore we have to augment the Local types which is done by the TypeAssigner. - t.b.c. -Method scoped optimisations: +Optimizations (method scope) + - ConditionalBranchFolder: removes tautologic ifs that are always true/false - if we can determine it in the scope of the method. - EmptySwitchEliminator: removes switches that are not really switching - ConstantPropagatorAndFolder: calculates constant values before runtime @@ -17,16 +18,14 @@ Method scoped optimisations: - UnreachableCodeEliminator: speaks for itself. - TrapTightener -Make Local names standardized: +Standardize Jimple appearance + - LocalNameStandardizer: numbers Locals with the scheme: type-initial + number of type occurence !!! info "Soot Equivalent" - [BodyTransformer](https://github.com/soot-oss/soot/blob/develop/src/main/java/soot/BodyTransformer.java) -Below, we show how these BodyInterceptors work for the users who are interested in their internal workings. - ### LocalSplitter 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. @@ -34,7 +33,7 @@ LocalSplitter is aBodyInterceptorthat attempts to identify and sepa Example 1: -![LocalSplitter Example_1](./figures/LocalSplitter%20Example_1.png) +![LocalSplitter Example_1](assets/figures/LocalSplitter%20Example_1.png) 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. @@ -45,7 +44,7 @@ Look for foldable navigation and tabs for showing old vs new Example 2: -![LocalSplitter Example_2](./figures/LocalSplitter%20Example_2.png) +![LocalSplitter Example_2](assets/figures/LocalSplitter%20Example_2.png) 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. @@ -57,7 +56,7 @@ LocalPacker is aBodyInterceptorthat attempts to minimize the number Example: -![LocalPacker Example](./figures/LocalPacker%20Example.png) +![LocalPacker Example](assets/figures/LocalPacker%20Example.png) 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. @@ -70,7 +69,7 @@ TrapTightener is aBodyInterceptorthat shrinks the protected area co Example: -![TrapTightener Example](./figures/TrapTightener%20Example.png) +![TrapTightener Example](assets/figures/TrapTightener%20Example.png) 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. @@ -82,7 +81,7 @@ EmptySwitchEliminator is aBodyInterceptorthat removes empty switch Example: -![EmptySwitchEliminator Example](./figures/EmptySwitchEliminator%20Example.png) +![EmptySwitchEliminator Example](assets/figures/EmptySwitchEliminator%20Example.png) 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. @@ -94,7 +93,7 @@ UnreachableCodeEliminator is aBodyInterceptorthat removes all unrea Example: -![UnreachableCodeEliminator Example](./figures/UnreachableCodeEliminator%20Example.png) +![UnreachableCodeEliminator Example](assets/figures/UnreachableCodeEliminator%20Example.png) Obviously, the code segmentl2 = 2; l3 = 3;is unreachable. It will be removed after running the UreachableCodeEliminator. @@ -106,7 +105,7 @@ CopyPropagator is aBodyInterceptorthat supports the global copy pro Example for global copy propagation: -![UnreachableCodeEliminator Example](./figures/CopyPropagator%20Example_1.png) +![UnreachableCodeEliminator Example](assets/figures/CopyPropagator%20Example_1.png) Consider a code segment in the following form: @@ -125,7 +124,7 @@ In the example for global copy propagation, the first usedl1is repl Example for constant propagation: -![CopyPropagator Example_1](figures/CopyPropagator%20Example_2.png) +![CopyPropagator Example_1](assets/figures/CopyPropagator%20Example_2.png) Constant propagation is similar to copy propagation. Consider a code segment in the following form: @@ -169,8 +168,8 @@ StaticSingleAssignmentFormer is aBodyInterceptorthat transforms jim Example: -![SSA Example_1](./figures/SSA%20Example_1.png) +![SSA Example_1](assets/figures/SSA%20Example_1.png) -![SSA Example_2](./figures/SSA%20Example_2.png) +![SSA Example_2](assets/figures/SSA%20Example_2.png) 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. \ No newline at end of file diff --git a/docs/advanced-topics.md b/docs/builtin-analyses.md similarity index 78% rename from docs/advanced-topics.md rename to docs/builtin-analyses.md index 28e67ac89fc..6878e646810 100644 --- a/docs/advanced-topics.md +++ b/docs/builtin-analyses.md @@ -1,19 +1,20 @@ -# Functionalities and Utilities +# BuiltIn Analyses +More to come! -#### LocalLivenessAnalyser +### LocalLivenessAnalyser LocalLivenessAnalyser is used for querying for the list of live local variables before and after a given Stmt. Example: -![LocalLiveness Example](./figures/LocalLiveness%20Example.png) +![LocalLiveness Example](assets/figures/LocalLiveness%20Example.png) 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. -#### DominanceFinder +### DominanceFinder DomianceFinder is used for querying for the immediate dominator and dominance frontiers for a given basic block. -Example: ![DominanceFinder Example](figures/DominanceFinder%20Example.png) +Example: ![DominanceFinder Example](assets/figures/DominanceFinder%20Example.png) 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. diff --git a/docs/call-graph-construction.md b/docs/callgraphs.md similarity index 80% rename from docs/call-graph-construction.md rename to docs/callgraphs.md index 79d87e55622..dbfb503481d 100644 --- a/docs/call-graph-construction.md +++ b/docs/callgraphs.md @@ -10,8 +10,9 @@ Below, we show how to create a type hierarchy: === "SootUp" ```java + String cpString = "src/test/resources/Callgraph/binary"; List inputLocations = new ArrayList(); - inputLocations.add(new JavaClassPathAnalysisInputLocation("src/test/resources/Callgraph/binary")); + inputLocations.add(new JavaClassPathAnalysisInputLocation(cpStr)); inputLocations.add(new DefaultRTJarAnalysisInputLocation()); JavaView view = new JavaView(inputLocations); @@ -43,23 +44,33 @@ Below, we show how to create a type hierarchy: ## Defining an Entry Method All the 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" +=== "SootUp (performant)" ```java - JavaClassType classTypeA = view.getIdentifierFactory().getClassType("A"); + JavaClassType classTypeA = view.getIdentifierFactory().getClassType("packageNameA.A"); MethodSignature entryMethodSignature = view.getIdentifierFactory() .getMethodSignature( classTypeA, - JavaIdentifierFactory.getInstance() - .getMethodSubSignature( - "calc", VoidType.getInstance(), Collections.singletonList(classTypeA))); + "calc", + VoidType.getInstance(), + Collections.singletonList(classTypeA) + ); ``` - + +=== "SootUp (alternative)" + + ```java + String methodSigStr = " System.out.println(entryMethodSignature + " may call " + tgt); ``` === "Soot" @@ -90,7 +100,7 @@ You can construct a call graph with CHA as follows: while (targets.hasNext()) { SootMethod tgt = (SootMethod)targets.next(); System.out.println(src + " may call " + tgt); - } + } ``` ## Rapid Type Analysis @@ -100,13 +110,12 @@ You can construct a call graph with RTA as follows: === "SootUp" ```java - CallGraphAlgorithm rta = - new RapidTypeAnalysisAlgorithm(view); + CallGraphAlgorithm rta = new RapidTypeAnalysisAlgorithm(view); - CallGraph cg = - rta.initialize(Collections.singletonList(entryMethodSignature)); + CallGraph cg = rta.initialize(Collections.singletonList(entryMethodSignature)); - System.out.println(cg); + cg.callsFrom(entryMethodSignature).stream() + .forEach(tgt -> System.out.println(entryMethodSignature + " may call " + tgt); ``` === "Soot" @@ -128,12 +137,14 @@ You can construct a call graph with RTA as follows: ``` ## Variable Type Analysis +(**WIP!**) + Variable Type Analysis (VTA) algorithm further refines the call graph that the RTA constructs. It refines RTA by considering only the assigned instantiations of the implementers of an interface, when resolving a method call on an interface. When considering assignments, we usually need to consider **pointer** (points-to) relationship. -!!! info +!!! info "WIP" - VTA algorithm was implemented using the [Spark](https://plg.uwaterloo.ca/~olhotak/pubs/thesis-olhotak-msc.pdf) pointer analysis framework. + VTA algorithm will be implemented using the [Spark](https://plg.uwaterloo.ca/~olhotak/pubs/thesis-olhotak-msc.pdf) pointer analysis framework. A reimplementation of Spark in SootUp is currently under development. Spark requires an initial call graph to begin with. You can use one of the call graphs that we have constructed above. You can construct a call graph with VTA as follows: diff --git a/docs/css/customizetheme.css b/docs/css/customizetheme.css new file mode 100644 index 00000000000..53d080d46d5 --- /dev/null +++ b/docs/css/customizetheme.css @@ -0,0 +1,172 @@ +:root { + --md-primary-fg-color: hsla(var(--md-hue), 0%, 100%, 1); + --md-primary-fg-color--light: hsla(var(--md-hue), 0%, 100%, 0.7); + --md-primary-fg-color--dark: hsla(var(--md-hue), 0%, 0%, 0.07); + --md-primary-bg-color: hsla(var(--md-hue), 0%, 0%, 0.87); + --md-primary-bg-color--light: hsla(var(--md-hue), 0%, 0%, 0.54); + + --md-accent-fg-color: rgba(255,140,0, 1); +} +[data-md-color-accent=indigo]{ + --md-accent-fg-color: rgba(255,140,0, 1); +} + +.md-main__inner { + margin-top: 0; + margin-bottom: 5em; +} + +.md-typeset{ + font-size: 12pt; +} + +.md-typeset a { + color: rgba(255,140,0, 0.8); +} + +.md-nav__link[for]:focus, .md-nav__link[for]:hover, .md-nav__link[href]:focus, .md-nav__link[href]:hover { + color: rgba(255,140,0, 0.8); +} + +.md-typeset h1>a, .md-typeset h2>a, .md-typeset h3>a { + text-decoration: underline; +} + +.md-typeset a:hover { + color: rgba(255,140,0, 0.4); +} + +.md-typeset h1, .md-typeset h2, .md-typeset h3{ + color:rgba(255,140,0, 1); + font-weight: normal; +} + +.md-typeset .admonition, .md-typeset .admonition.info, .md-typeset .admonition.example, .md-typeset .admonition{ + border-color: rgba(255,140,0, 0.1); + margin-bottom: 3em; +} + +.md-typeset .admonition>.admonition-title:before, .md-typeset .admonition>summary:before{ + background-color: rgba(255,140,0, 1); +} + +.md-typeset .admonition>.admonition-title, .md-typeset .admonition>.admonition-title{ + background: rgba(255,140,0, 0.1); + color: rgba(255,140,0, 1); +} +.md-typeset .admonition, .md-typeset details { + border-color: rgba(255,140,0, 1); + box-shadow: none; + +} + +.md-nav label.md-nav__title{ + color:rgba(255,140,0, 1); +} +.md-nav__item--section>.md-nav__link[for] { + color:rgba(255,140,0, 1); +} + + +.md-nav__item a{ + color: #222; +} + +.md-nav__link.md-nav__link--active{ + color: rgba(255,140,0, 1); +} + + +.md-sidebar.md-sidebar--primary .md-sidebar__scrollwrap{ + border-right: 1px solid #DDD; + margin-right: 2em; + padding-right: 2em; +} +.md-sidebar.md-sidebar--secondary .md-sidebar__scrollwrap{ + border-left: 1px solid #DDD; + margin-left: 2em; + padding-left: 2em; +} + +.md-sidebar.md-sidebar--secondary .md-nav__item a { + padding: 0; +} + +.md-sidebar.md-sidebar--secondary .md-nav__item .md-nav{ + padding-bottom: 1em; +} + +.md-search__form{ + background: #EEE; +} + +.md-typeset code { + padding:0.2em; + margin:0.2em; + font-size: 10pt; + background-color: #FCFCFC; +} + +.tabbed-set.tabbed-alternate{ + background: rgba(255,140,0, 0.1); + color: rgba(255,140,0, 1); + margin-bottom: 3em; +} + +.md-typeset .tabbed-labels>label>[href]:first-child{ + color: rgba(255,140,0, 1); +} + +.md-footer{ + margin-top: 2em; + padding:1em; + background: #EEE; +} + +.md-footer-meta.md-typeset, .md-footer-meta .md-copyright{ + background: none; + color:#000; +} + +html .md-footer-meta.md-typeset a{ + color:#666; +} + +.md-typeset table:not([class]), .md-typeset table:not([class]) td{ + border-collapse: collapse; + border:none; +} + +.admonition .highlighttable{ + margin: 0; + border: none; +} +.md-typeset .admonition .highlighttable, .md-typeset details .highlighttable{ + +} + +.highlighttable{ + border:1px solid rgba(255,140,0, 0.1); + border-top: 6px solid rgba(255,140,0, 0.1); +} + +.admonition .highlighttable, .tabbed-set .highlighttable{ + border-top:none; +} + +.highlighttable .linenos{ + background-color: #FCFCFC;; + font-size: 10pt; +} + +#developedBy{ + font-size: 11pt; +} + +.tooltip{ + color: rgba(255,140,0, 0.8); +} + +p{ + margin-bottom:1.5em; +} \ No newline at end of file diff --git a/docs/examples.md b/docs/examples.md new file mode 100644 index 00000000000..5fe5be75b1e --- /dev/null +++ b/docs/examples.md @@ -0,0 +1,91 @@ +# SootUp Example projects +Some examples that use SootUp to get insights about a Java program. + +- Basic setup [Example](https://github.com/soot-oss/SootUp-Examples/blob/main/BasicSetupExample/src/main/java/sootup/examples/BasicSetup.java) +- Configure a BodyInterceptor [Example](https://github.com/soot-oss/SootUp-Examples/blob/main/BodyInterceptorExample/src/main/java/sootup/examples/BodyInterceptor.java) +- CallGraph [Example](https://github.com/soot-oss/SootUp-Examples/blob/main/CallgraphExample/src/main/java/sootup/examples/CallgraphExample.java) +- Class Hierarchy Algoritm [Example](https://github.com/soot-oss/SootUp-Examples/blob/main/ClassHierarchyExample/src/main/java/sootup/examples/ClassHierarchy.java) +- Replace a SootMethod of a SootClass [Example](https://github.com/soot-oss/SootUp-Examples/blob/main/MutatingSootClassExample/src/main/java/sootup/examples/MutatingSootClass.java) + + +!!! info "Download" + The Examples can be cloned or downloaded from our [Example Repository](https://github.com/soot-oss/SootUp-Examples.git). + + + + \ No newline at end of file diff --git a/docs/faq.md b/docs/faq.md index f9c75c88b54..e7f2efa5e51 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -42,12 +42,14 @@ or create a convenient link with the exported stmtgraph as HTTP GET Parameter DotExporter.createUrlToWebeditor( stmtgraph ); ``` +### The Sourcecodefrontend... +is in a experimental state! If you wish to use it, please consider to contribute. ### Is there a way to use code exploration and syntax highlighting features in my IDE for .jimple files? -Try [JimpeLsp](https://github.com/swissiety/JimpleLsp). +Try [JimpeLsp](https://github.com/swissiety/JimpleLsp) or the [vscode plugin](https://marketplace.visualstudio.com/items?itemName=swissiety.jimplelsp) ### Is there a way to use syntax highlighting of .jimple in my paper, thesis, ...? -Have a look at [LspLexer4Pygments](https://github.com/swissiety/LspLexer4Pygments). +Have a look at [LspLexer4Pygments](https://github.com/swissiety/LspLexer4Pygments). Its the same syntax highlighting you see here in the documentation. You can export it to LaTex as well. ### How to ... add an entry in this list? i.e. Your question is not answered here? Feel free to start a [Discussion](https://github.com/soot-oss/SootUp/discussions). diff --git a/docs/getting-started.md b/docs/getting-started.md index 2f9df6b80a4..6ca98dbe806 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -1,34 +1,17 @@ -# General Usage of SootUp -This page walks you through the core data structures, as well as shows how to get started with SootUp. - -## The core datastructures +# First Steps with SootUp Before you get started with the SootUp library, it helps to learn about the following core data structures: -- `Language`: represents the programming language of the analyzed code. - -- `AnalysisInputLocation`: points to the target code to be analyzed. - -!!! info "Soot Equivalent" - - It corresponds to the `cp` option, which specifies the classpath for Soot to find classes to be analyzed. - -- `View`: presents the code/classes under analysis. - -!!! info "Soot Equivalent" - - It corresponds to the `Scene` class, but it is not a singleton. So it is possible to instantiate multiple views simultaneously. +- [`AnalysisInputLocation`]{It corresponds to the `cp` option, which specifies the classpath for Soot to find classes to be analyzed.} + : points to the target code that shall be loaded into the `View`. -- `Scope`: defines the scope of the `View`. By default, the `View` is created with all code found on the `AnalysisInputLocation` specified for the `Project` instance. +- [`View`]{Corresponds to the `Scene` class, but it is not a singleton. So it is possible to instantiate multiple views simultaneously.}: +handles the representation of the code you configured it to analyze. -- `SootClass`: represents a class loaded into the `View`. - -- `SootMethod`: represents a method of a class. - -- `SootField`: represents a field of a class. - -- `Body`: represents a method body in Jimpe. - -- `StmtGraph`: represents the control flow graph of a method body in Jimple statements. +- `SootClass`: represents a class. Can be loaded from the View via a `ClassType` identifier. +- `SootMethod`: represents a method of a class - loaded from the View via a `MethodSignature` identifier. +- `SootField`: represents a field of a class - loaded from the View via a `FieldSignature` identifier. +- `Body`: represents a method body of a `SootMethod`. +- `StmtGraph`: represents the control flow graph of a `Body`. `Stmt`'s represent actual Instructions. ## Creating a View @@ -45,11 +28,10 @@ You can use bytecode analysis typically when you do not have access to the sourc 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. -!!! info "Experimental" - - The source code frontend is experimental and should only be used for testing purposes. You should compile the code for analysis first and use the bytecode frontend instead. +!!! info "Experimental! - Create a view to analyze Java source code" -!!! example "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). ~~~java AnalysisInputLocation inputLocation = @@ -60,7 +42,7 @@ If you have access to the source code, it is also possible to create a view for If you have a [Jimple](../jimple) file, you can create a view for analyzing jimple code directly. Following example shows how to create a view for analyzing jimple code. -!!! example "Create a project to analyze jimple code" +!!! example "Create a view to analyze jimple code" ~~~java Path pathToJimple = Paths.get("path2Jimple"); @@ -79,10 +61,10 @@ If you have a [Jimple](../jimple) file, you can create a view for analyzing jimp 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 50 classes, and always replaces the least recently used class by a newly retrieved one, use the following call: +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: ```java -JavaView view = new JavaView(Collections.singletonList(inputLocation), new LRUCacheProvider(50)); +JavaView view = new JavaView(inputLocations, new LRUCacheProvider(50)); ``` @@ -136,17 +118,25 @@ Once we have a `ClassType` that identifies the `HelloWorld` class, we can use it 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: !!! example "Defining a MethodSignature" - - ```java - MethodSignature methodSignature = - view - .getIdentifierFactory() - .getMethodSignature( - "main", // method name - classType, - "void", // return type - Collections.singletonList("java.lang.String[]")); // args - ``` + === "Pure" + ```java + MethodSignature methodSignature = + view + .getIdentifierFactory() + .getMethodSignature( + "main", // method name + classType, + "void", // return type + Collections.singletonList("java.lang.String[]")); // args + ``` + === "Parse from String" + ```java + MethodSignature methodSignature = + view + .getIdentifierFactory() + .parseMethodSignature( + ""); + ``` 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: @@ -155,16 +145,19 @@ Once we have a `MethodSignature` that identifies the `main` method of the `Hello ```java Optional opt = view.getMethod(methodSignature); - if(opt.isPresent()){ - SootMethod method = opt.get(); + if(!opt.isPresent()){ + return; } + SootMethod method = opt.get(); + System.out.println(method.getModifiers()); ``` Alternatively, we can also retrieve a `SootMethod` from `SootClass` that contains it. !!! example "Retrieving a SootMethod from a SootClass" ```java - Optional opt = sootClass.getMethod(methodSignature.getSubSignature()); + MethodSubSignature mss = methodSignature.getSubSignature() + Optional opt = sootClass.getMethod(mss); if(opt.isPresent()){ JavaSootMethod method = opt.get(); @@ -178,201 +171,51 @@ Each `SootMethod` contains a Control-Flow Graph (CFG) which is represented via t !!! example "Retrieving the CFG of a SootMethod" ```java - sootMethod.getBody().getStmts(); + StmtGraph graph = sootMethod.getBody().getStmtGraph(); ``` +## Using the StmtGraph -!!! info "Access or Download all of the code used above" - - [BasicSetup.java](https://github.com/secure-software-engineering/soot-reloaded/blob/develop/sootup.examples/src/test/java/sootup/examples/basicSetup/BasicSetup.java) - -## SootUp vs Soot - -Below we show a comparison of the code so far with the same functionality in sootup. - -=== "SootUp" - - ``` java - AnalysisInputLocation inputLocation = - new JavaClassPathAnalysisInputLocation("path2Binary"); - - JavaView view = new JavaView(inputLocation); - - JavaClassType classType = - view.getIdentifierFactory().getClassType("HelloWorld"); - - MethodSignature methodSignature = - view - .getIdentifierFactory() - .getMethodSignature( - "main", classType, "void", - Collections.singletonList("java.lang.String[]")); - - JavaSootClass sootClass = view.getClass(classType).get(); +=== "StmtGraph Stmts" + ```java + for( Stmt stmt : graph.nodes()){ + // pseudo topological order as Stmts would be serialized to a Jimple file. + } - JavaSootMethod sootMethod = sootClass.getMethod(methodSignature.getSubSignature()).get(); - - sootMethod.getBody().getStmts(); + for( Stmt stmt : graph.nodes()){ + // Stmts are unordered! + } ``` +=== "StmtGraph Blocks" + ```java + List> blocks = graph.getBlocks(); + for( BasicBlock block : blocks){ + // e.g. check if its a merge point + if(block.getPredecessors().size() > 1){ + ... + } -=== "Soot" - - ``` java - G.reset(); - String userdir = System.getProperty("user.dir"); - String sootCp = - userdir - + File.separator - + "target" - + File.separator - + "test-classes" - + File.pathSeparator + "lib"+File.separator+"rt.jar"; - - Options.v().set_soot_classpath(sootCp); - Options.v().set_whole_program(true); - Options.v().setPhaseOption("cg.cha", "on"); - Options.v().setPhaseOption("cg", "all-reachable:true"); - Options.v().set_no_bodies_for_excluded(true); - Options.v().set_allow_phantom_refs(true); - Options.v().setPhaseOption("jb", "use-original-names:true"); - Options.v().set_prepend_classpath(false); - - Scene.v().addBasicClass("java.lang.StringBuilder"); - SootClass c = - Scene.v().forceResolve(targetTestClassName, SootClass.BODIES); - if (c != null) { - c.setApplicationClass(); - } - Scene.v().loadNecessaryClasses(); - - SootMethod method; - for (SootClass c : Scene.v().getApplicationClasses()) { - if(c.getName().equals("example.HelloWorld")){ - for (SootMethod m : c.getMethods()) { - if (!m.hasActiveBody()) { - continue; - } - if (m.getName().equals("entryPoint")) { - method = m; - break; - } - } + // e.g. check if its a branching point + if(block.getSuccessors().size() > 1){ + // or use block.getTail() instanceof BranchingStmt + ... + } + + // e.g. check if thrown exceptions would be caught in this method + if(!block.getExceptionalSuccessors().isEmpty()){ + ... } } - - method.getActiveBody().getUnits(); + ``` +=== "StmtGraph DotExport" + ```java + String urlToWebeditor = DotExporter.createUrlToWebeditor(this); + System.out.println(urlToWebeditor); ``` - - - - - - - +!!! info "Access a complete example of the code used above" -# SootUp-Examples -Example code to help getting start with SootUp - - -1) Here we will provide some examples that uses SootUp to provide insights about a Java program. The repository that contains the examples can be found in [https://github.com/soot-oss/SootUp-Examples.git]. -2) There are mainly 5 projects to be considered under SootUp. - a) *BasicSetupExample* - b) *BodyInterceptorExample* - c) *CallGraphExample* - d) *ClassHierarchyExample* - e) *MutatingSootClassExample*
- -3) We have included all the five projects in 5 different branches under SootUp-Examples with detailed explanation about the project. - - a) BasicSetupExample - 1) package sootup.examples; - defines the package name for the Java class. - 2) import statement - defines various classes and interfaces from different packages that the program uses. - 3) public class BasicSetup - declares a public class named 'BasicSetup' which is the main class for this program. - 4) Then we have created a main method which is the entry point of the progrram - 5) Path pathToBinary object pointing to a directory that contains the binary files ie class files to be analyzed and Paths.get is a static method that converts string path to a 'Path' object. - 6) AnalysisInputLocation object specifying where SootUp should look for classes to analyze. - 7) View object is created for the project allowing the retrieal of classes from the specified input location. JavaView is specific implementation of View tailed for Java projects. - 8) The ClassType object is created for the class name 'HelloWorld'. This object represents the type of class to be analyzed. - 9) A MethodSignature object is created for the main method of the HelloWorld class. This signature specifies the method's return type (void) and its parameter types (a single parameter of type String[]). - 10) The if statment checks for the presences of the class 'HelloWorld'. If not it prints "Class not ffound!" and exits the program. - 11) Then it retrieves the SootClass object representing the HelloWorld class, assuming it is present. - 12) view.getMethod(methodSignature); - Attempts to retrieve the specified method from the project. - 13) The if statment after this, checks if the main method is present in the HelloWorld class. If not, it prints "Method not found!" and exits. - 14) Then the next statment retrieves the SootMethod object for the main method and prints its body, which is in Jimple, a simplified version of Java bytecode used by Soot for analysis and transformation. - 15) Then the next if condition checks if the method containts a specific statement called 'Hello World!'. - - b) BodyInterceptor - 1) package sootup.examples; - defines the package name for the Java class. - 2) import statement - defines various classes and interfaces from different packages that the program uses. - 3) public class BodyInterceptor - declares a public class named "BodyInterceptor". - 4) Then we have created a main method in which is the entry point for the code. - 5) Then we have created an AnalysisInputLocation pointing to a directory with class files to be loaded. It specifies that the DeadAssignmentEliminator interceptor should be applied to these classes. - 6) Then created a View that initializes a JavaView with the specified inputLocation, allowing interaction with the classes for analysis. - 7) Then have created a ClassType and MethodSignature which is used for analysis. The signature contains method name, return type and parameters. - 8) Then we check for the existence of the class and method in the given view. - 9) If they exist, a SootClass and SootMethod objects are used to retrieve the same. - 10) Then prints the body of the SootMethod object. - 11) Then we check if the interceptor worked. ie here we check if the DeadAssignmentEliminator interceptor has successfully removed a specific assignment (l1 = 3) from the method's body. It does this by looking through all statements (JAssignStmt) in the method body and checking if the assignment is not present. - 12) Then it prints the result of the interceptor check. - - - c) CallGraphExample - 1) package sootup.examples; - defines the package name for the Java class. - 2) import statement - defines various classes and interfaces from different packages that the program uses. - 3) public class CallgraphExample - declares a public class named "CallGraphExample". - 4) Then we have created a main method in which is the entry point for the code. - 5) List inputLocations creates a list of AnalysisInputLocation objects. These specify where Soot should look for Java class files for analysis. - 6) Then we have provided towo inputLocations.add() - one for the project's class file directory and another for Java's runtime library (rt.jar). - 7) Then we have created a JavaView which is used for analysing the Java program. - 8) Then we have created two ClassType for two classes ie 'A' and 'B'. They are used to create a MethodSignature for a method that will be analysed. - 9) ViewTypeHierarchy - then we have set up a type hierarchy from the provided view and prints the subclasses of class 'A'. - 10) Initializes a CallGraphAlgorithm using the ClassHierarchyAnalysisAlgorithm, which is a method for constructing call graphs. - 11) Then we creates a call graph by initialising the Class Hierarchy Analysis (cha) with the entry method signature. - 12) Prints information about calls from the entry method in the call graph. - - d) ClassHierarchyExample - 1) package sootup.examples; - defines the package name for the Java class. - 2) import statement - defines various classes and interfaces from different packages that the program uses. - 3) public class ClassHierarchy - declares a public class named "ClassHierarchy". - 4) Then we have created a main method in which is the entry point for the code. - 5) Then creates a list of AnalysisInputLocation objects. These specify where Soot should look for Java class files for analysis. Two locations are added: one for the project's binary directory and another for the default Java runtime library (rt.jar). - 6) Initializes a JavaView object with the previously created input locations. - 7) Initializes a ViewTypeHierarchy object using the view. This object will be used to analyze the class hierarchy. - 8) Then we have created two ClassTypes. These lines get JavaClassType objects for classes "A" and "C". These types are used for further hierarchy analysis. - 9) Checks the direct subclasses of class "C". It verifies if all direct subclasses are "D" using two different methods: comparing class names and fully qualified names. - 10) Then prints a message based on whether all direct subtypes of "C" are correctly identified as "D". - 11) Retrieves and checks the superclasses of class "C". It then verifies if these superclasses include class "A" and java.lang.Object, printing a message based on the result. - - e) MutatingSootClassExample - - 1) package sootup.examples; - defines the package name for the Java class. - 2) import statement - defines various classes and interfaces from different packages that the program uses. - 3) public class MutatingSootClass - declares a public class named "MutatingSootClass". - 4) Then we have created a main method in which is the entry point for the code. - 5) First we have created an 'AnalysisInputLocation' which points to a directory which contains the class files to be analysed. - 6) Then we have created a JavaView which allos us to retrievet the classes. - 7) And also created a ClassType to get the class 'HelloWorld' and a method within that class ie main for analysis using MethodSignature. - 8) THen we are checking and retrieving the class and method. - 9) Then we retrives the existing body of the method and prints it. Then we create a new local variable to add it copy to the method body. - 10) Then we are overriding the method body and class. ie this lines creates new sources that overrides teh original method body and class. It replaces the old method in the class with the new method having the modified body. - 11) Prints the modified method body and checks if the new local variable (newLocal) exists in the modified method. Depending on the result, it prints a corresponding message. + Download [BasicSetup.java](https://github.com/secure-software-engineering/soot-reloaded/blob/develop/sootup.examples/src/test/java/sootup/examples/basicSetup/BasicSetup.java) diff --git a/docs/SootUpLogo.svg b/docs/img/SootUpLogo.svg similarity index 100% rename from docs/SootUpLogo.svg rename to docs/img/SootUpLogo.svg diff --git a/docs/icon.svg b/docs/img/icon.svg similarity index 100% rename from docs/icon.svg rename to docs/img/icon.svg diff --git a/docs/index.md b/docs/index.md index cd61f29e954..69638181c58 100644 --- a/docs/index.md +++ b/docs/index.md @@ -32,11 +32,13 @@ The goal is a lighter library that can easily be understood and maintained to be The development of SootUp is financed by generous support from the German Research Foundation (DFG) and the Heinz Nixdorf Institute (HNI). - +
+
[Become a sponsor!](https://github.com/sponsors/soot-oss) + diff --git a/docs/installation.md b/docs/installation.md index 35f840dec4a..239f709f565 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -1,105 +1,83 @@ # Installation -## Using the latest version on the develop branch -visit [SootUp on Jitpack.io](https://jitpack.io/#soot-oss/SootUp/develop-SNAPSHOT) for configuration options of your build tool. -## Using the release -SootUp is available in maven central, you can include it in your project as follows. - -Below we only show how you can add the SootUp modules to your project. It is not necessary to add all the modules as dependency. -Depending on your needs you can import only the modules you need. -Take a look at the [Modules](whatsnew.md#modular-architecture) to learn more about which modules you might need. - -### Maven - - Add the following dependency in the ```pom.xml``` file of your project to include all SootUp modules into your project. - -``` - - - jitpack.io - https://jitpack.io - - - - - - org.soot-oss - sootup.core - {{ git_latest_release }} - - - org.soot-oss - sootup.java.core - {{ git_latest_release }} - - - org.soot-oss - sootup.java.sourcecode - {{ git_latest_release }} - - - org.soot-oss - sootup.java.bytecode - {{ git_latest_release }} - - - org.soot-oss - sootup.jimple.parser - {{ git_latest_release }} - - - org.soot-oss - sootup.callgraph - {{ git_latest_release }} - - - org.soot-oss - sootup.analysis - {{ git_latest_release }} - - -``` -### Gradle - -Add the following dependency in the ```build.gradle``` file of your project to include all SootUp modules into your project. - -``` -repositories { - mavenCentral() - google() - maven { - url "https://jitpack.io" +## Use the latest [develop branch](https://github.com/soot-oss/SootUp/tree/develop) +For configuration options of your build tool please visit [SootUp on Jitpack.io](https://jitpack.io/#soot-oss/SootUp/develop-SNAPSHOT) + + +## Use Releases on Maven Central +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```. + +=== "Maven" + + ```mvn + + + org.soot-oss + sootup.core + {{ git_latest_release }} + + + org.soot-oss + sootup.java.core + {{ git_latest_release }} + + + org.soot-oss + sootup.java.sourcecode + {{ git_latest_release }} + + + org.soot-oss + sootup.java.bytecode + {{ git_latest_release }} + + + org.soot-oss + sootup.jimple.parser + {{ git_latest_release }} + + + org.soot-oss + sootup.callgraph + {{ git_latest_release }} + + + org.soot-oss + sootup.analysis + {{ git_latest_release }} + + + org.soot-oss + sootup.qilin + {{ git_latest_release }} + + + ``` + +=== "Gradle" + + ```groovy + repositories { + mavenCentral() + google() } -} - -compile "org.soot-oss:sootup.core:{{ git_latest_release }}" -compile "org.soot-oss:sootup.java.core:{{ git_latest_release }}" -compile "org.soot-oss:sootup.java.sourcecode:{{ git_latest_release }}" -compile "org.soot-oss:sootup.java.bytecode:{{ git_latest_release }}" -compile "org.soot-oss:sootup.jimple.parser:{{ git_latest_release }}" -compile "org.soot-oss:sootup.callgraph:{{ git_latest_release }}" -compile "org.soot-oss:sootup.analysis:{{ git_latest_release }}" -``` - -## Building from Source -Build from source if you'd like to get the most recent changes. -You can download the project as a zip file, or clone it using your favorite git client app or the command line: - -``` + + compile "org.soot-oss:sootup.core:{{ git_latest_release }}" + compile "org.soot-oss:sootup.java.core:{{ git_latest_release }}" + compile "org.soot-oss:sootup.java.sourcecode:{{ git_latest_release }}" + compile "org.soot-oss:sootup.java.bytecode:{{ git_latest_release }}" + compile "org.soot-oss:sootup.jimple.parser:{{ git_latest_release }}" + compile "org.soot-oss:sootup.callgraph:{{ git_latest_release }}" + compile "org.soot-oss:sootup.analysis:{{ git_latest_release }}" + compile "org.soot-oss:sootup.qilin:{{ git_latest_release }}" + ``` + +## Build from Source +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. +```sh git clone https://github.com/secure-software-engineering/SootUp.git -``` - -SootUp is a maven project. You can import it into your favorite IDE as a maven project. Run maven clean and install tasks using your IDE's maven plugin to set up the project. - -Alternatively, you can execute the following command in the project directory: - -``` mvn install -``` - -Or if you want to skip tests while building: - -``` -mvn -Dskiptests install -``` - +``` \ No newline at end of file diff --git a/docs/jimple-body.md b/docs/jimple-body.md new file mode 100644 index 00000000000..39ed9a06dd3 --- /dev/null +++ b/docs/jimple-body.md @@ -0,0 +1,142 @@ +# Jimple Body +A SootMethod `Body` consists of the `Modifiers` and its `StmtGraph` - SootUps Control Flow Graph Structure. +The StmtGraph models the flow of [Stmts](jimple-stmts.md). + +### Control Flow Graph +- unexceptional flow -> like FallsThroughStmts and BranchingStmts for if,goto etc. +- exceptional flow -> for exceptions, handled by traps. + +### Stmts +Learn more about the types of [Stmts](jimple-stmts.md). + +### Traps +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. + +=== "Jimple" + + ```jimple hl_lines="39" + public class target.exercise1.DemoClass extends java.lang.Object + { + public void () + { + target.exercise1.DemoClass this; + this := @this: target.exercise1.DemoClass; + specialinvoke this.()>(); + return; + } + + public void divideExample(int, int) + { + int x, y, $stack4; + java.io.PrintStream $stack5, $stack7; + java.lang.Exception $stack6; + target.exercise1.DemoClass this; + + this := @this: target.exercise1.DemoClass; + x := @parameter0: int; + y := @parameter1: int; + + label1: + $stack5 = ; + $stack4 = x / y; + virtualinvoke $stack5.($stack4); + + label2: + goto label4; + + label3: + $stack6 := @caughtexception; + $stack7 = ; + virtualinvoke $stack7.("Exception caught"); + + label4: + return; + + catch java.lang.Exception from label1 to label2 with label3; + } + } + /* + By calling getTraps() method, we can get the Traip chain. + For the above jimple code, we have the below trap: + Trap : + begin : $stack5 = + end : goto [?= return] + handler: $stack6 := @caughtexception + */ + ``` + +=== "Java" + + ```java + package target.exercise1; + + public class DemoClass { + public void divideExample(int x, int y){ + try { + System.out.println(x / y); + }catch (Exception e){ + System.out.println("Exception caught"); + } + } + } + ``` + +=== "Bytecode" + + ``` + // class version 52.0 (52) + // access flags 0x21 + public class target/exercise1/DemoClass { + + // compiled from: DemoClass.java + + // access flags 0x1 + public ()V + L0 + LINENUMBER 3 L0 + ALOAD 0 + INVOKESPECIAL java/lang/Object. ()V + RETURN + L1 + LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0 + MAXSTACK = 1 + MAXLOCALS = 1 + + // access flags 0x1 + public divideExample(II)V + TRYCATCHBLOCK L0 L1 L2 java/lang/Exception + L0 + LINENUMBER 6 L0 + GETSTATIC java/lang/System.out : Ljava/io/PrintStream; + ILOAD 1 + ILOAD 2 + IDIV + INVOKEVIRTUAL java/io/PrintStream.println (I)V + L1 + LINENUMBER 9 L1 + GOTO L3 + L2 + LINENUMBER 7 L2 + FRAME SAME1 java/lang/Exception + ASTORE 3 + L4 + LINENUMBER 8 L4 + GETSTATIC java/lang/System.out : Ljava/io/PrintStream; + LDC "Exception caught" + INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V + L3 + LINENUMBER 10 L3 + FRAME SAME + RETURN + L5 + LOCALVARIABLE e Ljava/lang/Exception; L4 L3 3 + LOCALVARIABLE this Land Ttarget/exercise1/DemoClass; L0 L5 0 + LOCALVARIABLE x I L0 L5 1 + LOCALVARIABLE y I L0 L5 2 + MAXSTACK = 3 + MAXLOCALS = 4 + } + ``` diff --git a/docs/jimple-stmts.md b/docs/jimple-stmts.md new file mode 100644 index 00000000000..06bc1c8a233 --- /dev/null +++ b/docs/jimple-stmts.md @@ -0,0 +1,1218 @@ +# Jimple Stmt ("Statement") +[Stmts]{formerly known as Units} 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`). + +- A `FallsThroughStmt` has always one successor - it basically represents `program counter++`. +- A `BranchingStmt` can have one, two or even n successors. +- All others (neither FallsThrough nor BranchingStmt) have no successors and therefore end the execution of the current method. + +## Branching Stmts +A BranchingStmt's job is to model the jumps or conditional branching flow between Stmts. + +### JGotoStmt +represents unconditional jumps to another Stmt. + +=== "Jimple" + + ```jimple hl_lines="18 22" + public class target.exercise1.DemoClass extends java.lang.Object + { + public void () + { + target.exercise1.DemoClass this; + this := @this: target.exercise1.DemoClass; + specialinvoke this.()>(); + return; + } + public static void sampleMethod() + { + int i; + i = 0; + + label1: + if i >= 5 goto label3; + if i != 3 goto label2; + goto label3; + + label2: + i = i + 1; + goto label1; + + label3: + return; + } + } + /* + Here for statements "goto label3;" and "goto label1;", + we have two instances of JGotoStmt : + "goto[?=return]" and "goto[?=(branch)]". + */ + ``` + +=== "Java" + + ```java + package target.exercise1; + + public class DemoClass { + public static void sampleMethod(){ + label1: + for (int i = 0; i < 5; i++){ + if(i == 3){ + break label1; + } + } + } + } + ``` + +=== "Bytecode" + + ``` + // class version 52.0 (52) + // access flags 0x21 + public class target/exercise1/DemoClass { + + // compiled from: DemoClass.java + + // access flags 0x1 + public ()V + L0 + LINENUMBER 3 L0 + ALOAD 0 + INVOKESPECIAL java/lang/Object. ()V + RETURN + L1 + LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0 + MAXSTACK = 1 + MAXLOCALS = 1 + + // access flags 0x9 + public static sampleMethod()V + L0 + LINENUMBER 6 L0 + ICONST_0 + ISTORE 0 + L1 + FRAME APPEND [I] + ILOAD 0 + ICONST_5 + IF_ICMPGE L2 + L3 + LINENUMBER 7 L3 + ILOAD 0 + ICONST_3 + IF_ICMPNE L4 + L5 + LINENUMBER 8 L5 + GOTO L2 + L4 + LINENUMBER 6 L4 + FRAME SAME + IINC 0 1 + GOTO L1 + L2 + LINENUMBER 11 L2 + FRAME CHOP 1 + RETURN + LOCALVARIABLE i I L1 L2 0 + MAXSTACK = 2 + MAXLOCALS = 1 + } + ``` + +### JIfStmt +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. + +=== "Jimple" + + ```jimple hl_lines="19" + public class target.exercise1.DemoClass extends java.lang.Object + { + public void () + { + target.exercise1.DemoClass this; + this := @this: target.exercise1.DemoClass; + specialinvoke this.()>(); + return; + } + + public static void sampleMethod(int) + { + int x, $stack1; + java.io.PrintStream $stack2, $stack3; + + x := @parameter0: int; + + $stack1 = x % 2; + if $stack1 != 0 goto label1; + + $stack3 = ; + virtualinvoke $stack3.("Even"); + goto label2; + + label1: + $stack2 = ; + virtualinvoke $stack2.("Odd"); + + label2: + return; + } + } + /* + For statement "if $stack1 != 0 goto label1;", + we have an instance of JIfStmt : + "if $stack1 != 0 goto $stack2 + = ". + */ + ``` + +=== "Java" + + ```java + package target.exercise1; + + public class DemoClass { + public static void sampleMethod(int x){ + if(x % 2 == 0){ + System.out.println("Even"); + }else{ + System.out.println("Odd"); + } + } + } + ``` + +=== "Bytecode" + + ``` + // class version 52.0 (52) + // access flags 0x21 + public class target/exercise1/DemoClass { + + // compiled from: DemoClass.java + + // access flags 0x1 + public ()V + L0 + LINENUMBER 3 L0 + ALOAD 0 + INVOKESPECIAL java/lang/Object. ()V + RETURN + L1 + LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0 + MAXSTACK = 1 + MAXLOCALS = 1 + + // access flags 0x9 + public static sampleMethod(I)V + L0 + LINENUMBER 5 L0 + ILOAD 0 + ICONST_2 + IREM + IFNE L1 + L2 + LINENUMBER 6 L2 + GETSTATIC java/lang/System.out : Ljava/io/PrintStream; + LDC "Even" + INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V + GOTO L3 + L1 + LINENUMBER 8 L1 + FRAME SAME + GETSTATIC java/lang/System.out : Ljava/io/PrintStream; + LDC "Odd" + INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V + L3 + LINENUMBER 10 L3 + FRAME SAME + RETURN + L4 + LOCALVARIABLE x I L0 L4 0 + MAXSTACK = 2 + MAXLOCALS = 1 + } + ``` + +### JSwitchStmt +for conditional flow that behaves like a switch-case. It has #numberOfCaseLabels+1 (for default) successor Stmt's. + +=== "Jimple" + + ```jimple hl_lines="20-25" + public class target.exercise1.DemoClass extends java.lang.Object + { + public void () + { + target.exercise1.DemoClass this; + this := @this: target.exercise1.DemoClass; + specialinvoke this.()>(); + return; + } + + public void switchExample(int) + { + int x; + java.io.PrintStream $stack2, $stack3, $stack4; + target.exercise1.DemoClass this; + + this := @this: target.exercise1.DemoClass; + x := @parameter0: int; + + lookupswitch(x) + { + case 1: goto label1; + case 2: goto label2; + default: goto label3; + }; + + label1: + $stack3 = ; + virtualinvoke $stack3.("Input 1"); + goto label4; + + label2: + $stack2 = ; + virtualinvoke $stack2.("Input 2"); + goto label4; + + label3: + $stack4 = ; + virtualinvoke $stack4.("Input more than 2"); + + label4: + return; + } + } + /* + Here for below statement: + lookupswitch(x) + { + case 1: goto label1; + case 2: goto label2; + default: goto label3; + }; + + we have an instance of JLookupSwitchStmt : + lookupswitch(x) + { + case 1: goto $stack3 + = ; + case 2: goto $stack2 + = ; + default: goto $stack4 + = ; + } + */ + ``` + +=== "Java" + + ```java + package target.exercise1; + + public class DemoClass { + public void switchExample(int x){ + switch (x){ + case 1: + System.out.println("Input 1"); + break; + + case 2: + System.out.println("Input 2"); + break; + + default: + System.out.println("Input more than 2"); + break; + + } + } + } + ``` + +=== "Bytecode" + + ``` + // class version 52.0 (52) + // access flags 0x21 + public class target/exercise1/DemoClass { + + // compiled from: DemoClass.java + + // access flags 0x1 + public ()V + L0 + LINENUMBER 3 L0 + ALOAD 0 + INVOKESPECIAL java/lang/Object. ()V + RETURN + L1 + LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0 + MAXSTACK = 1 + MAXLOCALS = 1 + + // access flags 0x1 + public switchExample(I)V + L0 + LINENUMBER 5 L0 + ILOAD 1 + LOOKUPSWITCH + 1: L1 + 2: L2 + default: L3 + L1 + LINENUMBER 7 L1 + FRAME SAME + GETSTATIC java/lang/System.out : Ljava/io/PrintStream; + LDC "Input 1" + INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V + L4 + LINENUMBER 8 L4 + GOTO L5 + L2 + LINENUMBER 11 L2 + FRAME SAME + GETSTATIC java/lang/System.out : Ljava/io/PrintStream; + LDC "Input 2" + INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V + L6 + LINENUMBER 12 L6 + GOTO L5 + L3 + LINENUMBER 15 L3 + FRAME SAME + GETSTATIC java/lang/System.out : Ljava/io/PrintStream; + LDC "Input more than 2" + INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V + L5 + LINENUMBER 19 L5 + FRAME SAME + RETURN + L7 + LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L7 0 + LOCALVARIABLE x I L0 L7 1 + MAXSTACK = 2 + MAXLOCALS = 2 + } + ``` + +## FallsThrough Stmts +The execution of a FallsthroughStmt goes on with the following Stmt (if no exception was thrown). + +### JInvokeStmt +transfers the control flow to another method until the called method returns. + +=== "Jimple" + + ```jimple hl_lines="7 20 22 24 26" + public class target.exercise1.DemoClass extends java.lang.Object + { + public void () + { + target.exercise1.DemoClass this; + this := @this: target.exercise1.DemoClass; + specialinvoke this.()>(); + return; + } + + public void print(int) + { + target.exercise1.DemoClass this; + int x, a; + java.io.PrintStream $stack4, $stack6; + + this := @this: target.exercise1.DemoClass; + x := @parameter0: int; + + a = virtualinvoke this.(x); + $stack4 = ; + virtualinvoke $stack4.(a); + + a = virtualinvoke this.(a); + $stack6 = ; + virtualinvoke $stack6.(a); + + return; + } + + public int increment(int) + { + int x, $stack2; + target.exercise1.DemoClass this; + + this := @this: target.exercise1.DemoClass; + x := @parameter0: int; + + $stack2 = x + 1; + return $stack2; + } + } + /* + "specialinvoke this.()>()", + "virtualinvoke this.(x)", + "virtualinvoke this.(a)" + are JInvokeStmts. + */ + ``` + +=== "Java" + + ```java + package target.exercise1; + + public class DemoClass { + public void print(int x){ + int a = increment(x); + System.out.println(a); + a = increment(a); + System.out.println(a); + } + public int increment(int x){ + return x + 1; + } + } + ``` + +=== "Bytecode" + + ``` + // class version 52.0 (52) + // access flags 0x21 + public class target/exercise1/DemoClass { + + // compiled from: DemoClass.java + + // access flags 0x1 + public ()V + L0 + LINENUMBER 3 L0 + ALOAD 0 + INVOKESPECIAL java/lang/Object. ()V + RETURN + L1 + LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0 + MAXSTACK = 1 + MAXLOCALS = 1 + + // access flags 0x1 + public print(I)V + L0 + LINENUMBER 5 L0 + ALOAD 0 + ILOAD 1 + INVOKEVIRTUAL target/exercise1/DemoClass.increment (I)I + ISTORE 2 + L1 + LINENUMBER 6 L1 + GETSTATIC java/lang/System.out : Ljava/io/PrintStream; + ILOAD 2 + INVOKEVIRTUAL java/io/PrintStream.println (I)V + L2 + LINENUMBER 7 L2 + ALOAD 0 + ILOAD 2 + INVOKEVIRTUAL target/exercise1/DemoClass.increment (I)I + ISTORE 2 + L3 + LINENUMBER 8 L3 + GETSTATIC java/lang/System.out : Ljava/io/PrintStream; + ILOAD 2 + INVOKEVIRTUAL java/io/PrintStream.println (I)V + L4 + LINENUMBER 9 L4 + RETURN + L5 + LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L5 0 + LOCALVARIABLE x I L0 L5 1 + LOCALVARIABLE a I L1 L5 2 + MAXSTACK = 2 + MAXLOCALS = 3 + + // access flags 0x1 + public increment(I)I + L0 + LINENUMBER 11 L0 + ILOAD 1 + ICONST_1 + IADD + IRETURN + L1 + LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0 + LOCALVARIABLE x I L0 L1 1 + MAXSTACK = 2 + MAXLOCALS = 2 + } + ``` + + +### JAssignStmt +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. + +=== "Jimple" + + ```jimple hl_lines="8 19-22" + public class target.exercise1.DemoClass extends java.lang.Object + { + public void () + { + target.exercise1.DemoClass this; + this := @this: target.exercise1.DemoClass; + specialinvoke this.()>(); + this. = 0; + return; + } + + public int updateCounter() + { + target.exercise1.DemoClass this; + int $stack1, $stack2, $stack3; + + this := @this: target.exercise1.DemoClass; + + $stack1 = this.; + $stack2 = $stack1 + 1; + this. = $stack2; + $stack3 = this.; + + return $stack3; + } + } + /* + "this. = 0", + "$stack1 = this.", + "$stack2 = $stack1 + 1" + "this. = $stack2" + "$stack3 = this." + are JAssignStmts. + */ + ``` + +=== "Java" + + ```java + package target.exercise1; + + public class DemoClass { + private int counter = 0; + public int updateCounter(){ + counter = counter + 1; + return counter; + } + } + ``` + +=== "Bytecode" + + ``` + // class version 52.0 (52) + // access flags 0x21 + public class target/exercise1/DemoClass { + + // compiled from: DemoClass.java + + // access flags 0x2 + private I counter + + // access flags 0x1 + public ()V + L0 + LINENUMBER 3 L0 + ALOAD 0 + INVOKESPECIAL java/lang/Object. ()V + L1 + LINENUMBER 4 L1 + ALOAD 0 + ICONST_0 + PUTFIELD target/exercise1/DemoClass.counter : I + RETURN + L2 + LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L2 0 + MAXSTACK = 2 + MAXLOCALS = 1 + + // access flags 0x1 + public updateCounter()I + L0 + LINENUMBER 6 L0 + ALOAD 0 + ALOAD 0 + GETFIELD target/exercise1/DemoClass.counter : I + ICONST_1 + IADD + PUTFIELD target/exercise1/DemoClass.counter : I + L1 + LINENUMBER 7 L1 + ALOAD 0 + GETFIELD target/exercise1/DemoClass.counter : I + IRETURN + L2 + LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L2 0 + MAXSTACK = 3 + MAXLOCALS = 1 + } + ``` + + +### JIdentityStmt +is similar to the `JAssignStmt` and but handles assignments of `IdentityRef`s to make implicit assignments explicit into the `StmtGraph`. + +- Assigns parameters to a `Local` via `JParameterRef` like `@parameter0: int` refering to the first argument of the method (which is of Type int in this case). +- Assigns exceptions to a `Local` via `JCaughtExceptionRef` like `@caughtexception: java.lang.NullpointerException` +- Assigns the `this` Variable to a `Local` via a `JThisRef` + +=== "Jimple" + + ```jimple hl_lines="16 17" + public class target.exercise1.DemoClass extends java.lang.Object + { + public void () + { + target.exercise1.DemoClass this; + this := @this: target.exercise1.DemoClass; + specialinvoke this.()>(); + return; + } + + public void DemoClass(int) + { + target.exercise1.DemoClass this; + int counter; + + this := @this: target.exercise1.DemoClass; + counter := @parameter0: int; + this. = counter; + return; + } + } + /* + "this := @this: target.exercise1.DemoClass" and + "counter := @parameter0: int" are JIdentityStmts + */ + ``` + +=== "Java" + + ```java + package target.exercise1; + + public class DemoClass { + private int counter; + public void DemoClass(int counter){ + this.counter = counter; + } + } + ``` + +=== "Bytecode" + + ``` + // class version 52.0 (52) + // access flags 0x21 + public class target/exercise1/DemoClass { + + // compiled from: DemoClass.java + + // access flags 0x2 + private I counter + + // access flags 0x1 + public ()V + L0 + LINENUMBER 3 L0 + ALOAD 0 + INVOKESPECIAL java/lang/Object. ()V + RETURN + L1 + LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0 + MAXSTACK = 1 + MAXLOCALS = 1 + + // access flags 0x1 + public DemoClass(I)V + L0 + LINENUMBER 6 L0 + ALOAD 0 + ILOAD 1 + PUTFIELD target/exercise1/DemoClass.counter : I + L1 + LINENUMBER 7 L1 + RETURN + L2 + LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L2 0 + LOCALVARIABLE counter I L0 L2 1 + MAXSTACK = 2 + MAXLOCALS = 2 + } + ``` + + +###JEnterMonitorStmt & JExitMonitorStmt +marks synchronized blocks of code from JEnterMonitorStmt to JExitMonitorStmt. + +=== "Jimple" + + ```jimple hl_lines="20 27 35" + public class target.exercise1.DemoClass extends java.lang.Object + { + public void () + { + target.exercise1.DemoClass this; + this := @this: target.exercise1.DemoClass; + specialinvoke this.()>(); + this. = 0; + return; + } + + public int updateCounter() + { + target.exercise1.DemoClass this; + int $stack4, $stack5, $stack7; + java.lang.Throwable $stack8; + + this := @this: target.exercise1.DemoClass; + + entermonitor this; + + label1: + $stack4 = this.; + $stack5 = $stack4 + 1; + this. = $stack5; + + exitmonitor this; + + label2: + goto label5; + + label3: + $stack8 := @caughtexception; + + exitmonitor this; + + label4: + throw $stack8; + + label5: + $stack7 = this.; + return $stack7; + + catch java.lang.Throwable from label1 to label2 with label3; + catch java.lang.Throwable from label3 to label4 with label3; + } + } + /* + "entermonitor this" is JEnterMonitorStmt. + "exitmonitor this" is JExitMonitorStmt. + */ + ``` + +=== "Java" + + ```java + package target.exercise1; + + public class DemoClass { + private int counter = 0; + public int updateCounter(){ + synchronized (this) { + counter = counter + 1; + } + return counter; + } + } + ``` + +=== "Bytecode" + + ``` + // class version 52.0 (52) + // access flags 0x21 + public class target/exercise1/DemoClass { + + // compiled from: DemoClass.java + + // access flags 0x2 + private I counter + + // access flags 0x1 + public ()V + L0 + LINENUMBER 3 L0 + ALOAD 0 + INVOKESPECIAL java/lang/Object. ()V + L1 + LINENUMBER 4 L1 + ALOAD 0 + ICONST_0 + PUTFIELD target/exercise1/DemoClass.counter : I + RETURN + L2 + LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L2 0 + MAXSTACK = 2 + MAXLOCALS = 1 + + // access flags 0x1 + public updateCounter()I + TRYCATCHBLOCK L0 L1 L2 null + TRYCATCHBLOCK L2 L3 L2 null + L4 + LINENUMBER 6 L4 + ALOAD 0 + DUP + ASTORE 1 + MONITORENTER + L0 + LINENUMBER 7 L0 + ALOAD 0 + ALOAD 0 + GETFIELD target/exercise1/DemoClass.counter : I + ICONST_1 + IADD + PUTFIELD target/exercise1/DemoClass.counter : I + L5 + LINENUMBER 8 L5 + ALOAD 1 + MONITOREXIT + L1 + GOTO L6 + L2 + FRAME FULL [target/exercise1/DemoClass java/lang/Object] + [java/lang/Throwable] + ASTORE 2 + ALOAD 1 + MONITOREXIT + L3 + ALOAD 2 + ATHROW + L6 + LINENUMBER 9 L6 + FRAME CHOP 1 + ALOAD 0 + GETFIELD target/exercise1/DemoClass.counter : I + IRETURN + L7 + LOCALVARIABLE this Ltarget/exercise1/DemoClass; L4 L7 0 + MAXSTACK = 3 + MAXLOCALS = 3 + } + ``` + +### JRetStmt +// TODO: [java 1.6 spec](https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-6.html#jvms-6.5.ret) + +### JBreakpointStmt +models a Breakpoint set by a Debugger. Therefore, not really relevant for static analyses but useful for code generation. + +## Other Stmts + +### JReturnStmt & JReturnVoidStmt +They end the execution/flow inside the current method and return (a value) to its caller. + +=== "Jimple" + + ```jimple hl_lines="20 32" + public class target.exercise1.DemoClass extends java.lang.Object + { + public void () + { + target.exercise1.DemoClass this; + this := @this: target.exercise1.DemoClass; + specialinvoke this.()>(); + return; + } + + public int increment(int) + { + int x, $stack2; + target.exercise1.DemoClass this; + + this := @this: target.exercise1.DemoClass; + x := @parameter0: int; + + $stack2 = x + 1; + return $stack2; + } + + public void print() + { + java.io.PrintStream $stack1; + target.exercise1.DemoClass this; + + this := @this: target.exercise1.DemoClass; + $stack1 = ; + virtualinvoke $stack1.("Inside method print"); + return; + } + } + /* + "return $stack2" is JReturnStmt. + "return" is JReturnVoidStmt. + */ + ``` + +=== "Java" + + ```java + package target.exercise1; + + public class DemoClass { + public int increment(int x){ + return x + 1; + } + public void print(){ + System.out.println("Inside method print"); + } + } + ``` + +=== "Bytecode" + + ``` + // class version 52.0 (52) + // access flags 0x21 + public class target/exercise1/DemoClass { + + // compiled from: DemoClass.java + + // access flags 0x1 + public ()V + L0 + LINENUMBER 3 L0 + ALOAD 0 + INVOKESPECIAL java/lang/Object. ()V + RETURN + L1 + LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0 + MAXSTACK = 1 + MAXLOCALS = 1 + + // access flags 0x1 + public increment(I)I + L0 + LINENUMBER 5 L0 + ILOAD 1 + ICONST_1 + IADD + IRETURN + L1 + LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0 + LOCALVARIABLE x I L0 L1 1 + MAXSTACK = 2 + MAXLOCALS = 2 + + // access flags 0x1 + public print()V + L0 + LINENUMBER 8 L0 + GETSTATIC java/lang/System.out : Ljava/io/PrintStream; + LDC "Inside method print" + INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V + L1 + LINENUMBER 9 L1 + RETURN + L2 + LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L2 0 + MAXSTACK = 2 + MAXLOCALS = 1 + } + ``` + + +### JThrowStmt +Ends the execution inside the current Method if the thrown exception is not caught by a Trap, which redirects the execution to an exceptionhandler. + + +=== "Jimple" + + ```jimple hl_lines="29" + public class target.exercise1.DemoClass extends java.lang.Object + { + public void () + { + target.exercise1.DemoClass this; + this := @this: target.exercise1.DemoClass; + specialinvoke this.()>(); + return; + } + + public void divideExample(int, int) + { + int y, x, $stack6; + java.lang.StringBuilder $stack3, $stack5, $stack7; + java.io.PrintStream $stack4; + java.lang.String $stack8; + java.lang.RuntimeException $stack9; + target.exercise1.DemoClass this; + + this := @this: target.exercise1.DemoClass; + x := @parameter0: int; + y := @parameter1: int; + + if y != 0 goto label1; + + $stack9 = new java.lang.RuntimeException; + specialinvoke $stack9.(java.lang.String)>("Divide by zero error"); + throw $stack9; + + label1: + $stack4 = ; + $stack3 = new java.lang.StringBuilder; + specialinvoke $stack3.()>(); + + $stack5 = virtualinvoke $stack3.("Divide result : "); + $stack6 = x / y; + $stack7 = virtualinvoke $stack5.($stack6); + $stack8 = virtualinvoke $stack7.(); + + virtualinvoke $stack4.($stack8); + return; + } + } + /* + "throw $stack9" is JThrowStmt. + */ + ``` + +=== "Java" + + ```java + package target.exercise1; + + public class DemoClass { + public void divideExample(int x, int y){ + if(y == 0){ + throw new RuntimeException("Divide by zero error"); + } + System.out.println("Divide result : " + x / y); + } + } + ``` + +=== "Bytecode" + + ``` + // class version 52.0 (52) + // access flags 0x21 + public class target/exercise1/DemoClass { + + // compiled from: DemoClass.java + + // access flags 0x1 + public ()V + L0 + LINENUMBER 3 L0 + ALOAD 0 + INVOKESPECIAL java/lang/Object. ()V + RETURN + L1 + LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0 + MAXSTACK = 1 + MAXLOCALS = 1 + + // access flags 0x1 + public divideExample(II)V + L0 + LINENUMBER 5 L0 + ILOAD 2 + IFNE L1 + L2 + LINENUMBER 6 L2 + NEW java/lang/RuntimeException + DUP + LDC "Divide by zero error" + INVOKESPECIAL java/lang/RuntimeException. + (Ljava/lang/String;)V + ATHROW + L1 + LINENUMBER 8 L1 + FRAME SAME + GETSTATIC java/lang/System.out : Ljava/io/PrintStream; + NEW java/lang/StringBuilder + DUP + INVOKESPECIAL java/lang/StringBuilder. ()V + LDC "Divide result : " + INVOKEVIRTUAL java/lang/StringBuilder.append + (Ljava/lang/String;)Ljava/lang/StringBuilder; + ILOAD 1 + ILOAD 2 + IDIV + INVOKEVIRTUAL java/lang/StringBuilder.append + (I)Ljava/lang/StringBuilder; + INVOKEVIRTUAL java/lang/StringBuilder.toString + ()Ljava/lang/String; + INVOKEVIRTUAL java/io/PrintStream.println + (Ljava/lang/String;)V + L3 + LINENUMBER 9 L3 + RETURN + L4 + LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L4 0 + LOCALVARIABLE x I L0 L4 1 + LOCALVARIABLE y I L0 L4 2 + MAXSTACK = 4 + MAXLOCALS = 3 + } + ``` + +## Good to know +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" + ```java + + List stmts = ... ; + for( Stmt stms : stmts ){ + if(stmt instanceof JAssignStmt){ + // found a JAssignStmt + Value rhsOp = ((JAssignStmt) stmt).getRightOp(); + ... + }else if(stmt instanceof JInvokeStmt){ + // found a JInvokeStmt + JInvokeStmt ivkStmt = ((JInvokeStmt) stmt); + MethodSignature rhsOp = ivkStmt.getInvokeExpr().getMethodSignature(); + ... + }else ... + } + + ``` + +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" + ```java + + List stmts = ...; + AbstractStmtVisitor visitor = new AbstractStmtVisitor() { + private int ifStmtsCounter = 0; + @Override + public void caseIfStmt(@Nonnull JIfStmt stmt) { + ifStmtsCounter++; + setResult(ifStmtCounter); + } + }; + + for( Stmt stms : stmts ){ + stmt.accept(visitor); + } + + int amountOfIfStmts = visitor.getResult(); + ``` + + Sidenote: Of course its possible can create a subclass instead of an anonymous class. \ No newline at end of file diff --git a/docs/jimple-types.md b/docs/jimple-types.md new file mode 100644 index 00000000000..1cfcff8f327 --- /dev/null +++ b/docs/jimple-types.md @@ -0,0 +1,541 @@ +# Jimple Types +represents primary types i.e. non-reference types and non-void + +### PrimaryType + +- `BooleanType` +- `ByteType` +- `CharType` +- `ShortType` +- `IntType` +- `LongType` +- `DoubleType` +- `FloatType` + +=== "Jimple" + + ```jimple hl_lines="14-21" + public class target.exercise1.DemoClass extends java.lang.Object + { + public void () + { + target.exercise1.DemoClass this; + this := @this: target.exercise1.DemoClass; + specialinvoke this.()>(); + return; + } + + + public void display() + { + java.io.PrintStream $stack11, $stack13, $stack15, + $stack17, $stack19, $stack21, $stack23, $stack25; + int $stack12, $stack14, $stack16, $stack18; + long $stack20; + double $stack22; + float $stack24; + target.exercise1.DemoClass this; + boolean $stack26; + + this := @this: target.exercise1.DemoClass; + + $stack11 = ; + + goto label1; + + label1: + $stack26 = 0; + virtualinvoke $stack11.($stack26); + + $stack13 = ; + $stack12 = 127 - 1; + virtualinvoke $stack13.($stack12); + + $stack15 = ; + $stack14 = 97 + 1; + virtualinvoke $stack15.($stack14); + + $stack17 = ; + $stack16 = 1123 + 1; + virtualinvoke $stack17.($stack16); + + $stack19 = ; + $stack18 = 123456 + 1; + virtualinvoke $stack19.($stack18); + + $stack21 = ; + $stack20 = 10L + 1L; + virtualinvoke $stack21.($stack20); + + $stack23 = ; + $stack22 = 10.1 + 1.0; + virtualinvoke $stack23.($stack22); + + $stack25 = ; + $stack24 = 10.1F + 1.0F; + virtualinvoke $stack25.($stack24); + + return; + } + } + /* + The JimpleLocal $stack12, $stack14, $stack16, $stack18 are of IntType. + Similarly, $stack20 is of LongType, $stack22 is of DoubleType and so on. + */ + ``` + +=== "Java" + + ```java + package target.exercise1; + + public class DemoClass { + public void display(){ + boolean varBoolean = true; + byte varByte = 127; + char varChar = 'a'; + short varShort = 1123; + int varInt = 123456; + long varLong = 10L; + double varDouble = 10.10; + float varFloat = 10.10f; + + System.out.println(!varBoolean); + System.out.println(varByte-1); + System.out.println(varChar+1); + System.out.println(varShort+1); + System.out.println(varInt+1); + System.out.println(varLong+1); + System.out.println(varDouble+1); + System.out.println(varFloat+1); + + } + } + ``` + +=== "Bytecode" + + ``` + // class version 52.0 (52) + // access flags 0x21 + public class target/exercise1/DemoClass { + + // compiled from: DemoClass.java + + // access flags 0x1 + public ()V + L0 + LINENUMBER 3 L0 + ALOAD 0 + INVOKESPECIAL java/lang/Object. ()V + RETURN + L1 + LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0 + MAXSTACK = 1 + MAXLOCALS = 1 + + // access flags 0x1 + public display()V + L0 + LINENUMBER 5 L0 + ICONST_1 + ISTORE 1 + L1 + LINENUMBER 6 L1 + BIPUSH 127 + ISTORE 2 + L2 + LINENUMBER 7 L2 + BIPUSH 97 + ISTORE 3 + L3 + LINENUMBER 8 L3 + SIPUSH 1123 + ISTORE 4 + L4 + LINENUMBER 9 L4 + LDC 123456 + ISTORE 5 + L5 + LINENUMBER 10 L5 + LDC 10 + LSTORE 6 + L6 + LINENUMBER 11 L6 + LDC 10.1 + DSTORE 8 + L7 + LINENUMBER 12 L7 + LDC 10.1 + FSTORE 10 + L8 + LINENUMBER 14 L8 + GETSTATIC java/lang/System.out : Ljava/io/PrintStream; + ILOAD 1 + IFNE L9 + ICONST_1 + GOTO L10 + L9 + FRAME FULL [target/exercise1/DemoClass I I I I I J D F] + [java/io/PrintStream] + ICONST_0 + L10 + FRAME FULL [target/exercise1/DemoClass I I I I I J D F] + [java/io/PrintStream I] + INVOKEVIRTUAL java/io/PrintStream.println (Z)V + L11 + LINENUMBER 15 L11 + GETSTATIC java/lang/System.out : Ljava/io/PrintStream; + ILOAD 2 + ICONST_1 + ISUB + INVOKEVIRTUAL java/io/PrintStream.println (I)V + L12 + LINENUMBER 16 L12 + GETSTATIC java/lang/System.out : Ljava/io/PrintStream; + ILOAD 3 + ICONST_1 + IADD + INVOKEVIRTUAL java/io/PrintStream.println (I)V + L13 + LINENUMBER 17 L13 + GETSTATIC java/lang/System.out : Ljava/io/PrintStream; + ILOAD 4 + ICONST_1 + IADD + INVOKEVIRTUAL java/io/PrintStream.println (I)V + L14 + LINENUMBER 18 L14 + GETSTATIC java/lang/System.out : Ljava/io/PrintStream; + ILOAD 5 + ICONST_1 + IADD + INVOKEVIRTUAL java/io/PrintStream.println (I)V + L15 + LINENUMBER 19 L15 + GETSTATIC java/lang/System.out : Ljava/io/PrintStream; + LLOAD 6 + LCONST_1 + LADD + INVOKEVIRTUAL java/io/PrintStream.println (J)V + L16 + LINENUMBER 20 L16 + GETSTATIC java/lang/System.out : Ljava/io/PrintStream; + DLOAD 8 + DCONST_1 + DADD + INVOKEVIRTUAL java/io/PrintStream.println (D)V + L17 + LINENUMBER 21 L17 + GETSTATIC java/lang/System.out : Ljava/io/PrintStream; + FLOAD 10 + FCONST_1 + FADD + INVOKEVIRTUAL java/io/PrintStream.println (F)V + L18 + LINENUMBER 23 L18 + RETURN + L19 + LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L19 0 + LOCALVARIABLE varBoolean Z L1 L19 1 + LOCALVARIABLE varByte B L2 L19 2 + LOCALVARIABLE varChar C L3 L19 3 + LOCALVARIABLE varShort S L4 L19 4 + LOCALVARIABLE varInt I L5 L19 5 + LOCALVARIABLE varLong J L6 L19 6 + LOCALVARIABLE varDouble D L7 L19 8 + LOCALVARIABLE varFloat F L8 L19 10 + MAXSTACK = 5 + MAXLOCALS = 11 + } + ``` + + +### ReferenceType +- `(Java)ClassType` - represents the type of a Class. +- `ArrayType` - represents an array. +- `NullType` - assignable to one of the other ReferenceTypes. + +=== "Jimple" + + ```jimple hl_lines="21 24 26" + public class target.exercise1.DemoClass extends java.lang.Object + { + public void () + { + target.exercise1.DemoClass this; + this := @this: target.exercise1.DemoClass; + specialinvoke this.()>(); + return; + } + + public target.exercise1.DemoClass getObject(target.exercise1.DemoClass) + { + target.exercise1.DemoClass obj, this; + this := @this: target.exercise1.DemoClass; + obj := @parameter0: target.exercise1.DemoClass; + return obj; + } + + public void compute(boolean) + { + int[] b; + java.io.PrintStream $stack5, $stack6; + boolean check; + target.exercise1.DemoClass this; + int i; + null_type r0; + java.lang.NullPointerException soot0; + this := @this: target.exercise1.DemoClass; + check := @parameter0: boolean; + b = newarray (int)[5]; + i = 0; + + label1: + if i >= 5 goto label3; + if check == 0 goto label2; + r0 = (null_type) i; + soot0 = new java.lang.NullPointerException; + specialinvoke soot0.(java.lang.String)> + ("This statement would have triggered an Exception: a[i#1] = r0"); + throw soot0; + + label2: + b[i] = i; + i = i + 1; + goto label1; + + label3: + $stack5 = ; + virtualinvoke $stack5.(b); + $stack6 = ; + virtualinvoke $stack6.(null); + return; + } + } + /* + The Local b is of ArrayType, + and Local r0 is of NullType. + */ + ``` + +=== "Java" + + ```java + package target.exercise1; + + public class DemoClass { + + public DemoClass getObject(DemoClass obj){ + return obj; + } + + public void compute(boolean check){ + int a[] = null; + int b[] = new int[5]; + for (int i = 0; i < 5; i++) { + if(check){ + a[i] = i; + } + b[i] = i; + } + System.out.println(b); + System.out.println(a); + } + } + ``` + +=== "Bytecode" + + ``` + // class version 52.0 (52) + // access flags 0x21 + public class target/exercise1/DemoClass { + + // compiled from: DemoClass.java + + // access flags 0x1 + public ()V + L0 + LINENUMBER 3 L0 + ALOAD 0 + INVOKESPECIAL java/lang/Object. ()V + RETURN + L1 + LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0 + MAXSTACK = 1 + MAXLOCALS = 1 + + // access flags 0x1 + public getObject(Ltarget/exercise1/DemoClass;)Ltarget/exercise1/DemoClass; + L0 + LINENUMBER 6 L0 + ALOAD 1 + ARETURN + L1 + LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0 + LOCALVARIABLE obj Ltarget/exercise1/DemoClass; L0 L1 1 + MAXSTACK = 1 + MAXLOCALS = 2 + + // access flags 0x1 + public compute(Z)V + L0 + LINENUMBER 10 L0 + ACONST_NULL + ASTORE 2 + L1 + LINENUMBER 11 L1 + ICONST_5 + NEWARRAY T_INT + ASTORE 3 + L2 + LINENUMBER 12 L2 + ICONST_0 + ISTORE 4 + L3 + FRAME APPEND [[I [I I] + ILOAD 4 + ICONST_5 + IF_ICMPGE L4 + L5 + LINENUMBER 13 L5 + ILOAD 1 + IFEQ L6 + L7 + LINENUMBER 14 L7 + ALOAD 2 + ILOAD 4 + ILOAD 4 + IASTORE + L6 + LINENUMBER 16 L6 + FRAME SAME + ALOAD 3 + ILOAD 4 + ILOAD 4 + IASTORE + L8 + LINENUMBER 12 L8 + IINC 4 1 + GOTO L3 + L4 + LINENUMBER 18 L4 + FRAME CHOP 1 + GETSTATIC java/lang/System.out : Ljava/io/PrintStream; + ALOAD 3 + INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V + L9 + LINENUMBER 19 L9 + GETSTATIC java/lang/System.out : Ljava/io/PrintStream; + ALOAD 2 + INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V + L10 + LINENUMBER 20 L10 + RETURN + L11 + LOCALVARIABLE i I L3 L4 4 + LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L11 0 + LOCALVARIABLE check Z L0 L11 1 + LOCALVARIABLE a [I L1 L11 2 + LOCALVARIABLE b [I L2 L11 3 + MAXSTACK = 3 + MAXLOCALS = 5 + } + ``` + + +### VoidType +Used as a possible return type of a method. + +=== "Jimple" + + ```jimple hl_lines="11" + public class target.exercise1.DemoClass extends java.lang.Object + { + public void () + { + target.exercise1.DemoClass this; + this := @this: target.exercise1.DemoClass; + specialinvoke this.()>(); + return; + } + + public void voidMethod() + { + java.io.PrintStream $stack1; + target.exercise1.DemoClass this; + this := @this: target.exercise1.DemoClass; + $stack1 = ; + virtualinvoke $stack1.("In voidMethod()."); + return; + } + } + /* + For the SootMethod - , + returnType is instance of VoidType. + */ + ``` + +=== "Java" + + ```java + package target.exercise1; + + public class DemoClass { + public void voidMethod(){ + System.out.println("In voidMethod()."); + } + } + ``` + +=== "Bytecode" + + ``` + // class version 52.0 (52) + // access flags 0x21 + public class target/exercise1/DemoClass { + + // compiled from: DemoClass.java + + // access flags 0x1 + public ()V + L0 + LINENUMBER 3 L0 + ALOAD 0 + INVOKESPECIAL java/lang/Object. ()V + RETURN + L1 + LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0 + MAXSTACK = 1 + MAXLOCALS = 1 + + // access flags 0x1 + public voidMethod()V + L0 + LINENUMBER 5 L0 + GETSTATIC java/lang/System.out : Ljava/io/PrintStream; + LDC "In voidMethod()." + INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V + L1 + LINENUMBER 6 L1 + RETURN + L2 + LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L2 0 + MAXSTACK = 2 + MAXLOCALS = 1 + } + ``` + diff --git a/docs/jimple-values.md b/docs/jimple-values.md new file mode 100644 index 00000000000..cdcb1cc35b8 --- /dev/null +++ b/docs/jimple-values.md @@ -0,0 +1,217 @@ +# Jimple Values + +### Immediate +An `Immediate` has a [**given**]{as in constant or immutable} Type and consists of a Local ("a Variable", "Something that contains a Value") or a Constant ("Something that is a Value"). + +#### Local +``` +i0 +``` + +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. + +=== "Jimple" + + ```jimple + public class target.exercise1.DemoClass extends java.lang.Object + { + public void () + { + target.exercise1.DemoClass this; + this := @this: target.exercise1.DemoClass; + specialinvoke this.()>(); + return; + } + + public void compute() + { + java.io.PrintStream $stack2, $stack3; + target.exercise1.DemoClass this; + int local2; + + this := @this: target.exercise1.DemoClass; + $stack2 = ; + virtualinvoke $stack2.(1); + + local2 = this.; + $stack3 = ; + virtualinvoke $stack3.(local2); + return; + } + } + /* + $stack2, this, $stack3, local2 are all Locals. + + "this := @this: target.exercise1.DemoClass" is a JIdentityStmt assigning to a Local. + + "$stack2 = ", + "local2 = this.", + "$stack3 = " + are JAssignStmts assigning to a Local. + + */ + ``` + +=== "Java" + + ```java + package target.exercise1; + + public class DemoClass { + + private int global; + + public void compute(){ + int local; + local = 1; + System.out.println(local); + local = this.global; + System.out.println(local); + } + } + ``` + +=== "Bytecode" + + ``` + // class version 52.0 (52) + // access flags 0x21 + public class target/exercise1/DemoClass { + + // compiled from: DemoClass.java + + // access flags 0x2 + private I global + + // access flags 0x1 + public ()V + L0 + LINENUMBER 3 L0 + ALOAD 0 + INVOKESPECIAL java/lang/Object. ()V + RETURN + L1 + LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0 + MAXSTACK = 1 + MAXLOCALS = 1 + + // access flags 0x1 + public compute()V + L0 + LINENUMBER 9 L0 + ICONST_1 + ISTORE 1 + L1 + LINENUMBER 10 L1 + GETSTATIC java/lang/System.out : Ljava/io/PrintStream; + ILOAD 1 + INVOKEVIRTUAL java/io/PrintStream.println (I)V + L2 + LINENUMBER 11 L2 + ALOAD 0 + GETFIELD target/exercise1/DemoClass.global : I + ISTORE 1 + L3 + LINENUMBER 12 L3 + GETSTATIC java/lang/System.out : Ljava/io/PrintStream; + ILOAD 1 + INVOKEVIRTUAL java/io/PrintStream.println (I)V + L4 + LINENUMBER 14 L4 + RETURN + L5 + LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L5 0 + LOCALVARIABLE local I L1 L5 1 + MAXSTACK = 2 + MAXLOCALS = 2 + } + ``` + + + +#### Constant +represents an actual value itself like `42` or `"This is a String"`. +Constants are usually assigned to `Local`s or `Ref`s. +There exists a constant entity for every [Primitive Type](jimple-types.md). + +### Expr +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.(1);` or an `UnaryExpr` such as `!valid`. +And a bunch more! + +### Ref +#### JArrayRef +``` +$arr[1] = 42; +$anotherLocal = arr[99]; +``` +referencing an array position. + +#### JFieldRef +`JFieldRef`s are referencing a `SootField` via its FieldSignature + +- `JStaticFieldRef` like ` ` +- `JInstanceFieldRef` like ` r1.` + You can see the JInstanceFieldRef has the corresponding Local instance that points to the instance of the object which is holding the field. + + +#### IdentityRef +The IdentityRef makes those implicit special value assignments explicit. + +##### JThisRef +``` +@this: package.fruit.Banana +``` +represents the this pointer of the current class. + +##### JCaughtExceptionRef +``` +@caughtexception +``` +represents the value of the thrown exception (caught by this exceptionhandler). + +##### JParameterRef +``` +i0 := @parameter0 +i1 := @parameter1 +``` +represents a parameter of a method, identified by its index. + +## Good to know +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" + ```java + + Value op = assignStmt.getRightOp(); + if(op instanceof Local){ + // found a Local + ... + }else if(stmt instanceof Constant){ + // found a Constant + ... + }else ... + + ``` + +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 `Value`s you need to handle. This is visitor acts like a switch-case, implemented via two dynamic calls. +=== "StmtVisitor" + ```java + + Value op = assignStmt.getRightOp() ; + AbstractValueVisitor visitor = new AbstractValueVisitor() { + private int intConstantCounter = 0; + @Override + public void caseConstant(@Nonnull Constant c) { + intConstantCounter++; + setResult(intConstantCounter); + } + }; + + op.accept(visitor); + int amountOfIfStmts = visitor.getResult(); + ``` + + 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. diff --git a/docs/jimple.md b/docs/jimple.md index 007cd9baff8..7370de698ae 100644 --- a/docs/jimple.md +++ b/docs/jimple.md @@ -6,11 +6,10 @@ Therefore, Jimple aims to bring the best of both worlds, a non-stack-based and f 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](https://courses.cs.washington.edu/courses/cse501/01wi/project/sable-thesis.pdf) by Raja Vallee-Rai. -It might help to visualize how the Jimple version of a Java code looks like. Have a look at the following example on the `HelloWorld` class. +Lets have a look at the following Jimple code representing Java code of a `HelloWorld` class. === "Jimple" @@ -55,7 +54,7 @@ It might help to visualize how the Jimple version of a Java code looks like. Hav } ``` -=== "Byte Code" +=== "Bytecode" ``` // class version 52.0 (52) @@ -95,6 +94,12 @@ It might help to visualize how the Jimple version of a Java code looks like. Hav } ``` +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 . + + ## Jimple Grammar Structure Jimple mimics the JVMs class file structure. Therefore it is object oriented. @@ -103,224 +108,9 @@ Three-Address-Code which means there are no nested expressions. (nested expressions can be modeled via Locals that store intermediate calculation results.) -### Class (or Interface) -A class consists of Fields and Methods. -It is referenced by its ClassType. - -=== "Jimple" - - ```jimple - public class target.exercise1.DemoClass extends java.lang.Object - { - public void () - { - target.exercise1.DemoClass this; - this := @this: target.exercise1.DemoClass; - specialinvoke this.()>(); - return; - } - } - ``` - -=== "Java" - - ```java - package target.exercise1; - - public class DemoClass {} - ``` - -=== "Byte Code" - - ``` - // class version 52.0 (52) - // access flags 0x21 - public class target/exercise1/DemoClass { - - // compiled from: DemoClass.java - - // access flags 0x1 - public ()V - L0 - LINENUMBER 3 L0 - ALOAD 0 - INVOKESPECIAL java/lang/Object. ()V - RETURN - L1 - LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0 - MAXSTACK = 1 - MAXLOCALS = 1 - } - ``` - - -### Field -A Field is a piece of memory which can store a value that is accessible according to its visibility modifier. -It is referenced by its FieldSignature. - -=== "Jimple" - - ```jimple - public class target.exercise1.DemoClass extends java.lang.Object - { - public void () - { - target.exercise1.DemoClass this; - this := @this: target.exercise1.DemoClass; - specialinvoke this.()>(); - this. = 3.14; - return; - } - } - /* - "this." is JInstanceFieldRef - */ - ``` - -=== "Java" - - ```java - package target.exercise1; - - public class DemoClass { - private final double pi = 3.14; - } - ``` - -=== "Byte Code" - - ``` - // class version 52.0 (52) - // access flags 0x21 - public class target/exercise1/DemoClass { - - // compiled from: DemoClass.java - - // access flags 0x12 - private final D pi = 3.14 - - // access flags 0x1 - public ()V - L0 - LINENUMBER 3 L0 - ALOAD 0 - INVOKESPECIAL java/lang/Object. ()V - L1 - LINENUMBER 4 L1 - ALOAD 0 - LDC 3.14 - PUTFIELD target/exercise1/DemoClass.pi : D - RETURN - L2 - LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L2 0 - MAXSTACK = 3 - MAXLOCALS = 1 - } - ``` - - -### Method and the Body -The interesting part is a method. A method is a "piece of code" that can be executed. -It is referenced by its MethodSignature and contains a [**StmtGraph**]{a control flow graph} that models the sequence of single instructions/statements (Stmts). - -=== "Jimple" - - ```jimple - public class target.exercise1.DemoClass extends java.lang.Object - { - public void () - { - target.exercise1.DemoClass this; - this := @this: target.exercise1.DemoClass; - specialinvoke this.()>(); - virtualinvoke this.(); - return; - } - - public void demoMethod() - { - java.io.PrintStream $stack1; - target.exercise1.DemoClass this; - - this := @this: target.exercise1.DemoClass; - $stack1 = ; - - virtualinvoke $stack1.("Inside method."); - return; - } - } - /* - "" - and "()>" - are instances of SootMethod - */ - ``` - -=== "Java" - - ```java - package target.exercise1; - - public class DemoClass { - DemoClass(){ - demoMethod(); - } - public void demoMethod(){ - System.out.println("Inside method."); - } - } - ``` - -=== "Byte Code" - - ``` - // class version 52.0 (52) - // access flags 0x21 - public class target/exercise1/DemoClass { - - // compiled from: DemoClass.java - - // access flags 0x0 - ()V - L0 - LINENUMBER 5 L0 - ALOAD 0 - INVOKESPECIAL java/lang/Object. ()V - L1 - LINENUMBER 6 L1 - ALOAD 0 - INVOKEVIRTUAL target/exercise1/DemoClass.demoMethod ()V - L2 - LINENUMBER 7 L2 - RETURN - L3 - LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L3 0 - MAXSTACK = 1 - MAXLOCALS = 1 - - // access flags 0x1 - public demoMethod()V - L0 - LINENUMBER 10 L0 - GETSTATIC java/lang/System.out : Ljava/io/PrintStream; - LDC "Inside method." - INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V - L1 - LINENUMBER 11 L1 - RETURN - L2 - LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L2 0 - MAXSTACK = 2 - MAXLOCALS = 1 - } - ``` - - -### Signatures -Signatures are required for identifying or referencing things across a method, such as Classes, Interfaces, Methods or Fields. -Locals, on the other hand, do not need signatures, since they are referenced within method boundaries. +### Signatures and ClassTypes +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. === "Jimple" @@ -392,7 +182,7 @@ Locals, on the other hand, do not need signatures, since they are referenced wit } ``` -=== "Byte Code" +=== "Bytecode" ``` // class version 52.0 (52) @@ -456,8 +246,9 @@ Locals, on the other hand, do not need signatures, since they are referenced wit } ``` -### Trap -A Trap is a mechanism to model exceptional flow. +### SootClass +A `SootClass` consists of SootFields and SootMethods. +It is referenced by its global identifier the `ClassType` like `java.lang.String`. === "Jimple" @@ -471,65 +262,18 @@ A Trap is a mechanism to model exceptional flow. specialinvoke this.()>(); return; } - - public void divideExample(int, int) - { - int x, y, $stack4; - java.io.PrintStream $stack5, $stack7; - java.lang.Exception $stack6; - target.exercise1.DemoClass this; - - this := @this: target.exercise1.DemoClass; - x := @parameter0: int; - y := @parameter1: int; - - label1: - $stack5 = ; - $stack4 = x / y; - virtualinvoke $stack5.($stack4); - - label2: - goto label4; - - label3: - $stack6 := @caughtexception; - $stack7 = ; - virtualinvoke $stack7.("Exception caught"); - - label4: - return; - - catch java.lang.Exception from label1 to label2 with label3; - } } - /* - By calling getTraps() method, we can get the Traip chain. - For the above jimple code, we have the below trap: - Trap : - begin : $stack5 = - end : goto [?= return] - handler: $stack6 := @caughtexception - */ ``` === "Java" ```java - package target.exercise1; + package target.exercise1; - public class DemoClass { - public void divideExample(int x, int y){ - try { - System.out.println(x / y); - }catch (Exception e){ - System.out.println("Exception caught"); - } - } - } + public class DemoClass {} ``` -=== "Byte Code" +=== "Bytecode" ``` // class version 52.0 (52) @@ -539,63 +283,23 @@ A Trap is a mechanism to model exceptional flow. // compiled from: DemoClass.java // access flags 0x1 - public ()V + public ()V L0 LINENUMBER 3 L0 ALOAD 0 INVOKESPECIAL java/lang/Object. ()V RETURN - L1 - LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0 - MAXSTACK = 1 - MAXLOCALS = 1 - - // access flags 0x1 - public divideExample(II)V - TRYCATCHBLOCK L0 L1 L2 java/lang/Exception - L0 - LINENUMBER 6 L0 - GETSTATIC java/lang/System.out : Ljava/io/PrintStream; - ILOAD 1 - ILOAD 2 - IDIV - INVOKEVIRTUAL java/io/PrintStream.println (I)V L1 - LINENUMBER 9 L1 - GOTO L3 - L2 - LINENUMBER 7 L2 - FRAME SAME1 java/lang/Exception - ASTORE 3 - L4 - LINENUMBER 8 L4 - GETSTATIC java/lang/System.out : Ljava/io/PrintStream; - LDC "Exception caught" - INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V - L3 - LINENUMBER 10 L3 - FRAME SAME - RETURN - L5 - LOCALVARIABLE e Ljava/lang/Exception; L4 L3 3 - LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L5 0 - LOCALVARIABLE x I L0 L5 1 - LOCALVARIABLE y I L0 L5 2 - MAXSTACK = 3 - MAXLOCALS = 4 + LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0 + MAXSTACK = 1 + MAXLOCALS = 1 } ``` -### Stmt -The main piece of Jimple is a Statement (Stmt). [**Stmts**]{formerly known as Units} represent that can be executed by the JVM. - - -#### Branching Statements -A BranchingStmt's job is to model the flow between Stmts. - -##### JGotoStmt -for unconditional flow. +### SootField +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 ` `. === "Jimple" @@ -607,51 +311,26 @@ for unconditional flow. target.exercise1.DemoClass this; this := @this: target.exercise1.DemoClass; specialinvoke this.()>(); + this. = 3.14; return; } - public static void sampleMethod() - { - int i; - i = 0; - - label1: - if i >= 5 goto label3; - if i != 3 goto label2; - goto label3; - - label2: - i = i + 1; - goto label1; - - label3: - return; - } } /* - Here for statements "goto label3;" and "goto label1;", - we have two instances of JGotoStmt : - "goto[?=return]" and "goto[?=(branch)]". + "this." is JInstanceFieldRef */ ``` === "Java" ```java - package target.exercise1; + package target.exercise1; - public class DemoClass { - public static void sampleMethod(){ - label1: - for (int i = 0; i < 5; i++){ - if(i == 3){ - break label1; - } - } - } - } + public class DemoClass { + private final double pi = 3.14; + } ``` -=== "Byte Code" +=== "Bytecode" ``` // class version 52.0 (52) @@ -660,1188 +339,32 @@ for unconditional flow. // compiled from: DemoClass.java - // access flags 0x1 - public ()V - L0 - LINENUMBER 3 L0 - ALOAD 0 - INVOKESPECIAL java/lang/Object. ()V - RETURN - L1 - LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0 - MAXSTACK = 1 - MAXLOCALS = 1 - - // access flags 0x9 - public static sampleMethod()V - L0 - LINENUMBER 6 L0 - ICONST_0 - ISTORE 0 - L1 - FRAME APPEND [I] - ILOAD 0 - ICONST_5 - IF_ICMPGE L2 - L3 - LINENUMBER 7 L3 - ILOAD 0 - ICONST_3 - IF_ICMPNE L4 - L5 - LINENUMBER 8 L5 - GOTO L2 - L4 - LINENUMBER 6 L4 - FRAME SAME - IINC 0 1 - GOTO L1 - L2 - LINENUMBER 11 L2 - FRAME CHOP 1 - RETURN - LOCALVARIABLE i I L1 L2 0 - MAXSTACK = 2 - MAXLOCALS = 1 - } - ``` - -##### JIfStmt -for conditional flow depending on boolean Expression (AbstractConditionExpr) so they have two successor Stmt's. - -=== "Jimple" - - ```jimple - public class target.exercise1.DemoClass extends java.lang.Object - { - public void () - { - target.exercise1.DemoClass this; - this := @this: target.exercise1.DemoClass; - specialinvoke this.()>(); - return; - } - - public static void sampleMethod(int) - { - int x, $stack1; - java.io.PrintStream $stack2, $stack3; - - x := @parameter0: int; - - $stack1 = x % 2; - if $stack1 != 0 goto label1; - - $stack3 = ; - virtualinvoke $stack3.("Even"); - goto label2; - - label1: - $stack2 = ; - virtualinvoke $stack2.("Odd"); - - label2: - return; - } - } - /* - For statement "if $stack1 != 0 goto label1;", - we have an instance of JIfStmt : - "if $stack1 != 0 goto $stack2 - = ". - */ - ``` - -=== "Java" - - ```java - package target.exercise1; - - public class DemoClass { - public static void sampleMethod(int x){ - if(x % 2 == 0){ - System.out.println("Even"); - }else{ - System.out.println("Odd"); - } - } - } - ``` - -=== "Byte Code" - - ``` - // class version 52.0 (52) - // access flags 0x21 - public class target/exercise1/DemoClass { - - // compiled from: DemoClass.java - - // access flags 0x1 - public ()V - L0 - LINENUMBER 3 L0 - ALOAD 0 - INVOKESPECIAL java/lang/Object. ()V - RETURN - L1 - LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0 - MAXSTACK = 1 - MAXLOCALS = 1 - - // access flags 0x9 - public static sampleMethod(I)V - L0 - LINENUMBER 5 L0 - ILOAD 0 - ICONST_2 - IREM - IFNE L1 - L2 - LINENUMBER 6 L2 - GETSTATIC java/lang/System.out : Ljava/io/PrintStream; - LDC "Even" - INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V - GOTO L3 - L1 - LINENUMBER 8 L1 - FRAME SAME - GETSTATIC java/lang/System.out : Ljava/io/PrintStream; - LDC "Odd" - INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V - L3 - LINENUMBER 10 L3 - FRAME SAME - RETURN - L4 - LOCALVARIABLE x I L0 L4 0 - MAXSTACK = 2 - MAXLOCALS = 1 - } - ``` - -##### JSwitchStmt -for conditional flow that behaves like a switch-case. It has #numberOfCaseLabels+1 (for default) successor Stmt's. - -All other Stmts are not manipulating the flow, which means they have a single successor Stmt as long as they are not exiting the flow inside a method. - -=== "Jimple" - - ```jimple - public class target.exercise1.DemoClass extends java.lang.Object - { - public void () - { - target.exercise1.DemoClass this; - this := @this: target.exercise1.DemoClass; - specialinvoke this.()>(); - return; - } - - public void switchExample(int) - { - int x; - java.io.PrintStream $stack2, $stack3, $stack4; - target.exercise1.DemoClass this; - - this := @this: target.exercise1.DemoClass; - x := @parameter0: int; - - lookupswitch(x) - { - case 1: goto label1; - case 2: goto label2; - default: goto label3; - }; - - label1: - $stack3 = ; - virtualinvoke $stack3.("Input 1"); - goto label4; - - label2: - $stack2 = ; - virtualinvoke $stack2.("Input 2"); - goto label4; - - label3: - $stack4 = ; - virtualinvoke $stack4.("Input more than 2"); - - label4: - return; - } - } - /* - Here for below statement: - lookupswitch(x) - { - case 1: goto label1; - case 2: goto label2; - default: goto label3; - }; - - we have an instance of JLookupSwitchStmt : - lookupswitch(x) - { - case 1: goto $stack3 - = ; - case 2: goto $stack2 - = ; - default: goto $stack4 - = ; - } - */ - ``` - -=== "Java" - - ```java - package target.exercise1; - - public class DemoClass { - public void switchExample(int x){ - switch (x){ - case 1: - System.out.println("Input 1"); - break; - - case 2: - System.out.println("Input 2"); - break; - - default: - System.out.println("Input more than 2"); - break; - - } - } - } - ``` - -=== "Byte Code" - - ``` - // class version 52.0 (52) - // access flags 0x21 - public class target/exercise1/DemoClass { - - // compiled from: DemoClass.java - - // access flags 0x1 - public ()V - L0 - LINENUMBER 3 L0 - ALOAD 0 - INVOKESPECIAL java/lang/Object. ()V - RETURN - L1 - LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0 - MAXSTACK = 1 - MAXLOCALS = 1 - - // access flags 0x1 - public switchExample(I)V - L0 - LINENUMBER 5 L0 - ILOAD 1 - LOOKUPSWITCH - 1: L1 - 2: L2 - default: L3 - L1 - LINENUMBER 7 L1 - FRAME SAME - GETSTATIC java/lang/System.out : Ljava/io/PrintStream; - LDC "Input 1" - INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V - L4 - LINENUMBER 8 L4 - GOTO L5 - L2 - LINENUMBER 11 L2 - FRAME SAME - GETSTATIC java/lang/System.out : Ljava/io/PrintStream; - LDC "Input 2" - INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V - L6 - LINENUMBER 12 L6 - GOTO L5 - L3 - LINENUMBER 15 L3 - FRAME SAME - GETSTATIC java/lang/System.out : Ljava/io/PrintStream; - LDC "Input more than 2" - INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V - L5 - LINENUMBER 19 L5 - FRAME SAME - RETURN - L7 - LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L7 0 - LOCALVARIABLE x I L0 L7 1 - MAXSTACK = 2 - MAXLOCALS = 2 - } - ``` - - -##### JReturnStmt & JReturnVoidStmt -They end the execution/flow inside the current method and return (a value) to its caller. - -=== "Jimple" - - ```jimple - public class target.exercise1.DemoClass extends java.lang.Object - { - public void () - { - target.exercise1.DemoClass this; - this := @this: target.exercise1.DemoClass; - specialinvoke this.()>(); - return; - } - - public int increment(int) - { - int x, $stack2; - target.exercise1.DemoClass this; - - this := @this: target.exercise1.DemoClass; - x := @parameter0: int; - - $stack2 = x + 1; - return $stack2; - } - - public void print() - { - java.io.PrintStream $stack1; - target.exercise1.DemoClass this; - - this := @this: target.exercise1.DemoClass; - $stack1 = ; - virtualinvoke $stack1.("Inside method print"); - return; - } - } - /* - "return $stack2" is JReturnStmt. - "return" is JReturnVoidStmt. - */ - ``` - -=== "Java" - - ```java - package target.exercise1; - - public class DemoClass { - public int increment(int x){ - return x + 1; - } - public void print(){ - System.out.println("Inside method print"); - } - } - ``` - -=== "Byte Code" - - ``` - // class version 52.0 (52) - // access flags 0x21 - public class target/exercise1/DemoClass { - - // compiled from: DemoClass.java - - // access flags 0x1 - public ()V - L0 - LINENUMBER 3 L0 - ALOAD 0 - INVOKESPECIAL java/lang/Object. ()V - RETURN - L1 - LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0 - MAXSTACK = 1 - MAXLOCALS = 1 - - // access flags 0x1 - public increment(I)I - L0 - LINENUMBER 5 L0 - ILOAD 1 - ICONST_1 - IADD - IRETURN - L1 - LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0 - LOCALVARIABLE x I L0 L1 1 - MAXSTACK = 2 - MAXLOCALS = 2 - - // access flags 0x1 - public print()V - L0 - LINENUMBER 8 L0 - GETSTATIC java/lang/System.out : Ljava/io/PrintStream; - LDC "Inside method print" - INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V - L1 - LINENUMBER 9 L1 - RETURN - L2 - LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L2 0 - MAXSTACK = 2 - MAXLOCALS = 1 - } - ``` - - -##### JThrowStmt -Ends the execution inside the current Method if the thrown exception is not caught by a Trap, which redirects the execution to an exceptionhandler. - - -=== "Jimple" - - ```jimple - public class target.exercise1.DemoClass extends java.lang.Object - { - public void () - { - target.exercise1.DemoClass this; - this := @this: target.exercise1.DemoClass; - specialinvoke this.()>(); - return; - } - - public void divideExample(int, int) - { - int y, x, $stack6; - java.lang.StringBuilder $stack3, $stack5, $stack7; - java.io.PrintStream $stack4; - java.lang.String $stack8; - java.lang.RuntimeException $stack9; - target.exercise1.DemoClass this; - - this := @this: target.exercise1.DemoClass; - x := @parameter0: int; - y := @parameter1: int; - - if y != 0 goto label1; - - $stack9 = new java.lang.RuntimeException; - specialinvoke $stack9.(java.lang.String)>("Divide by zero error"); - throw $stack9; - - label1: - $stack4 = ; - $stack3 = new java.lang.StringBuilder; - specialinvoke $stack3.()>(); - - $stack5 = virtualinvoke $stack3.("Divide result : "); - $stack6 = x / y; - $stack7 = virtualinvoke $stack5.($stack6); - $stack8 = virtualinvoke $stack7.(); - - virtualinvoke $stack4.($stack8); - return; - } - } - /* - "throw $stack9" is JThrowStmt. - */ - ``` - -=== "Java" - - ```java - package target.exercise1; - - public class DemoClass { - public void divideExample(int x, int y){ - if(y == 0){ - throw new RuntimeException("Divide by zero error"); - } - System.out.println("Divide result : " + x / y); - } - } - ``` - -=== "Byte Code" - - ``` - // class version 52.0 (52) - // access flags 0x21 - public class target/exercise1/DemoClass { - - // compiled from: DemoClass.java - - // access flags 0x1 - public ()V - L0 - LINENUMBER 3 L0 - ALOAD 0 - INVOKESPECIAL java/lang/Object. ()V - RETURN - L1 - LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0 - MAXSTACK = 1 - MAXLOCALS = 1 - - // access flags 0x1 - public divideExample(II)V - L0 - LINENUMBER 5 L0 - ILOAD 2 - IFNE L1 - L2 - LINENUMBER 6 L2 - NEW java/lang/RuntimeException - DUP - LDC "Divide by zero error" - INVOKESPECIAL java/lang/RuntimeException. - (Ljava/lang/String;)V - ATHROW - L1 - LINENUMBER 8 L1 - FRAME SAME - GETSTATIC java/lang/System.out : Ljava/io/PrintStream; - NEW java/lang/StringBuilder - DUP - INVOKESPECIAL java/lang/StringBuilder. ()V - LDC "Divide result : " - INVOKEVIRTUAL java/lang/StringBuilder.append - (Ljava/lang/String;)Ljava/lang/StringBuilder; - ILOAD 1 - ILOAD 2 - IDIV - INVOKEVIRTUAL java/lang/StringBuilder.append - (I)Ljava/lang/StringBuilder; - INVOKEVIRTUAL java/lang/StringBuilder.toString - ()Ljava/lang/String; - INVOKEVIRTUAL java/io/PrintStream.println - (Ljava/lang/String;)V - L3 - LINENUMBER 9 L3 - RETURN - L4 - LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L4 0 - LOCALVARIABLE x I L0 L4 1 - LOCALVARIABLE y I L0 L4 2 - MAXSTACK = 4 - MAXLOCALS = 3 - } - ``` - - -##### JInvokeStmt -transfers the control flow to another method until the called method returns. - -=== "Jimple" - - ```jimple - public class target.exercise1.DemoClass extends java.lang.Object - { - public void () - { - target.exercise1.DemoClass this; - this := @this: target.exercise1.DemoClass; - specialinvoke this.()>(); - return; - } - - public void print(int) - { - target.exercise1.DemoClass this; - int x, a; - java.io.PrintStream $stack4, $stack6; - - this := @this: target.exercise1.DemoClass; - x := @parameter0: int; - - a = virtualinvoke this.(x); - $stack4 = ; - virtualinvoke $stack4.(a); - - a = virtualinvoke this.(a); - $stack6 = ; - virtualinvoke $stack6.(a); - - return; - } - - public int increment(int) - { - int x, $stack2; - target.exercise1.DemoClass this; - - this := @this: target.exercise1.DemoClass; - x := @parameter0: int; - - $stack2 = x + 1; - return $stack2; - } - } - /* - "specialinvoke this.()>()", - "virtualinvoke this.(x)", - "virtualinvoke this.(a)" - are JInvokeStmts. - */ - ``` - -=== "Java" - - ```java - package target.exercise1; - - public class DemoClass { - public void print(int x){ - int a = increment(x); - System.out.println(a); - a = increment(a); - System.out.println(a); - } - public int increment(int x){ - return x + 1; - } - } - ``` - -=== "Byte Code" - - ``` - // class version 52.0 (52) - // access flags 0x21 - public class target/exercise1/DemoClass { - - // compiled from: DemoClass.java - - // access flags 0x1 - public ()V - L0 - LINENUMBER 3 L0 - ALOAD 0 - INVOKESPECIAL java/lang/Object. ()V - RETURN - L1 - LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0 - MAXSTACK = 1 - MAXLOCALS = 1 - - // access flags 0x1 - public print(I)V - L0 - LINENUMBER 5 L0 - ALOAD 0 - ILOAD 1 - INVOKEVIRTUAL target/exercise1/DemoClass.increment (I)I - ISTORE 2 - L1 - LINENUMBER 6 L1 - GETSTATIC java/lang/System.out : Ljava/io/PrintStream; - ILOAD 2 - INVOKEVIRTUAL java/io/PrintStream.println (I)V - L2 - LINENUMBER 7 L2 - ALOAD 0 - ILOAD 2 - INVOKEVIRTUAL target/exercise1/DemoClass.increment (I)I - ISTORE 2 - L3 - LINENUMBER 8 L3 - GETSTATIC java/lang/System.out : Ljava/io/PrintStream; - ILOAD 2 - INVOKEVIRTUAL java/io/PrintStream.println (I)V - L4 - LINENUMBER 9 L4 - RETURN - L5 - LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L5 0 - LOCALVARIABLE x I L0 L5 1 - LOCALVARIABLE a I L1 L5 2 - MAXSTACK = 2 - MAXLOCALS = 3 - - // access flags 0x1 - public increment(I)I - L0 - LINENUMBER 11 L0 - ILOAD 1 - ICONST_1 - IADD - IRETURN - L1 - LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0 - LOCALVARIABLE x I L0 L1 1 - MAXSTACK = 2 - MAXLOCALS = 2 - } - ``` - - -##### JAssignStmt -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. - -=== "Jimple" - - ```jimple - public class target.exercise1.DemoClass extends java.lang.Object - { - public void () - { - target.exercise1.DemoClass this; - this := @this: target.exercise1.DemoClass; - specialinvoke this.()>(); - this. = 0; - return; - } - - public int updateCounter() - { - target.exercise1.DemoClass this; - int $stack1, $stack2, $stack3; - - this := @this: target.exercise1.DemoClass; - - $stack1 = this.; - $stack2 = $stack1 + 1; - this. = $stack2; - $stack3 = this.; - - return $stack3; - } - } - /* - "this. = 0", - "$stack1 = this.", - "$stack2 = $stack1 + 1" - "this. = $stack2" - "$stack3 = this." - are JAssignStmts. - */ - ``` - -=== "Java" - - ```java - package target.exercise1; - - public class DemoClass { - private int counter = 0; - public int updateCounter(){ - counter = counter + 1; - return counter; - } - } - ``` - -=== "Byte Code" - - ``` - // class version 52.0 (52) - // access flags 0x21 - public class target/exercise1/DemoClass { - - // compiled from: DemoClass.java - - // access flags 0x2 - private I counter - - // access flags 0x1 - public ()V - L0 - LINENUMBER 3 L0 - ALOAD 0 - INVOKESPECIAL java/lang/Object. ()V - L1 - LINENUMBER 4 L1 - ALOAD 0 - ICONST_0 - PUTFIELD target/exercise1/DemoClass.counter : I - RETURN - L2 - LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L2 0 - MAXSTACK = 2 - MAXLOCALS = 1 - - // access flags 0x1 - public updateCounter()I - L0 - LINENUMBER 6 L0 - ALOAD 0 - ALOAD 0 - GETFIELD target/exercise1/DemoClass.counter : I - ICONST_1 - IADD - PUTFIELD target/exercise1/DemoClass.counter : I - L1 - LINENUMBER 7 L1 - ALOAD 0 - GETFIELD target/exercise1/DemoClass.counter : I - IRETURN - L2 - LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L2 0 - MAXSTACK = 3 - MAXLOCALS = 1 - } - ``` - - -##### JIdentityStmt -is semantically like the JAssignStmt and handles assignments of IdentityRef's to make implicit assignments explicit into the StmtGraph. - -=== "Jimple" - - ```jimple - public class target.exercise1.DemoClass extends java.lang.Object - { - public void () - { - target.exercise1.DemoClass this; - this := @this: target.exercise1.DemoClass; - specialinvoke this.()>(); - return; - } - - public void DemoClass(int) - { - target.exercise1.DemoClass this; - int counter; - - this := @this: target.exercise1.DemoClass; - counter := @parameter0: int; - this. = counter; - return; - } - } - /* - "this := @this: target.exercise1.DemoClass" and - "counter := @parameter0: int" are JIdentityStmts - */ - ``` - -=== "Java" - - ```java - package target.exercise1; - - public class DemoClass { - private int counter; - public void DemoClass(int counter){ - this.counter = counter; - } - } - ``` - -=== "Byte Code" - - ``` - // class version 52.0 (52) - // access flags 0x21 - public class target/exercise1/DemoClass { - - // compiled from: DemoClass.java - - // access flags 0x2 - private I counter - - // access flags 0x1 - public ()V - L0 - LINENUMBER 3 L0 - ALOAD 0 - INVOKESPECIAL java/lang/Object. ()V - RETURN - L1 - LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0 - MAXSTACK = 1 - MAXLOCALS = 1 - - // access flags 0x1 - public DemoClass(I)V - L0 - LINENUMBER 6 L0 - ALOAD 0 - ILOAD 1 - PUTFIELD target/exercise1/DemoClass.counter : I - L1 - LINENUMBER 7 L1 - RETURN - L2 - LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L2 0 - LOCALVARIABLE counter I L0 L2 1 - MAXSTACK = 2 - MAXLOCALS = 2 - } - ``` - - -#####JEnterMonitorStmt & JExitMonitorStmt -marks synchronized blocks of code from JEnterMonitorStmt to JExitMonitorStmt. - -=== "Jimple" - - ```jimple - public class target.exercise1.DemoClass extends java.lang.Object - { - public void () - { - target.exercise1.DemoClass this; - this := @this: target.exercise1.DemoClass; - specialinvoke this.()>(); - this. = 0; - return; - } - - public int updateCounter() - { - target.exercise1.DemoClass this; - int $stack4, $stack5, $stack7; - java.lang.Throwable $stack8; - - this := @this: target.exercise1.DemoClass; - - entermonitor this; - - label1: - $stack4 = this.; - $stack5 = $stack4 + 1; - this. = $stack5; - - exitmonitor this; - - label2: - goto label5; - - label3: - $stack8 := @caughtexception; - - exitmonitor this; - - label4: - throw $stack8; - - label5: - $stack7 = this.; - return $stack7; - - catch java.lang.Throwable from label1 to label2 with label3; - catch java.lang.Throwable from label3 to label4 with label3; - } - } - /* - "entermonitor this" is JEnterMonitorStmt. - "exitmonitor this" is JExitMonitorStmt. - */ - ``` - -=== "Java" - - ```java - package target.exercise1; - - public class DemoClass { - private int counter = 0; - public int updateCounter(){ - synchronized (this) { - counter = counter + 1; - } - return counter; - } - } - ``` - -=== "Byte Code" - - ``` - // class version 52.0 (52) - // access flags 0x21 - public class target/exercise1/DemoClass { - - // compiled from: DemoClass.java - - // access flags 0x2 - private I counter - - // access flags 0x1 - public ()V - L0 - LINENUMBER 3 L0 - ALOAD 0 - INVOKESPECIAL java/lang/Object. ()V - L1 - LINENUMBER 4 L1 - ALOAD 0 - ICONST_0 - PUTFIELD target/exercise1/DemoClass.counter : I - RETURN - L2 - LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L2 0 - MAXSTACK = 2 - MAXLOCALS = 1 - - // access flags 0x1 - public updateCounter()I - TRYCATCHBLOCK L0 L1 L2 null - TRYCATCHBLOCK L2 L3 L2 null - L4 - LINENUMBER 6 L4 - ALOAD 0 - DUP - ASTORE 1 - MONITORENTER - L0 - LINENUMBER 7 L0 - ALOAD 0 - ALOAD 0 - GETFIELD target/exercise1/DemoClass.counter : I - ICONST_1 - IADD - PUTFIELD target/exercise1/DemoClass.counter : I - L5 - LINENUMBER 8 L5 - ALOAD 1 - MONITOREXIT - L1 - GOTO L6 - L2 - FRAME FULL [target/exercise1/DemoClass java/lang/Object] - [java/lang/Throwable] - ASTORE 2 - ALOAD 1 - MONITOREXIT - L3 - ALOAD 2 - ATHROW - L6 - LINENUMBER 9 L6 - FRAME CHOP 1 - ALOAD 0 - GETFIELD target/exercise1/DemoClass.counter : I - IRETURN - L7 - LOCALVARIABLE this Ltarget/exercise1/DemoClass; L4 L7 0 - MAXSTACK = 3 - MAXLOCALS = 3 - } - ``` - - -##### JRetStmt -##### JBreakpointStmt -models a Breakpoint set by a Debugger (usually not relevant for static analyses) - - -### Immediate -An Immediate has a [**given**]{as in constant or immutable} Type and consists of a Local ("a Variable", "Something that contains a Value") or a Constant ("Something that is a Value"). - - -### Type -VoidType - -=== "Jimple" - - ```jimple - public class target.exercise1.DemoClass extends java.lang.Object - { - public void () - { - target.exercise1.DemoClass this; - this := @this: target.exercise1.DemoClass; - specialinvoke this.()>(); - return; - } - - public void voidMethod() - { - java.io.PrintStream $stack1; - target.exercise1.DemoClass this; - this := @this: target.exercise1.DemoClass; - $stack1 = ; - virtualinvoke $stack1.("In voidMethod()."); - return; - } - } - /* - For the SootMethod - , - returnType is instance of VoidType. - */ - ``` - -=== "Java" - - ```java - package target.exercise1; - - public class DemoClass { - public void voidMethod(){ - System.out.println("In voidMethod()."); - } - } - ``` - -=== "Byte Code" - - ``` - // class version 52.0 (52) - // access flags 0x21 - public class target/exercise1/DemoClass { + // access flags 0x12 + private final D pi = 3.14 - // compiled from: DemoClass.java - // access flags 0x1 public ()V L0 - LINENUMBER 3 L0 + LINENUMBER 3 L0 ALOAD 0 INVOKESPECIAL java/lang/Object. ()V - RETURN - L1 - LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0 - MAXSTACK = 1 - MAXLOCALS = 1 - - // access flags 0x1 - public voidMethod()V - L0 - LINENUMBER 5 L0 - GETSTATIC java/lang/System.out : Ljava/io/PrintStream; - LDC "In voidMethod()." - INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V L1 - LINENUMBER 6 L1 + LINENUMBER 4 L1 + ALOAD 0 + LDC 3.14 + PUTFIELD target/exercise1/DemoClass.pi : D RETURN L2 LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L2 0 - MAXSTACK = 2 + MAXSTACK = 3 MAXLOCALS = 1 } ``` -#### PrimaryType -BooleanType, ByteType, CharType, ShortType, IntType, LongType, DoubleType, FloatType +### SootMethod and its Body +The interesting part is a method. A method is a "piece of code" that can be executed. +It is referenced by its MethodSignature like ` `. === "Jimple" @@ -1850,314 +373,31 @@ BooleanType, ByteType, CharType, ShortType, IntType, LongType, DoubleType, Float { public void () { - target.exercise1.DemoClass this; - this := @this: target.exercise1.DemoClass; - specialinvoke this.()>(); - return; - } - - - public void display() - { - java.io.PrintStream $stack11, $stack13, $stack15, - $stack17, $stack19, $stack21, $stack23, $stack25; - int $stack12, $stack14, $stack16, $stack18; - long $stack20; - double $stack22; - float $stack24; - target.exercise1.DemoClass this; - boolean $stack26; - - this := @this: target.exercise1.DemoClass; - - $stack11 = ; - - goto label1; - - label1: - $stack26 = 0; - virtualinvoke $stack11.($stack26); - - $stack13 = ; - $stack12 = 127 - 1; - virtualinvoke $stack13.($stack12); - - $stack15 = ; - $stack14 = 97 + 1; - virtualinvoke $stack15.($stack14); - - $stack17 = ; - $stack16 = 1123 + 1; - virtualinvoke $stack17.($stack16); - - $stack19 = ; - $stack18 = 123456 + 1; - virtualinvoke $stack19.($stack18); - - $stack21 = ; - $stack20 = 10L + 1L; - virtualinvoke $stack21.($stack20); - - $stack23 = ; - $stack22 = 10.1 + 1.0; - virtualinvoke $stack23.($stack22); - - $stack25 = ; - $stack24 = 10.1F + 1.0F; - virtualinvoke $stack25.($stack24); - - return; - } - } - /* - The JimpleLocal $stack12, $stack14, $stack16, $stack18 are of IntType. - Similarly, $stack20 is of LongType, $stack22 is of DoubleType and so on. - */ - ``` - -=== "Java" - - ```java - package target.exercise1; - - public class DemoClass { - public void display(){ - boolean varBoolean = true; - byte varByte = 127; - char varChar = 'a'; - short varShort = 1123; - int varInt = 123456; - long varLong = 10L; - double varDouble = 10.10; - float varFloat = 10.10f; - - System.out.println(!varBoolean); - System.out.println(varByte-1); - System.out.println(varChar+1); - System.out.println(varShort+1); - System.out.println(varInt+1); - System.out.println(varLong+1); - System.out.println(varDouble+1); - System.out.println(varFloat+1); - + target.exercise1.DemoClass this; + this := @this: target.exercise1.DemoClass; + specialinvoke this.()>(); + virtualinvoke this.(); + return; } - } - ``` - -=== "Byte Code" - - ``` - // class version 52.0 (52) - // access flags 0x21 - public class target/exercise1/DemoClass { - - // compiled from: DemoClass.java - - // access flags 0x1 - public ()V - L0 - LINENUMBER 3 L0 - ALOAD 0 - INVOKESPECIAL java/lang/Object. ()V - RETURN - L1 - LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0 - MAXSTACK = 1 - MAXLOCALS = 1 - - // access flags 0x1 - public display()V - L0 - LINENUMBER 5 L0 - ICONST_1 - ISTORE 1 - L1 - LINENUMBER 6 L1 - BIPUSH 127 - ISTORE 2 - L2 - LINENUMBER 7 L2 - BIPUSH 97 - ISTORE 3 - L3 - LINENUMBER 8 L3 - SIPUSH 1123 - ISTORE 4 - L4 - LINENUMBER 9 L4 - LDC 123456 - ISTORE 5 - L5 - LINENUMBER 10 L5 - LDC 10 - LSTORE 6 - L6 - LINENUMBER 11 L6 - LDC 10.1 - DSTORE 8 - L7 - LINENUMBER 12 L7 - LDC 10.1 - FSTORE 10 - L8 - LINENUMBER 14 L8 - GETSTATIC java/lang/System.out : Ljava/io/PrintStream; - ILOAD 1 - IFNE L9 - ICONST_1 - GOTO L10 - L9 - FRAME FULL [target/exercise1/DemoClass I I I I I J D F] - [java/io/PrintStream] - ICONST_0 - L10 - FRAME FULL [target/exercise1/DemoClass I I I I I J D F] - [java/io/PrintStream I] - INVOKEVIRTUAL java/io/PrintStream.println (Z)V - L11 - LINENUMBER 15 L11 - GETSTATIC java/lang/System.out : Ljava/io/PrintStream; - ILOAD 2 - ICONST_1 - ISUB - INVOKEVIRTUAL java/io/PrintStream.println (I)V - L12 - LINENUMBER 16 L12 - GETSTATIC java/lang/System.out : Ljava/io/PrintStream; - ILOAD 3 - ICONST_1 - IADD - INVOKEVIRTUAL java/io/PrintStream.println (I)V - L13 - LINENUMBER 17 L13 - GETSTATIC java/lang/System.out : Ljava/io/PrintStream; - ILOAD 4 - ICONST_1 - IADD - INVOKEVIRTUAL java/io/PrintStream.println (I)V - L14 - LINENUMBER 18 L14 - GETSTATIC java/lang/System.out : Ljava/io/PrintStream; - ILOAD 5 - ICONST_1 - IADD - INVOKEVIRTUAL java/io/PrintStream.println (I)V - L15 - LINENUMBER 19 L15 - GETSTATIC java/lang/System.out : Ljava/io/PrintStream; - LLOAD 6 - LCONST_1 - LADD - INVOKEVIRTUAL java/io/PrintStream.println (J)V - L16 - LINENUMBER 20 L16 - GETSTATIC java/lang/System.out : Ljava/io/PrintStream; - DLOAD 8 - DCONST_1 - DADD - INVOKEVIRTUAL java/io/PrintStream.println (D)V - L17 - LINENUMBER 21 L17 - GETSTATIC java/lang/System.out : Ljava/io/PrintStream; - FLOAD 10 - FCONST_1 - FADD - INVOKEVIRTUAL java/io/PrintStream.println (F)V - L18 - LINENUMBER 23 L18 - RETURN - L19 - LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L19 0 - LOCALVARIABLE varBoolean Z L1 L19 1 - LOCALVARIABLE varByte B L2 L19 2 - LOCALVARIABLE varChar C L3 L19 3 - LOCALVARIABLE varShort S L4 L19 4 - LOCALVARIABLE varInt I L5 L19 5 - LOCALVARIABLE varLong J L6 L19 6 - LOCALVARIABLE varDouble D L7 L19 8 - LOCALVARIABLE varFloat F L8 L19 10 - MAXSTACK = 5 - MAXLOCALS = 11 - } - ``` - - -#### ReferenceType -ClassType, -ArrayType -NullType - -=== "Jimple" - ```jimple - public class target.exercise1.DemoClass extends java.lang.Object - { - public void () + public void demoMethod() { - target.exercise1.DemoClass this; - this := @this: target.exercise1.DemoClass; - specialinvoke this.()>(); - return; - } + java.io.PrintStream $stack1; + target.exercise1.DemoClass this; - public target.exercise1.DemoClass getObject(target.exercise1.DemoClass) - { - target.exercise1.DemoClass obj, this; - this := @this: target.exercise1.DemoClass; - obj := @parameter0: target.exercise1.DemoClass; - return obj; - } + this := @this: target.exercise1.DemoClass; + $stack1 = ; - public void compute(boolean) - { - int[] b; - java.io.PrintStream $stack5, $stack6; - boolean check; - target.exercise1.DemoClass this; - int i; - null_type r0; - java.lang.NullPointerException soot0; - this := @this: target.exercise1.DemoClass; - check := @parameter0: boolean; - b = newarray (int)[5]; - i = 0; - - label1: - if i >= 5 goto label3; - if check == 0 goto label2; - r0 = (null_type) i; - soot0 = new java.lang.NullPointerException; - specialinvoke soot0.(java.lang.String)> - ("This statement would have triggered an Exception: a[i#1] = r0"); - throw soot0; - - label2: - b[i] = i; - i = i + 1; - goto label1; - - label3: - $stack5 = ; - virtualinvoke $stack5.(b); - $stack6 = ; - virtualinvoke $stack6.(null); - return; + virtualinvoke $stack1.("Inside method."); + return; } } /* - The JimpleLocal b is of ArrayType, - and JimpleLocal r0 is of NullType. + "" + and "()>" + are instances of SootMethod */ ``` @@ -2167,296 +407,57 @@ NullType package target.exercise1; public class DemoClass { - - public DemoClass getObject(DemoClass obj){ - return obj; - } - - public void compute(boolean check){ - int a[] = null; - int b[] = new int[5]; - for (int i = 0; i < 5; i++) { - if(check){ - a[i] = i; - } - b[i] = i; - } - System.out.println(b); - System.out.println(a); + DemoClass(){ + demoMethod(); + } + public void demoMethod(){ + System.out.println("Inside method."); } } ``` -=== "Byte Code" +=== "Bytecode" ``` - // class version 52.0 (52) + // class version 52.0 (52) // access flags 0x21 public class target/exercise1/DemoClass { // compiled from: DemoClass.java - // access flags 0x1 - public ()V + // access flags 0x0 + ()V L0 - LINENUMBER 3 L0 + LINENUMBER 5 L0 ALOAD 0 INVOKESPECIAL java/lang/Object. ()V - RETURN L1 - LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0 + LINENUMBER 6 L1 + ALOAD 0 + INVOKEVIRTUAL target/exercise1/DemoClass.demoMethod ()V + L2 + LINENUMBER 7 L2 + RETURN + L3 + LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L3 0 MAXSTACK = 1 MAXLOCALS = 1 // access flags 0x1 - public getObject(Ltarget/exercise1/DemoClass;)Ltarget/exercise1/DemoClass; - L0 - LINENUMBER 6 L0 - ALOAD 1 - ARETURN - L1 - LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0 - LOCALVARIABLE obj Ltarget/exercise1/DemoClass; L0 L1 1 - MAXSTACK = 1 - MAXLOCALS = 2 - - // access flags 0x1 - public compute(Z)V + public demoMethod()V L0 LINENUMBER 10 L0 - ACONST_NULL - ASTORE 2 + GETSTATIC java/lang/System.out : Ljava/io/PrintStream; + LDC "Inside method." + INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/String;)V L1 LINENUMBER 11 L1 - ICONST_5 - NEWARRAY T_INT - ASTORE 3 - L2 - LINENUMBER 12 L2 - ICONST_0 - ISTORE 4 - L3 - FRAME APPEND [[I [I I] - ILOAD 4 - ICONST_5 - IF_ICMPGE L4 - L5 - LINENUMBER 13 L5 - ILOAD 1 - IFEQ L6 - L7 - LINENUMBER 14 L7 - ALOAD 2 - ILOAD 4 - ILOAD 4 - IASTORE - L6 - LINENUMBER 16 L6 - FRAME SAME - ALOAD 3 - ILOAD 4 - ILOAD 4 - IASTORE - L8 - LINENUMBER 12 L8 - IINC 4 1 - GOTO L3 - L4 - LINENUMBER 18 L4 - FRAME CHOP 1 - GETSTATIC java/lang/System.out : Ljava/io/PrintStream; - ALOAD 3 - INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V - L9 - LINENUMBER 19 L9 - GETSTATIC java/lang/System.out : Ljava/io/PrintStream; - ALOAD 2 - INVOKEVIRTUAL java/io/PrintStream.println (Ljava/lang/Object;)V - L10 - LINENUMBER 20 L10 RETURN - L11 - LOCALVARIABLE i I L3 L4 4 - LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L11 0 - LOCALVARIABLE check Z L0 L11 1 - LOCALVARIABLE a [I L1 L11 2 - LOCALVARIABLE b [I L2 L11 3 - MAXSTACK = 3 - MAXLOCALS = 5 - } - ``` - - -#### Local -```jimple -i0 -``` -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. - -=== "Jimple" - - ```jimple - public class target.exercise1.DemoClass extends java.lang.Object - { - public void () - { - target.exercise1.DemoClass this; - this := @this: target.exercise1.DemoClass; - specialinvoke this.()>(); - return; - } - - public void compute() - { - java.io.PrintStream $stack2, $stack3; - target.exercise1.DemoClass this; - int local#2; - - this := @this: target.exercise1.DemoClass; - $stack2 = ; - virtualinvoke $stack2.(1); - - local#2 = this.; - $stack3 = ; - virtualinvoke $stack3.(local#2); - return; - } - } - /* - $stack2, this, $stack3, local#2 are all JimpleLocal. - - "this := @this: target.exercise1.DemoClass" is JIdentityStmt - - "$stack2 = ", - "local#2 = this.", - "$stack3 = " - are JAssignStmt - - */ - ``` - -=== "Java" - - ```java - package target.exercise1; - - public class DemoClass { - - private int global; - - public void compute(){ - int local; - local = 1; - System.out.println(local); - local = this.global; - System.out.println(local); - } - } - ``` - -=== "Byte Code" - - ``` - // class version 52.0 (52) - // access flags 0x21 - public class target/exercise1/DemoClass { - - // compiled from: DemoClass.java - - // access flags 0x2 - private I global - - // access flags 0x1 - public ()V - L0 - LINENUMBER 3 L0 - ALOAD 0 - INVOKESPECIAL java/lang/Object. ()V - RETURN - L1 - LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L1 0 - MAXSTACK = 1 - MAXLOCALS = 1 - - // access flags 0x1 - public compute()V - L0 - LINENUMBER 9 L0 - ICONST_1 - ISTORE 1 - L1 - LINENUMBER 10 L1 - GETSTATIC java/lang/System.out : Ljava/io/PrintStream; - ILOAD 1 - INVOKEVIRTUAL java/io/PrintStream.println (I)V L2 - LINENUMBER 11 L2 - ALOAD 0 - GETFIELD target/exercise1/DemoClass.global : I - ISTORE 1 - L3 - LINENUMBER 12 L3 - GETSTATIC java/lang/System.out : Ljava/io/PrintStream; - ILOAD 1 - INVOKEVIRTUAL java/io/PrintStream.println (I)V - L4 - LINENUMBER 14 L4 - RETURN - L5 - LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L5 0 - LOCALVARIABLE local I L1 L5 1 - MAXSTACK = 2 - MAXLOCALS = 2 - } + LOCALVARIABLE this Ltarget/exercise1/DemoClass; L0 L2 0 + MAXSTACK = 2 + MAXLOCALS = 1 + } ``` - - -#### Constant -represents a value itself. don't confuse it with a variable/Local which has a immutable (i.e. final) attribute. - -There exists a constant entity for every Type - that way all value types can have a representation. - - -### Expr -An expression is a language construct that returns a value. E.g. a binary operation such as addition. - - -### Ref -#### JArrayRef -```jimple -$arr[1] -``` -referencing a position inside an array. - -#### JFieldRef (JStaticFieldRef & JInstanceFieldRef) -```jimple - -// or -r1. -``` -referencing a Field via its FieldSignature and if necessary (i.e. with JInstanceFieldRef) the corresponding Local instance that points to the object instance. - -#### IdentityRef -The IdentityRef makes those implicit special value assignments explicit. - -##### JThisRef -```jimple -@this: package.fruit.Banana -``` -represents the this pointer of the current class. - -##### JCaughtExceptionRef -```jimple -@caughtexception -``` -represents the value of the thrown exception (caught by this exceptionhandler). - -##### JParameterRef -```jimple -i0 := @parameter0 -i1 := @parameter1 -``` -represents a parameter of a method, identified by its index. - +More about the [Body](jimple-body.md) of the SootMethod. \ No newline at end of file diff --git a/docs/migrating.md b/docs/migrating.md new file mode 100644 index 00000000000..dc2eca2059c --- /dev/null +++ b/docs/migrating.md @@ -0,0 +1,116 @@ +# Migration Help + +### Version 1.3.0 +- The Typehierarchy API is now returning `Stream` instead of `Collection`. The simplest fix to have the same behaviour as before would be to collect the Stream on your own ( e.g. via `.collect(Collectors.toList())` ). +- Default BytecodeBodyinterceptors are enabled to improve Jimple. To mitigate that adapt the List of BodyInterceptors to your needs. + +### Version 1.2.0 +- The (Java)Project structure was removed. You can configure the (Java)View directly. +- Bodyinterceptors are now passed as arguments into AnalysisInputLocations. + +### From [Soot](https://github.com/soot-oss/Soot) +- The Scene singleton is dead. Long live the Scene. We have a central View object(!) now. +- Library first! No command line tool as primary goal. So you can configure parts of SootUp (near) where it is actually used. +- t.b.c. + +Below we show a comparison of the code so far with the same functionality in sootup. + +=== "SootUp" + + ``` java + AnalysisInputLocation inputLocation = + new JavaClassPathAnalysisInputLocation("path2Binary"); + + JavaView view = new JavaView(inputLocation); + + JavaClassType classType = + view.getIdentifierFactory().getClassType("HelloWorld"); + + MethodSignature methodSignature = + view + .getIdentifierFactory() + .getMethodSignature( + "main", classType, "void", + Collections.singletonList("java.lang.String[]")); + + JavaSootClass sootClass = view.getClass(classType).get(); + + MethodSubSignature mss = methodSignature.getSubSignature(); + JavaSootMethod sootMethod = sootClass.getMethod(mss).get(); + + sootMethod.getBody().getStmts(); + ``` + +=== "Soot" + + ``` java + G.reset(); + String userdir = System.getProperty("user.dir"); + String sootCp = + userdir + + File.separator + + "target" + + File.separator + + "test-classes" + + File.pathSeparator + "lib"+File.separator+"rt.jar"; + + Options.v().set_soot_classpath(sootCp); + Options.v().set_whole_program(true); + Options.v().setPhaseOption("cg.cha", "on"); + Options.v().setPhaseOption("cg", "all-reachable:true"); + Options.v().set_no_bodies_for_excluded(true); + Options.v().set_allow_phantom_refs(true); + Options.v().setPhaseOption("jb", "use-original-names:true"); + Options.v().set_prepend_classpath(false); + + Scene.v().addBasicClass("java.lang.StringBuilder"); + SootClass c = + Scene.v().forceResolve(targetTestClassName, SootClass.BODIES); + if (c != null) { + c.setApplicationClass(); + } + Scene.v().loadNecessaryClasses(); + + SootMethod method; + for (SootClass c : Scene.v().getApplicationClasses()) { + if(c.getName().equals("example.HelloWorld")){ + for (SootMethod m : c.getMethods()) { + if (!m.hasActiveBody()) { + continue; + } + if (m.getName().equals("entryPoint")) { + method = m; + break; + } + } + } + } + + method.getActiveBody().getUnits(); + ``` + + + + + + + + + diff --git a/docs/overrides/partials/footer.html b/docs/overrides/partials/footer.html new file mode 100644 index 00000000000..12330e0318a --- /dev/null +++ b/docs/overrides/partials/footer.html @@ -0,0 +1,108 @@ + + + + \ No newline at end of file diff --git a/docs/overrides/partials/outdated.html b/docs/overrides/partials/outdated.html new file mode 100644 index 00000000000..36a4967d7de --- /dev/null +++ b/docs/overrides/partials/outdated.html @@ -0,0 +1,8 @@ +{% extends "base.html" %} + +{% block outdated %} +You're not viewing the latest version. + + Click here to go to latest version. + +{% endblock %} \ No newline at end of file diff --git a/docs/qilin.md b/docs/qilin.md new file mode 100644 index 00000000000..9c9971adbae --- /dev/null +++ b/docs/qilin.md @@ -0,0 +1,22 @@ +# Incorporate Qilin Pointer Analysis +see [QilinPTA](https://github.com/QilinPTA/Qilin). + +### Dependencies +=== "Maven" + ```maven + + org.soot-oss + sootup.java.sourcecode + + + ``` + +=== "Gradle" + + ```groovy + compile "org.soot-oss:sootup.qilin:{{ git_latest_release }}" + ``` + +### How to + +// TODO \ No newline at end of file diff --git a/docs/tool_setup.md b/docs/tool_setup.md new file mode 100644 index 00000000000..ee4445427f8 --- /dev/null +++ b/docs/tool_setup.md @@ -0,0 +1,36 @@ +# From Prototype to an intuitive Tool + +`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 and calling 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. + +Dependencies: +=== "Maven" + ```maven + + commons-cli + commons-cli + 1.8.0 + + ``` + +=== "Gradle" + ```groovy + implementation("commons-cli:commons-cli:1.8.0") + ``` + +### Java Code + + ```java + + class SootUpConfiguration{ + // TODO incorporate + } + + ``` + +We are happy if you steal the following code to create a tool where the setup is just simple. diff --git a/docs/write_analyses.md b/docs/write_analyses.md index 7ee09b1b10e..5604ea1e47c 100644 --- a/docs/write_analyses.md +++ b/docs/write_analyses.md @@ -1,7 +1,34 @@ -# Writing Analyses +# Write your own Interprocedural Dataflow Analysis + +### Dependencies +=== "Maven" + ```maven + + org.soot-oss + sootup.analysis + + + ``` +=== "Gradle" + ```groovy + compile "org.soot-oss:sootup.analysis:{{ git_latest_release }}" + ``` + +### Useful Knowledge +Background Knowledge as online lectures are available on YouTube. + +- [IFDS Framework](https://www.youtube.com/watch?v=QkK79fT0TFU&ab_channel=SecureSoftwareEngineering) +- [IDE Framework](https://www.youtube.com/watch?v=0uMHX3UY9bg&ab_channel=SecureSoftwareEngineering) + +### Examples +Taint Analysis, TypeState Analysis, Linear Constant Propagation, ... ``` -// TODO improve tutorial! +// TODO incorporate & guide through examples + +In the meantime please have a look into the test cases of the +analysis submodule to see example implementations of interprocedural +data-flow analysis via the IFDS or IDE Framework. + ``` -If you wish to implement an interprocedural data-flow analysis via the IFDS or IDE Framework please have a look at the test cases in the sootup.analysis submodule. \ No newline at end of file diff --git a/mkdocs.yml b/mkdocs.yml index baf4d12f4bf..87633845ac6 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -1,54 +1,65 @@ -site_name: SootUp +site_name: "" site_url: https://soot-oss.github.io/SootUp/ repo_url: https://github.com/soot-oss/SootUp/ edit_uri: edit/develop/docs/ nav: - - Home: index.md - - Announcements: announce.md - - Design Decisions: whatsnew.md - - - Basics: + - Getting Started: - Installation: installation.md -# - Configure your Input: analysisinputlocations.md - - Getting started: getting-started.md - - Jimple: jimple.md + - First Steps: getting-started.md + - Analysis Input: analysisinputlocations.md + - Examples: examples.md + + - Basics: + - Jimple IR: jimple.md + - Jimple Body: jimple-body.md + - Jimple Statements: jimple-stmts.md + - Jimple Types: jimple-types.md + - Jimple Values: jimple-values.md - - Advanced Topics: + - Advanced Topics: - BodyInterceptors: bodyinterceptors.md - - Call Graph Construction: call-graph-construction.md - - SootUp Utilities: advanced-topics.md + - Callgraphs: callgraphs.md + - BuiltIn Analyses: builtin-analyses.md - - How to..: - - Write an Analysis: write_analyses.md - # - Modify a StmtGraph: mutable_stmtgraph.md - # - Modify a View: mutable_view.md - # - Implement a BodyInterceptor: body_interceptor.md - # - Implement an AnalysisTool: write_analysis_tool.md + - How to..: + - Write a Dataflow analysis: write_analyses.md + - Incorporate Pointer Analysis: qilin.md + # - Modify a StmtGraph: mutable_stmtgraph.md + # - Modify a View: mutable_view.md + # - Implement a BodyInterceptor: body_interceptor.md + # - Implement an AnalysisTool: write_analysis_tool.md + # - From Prototype to Tool: tool_setup.md - - More information: - - Javadoc: /SootUp/apidocs + - Misc & More information: + - Announcements: announcement.md + - Design Decisions: whatsnew.md + - Migration Help: migrating.md + - Latest Javadoc: /SootUp/apidocs - Troubleshooting & FAQ: faq.md - # - Based on SootUp: tools.md + # - Based on SootUp: tools.md + theme: - palette: - primary: white name: material - logo: ./SootUpLogo.svg - favicon: ./icon.svg + logo: ./img/SootUpLogo.svg + favicon: ./img/icon.svg + palette: + primary: custom + custom_dir: ./docs/overrides features: - navigation.sections +extra_css: + - css/customizetheme.css + - css/hint.min.css + plugins: - tooltips - search - include: src_path: 'sootup.examples/src/test/java/sootup/examples' -extra_css: - - css/hint.min.css - markdown_extensions: - pymdownx.highlight: linenums: true diff --git a/sootup.core/src/main/java/sootup/core/jimple/javabytecode/stmt/JRetStmt.java b/sootup.core/src/main/java/sootup/core/jimple/javabytecode/stmt/JRetStmt.java index d2e1fcc36a7..3a70f99745c 100644 --- a/sootup.core/src/main/java/sootup/core/jimple/javabytecode/stmt/JRetStmt.java +++ b/sootup.core/src/main/java/sootup/core/jimple/javabytecode/stmt/JRetStmt.java @@ -34,8 +34,8 @@ import sootup.core.util.printer.StmtPrinter; /** - * Represents the deprecated JVM ret statement - which is used in JSR Context - which - * is deprecated as well + * Represents the deprecated JVM ret statement (< java 1.6) - which is used in JSR + * Context - which is deprecated as well. */ public final class JRetStmt extends AbstractStmt implements FallsThroughStmt {