Completed implementation of basic functionality.
This commit is contained in:
parent
c5c4799b35
commit
79883b3def
|
@ -17,6 +17,9 @@ import com.ibm.wala.dataflow.graph.BitVectorSolver;
|
|||
import com.ibm.wala.fixpoint.BitVectorVariable;
|
||||
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.cha.ClassHierarchy;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.CancelException;
|
||||
import com.ibm.wala.util.graph.Graph;
|
||||
|
@ -27,8 +30,8 @@ public class ExceptionAnalysis {
|
|||
private BitVectorSolver<CGNode> solver;
|
||||
private ExceptionToBitvectorTransformer transformer;
|
||||
|
||||
public ExceptionAnalysis(CallGraph callgraph){
|
||||
IntraproceduralResult intraResult = new IntraproceduralResult(callgraph);
|
||||
public ExceptionAnalysis(CallGraph callgraph, PointerAnalysis<InstanceKey> pointerAnalysis, ClassHierarchy cha){
|
||||
IntraproceduralResult intraResult = new IntraproceduralResult(callgraph, pointerAnalysis, cha);
|
||||
transformer = new ExceptionToBitvectorTransformer(intraResult.getExceptions());
|
||||
ExceptionTransferFunctionProvider transferFunctionProvider = new ExceptionTransferFunctionProvider(intraResult, callgraph, transformer);
|
||||
|
||||
|
|
|
@ -52,34 +52,35 @@ public class ExceptionToBitvectorTransformer {
|
|||
values = new ObjectArrayMapping<TypeReference>(exceptionsArray);
|
||||
}
|
||||
|
||||
public BitVector computeBitVector(Set<TypeReference> exceptions) {
|
||||
public BitVector computeBitVector(Set<TypeReference> exceptions) {
|
||||
BitVector result = new BitVector(values.getSize());
|
||||
for (TypeReference exception : exceptions) {
|
||||
if (!includingExceptions.containsKey(exception)) {
|
||||
throw new IllegalArgumentException("Got exception I don't know about,"
|
||||
+ "make sure only to use exceptions given to the constructor ");
|
||||
// if (!includingExceptions.containsKey(exception)) {
|
||||
// throw new IllegalArgumentException("Got exception I don't know about,"
|
||||
// + "make sure only to use exceptions given to the constructor ");
|
||||
// }
|
||||
if (includingExceptions.containsKey(exception)) {
|
||||
result.or(includingExceptions.get(exception));
|
||||
}
|
||||
|
||||
result.or(includingExceptions.get(exception));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Set<TypeReference> computeExceptions(BitVector bitVector) {
|
||||
|
||||
public Set<TypeReference> computeExceptions(BitVector bitVector) {
|
||||
assert bitVector.length() == values.getSize();
|
||||
Set<TypeReference> result = new HashSet<>();
|
||||
for (int i = 0; i < bitVector.length(); i++) {
|
||||
if (bitVector.get(i)){
|
||||
if (bitVector.get(i)) {
|
||||
result.add(values.getMappedObject(i));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Set<TypeReference> computeExceptions(BitVectorVariable bitVector) {
|
||||
|
||||
public Set<TypeReference> computeExceptions(BitVectorVariable bitVector) {
|
||||
Set<TypeReference> result = new HashSet<>();
|
||||
for (int i = 0; i < values.getSize(); i++) {
|
||||
if (bitVector.get(i)){
|
||||
if (bitVector.get(i)) {
|
||||
result.add(values.getMappedObject(i));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,12 +77,21 @@ public class ExceptionTransferFunctionProvider implements ITransferFunctionProvi
|
|||
// return BitVectorIdentity.instance();
|
||||
// } else
|
||||
{
|
||||
CGNode tmp = src;
|
||||
src = dst;
|
||||
dst = tmp;
|
||||
|
||||
|
||||
Iterator<CallSiteReference> callsites = cg.getPossibleSites(src, dst);
|
||||
BitVector filtered = new BitVector(transformer.getValues().getSize());
|
||||
|
||||
if (callsites.hasNext()) {
|
||||
System.out.println(src.getMethod().toString() + " -> " + dst.getMethod().toString());
|
||||
|
||||
CallSiteReference callsite = callsites.next();
|
||||
filtered = transformer.computeBitVector(intraResult.getFilteredExceptions(src, callsite));
|
||||
while (callsites.hasNext()) {
|
||||
CallSiteReference callsite = callsites.next();
|
||||
callsite = callsites.next();
|
||||
BitVector bv = transformer.computeBitVector(intraResult.getFilteredExceptions(src, callsite));
|
||||
filtered.and(bv);
|
||||
}
|
||||
|
|
|
@ -13,54 +13,211 @@ package com.ibm.wala.analysis.exceptionanalysis;
|
|||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.wala.classLoader.CallSiteReference;
|
||||
import com.ibm.wala.classLoader.IClass;
|
||||
import com.ibm.wala.classLoader.IMethod;
|
||||
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.callgraph.propagation.PointerKey;
|
||||
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.SSAInstruction.Visitor;
|
||||
import com.ibm.wala.ssa.SSAInvokeInstruction;
|
||||
import com.ibm.wala.ssa.SSAThrowInstruction;
|
||||
import com.ibm.wala.types.TypeReference;
|
||||
import com.ibm.wala.util.intset.IntIterator;
|
||||
import com.ibm.wala.util.intset.IntSet;
|
||||
|
||||
public class IntraproceduralResult {
|
||||
private Set<TypeReference> exceptions;
|
||||
private Map<CGNode, Set<TypeReference>> intraproceduralExceptions;
|
||||
private CallGraph callGraph;
|
||||
private PointerAnalysis<InstanceKey> pointerAnalysis;
|
||||
private ClassHierarchy classHierachy;
|
||||
|
||||
public IntraproceduralResult(CallGraph cg) {
|
||||
public IntraproceduralResult(CallGraph cg, PointerAnalysis<InstanceKey> pointerAnalysis, ClassHierarchy cha) {
|
||||
this.callGraph = cg;
|
||||
intraproceduralExceptions = new HashMap<CGNode, Set<TypeReference>>();
|
||||
this.pointerAnalysis = pointerAnalysis;
|
||||
this.classHierachy = cha;
|
||||
intraproceduralExceptions = new HashMap<>();
|
||||
exceptions = new HashSet<>();
|
||||
compute();
|
||||
}
|
||||
|
||||
private void compute() {
|
||||
for (CGNode node : callGraph) {
|
||||
for (final CGNode node : callGraph) {
|
||||
intraproceduralExceptions.put(node, new HashSet<TypeReference>());
|
||||
|
||||
IR ir = node.getIR();
|
||||
|
||||
if (ir != null) {
|
||||
for (ISSABasicBlock block : ir.getControlFlowGraph()) {
|
||||
if (block.getLastInstructionIndex() >= 0) {
|
||||
SSAInstruction lastInstruction = block.getLastInstruction();
|
||||
intraproceduralExceptions.get(node).addAll(lastInstruction.getExceptionTypes());
|
||||
SSAInstruction throwingInstruction = getThrowingInstruction(block);
|
||||
if (throwingInstruction != null) {
|
||||
Set<TypeReference> caughtExceptions = collectCaughtExceptions(node, block);
|
||||
Set<TypeReference> thrownExceptions = collectThrownExceptions(node, throwingInstruction);
|
||||
|
||||
Set<TypeReference> exceptions = computeThrownMinusCaughtExceptions(thrownExceptions, caughtExceptions);
|
||||
if (node.getMethod().getName().toString().equals("foo") && !exceptions.isEmpty()) {
|
||||
System.out.println(throwingInstruction);
|
||||
}
|
||||
intraproceduralExceptions.get(node).addAll(exceptions);
|
||||
}
|
||||
// TODO: Add Throw, Analyze catch
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (Set<TypeReference> exceptions :intraproceduralExceptions.values()) {
|
||||
|
||||
for (Set<TypeReference> exceptions : intraproceduralExceptions.values()) {
|
||||
this.exceptions.addAll(exceptions);
|
||||
}
|
||||
}
|
||||
|
||||
private Set<TypeReference> computeThrownMinusCaughtExceptions(Set<TypeReference> thrownExceptions,
|
||||
Set<TypeReference> caughtExceptions) {
|
||||
Set<TypeReference> result = new LinkedHashSet<>();
|
||||
|
||||
result.addAll(thrownExceptions);
|
||||
result.removeAll(caughtExceptions);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 node
|
||||
* @param throwingInstruction
|
||||
* @return a set of exceptions, which might be thrown from this instruction
|
||||
* within this method
|
||||
*/
|
||||
private Set<TypeReference> collectThrownExceptions(final CGNode node, SSAInstruction throwingInstruction) {
|
||||
final LinkedHashSet<TypeReference> result = new LinkedHashSet<>();
|
||||
result.addAll(throwingInstruction.getExceptionTypes());
|
||||
|
||||
throwingInstruction.visit(new Visitor() {
|
||||
@Override
|
||||
public void visitThrow(SSAThrowInstruction instruction) {
|
||||
addThrown(result, node, instruction);
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collects all exceptions, which could be dispatched by the throw
|
||||
* instruction, by using the pointer analysis. Adds the collected exceptions
|
||||
* to addTo.
|
||||
*
|
||||
* @param addTo
|
||||
* set to add the result
|
||||
* @param node
|
||||
* node of the instruction
|
||||
* @param instruction
|
||||
* the throw instruction
|
||||
*/
|
||||
private void addThrown(LinkedHashSet<TypeReference> addTo, CGNode node, SSAThrowInstruction instruction) {
|
||||
int exceptionVariable = instruction.getException();
|
||||
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 node
|
||||
* @param block
|
||||
* @return a set of all exceptions which will be caught, if thrown by the
|
||||
* given block.
|
||||
*/
|
||||
private Set<TypeReference> collectCaughtExceptions(CGNode node, ISSABasicBlock block) {
|
||||
LinkedHashSet<TypeReference> result = new LinkedHashSet<TypeReference>();
|
||||
List<ISSABasicBlock> exceptionalSuccessors = node.getIR().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;
|
||||
}
|
||||
|
||||
public Set<TypeReference> getFilteredExceptions(CGNode node, CallSiteReference callsite) {
|
||||
assert (node.getIR().getInstructions()[callsite.getProgramCounter()] instanceof SSAInvokeInstruction);
|
||||
return Collections.emptySet();
|
||||
Set<TypeReference> result = new LinkedHashSet<>();
|
||||
|
||||
IntSet iindices = node.getIR().getCallInstructionIndices(callsite);
|
||||
IntIterator it = iindices.intIterator();
|
||||
while (it.hasNext()) {
|
||||
int iindex = it.next();
|
||||
|
||||
SSAInstruction instruction = node.getIR().getInstructions()[iindex];
|
||||
if (!((instruction instanceof SSAInvokeInstruction))) {
|
||||
throw new IllegalArgumentException("The given callsite dose not correspond to an invoke instruction." + instruction);
|
||||
}
|
||||
|
||||
// SSAInvokeInstruction invoke = (SSAInvokeInstruction) instruction;
|
||||
// if (instruction == null) {
|
||||
// throw new IllegalStateException();
|
||||
// }
|
||||
ISSABasicBlock block = node.getIR().getBasicBlockForInstruction(instruction);
|
||||
if (result.isEmpty()) {
|
||||
result.addAll(collectCaughtExceptions(node, block));
|
||||
} else {
|
||||
result.retainAll(collectCaughtExceptions(node, block));
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Set<TypeReference> getIntraproceduralExceptions(CGNode node) {
|
||||
|
|
Loading…
Reference in New Issue