/* * Copyright 2015 the original author or authors. * @https://github.com/scouter-project/scouter * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package scouter.agent.asm.util; import scouter.org.objectweb.asm.MethodVisitor; import scouter.org.objectweb.asm.Opcodes; import scouter.org.objectweb.asm.Type; import java.util.Map; /** * BCI for a constructor of PreparedStatement * @author @author Paul S.J. Kim(sjkim@whatap.io) * @author Gun Lee (gunlee01@gmail.com) */ public class AsmUtil implements Opcodes { public static boolean isStatic(int access) { return (access & ACC_STATIC) != 0; } public static boolean isPublic(int access) { return (access & ACC_PUBLIC) != 0; } public static Type stringType = Type.getType(String.class); public static String makeMethodFullName(String className, String methodName, String methodSignature) { return new StringBuffer().append(className.replace('/','.')).append(".").append(methodName).append(methodSignature).toString(); } public static void add(Map<String, HookingSet> classSet, String klass, String method) { klass=klass.replace('.', '/'); HookingSet mset = classSet.get(klass); if (mset == null) { mset = new HookingSet(); classSet.put(klass, mset); } mset.add(method); } public static void PUSH(MethodVisitor mv, int value) { if ((value >= -1) && (value <= 5)) // Use ICONST_n mv.visitInsn(ICONST_0 + value); else if ((value >= -128) && (value <= 127)) // Use BIPUSH mv.visitIntInsn(BIPUSH, value); else if ((value >= -32768) && (value <= 32767)) // Use SIPUSH mv.visitIntInsn(SIPUSH, value); else mv.visitLdcInsn(new Integer(value)); } public static void PUSH(MethodVisitor mv, boolean value) { mv.visitInsn(ICONST_0 + (value ? 1 : 0)); } public static void PUSH(MethodVisitor mv, float value) { if (value == 0.0) mv.visitInsn(FCONST_0); else if (value == 1.0) mv.visitInsn(FCONST_1); else if (value == 2.0) mv.visitInsn(FCONST_2); else mv.visitLdcInsn(new Float(value)); } public static void PUSH(MethodVisitor mv, long value) { if (value == 0) mv.visitInsn(LCONST_0); else if (value == 1) mv.visitInsn(LCONST_1); else mv.visitLdcInsn(new Long(value)); // LDC2_W } /** * @param mv * @param value */ public static void PUSH(MethodVisitor mv, double value) { if (value == 0) mv.visitInsn(DCONST_0); else if (value == 1) mv.visitInsn(DCONST_1); else mv.visitLdcInsn(new Double(value)); } public static void PUSHNULL(MethodVisitor mv) { mv.visitInsn(ACONST_NULL); } public static void PUSH(MethodVisitor mv, String value) { if (value == null) mv.visitInsn(ACONST_NULL); else mv.visitLdcInsn(value); } public static void PUSH(MethodVisitor mv, Number value) { if ((value instanceof Integer) || (value instanceof Short) || (value instanceof Byte)) PUSH(mv, value.intValue()); else if (value instanceof Double) PUSH(mv, value.doubleValue()); else if (value instanceof Float) PUSH(mv, value.floatValue()); else if (value instanceof Long) PUSH(mv, value.longValue()); else throw new RuntimeException("What's this: " + value); } public static void PUSH(MethodVisitor mv, Character value) { PUSH(mv, (int) value.charValue()); } public static void PUSH(MethodVisitor mv, Boolean value) { PUSH(mv, value.booleanValue()); } public static int getStringIdx(int access, String desc) { return getIdxByType(access, desc, AsmUtil.stringType); /*Type[] t = Type.getArgumentTypes(desc); int sidx = (AsmUtil.isStatic(access) ? 0 : 1); for (int i = 0; t != null && i < t.length; i++) { if (AsmUtil.stringType.equals(t[i])) { return sidx; } sidx += t[i].getSize(); } return -1;*/ } public static int getIdxByType(int access, String desc, Type type) { Type[] t = Type.getArgumentTypes(desc); int sidx = (AsmUtil.isStatic(access) ? 0 : 1); for (int i = 0; t != null && i < t.length; i++) { if (type.equals(t[i])) { return sidx; } sidx += t[i].getSize(); } return -1; } public static boolean isSpecial(String name) { //return (name.indexOf("$") >= 0 && name.indexOf("lambda$") != 0) || name.startsWith("<"); //FIXME for testing return name.startsWith("<"); } public static boolean isInterface(int access) { return (access & ACC_INTERFACE) != 0; } public static void loadForArrayElement(MethodVisitor mv, Type tp, int sidx) { switch (tp.getSort()) { case Type.BOOLEAN: mv.visitVarInsn(Opcodes.ILOAD, sidx); mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Boolean", "valueOf", "(Z)Ljava/lang/Boolean;",false); break; case Type.BYTE: mv.visitVarInsn(Opcodes.ILOAD, sidx); mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Byte", "valueOf", "(B)Ljava/lang/Byte;",false); break; case Type.CHAR: mv.visitVarInsn(Opcodes.ILOAD, sidx); mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Character", "valueOf", "(C)Ljava/lang/Character;",false); break; case Type.SHORT: mv.visitVarInsn(Opcodes.ILOAD, sidx); mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Short", "valueOf", "(S)Ljava/lang/Short;",false); break; case Type.INT: mv.visitVarInsn(Opcodes.ILOAD, sidx); mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Integer", "valueOf", "(I)Ljava/lang/Integer;",false); break; case Type.LONG: mv.visitVarInsn(Opcodes.LLOAD, sidx); mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Long", "valueOf", "(J)Ljava/lang/Long;",false); break; case Type.FLOAT: mv.visitVarInsn(Opcodes.FLOAD, sidx); mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Float", "valueOf", "(F)Ljava/lang/Float;",false); break; case Type.DOUBLE: mv.visitVarInsn(Opcodes.DLOAD, sidx); mv.visitMethodInsn(Opcodes.INVOKESTATIC, "java/lang/Double", "valueOf", "(D)Ljava/lang/Double;",false); break; default: mv.visitVarInsn(Opcodes.ALOAD, sidx); } } }