All Downloads are FREE. Search and download functionalities are using the official Maven repository.

soot.asm.AsmUtil Maven / Gradle / Ivy

package soot.asm;

/*-
 * #%L
 * Soot - a J*va Optimization Framework
 * %%
 * Copyright (C) 1997 - 2014 Raja Vallee-Rai and others
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation, either version 2.1 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 Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public
 * License along with this program.  If not, see
 * .
 * #L%
 */

import java.util.ArrayList;
import java.util.List;

import soot.ArrayType;
import soot.BooleanType;
import soot.ByteType;
import soot.CharType;
import soot.DoubleType;
import soot.FloatType;
import soot.IntType;
import soot.LongType;
import soot.RefLikeType;
import soot.RefType;
import soot.ShortType;
import soot.SootClass;
import soot.Type;
import soot.VoidType;

/**
 * Contains static utility methods.
 * 
 * @author Aaloan Miftah
 */
/**
 * @author eric
 *
 */
public class AsmUtil {

  /**
   * Determines if a type is a dword type.
   * 
   * @param type
   *          the type to check.
   * @return {@code true} if its a dword type.
   */
  public static boolean isDWord(Type type) {
    return type instanceof LongType || type instanceof DoubleType;
  }

  /**
   * Converts an internal class name to a Type.
   * 
   * @param internal
   *          internal name.
   * @return type
   */
  public static Type toBaseType(String internal) {
    if (internal.charAt(0) == '[') {
      /* [Ljava/lang/Object; */
      internal = internal.substring(internal.lastIndexOf('[') + 1, internal.length());
      /* Ljava/lang/Object */
    }
    if (internal.charAt(internal.length() - 1) == ';') {
      internal = internal.substring(0, internal.length() - 1);
      // we need to have this guarded by a ; check as you can have a situation
      // were a call is called Lxxxxx with now leading package name. Rare, but it
      // happens. However, you need to strip the leading L it will always be
      // followed by a ; per
      // http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html
      if (internal.charAt(0) == 'L') {
        internal = internal.substring(1, internal.length());
      }
      internal = toQualifiedName(internal);
      return RefType.v(internal);
    }
    switch (internal.charAt(0)) {
      case 'Z':
        return BooleanType.v();
      case 'B':
        return ByteType.v();
      case 'C':
        return CharType.v();
      case 'S':
        return ShortType.v();
      case 'I':
        return IntType.v();
      case 'F':
        return FloatType.v();
      case 'J':
        return LongType.v();
      case 'D':
        return DoubleType.v();
      default:
        internal = toQualifiedName(internal);
        return RefType.v(internal);
    }
  }

  /**
   * Converts an internal class name to a fully qualified name.
   * 
   * @param internal
   *          internal name.
   * @return fully qualified name.
   */
  public static String toQualifiedName(String internal) {
    return internal.replace('/', '.');
  }

  /**
   * Converts a fully qualified class name to an internal name.
   * 
   * @param qual
   *          fully qualified class name.
   * @return internal name.
   */
  public static String toInternalName(String qual) {
    return qual.replace('.', '/');
  }

  /**
   * Determines and returns the internal name of a class.
   * 
   * @param cls
   *          the class.
   * @return corresponding internal name.
   */
  public static String toInternalName(SootClass cls) {
    return toInternalName(cls.getName());
  }

  /**
   * Converts a type descriptor to a Jimple reference type.
   * 
   * @param desc
   *          the descriptor.
   * @return the reference type.
   */
  public static Type toJimpleRefType(String desc) {
    return desc.charAt(0) == '[' ? toJimpleType(desc) : RefType.v(toQualifiedName(desc));
  }

  /**
   * Converts a type descriptor to a Jimple type.
   * 
   * @param desc
   *          the descriptor.
   * @return equivalent Jimple type.
   */
  public static Type toJimpleType(String desc) {
    int idx = desc.lastIndexOf('[');
    int nrDims = idx + 1;
    if (nrDims > 0) {
      if (desc.charAt(0) != '[') {
        throw new AssertionError("Invalid array descriptor: " + desc);
      }
      desc = desc.substring(idx + 1);
    }
    Type baseType;
    switch (desc.charAt(0)) {
      case 'Z':
        baseType = BooleanType.v();
        break;
      case 'B':
        baseType = ByteType.v();
        break;
      case 'C':
        baseType = CharType.v();
        break;
      case 'S':
        baseType = ShortType.v();
        break;
      case 'I':
        baseType = IntType.v();
        break;
      case 'F':
        baseType = FloatType.v();
        break;
      case 'J':
        baseType = LongType.v();
        break;
      case 'D':
        baseType = DoubleType.v();
        break;
      case 'L':
        if (desc.charAt(desc.length() - 1) != ';') {
          throw new AssertionError("Invalid reference descriptor: " + desc);
        }
        String name = desc.substring(1, desc.length() - 1);
        name = toQualifiedName(name);
        baseType = RefType.v(name);
        break;
      default:
        throw new AssertionError("Unknown descriptor: " + desc);
    }
    if (!(baseType instanceof RefLikeType) && desc.length() > 1) {
      throw new AssertionError("Invalid primitive type descriptor: " + desc);
    }
    return nrDims > 0 ? ArrayType.v(baseType, nrDims) : baseType;
  }

  /**
   * Converts a method signature to a list of types, with the last entry in the returned list denoting the return type.
   * 
   * @param desc
   *          method signature.
   * @return list of types.
   */
  public static List toJimpleDesc(String desc) {
    ArrayList types = new ArrayList(2);
    int len = desc.length();
    int idx = 0;
    all: while (idx != len) {
      int nrDims = 0;
      Type baseType = null;
      this_type: while (idx != len) {
        char c = desc.charAt(idx++);
        switch (c) {
          case '(':
          case ')':
            continue all;
          case '[':
            ++nrDims;
            continue this_type;
          case 'Z':
            baseType = BooleanType.v();
            break this_type;
          case 'B':
            baseType = ByteType.v();
            break this_type;
          case 'C':
            baseType = CharType.v();
            break this_type;
          case 'S':
            baseType = ShortType.v();
            break this_type;
          case 'I':
            baseType = IntType.v();
            break this_type;
          case 'F':
            baseType = FloatType.v();
            break this_type;
          case 'J':
            baseType = LongType.v();
            break this_type;
          case 'D':
            baseType = DoubleType.v();
            break this_type;
          case 'V':
            baseType = VoidType.v();
            break this_type;
          case 'L':
            int begin = idx;
            while (desc.charAt(++idx) != ';') {
              ;
            }
            String cls = desc.substring(begin, idx++);
            baseType = RefType.v(toQualifiedName(cls));
            break this_type;
          default:
            throw new AssertionError("Unknown type: " + c);
        }
      }
      if (baseType != null && nrDims > 0) {
        types.add(ArrayType.v(baseType, nrDims));
      } else {
        types.add(baseType);
      }
    }
    return types;
  }

  /**
   * strips suffix for indicating an array type
   */
  public static String baseTypeName(String s) {
    int index = s.indexOf("[");
    if (index < 0) {
      return s;
    } else {
      return s.substring(0, index);
    }
  }

  private AsmUtil() {
  }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy