/******************************************************************************* * 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. * * This file is a derivative of code released by the University of * California under the terms listed below. * * Refinement Analysis Tools is Copyright (c) 2007 The Regents of the * University of California (Regents). Provided that this notice and * the following two paragraphs are included in any distribution of * Refinement Analysis Tools or its derivative work, Regents agrees * not to assert any of Regents' copyright rights in Refinement * Analysis Tools against recipient for recipient's reproduction, * preparation of derivative works, public display, public * performance, distribution or sublicensing of Refinement Analysis * Tools and derivative works, in source code and object code form. * This agreement not to assert does not confer, by implication, * estoppel, or otherwise any license or rights in any intellectual * property of Regents, including, but not limited to, any patents * of Regents or Regents' employees. * * IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, * INCLUDING LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE * AND ITS DOCUMENTATION, EVEN IF REGENTS HAS BEEN ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. * * REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE AND FURTHER DISCLAIMS ANY STATUTORY * WARRANTY OF NON-INFRINGEMENT. THE SOFTWARE AND ACCOMPANYING * DOCUMENTATION, IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS * IS". REGENTS HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, * UPDATES, ENHANCEMENTS, OR MODIFICATIONS. */ package com.ibm.wala.demandpa.util; import java.util.Set; import com.ibm.wala.analysis.reflection.InstanceKeyWithNode; import com.ibm.wala.ipa.callgraph.CGNode; import com.ibm.wala.ipa.callgraph.CallGraph; import com.ibm.wala.ipa.callgraph.propagation.AbstractLocalPointerKey; import com.ibm.wala.ipa.callgraph.propagation.AllocationSiteInNode; import com.ibm.wala.ipa.callgraph.propagation.ConcreteTypeKey; import com.ibm.wala.ipa.callgraph.propagation.HeapModel; import com.ibm.wala.ipa.callgraph.propagation.InstanceKey; import com.ibm.wala.ipa.callgraph.propagation.LocalPointerKey; import com.ibm.wala.ipa.callgraph.propagation.MultiNewArrayInNode; import com.ibm.wala.ipa.callgraph.propagation.NormalAllocationInNode; import com.ibm.wala.ipa.callgraph.propagation.PointerKey; import com.ibm.wala.ipa.callgraph.propagation.ReturnValueKey; import com.ibm.wala.ipa.callgraph.propagation.cfa.ExceptionReturnValueKey; import com.ibm.wala.types.MethodReference; import com.ibm.wala.util.debug.Assertions; import com.ibm.wala.util.debug.UnimplementedError; /** * utility methods for mapping various program entities from one call graph to the corresponding entity in another one * * @author Manu Sridharan * */ public class CallGraphMapUtil { /** * map a call graph node from one call graph to the corresponding node in another. Note that the target call graph must be * context-insensitive for the method, i.e., the only context for the method should be Everywhere.EVERYWHERE. * * @return the corresponding node, or <code>null</code> if the method is not in the target call graph * @throws IllegalArgumentException if fromCG == null */ public static CGNode mapCGNode(CGNode orig, CallGraph fromCG, CallGraph toCG) throws IllegalArgumentException { if (fromCG == null) { throw new IllegalArgumentException("fromCG == null"); } if (orig == fromCG.getFakeRootNode()) { return toCG.getFakeRootNode(); } else { MethodReference methodRef = orig.getMethod().getReference(); if (methodRef.toString().equals("< Primordial, Ljava/lang/Object, clone()Ljava/lang/Object; >")) { // NOTE: clone() is cloned one level, even by RTA, so we need to handle it CGNode ret = toCG.getNode(orig.getMethod(), orig.getContext()); if (ret == null) { System.err.println(("WEIRD can't map node " + orig)); } return ret; } else { Set<CGNode> nodes = toCG.getNodes(methodRef); int size = nodes.size(); assert size <= 1; return (size == 0) ? null : nodes.iterator().next(); } } } public static InstanceKey mapInstKey(InstanceKey ik, CallGraph fromCG, CallGraph toCG, HeapModel heapModel) throws UnimplementedError, NullPointerException { InstanceKey ret = null; if (ik instanceof InstanceKeyWithNode) { CGNode oldCGNode = ((InstanceKeyWithNode) ik).getNode(); CGNode newCGNode = mapCGNode(oldCGNode, fromCG, toCG); if (newCGNode == null) { return null; } if (ik instanceof AllocationSiteInNode) { if (ik instanceof NormalAllocationInNode) { ret = heapModel.getInstanceKeyForAllocation(newCGNode, ((AllocationSiteInNode) ik).getSite()); } else if (ik instanceof MultiNewArrayInNode) { MultiNewArrayInNode mnik = (MultiNewArrayInNode) ik; ret = heapModel.getInstanceKeyForMultiNewArray(newCGNode, mnik.getSite(), mnik.getDim()); } else { Assertions.UNREACHABLE(); } } else { Assertions.UNREACHABLE(); } } else if (ik instanceof ConcreteTypeKey) { return ik; } else { Assertions.UNREACHABLE(); } assert ret != null; assert ret.getClass() == ik.getClass(); return ret; } public static PointerKey mapPointerKey(PointerKey pk, CallGraph fromCG, CallGraph toCG, HeapModel heapModel) throws UnimplementedError { PointerKey ret = null; if (pk instanceof AbstractLocalPointerKey) { CGNode oldCGNode = ((AbstractLocalPointerKey) pk).getNode(); CGNode newCGNode = mapCGNode(oldCGNode, fromCG, toCG); if (newCGNode == null) { return null; } if (pk instanceof LocalPointerKey) { ret = heapModel.getPointerKeyForLocal(newCGNode, ((LocalPointerKey) pk).getValueNumber()); } else if (pk instanceof ReturnValueKey) { // NOTE: must check for ExceptionReturnValueKey first, // since its a subclass if ReturnValueKey if (pk instanceof ExceptionReturnValueKey) { ret = heapModel.getPointerKeyForExceptionalReturnValue(newCGNode); } else { ret = heapModel.getPointerKeyForReturnValue(newCGNode); } } else { Assertions.UNREACHABLE(); } } else { Assertions.UNREACHABLE(); } assert ret != null; return ret; } }