Skip to content

Commit

Permalink
New -android-jars and -force-android-jar options to select Android AP…
Browse files Browse the repository at this point in the history
…I versions when analyzing Android applications
  • Loading branch information
Alexandre-Bartel committed Jul 15, 2012
1 parent d489cb6 commit 237aebd
Show file tree
Hide file tree
Showing 9 changed files with 304 additions and 3 deletions.
2 changes: 2 additions & 0 deletions ant.settings.template
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,5 @@ release.loc=lib
## javadoc comments.
javaapi.url=http://java.sun.com/j2se/1.5.0/docs/api/

# AXMLPrinter2.jar
axmlprinter2.jar=./libs/AXMLPrinter2.jar
1 change: 1 addition & 0 deletions build.xml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
<pathelement location="classes"/>
<pathelement location="${polyglot.jar}"/>
<pathelement location="${jasmin.jar}"/>
<pathelement location="${axmlprinter2.jar}"/>
</classpath>
<src path="src"/>
<src path="generated/singletons"/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2093,6 +2093,24 @@ private boolean createNewConfig() {
getConfig().put(getInput_Optionsprocess_dir_widget().getAlias(), stringRes);
}

stringRes = getInput_Optionsandroid_jars_widget().getText().getText();

defStringRes = "";


if ( (!(stringRes.equals(defStringRes))) && (stringRes != null) && (stringRes.length() != 0)) {
getConfig().put(getInput_Optionsandroid_jars_widget().getAlias(), stringRes);
}

stringRes = getInput_Optionsforce_android_jar_widget().getText().getText();

defStringRes = "";


if ( (!(stringRes.equals(defStringRes))) && (stringRes != null) && (stringRes.length() != 0)) {
getConfig().put(getInput_Optionsforce_android_jar_widget().getAlias(), stringRes);
}

stringRes = getInput_Optionsmain_class_widget().getText().getText();

defStringRes = "";
Expand Down Expand Up @@ -6572,6 +6590,30 @@ public StringOptionWidget getInput_Optionssoot_classpath_widget() {



private StringOptionWidget Input_Optionsandroid_jars_widget;

private void setInput_Optionsandroid_jars_widget(StringOptionWidget widget) {
Input_Optionsandroid_jars_widget = widget;
}

public StringOptionWidget getInput_Optionsandroid_jars_widget() {
return Input_Optionsandroid_jars_widget;
}



private StringOptionWidget Input_Optionsforce_android_jar_widget;

private void setInput_Optionsforce_android_jar_widget(StringOptionWidget widget) {
Input_Optionsforce_android_jar_widget = widget;
}

public StringOptionWidget getInput_Optionsforce_android_jar_widget() {
return Input_Optionsforce_android_jar_widget;
}



private StringOptionWidget Input_Optionsmain_class_widget;

private void setInput_Optionsmain_class_widget(StringOptionWidget widget) {
Expand Down Expand Up @@ -10285,6 +10327,36 @@ private Composite Input_OptionsCreate(Composite parent) {
setInput_Optionssoot_classpath_widget(new StringOptionWidget(editGroupInput_Options, SWT.NONE, new OptionData("Soot Classpath", "", "","cp", "\nUse PATH as the list of directories in which Soot should search \nfor classes. PATH should be a series of directories, separated \nby the path separator character for your system. If no classpath \nis set on the command line, but the system property \nsoot.class.path has been set, Soot uses its value as the \nclasspath. If neither the command line nor the system properties \nspecify a Soot classpath, Soot falls back on a default classpath \nconsisting of the value of the system property java.class.path \nfollowed java.home/lib/rt.jar, where java.home stands for the \ncontents of the system property java.home and / stands for the \nsystem file separator.", defaultString)));


defKey = ""+" "+""+" "+"android-jars";
defKey = defKey.trim();

if (isInDefList(defKey)) {
defaultString = getStringDef(defKey);
}
else {

defaultString = "";

}

setInput_Optionsandroid_jars_widget(new StringOptionWidget(editGroupInput_Options, SWT.NONE, new OptionData("Path to Android jar files", "", "","android-jars", "\nUse PATH as the directory in which Soot should search for the \nappropriate android.jar file to use. The directory must contain \nsubdirectories named after the Android SDK version. Those \nsubdirectories must each contain one android.jar file. For \ninstance if the target directory is \n/home/user/androidSDK/platforms/ subdirectories containing \nandroid.jar for Android SDK 8 and 13 must be named android-8/ \nand android-13/ respectively. Note, that this options requires \nthat only one Android application is analyzed at a time. The \nAndroid application must contain the AndroidManifest.xml file. \n ", defaultString)));


defKey = ""+" "+""+" "+"force-android-jar";
defKey = defKey.trim();

if (isInDefList(defKey)) {
defaultString = getStringDef(defKey);
}
else {

defaultString = "";

}

setInput_Optionsforce_android_jar_widget(new StringOptionWidget(editGroupInput_Options, SWT.NONE, new OptionData("Force specific Android jar file", "", "","force-android-jar", "\nUse PATH as the path to the android.jar file Soot should use. \nThis option overrides the "android-jars" option. ", defaultString)));


defKey = ""+" "+""+" "+"main-class";
defKey = defKey.trim();

Expand Down
10 changes: 10 additions & 0 deletions generated/options/soot/AntTask.java
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,16 @@ public void setoaat(boolean arg) {
if(arg) addArg("-oaat");
}

public void setandroid_jars(String arg) {
addArg("-android-jars");
addArg(arg);
}

public void setforce_android_jar(String arg) {
addArg("-force-android-jar");
addArg(arg);
}

public void setast_metrics(boolean arg) {
if(arg) addArg("-ast-metrics");
}
Expand Down
42 changes: 42 additions & 0 deletions generated/options/soot/options/Options.java
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,40 @@ else if( false
)
oaat = true;

else if( false
|| option.equals( "android-jars" )
) {
if( !hasMoreOptions() ) {
G.v().out.println( "No value given for option -"+option );
return false;
}
String value = nextOption();

if( android_jars.length() == 0 )
android_jars = value;
else {
G.v().out.println( "Duplicate values "+android_jars+" and "+value+" for option -"+option );
return false;
}
}

else if( false
|| option.equals( "force-android-jar" )
) {
if( !hasMoreOptions() ) {
G.v().out.println( "No value given for option -"+option );
return false;
}
String value = nextOption();

if( force_android_jar.length() == 0 )
force_android_jar = value;
else {
G.v().out.println( "Duplicate values "+force_android_jar+" and "+value+" for option -"+option );
return false;
}
}

else if( false
|| option.equals( "ast-metrics" )
)
Expand Down Expand Up @@ -997,6 +1031,12 @@ public List process_dir() {
private boolean oaat = false;
public void set_oaat( boolean setting ) { oaat = setting; }

public String android_jars() { return android_jars; }
public void set_android_jars( String setting ) { android_jars = setting; }
private String android_jars = "";
public String force_android_jar() { return force_android_jar; }
public void set_force_android_jar( String setting ) { force_android_jar = setting; }
private String force_android_jar = "";
public boolean ast_metrics() { return ast_metrics; }
private boolean ast_metrics = false;
public void set_ast_metrics( boolean setting ) { ast_metrics = setting; }
Expand Down Expand Up @@ -1186,6 +1226,8 @@ public String getUsage() {
+padOpt(" -pp -prepend-classpath", "Prepend the given soot classpath to the default classpath." )
+padOpt(" -process-path DIR -process-dir DIR", "Process all classes found in DIR" )
+padOpt(" -oaat", "From the process-dir, processes one class at a time." )
+padOpt(" -android-jars PATH", "Use PATH as the path for finding the android.jar file" )
+padOpt(" -force-android-jar PATH", "Force Soot to use PATH as the path for the android.jar file." )
+padOpt(" -ast-metrics", "Compute AST Metrics if performing java to jimple" )
+padOpt(" -src-prec FORMAT", "Sets source precedence to FORMAT files" )
+padVal(" c class (default)", "Favour class files as Soot source" )
Expand Down
2 changes: 1 addition & 1 deletion generated/options/soot/options/SparkOptions.java
Original file line number Diff line number Diff line change
Expand Up @@ -536,7 +536,7 @@ public String geom_dump_verbose() {
* If you want to compare the precision of the points-to
* results with other solvers (e.g. Paddle), you can use the
* "verify-file" to specify the list of methods (soot method
* 'verify-file' to specify the list of methods (soot method
* signature format) that are reachable by that solver. Then, in
* the internal evaluations (see the switch geom-eval), we only
* consider the methods that are present to both solvers.
Expand Down
Binary file added libs/AXMLPrinter2.jar
Binary file not shown.
149 changes: 147 additions & 2 deletions src/soot/Scene.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
Expand All @@ -39,6 +41,8 @@
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import soot.jimple.toolkits.callgraph.CallGraph;
import soot.jimple.toolkits.callgraph.ContextSensitiveCallGraph;
Expand All @@ -58,6 +62,10 @@
import soot.util.SingletonList;
import soot.util.StringNumberer;

import org.xmlpull.v1.XmlPullParser;
import android.content.res.AXmlResourceParser;
import test.AXMLPrinter;

/** Manages the SootClasses of the application being analyzed. */
public class Scene //extends AbstractHost
{
Expand Down Expand Up @@ -223,9 +231,112 @@ public String getSootClassPath()
}
}



return sootClassPath;
}


public String getAndroidJarPath (String jars, String apk) {
File jarsF = new File (jars);
File apkF = new File (apk);

int APIVersion = -1;
String jarPath = "";

if (!jarsF.exists())
throw new RuntimeException("file '"+ jars +"' does not exist!");

if (!apkF.exists())
throw new RuntimeException("file '"+ apk +"' does not exist!");

// get AndroidManifest
InputStream manifestIS = null;
try {
ZipFile archive = new ZipFile (apkF);
for (Enumeration entries = archive.entries(); entries.hasMoreElements(); ) {
ZipEntry entry = (ZipEntry) entries.nextElement();
String entryName = entry.getName();
// We are dealing with the Android manifest
if (entryName.equals("AndroidManifest.xml")) {
manifestIS = archive.getInputStream (entry);
break;
}
}
} catch(Exception e) {
throw new RuntimeException ("Error when looking for manifest in apk: "+ e);
}
if (manifestIS == null)
throw new RuntimeException ("Android manifest not found in apk ("+ apkF +")");


// process AndroidManifest.xml
int sdkTargetVersion = -1;
int minSdkVersion = -1;
int defaultSdkVersion = 15;
try {
AXmlResourceParser parser=new AXmlResourceParser();
parser.open(manifestIS);
StringBuilder indent=new StringBuilder(10);
final String indentStep=" ";
int depth = 0;
while (true) {
int type=parser.next();
if (type==XmlPullParser.END_DOCUMENT) {
//throw new RuntimeException ("target sdk version not found in Android manifest ("+ apkF +")");
break;
}
switch (type) {
case XmlPullParser.START_DOCUMENT:
{
break;
}
case XmlPullParser.START_TAG:
{
depth++;
String tagName = parser.getName();
if (depth == 2 && tagName.equals("uses-sdk")) {
for (int i=0;i!=parser.getAttributeCount();++i) {
String attributeName = parser.getAttributeName (i);
String attributeValue = AXMLPrinter.getAttributeValue(parser,i);
if (attributeName.equals("targetSdkVersion")) {
sdkTargetVersion = Integer.parseInt (attributeValue);
} else if (attributeName.equals("minSdkVersion")) {
minSdkVersion = Integer.parseInt (attributeValue);
}
}
}
break;
}
case XmlPullParser.END_TAG:
depth--;
break;
case XmlPullParser.TEXT:
break;
}
}
}
catch (Exception e) {
e.printStackTrace();
}

if (sdkTargetVersion != -1) {
APIVersion = sdkTargetVersion;
} else if (minSdkVersion != -1) {
if (minSdkVersion <= 2)
minSdkVersion = 3;
APIVersion = minSdkVersion;
} else {
G.v().out.println ("Could not find sdk version in Android manifest! Using default.");
APIVersion = defaultSdkVersion;
}

// get path to appropriate android.jar
jarPath = jars + File.separator + "android-" + APIVersion + File.separator + "android.jar";

return jarPath;

}

public String defaultClassPath() {
StringBuffer sb = new StringBuffer();
sb.append(System.getProperty("java.class.path")+File.pathSeparator);
Expand Down Expand Up @@ -265,8 +376,42 @@ public String defaultClassPath() {
sb.append(File.pathSeparator+
System.getProperty("java.home")+File.separator+"lib"+File.separator+"jce.jar");
}

String defaultClassPath = sb.toString();

return sb.toString();
if (Options.v().src_prec() == Options.src_prec_apk) {
// check that android.jar is not in classpath
if (!defaultClassPath.contains ("android.jar")) {
String androidJars = Options.v().android_jars();
String forceAndroidJar = Options.v().force_android_jar();
if (androidJars.equals("") && forceAndroidJar.equals("")) {
throw new RuntimeException("You are analyzing an Android application but did not define android.jar. Options -android-jars or -force-android-jar should be used.");
}

String jarPath = "";
if (!forceAndroidJar.equals("")) {
jarPath = forceAndroidJar;
} else if (!androidJars.equals("")) {
Collection<String> targetApks = Options.v().process_dir();
if (targetApks.size() == 0 || targetApks.size() > 1)
throw new RuntimeException("only one Android application can be analyzed when using option -android-jars.");
jarPath = getAndroidJarPath (androidJars, (String)targetApks.toArray()[0]);
}
if (jarPath.equals(""))
throw new RuntimeException("android.jar not found.");
File f = new File (jarPath);
if (!f.exists())
throw new RuntimeException("file '"+ jarPath +"' does not exist!");
else
G.v().out.println("Using '"+ jarPath +"' as android.jar");
defaultClassPath += File.pathSeparator + jarPath;

} else {
G.v().out.println("warning: defaultClassPath contains android.jar! Options -android-jars and -force-android-jar are ignored!");
}
}

return defaultClassPath;
}


Expand Down
Loading

0 comments on commit 237aebd

Please sign in to comment.