# HG changeset patch
# User forax
# Date 1301649349 -7200
# Node ID cf71c6ab82fcef13a35ffa9b8831939e6dfc887d
# Parent 19915795c08c2bc34fca5570bb4b0e291355771e
Add a flag daneel.verify to enable post verification of DEX to bytecode translation
diff -r 19915795c08c -r cf71c6ab82fc src/main/java/org/icedrobot/daneel/loader/DaneelClassLoader.java
--- a/src/main/java/org/icedrobot/daneel/loader/DaneelClassLoader.java Thu Mar 31 00:54:29 2011 +0200
+++ b/src/main/java/org/icedrobot/daneel/loader/DaneelClassLoader.java Fri Apr 01 11:15:49 2011 +0200
@@ -40,6 +40,7 @@
import java.io.File;
import java.io.IOError;
import java.io.IOException;
+import java.io.PrintWriter;
import java.net.URL;
import java.util.ArrayList;
import java.util.zip.ZipEntry;
@@ -117,6 +118,9 @@
for (DexFile dexFile : dexFiles) {
try {
byte[] bytecode = DexRewriter.rewrite(name, dexFile);
+ if (VERIFY) {
+ Verifier.verify(this, dexFile, name, bytecode, new PrintWriter(System.err));
+ }
return defineClass(name, bytecode, 0, bytecode.length);
} catch (ClassNotFoundException e) {
// Ignore and skip to the next file.
@@ -208,4 +212,9 @@
}
return apks.toArray(new ApkFile[apks.size()]);
}
+
+ private static final boolean VERIFY;
+ static {
+ VERIFY = Boolean.getBoolean("daneel.verify");
+ }
}
diff -r 19915795c08c -r cf71c6ab82fc src/main/java/org/icedrobot/daneel/loader/Verifier.java
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/org/icedrobot/daneel/loader/Verifier.java Fri Apr 01 11:15:49 2011 +0200
@@ -0,0 +1,478 @@
+/*
+ * Daneel - Dalvik to Java bytecode compiler
+ * Copyright (C) 2011 IcedRobot team
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ *
+ * This file is subject to the "Classpath" exception:
+ *
+ * Linking this library statically or dynamically with other modules is
+ * making a combined work based on this library. Thus, the terms and
+ * conditions of the GNU General Public License cover the whole
+ * combination.
+ *
+ * As a special exception, the copyright holders of this library give you
+ * permission to link this library with independent modules to produce an
+ * executable, regardless of the license terms of these independent
+ * modules, and to copy and distribute the resulting executable under terms
+ * of your choice, provided that you also meet, for each linked independent
+ * module, the terms and conditions of the license of that module. An
+ * independent module is a module which is not derived from or based on
+ * this library. If you modify this library, you may extend this exception
+ * to your version of the library, but you are not obligated to do so. If
+ * you do not wish to do so, delete this exception statement from your
+ * version.
+ */
+
+/*
+ * A non negligible part of this code comes from a code
+ * that can be found in ASM's class file CheckClassAdapter.java.
+ *
+ * ASM: a very small and fast Java bytecode manipulation framework
+ * Copyright (c) 2000-2007 INRIA, France Telecom
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package org.icedrobot.daneel.loader;
+
+import java.io.PrintWriter;
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+
+import org.icedrobot.daneel.dex.DexAnnotationVisitor;
+import org.icedrobot.daneel.dex.DexClassVisitor;
+import org.icedrobot.daneel.dex.DexFieldVisitor;
+import org.icedrobot.daneel.dex.DexFile;
+import org.icedrobot.daneel.dex.DexMethodVisitor;
+import org.icedrobot.daneel.dex.DexReader;
+import org.icedrobot.daneel.dex.Label;
+import org.icedrobot.daneel.dex.Opcode;
+import org.icedrobot.daneel.rewriter.DexRewriter.MethodRewriter;
+import org.icedrobot.daneel.rewriter.Interpreter;
+import org.icedrobot.daneel.util.TypeUtil;
+import org.objectweb.asm.ClassReader;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
+import org.objectweb.asm.commons.EmptyVisitor;
+import org.objectweb.asm.tree.ClassNode;
+import org.objectweb.asm.tree.MethodNode;
+import org.objectweb.asm.tree.TryCatchBlockNode;
+import org.objectweb.asm.tree.analysis.Analyzer;
+import org.objectweb.asm.tree.analysis.Frame;
+import org.objectweb.asm.tree.analysis.SimpleVerifier;
+import org.objectweb.asm.util.CheckClassAdapter;
+import org.objectweb.asm.util.TraceMethodVisitor;
+
+class Verifier {
+ public static void verify(ClassLoader classloader, DexFile dexFile, String className, byte[] bytecode, PrintWriter writer) {
+ ClassReader reader = new ClassReader(bytecode);
+ ClassNode node = new ClassNode();
+ reader.accept(new CheckClassAdapter(node, false),
+ ClassReader.SKIP_DEBUG);
+
+ Type superType = (node.superName == null) ? null : Type
+ .getObjectType(node.superName);
+
+ @SuppressWarnings("unchecked")
+ List interfaces = node.interfaces;
+ Type[] interfazes = new Type[interfaces.size()];
+ for (int i = 0; i < interfazes.length; i++) {
+ interfazes[i] = Type.getObjectType(interfaces.get(i));
+ }
+
+ @SuppressWarnings("unchecked")
+ List methods = node.methods;
+ String internalName = node.name;
+ for (int i = 0; i < methods.size(); i++) {
+ MethodNode method = methods.get(i);
+ SimpleVerifier verifier = new SimpleVerifier(
+ Type.getObjectType(internalName),
+ superType,
+ Arrays.asList(interfazes),
+ (node.access & ~Opcodes.ACC_INTERFACE) != 0);
+ Analyzer analyzer = new Analyzer(verifier);
+ verifier.setClassLoader(classloader);
+
+ try {
+ analyzer.analyze(internalName, method);
+ } catch (Exception e) {
+ dump(dexFile, className, method, analyzer, writer);
+ e.printStackTrace(writer);
+ }
+ }
+ writer.flush();
+ }
+
+ private static void dump(DexFile dexFile, final String className, final MethodNode method,
+ Analyzer analyzer, final PrintWriter writer) {
+ writer.println("--- DEX bytecode");
+ try {
+ dexFile.accept("L" + className.replace('.', '/') + ";", new DexClassVisitor() {
+ @Override
+ public void visit(int access, String name, String supername,
+ String[] interfaces) {
+ // nothing
+ }
+
+ @Override
+ public void visitSource(String source) {
+ // nothing
+ }
+
+ @Override
+ public DexAnnotationVisitor visitAnnotation(int visibility, String type) {
+ return null;
+ }
+
+ @Override
+ public DexMethodVisitor visitMethod(int access, String name, String shorty,
+ String returnType, String[] parameterTypes) {
+
+ String desc = TypeUtil.convertProtoToDesc(returnType, parameterTypes);
+ if (!name.equals(method.name) || !desc.equals(method.desc)) {
+ return null;
+ }
+
+ final MethodRewriter mv = new MethodRewriter(new EmptyVisitor(),
+ (access & Opcodes.ACC_STATIC) != 0,
+ desc);
+
+ writer.println(className+'.'+method.name + method.desc);
+ return new DexMethodVisitor() {
+ private final HashMap