/* Soot - a J*va Optimization Framework * Copyright (C) 2002 Ondrej Lhotak * * This library 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 library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ package soot.jimple.spark.solver; import soot.jimple.spark.pag.*; import soot.jimple.spark.sets.*; import soot.*; /** Checks points-to sets with pointer assignment graph to make sure everything * has been correctly propagated. * @author Ondrej Lhotak */ public class Checker { public Checker( PAG pag ) { this.pag = pag; } /** Actually does the propagation. */ public void check() { for (Object object : pag.allocSources()) { handleAllocNode( (AllocNode) object ); } for (Object object : pag.simpleSources()) { handleSimples( (VarNode) object ); } for (Object object : pag.loadSources()) { handleLoads( (FieldRefNode) object ); } for (Object object : pag.storeSources()) { handleStores( (VarNode) object ); } } /* End of public methods. */ /* End of package methods. */ protected void checkAll( final Node container, PointsToSetInternal nodes, final Node upstream ) { nodes.forall( new P2SetVisitor() { public final void visit( Node n ) { checkNode( container, n, upstream ); } } ); } protected void checkNode( Node container, Node n, Node upstream ) { if( container.getReplacement() != container ) throw new RuntimeException( "container "+container+" is illegal" ); if( upstream.getReplacement() != upstream ) throw new RuntimeException( "upstream "+upstream+" is illegal" ); PointsToSetInternal p2set = container.getP2Set(); FastHierarchy fh = pag.getTypeManager().getFastHierarchy(); if( !p2set.contains( n ) && ( fh == null || container.getType() == null || fh.canStoreType( n.getType(), container.getType() ) ) ) { G.v().out.println( "Check failure: "+container+" does not have "+n +"; upstream is "+upstream ); } } protected void handleAllocNode( AllocNode src ) { Node[] targets = pag.allocLookup( src ); for (Node element : targets) { checkNode( element, src, src ); } } protected void handleSimples( VarNode src ) { PointsToSetInternal srcSet = src.getP2Set(); if( srcSet.isEmpty() ) return; final Node[] simpleTargets = pag.simpleLookup( src ); for (Node element : simpleTargets) { checkAll( element, srcSet, src ); } } protected void handleStores( final VarNode src ) { final PointsToSetInternal srcSet = src.getP2Set(); if( srcSet.isEmpty() ) return; Node[] storeTargets = pag.storeLookup( src ); for (Node element : storeTargets) { final FieldRefNode fr = (FieldRefNode) element; final SparkField f = fr.getField(); fr.getBase().getP2Set().forall( new P2SetVisitor() { public final void visit( Node n ) { AllocDotField nDotF = pag.makeAllocDotField( (AllocNode) n, f ); checkAll( nDotF, srcSet, src ); } } ); } } protected void handleLoads( final FieldRefNode src ) { final Node[] loadTargets = pag.loadLookup( src ); final SparkField f = src.getField(); src.getBase().getP2Set().forall( new P2SetVisitor() { public final void visit( Node n ) { AllocDotField nDotF = ((AllocNode)n).dot( f ); if( nDotF == null ) return; PointsToSetInternal set = nDotF.getP2Set(); if( set.isEmpty() ) return; for (Node element : loadTargets) { VarNode target = (VarNode) element; checkAll( target, set, src ); } } } ); } protected PAG pag; }