Missing Files for last commit.
This commit is contained in:
parent
c3b7f9ffb3
commit
448c8c5f86
|
@ -0,0 +1,75 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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.analysis.exceptionanalysis;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.callgraph.CallGraph;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
|
||||
import com.ibm.wala.ipa.cfg.exceptionpruning.interprocedural.InterproceduralExceptionFilter;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
|
||||
public class CGIntraproceduralExceptionAnalysis {
|
||||
private Map<CGNode, IntraproceduralExceptionAnalysis> analysis;
|
||||
private Set<TypeReference> exceptions;
|
||||
private CallGraph callGraph;
|
||||
|
||||
public CGIntraproceduralExceptionAnalysis(CallGraph cg, PointerAnalysis<InstanceKey> pointerAnalysis, ClassHierarchy cha,
|
||||
InterproceduralExceptionFilter<SSAInstruction> filter) {
|
||||
this.callGraph = cg;
|
||||
this.exceptions = new LinkedHashSet<>();
|
||||
this.analysis = new LinkedHashMap<>();
|
||||
for (CGNode node : cg) {
|
||||
if (node.getIR() == null || node.getIR().isEmptyIR()) {
|
||||
analysis.put(node, IntraproceduralExceptionAnalysis.newDummy());
|
||||
} else {
|
||||
IntraproceduralExceptionAnalysis intraEA;
|
||||
intraEA = new IntraproceduralExceptionAnalysis(node, filter.getFilter(node), cha, pointerAnalysis);
|
||||
analysis.put(node, intraEA);
|
||||
exceptions.addAll(intraEA.getExceptions());
|
||||
exceptions.addAll(intraEA.getPossiblyCaughtExceptions());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param node
|
||||
* @return IntraproceduralExceptionAnalysis for given node.
|
||||
*/
|
||||
public IntraproceduralExceptionAnalysis getAnalysis(CGNode node) {
|
||||
if (!callGraph.containsNode(node)) {
|
||||
throw new IllegalArgumentException("The given CG node has to be part " + "of the call graph given during construction.");
|
||||
}
|
||||
|
||||
IntraproceduralExceptionAnalysis result = analysis.get(node);
|
||||
if (result == null) {
|
||||
throw new RuntimeException("Internal Error: No result for the given node.");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a set of all Exceptions, which might occur within the given call
|
||||
* graph.
|
||||
*
|
||||
* @return all exceptions, which might occur.
|
||||
*/
|
||||
public Set<TypeReference> getExceptions() {
|
||||
return exceptions;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,332 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 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.analysis.exceptionanalysis;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.classLoader.CallSiteReference;
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.ipa.callgraph.CGNode;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.InstanceKey;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerAnalysis;
|
||||
import com.ibm.wala.ipa.callgraph.propagation.PointerKey;
|
||||
import com.ibm.wala.ipa.cfg.exceptionpruning.ExceptionFilter;
|
||||
import com.ibm.wala.ipa.cfg.exceptionpruning.FilteredException;
|
||||
import com.ibm.wala.ipa.cha.ClassHierarchy;
|
||||
import com.ibm.wala.ssa.IR;
|
||||
import com.ibm.wala.ssa.ISSABasicBlock;
|
||||
import com.ibm.wala.ssa.SSAInstruction;
|
||||
import com.ibm.wala.ssa.SSAInvokeInstruction;
|
||||
import com.ibm.wala.ssa.SSAThrowInstruction;
|
||||
import com.ibm.wala.ssa.SSAInstruction.Visitor;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.intset.IntIterator;
|
||||
import com.ibm.wala.util.intset.IntSet;
|
||||
|
||||
public class IntraproceduralExceptionAnalysis {
|
||||
private Set<TypeReference> exceptions;
|
||||
private Set<TypeReference> possiblyCaughtExceptions;
|
||||
private PointerAnalysis<InstanceKey> pointerAnalysis;
|
||||
private CGNode node;
|
||||
private ClassHierarchy classHierachy;
|
||||
private ExceptionFilter<SSAInstruction> filter;
|
||||
private IR ir;
|
||||
private boolean dummy = false;
|
||||
|
||||
public static IntraproceduralExceptionAnalysis newDummy() {
|
||||
return new IntraproceduralExceptionAnalysis();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a dummy analysis.
|
||||
*/
|
||||
private IntraproceduralExceptionAnalysis() {
|
||||
this.dummy = true;
|
||||
this.exceptions = Collections.emptySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* You can use this method, if you don't have a call graph, but want some
|
||||
* exception analysis. But as no pointer analysis is given, we can not
|
||||
* consider throw instructions.
|
||||
*
|
||||
* @param ir
|
||||
* @param filter
|
||||
* @param cha
|
||||
*/
|
||||
@Deprecated
|
||||
public IntraproceduralExceptionAnalysis(IR ir, ExceptionFilter<SSAInstruction> filter, ClassHierarchy cha) {
|
||||
this(ir, filter, cha, null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and compute intraprocedural exception analysis. (IR from
|
||||
* node.getIR() will be used.)
|
||||
*
|
||||
* @param node
|
||||
* @param filter
|
||||
* @param cha
|
||||
* @param pointerAnalysis
|
||||
*/
|
||||
public IntraproceduralExceptionAnalysis(CGNode node, ExceptionFilter<SSAInstruction> filter, ClassHierarchy cha,
|
||||
PointerAnalysis<InstanceKey> pointerAnalysis) {
|
||||
this(node.getIR(), filter, cha, pointerAnalysis, node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and compute intraprocedural exception analysis.
|
||||
*
|
||||
* @param ir
|
||||
* @param filter
|
||||
* @param cha
|
||||
* @param pointerAnalysis
|
||||
* @param node
|
||||
*/
|
||||
public IntraproceduralExceptionAnalysis(IR ir, ExceptionFilter<SSAInstruction> filter, ClassHierarchy cha,
|
||||
PointerAnalysis<InstanceKey> pointerAnalysis, CGNode node) {
|
||||
this.pointerAnalysis = pointerAnalysis;
|
||||
this.classHierachy = cha;
|
||||
this.filter = filter;
|
||||
this.ir = ir;
|
||||
this.node = node;
|
||||
this.exceptions = new LinkedHashSet<>();
|
||||
this.possiblyCaughtExceptions = new LinkedHashSet<>();
|
||||
compute();
|
||||
this.filter = null;
|
||||
this.pointerAnalysis = null;
|
||||
this.node = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes thrown exceptions for each basic block of all call graph nodes.
|
||||
* Everything, but invoke instructions, will be considered. This includes
|
||||
* filtered and caught exceptions.
|
||||
*/
|
||||
private void compute() {
|
||||
if (ir != null) {
|
||||
for (ISSABasicBlock block : ir.getControlFlowGraph()) {
|
||||
SSAInstruction throwingInstruction = getThrowingInstruction(block);
|
||||
if (throwingInstruction != null) {
|
||||
Set<TypeReference> thrownExceptions = collectThrownExceptions(throwingInstruction);
|
||||
Set<TypeReference> caughtExceptions = collectCaughtExceptions(block);
|
||||
Set<TypeReference> filteredExceptions = collectFilteredExceptions(throwingInstruction);
|
||||
|
||||
thrownExceptions.removeAll(filteredExceptions);
|
||||
thrownExceptions.removeAll(caughtExceptions);
|
||||
exceptions.addAll(thrownExceptions);
|
||||
}
|
||||
|
||||
if (block.isCatchBlock()) {
|
||||
Iterator<TypeReference> it = block.getCaughtExceptionTypes();
|
||||
while (it.hasNext()) {
|
||||
possiblyCaughtExceptions.add(it.next());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Set<TypeReference> subClasses = new LinkedHashSet<>();
|
||||
for (TypeReference caught : possiblyCaughtExceptions) {
|
||||
for (IClass iclass : this.classHierachy.computeSubClasses(caught)) {
|
||||
subClasses.add(iclass.getReference());
|
||||
}
|
||||
}
|
||||
|
||||
possiblyCaughtExceptions.addAll(subClasses);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all exceptions that could be returned from getCaughtExceptions
|
||||
* @return all exceptions that could be returned from getCaughtExceptions
|
||||
*/
|
||||
public Set<TypeReference> getPossiblyCaughtExceptions() {
|
||||
return possiblyCaughtExceptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the set of exceptions, which are to be filtered for
|
||||
* throwingInstruction.
|
||||
*
|
||||
* @param node
|
||||
* @param throwingInstruction
|
||||
* @return exceptions, which are to be filtered
|
||||
*/
|
||||
private Set<TypeReference> collectFilteredExceptions(SSAInstruction throwingInstruction) {
|
||||
if (filter != null) {
|
||||
Set<TypeReference> filtered = new LinkedHashSet<>();
|
||||
Collection<FilteredException> filters = filter.filteredExceptions(throwingInstruction);
|
||||
for (FilteredException filter : filters) {
|
||||
if (filter.isSubclassFiltered()) {
|
||||
for (IClass iclass : this.classHierachy.computeSubClasses(filter.getException())) {
|
||||
filtered.add(iclass.getReference());
|
||||
}
|
||||
} else {
|
||||
filtered.add(filter.getException());
|
||||
}
|
||||
}
|
||||
return filtered;
|
||||
} else {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a set of exceptions, which might be thrown from this instruction
|
||||
* within this method.
|
||||
*
|
||||
* This does include exceptions dispatched by throw instructions, but not
|
||||
* exceptions from method calls.
|
||||
*
|
||||
* @param throwingInstruction
|
||||
* @return a set of exceptions, which might be thrown from this instruction
|
||||
* within this method
|
||||
*/
|
||||
private Set<TypeReference> collectThrownExceptions(SSAInstruction throwingInstruction) {
|
||||
final LinkedHashSet<TypeReference> result = new LinkedHashSet<>();
|
||||
result.addAll(throwingInstruction.getExceptionTypes());
|
||||
|
||||
throwingInstruction.visit(new Visitor() {
|
||||
@Override
|
||||
public void visitThrow(SSAThrowInstruction instruction) {
|
||||
addThrown(result, instruction);
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects all exceptions, which could be dispatched by the throw
|
||||
* instruction, using the pointer analysis. Adds the collected exceptions to
|
||||
* addTo.
|
||||
*
|
||||
* @param addTo
|
||||
* set to add the result
|
||||
* @param instruction
|
||||
* the throw instruction
|
||||
*/
|
||||
private void addThrown(LinkedHashSet<TypeReference> addTo, SSAThrowInstruction instruction) {
|
||||
int exceptionVariable = instruction.getException();
|
||||
|
||||
if (pointerAnalysis != null) {
|
||||
PointerKey pointerKey = pointerAnalysis.getHeapModel().getPointerKeyForLocal(node, exceptionVariable);
|
||||
Iterator it = pointerAnalysis.getHeapGraph().getSuccNodes(pointerKey);
|
||||
while (it.hasNext()) {
|
||||
Object next = it.next();
|
||||
if (next instanceof InstanceKey) {
|
||||
InstanceKey instanceKey = (InstanceKey) next;
|
||||
IClass iclass = instanceKey.getConcreteType();
|
||||
addTo.add(iclass.getReference());
|
||||
} else {
|
||||
throw new IllegalStateException("Internal error: Expected InstanceKey, got " + next.getClass().getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param block
|
||||
* @return an instruction which may throw exceptions, or null if this block
|
||||
* can't throw exceptions
|
||||
*/
|
||||
private SSAInstruction getThrowingInstruction(ISSABasicBlock block) {
|
||||
SSAInstruction result = null;
|
||||
if (block.getLastInstructionIndex() >= 0) {
|
||||
SSAInstruction lastInstruction = block.getLastInstruction();
|
||||
if (lastInstruction != null) {
|
||||
result = lastInstruction;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param block
|
||||
* @return a set of all exceptions which will be caught, if thrown by the
|
||||
* given block.
|
||||
*/
|
||||
private Set<TypeReference> collectCaughtExceptions(ISSABasicBlock block) {
|
||||
LinkedHashSet<TypeReference> result = new LinkedHashSet<TypeReference>();
|
||||
List<ISSABasicBlock> exceptionalSuccessors = ir.getControlFlowGraph().getExceptionalSuccessors(block);
|
||||
for (ISSABasicBlock succ : exceptionalSuccessors) {
|
||||
if (succ.isCatchBlock()) {
|
||||
Iterator<TypeReference> it = succ.getCaughtExceptionTypes();
|
||||
while (it.hasNext()) {
|
||||
result.add(it.next());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Set<TypeReference> subClasses = new LinkedHashSet<>();
|
||||
for (TypeReference caught : result) {
|
||||
for (IClass iclass : this.classHierachy.computeSubClasses(caught)) {
|
||||
subClasses.add(iclass.getReference());
|
||||
}
|
||||
}
|
||||
|
||||
result.addAll(subClasses);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns all exceptions for the given call site in the given call graph
|
||||
* node, which will be caught.
|
||||
*
|
||||
* @param callsite
|
||||
* @return caught exceptions
|
||||
*/
|
||||
public Set<TypeReference> getCaughtExceptions(CallSiteReference callsite) {
|
||||
Set<TypeReference> result = null;
|
||||
if (dummy) {
|
||||
result = Collections.emptySet();
|
||||
} else {
|
||||
IntSet iindices = ir.getCallInstructionIndices(callsite);
|
||||
IntIterator it = iindices.intIterator();
|
||||
while (it.hasNext()) {
|
||||
int iindex = it.next();
|
||||
|
||||
SSAInstruction instruction = ir.getInstructions()[iindex];
|
||||
if (!((instruction instanceof SSAInvokeInstruction))) {
|
||||
throw new IllegalArgumentException("The given callsite dose not correspond to an invoke instruction." + instruction);
|
||||
}
|
||||
|
||||
ISSABasicBlock block = ir.getBasicBlockForInstruction(instruction);
|
||||
if (result == null) {
|
||||
result = new LinkedHashSet<>();
|
||||
result.addAll(collectCaughtExceptions(block));
|
||||
} else {
|
||||
result.retainAll(collectCaughtExceptions(block));
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns all exceptions which might be created and thrown but not caught or
|
||||
* filtered. (So this does not contain exceptions from invoked methods.)
|
||||
*
|
||||
* If constructed without points-to-analysis, it does not contain exceptions
|
||||
* thrown by throw statements.
|
||||
*
|
||||
* @return all exceptions created and thrown intraprocedural
|
||||
*/
|
||||
public Set<TypeReference> getExceptions() {
|
||||
return exceptions;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue