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

com.ibm.wala.ipa.summaries.MethodBypass Maven / Gradle / Ivy

/*
 * Copyright (c) 2002 - 2006 IBM Corporation.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 */
package com.ibm.wala.ipa.summaries;

import com.ibm.wala.classLoader.IClass;
import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.classLoader.SyntheticMethod;
import com.ibm.wala.core.util.strings.Atom;
import com.ibm.wala.ipa.cha.IClassHierarchy;
import com.ibm.wala.types.MemberReference;
import com.ibm.wala.types.MethodReference;
import com.ibm.wala.types.TypeReference;
import com.ibm.wala.util.collections.HashMapFactory;
import com.ibm.wala.util.collections.HashSetFactory;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * "Non-standard" bypass rules to use during call graph construction.
 *
 * 

Normally, the method bypass rules replace the IMethod that is resolved by other means, via the * getBypass() method. However, the bypass rules can be invoked even before resolving the target of * a call, by checking the intercept rules. */ public class MethodBypass { static final boolean DEBUG = false; /** * Method summaries collected for methods. Mapping Object -> MethodSummary where Object is * either a * *

    *
  • MethodReference *
  • TypeReference *
  • Atom (package name) *
*/ private final Map methodSummaries; /** Set of TypeReferences which are marked "allocatable" */ private final Set allocatable; /** Governing class hierarchy. */ private final IClassHierarchy cha; /** Mapping from MethodReference -> SyntheticMethod */ private final HashMap syntheticMethods = HashMapFactory.make(); /** Set of method references that have been considered already. */ private final HashSet considered = HashSetFactory.make(); public MethodBypass( Map methodSummaries, Set allocatable, IClassHierarchy cha) { this.methodSummaries = methodSummaries; this.allocatable = allocatable; this.cha = cha; } /** * Lookup bypass rules based on a method reference only. * *

Method getBypass. */ private SyntheticMethod getBypass(MethodReference m) { if (DEBUG) { System.err.println(("MethodBypass.getBypass? " + m)); } SyntheticMethod result = findOrCreateSyntheticMethod(m); if (result != null) { return result; } // first lookup failed ... try resolving target via CHA and try again. m = resolveTarget(m); return findOrCreateSyntheticMethod(m); } /** * @param m a method reference * @return a SyntheticMethod corresponding to m; or null if none is available. */ private SyntheticMethod findOrCreateSyntheticMethod(MethodReference m) { if (considered.contains(m)) { return syntheticMethods.get(m); } else { considered.add(m); MethodSummary summ = findSummary(m); if (summ != null) { TypeReference T = m.getDeclaringClass(); IClass c = cha.lookupClass(T); assert c != null : "null class for " + T; SummarizedMethod n = new SummarizedMethod(m, summ, c); syntheticMethods.put(m, n); return n; } return null; } } private MethodSummary findSummary(MemberReference m) { MethodSummary result = methodSummaries.get(m); if (result != null) { if (DEBUG) { System.err.println(("findSummary succeeded: " + m)); } return result; } // try the class instead. TypeReference t = m.getDeclaringClass(); result = methodSummaries.get(t); if (result != null) { if (DEBUG) { System.err.println(("findSummary succeeded: " + t)); } return result; } if (t.isArrayType()) return null; // finally try the package. Atom p = extractPackage(t); result = methodSummaries.get(p); if (result != null) { if (DEBUG) { System.err.println(("findSummary succeeded: " + p)); } } else { if (DEBUG) { System.err.println(("findSummary failed: " + m)); } } return result; } /** * Method getBypass. check to see if a call to the receiver 'target' should be redirected to a * different receiver. * * @throws IllegalArgumentException if target is null */ public SyntheticMethod getBypass(IMethod target) { if (target == null) { throw new IllegalArgumentException("target is null"); } return getBypass(target.getReference()); } /** * Method extractPackage. * * @return Atom that represents the package name, or null if this is the unnamed package. */ private static Atom extractPackage(TypeReference type) { String s = type.getName().toString(); int index = s.lastIndexOf('/'); if (index == -1) { return null; } else { s = s.substring(0, index); return Atom.findOrCreateAsciiAtom(s); } } protected IClassHierarchy getClassHierarchy() { return cha; } protected MethodReference resolveTarget(MethodReference target) { IMethod m = getClassHierarchy().resolveMethod(target); if (m != null) { if (DEBUG) { System.err.println(("resolveTarget: resolved to " + m)); } target = m.getReference(); } return target; } /** * Are we allowed to allocate (for analysis purposes) an instance of a given type? By default, the * answer is yes iff T is not abstract. However, subclasses and summaries can override this to * allow "special" abstract classes to be allocatable as well. * * @throws IllegalArgumentException if klass is null */ public boolean isAllocatable(IClass klass) { if (klass == null) { throw new IllegalArgumentException("klass is null"); } if (!klass.isAbstract() && !klass.isInterface()) { return true; } else { return allocatable.contains(klass.getReference()); } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy