Completed implementation of basic functionality.

This commit is contained in:
Stephan Gocht 2015-11-25 17:05:51 +01:00
parent c5c4799b35
commit 79883b3def
4 changed files with 196 additions and 26 deletions

View File

@ -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);

View File

@ -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));
}
}

View File

@ -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);
}

View File

@ -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) {