java annotations support for dalvik
This commit is contained in:
parent
3cd36c904b
commit
de26484098
|
@ -13,22 +13,17 @@ package com.ibm.wala.core.tests.ir;
|
|||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.ibm.wala.classLoader.BytecodeClass;
|
||||
import com.ibm.wala.classLoader.IBytecodeMethod;
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.classLoader.IField;
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.classLoader.ShrikeCTMethod;
|
||||
import com.ibm.wala.classLoader.ShrikeClass;
|
||||
import com.ibm.wala.core.tests.callGraph.CallGraphTestUtil;
|
||||
import com.ibm.wala.core.tests.util.TestConstants;
|
||||
import com.ibm.wala.core.tests.util.WalaTestCase;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisScope;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchyException;
|
||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||
import com.ibm.wala.shrikeCT.InvalidClassFileException;
|
||||
|
@ -39,30 +34,13 @@ import com.ibm.wala.types.Selector;
|
|||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.types.annotations.Annotation;
|
||||
import com.ibm.wala.util.collections.HashSetFactory;
|
||||
import com.ibm.wala.util.config.AnalysisScopeReader;
|
||||
import com.ibm.wala.util.io.FileProvider;
|
||||
import com.ibm.wala.util.collections.Pair;
|
||||
import com.ibm.wala.util.strings.Atom;
|
||||
|
||||
public class AnnotationTest extends WalaTestCase {
|
||||
public abstract class AnnotationTest extends WalaTestCase {
|
||||
|
||||
public static void main(String[] args) {
|
||||
justThisTest(AnnotationTest.class);
|
||||
}
|
||||
|
||||
private static IClassHierarchy cha;
|
||||
protected static IClassHierarchy cha;
|
||||
|
||||
@BeforeClass
|
||||
public static void before() throws IOException, ClassHierarchyException {
|
||||
AnalysisScope scope = AnalysisScopeReader.readJavaScope(TestConstants.WALA_TESTDATA,
|
||||
(new FileProvider()).getFile(CallGraphTestUtil.REGRESSION_EXCLUSIONS), AnnotationTest.class.getClassLoader());
|
||||
cha = ClassHierarchy.make(scope);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void after() {
|
||||
cha = null;
|
||||
|
||||
}
|
||||
@Test
|
||||
public void testClassAnnotations1() throws Exception {
|
||||
TypeReference typeUnderTest = TypeReference.findOrCreate(ClassLoaderReference.Application, "Lannotations/AnnotatedClass1");
|
||||
|
@ -104,13 +82,13 @@ public class AnnotationTest extends WalaTestCase {
|
|||
InvalidClassFileException {
|
||||
IClass classUnderTest = cha.lookupClass(typeUnderTest);
|
||||
Assert.assertNotNull(typeUnderTest.toString() + " not found", classUnderTest);
|
||||
Assert.assertTrue(classUnderTest instanceof ShrikeClass);
|
||||
ShrikeClass shrikeClassUnderTest = (ShrikeClass) classUnderTest;
|
||||
Assert.assertTrue(classUnderTest instanceof BytecodeClass);
|
||||
BytecodeClass<?> bcClassUnderTest = (BytecodeClass<?>) classUnderTest;
|
||||
|
||||
Collection<Annotation> runtimeInvisibleAnnotations = shrikeClassUnderTest.getRuntimeInvisibleAnnotations();
|
||||
Collection<Annotation> runtimeInvisibleAnnotations = bcClassUnderTest.getAnnotations(true);
|
||||
assertEqualCollections(expectedRuntimeInvisibleAnnotations, runtimeInvisibleAnnotations);
|
||||
|
||||
Collection<Annotation> runtimeVisibleAnnotations = shrikeClassUnderTest.getRuntimeVisibleAnnotations();
|
||||
Collection<Annotation> runtimeVisibleAnnotations = bcClassUnderTest.getAnnotations(false);
|
||||
assertEqualCollections(expectedRuntimeVisibleAnnotations, runtimeVisibleAnnotations);
|
||||
}
|
||||
|
||||
|
@ -130,13 +108,14 @@ public class AnnotationTest extends WalaTestCase {
|
|||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testClassAnnotations3() throws Exception {
|
||||
|
||||
TypeReference typeRef = TypeReference.findOrCreate(ClassLoaderReference.Application, "Lannotations/AnnotatedClass3");
|
||||
IClass klass = cha.lookupClass(typeRef);
|
||||
Assert.assertNotNull(klass);
|
||||
ShrikeClass shrikeClass = (ShrikeClass) klass;
|
||||
BytecodeClass<?> shrikeClass = (BytecodeClass<?>) klass;
|
||||
Collection<Annotation> classAnnotations = shrikeClass.getAnnotations(true);
|
||||
Assert.assertEquals("[Annotation type <Application,Lannotations/AnnotationWithParams> {strParam=classStrParam}]",
|
||||
classAnnotations.toString());
|
||||
|
@ -145,16 +124,23 @@ public class AnnotationTest extends WalaTestCase {
|
|||
|
||||
IMethod methodUnderTest = cha.resolveMethod(methodRefUnderTest);
|
||||
Assert.assertNotNull(methodRefUnderTest.toString() + " not found", methodUnderTest);
|
||||
Assert.assertTrue(methodUnderTest instanceof ShrikeCTMethod);
|
||||
ShrikeCTMethod shrikeCTMethodUnderTest = (ShrikeCTMethod) methodUnderTest;
|
||||
Assert.assertTrue(methodUnderTest instanceof IBytecodeMethod);
|
||||
IBytecodeMethod bcMethodUnderTest = (IBytecodeMethod) methodUnderTest;
|
||||
|
||||
Collection<Annotation> runtimeInvisibleAnnotations = shrikeCTMethodUnderTest.getAnnotations(true);
|
||||
Assert
|
||||
.assertEquals(
|
||||
"[Annotation type <Application,Lannotations/AnnotationWithParams> {enumParam=EnumElementValue [type=Lannotations/AnnotationEnum;, val=VAL1], strArrParam=ArrayElementValue [vals=[biz, boz]], annotParam=AnnotationElementValue [type=Lannotations/AnnotationWithSingleParam;, elementValues={value=sdfevs}], strParam=sdfsevs, intParam=25, klassParam=Ljava/lang/Integer;}]",
|
||||
runtimeInvisibleAnnotations.toString());
|
||||
|
||||
}
|
||||
Collection<Annotation> runtimeInvisibleAnnotations = bcMethodUnderTest.getAnnotations(true);
|
||||
Assert.assertEquals(1, runtimeInvisibleAnnotations.size());
|
||||
|
||||
Annotation x = runtimeInvisibleAnnotations.iterator().next();
|
||||
Assert.assertEquals(TypeReference.findOrCreate(ClassLoaderReference.Application, "Lannotations/AnnotationWithParams"), x.getType());
|
||||
for(Pair<String,String> n : new Pair[]{Pair.make("enumParam", "EnumElementValue [type=Lannotations/AnnotationEnum;, val=VAL1]"),
|
||||
Pair.make("strArrParam", "ArrayElementValue [vals=[biz, boz]]"),
|
||||
Pair.make("annotParam", "AnnotationElementValue [type=Lannotations/AnnotationWithSingleParam;, elementValues={value=sdfevs}]"),
|
||||
Pair.make("strParam", "sdfsevs"),
|
||||
Pair.make("intParam", "25"),
|
||||
Pair.make("klassParam", "Ljava/lang/Integer;")}) {
|
||||
Assert.assertEquals(n.snd, x.getNamedArguments().get(n.fst).toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClassAnnotations4() throws Exception {
|
||||
|
@ -179,35 +165,47 @@ public class AnnotationTest extends WalaTestCase {
|
|||
TypeReference typeRef = TypeReference.findOrCreate(ClassLoaderReference.Application, "Lannotations/ParameterAnnotations1");
|
||||
|
||||
checkParameterAnnots(typeRef, "foo(Ljava/lang/String;)V",
|
||||
"[Annotation type <Application,Lannotations/RuntimeVisableAnnotation>]");
|
||||
new String[]{"Annotation type <Application,Lannotations/RuntimeVisableAnnotation>"});
|
||||
checkParameterAnnots(
|
||||
typeRef,
|
||||
"bar(Ljava/lang/Integer;)V",
|
||||
"[Annotation type <Application,Lannotations/AnnotationWithParams> {enumParam=EnumElementValue [type=Lannotations/AnnotationEnum;, val=VAL1], strArrParam=ArrayElementValue [vals=[biz, boz]], annotParam=AnnotationElementValue [type=Lannotations/AnnotationWithSingleParam;, elementValues={value=sdfevs}], strParam=sdfsevs, intParam=25, klassParam=Ljava/lang/Integer;}]");
|
||||
new String[]{"Annotation type <Application,Lannotations/AnnotationWithParams> {annotParam=AnnotationElementValue [type=Lannotations/AnnotationWithSingleParam;, elementValues={value=sdfevs}], enumParam=EnumElementValue [type=Lannotations/AnnotationEnum;, val=VAL1], intParam=25, klassParam=Ljava/lang/Integer;, strArrParam=ArrayElementValue [vals=[biz, boz]], strParam=sdfsevs}"});
|
||||
checkParameterAnnots(typeRef, "foo2(Ljava/lang/String;Ljava/lang/Integer;)V",
|
||||
"[Annotation type <Application,Lannotations/RuntimeVisableAnnotation>]",
|
||||
"[Annotation type <Application,Lannotations/RuntimeInvisableAnnotation>]");
|
||||
new String[]{"Annotation type <Application,Lannotations/RuntimeVisableAnnotation>"},
|
||||
new String[]{"Annotation type <Application,Lannotations/RuntimeInvisableAnnotation>"});
|
||||
checkParameterAnnots(typeRef, "foo3(Ljava/lang/String;Ljava/lang/Integer;)V",
|
||||
"[Annotation type <Application,Lannotations/RuntimeVisableAnnotation>]",
|
||||
"[Annotation type <Application,Lannotations/RuntimeInvisableAnnotation>]");
|
||||
new String[]{"Annotation type <Application,Lannotations/RuntimeVisableAnnotation>"},
|
||||
new String[]{"Annotation type <Application,Lannotations/RuntimeInvisableAnnotation>"});
|
||||
checkParameterAnnots(typeRef, "foo4(Ljava/lang/String;Ljava/lang/Integer;)V",
|
||||
"[Annotation type <Application,Lannotations/RuntimeInvisableAnnotation>, Annotation type <Application,Lannotations/RuntimeVisableAnnotation>]",
|
||||
"[]");
|
||||
new String[]{"Annotation type <Application,Lannotations/RuntimeInvisableAnnotation>", "Annotation type <Application,Lannotations/RuntimeVisableAnnotation>"},
|
||||
new String[0]);
|
||||
|
||||
}
|
||||
|
||||
protected void checkParameterAnnots(TypeReference typeRef, String selector, String... expected) {
|
||||
protected void checkParameterAnnots(TypeReference typeRef, String selector, String[]... expected) {
|
||||
MethodReference methodRefUnderTest = MethodReference.findOrCreate(typeRef, Selector.make(selector));
|
||||
|
||||
IMethod methodUnderTest = cha.resolveMethod(methodRefUnderTest);
|
||||
Assert.assertNotNull(methodRefUnderTest.toString() + " not found", methodUnderTest);
|
||||
Assert.assertTrue(methodUnderTest instanceof ShrikeCTMethod);
|
||||
ShrikeCTMethod shrikeCTMethodUnderTest = (ShrikeCTMethod) methodUnderTest;
|
||||
Assert.assertTrue(methodUnderTest instanceof IBytecodeMethod);
|
||||
IBytecodeMethod IBytecodeMethodUnderTest = (IBytecodeMethod) methodUnderTest;
|
||||
|
||||
Collection<Annotation>[] parameterAnnotations = shrikeCTMethodUnderTest.getParameterAnnotations();
|
||||
Collection<Annotation>[] parameterAnnotations = IBytecodeMethodUnderTest.getParameterAnnotations();
|
||||
Assert.assertEquals(expected.length, parameterAnnotations.length);
|
||||
for (int i = 0; i < expected.length; i++) {
|
||||
Assert.assertEquals(expected[i], parameterAnnotations[i].toString());
|
||||
Set<String> e = HashSetFactory.make();
|
||||
for(String s : expected[i]) {
|
||||
e.add(s);
|
||||
}
|
||||
|
||||
Set<String> a = HashSetFactory.make();
|
||||
if (parameterAnnotations[i] != null) {
|
||||
for(Annotation x : parameterAnnotations[i]) {
|
||||
a.add(x.toString());
|
||||
}
|
||||
}
|
||||
|
||||
Assert.assertEquals(e, a);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
package com.ibm.wala.core.tests.ir;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
import com.ibm.wala.core.tests.callGraph.CallGraphTestUtil;
|
||||
import com.ibm.wala.core.tests.util.TestConstants;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisScope;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchyException;
|
||||
import com.ibm.wala.util.config.AnalysisScopeReader;
|
||||
import com.ibm.wala.util.io.FileProvider;
|
||||
|
||||
public class JVMLAnnotationTest extends AnnotationTest {
|
||||
|
||||
public static void main(String[] args) {
|
||||
justThisTest(JVMLAnnotationTest.class);
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void before() throws IOException, ClassHierarchyException {
|
||||
AnalysisScope scope = AnalysisScopeReader.readJavaScope(TestConstants.WALA_TESTDATA,
|
||||
(new FileProvider()).getFile(CallGraphTestUtil.REGRESSION_EXCLUSIONS), AnnotationTest.class.getClassLoader());
|
||||
cha = ClassHierarchy.make(scope);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void after() {
|
||||
cha = null;
|
||||
}
|
||||
|
||||
}
|
|
@ -590,4 +590,7 @@ public abstract class BytecodeClass<T extends IClassLoader> implements IClass {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
public abstract Collection<Annotation> getAnnotations(boolean runtimeVisible) throws InvalidClassFileException;
|
||||
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@ import com.ibm.wala.shrikeBT.ExceptionHandler;
|
|||
import com.ibm.wala.shrikeBT.IInstruction;
|
||||
import com.ibm.wala.shrikeBT.IndirectionData;
|
||||
import com.ibm.wala.shrikeCT.InvalidClassFileException;
|
||||
import com.ibm.wala.types.annotations.Annotation;
|
||||
|
||||
/**
|
||||
* A method which originated in bytecode, decoded by Shrike
|
||||
|
@ -47,4 +48,8 @@ public interface IBytecodeMethod extends IMethod {
|
|||
*/
|
||||
IndirectionData getIndirectionData();
|
||||
|
||||
Collection<Annotation>[] getParameterAnnotations();
|
||||
|
||||
Collection<Annotation> getAnnotations(boolean runtimeVisible) throws InvalidClassFileException;
|
||||
|
||||
}
|
||||
|
|
|
@ -183,5 +183,5 @@ public interface IClass extends IClassHierarchyDweller {
|
|||
* get annotations, if any
|
||||
*/
|
||||
Collection<Annotation> getAnnotations();
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -446,6 +446,7 @@ public final class ShrikeCTMethod extends ShrikeBTMethod implements IBytecodeMet
|
|||
return getAnnotations(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Annotation> getAnnotations(boolean runtimeInvisible) throws InvalidClassFileException {
|
||||
AnnotationsReader r = getAnnotationsReader(runtimeInvisible ? AnnotationType.RuntimeInvisibleAnnotations
|
||||
: AnnotationType.RuntimeVisibleAnnotations);
|
||||
|
|
|
@ -244,6 +244,7 @@ public final class ShrikeClass extends JVMClass<IClassLoader> {
|
|||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Annotation> getAnnotations(boolean runtimeInvisible) throws InvalidClassFileException {
|
||||
AnnotationsReader r = getAnnotationsReader(runtimeInvisible);
|
||||
return Annotation.getAnnotationsFromReader(r, getClassLoader().getReference());
|
||||
|
|
|
@ -14,6 +14,7 @@ import java.util.Arrays;
|
|||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import com.ibm.wala.shrikeCT.AnnotationsReader;
|
||||
import com.ibm.wala.shrikeCT.AnnotationsReader.AnnotationAttribute;
|
||||
|
@ -121,7 +122,7 @@ public class Annotation {
|
|||
sb.append(" ]");
|
||||
}
|
||||
if (!namedArguments.isEmpty()) {
|
||||
sb.append(" " + namedArguments);
|
||||
sb.append(" " + new TreeMap<String, ElementValue>(namedArguments));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
|
|
@ -0,0 +1,120 @@
|
|||
package com.ibm.wala.dalvik.test;
|
||||
|
||||
import static com.ibm.wala.properties.WalaProperties.ANDROID_RT_JAR;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
|
||||
import com.ibm.wala.classLoader.JarFileModule;
|
||||
import com.ibm.wala.classLoader.Module;
|
||||
import com.ibm.wala.classLoader.NestedJarFileModule;
|
||||
import com.ibm.wala.core.tests.callGraph.CallGraphTestUtil;
|
||||
import com.ibm.wala.core.tests.shrike.DynamicCallGraphTestBase;
|
||||
import com.ibm.wala.dalvik.test.callGraph.DalvikCallGraphTestBase;
|
||||
import com.ibm.wala.dalvik.util.AndroidAnalysisScope;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisScope;
|
||||
import com.ibm.wala.properties.WalaProperties;
|
||||
import com.ibm.wala.util.WalaException;
|
||||
import com.ibm.wala.util.io.TemporaryFile;
|
||||
|
||||
public abstract class DalvikTestBase extends DynamicCallGraphTestBase {
|
||||
|
||||
public static Properties walaProperties;
|
||||
|
||||
static {
|
||||
try {
|
||||
walaProperties = WalaProperties.loadProperties();
|
||||
} catch (WalaException e) {
|
||||
walaProperties = null;
|
||||
}
|
||||
}
|
||||
|
||||
public static String getJavaJar(AnalysisScope javaScope) throws IOException {
|
||||
Module javaJar = javaScope.getModules(javaScope.getApplicationLoader()).iterator().next();
|
||||
if (javaJar instanceof JarFileModule) {
|
||||
String javaJarPath = ((JarFileModule)javaJar).getAbsolutePath();
|
||||
return javaJarPath;
|
||||
} else {
|
||||
assert javaJar instanceof NestedJarFileModule : javaJar;
|
||||
File F = File.createTempFile("android", ".jar");
|
||||
//F.deleteOnExit();
|
||||
System.err.println(F.getAbsolutePath());
|
||||
TemporaryFile.streamToFile(F, ((NestedJarFileModule)javaJar).getNestedContents());
|
||||
return F.getAbsolutePath();
|
||||
}
|
||||
}
|
||||
|
||||
public static File convertJarToDex(String jarFile) throws IOException {
|
||||
File f = File.createTempFile("convert", ".dex");
|
||||
//f.deleteOnExit();
|
||||
System.err.println(f);
|
||||
com.android.dx.command.Main.main(new String[]{"--dex", "--output=" + f.getAbsolutePath(), jarFile});
|
||||
return f;
|
||||
}
|
||||
|
||||
public static URI[] androidLibs() {
|
||||
if ("Dalvik".equals(System.getProperty("java.vm.name"))) {
|
||||
try {
|
||||
return new URI[]{
|
||||
new URL("file:///system/framework/core.jar").toURI(),
|
||||
new URL("file:///system/framework/framework.jar").toURI(),
|
||||
new URL("file:///system/framework/framework2.jar").toURI(),
|
||||
new URL("file:///system/framework/framework3.jar").toURI()
|
||||
};
|
||||
} catch (MalformedURLException e) {
|
||||
assert false : e;
|
||||
return null;
|
||||
} catch (URISyntaxException e) {
|
||||
assert false : e;
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
List<URI> libs = new ArrayList<URI>();
|
||||
try {
|
||||
for(File lib : new File(walaProperties.getProperty(ANDROID_RT_JAR)).listFiles(new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(File dir, String name) {
|
||||
return name.endsWith("dex") || name.endsWith("jar");
|
||||
}
|
||||
})) {
|
||||
libs.add(lib.toURI());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
for(String l : WalaProperties.getJ2SEJarFiles()) {
|
||||
libs.add(new File(l).toURI());
|
||||
}
|
||||
try {
|
||||
File jarFile = TemporaryFile.urlToFile("android.jar", DalvikCallGraphTestBase.class.getClassLoader().getResource("android.jar"));
|
||||
libs.add(jarFile.toURI());
|
||||
} catch (IOException e1) {
|
||||
assert false : e1;
|
||||
}
|
||||
}
|
||||
return libs.toArray(new URI[ libs.size() ]);
|
||||
}
|
||||
}
|
||||
|
||||
public static AnalysisScope makeDalvikScope(boolean useAndroidLib, String dexFileName) throws IOException {
|
||||
AnalysisScope scope =
|
||||
useAndroidLib?
|
||||
AndroidAnalysisScope.setUpAndroidAnalysisScope(
|
||||
new File(dexFileName).toURI(),
|
||||
CallGraphTestUtil.REGRESSION_EXCLUSIONS,
|
||||
CallGraphTestUtil.class.getClassLoader(),
|
||||
androidLibs()):
|
||||
AndroidAnalysisScope.setUpAndroidAnalysisScope(
|
||||
new File(dexFileName).toURI(),
|
||||
CallGraphTestUtil.REGRESSION_EXCLUSIONS,
|
||||
CallGraphTestUtil.class.getClassLoader());
|
||||
return scope;
|
||||
}
|
||||
|
||||
}
|
|
@ -10,32 +10,20 @@
|
|||
*******************************************************************************/
|
||||
package com.ibm.wala.dalvik.test.callGraph;
|
||||
|
||||
import static com.ibm.wala.properties.WalaProperties.ANDROID_RT_JAR;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FilenameFilter;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.classLoader.JarFileModule;
|
||||
import com.ibm.wala.classLoader.Module;
|
||||
import com.ibm.wala.classLoader.NestedJarFileModule;
|
||||
import com.ibm.wala.classLoader.NewSiteReference;
|
||||
import com.ibm.wala.core.tests.callGraph.CallGraphTestUtil;
|
||||
import com.ibm.wala.core.tests.shrike.DynamicCallGraphTestBase;
|
||||
import com.ibm.wala.dalvik.classLoader.DexIRFactory;
|
||||
import com.ibm.wala.dalvik.test.DalvikTestBase;
|
||||
import com.ibm.wala.dalvik.util.AndroidAnalysisScope;
|
||||
import com.ibm.wala.dalvik.util.AndroidEntryPointLocator;
|
||||
import com.ibm.wala.dalvik.util.AndroidEntryPointLocator.LocatorFlags;
|
||||
|
@ -75,17 +63,7 @@ import com.ibm.wala.util.collections.Pair;
|
|||
import com.ibm.wala.util.functions.Function;
|
||||
import com.ibm.wala.util.io.TemporaryFile;
|
||||
|
||||
public class DalvikCallGraphTestBase extends DynamicCallGraphTestBase {
|
||||
|
||||
public static Properties walaProperties;
|
||||
|
||||
static {
|
||||
try {
|
||||
walaProperties = WalaProperties.loadProperties();
|
||||
} catch (WalaException e) {
|
||||
walaProperties = null;
|
||||
}
|
||||
}
|
||||
public class DalvikCallGraphTestBase extends DalvikTestBase {
|
||||
|
||||
protected static <T> Set<T> processCG(CallGraph cg, Predicate<CGNode> filter, Function<CGNode,T> map) {
|
||||
Set<T> result = HashSetFactory.make();
|
||||
|
@ -114,29 +92,6 @@ public class DalvikCallGraphTestBase extends DynamicCallGraphTestBase {
|
|||
}
|
||||
|
||||
|
||||
protected static String getJavaJar(AnalysisScope javaScope) throws IOException {
|
||||
Module javaJar = javaScope.getModules(javaScope.getApplicationLoader()).iterator().next();
|
||||
if (javaJar instanceof JarFileModule) {
|
||||
String javaJarPath = ((JarFileModule)javaJar).getAbsolutePath();
|
||||
return javaJarPath;
|
||||
} else {
|
||||
assert javaJar instanceof NestedJarFileModule : javaJar;
|
||||
File F = File.createTempFile("android", ".jar");
|
||||
//F.deleteOnExit();
|
||||
System.err.println(F.getAbsolutePath());
|
||||
TemporaryFile.streamToFile(F, ((NestedJarFileModule)javaJar).getNestedContents());
|
||||
return F.getAbsolutePath();
|
||||
}
|
||||
}
|
||||
|
||||
public static File convertJarToDex(String jarFile) throws IOException, InterruptedException {
|
||||
File f = File.createTempFile("convert", ".dex");
|
||||
//f.deleteOnExit();
|
||||
System.err.println(f);
|
||||
com.android.dx.command.Main.main(new String[]{"--dex", "--output=" + f.getAbsolutePath(), jarFile});
|
||||
return f;
|
||||
}
|
||||
|
||||
public void dynamicCG(File javaJarPath, String mainClass, String... args) throws FileNotFoundException, IOException, ClassNotFoundException, InvalidClassFileException, FailureException, SecurityException, NoSuchMethodException, IllegalArgumentException, IllegalAccessException, InvocationTargetException, InterruptedException {
|
||||
File F = TemporaryFile.streamToFile(new File("test_jar.jar"), new FileInputStream(javaJarPath));
|
||||
F.deleteOnExit();
|
||||
|
@ -216,60 +171,8 @@ public class DalvikCallGraphTestBase extends DynamicCallGraphTestBase {
|
|||
return Pair.make(callGraph, ptrAnalysis);
|
||||
}
|
||||
|
||||
public static URI[] androidLibs() {
|
||||
if ("Dalvik".equals(System.getProperty("java.vm.name"))) {
|
||||
try {
|
||||
return new URI[]{
|
||||
new URL("file:///system/framework/core.jar").toURI(),
|
||||
new URL("file:///system/framework/framework.jar").toURI(),
|
||||
new URL("file:///system/framework/framework2.jar").toURI(),
|
||||
new URL("file:///system/framework/framework3.jar").toURI()
|
||||
};
|
||||
} catch (MalformedURLException e) {
|
||||
assert false : e;
|
||||
return null;
|
||||
} catch (URISyntaxException e) {
|
||||
assert false : e;
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
List<URI> libs = new ArrayList<URI>();
|
||||
try {
|
||||
for(File lib : new File(walaProperties.getProperty(ANDROID_RT_JAR)).listFiles(new FilenameFilter() {
|
||||
@Override
|
||||
public boolean accept(File dir, String name) {
|
||||
return name.endsWith("dex") || name.endsWith("jar");
|
||||
}
|
||||
})) {
|
||||
libs.add(lib.toURI());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
for(String l : WalaProperties.getJ2SEJarFiles()) {
|
||||
libs.add(new File(l).toURI());
|
||||
}
|
||||
try {
|
||||
File jarFile = TemporaryFile.urlToFile("android.jar", DalvikCallGraphTestBase.class.getClassLoader().getResource("android.jar"));
|
||||
libs.add(jarFile.toURI());
|
||||
} catch (IOException e1) {
|
||||
assert false : e1;
|
||||
}
|
||||
}
|
||||
return libs.toArray(new URI[ libs.size() ]);
|
||||
}
|
||||
}
|
||||
|
||||
public static Pair<CallGraph, PointerAnalysis<InstanceKey>> makeDalvikCallGraph(boolean useAndroidLib, String mainClassName, String dexFileName) throws IOException, ClassHierarchyException, IllegalArgumentException, CancelException {
|
||||
AnalysisScope scope =
|
||||
useAndroidLib?
|
||||
AndroidAnalysisScope.setUpAndroidAnalysisScope(
|
||||
new File(dexFileName).toURI(),
|
||||
CallGraphTestUtil.REGRESSION_EXCLUSIONS,
|
||||
CallGraphTestUtil.class.getClassLoader(),
|
||||
androidLibs()):
|
||||
AndroidAnalysisScope.setUpAndroidAnalysisScope(
|
||||
new File(dexFileName).toURI(),
|
||||
CallGraphTestUtil.REGRESSION_EXCLUSIONS,
|
||||
CallGraphTestUtil.class.getClassLoader());
|
||||
AnalysisScope scope = makeDalvikScope(useAndroidLib, dexFileName);
|
||||
|
||||
final IClassHierarchy cha = ClassHierarchy.make(scope);
|
||||
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
package com.ibm.wala.dalvik.test.ir;
|
||||
|
||||
import static com.ibm.wala.dalvik.test.DalvikTestBase.convertJarToDex;
|
||||
import static com.ibm.wala.dalvik.test.DalvikTestBase.makeDalvikScope;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
import com.ibm.wala.core.tests.ir.AnnotationTest;
|
||||
import com.ibm.wala.core.tests.ir.JVMLAnnotationTest;
|
||||
import com.ibm.wala.ipa.callgraph.AnalysisScope;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchyException;
|
||||
import com.ibm.wala.util.io.TemporaryFile;
|
||||
|
||||
public class DalvikAnnotationsTest extends AnnotationTest {
|
||||
|
||||
public static void main(String[] args) {
|
||||
justThisTest(JVMLAnnotationTest.class);
|
||||
}
|
||||
|
||||
@BeforeClass
|
||||
public static void before() throws IOException, ClassHierarchyException {
|
||||
File F = File.createTempFile("waladata", ".jar");
|
||||
F.deleteOnExit();
|
||||
TemporaryFile.streamToFile(F, DalvikAnnotationsTest.class.getClassLoader().getResourceAsStream("com.ibm.wala.core.testdata_1.0.0a.jar"));
|
||||
File androidDex = convertJarToDex(F.getAbsolutePath());
|
||||
AnalysisScope dalvikScope = makeDalvikScope(true, androidDex.getAbsolutePath());
|
||||
cha = ClassHierarchy.make(dalvikScope);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void after() {
|
||||
cha = null;
|
||||
}
|
||||
|
||||
}
|
|
@ -47,8 +47,6 @@
|
|||
|
||||
package com.ibm.wala.dalvik.classLoader;
|
||||
|
||||
import static org.jf.dexlib.ItemType.TYPE_CLASS_DEF_ITEM;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
|
@ -90,9 +88,7 @@ public class DexFileModule implements Module {
|
|||
// create ModuleEntries from ClassDefItem
|
||||
entries = new HashSet<ModuleEntry>();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
Section<ClassDefItem> cldeff = dexfile.getSectionForType(TYPE_CLASS_DEF_ITEM);
|
||||
|
||||
Section<ClassDefItem> cldeff = dexfile.ClassDefsSection;
|
||||
for (ClassDefItem cdefitems : cldeff.getItems()) {
|
||||
logger.debug("DexFileModule adding class: " + cdefitems.getConciseIdentity());
|
||||
entries.add(new DexModuleEntry(cdefitems));
|
||||
|
|
|
@ -54,12 +54,21 @@ import static org.jf.dexlib.Util.AccessFlags.PUBLIC;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jf.dexlib.AnnotationDirectoryItem;
|
||||
import org.jf.dexlib.AnnotationItem;
|
||||
import org.jf.dexlib.AnnotationSetItem;
|
||||
import org.jf.dexlib.AnnotationVisibility;
|
||||
import org.jf.dexlib.ClassDataItem;
|
||||
import org.jf.dexlib.ClassDataItem.EncodedField;
|
||||
import org.jf.dexlib.ClassDataItem.EncodedMethod;
|
||||
import org.jf.dexlib.ClassDefItem;
|
||||
import org.jf.dexlib.FieldIdItem;
|
||||
import org.jf.dexlib.MethodIdItem;
|
||||
import org.jf.dexlib.TypeIdItem;
|
||||
import org.jf.dexlib.TypeListItem;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -71,9 +80,12 @@ import com.ibm.wala.classLoader.IField;
|
|||
import com.ibm.wala.classLoader.IMethod;
|
||||
import com.ibm.wala.classLoader.Module;
|
||||
import com.ibm.wala.ipa.cha.IClassHierarchy;
|
||||
import com.ibm.wala.shrikeCT.AnnotationsReader.AnnotationType;
|
||||
import com.ibm.wala.shrikeCT.InvalidClassFileException;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.types.annotations.Annotation;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
import com.ibm.wala.util.collections.HashSetFactory;
|
||||
import com.ibm.wala.util.strings.ImmutableByteArray;
|
||||
|
||||
public class DexIClass extends BytecodeClass<IClassLoader> {
|
||||
|
@ -258,6 +270,79 @@ public class DexIClass extends BytecodeClass<IClassLoader> {
|
|||
return hashCode;
|
||||
}
|
||||
|
||||
Collection<Annotation> getAnnotations(Set<AnnotationVisibility> types) {
|
||||
Set<Annotation> result = HashSetFactory.make();
|
||||
AnnotationDirectoryItem d = dexModuleEntry.getClassDefItem().getAnnotations();
|
||||
if (d.getClassAnnotations() != null) {
|
||||
for(AnnotationItem a : d.getClassAnnotations().getAnnotations()) {
|
||||
if (types == null || types.contains(a.getVisibility())) {
|
||||
result.add(DexUtil.getAnnotation(a, getClassLoader().getReference()));
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Collection<Annotation> getAnnotations() {
|
||||
return getAnnotations((Set<AnnotationVisibility>)null);
|
||||
}
|
||||
|
||||
public Collection<Annotation> getAnnotations(boolean runtimeInvisible) throws InvalidClassFileException {
|
||||
return getAnnotations(getTypes(runtimeInvisible));
|
||||
}
|
||||
|
||||
static Set<AnnotationVisibility> getTypes(boolean runtimeInvisible) {
|
||||
Set<AnnotationVisibility> types = HashSetFactory.make();
|
||||
types.add(AnnotationVisibility.SYSTEM);
|
||||
if (runtimeInvisible) {
|
||||
types.add(AnnotationVisibility.BUILD);
|
||||
} else {
|
||||
types.add(AnnotationVisibility.RUNTIME);
|
||||
}
|
||||
return types;
|
||||
}
|
||||
|
||||
List<AnnotationItem> getAnnotations(MethodIdItem m, Set<AnnotationVisibility> types) {
|
||||
List<AnnotationItem> result = new ArrayList<AnnotationItem>();
|
||||
AnnotationDirectoryItem d = dexModuleEntry.getClassDefItem().getAnnotations();
|
||||
if (d != null) {
|
||||
for(AnnotationItem a : d.getMethodAnnotations(m).getAnnotations()) {
|
||||
if (types == null || types.contains(a.getVisibility())) {
|
||||
result.add(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
List<AnnotationItem> getAnnotations(FieldIdItem m) {
|
||||
List<AnnotationItem> result = new ArrayList<AnnotationItem>();
|
||||
AnnotationDirectoryItem d = dexModuleEntry.getClassDefItem().getAnnotations();
|
||||
if (d != null) {
|
||||
for(AnnotationItem a : d.getFieldAnnotations(m).getAnnotations()) {
|
||||
result.add(a);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Map<Integer,List<AnnotationItem>> getParameterAnnotations(MethodIdItem m) {
|
||||
Map<Integer,List<AnnotationItem>> result = HashMapFactory.make();
|
||||
AnnotationDirectoryItem d = dexModuleEntry.getClassDefItem().getAnnotations();
|
||||
if (d != null) {
|
||||
int i = 0;
|
||||
for(AnnotationSetItem as : d.getParameterAnnotations(m).getAnnotationSets()) {
|
||||
for(AnnotationItem a : as.getAnnotations()) {
|
||||
if (! result.containsKey(i)) {
|
||||
result.put(i, new ArrayList<AnnotationItem>());
|
||||
}
|
||||
result.get(i).add(a);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
|
@ -339,11 +424,6 @@ public class DexIClass extends BytecodeClass<IClassLoader> {
|
|||
return clinitId!=-1?methods[clinitId]:null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Annotation> getAnnotations() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Module getContainer() {
|
||||
return dexModuleEntry.asModule();
|
||||
|
|
|
@ -58,6 +58,8 @@ import static org.jf.dexlib.Util.AccessFlags.VOLATILE;
|
|||
import java.util.Collection;
|
||||
|
||||
import org.jf.dexlib.ClassDataItem.EncodedField;
|
||||
import org.jf.dexlib.StringIdItem;
|
||||
import org.jf.dexlib.TypeIdItem;
|
||||
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.classLoader.IField;
|
||||
|
@ -67,7 +69,6 @@ import com.ibm.wala.types.TypeName;
|
|||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.types.annotations.Annotation;
|
||||
import com.ibm.wala.util.strings.Atom;
|
||||
import com.ibm.wala.util.strings.ImmutableByteArray;
|
||||
|
||||
public class DexIField implements IField {
|
||||
|
||||
|
@ -100,20 +101,16 @@ public class DexIField implements IField {
|
|||
//public DexIField(EncodedField encodedField) {
|
||||
eField = encodedField;
|
||||
myClass = klass;
|
||||
name = Atom.findOrCreateUnicodeAtom(eField.field.getFieldName().getStringValue());
|
||||
StringIdItem fieldName = eField.field.getFieldName();
|
||||
name = Atom.findOrCreateUnicodeAtom(fieldName.getStringValue());
|
||||
|
||||
ImmutableByteArray fieldType = ImmutableByteArray.make(eField.field.getFieldType().getTypeDescriptor());
|
||||
TypeName T = null;
|
||||
if (fieldType.get(fieldType.length() - 1) == ';') {
|
||||
T = TypeName.findOrCreate(fieldType, 0, fieldType.length() - 1);
|
||||
} else {
|
||||
T = TypeName.findOrCreate(fieldType);
|
||||
}
|
||||
TypeIdItem fieldType = eField.field.getFieldType();
|
||||
TypeName T = DexUtil.getTypeName(fieldType);
|
||||
TypeReference type = TypeReference.findOrCreate(myClass.getClassLoader().getReference(), T);
|
||||
myFieldRef = FieldReference.findOrCreate(myClass.getReference(), name, type);
|
||||
}
|
||||
|
||||
public TypeReference getFieldTypeReference() {
|
||||
public TypeReference getFieldTypeReference() {
|
||||
|
||||
//compute the typeReference from the EncodedField
|
||||
// if (typeReference == null) {
|
||||
|
@ -176,7 +173,7 @@ public class DexIField implements IField {
|
|||
|
||||
@Override
|
||||
public Collection<Annotation> getAnnotations() {
|
||||
throw new UnsupportedOperationException();
|
||||
return DexUtil.getAnnotations(myClass.getAnnotations(eField.field), myClass.getClassLoader().getReference());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -61,6 +61,9 @@ import static org.jf.dexlib.Util.AccessFlags.VOLATILE;
|
|||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.jf.dexlib.AnnotationItem;
|
||||
import org.jf.dexlib.AnnotationSetItem;
|
||||
|
@ -191,9 +194,6 @@ public class DexIMethod implements IBytecodeMethod {
|
|||
public DexIMethod(EncodedMethod encodedMethod, DexIClass klass) {
|
||||
eMethod = encodedMethod;
|
||||
myClass = klass;
|
||||
//XXX TEST
|
||||
//myClass.iterateMethodAnnotations(this);
|
||||
|
||||
}
|
||||
|
||||
public static int getTotalInsts() {
|
||||
|
@ -3357,7 +3357,24 @@ public class DexIMethod implements IBytecodeMethod {
|
|||
|
||||
@Override
|
||||
public Collection<Annotation> getAnnotations() {
|
||||
throw new UnsupportedOperationException();
|
||||
return DexUtil.getAnnotations(myClass.getAnnotations(eMethod.method, null), myClass.getClassLoader().getReference());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Annotation> getAnnotations(boolean runtimeInvisible) {
|
||||
return DexUtil.getAnnotations(myClass.getAnnotations(eMethod.method, DexIClass.getTypes(runtimeInvisible)), myClass.getClassLoader().getReference());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<Annotation>[] getParameterAnnotations() {
|
||||
Map<Integer, List<AnnotationItem>> raw = myClass.getParameterAnnotations(eMethod.method);
|
||||
@SuppressWarnings("unchecked")
|
||||
Collection<Annotation>[] result = new Collection[ getReference().getNumberOfParameters() ];
|
||||
for(Map.Entry<Integer, List<AnnotationItem>> x : raw.entrySet()) {
|
||||
result[x.getKey()] = DexUtil.getAnnotations(x.getValue(), myClass.getClassLoader().getReference());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,169 @@
|
|||
package com.ibm.wala.dalvik.classLoader;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import org.jf.dexlib.AnnotationItem;
|
||||
import org.jf.dexlib.FieldIdItem;
|
||||
import org.jf.dexlib.MethodIdItem;
|
||||
import org.jf.dexlib.TypeIdItem;
|
||||
import org.jf.dexlib.EncodedValue.AnnotationEncodedSubValue;
|
||||
import org.jf.dexlib.EncodedValue.ArrayEncodedValue;
|
||||
import org.jf.dexlib.EncodedValue.BooleanEncodedValue;
|
||||
import org.jf.dexlib.EncodedValue.ByteEncodedValue;
|
||||
import org.jf.dexlib.EncodedValue.CharEncodedValue;
|
||||
import org.jf.dexlib.EncodedValue.DoubleEncodedValue;
|
||||
import org.jf.dexlib.EncodedValue.EncodedValue;
|
||||
import org.jf.dexlib.EncodedValue.EnumEncodedValue;
|
||||
import org.jf.dexlib.EncodedValue.FieldEncodedValue;
|
||||
import org.jf.dexlib.EncodedValue.FloatEncodedValue;
|
||||
import org.jf.dexlib.EncodedValue.IntEncodedValue;
|
||||
import org.jf.dexlib.EncodedValue.LongEncodedValue;
|
||||
import org.jf.dexlib.EncodedValue.MethodEncodedValue;
|
||||
import org.jf.dexlib.EncodedValue.ShortEncodedValue;
|
||||
import org.jf.dexlib.EncodedValue.StringEncodedValue;
|
||||
import org.jf.dexlib.EncodedValue.TypeEncodedValue;
|
||||
import org.jf.dexlib.EncodedValue.ValueType;
|
||||
|
||||
import com.ibm.wala.shrikeCT.AnnotationsReader.AnnotationAttribute;
|
||||
import com.ibm.wala.shrikeCT.AnnotationsReader.ArrayElementValue;
|
||||
import com.ibm.wala.shrikeCT.AnnotationsReader.ConstantElementValue;
|
||||
import com.ibm.wala.shrikeCT.AnnotationsReader.ElementValue;
|
||||
import com.ibm.wala.shrikeCT.AnnotationsReader.EnumElementValue;
|
||||
import com.ibm.wala.types.ClassLoaderReference;
|
||||
import com.ibm.wala.types.Descriptor;
|
||||
import com.ibm.wala.types.FieldReference;
|
||||
import com.ibm.wala.types.MethodReference;
|
||||
import com.ibm.wala.types.TypeName;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.types.annotations.Annotation;
|
||||
import com.ibm.wala.util.collections.HashMapFactory;
|
||||
import com.ibm.wala.util.collections.HashSetFactory;
|
||||
import com.ibm.wala.util.strings.Atom;
|
||||
import com.ibm.wala.util.strings.ImmutableByteArray;
|
||||
|
||||
public class DexUtil {
|
||||
|
||||
static Collection<Annotation> getAnnotations(Collection<AnnotationItem> as, ClassLoaderReference clr) {
|
||||
Collection<Annotation> result = HashSetFactory.make();
|
||||
for(AnnotationItem a : as) {
|
||||
result.add(getAnnotation(a, clr));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static Annotation getAnnotation(AnnotationItem a, ClassLoaderReference clr) {
|
||||
return getAnnotation(a.getEncodedAnnotation(), clr);
|
||||
}
|
||||
|
||||
static Annotation getAnnotation(AnnotationEncodedSubValue ea, ClassLoaderReference clr) {
|
||||
Map<String,ElementValue> values = HashMapFactory.make();
|
||||
TypeReference at = getTypeRef(ea.annotationType, clr);
|
||||
|
||||
for(int i = 0; i < ea.names.length; i++) {
|
||||
String name = ea.names[i].getStringValue();
|
||||
EncodedValue v = ea.values[i];
|
||||
ElementValue value = getValue(clr, v);
|
||||
values.put(name, value);
|
||||
}
|
||||
|
||||
return Annotation.makeWithNamed(at, values);
|
||||
}
|
||||
|
||||
static ElementValue getValue(ClassLoaderReference clr, EncodedValue v) {
|
||||
switch (v.getValueType()) {
|
||||
case VALUE_ANNOTATION:
|
||||
Annotation a = getAnnotation((AnnotationEncodedSubValue)v, clr);
|
||||
return new AnnotationAttribute(a.getType().getName().toString() +";", a.getNamedArguments());
|
||||
|
||||
case VALUE_ARRAY:
|
||||
EncodedValue[] vs = ((ArrayEncodedValue)v).values;
|
||||
ElementValue rs[] = new ElementValue[ vs.length ];
|
||||
for(int idx = 0; idx < vs.length; idx++) {
|
||||
rs[idx] = getValue(clr, vs[idx]);
|
||||
}
|
||||
return new ArrayElementValue(rs);
|
||||
|
||||
case VALUE_BOOLEAN:
|
||||
Boolean bl = ((BooleanEncodedValue)v).value;
|
||||
return new ConstantElementValue(bl);
|
||||
|
||||
case VALUE_BYTE:
|
||||
Byte bt = ((ByteEncodedValue)v).value;
|
||||
return new ConstantElementValue(bt);
|
||||
|
||||
case VALUE_CHAR:
|
||||
Character c = ((CharEncodedValue)v).value;
|
||||
return new ConstantElementValue(c);
|
||||
|
||||
case VALUE_DOUBLE:
|
||||
Double d = ((DoubleEncodedValue)v).value;
|
||||
return new ConstantElementValue(d);
|
||||
|
||||
case VALUE_ENUM:
|
||||
FieldIdItem o = ((EnumEncodedValue)v).value;
|
||||
return new EnumElementValue(o.getFieldType().getTypeDescriptor(), o.getFieldName().getStringValue());
|
||||
|
||||
case VALUE_FIELD:
|
||||
o = v.getValueType()==ValueType.VALUE_ENUM? ((EnumEncodedValue)v).value: ((FieldEncodedValue)v).value;
|
||||
String fieldName = o.getFieldName().getStringValue();
|
||||
TypeReference ft = getTypeRef(o.getFieldType(), clr);
|
||||
TypeReference ct = getTypeRef(o.getContainingClass(), clr);
|
||||
return new ConstantElementValue(FieldReference.findOrCreate(ct, Atom.findOrCreateUnicodeAtom(fieldName), ft));
|
||||
|
||||
case VALUE_FLOAT:
|
||||
Float f = ((FloatEncodedValue)v).value;
|
||||
return new ConstantElementValue(f);
|
||||
|
||||
case VALUE_INT:
|
||||
Integer iv = ((IntEncodedValue)v).value;
|
||||
return new ConstantElementValue(iv);
|
||||
|
||||
case VALUE_LONG:
|
||||
Long l = ((LongEncodedValue)v).value;
|
||||
return new ConstantElementValue(l);
|
||||
|
||||
case VALUE_METHOD:
|
||||
MethodIdItem m = ((MethodEncodedValue)v).value;
|
||||
ct = getTypeRef(m.getContainingClass(), clr);
|
||||
String methodName = m.getMethodName().getStringValue();
|
||||
String methodSig = m.getPrototype().getPrototypeString();
|
||||
return new ConstantElementValue(MethodReference.findOrCreate(ct, Atom.findOrCreateUnicodeAtom(methodName), Descriptor.findOrCreateUTF8(methodSig)));
|
||||
|
||||
case VALUE_NULL:
|
||||
return new ConstantElementValue(null);
|
||||
|
||||
case VALUE_SHORT:
|
||||
Short s = ((ShortEncodedValue)v).value;
|
||||
return new ConstantElementValue(s);
|
||||
|
||||
case VALUE_STRING:
|
||||
String str = ((StringEncodedValue)v).value.getStringValue();
|
||||
return new ConstantElementValue(str);
|
||||
|
||||
case VALUE_TYPE:
|
||||
TypeIdItem t = ((TypeEncodedValue)v).value;
|
||||
return new ConstantElementValue(getTypeName(t) + ";");
|
||||
|
||||
default:
|
||||
assert false : v;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static TypeReference getTypeRef(TypeIdItem type, ClassLoaderReference clr) {
|
||||
return TypeReference.findOrCreate(clr, getTypeName(type));
|
||||
}
|
||||
|
||||
static TypeName getTypeName(TypeIdItem fieldType) {
|
||||
ImmutableByteArray fieldTypeArray = ImmutableByteArray.make(fieldType.getTypeDescriptor());
|
||||
TypeName T = null;
|
||||
if (fieldTypeArray.get(fieldTypeArray.length() - 1) == ';') {
|
||||
T = TypeName.findOrCreate(fieldTypeArray, 0, fieldTypeArray.length() - 1);
|
||||
} else {
|
||||
T = TypeName.findOrCreate(fieldTypeArray);
|
||||
}
|
||||
return T;
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue