changeset 72:57fe21b3757e

Added method to identify jump target labels. Reviewed-by: Remi Forax * dex/Label.java (isJumpTarget): Added new abstract method. * dex/Code.java: Correctly mark jump target labels. * dex/DebugInfo.java: Likewise.
author Michael Starzinger <michi@complang.tuwien.ac.at>
date Wed, 23 Mar 2011 23:18:49 +0100
parents e2aee3228a72
children 15cfcc7a8756
files src/main/java/org/icedrobot/daneel/dex/Code.java src/main/java/org/icedrobot/daneel/dex/DebugInfo.java src/main/java/org/icedrobot/daneel/dex/Label.java
diffstat 3 files changed, 62 insertions(+), 19 deletions(-) [+]
line wrap: on
line diff
--- a/src/main/java/org/icedrobot/daneel/dex/Code.java	Wed Mar 23 11:00:12 2011 +0100
+++ b/src/main/java/org/icedrobot/daneel/dex/Code.java	Wed Mar 23 23:18:49 2011 +0100
@@ -131,8 +131,8 @@
             }
             ByteBuffer buf = buffer.slice();
             for (int i = 0; i < triesSize; i++) {
-                Label startLabel = putLabel(startAddr[i]);
-                Label endLabel = putLabel(startAddr[i] + insnCount[i]);
+                Label startLabel = putLabel(startAddr[i], false);
+                Label endLabel = putLabel(startAddr[i] + insnCount[i], false);
                 buf.position(handlerOff[i]);
                 // Note that size is a signed value here, which indicates
                 // whether the try-block has a catch-all handler or not.
@@ -730,7 +730,7 @@
      */
     private void addTryCatch(Label startLabel, Label endLabel, String type,
             int handlerAddr) {
-        Label handlerLabel = putLabel(handlerAddr);
+        Label handlerLabel = putLabel(handlerAddr, true);
         TryCatchInfo info = new TryCatchInfo(startLabel, endLabel,
                 handlerLabel, type);
         tryCatchInfos.add(info);
@@ -761,15 +761,25 @@
      * which call it, to avoid trampoline code.
      * 
      * @param pos The given bytecode position in 16-bit code units.
+     * @param jumpTarget Indicates whether the label should be marked as a jump
+     *        target or not. That information can be useful for the visitor and
+     *        is passed out through the {@link Label#isJumpTarget()} method.
      * @return The associated label, never returns {@code null}.
      */
-    Label putLabel(int pos) {
+    Label putLabel(int pos, boolean jumpTarget) {
         if (pos < 0 || pos >= insnsSize)
             throw new DexParseException("Label position out of range: " + pos);
         Label label = labelMap.get(pos);
         if (label == null) {
-            label = new DebugLabel(pos);
+            label = new DebugLabel(pos, jumpTarget);
             labelMap.put(pos, label);
+        } else {
+            if (jumpTarget & !label.isJumpTarget()) {
+                if (!(label instanceof DebugLabel))
+                    throw new DexParseException("Cannot mark label as target.");
+                DebugLabel debugLabel = (DebugLabel) label;
+                debugLabel.setJumpTarget();
+            }
         }
         return label;
     }
@@ -830,7 +840,7 @@
             case GOTO:
                 // Format 10t: AA|op
                 // Syntax: op +AA
-                putLabel(pos + (s1 >> 8));
+                putLabel(pos + (s1 >> 8), true);
                 break;
 
             case GOTO_16:
@@ -856,7 +866,7 @@
             case IF_LEZ:
                 // Format 21t: AA|op BBBB
                 // Syntax: op vAA, +BBBB
-                putLabel(pos + s2);
+                putLabel(pos + s2, true);
                 break;
 
             case FILL_ARRAY_DATA:
@@ -961,12 +971,17 @@
             int firstKey = buffer.getInt();
             int[] targets = BufferUtil.getInts(buffer, size);
             for (int i = 0; i < size; i++)
-                map.put(firstKey + i, putLabel(pos + targets[i]));
+                map.put(firstKey + i, putLabel(pos + targets[i], true));
         }
 
         public int length() {
             return (size * 2) + 4;
         }
+
+        @Override
+        public boolean isJumpTarget() {
+            return false;
+        }
     };
 
     /**
@@ -984,12 +999,17 @@
             int[] keys = BufferUtil.getInts(buffer, size);
             int[] targets = BufferUtil.getInts(buffer, size);
             for (int i = 0; i < size; i++)
-                map.put(keys[i], putLabel(pos + targets[i]));
+                map.put(keys[i], putLabel(pos + targets[i], true));
         }
 
         public int length() {
             return (size * 4) + 2;
         }
+
+        @Override
+        public boolean isJumpTarget() {
+            return false;
+        }
     };
 
     /**
@@ -1012,22 +1032,38 @@
         public int length() {
             return (size * elementWidth + 1) / 2 + 4;
         }
+
+        @Override
+        public boolean isJumpTarget() {
+            return false;
+        }
     };
 
     /**
      * A label as defined by the interface, but enriched with additional debug
      * information.
      */
-    private static class DebugLabel extends Label {
+    static class DebugLabel extends Label {
         private final int pos;
+        private boolean jumpTarget;
 
-        public DebugLabel(int pos) {
+        public DebugLabel(int pos, boolean jumpTarget) {
             this.pos = pos;
+            this.jumpTarget = jumpTarget;
+        }
+
+        @Override
+        public boolean isJumpTarget() {
+            return jumpTarget;
+        }
+
+        public void setJumpTarget() {
+            this.jumpTarget = true;
         }
 
         @Override
         public String toString() {
-            return String.format("L%03d", pos);
+            return String.format("L%03d%s", pos, jumpTarget ? "*" : "");
         }
     };
 }
--- a/src/main/java/org/icedrobot/daneel/dex/DebugInfo.java	Wed Mar 23 11:00:12 2011 +0100
+++ b/src/main/java/org/icedrobot/daneel/dex/DebugInfo.java	Wed Mar 23 23:18:49 2011 +0100
@@ -41,6 +41,7 @@
 import java.util.LinkedList;
 import java.util.List;
 
+import org.icedrobot.daneel.dex.Code.DebugLabel;
 import org.icedrobot.daneel.util.BufferUtil;
 
 /**
@@ -194,7 +195,7 @@
                     // XXX Check why this happens, this shouldn't happen.
                     //throw new DexParseException("No live local in register.");
                     break;
-                local.setEnd(code.putLabel(addr));
+                local.setEnd(code.putLabel(addr, false));
                 break;
 
             case DBG_RESTART_LOCAL:
@@ -243,7 +244,7 @@
      */
     private LocalVariable emitLocalVariable(int regNum, int startAddr,
             int nameIdx, int typeIdx, int sigIdx) {
-        Label startLabel = code.putLabel(startAddr);
+        Label startLabel = code.putLabel(startAddr, false);
         LocalVariable local = new LocalVariable(regNum, nameIdx, typeIdx,
                 sigIdx, startLabel);
         localVariables.add(local);
@@ -301,18 +302,17 @@
      * A label as defined by the interface, but enriched with additional debug
      * and line number information.
      */
-    static class LineNumberLabel extends Label {
-        private final int pos;
+    static class LineNumberLabel extends DebugLabel {
         final int line;
 
         public LineNumberLabel(int pos, int line) {
-            this.pos = pos;
+            super(pos, false);
             this.line = line;
         }
 
         @Override
         public String toString() {
-            return String.format("L%03d[line=%d]", pos, line);
+            return String.format("%s[line=%d]", super.toString(), line);
         }
     };
 }
--- a/src/main/java/org/icedrobot/daneel/dex/Label.java	Wed Mar 23 11:00:12 2011 +0100
+++ b/src/main/java/org/icedrobot/daneel/dex/Label.java	Wed Mar 23 23:18:49 2011 +0100
@@ -40,6 +40,13 @@
 /**
  * A label referencing a certain position in Dalvik VM bytecode.
  */
-public class Label {
+public abstract class Label {
 
+    /**
+     * Checks whether this label is used as a jump target for any instruction in
+     * the code it is associated with.
+     * 
+     * @return True if label is used as jump target, false otherwise.
+     */
+    public abstract boolean isJumpTarget();
 }