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

View File

@ -47,6 +47,8 @@
package com.ibm.wala.dalvik.classLoader;
import static com.ibm.wala.classLoader.ClassLoaderImpl.DEBUG_LEVEL;
import java.io.IOException;
import java.util.Collection;
import java.util.HashSet;
@ -55,7 +57,6 @@ import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.ibm.wala.classLoader.ClassLoaderImpl;
@ -78,10 +79,11 @@ import com.ibm.wala.util.warnings.Warnings;
*
*/
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 final SetOfClasses exclusions;
//Commented out until IBM fixes ClassLoaderFactoryImpl "protected IClassLoader makeNewClassLoader"
@ -98,7 +100,7 @@ public class WDexClassLoaderImpl extends ClassLoaderImpl {
SetOfClasses exclusions, IClassHierarchy cha) {
super(loader, cha.getScope().getArrayClassLoader(), parent, exclusions, cha);
lParent = parent;
// lExclusions = exclusions;
this.exclusions = exclusions;
//DEBUG_LEVEL = 0;
}
@ -165,7 +167,8 @@ public class WDexClassLoaderImpl extends ClassLoaderImpl {
// Dalvik class
if (entry instanceof DexModuleEntry) {
DexModuleEntry dexEntry = ((DexModuleEntry) entry);
TypeName tName = TypeName.string2TypeName(dexEntry.getClassName());
String className = dexEntry.getClassName();
TypeName tName = TypeName.string2TypeName(className);
//if (DEBUG_LEVEL > 0) {
// System.err.println("Consider dex class: " + tName);
@ -175,10 +178,10 @@ public class WDexClassLoaderImpl extends ClassLoaderImpl {
//System.out.println(tName.getClassName());
if (loadedClasses.get(tName) != null) {
Warnings.add(MultipleDexImplementationsWarning
.create(dexEntry.getClassName()));
.create(className));
} else if (lParent != null && lParent.lookupClass(tName) != null) {
Warnings.add(MultipleDexImplementationsWarning
.create(dexEntry.getClassName()));
.create(className));
}
//if the class is empty, ie an interface
// else if (dexEntry.getClassDefItem().getClassData() == null) {
@ -189,10 +192,19 @@ public class WDexClassLoaderImpl extends ClassLoaderImpl {
else {
IClass iClass = new DexIClass(this, cha, dexEntry);
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);
} 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
/** 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(
String classPath, File exclusionsFile) throws IOException {
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,
URI classPath,
String exclusionsFile) throws IOException {
if (classPath == null) {
throw new IllegalArgumentException("classPath null");
}
AnalysisScope scope = AnalysisScope.createJavaAnalysisScope();
scope.setExclusions(new FileOfClasses(new FileInputStream(exclusionsFile)));
AnalysisScope scope = AnalysisScopeReader.readJavaScope(BASIC_FILE,
new File(exclusionsFile), WALA_CLASSLOADER);
ClassLoaderReference loader = scope.getLoader(AnalysisScope.APPLICATION);
final String path = classPath.getPath();
if (path.endsWith(".jar")) {
scope.addToScope(loader, new JarFile(new File(classPath)));
@ -163,49 +101,4 @@ public class DexAnalysisScopeReader extends AnalysisScopeReader {
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;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.jar.JarFile;
import java.util.jar.JarInputStream;
import com.ibm.wala.classLoader.JarStreamModule;
import com.ibm.wala.classLoader.Module;
import com.ibm.wala.classLoader.BinaryDirectoryTreeModule;
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.shrikeCT.InvalidClassFileException;
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 {
/** BEGIN Custom change: Fixes in AndroidAnalysisScope */
public static AnalysisScope setUpAndroidAnalysisScope(String androidLib, String classpath, String exclusions) throws IOException {
private static final ClassLoader WALA_CLASSLOADER = AnalysisScopeReader.class.getClassLoader();
private static final String BASIC_FILE = "./primordial.txt";
public static AnalysisScope setUpAndroidAnalysisScope(URI classpath, String exclusions, URI... androidLib) throws IOException {
AnalysisScope scope;
if (androidLib == null) {
scope = DexAnalysisScopeReader.makeTestAndroidBinaryAnalysisScope(classpath, exclusions);
if (androidLib == null || androidLib.length == 0) {
scope = AnalysisScopeReader.readJavaScope(BASIC_FILE, new File(exclusions), WALA_CLASSLOADER);
} else {
scope = DexAnalysisScopeReader.makeAndroidBinaryAnalysisScope(classpath, exclusions);
}
setUpAnalysisScope(scope, androidLib==null? null: new File(androidLib).toURI());
return scope;
}
/** END Custom change: Fixes in AndroidAnalysisScope */
scope = AnalysisScope.createJavaAnalysisScope();
public static AnalysisScope setUpAndroidAnalysisScope(URI androidLib, URI classpath, String exclusions) throws IOException {
AnalysisScope scope = DexAnalysisScopeReader.makeAndroidBinaryAnalysisScope(classpath, exclusions);
setUpAnalysisScope(scope, androidLib);
return scope;
}
private static void setUpAnalysisScope(AnalysisScope scope, URI androidLib) throws IOException {
File exclusionsFile = new File(exclusions);
InputStream fs = exclusionsFile.exists()? new FileInputStream(exclusionsFile): FileProvider.class.getClassLoader().getResourceAsStream(exclusionsFile.getName());
scope.setExclusions(new FileOfClasses(fs));
scope.setLoaderImpl(ClassLoaderReference.Primordial,
"com.ibm.wala.dalvik.classLoader.WDexClassLoaderImpl");
for(URI al : androidLib) {
scope.addToScope(ClassLoaderReference.Primordial, new DexFileModule(new File(al)));
}
}
scope.setLoaderImpl(ClassLoaderReference.Application,
"com.ibm.wala.dalvik.classLoader.WDexClassLoaderImpl");
if (androidLib != null) {
if (FileSuffixes.isDexFile(androidLib)) {
/** END Custom change: Fixes in AndroidAnalysisScope */
Module dexMod = new DexFileModule(new File(androidLib));
// Iterator<ModuleEntry> mitr = dexMod.getEntries();
// while (mitr.hasNext()) {
// ModuleEntry moduleEntry = (ModuleEntry) mitr.next();
// logger.error("dex module: {}", moduleEntry.getName());
// }
scope.addToScope(ClassLoaderReference.Application, new DexFileModule(new File(classpath)));
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);
scope.setLoaderImpl(ClassLoaderReference.Primordial,
"com.ibm.wala.dalvik.classLoader.WDexClassLoaderImpl");
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");
}
}
}
}
scope.addToScope(ClassLoaderReference.Primordial, dexMod);
} else {
/** 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 */
} catch (IOException e) {
Assertions.UNREACHABLE(e.toString());
}
}
}
}