WALA/com.ibm.wala.scandroid/source/org/scandroid/prefixtransfer/PrefixTransferGraph.java

288 lines
12 KiB
Java

/*
* 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 under the terms listed below.
*
*/
/*
*
* Copyright (c) 2009-2012,
*
* Adam Fuchs <afuchs@cs.umd.edu>
* Avik Chaudhuri <avik@cs.umd.edu>
* Steve Suh <suhsteve@gmail.com>
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The names of the contributors may not be used to endorse or promote
* products derived from this software without specific prior written
* permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*
*/
package org.scandroid.prefixtransfer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.scandroid.prefixtransfer.StringBuilderUseAnalysis.StringBuilderToStringInstanceKeySite;
import org.scandroid.prefixtransfer.modeledAllocations.ConstantString;
import com.ibm.wala.classLoader.CallSiteReference;
import com.ibm.wala.classLoader.IMethod;
import com.ibm.wala.ipa.callgraph.CGNode;
import com.ibm.wala.ipa.callgraph.Context;
import com.ibm.wala.ipa.callgraph.ContextKey;
import com.ibm.wala.ipa.callgraph.propagation.AllocationSite;
import com.ibm.wala.ipa.callgraph.propagation.AllocationSiteInNode;
import com.ibm.wala.ipa.callgraph.propagation.ConstantKey;
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
import com.ibm.wala.ipa.callgraph.propagation.NormalAllocationInNode;
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
import com.ibm.wala.types.ClassLoaderReference;
import com.ibm.wala.util.graph.Graph;
public class PrefixTransferGraph implements Graph<InstanceKeySite> {
private final Map<InstanceKey, InstanceKeySite> nodeMap = new HashMap<InstanceKey, InstanceKeySite>();
private final List<InstanceKeySite> nodes = new ArrayList<InstanceKeySite>();
private final Map<InstanceKeySite,Set<InstanceKeySite>> successors = new HashMap<InstanceKeySite, Set<InstanceKeySite>>();
private final Map<InstanceKeySite,Set<InstanceKeySite>> predecessors = new HashMap<InstanceKeySite, Set<InstanceKeySite>>();
public final Map<InstanceKey, StringBuilderUseAnalysis> sbuaMap = new HashMap<InstanceKey, StringBuilderUseAnalysis>();
public PrefixTransferGraph(PointerAnalysis<InstanceKey> pa)
{
Map<InstanceKeySite, Set<InstanceKey>> unresolvedDependencies = new HashMap<InstanceKeySite, Set<InstanceKey>>();
ArrayList<InstanceKey> instanceKeys = new ArrayList<InstanceKey>();
instanceKeys.addAll(pa.getInstanceKeys());
for(InstanceKey k:instanceKeys)
{
if(k.getConcreteType().getName().toString().equals("Ljava/lang/StringBuilder"))
{
if(k instanceof AllocationSiteInNode)
{
AllocationSiteInNode as = (AllocationSiteInNode)k;
if(as.getSite().getDeclaredType().getClassLoader().equals(ClassLoaderReference.Application))
{
StringBuilderUseAnalysis sbua;
try
{
sbua = new StringBuilderUseAnalysis(k,pa);
}
catch(Exception e)
{
continue;
}
sbuaMap.put(k, sbua); // map k to sbua in some global map
}
continue;
}
}
}
InstanceKeySite node = null;
for (InstanceKey k:instanceKeys)
{
// create a node for each InstanceKey of type string
if(k.getConcreteType().getName().toString().equals("Ljava/lang/String"))
{
if(k instanceof ConstantKey)
{
node = new ConstantString(pa.getInstanceKeyMapping().getMappedIndex(k), (String)((ConstantKey<?>)k).getValue());
addNode(node);
nodeMap.put(k, node);
}
else if(k instanceof NormalAllocationInNode)
{
IMethod m = ((NormalAllocationInNode) k).getNode().getMethod();
if (m.getSignature().equals("java.lang.StringBuilder.toString()Ljava/lang/String;")) {
Context context = ((NormalAllocationInNode) k).getNode().getContext();
CGNode caller = (CGNode) context.get(ContextKey.CALLER);
CallSiteReference csr = (CallSiteReference) context.get(ContextKey.CALLSITE);
InstanceKey receiver = (InstanceKey) context.get(ContextKey.RECEIVER);
if (caller != null && caller.getMethod().getReference().getDeclaringClass().getClassLoader().equals(ClassLoaderReference.Application))
{
node = sbuaMap.get(receiver).getNode(csr,k);
if(node == null)
{
continue;
}
addNode(node);
nodeMap.put(k, node);
HashSet<InstanceKey> iks = new HashSet<InstanceKey>();
for (Integer i: ((StringBuilderToStringInstanceKeySite) node).concatenatedInstanceKeys) {
iks.add(pa.getInstanceKeyMapping().getMappedObject(i));
}
unresolvedDependencies.put(node, iks);
// TODO: if this string is created inside the toString function of a string builder, find the StringBuilderUseAnalysis for that string builder and call getNode(k) to get the node for this instance key
// - this may have to be done in another phase
// NormalAllocationInNode ak = (NormalAllocationInNode)k;
// SSAInstruction inst = ak.getNode().getIR().getPEI(ak.getSite());
//
//
// for(int i = 0; i < inst.getNumberOfUses(); i++)
// {
// int use = inst.getUse(i);
// OrdinalSet<InstanceKey> useKeys = pa.getPointsToSet(new LocalPointerKey(ak.getNode(), use));
//
// }
//
// for(int i = 0; i < inst.getNumberOfDefs(); i++)
// {
// int def = inst.getDef(i);
// OrdinalSet<InstanceKey> useKeys = pa.getPointsToSet(new LocalPointerKey(ak.getNode(), def));
//
// }
}
}
}
else if(k instanceof AllocationSite)
{
}
else
{
}
// create an edge for dependencies used in the creation of each instance key
}
else
{
}
}
for(Entry<InstanceKeySite, Set<InstanceKey>> deps:unresolvedDependencies.entrySet())
{
for(InstanceKey dep:deps.getValue())
{
InstanceKeySite depSite = nodeMap.get(dep);
if(depSite == null)
{
throw new IllegalStateException("cannot resolve dependency of "+deps.getKey()+" on "+dep);
}
addEdge(depSite, deps.getKey());
}
}
}
public void removeNodeAndEdges(InstanceKeySite n)
throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
public void addNode(InstanceKeySite n) {
predecessors.put(n,new HashSet<InstanceKeySite>());
successors.put(n,new HashSet<InstanceKeySite>());
nodes.add(n);
}
public boolean containsNode(InstanceKeySite n) {
return nodes.contains(n);
}
public int getNumberOfNodes() {
return nodes.size();
}
public Iterator<InstanceKeySite> iterator() {
return nodes.iterator();
}
public void removeNode(InstanceKeySite n) {
throw new UnsupportedOperationException();
}
public void addEdge(InstanceKeySite src, InstanceKeySite dst) {
Set<InstanceKeySite> predSet = predecessors.get(dst);
if(predSet == null)
{
predSet = new HashSet<InstanceKeySite>();
predecessors.put(dst,predSet);
}
predSet.add(src);
Set<InstanceKeySite> succSet = successors.get(src);
if(succSet == null)
{
succSet = new HashSet<InstanceKeySite>();
successors.put(src,succSet);
}
succSet.add(dst);
}
public int getPredNodeCount(InstanceKeySite n) {
return predecessors.get(n).size();
}
public Iterator<InstanceKeySite> getPredNodes(InstanceKeySite n) {
return predecessors.get(n).iterator();
}
public int getSuccNodeCount(InstanceKeySite N) {
return successors.get(N).size();
}
public Iterator<InstanceKeySite> getSuccNodes(InstanceKeySite n) {
return successors.get(n).iterator();
}
public boolean hasEdge(InstanceKeySite src, InstanceKeySite dst) {
throw new UnsupportedOperationException();
}
public void removeAllIncidentEdges(InstanceKeySite node)
throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
public void removeEdge(InstanceKeySite src, InstanceKeySite dst)
throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
public void removeIncomingEdges(InstanceKeySite node)
throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
public void removeOutgoingEdges(InstanceKeySite node)
throws UnsupportedOperationException {
throw new UnsupportedOperationException();
}
}