changeset 26:b27ad11dfcf9

Added utility class for name and type mangling. Reviewed-by: Roman Kennke * util/TypeUtil.java: New utility class. * rewriter/DexRewriter.java (visitMethod): Switched to above utility. * dex/Code.java (acceptInsns): Likewise. * ClassTransformer.java: Likewise.
author Michael Starzinger <michi@complang.tuwien.ac.at>
date Wed, 16 Mar 2011 23:13:52 +0100
parents da537f70dec2
children b0d7f00453ea
files src/main/java/org/icedrobot/daneel/ClassTransformer.java src/main/java/org/icedrobot/daneel/dex/Code.java src/main/java/org/icedrobot/daneel/rewriter/DexRewriter.java src/main/java/org/icedrobot/daneel/util/TypeUtil.java
diffstat 4 files changed, 82 insertions(+), 30 deletions(-) [+]
line wrap: on
line diff
--- a/src/main/java/org/icedrobot/daneel/ClassTransformer.java	Wed Mar 16 22:52:53 2011 +0100
+++ b/src/main/java/org/icedrobot/daneel/ClassTransformer.java	Wed Mar 16 23:13:52 2011 +0100
@@ -21,6 +21,7 @@
 import org.icedrobot.daneel.dex.ClassData;
 import org.icedrobot.daneel.dex.ClassDef;
 import org.icedrobot.daneel.dex.FieldId;
+import org.icedrobot.daneel.util.TypeUtil;
 import org.objectweb.asm.ClassWriter;
 import org.objectweb.asm.Opcodes;
 
@@ -52,8 +53,8 @@
 
     private void visitClass() {
         int access = classDef.getAccessFlags();
-        String name = extractName(classDef.getClassName());
-        String superName = extractName(classDef.getSuperclass());
+        String name = TypeUtil.convertDescToInternal(classDef.getClassName());
+        String superName = TypeUtil.convertDescToInternal(classDef.getSuperclass());
         writer.visit(Opcodes.V1_6, access, name, null, superName, null);
     }
 
@@ -71,18 +72,4 @@
         writer.visitEnd();
         return writer.toByteArray();
     }
-
-    /**
-     * Converts a type descriptor for a class type into an internal class name
-     * as the ASM library expects it. For details about those type names see the
-     * "ASM 3.0 User Guide, Section 2.1.2 and 2.1.3".
-     * 
-     * @param desc The given type descriptor.
-     * @return The internal class name.
-     */
-    private static String extractName(String desc) {
-        if (!desc.startsWith("L") || !desc.endsWith(";"))
-            throw new DaneelException("Descriptor is not a class type.");
-        return desc.substring(1, desc.length() - 1);
-    }
 }
--- a/src/main/java/org/icedrobot/daneel/dex/Code.java	Wed Mar 16 22:52:53 2011 +0100
+++ b/src/main/java/org/icedrobot/daneel/dex/Code.java	Wed Mar 16 23:13:52 2011 +0100
@@ -26,6 +26,7 @@
 import java.util.Map;
 
 import org.icedrobot.daneel.util.BufferUtil;
+import org.icedrobot.daneel.util.TypeUtil;
 
 /**
  * A parser class capable of parsing {@code code_item} structures as part of DEX
@@ -496,9 +497,10 @@
                 // Format 35c B|A|op CCCC G|F|E|D
                 // Syntax: op {vD, vE, vF, vG, vA}, meth@CCCC
                 method = dex.getMethodId(u2);
-                // XXX Don't use the shorty as type descriptor.
+                string = TypeUtil.convertProtoToDesc(method.getProtoId()
+                        .getReturnType(), method.getProtoId().getParameters());
                 v.visitInstrMethod(op, n1, n2, u3, method.getClassName(),
-                        method.getName(), method.getProtoId().getShorty());
+                        method.getName(), string);
                 break;
 
             case INVOKE_VIRTUAL_RANGE:
@@ -509,9 +511,10 @@
                 // Format 3rc AA|op BBBB CCCC
                 // Syntax: op {vCCCC .. vNNNN}, meth@BBBB
                 method = dex.getMethodId(u2);
-                // XXX Don't use the shorty as type descriptor.
+                string = TypeUtil.convertProtoToDesc(method.getProtoId()
+                        .getReturnType(), method.getProtoId().getParameters());
                 v.visitInstrMethod(op, b1, u3, 0, method.getClassName(),
-                        method.getName(), method.getProtoId().getShorty());
+                        method.getName(), string);
                 break;
 
             case CMPL_FLOAT:
--- a/src/main/java/org/icedrobot/daneel/rewriter/DexRewriter.java	Wed Mar 16 22:52:53 2011 +0100
+++ b/src/main/java/org/icedrobot/daneel/rewriter/DexRewriter.java	Wed Mar 16 23:13:52 2011 +0100
@@ -12,6 +12,7 @@
 import org.icedrobot.daneel.dex.DexMethodVisitor;
 import org.icedrobot.daneel.dex.Label;
 import org.icedrobot.daneel.dex.Opcode;
+import org.icedrobot.daneel.util.TypeUtil;
 import org.objectweb.asm.ClassVisitor;
 import org.objectweb.asm.FieldVisitor;
 import org.objectweb.asm.MethodVisitor;
@@ -57,16 +58,8 @@
     @Override
     public DexMethodVisitor visitMethod(int access, String name, String shorty,
             String returnType, String[] parameterTypes) {
-        StringBuilder desc = new StringBuilder();
-        desc.append('(');
-        for (String parameterType : parameterTypes) {
-            desc.append(parameterType);
-        }
-        desc.append(')');
-        desc.append(returnType);
-
-        MethodVisitor mv = cv.visitMethod(access, name, desc.toString(), null,
-                null);
+        String desc = TypeUtil.convertProtoToDesc(returnType, parameterTypes);
+        MethodVisitor mv = cv.visitMethod(access, name, desc, null, null);
         if (mv == null) {
             return null;
         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main/java/org/icedrobot/daneel/util/TypeUtil.java	Wed Mar 16 23:13:52 2011 +0100
@@ -0,0 +1,69 @@
+/*
+ * 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 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 License for more details.
+ *
+ * You should have received a copy of the GNU General License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.icedrobot.daneel.util;
+
+import org.icedrobot.daneel.DaneelException;
+
+/**
+ * Utility methods for mangling names and type descriptors. For specifications
+ * about the differences between each form of representation you should visit
+ * the following material:
+ * <ul>
+ * <li>The Java(TM) Virtual Machine Specification, Section 4.2 and 4.3</li>
+ * <li>DEX - Dalvik Executable Format, Section "String Syntax"</li>
+ * <li>ASM 3.0 User Guide, Section 2.1.2 and 2.1.3</li>
+ * </ul>
+ */
+public class TypeUtil {
+
+    /**
+     * Converts a method prototype (separate type descriptors for return type
+     * and parameter types) into a method descriptor.
+     * 
+     * @param returnType The method's return type as a type descriptor or
+     *        {@code "V"} in case the method returns {@code void}.
+     * @param parameterTypes The method's parameter types as type descriptors or
+     *        {@code null} in case there are none.
+     * @return The method descriptor for the given method prototype.
+     */
+    public static String convertProtoToDesc(String returnType,
+            String[] parameterTypes) {
+        StringBuilder builder = new StringBuilder();
+        builder.append('(');
+        if (parameterTypes != null)
+            for (String parameterType : parameterTypes)
+                builder.append(parameterType);
+        builder.append(')');
+        builder.append(returnType);
+        return builder.toString();
+    }
+
+    /**
+     * Converts a type descriptor for a class type into a fully qualified
+     * internal class name.
+     * 
+     * @param desc The given type descriptor for a class type.
+     * @return The internal class name for the given type descriptor.
+     */
+    public static String convertDescToInternal(String desc) {
+        if (!desc.startsWith("L") || !desc.endsWith(";"))
+            throw new DaneelException("Descriptor is not a class type.");
+        return desc.substring(1, desc.length() - 1);
+    }
+}