Guest User

Untitled

a guest
Jan 2nd, 2014
218
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 6.50 KB | None | 0 0
  1. /**
  2.  *  MicroEmulator
  3.  *  Copyright (C) 2006-2007 Bartek Teodorczyk <[email protected]>
  4.  *  Copyright (C) 2006-2007 Vlad Skarzhevskyy
  5.  *
  6.  *  It is licensed under the following two licenses as alternatives:
  7.  *    1. GNU Lesser General Public License (the "LGPL") version 2.1 or any newer version
  8.  *    2. Apache License (the "AL") Version 2.0
  9.  *
  10.  *  You may not use this file except in compliance with at least one of
  11.  *  the above two licenses.
  12.  *
  13.  *  You may obtain a copy of the LGPL at
  14.  *      http://www.gnu.org/licenses/old-licenses/lgpl-2.1.txt
  15.  *
  16.  *  You may obtain a copy of the AL at
  17.  *      http://www.apache.org/licenses/LICENSE-2.0
  18.  *
  19.  *  Unless required by applicable law or agreed to in writing, software
  20.  *  distributed under the License is distributed on an "AS IS" BASIS,
  21.  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  22.  *  See the LGPL or the AL for the specific language governing permissions and
  23.  *  limitations.
  24.  *
  25.  *  @version $Id: ChangeCallsMethodVisitor.java 2092 2009-06-13 10:14:45Z barteo $
  26.  */
  27. package org.microemu.app.classloader;
  28.  
  29. import java.util.HashMap;
  30.  
  31. import org.microemu.Injected;
  32. import org.microemu.app.util.MIDletThread;
  33. import org.microemu.app.util.MIDletTimer;
  34. import org.microemu.app.util.MIDletTimerTask;
  35. import org.objectweb.asm.Label;
  36. import org.objectweb.asm.MethodAdapter;
  37. import org.objectweb.asm.MethodVisitor;
  38. import org.objectweb.asm.Opcodes;
  39.  
  40. /**
  41.  * @author vlads
  42.  *
  43.  */
  44. public class ChangeCallsMethodVisitor extends MethodAdapter implements Opcodes {
  45.  
  46.     private static final String INJECTED_CLASS = codeName(Injected.class);
  47.    
  48.     static String NEW_SYSTEM_OUT_CLASS = INJECTED_CLASS;
  49.    
  50.     static String NEW_SYSTEM_PROPERTIES_CLASS = INJECTED_CLASS;
  51.    
  52.     static String NEW_RESOURCE_LOADER_CLASS = INJECTED_CLASS;
  53.    
  54.     private HashMap catchInfo;
  55.    
  56.     private InstrumentationConfig config;
  57.    
  58.     private static class CatchInformation {
  59.        
  60.         Label label;
  61.        
  62.         String type;
  63.  
  64.         public CatchInformation(String type) {
  65.             this.label = new Label();
  66.             this.type = type;
  67.         }
  68.     }
  69.    
  70.     public ChangeCallsMethodVisitor(MethodVisitor mv, InstrumentationConfig config) {
  71.         super(mv);
  72.         this.config = config;
  73.     }
  74.  
  75.     public static String codeName(Class klass) {
  76.         return klass.getName().replace('.', '/');
  77.     }
  78.  
  79.     public void visitFieldInsn(final int opcode, final String owner, final String name, final String desc) {
  80.         switch (opcode) {
  81.         case GETSTATIC:
  82.             if ((name.equals("out")) && (owner.equals("java/lang/System"))) {
  83.                 //System.out.println("owner " + owner + " name " + name + " desc " + desc);
  84.                 // GETSTATIC System.out : PrintStream
  85.                 mv.visitFieldInsn(opcode, NEW_SYSTEM_OUT_CLASS, name, desc);
  86.                 return;
  87.             }
  88.             if ((name.equals("err")) && (owner.equals("java/lang/System"))) {
  89.                 //System.out.println("owner " + owner + " name " + name + " desc " + desc);
  90.                 // GETSTATIC System.out : PrintStream
  91.                 mv.visitFieldInsn(opcode, NEW_SYSTEM_OUT_CLASS, name, desc);
  92.                 return;
  93.             }
  94.             break;
  95.  
  96.         }
  97.         mv.visitFieldInsn(opcode, owner, name, desc);
  98.     }
  99.    
  100.     public void visitMethodInsn(int opcode, String owner, String name, String desc) {
  101.         switch (opcode) {
  102.         case INVOKESTATIC:
  103.             //System.out.println("Method owner " + owner + " name " + name + " desc " + desc);
  104.             if ((name.equals("getProperty")) && (owner.equals("java/lang/System"))) {
  105.                 // INVOKESTATIC
  106.                 // java/lang/System.getProperty(Ljava/lang/String;)Ljava/lang/String;
  107.                 mv.visitMethodInsn(opcode, NEW_SYSTEM_PROPERTIES_CLASS, name, desc);
  108.                 return;
  109.             }
  110.             break;
  111.         case INVOKEVIRTUAL:
  112.             if ((name.equals("getResourceAsStream")) && (owner.equals("java/lang/Class"))) {
  113.                 // INVOKEVIRTUAL
  114.                 // java/lang/Class.getResourceAsStream(Ljava/lang/String;)Ljava/io/InputStream;
  115.                 // "org/microemu/ResourceLoader", "getResourceAsStream", "(Ljava/lang/Class;Ljava/lang/String;)Ljava/io/InputStream;");
  116.                 mv.visitMethodInsn(INVOKESTATIC, NEW_RESOURCE_LOADER_CLASS, name, "(Ljava/lang/Class;Ljava/lang/String;)Ljava/io/InputStream;");
  117.                 return;
  118.             } else if ((name.equals("printStackTrace")) && (owner.equals("java/lang/Throwable"))) {
  119.                 // INVOKEVIRTUAL java/lang/Throwable.printStackTrace()V
  120.                 mv.visitMethodInsn(INVOKESTATIC, INJECTED_CLASS, name, "(Ljava/lang/Throwable;)V");
  121.                 return;
  122.             }
  123.             break;
  124.         case INVOKESPECIAL:
  125.             if  ((config.isEnhanceThreadCreation()) && (name.equals("<init>"))) {
  126.                 if (owner.equals("java/util/Timer")) {
  127.                     owner = codeName(MIDletTimer.class);
  128.                 } else if (owner.equals("java/util/TimerTask")) {
  129.                     owner = codeName(MIDletTimerTask.class);
  130.                 } else if (owner.equals("java/lang/Thread")) {
  131.                     owner = codeName(MIDletThread.class);
  132.                 }
  133.             }
  134.             break;
  135.         }
  136.  
  137.         mv.visitMethodInsn(opcode, owner, name, desc);
  138.     }
  139.    
  140.     public void visitTypeInsn(final int opcode, String desc) {
  141.         if ((opcode == NEW) && (config.isEnhanceThreadCreation())) {
  142.             if ("java/util/Timer".equals(desc)) {
  143.                 desc = codeName(MIDletTimer.class);
  144.             } else if ("java/util/TimerTask".equals(desc)) {
  145.                 desc = codeName(MIDletTimerTask.class);
  146.             } else if ("java/lang/Thread".equals(desc)) {
  147.                 desc = codeName(MIDletThread.class);
  148.             }
  149.         }
  150.         mv.visitTypeInsn(opcode, desc);
  151.     }
  152.    
  153.     public void visitTryCatchBlock(final Label start, final Label end, final Label handler, final String type) {
  154.         if (config.isEnhanceCatchBlock() && type != null) {
  155.             if (catchInfo == null) {
  156.                 catchInfo = new HashMap();
  157.             }
  158.             CatchInformation newHandler = (CatchInformation)catchInfo.get(handler);
  159.             if (newHandler == null) {
  160.                 newHandler = new CatchInformation(type);
  161.                 catchInfo.put(handler, newHandler);
  162.             }
  163.             mv.visitTryCatchBlock(start, end, newHandler.label, type);
  164.         } else {
  165.             mv.visitTryCatchBlock(start, end, handler, type);
  166.         }
  167.     }
  168.    
  169.     //TODO make this work for gMaps case
  170.     public void visitLabel(Label label) {
  171.         if (config.isEnhanceCatchBlock() && catchInfo != null) {
  172.             CatchInformation newHandler = (CatchInformation)catchInfo.get(label);
  173.             if (newHandler != null) {
  174.                 mv.visitLabel(newHandler.label);
  175.                 // no push, just use current Throwable in stack
  176.                 mv.visitMethodInsn(INVOKESTATIC, INJECTED_CLASS, "handleCatchThrowable", "(Ljava/lang/Throwable;)Ljava/lang/Throwable;");
  177.                 // stack contains Throwable, just verify that it is right type for this handler
  178.                 mv.visitTypeInsn(CHECKCAST, newHandler.type);
  179.             }  
  180.         }
  181.         mv.visitLabel(label);
  182.     }
  183.    
  184. }
Advertisement
Add Comment
Please, Sign In to add comment