CS 201 Project

Handed Out: Oct 26, 2018
Due: Nov 26, 2018
Grade Weight: 30% of total course grade
This assignment can be done individually, or in a group of two.


Project Description

The goal of this project is to understand and implement the basic program analysis and instrumentation techniques. In this project, you are required to implement the followings:
  1. Intra-procedural live variable analysis: Live variable analysis is a backward may/union data flow analysis. A variable X is live at point p if there exists a X-clear path from p to a use of X.
  2. Profiling:
    1. Basic Block profiling: Basic block profiling collects the execution frequency of each basic block executed during a specific program run.
    2. Edge profiling: Edge profiling collects the execution frequency of each control-flow edge executed during a specific program run.
  3. Average number of variables live at an executed instruction:: $$ \sum_{i=1}^n {\textrm{(Execution frequency for instruction } i \times {\textrm{Number of live variables at the entry point of instruction } i)}} \over \textrm{Total number of instructions executed}$$
You will carry out this project as follows:
  1. Parse the input file, collect the control flow information and output the live variable analysis results.
  2. Instrument the code to find the execution frequency of each basic block and control flow edge.
  3. Run the instrumented code and output the profiling results.
More details about the languages, tools, output requirements and submission format can be found in the following:

Soot

Soot is a Java optimization framework which is used to analyze, instrument, optimize and visualize Java programs. More detailed information can be found in The Soot framework for Java program analysis: a retrospective paper. Soot can process code from Java sources and produce (possibly transformed/instrumented/optimized) code in the following output formats: Below is an example of a simple Java program, and the corresponding Soot Jimple IR.

An unconventional hello world in Java

public class HelloWorld {

	public static void main(String[] args) {		
		int x=10;
		System.out.println("Hello World");
	}

}

The Corresponding Jimple IR

    public static void main(java.lang.String[])
    {
        java.lang.String[] args;
        int x;
        java.io.PrintStream temp$0;

        args := @parameter0: java.lang.String[];
        x = 10;
        temp$0 = ;
        virtualinvoke temp$0.("Hello World");
        return;
    }

    public void ()
    {
        HelloWorld this;

        this := @this: HelloWorld;
        specialinvoke this.()>();
        return;
    }

Getting Started with soot

The pre-requisites for working with Soot are as follows:
  1. Familiarity with Java: The Java Tutorials
  2. Familiarity with Eclipse: Eclipse Homepage
  3. On-demand faimilarity with Soot: Tutorials for Soot
  4. Familiarity with compiler terminology like BasicBlocks etc.
You can find useful info about Soot in the following links:
  1. Soot mailing list
  2. Master's thesis describing Soot
  3. Sample Soot programs

Program Analysis and Profiling Using Soot: Setup and Program Template

The following instructions will help you setup your computer for this project.
Important Note: (These instructions have been tested and verified on Ubuntu 14.04 LTS. In these instructions, Soot has been used as the Eclipse plugin.
You are still free to use Soot as a command-line tool or you can use any other versions of Soot/Java but your submission README file MUST contain complete information and instructions for compiling your code and running it. Please see Submission section.)
  1. Install JDK 7 (Works better for Soot Dava Decompile) and JDK 8 (Works better for Soot instrumentation and analysis) on your computer if you do not have them.
  2. Install Eclipse Kepler on your computer if you do not have it.
  3. Open Eclipse. Select Help -> Install New Software -> In Work with: type the following link: "http://www.sable.mcgill.ca/soot/eclipse/updates/" -> Select Add -> In Location type the same link -> Select OK -> Select the Soot package -> Select Next -> Select Next -> Select "I accept the terms..." -> Select Finish and then Eclipse will be reinstalled.
  4. Extract this sample project and import it to Eclipse (Select File -> Import -> select "Existing Projects into Workspace" -> Select Next -> For root directory, select the extracted folder CS201Fall18 -> Select Finish.
  5. Add one of the following Soot jar files to your project (Right click on your project and select Properties -> Select Java Build Path -> Select Libraries -> Select Add External JARs -> Select the downloaded jar file -> Select OK -> Select OK)
    1. soot-2.5.0.jar or
    2. (In case if you use Java 7. Hence, you should select Java 7 as your JRE System Library in Eclipse (Right click on your project and select Properties -> Select Java Build Path -> Select Libraries -> Select JRE System Library -> In Alternative JRE, choose Installed JREs, select java-7-openjdk. If you do not have any Installed JRE listed, click Add and add a Standard VM by navigating to your JRE directory))
    3. sootclasses-trunk-jar-with-dependencies.jar
    4. (In case if you use Java 8. Hence, you should select Java 8 as your JRE System Library in Eclipse (Right click on your project and select Properties -> Select Java Build Path -> Select Libraries -> Select JRE System Library -> In Alternative JRE, choose Installed JREs, select java-8-openjdk. If you do not have any Installed JRE listed, click Add and add a Standard VM by navigating to your JRE directory))
  6. Add the Analysis Folder to the soot –process-dir (Right click on the Main.java class -> Select Run as -> Select Run Configurations -> Select Arguments -> In Program arguments type -allow-phantom-refs -process-dir /your/Analysis/folder/path/in/your/project/directory/) -> Select Apply
  7. Fill in the details for staticAnalysis() and dynamicAnalysis() methods and run your program.
  8. Your instrumented .jimple file (e.g., Test1.jimple) will be written to sootOutput/Test1.jimple.
  9. In Eclipse, right click on Test1.jimple -> Select Soot -> Select Dava Decompile App to create the instrumented java file. (At this step you might get some errors if you are using Java 8, so it is recommended to set your Java to Java 7 for this step)
  10. Your instrumented .java file (e.g., Test1.java) will be written to sootOutput/dava/src/Test1.java.
  11. Run the instrumented Test1.java to print the dynamic analysis outputs.

Output Requirements

Instrumented programs should output the number of times each Basic Block and Edge was executed during the run of the program. Since there are many reasonable ways this can be done, we are going to leave the specifics up to you. There are however, some broad requirements.

The output requirements are as follows: First, you need to report the intra-procedural liveness variable analysis results. This way, we will be able to identify whether or not you have identified the correct live variables at each point. If these can't be determined from your output, your score will be penalized accordingly. Second, you instrument the code to gather basic block and edge profiles. Third, using the Basic Blocks execution frequencies results (accordingly instructions execution frequencies) and live variables analysis results, find out the average number of variables live at an executed instruction using the mentioned formula.


Here is an example of a Java class that we might want to analyze:

Example Java Class

public class Test1 {

	public static void main(String[] args) {		
		int a = 0;
		int b = 95;
		func1(a);	
		func1(b);	
	}
	
	public static void func1 (int x) {
		if(x != 0){
		  while(x % 4 != 0){
		    x = x/4;
		  }
		}
	}
	
}

Example CFG Output

Method:<Test1: void main(java.lang.String[])>
BB0:
args := @parameter0: java.lang.String[]
a = 0
b = 95
staticinvoke <Test1: void func1(int)>(a)
staticinvoke <Test1: void func1(int)>(b)
return

Method:<Test1: void func1(int)>
BB0:
x := @parameter0: int
if x != 0 goto nop

BB1:
goto [?= nop]

BB2:
nop

BB3:
nop
temp$0 = x % 4
if temp$0 != 0 goto nop

BB4:
goto [?= nop]

BB5:
nop
temp$1 = x / 4
x = temp$1
goto [?= nop]

BB6:
nop

BB7:
nop
return

Method:<Test1: void <init>()>
BB0:
this := @this: Test1
specialinvoke this.<java.lang.Object: void <init>()>()
return

Example Intra-Procedural Liveness Variable Analysis Output

Method:<Test1: void main(java.lang.String[])>
args := @parameter0: java.lang.String[].	[entry: ]	[exit: ]
a = 0...................................	[entry: ]	[exit: a ]
b = 95..................................	[entry: a ]	[exit: b a ]
staticinvoke <Test1: void func1(int)>(a)	[entry: b a ]	[exit: b ]
staticinvoke <Test1: void func1(int)>(b)	[entry: b ]	[exit: ]
return..................................	[entry: ]	[exit: ]

Method:<Test1: void func1(int)>
x := @parameter0: int...................	[entry: ]	[exit: x ]
if x != 0 goto nop......................	[entry: x ]	[exit: x ]
goto [?= nop]...........................	[entry: ]	[exit: ]
nop.....................................	[entry: x ]	[exit: x ]
nop.....................................	[entry: x ]	[exit: x ]
temp$0 = x % 4..........................	[entry: x ]	[exit: x temp$0 ]
if temp$0 != 0 goto nop.................	[entry: x temp$0 ]	[exit: x ]
goto [?= nop]...........................	[entry: ]	[exit: ]
nop.....................................	[entry: x ]	[exit: x ]
temp$1 = x / 4..........................	[entry: x ]	[exit: temp$1 ]
x = temp$1..............................	[entry: temp$1 ]	[exit: x ]
goto [?= nop]...........................	[entry: x ]	[exit: x ]
nop.....................................	[entry: ]	[exit: ]
nop.....................................	[entry: ]	[exit: ]
return..................................	[entry: ]	[exit: ]

Example Output of Profiled Program

BASIC BLOCK PROFILING:
Method:<Test1: void main(java.lang.String[])>
BB0: 1

Method:<Test1: void func1(int)>
BB0: 2
BB1: 1
BB2: 1
BB3: 5
BB4: 1
BB5: 4
BB6: 1
BB7: 2


EDGE PROFILING:
Method:<Test1: void func1(int)>
BB0 -> BB1: 1
BB0 -> BB2: 1
BB1 -> BB7: 1
BB2 -> BB3: 1
BB3 -> BB4: 1
BB3 -> BB5: 4
BB4 -> BB6: 1
BB5 -> BB3: 4
BB6 -> BB7: 1


AVERAGE NUMBER OF VARIABLES LIVE AT AN EXECUTED INSTRUCTION:
Method:<Test1: void main(java.lang.String[])>
0.66

Method:<Test1: void func1(int)>
0.90


Example Java Programs for Testing

Additional Java programs that you can use to test your code can be found in the Analysis directory of the project folder.

Submission

The submission should be a tar file named 'username1_username2.tar' (where 'username' is your CSE account username) emailed to the TA, Arash Alavi aalav003@ucr.edu. Also include the Name and Student-ID of each member of your submission group in your submission email. The tar file MUST contain:
  1. The finished CS201Fall18/, similar to the one that you downloaded and used to complete this assignment.
  2. The folder extracted from your submission should work as described above in Program Analysis and Profiling Using Soot: Setup and Program Template.
  3. A README listing the Name, Email and Student ID of each member of the group. Your README MUST also contain instructions for compiling your code and running it on an arbitrary Java program.

Reporting problems

Please read this document in its entirety before you email the TA: aalav003@ucr.edu.