fixes for reading core libraries from dex

This commit is contained in:
Julian Dolby 2014-11-18 22:34:42 -05:00
parent 1a4757cf10
commit 97920a4ab9
4 changed files with 104 additions and 183 deletions

View File

@ -120,10 +120,10 @@ public class DexIClass extends BytecodeClass<IClassLoader> {
//computeSuperName() //computeSuperName()
// Set Super Name; // Set Super Name;
String descriptor = classDef.getSuperclass().getTypeDescriptor(); String descriptor = classDef.getSuperclass() != null? classDef.getSuperclass().getTypeDescriptor(): null;
if (descriptor.endsWith(";")) if (descriptor != null && descriptor.endsWith(";"))
descriptor = descriptor.substring(0,descriptor.length()-1); //remove last ';' descriptor = descriptor.substring(0,descriptor.length()-1); //remove last ';'
superName = ImmutableByteArray.make(descriptor); superName = descriptor != null? ImmutableByteArray.make(descriptor): null;
//computeInterfaceNames() //computeInterfaceNames()
// Set interfaceNames // Set interfaceNames
@ -268,8 +268,10 @@ public class DexIClass extends BytecodeClass<IClassLoader> {
ArrayList<IMethod> methodsAL = new ArrayList<IMethod>(); ArrayList<IMethod> methodsAL = new ArrayList<IMethod>();
logger.debug("class: " + classDef.getClassType().getTypeDescriptor()); logger.debug("class: " + classDef.getClassType().getTypeDescriptor());
logger.debug("superclass: " + classDef.getSuperclass().getTypeDescriptor()); if (classDef.getSuperclass() != null){
logger.debug("superclass: " + classDef.getSuperclass().getTypeDescriptor());
}
if (methods == null && classDef.getClassData() == null) if (methods == null && classDef.getClassData() == null)
methods = new IMethod[0]; methods = new IMethod[0];

View File

@ -47,6 +47,8 @@
package com.ibm.wala.dalvik.classLoader; package com.ibm.wala.dalvik.classLoader;
import static com.ibm.wala.classLoader.ClassLoaderImpl.DEBUG_LEVEL;
import java.io.IOException; import java.io.IOException;
import java.util.Collection; import java.util.Collection;
import java.util.HashSet; import java.util.HashSet;
@ -55,7 +57,6 @@ import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.TreeSet; import java.util.TreeSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.ibm.wala.classLoader.ClassLoaderImpl; import com.ibm.wala.classLoader.ClassLoaderImpl;
@ -78,10 +79,11 @@ import com.ibm.wala.util.warnings.Warnings;
* *
*/ */
public class WDexClassLoaderImpl extends ClassLoaderImpl { public class WDexClassLoaderImpl extends ClassLoaderImpl {
private static final Logger logger = LoggerFactory.getLogger(WDexClassLoaderImpl.class); private static final org.slf4j.Logger logger = LoggerFactory.getLogger(WDexClassLoaderImpl.class);
private IClassLoader lParent; private IClassLoader lParent;
private final SetOfClasses exclusions;
//Commented out until IBM fixes ClassLoaderFactoryImpl "protected IClassLoader makeNewClassLoader" //Commented out until IBM fixes ClassLoaderFactoryImpl "protected IClassLoader makeNewClassLoader"
@ -98,7 +100,7 @@ public class WDexClassLoaderImpl extends ClassLoaderImpl {
SetOfClasses exclusions, IClassHierarchy cha) { SetOfClasses exclusions, IClassHierarchy cha) {
super(loader, cha.getScope().getArrayClassLoader(), parent, exclusions, cha); super(loader, cha.getScope().getArrayClassLoader(), parent, exclusions, cha);
lParent = parent; lParent = parent;
// lExclusions = exclusions; this.exclusions = exclusions;
//DEBUG_LEVEL = 0; //DEBUG_LEVEL = 0;
} }
@ -165,7 +167,8 @@ public class WDexClassLoaderImpl extends ClassLoaderImpl {
// Dalvik class // Dalvik class
if (entry instanceof DexModuleEntry) { if (entry instanceof DexModuleEntry) {
DexModuleEntry dexEntry = ((DexModuleEntry) entry); DexModuleEntry dexEntry = ((DexModuleEntry) entry);
TypeName tName = TypeName.string2TypeName(dexEntry.getClassName()); String className = dexEntry.getClassName();
TypeName tName = TypeName.string2TypeName(className);
//if (DEBUG_LEVEL > 0) { //if (DEBUG_LEVEL > 0) {
// System.err.println("Consider dex class: " + tName); // System.err.println("Consider dex class: " + tName);
@ -175,10 +178,10 @@ public class WDexClassLoaderImpl extends ClassLoaderImpl {
//System.out.println(tName.getClassName()); //System.out.println(tName.getClassName());
if (loadedClasses.get(tName) != null) { if (loadedClasses.get(tName) != null) {
Warnings.add(MultipleDexImplementationsWarning Warnings.add(MultipleDexImplementationsWarning
.create(dexEntry.getClassName())); .create(className));
} else if (lParent != null && lParent.lookupClass(tName) != null) { } else if (lParent != null && lParent.lookupClass(tName) != null) {
Warnings.add(MultipleDexImplementationsWarning Warnings.add(MultipleDexImplementationsWarning
.create(dexEntry.getClassName())); .create(className));
} }
//if the class is empty, ie an interface //if the class is empty, ie an interface
// else if (dexEntry.getClassDefItem().getClassData() == null) { // else if (dexEntry.getClassDefItem().getClassData() == null) {
@ -189,10 +192,19 @@ public class WDexClassLoaderImpl extends ClassLoaderImpl {
else { else {
IClass iClass = new DexIClass(this, cha, dexEntry); IClass iClass = new DexIClass(this, cha, dexEntry);
if (iClass.getReference().getName().equals(tName)) { if (iClass.getReference().getName().equals(tName)) {
logger.debug("Load class: " + dexEntry.getClassName());
// className is a descriptor, so strip the 'L'
if (exclusions != null && exclusions.contains(className.substring(1))) {
if (DEBUG_LEVEL > 0) {
System.err.println("Excluding " + className);
}
continue;
}
logger.debug("Load class: " + className);
loadedClasses.put(tName, iClass); loadedClasses.put(tName, iClass);
} else { } else {
Warnings.add(InvalidDexFile.create(dexEntry.getClassName())); Warnings.add(InvalidDexFile.create(className));
} }
} }
} }

View File

@ -78,78 +78,16 @@ public class DexAnalysisScopeReader extends AnalysisScopeReader {
private static final String BASIC_FILE = "./primordial.txt"; // Path inside jar private static final String BASIC_FILE = "./primordial.txt"; // Path inside jar
/** END Custom change: Fixes in AndroidAnalysisScope */ /** END Custom change: Fixes in AndroidAnalysisScope */
public static AnalysisScope makeAndroidBinaryAnalysisScope(String classPath, String exclusionsFile) throws IOException {
if (classPath == null) {
throw new IllegalArgumentException("classPath null");
}
/** BEGIN Custom change: Fixes in AndroidAnalysisScope */
AnalysisScope scope = AnalysisScope.createJavaAnalysisScope();
//AnalysisScope scope = AnalysisScopeReader.makePrimordialScope(null);
scope.setExclusions(new FileOfClasses(new FileInputStream((new FileProvider()).getFile(exclusionsFile))));
ClassLoaderReference loader = scope.getLoader(AnalysisScope.APPLICATION);
/** END Custom change: Fixes in AndroidAnalysisScope */
addClassPathToScope(classPath, scope, loader);
return scope;
}
public static AnalysisScope makeTestAndroidBinaryAnalysisScope(String classPath, String exclusionsFile) throws IOException {
if (classPath == null) {
throw new IllegalArgumentException("classPath null");
}
/** BEGIN Custom change: Fixes in AndroidAnalysisScope */
// AnalysisScope scope = AnalysisScope.createJavaAnalysisScope();
AnalysisScope scope = AnalysisScopeReader.makePrimordialScope((new FileProvider()).getFile(exclusionsFile));
ClassLoaderReference loader = scope.getLoader(AnalysisScope.APPLICATION);
/** END Custom change: Fixes in AndroidAnalysisScope */
addClassPathToScope(classPath, scope, loader);
return scope;
}
/**
* @param classPath
* class path to analyze, delimited by File.pathSeparator
* @param exclusionsFile
* file holding class hierarchy exclusions. may be null
* @throws IOException
* @throws IllegalStateException
* if there are problems reading wala properties
*/
public static AnalysisScope makeAndroidBinaryAnalysisScope( public static AnalysisScope makeAndroidBinaryAnalysisScope(
String classPath, File exclusionsFile) throws IOException { URI classPath,
if (classPath == null) {
throw new IllegalArgumentException("classPath null");
}
/** BEGIN Custom change: Fixes in AndroidAnalysisScope */
AnalysisScope scope = AnalysisScope.createJavaAnalysisScope();
scope.setExclusions(new FileOfClasses(new FileInputStream(exclusionsFile)));
ClassLoaderReference loader = scope.getLoader(AnalysisScope.APPLICATION);
/** END Custom change: Fixes in AndroidAnalysisScope */
addClassPathToScope(classPath, scope, loader);
return scope;
}
public static AnalysisScope makeAndroidBinaryAnalysisScope(
JarFile classPath, File exclusionsFile) throws IOException {
if (classPath == null) {
throw new IllegalArgumentException("classPath null");
}
AnalysisScope scope = AnalysisScopeReader.readJavaScope(BASIC_FILE,
exclusionsFile, WALA_CLASSLOADER);
ClassLoaderReference loader = scope
.getLoader(AnalysisScope.APPLICATION);
scope.addToScope(loader, classPath);
return scope;
}
public static AnalysisScope makeAndroidBinaryAnalysisScope(URI classPath,
String exclusionsFile) throws IOException { String exclusionsFile) throws IOException {
if (classPath == null) { if (classPath == null) {
throw new IllegalArgumentException("classPath null"); throw new IllegalArgumentException("classPath null");
} }
AnalysisScope scope = AnalysisScope.createJavaAnalysisScope(); AnalysisScope scope = AnalysisScopeReader.readJavaScope(BASIC_FILE,
scope.setExclusions(new FileOfClasses(new FileInputStream(exclusionsFile))); new File(exclusionsFile), WALA_CLASSLOADER);
ClassLoaderReference loader = scope.getLoader(AnalysisScope.APPLICATION); ClassLoaderReference loader = scope.getLoader(AnalysisScope.APPLICATION);
final String path = classPath.getPath(); final String path = classPath.getPath();
if (path.endsWith(".jar")) { if (path.endsWith(".jar")) {
scope.addToScope(loader, new JarFile(new File(classPath))); scope.addToScope(loader, new JarFile(new File(classPath)));
@ -163,49 +101,4 @@ public class DexAnalysisScopeReader extends AnalysisScopeReader {
return scope; return scope;
} }
/**
* Handle .apk file.
*
* @param classPath
* @param scope
* @param loader
*/
public static void addClassPathToScope(String classPath,
AnalysisScope scope, ClassLoaderReference loader) {
if (classPath == null) {
throw new IllegalArgumentException("null classPath");
}
try {
String[] paths = classPath.split(File.pathSeparator);
for (int i = 0; i < paths.length; i++) {
if (paths[i].endsWith(".jar")) { // handle jar file
scope.addToScope(loader, new JarFile(paths[i]));
} else if (paths[i].endsWith(".apk")
|| paths[i].endsWith(".dex")) { // Handle android file.
File f = new File(paths[i]);
scope.addToScope(loader, new DexFileModule(f));
} else {
File f = new File(paths[i]);
if (f.isDirectory()) { // handle directory FIXME not working
// for .dex and .apk files into that
// directory
scope.addToScope(loader, new BinaryDirectoryTreeModule(
f));
} else { // handle java class file.
try {
scope.addClassFileToScope(loader, f);
} catch (InvalidClassFileException e) {
throw new IllegalArgumentException(
"Invalid class file");
}
}
}
}
} catch (IOException e) {
Assertions.UNREACHABLE(e.toString());
}
}
} }

View File

@ -10,84 +10,98 @@
package com.ibm.wala.dalvik.util; package com.ibm.wala.dalvik.util;
import java.io.File; import java.io.File;
import java.io.FileInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.net.URI; import java.net.URI;
import java.util.jar.JarFile; import java.util.jar.JarFile;
import java.util.jar.JarInputStream;
import com.ibm.wala.classLoader.JarStreamModule; import com.ibm.wala.classLoader.BinaryDirectoryTreeModule;
import com.ibm.wala.classLoader.Module;
import com.ibm.wala.dalvik.classLoader.DexFileModule; import com.ibm.wala.dalvik.classLoader.DexFileModule;
import com.ibm.wala.dalvik.dex.util.config.DexAnalysisScopeReader;
import com.ibm.wala.ipa.callgraph.AnalysisScope; import com.ibm.wala.ipa.callgraph.AnalysisScope;
import com.ibm.wala.shrikeCT.InvalidClassFileException;
import com.ibm.wala.types.ClassLoaderReference; import com.ibm.wala.types.ClassLoaderReference;
import com.ibm.wala.util.io.FileSuffixes; import com.ibm.wala.util.config.AnalysisScopeReader;
import com.ibm.wala.util.config.FileOfClasses;
import com.ibm.wala.util.debug.Assertions;
import com.ibm.wala.util.io.FileProvider;
public class AndroidAnalysisScope { public class AndroidAnalysisScope {
/** BEGIN Custom change: Fixes in AndroidAnalysisScope */ private static final ClassLoader WALA_CLASSLOADER = AnalysisScopeReader.class.getClassLoader();
public static AnalysisScope setUpAndroidAnalysisScope(String androidLib, String classpath, String exclusions) throws IOException {
private static final String BASIC_FILE = "./primordial.txt";
public static AnalysisScope setUpAndroidAnalysisScope(URI classpath, String exclusions, URI... androidLib) throws IOException {
AnalysisScope scope; AnalysisScope scope;
if (androidLib == null) { if (androidLib == null || androidLib.length == 0) {
scope = DexAnalysisScopeReader.makeTestAndroidBinaryAnalysisScope(classpath, exclusions); scope = AnalysisScopeReader.readJavaScope(BASIC_FILE, new File(exclusions), WALA_CLASSLOADER);
} else { } else {
scope = DexAnalysisScopeReader.makeAndroidBinaryAnalysisScope(classpath, exclusions); scope = AnalysisScope.createJavaAnalysisScope();
}
setUpAnalysisScope(scope, androidLib==null? null: new File(androidLib).toURI());
return scope;
}
/** END Custom change: Fixes in AndroidAnalysisScope */
public static AnalysisScope setUpAndroidAnalysisScope(URI androidLib, URI classpath, String exclusions) throws IOException { File exclusionsFile = new File(exclusions);
AnalysisScope scope = DexAnalysisScopeReader.makeAndroidBinaryAnalysisScope(classpath, exclusions); InputStream fs = exclusionsFile.exists()? new FileInputStream(exclusionsFile): FileProvider.class.getClassLoader().getResourceAsStream(exclusionsFile.getName());
setUpAnalysisScope(scope, androidLib); scope.setExclusions(new FileOfClasses(fs));
return scope;
} scope.setLoaderImpl(ClassLoaderReference.Primordial,
"com.ibm.wala.dalvik.classLoader.WDexClassLoaderImpl");
private static void setUpAnalysisScope(AnalysisScope scope, URI androidLib) throws IOException {
for(URI al : androidLib) {
scope.addToScope(ClassLoaderReference.Primordial, new DexFileModule(new File(al)));
}
}
scope.setLoaderImpl(ClassLoaderReference.Application, scope.setLoaderImpl(ClassLoaderReference.Application,
"com.ibm.wala.dalvik.classLoader.WDexClassLoaderImpl"); "com.ibm.wala.dalvik.classLoader.WDexClassLoaderImpl");
if (androidLib != null) { scope.addToScope(ClassLoaderReference.Application, new DexFileModule(new File(classpath)));
if (FileSuffixes.isDexFile(androidLib)) {
return scope;
/** END Custom change: Fixes in AndroidAnalysisScope */ }
Module dexMod = new DexFileModule(new File(androidLib));
/**
// Iterator<ModuleEntry> mitr = dexMod.getEntries(); * Handle .apk file.
// while (mitr.hasNext()) { *
// ModuleEntry moduleEntry = (ModuleEntry) mitr.next(); * @param classPath
// logger.error("dex module: {}", moduleEntry.getName()); * @param scope
// } * @param loader
*/
public static void addClassPathToScope(String classPath,
AnalysisScope scope, ClassLoaderReference loader) {
if (classPath == null) {
throw new IllegalArgumentException("null classPath");
}
try {
String[] paths = classPath.split(File.pathSeparator);
scope.setLoaderImpl(ClassLoaderReference.Primordial, for (int i = 0; i < paths.length; i++) {
"com.ibm.wala.dalvik.classLoader.WDexClassLoaderImpl"); if (paths[i].endsWith(".jar")) { // handle jar file
scope.addToScope(loader, new JarFile(paths[i]));
} else if (paths[i].endsWith(".apk")
|| paths[i].endsWith(".dex")) { // Handle android file.
File f = new File(paths[i]);
scope.addToScope(loader, new DexFileModule(f));
} else {
File f = new File(paths[i]);
if (f.isDirectory()) { // handle directory FIXME not working
// for .dex and .apk files into that
// directory
scope.addToScope(loader, new BinaryDirectoryTreeModule(
f));
} else { // handle java class file.
try {
scope.addClassFileToScope(loader, f);
} catch (InvalidClassFileException e) {
throw new IllegalArgumentException(
"Invalid class file");
}
}
}
}
scope.addToScope(ClassLoaderReference.Primordial, dexMod); } catch (IOException e) {
} else { Assertions.UNREACHABLE(e.toString());
/** BEGIN Custom change: Fixes in AndroidAnalysisScope */
if (FileSuffixes.isRessourceFromJar(androidLib)) {
scope.setLoaderImpl(ClassLoaderReference.Primordial,
"com.ibm.wala.dalvik.classLoader.WDexClassLoaderImpl");
//final FileProvider fileProvider = new FileProvider();
final InputStream is = androidLib.toURL().openStream();
assert (is != null);
final Module libMod = new JarStreamModule(new JarInputStream(is));
scope.addToScope(ClassLoaderReference.Primordial, libMod);
//throw new UnsupportedOperationException("Cannot extract lib from jar");
} else {
// assume it is really a JVML jar file, not Android at all
scope.addToScope(ClassLoaderReference.Primordial, new JarFile(new File(
androidLib)));
}
/** END Custom change: Fixes in AndroidAnalysisScope */
} }
} }
}
} }